From 262faa2e2f4aed1a0125aa8d5a8a8fe40072e43e Mon Sep 17 00:00:00 2001 From: BastiaanOlij Date: Thu, 9 Nov 2017 21:58:58 +1100 Subject: [PATCH] Sensor example --- misc/sensors/cube_6.png | Bin 0 -> 11311 bytes misc/sensors/default_env.tres | 104 ++++++ misc/sensors/icon.png | Bin 0 -> 3498 bytes misc/sensors/main.gd | 141 ++++++++ misc/sensors/main.tscn | 592 ++++++++++++++++++++++++++++++++++ misc/sensors/project.godot | 23 ++ 6 files changed, 860 insertions(+) create mode 100644 misc/sensors/cube_6.png create mode 100644 misc/sensors/default_env.tres create mode 100644 misc/sensors/icon.png create mode 100644 misc/sensors/main.gd create mode 100644 misc/sensors/main.tscn create mode 100644 misc/sensors/project.godot diff --git a/misc/sensors/cube_6.png b/misc/sensors/cube_6.png new file mode 100644 index 0000000000000000000000000000000000000000..b572343c3005a5ace070381fca6d58df304107e1 GIT binary patch literal 11311 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 Y|LV|6es%hBO8@`>07*qoM6N<$f`}~Z-v9sr literal 0 HcmV?d00001 diff --git a/misc/sensors/main.gd b/misc/sensors/main.gd new file mode 100644 index 00000000..9161c141 --- /dev/null +++ b/misc/sensors/main.gd @@ -0,0 +1,141 @@ +extends Node + +# Below are a number of helper functions that show how you can use the raw sensor data to determine the orientation +# of your phone/device. The cheapest phones only have an accelerometer only the most expensive phones have all three. +# Note that none of this logic filters data. Filters introduce lag but also provide stability. There are plenty +# of examples on the internet on how to implement these. I wanted to keep this straight forward. + +# We draw a few arrow objects to visualize the vectors and two cubes to show two implementation for orientating +# these cubes to our phones orientation. +# This is a 3D example however reading the phones orientation is also invaluable for 2D + +# This function calculates a rotation matrix based on a direction vector. As our arrows are cylindrical we don't +# care about the rotation around this axis. +func get_basis_for_arrow(p_vector): + var rotate = Basis() + + # as our arrow points up, Y = our direction vector + rotate.y = p_vector.normalized() + + # get an arbitrary vector we can use to calculate our other two vectors + var v = Vector3(1.0, 0.0, 0.0) + if (abs(v.dot(rotate.y)) > 0.9): + v = Vector3(0.0, 1.0, 0.0) + + # use our vector to get a vector perpendicular to our two vectors + rotate.x = rotate.y.cross(v).normalized() + + # and the cross product again gives us our final vector perpendicular to our previous two vectors + rotate.z = rotate.x.cross(rotate.y).normalized() + + return rotate + +# This function combines the magnetometer reading with the gravity vector to get a vector that points due north +func calc_north(p_grav, p_mag): + # Always use normalized vectors! + p_grav = p_grav.normalized() + + # Calculate east (or is it west) by getting our cross product. + # The cross product of two normalized vectors returns a vector that + # is perpendicular to our two vectors + var east = p_grav.cross(p_mag.normalized()).normalized() + + # Cross again to get our horizon aligned north + return east.cross(p_grav).normalized() + +# This function creates an orientation matrix using the magnetometer and gravity vector as inputs. +func orientate_by_mag_and_grav(p_mag, p_grav): + var rotate = Basis() + + # as always, normalize! + p_mag = p_mag.normalized() + + # gravity points down, so - gravity points up! + rotate.y = -p_grav.normalized() + + # Cross products with our magnetic north gives an aligned east (or west, I always forget) + rotate.x = rotate.y.cross(p_mag) + + # And cross product again and we get our aligned north completing our matrix + rotate.z = rotate.x.cross(rotate.y) + + return rotate + +# This function takes our gyro input and update an orientation matrix accordingly +# The gyro is special as this vector does not contain a direction but rather a +# rotational velocity. This is why we multiply our values with delta. +func rotate_by_gyro(p_gyro, p_basis, p_delta): + var rotate = Basis() + + rotate = rotate.rotated(p_basis.x, -p_gyro.x * p_delta) + rotate = rotate.rotated(p_basis.y, -p_gyro.y * p_delta) + rotate = rotate.rotated(p_basis.z, -p_gyro.z * p_delta) + + return rotate * p_basis + +# This function corrects the drift in our matrix by our gravity vector +func drift_correction(p_basis, p_grav): + # as always, make sure our vector is normalized but also invert as our gravity points down + var real_up = -p_grav.normalized() + + # start by calculating the dot product, this gives us the cosine angle between our two vectors + var dot = p_basis.y.dot(real_up) + + # if our dot is 1.0 we're good + if (dot < 1.0): + # the cross between our two vectors gives us a vector perpendicular to our two vectors + var axis = p_basis.y.cross(real_up).normalized() + var correction = Basis(axis, acos(dot)) + p_basis = correction * p_basis + + return p_basis + +func _process(delta): + # Get our data + var acc = Input.get_accelerometer() + var grav = Input.get_gravity() + var mag = Input.get_magnetometer() + var gyro = Input.get_gyroscope() + + # Show our base values + get_node("Control/Accelerometer").text = 'Accelerometer: ' + str(acc) + ', gravity: ' + str(grav) + get_node("Control/Magnetometer").text = 'Magnetometer: ' + str(mag) + get_node("Control/Gyroscope").text = 'Gyroscope: ' + str(gyro) + + # Check if we have all needed data + if grav.length() < 0.1: + if acc.length() < 0.1: + # we don't have either... + grav = Vector3(0.0, -1.0, 0.0) + else: + # The gravity vector is calculated by the OS by combining the other sensor inputs. + # If we don't have a gravity vector, from now on, use accelerometer... + grav = acc + + if mag.length() < 0.1: + mag = Vector3(1.0, 0.0, 0.0) + + # Update our arrow showing gravity + get_node("Arrows/AccelerometerArrow").transform.basis = get_basis_for_arrow(grav) + + # Update our arrow showing our magnetometer + # Note that in absense of other strong magnetic forces this will point to magnetic north, which is not horizontal thanks to the earth being, uhm, round + get_node("Arrows/MagnetoArrow").transform.basis = get_basis_for_arrow(mag) + + # Calculate our north vector and show that + var north = calc_north(grav,mag) + get_node("Arrows/NorthArrow").transform.basis = get_basis_for_arrow(north) + + # Combine our magnetometer and gravity vector to position our box. This will be fairly accurate + # but our magnetometer can be easily influenced by magnets. Cheaper phones often don't have gyros + # so it is a good backup. + var mag_and_grav = get_node("Boxes/MagAndGrav") + mag_and_grav.transform.basis = orientate_by_mag_and_grav(mag, grav).orthonormalized() + + # Using our gyro and do a drift correction using our gravity vector gives the best result + var gyro_and_grav = get_node("Boxes/GyroAndGrav") + var new_basis = rotate_by_gyro(gyro, gyro_and_grav.transform.basis, delta).orthonormalized() + gyro_and_grav.transform.basis = drift_correction(new_basis, grav) + + + diff --git a/misc/sensors/main.tscn b/misc/sensors/main.tscn new file mode 100644 index 00000000..0df61510 --- /dev/null +++ b/misc/sensors/main.tscn @@ -0,0 +1,592 @@ +[gd_scene load_steps=11 format=2] + +[ext_resource path="res://main.gd" type="Script" id=1] +[ext_resource path="res://cube_6.png" type="Texture" id=2] + +[sub_resource type="Environment" id=1] + +background_mode = 1 +background_sky_custom_fov = 0.0 +background_color = Color( 0, 0, 0, 1 ) +background_energy = 1.0 +background_canvas_max_layer = 0 +background_camera_feed_id = 1 +background_camera_feed_h_flip = false +background_camera_feed_v_flip = true +ambient_light_color = Color( 0.648438, 0.64578, 0.64578, 1 ) +ambient_light_energy = 1.0 +ambient_light_sky_contribution = 1.0 +fog_enabled = false +fog_color = Color( 0.5, 0.6, 0.7, 1 ) +fog_sun_color = Color( 1, 0.9, 0.7, 1 ) +fog_sun_amount = 0.0 +fog_depth_enabled = true +fog_depth_begin = 10.0 +fog_depth_curve = 1.0 +fog_transmit_enabled = false +fog_transmit_curve = 1.0 +fog_height_enabled = false +fog_height_min = 0.0 +fog_height_max = 100.0 +fog_height_curve = 1.0 +tonemap_mode = 0 +tonemap_exposure = 1.0 +tonemap_white = 1.0 +auto_exposure_enabled = false +auto_exposure_scale = 0.4 +auto_exposure_min_luma = 0.05 +auto_exposure_max_luma = 8.0 +auto_exposure_speed = 0.5 +ss_reflections_enabled = false +ss_reflections_max_steps = 64 +ss_reflections_fade_in = 0.15 +ss_reflections_fade_out = 2.0 +ss_reflections_depth_tolerance = 0.2 +ss_reflections_roughness = true +ssao_enabled = false +ssao_radius = 1.0 +ssao_intensity = 1.0 +ssao_radius2 = 0.0 +ssao_intensity2 = 1.0 +ssao_bias = 0.01 +ssao_light_affect = 0.0 +ssao_color = Color( 0, 0, 0, 1 ) +ssao_quality = 0 +ssao_blur = 3 +ssao_edge_sharpness = 4.0 +dof_blur_far_enabled = false +dof_blur_far_distance = 10.0 +dof_blur_far_transition = 5.0 +dof_blur_far_amount = 0.1 +dof_blur_far_quality = 1 +dof_blur_near_enabled = false +dof_blur_near_distance = 2.0 +dof_blur_near_transition = 1.0 +dof_blur_near_amount = 0.1 +dof_blur_near_quality = 1 +glow_enabled = false +glow_levels/1 = false +glow_levels/2 = false +glow_levels/3 = true +glow_levels/4 = false +glow_levels/5 = true +glow_levels/6 = false +glow_levels/7 = false +glow_intensity = 0.8 +glow_strength = 1.0 +glow_bloom = 0.0 +glow_blend_mode = 2 +glow_hdr_threshold = 1.0 +glow_hdr_scale = 2.0 +glow_bicubic_upscale = false +adjustment_enabled = false +adjustment_brightness = 1.0 +adjustment_contrast = 1.0 +adjustment_saturation = 1.0 +_sections_unfolded = [ "Ambient Light", "Background" ] + +[sub_resource type="CylinderMesh" id=2] + +top_radius = 0.2 +bottom_radius = 0.1 +height = 4.0 +radial_segments = 16 +rings = 4 + +[sub_resource type="SpatialMaterial" id=3] + +render_priority = 0 +flags_transparent = false +flags_unshaded = false +flags_vertex_lighting = false +flags_no_depth_test = false +flags_use_point_size = false +flags_world_triplanar = false +flags_fixed_size = false +vertex_color_use_as_albedo = false +vertex_color_is_srgb = false +params_diffuse_mode = 1 +params_specular_mode = 0 +params_blend_mode = 0 +params_cull_mode = 0 +params_depth_draw_mode = 0 +params_line_width = 1.0 +params_point_size = 1.0 +params_billboard_mode = 0 +params_grow = false +params_use_alpha_scissor = false +albedo_color = Color( 0.356557, 1, 0.366611, 1 ) +metallic = 0.0 +metallic_specular = 0.5 +metallic_texture_channel = 0 +roughness = 0.0 +roughness_texture_channel = 0 +emission_enabled = false +normal_enabled = false +rim_enabled = false +clearcoat_enabled = false +anisotropy_enabled = false +ao_enabled = false +depth_enabled = false +subsurf_scatter_enabled = false +transmission_enabled = false +refraction_enabled = false +detail_enabled = false +uv1_scale = Vector3( 1, 1, 1 ) +uv1_offset = Vector3( 0, 0, 0 ) +uv1_triplanar = false +uv1_triplanar_sharpness = 1.0 +uv2_scale = Vector3( 1, 1, 1 ) +uv2_offset = Vector3( 0, 0, 0 ) +uv2_triplanar = false +uv2_triplanar_sharpness = 1.0 +proximity_fade_enable = false +distance_fade_enable = false +_sections_unfolded = [ "Albedo", "Flags", "Parameters", "Resource", "Vertex Color" ] + +[sub_resource type="CylinderMesh" id=4] + +top_radius = 0.1 +bottom_radius = 1.0 +height = 2.0 +radial_segments = 16 +rings = 4 + +[sub_resource type="SpatialMaterial" id=5] + +render_priority = 0 +flags_transparent = false +flags_unshaded = false +flags_vertex_lighting = false +flags_no_depth_test = false +flags_use_point_size = false +flags_world_triplanar = false +flags_fixed_size = false +vertex_color_use_as_albedo = false +vertex_color_is_srgb = false +params_diffuse_mode = 1 +params_specular_mode = 0 +params_blend_mode = 0 +params_cull_mode = 0 +params_depth_draw_mode = 0 +params_line_width = 1.0 +params_point_size = 1.0 +params_billboard_mode = 0 +params_grow = false +params_use_alpha_scissor = false +albedo_color = Color( 0.0266393, 0.292793, 1, 1 ) +metallic = 0.0 +metallic_specular = 0.5 +metallic_texture_channel = 0 +roughness = 0.0 +roughness_texture_channel = 0 +emission_enabled = false +normal_enabled = false +rim_enabled = false +clearcoat_enabled = false +anisotropy_enabled = false +ao_enabled = false +depth_enabled = false +subsurf_scatter_enabled = false +transmission_enabled = false +refraction_enabled = false +detail_enabled = false +uv1_scale = Vector3( 1, 1, 1 ) +uv1_offset = Vector3( 0, 0, 0 ) +uv1_triplanar = false +uv1_triplanar_sharpness = 1.0 +uv2_scale = Vector3( 1, 1, 1 ) +uv2_offset = Vector3( 0, 0, 0 ) +uv2_triplanar = false +uv2_triplanar_sharpness = 1.0 +proximity_fade_enable = false +distance_fade_enable = false +_sections_unfolded = [ "Albedo", "Vertex Color" ] + +[sub_resource type="SpatialMaterial" id=6] + +render_priority = 0 +flags_transparent = false +flags_unshaded = false +flags_vertex_lighting = false +flags_no_depth_test = false +flags_use_point_size = false +flags_world_triplanar = false +flags_fixed_size = false +vertex_color_use_as_albedo = false +vertex_color_is_srgb = false +params_diffuse_mode = 1 +params_specular_mode = 0 +params_blend_mode = 0 +params_cull_mode = 0 +params_depth_draw_mode = 0 +params_line_width = 1.0 +params_point_size = 1.0 +params_billboard_mode = 0 +params_grow = false +params_use_alpha_scissor = false +albedo_color = Color( 0.957031, 0.801627, 0.0921731, 1 ) +metallic = 0.0 +metallic_specular = 0.5 +metallic_texture_channel = 0 +roughness = 0.0 +roughness_texture_channel = 0 +emission_enabled = false +normal_enabled = false +rim_enabled = false +clearcoat_enabled = false +anisotropy_enabled = false +ao_enabled = false +depth_enabled = false +subsurf_scatter_enabled = false +transmission_enabled = false +refraction_enabled = false +detail_enabled = false +uv1_scale = Vector3( 1, 1, 1 ) +uv1_offset = Vector3( 0, 0, 0 ) +uv1_triplanar = false +uv1_triplanar_sharpness = 1.0 +uv2_scale = Vector3( 1, 1, 1 ) +uv2_offset = Vector3( 0, 0, 0 ) +uv2_triplanar = false +uv2_triplanar_sharpness = 1.0 +proximity_fade_enable = false +distance_fade_enable = false +_sections_unfolded = [ "Albedo" ] + +[sub_resource type="CubeMesh" id=7] + +size = Vector3( 4, 4, 4 ) +subdivide_width = 0 +subdivide_height = 0 +subdivide_depth = 0 + +[sub_resource type="SpatialMaterial" id=8] + +render_priority = 0 +flags_transparent = false +flags_unshaded = false +flags_vertex_lighting = false +flags_no_depth_test = false +flags_use_point_size = false +flags_world_triplanar = false +flags_fixed_size = false +vertex_color_use_as_albedo = false +vertex_color_is_srgb = false +params_diffuse_mode = 1 +params_specular_mode = 0 +params_blend_mode = 0 +params_cull_mode = 0 +params_depth_draw_mode = 0 +params_line_width = 1.0 +params_point_size = 1.0 +params_billboard_mode = 0 +params_grow = false +params_use_alpha_scissor = false +albedo_color = Color( 1, 1, 1, 1 ) +albedo_texture = ExtResource( 2 ) +metallic = 0.0 +metallic_specular = 0.5 +metallic_texture_channel = 0 +roughness = 0.0 +roughness_texture_channel = 0 +emission_enabled = false +normal_enabled = false +rim_enabled = false +clearcoat_enabled = false +anisotropy_enabled = false +ao_enabled = false +depth_enabled = false +subsurf_scatter_enabled = false +transmission_enabled = false +refraction_enabled = false +detail_enabled = false +uv1_scale = Vector3( 1, 1, 1 ) +uv1_offset = Vector3( 0, 0, 0 ) +uv1_triplanar = false +uv1_triplanar_sharpness = 1.0 +uv2_scale = Vector3( 1, 1, 1 ) +uv2_offset = Vector3( 0, 0, 0 ) +uv2_triplanar = false +uv2_triplanar_sharpness = 1.0 +proximity_fade_enable = false +distance_fade_enable = false +_sections_unfolded = [ "Albedo" ] + +[node name="Main" type="Node"] + +script = ExtResource( 1 ) + +[node name="Control" type="Control" parent="."] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 1025.0 +margin_bottom = 602.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +_sections_unfolded = [ "Anchor", "Grow Direction", "Hint", "Margin", "Rect", "Size Flags" ] + +[node name="Accelerometer" type="Label" parent="Control"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 340.0 +margin_bottom = 14.0 +rect_scale = Vector2( 2, 2 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 1 +size_flags_vertical = 4 +text = "Accelerometer" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 +_sections_unfolded = [ "Anchor", "Margin", "Rect", "Size Flags" ] + +[node name="Magnetometer" type="Label" parent="Control"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 30.0 +margin_right = 340.0 +margin_bottom = 44.0 +rect_scale = Vector2( 2, 2 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 1 +size_flags_vertical = 4 +text = "Magnetometer" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 +_sections_unfolded = [ "Anchor", "Margin", "Rect", "Size Flags" ] + +[node name="Gyroscope" type="Label" parent="Control"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 60.0 +margin_right = 340.0 +margin_bottom = 74.0 +rect_scale = Vector2( 2, 2 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +size_flags_horizontal = 1 +size_flags_vertical = 4 +text = "Gyroscope" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 +_sections_unfolded = [ "Anchor", "Margin", "Rect", "Size Flags" ] + +[node name="Camera" type="Camera" parent="."] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.285209, 0, 11.9833 ) +projection = 0 +fov = 65.0 +near = 0.1 +far = 100.0 +keep_aspect = 1 +current = false +cull_mask = 1048575 +environment = SubResource( 1 ) +h_offset = 0.0 +v_offset = 0.0 +doppler/tracking = 0 + +[node name="Arrows" type="Spatial" parent="."] + +[node name="AccelerometerArrow" type="Spatial" parent="Arrows"] + +transform = Transform( 1, 0, 0, 0, -1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 0, 0 ) +_sections_unfolded = [ "Transform" ] + +[node name="Bottom" type="MeshInstance" parent="Arrows/AccelerometerArrow"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 2 ) +skeleton = NodePath("..") +material/0 = SubResource( 3 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="Top" type="MeshInstance" parent="Arrows/AccelerometerArrow"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 4 ) +skeleton = NodePath("..") +material/0 = SubResource( 3 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="MagnetoArrow" type="Spatial" parent="Arrows"] + +transform = Transform( -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0, 1, 0, 0, 0 ) +_sections_unfolded = [ "Transform" ] + +[node name="Bottom" type="MeshInstance" parent="Arrows/MagnetoArrow"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 2 ) +skeleton = NodePath("..") +material/0 = SubResource( 5 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="Top" type="MeshInstance" parent="Arrows/MagnetoArrow"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 4 ) +skeleton = NodePath("..") +material/0 = SubResource( 5 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="NorthArrow" type="Spatial" parent="Arrows"] + +transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0 ) +_sections_unfolded = [ "Transform" ] + +[node name="Bottom" type="MeshInstance" parent="Arrows/NorthArrow"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 2 ) +skeleton = NodePath("..") +material/0 = SubResource( 6 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="Top" type="MeshInstance" parent="Arrows/NorthArrow"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 4 ) +skeleton = NodePath("..") +material/0 = SubResource( 6 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="Boxes" type="Spatial" parent="."] + +[node name="MagAndGrav" type="MeshInstance" parent="Boxes"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -7, -4, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 7 ) +skeleton = NodePath("..") +material/0 = SubResource( 8 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="GyroAndGrav" type="MeshInstance" parent="Boxes"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 7, -4, 0 ) +layers = 1 +material_override = null +cast_shadow = 1 +extra_cull_margin = 0.0 +use_in_baked_light = false +lod_min_distance = 0.0 +lod_min_hysteresis = 0.0 +lod_max_distance = 0.0 +lod_max_hysteresis = 0.0 +mesh = SubResource( 7 ) +skeleton = NodePath("..") +material/0 = SubResource( 8 ) +_sections_unfolded = [ "Transform", "material" ] + +[node name="DirectionalLight" type="DirectionalLight" parent="."] + +transform = Transform( 0.884838, -0.329433, 0.329449, 0, 0.707124, 0.707089, -0.4659, -0.625659, 0.62569, 0, 4.69444, 0 ) +layers = 1 +light_color = Color( 1, 1, 1, 1 ) +light_energy = 1.0 +light_negative = false +light_specular = 0.5 +light_cull_mask = -1 +shadow_enabled = false +shadow_color = Color( 0, 0, 0, 1 ) +shadow_bias = 0.1 +shadow_contact = 0.0 +shadow_reverse_cull_face = false +editor_only = false +directional_shadow_mode = 2 +directional_shadow_split_1 = 0.1 +directional_shadow_split_2 = 0.2 +directional_shadow_split_3 = 0.5 +directional_shadow_blend_splits = false +directional_shadow_normal_bias = 0.8 +directional_shadow_bias_split_scale = 0.25 +directional_shadow_depth_range = 0 +directional_shadow_max_distance = 200.0 + + diff --git a/misc/sensors/project.godot b/misc/sensors/project.godot new file mode 100644 index 00000000..3077d0e1 --- /dev/null +++ b/misc/sensors/project.godot @@ -0,0 +1,23 @@ +; 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=3 + +[application] + +config/name="Accelerometer, magnetometer and gyro demo" +run/main_scene="res://main.tscn" +config/icon="res://icon.png" + +[gdnative] + +singletons=[ ] + +[rendering] + +environment/default_environment="res://default_env.tres"