commit a81ce96b6a047de6067f89da93a96fdfb5cedd47 Author: Evert Prants Date: Wed Nov 6 19:24:55 2019 +0200 stash this project for future reference diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b26143 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/**/*.import diff --git a/assets/AtmosphereShader.tres b/assets/AtmosphereShader.tres new file mode 100644 index 0000000..272f4f0 --- /dev/null +++ b/assets/AtmosphereShader.tres @@ -0,0 +1,186 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=2] + +[sub_resource type="Shader" id=1] +code = "shader_type spatial; // Written by GLtracy, ported to Godot by SolarLiner +render_mode blend_add, depth_test_disable; +// math const +uniform float PI = 3.14159265359; +uniform float MAX = 100000.0; +uniform vec3 position = vec3(0.0); + +// scatter const +uniform float length_scale = 1000.0; +uniform float ground_radius = 128.0; +uniform float atmosphere_radius = 128.05; +uniform vec4 scattering_cf: hint_color = vec4(0.105707, 0.375536, 0.92076, 1.0); +uniform float scattering_power = 35.92; +uniform float rayleight_cf: hint_range(0.001, 1.0) = 0.07; +uniform float mie_cf: hint_range(0.001, 1.0) = 0.04; + +uniform int scatter_passes: hint_range(0, 10) = 1; + +// ray intersects sphere +// e = -b +/- sqrt( b^2 - c ) +vec2 ray_vs_sphere( vec3 p, vec3 dir, float r ) { + float b = dot( p, dir ); + float c = dot( p, p ) - r * r; + + float d = b * b - c; + if ( d < 0.0 ) { + return vec2( MAX, -MAX ); + } + d = sqrt( d ); + + return vec2( -b - d, -b + d ); +} + +// Mie +// g : ( -0.75, -0.999 ) +// 3 * ( 1 - g^2 ) 1 + c^2 +// F = ----------------- * ------------------------------- +// 8pi * ( 2 + g^2 ) ( 1 + g^2 - 2 * g * c )^(3/2) +float phase_mie( float g, float c, float cc ) { + float gg = g * g; + + float a = ( 1.0 - gg ) * ( 1.0 + cc ); + + float b = 1.0 + gg - 2.0 * (-g) * c; + b *= sqrt( b ); + b *= 2.0 + gg; + + return ( 3.0 / 8.0 * PI ) * a / b; +} + +// Rayleigh +// g : 0 +// F = 3/16PI * ( 1 + c^2 ) +float phase_ray( float cc ) { + return ( 3.0 / 16.0 * PI ) * ( 1.0 + cc ); +} + +float density( vec3 p, float ph ) { + float scale_height = (atmosphere_radius - ground_radius); + return exp( -max( (length( p ) - ground_radius)/scale_height, 0.0 ) / ph ); +} + +float optic( vec3 p, vec3 q, float ph ) { + vec3 s = ( q - p ) / float( scatter_passes ); + vec3 v = p + s * 0.5; + + float sum = 0.0; + for ( int i = 0; i < scatter_passes; i++ ) { + sum += density( v, ph ); + v += s; + } + sum *= length( s ); + + return sum; +} + +vec3 in_scatter(vec3 o, vec3 dir, vec2 e, vec3 l) { + float ph_ray = rayleight_cf; + float ph_mie = mie_cf; + + vec3 k_ray = scattering_cf.rgb * scattering_power; //(0.105707, 0.375536, 0.92076)*35.9486 + vec3 k_mie = vec3( 1. * scattering_power ); + float k_mie_ex = 1.1; + + vec3 sum_ray = vec3( 0.0 ); + vec3 sum_mie = vec3( 0.0 ); + + float n_ray0 = 0.0; + float n_mie0 = 0.0; + + float len = ( e.y - e.x ) / float( scatter_passes*100 ); + vec3 s = dir * len; + vec3 v = o + dir * ( e.x + len * 0.5 ); + + for ( int i = 0; i < scatter_passes*100; i++) { + float d_ray = density( v, ph_ray ) * len; + float d_mie = density( v, ph_mie ) * len; + + n_ray0 += d_ray; + n_mie0 += d_mie; + v += s; + + /*vec2 e = ray_vs_sphere( v, l, R_INNER ); + e.x = max( e.x, 0.0 ); + if ( e.x < e.y ) { + continue; + }*/ + + vec2 f = ray_vs_sphere( v, l, atmosphere_radius ); + vec3 u = v + l * f.y; + + float n_ray1 = optic( v, u, ph_ray ); + float n_mie1 = optic( v, u, ph_mie ); + + vec3 att = exp( - ( n_ray0 + n_ray1 ) * k_ray - ( n_mie0 + n_mie1 ) * k_mie * k_mie_ex ); + + sum_ray += d_ray * att; + sum_mie += d_mie * att; + } + + float c = dot( dir, -l ); + float cc = c * c; + vec3 scatter = + sum_ray * k_ray * phase_ray( cc ) + + sum_mie * k_mie * phase_mie( -0.78, c, cc ); + + + return scatter; +} + +// ray direction +vec3 ray_dir( float fov, vec2 size, vec2 pos ) { + vec2 xy = pos - size * 0.5; + + float cot_half_fov = tan( radians( 90.0 - fov * 0.5 ) ); + float z = size.y * 0.5 * cot_half_fov; + + return normalize( vec3( xy, -z ) ); +} + +void vertex() { + VERTEX += NORMAL * (atmosphere_radius - ground_radius)/1.; +} + +void light() +{ + // default ray dir + vec3 dir = VIEW; + + // default ray origin + vec3 eye = INV_CAMERA_MATRIX[3].xyz + (CAMERA_MATRIX*vec4(position, 0.0)).xyz; + + // sun light dir + vec3 l = -LIGHT; + + vec2 e = ray_vs_sphere( eye, dir, atmosphere_radius ); + if ( e.x > e.y ) { + DIFFUSE_LIGHT = vec3(0.0); + return; + } + + vec2 f = ray_vs_sphere( eye, dir, ground_radius ); + e.y = min( e.y, f.x ); + + vec3 I = in_scatter(eye, dir, e, l); + + //DIFFUSE_LIGHT = vec3( pow( I, vec3( 1.0 / 2.2 ) )); + DIFFUSE_LIGHT = I*LIGHT_COLOR; +}" + +[resource] +shader = SubResource( 1 ) +shader_param/PI = 3.14159 +shader_param/MAX = 100000.0 +shader_param/position = Vector3( 0, 0, 0 ) +shader_param/length_scale = 1000.0 +shader_param/ground_radius = 6.371 +shader_param/atmosphere_radius = 6.471 +shader_param/scattering_cf = Color( 0.14902, 0.4, 0.909804, 1 ) +shader_param/scattering_power = 36.0 +shader_param/rayleight_cf = 0.07 +shader_param/mie_cf = 0.04 +shader_param/scatter_passes = 2 diff --git a/assets/maujoe.camera_control/CHANGELOG.md b/assets/maujoe.camera_control/CHANGELOG.md new file mode 100644 index 0000000..314954e --- /dev/null +++ b/assets/maujoe.camera_control/CHANGELOG.md @@ -0,0 +1,7 @@ +## 1.2 +- Ingame gui configuration: + - draggability (configurable) + - customizable gui background + + +- enhanced movement (acceleration, deceleration..) diff --git a/assets/maujoe.camera_control/DOCUMENTATION.md b/assets/maujoe.camera_control/DOCUMENTATION.md new file mode 100644 index 0000000..e77902b --- /dev/null +++ b/assets/maujoe.camera_control/DOCUMENTATION.md @@ -0,0 +1,54 @@ +## Docummentation: + + +### Settings available via Editor/GDscript: + +- bool enable : enable/disable camera controls. Default is true. +- int mouse_mode: Same as Godot's mouse settings by default the mouse is captured: + - Visible = 0 (MOUSE_MODE_VISIBLE), + - Hidden = 1 (MOUSE_MODE_HIDDEN), + - Capture = 2 (MOUSE_MODE_CAPTURED), + - Confined = 3 (MOUSE_MODE_CONFINED). + + +- bool mouselook - Enable/disable mouselook. Default is true. +- float sensitivity - Sensitivity of the mouselook. A value between 0 and 1. Default value is 0.5. +- float smoothness - Smoothness of the mouselook. A value between 0,001 and 0,999. Default value is 0.5. +- Spatial privot - Optional privot object for thirdperson like mouselook. Default value is None (no privot). +- bool rotate_privot - Enable/disable if the will be rotated with the camera. Default is false. +- float distance - The distance between the camera and the privot object. Minimum value is 0. Default value is 5.0 +- bool rotate_privote - Rotate privot object with the mouselook. Default is false. +- bool collision - The camera avoid it to go through/behind objects. Default is true. +- int yaw_limit - Limit the yaw of the mouselook in Degrees, if limit >= 360 there is no limit. Default value is 360. +- int pitch_limit - Limit the Pitch of the mouselook in Degrees, if limit = 360 there is no limit. Default value is 360. + + +- bool movement - Enable/disable camera movement (flying). Default is true. +- bool local - Switch between movement on local or global axes. Default is true. +- float acceleration - Set the movement speed up factor. A Value between 0 and 1. Default value is 1.0. +- float deceleration - Set the movement slow down factor. A Value between 0 and 1. Default value is 0.1. +- Vector3 max_speed - Set maximum movement speed for each axes separately. Default value is (1.0, 1.0, 1.0). + + +- String forword_action - Input Action for fordward movement. Default action is "ui_up". +- String backward_action - Input Action for backward movement. Default action is "ui_down". +- String left_action - Input Action for Left movement. Default action is "ui_left". +- String right_action: Input Action for Right movement. Default action is "ui_right". +- String up_action - Input Action for upward movement. Default action is "ui_page_up". +- String down_action: Input Action for downward movement. Default action is "ui_page_down". + + +- String gui_action - Input Action to show/hide the ingame control gui. Default action is "ui_cancel". +- bool use_gui - Enable/disable ingame gui. Default is true. + + +### Gui configuration: + +The ingame gui can also be configurated via constants in the camera_control_gui.gd script + +- const Vector2 GUI_POS - The default position of the gui. Default is (10, 10). +- const Vector2 GUI_SIZE - The size of the gui. Default is (200, 0) +- const bool DRAGGABLE - Enable/disable draggable gui. Default is true. +- const bool CUSTOM_BACKGROUND - Enable/disable custom background color. Default is false. +- const Color CUSTOM_COLOR - Set custom background color. +- const MAX_SPEED - The maximal value of the speedslider diff --git a/assets/maujoe.camera_control/LICENSE.md b/assets/maujoe.camera_control/LICENSE.md new file mode 100644 index 0000000..944adb8 --- /dev/null +++ b/assets/maujoe.camera_control/LICENSE.md @@ -0,0 +1,51 @@ + +All parts of this project that are not copyrighted or licensed by someone else are released under the MIT License: + +Copyright (c) 2018 Jaccomo Lorenz (Maujoe) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +------------ +Other Files: + +Some files caintained in this project may be generated by the Godot Engine version 3.0 that is covered by its own license, an up to date version can be found on: https://github.com/godotengine/godot/blob/master/LICENSE.txt. + +Quote (18th February 2018): + +"Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. +Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE." diff --git a/assets/maujoe.camera_control/README.md b/assets/maujoe.camera_control/README.md new file mode 100644 index 0000000..cfb606d --- /dev/null +++ b/assets/maujoe.camera_control/README.md @@ -0,0 +1,98 @@ +# Camera Control Script + +An easy "plug and play" camera script for the godot engine 3.0 that provides controls like mouselook, movement and an optional ingame control gui. +Useful for development and quick tests. + +### Features: +- mouselook +- movement +- ingame gui (optional) + +### Preview: +Demo video: https://www.youtube.com/watch?v=OSJRc-IiOio&t=9s + +
+ Editor Settings + +
+
+ Ingame Gui + +
+ +## How to use + +There is a demo scene in the demo folder where you can test all features and play with the script settings. + +If you don't need the demo just ignore the demo folder and connect your camera with the "camera_control.gd" script that can be found in the script folder. + +## Docummentation: + +### Settings available via Editor/GDscript: + +- bool enable : enable/disable camera controls. Default is true. +- int mouse_mode: Same as Godot's mouse settings by default the mouse is captured: + - Visible = 0 (MOUSE_MODE_VISIBLE), + - Hidden = 1 (MOUSE_MODE_HIDDEN), + - Capture = 2 (MOUSE_MODE_CAPTURED), + - Confined = 3 (MOUSE_MODE_CONFINED). + + +- bool mouselook - Enable/disable mouselook. Default is true. +- float sensitivity - Sensitivity of the mouselook. A value between 0 and 1. Default value is 0.5. +- float smoothness - Smoothness of the mouselook. A value between 0,001 and 0,999. Default value is 0.5. +- Spatial privot - Optional privot object for thirdperson like mouselook. Default value is None (no privot). +- bool rotate_privot - Enable/disable if the will be rotated with the camera. Default is false. +- float distance - The distance between the camera and the privot object. Minimum value is 0. Default value is 5.0 +- bool rotate_privote - Rotate privot object with the mouselook. Default is false. +- bool collision - The camera avoid it to go through/behind objects. Default is true. +- int yaw_limit - Limit the yaw of the mouselook in Degrees, if limit >= 360 there is no limit. Default value is 360. +- int pitch_limit - Limit the Pitch of the mouselook in Degrees, if limit = 360 there is no limit. Default value is 360. + + +- bool movement - Enable/disable camera movement (flying). Default is true. +- bool local - Switch between movement on local or global axes. Default is true. +- float acceleration - Set the movement speed up factor. A Value between 0 and 1. Default value is 1.0. +- float deceleration - Set the movement slow down factor. A Value between 0 and 1. Default value is 0.1. +- Vector3 max_speed - Set maximum movement speed for each axes separately. Default value is (1.0, 1.0, 1.0). + + +- String forword_action - Input Action for fordward movement. Default action is "ui_up". +- String backward_action - Input Action for backward movement. Default action is "ui_down". +- String left_action - Input Action for Left movement. Default action is "ui_left". +- String right_action: Input Action for Right movement. Default action is "ui_right". +- String up_action - Input Action for upward movement. Default action is "ui_page_up". +- String down_action: Input Action for downward movement. Default action is "ui_page_down". + + +- String gui_action - Input Action to show/hide the ingame control gui. Default action is "ui_cancel". +- bool use_gui - Enable/disable ingame gui. Default is true. + +### Gui configuration: + +The ingame gui can also be configurated via constants in the camera_control_gui.gd script + +![Image](screenshots/gui_settings.png) + +- const Vector2 GUI_POS - The default position of the gui. Default is (10, 10). +- const Vector2 GUI_SIZE - The size of the gui. Default is (200, 0) +- const bool DRAGGABLE - Enable/disable draggable gui. Default is true. +- const bool CUSTOM_BACKGROUND - Enable/disable custom background color. Default is false. +- const Color CUSTOM_COLOR - Set custom background color. +- const MAX_SPEED - The maximal value of the speedslider + +### To-do/possible features: +- refactoring +- distance shortcut key. +- improve movement: speed shortcut +- multiple camera support/jump between cameras +- screenshot functionality(?) +- more modularisation(?) +- add signal notification(?) +- ... + + +## License + +All parts of this project that are not copyrighted or licensed by someone else are released free under the MIT License - see the LICENSE.md file for details. +Please keep license file, thanks. :) diff --git a/assets/maujoe.camera_control/demo/default_env.tres b/assets/maujoe.camera_control/demo/default_env.tres new file mode 100644 index 0000000..691fbff --- /dev/null +++ b/assets/maujoe.camera_control/demo/default_env.tres @@ -0,0 +1,102 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +radiance_size = 4 +sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 ) +sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) +sky_curve = 0.25 +sky_energy = 1.0 +ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 ) +ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 ) +ground_curve = 0.01 +ground_energy = 1.0 +sun_color = Color( 1, 1, 1, 1 ) +sun_latitude = 35.0 +sun_longitude = 0.0 +sun_angle_min = 1.0 +sun_angle_max = 100.0 +sun_curve = 0.05 +sun_energy = 16.0 +texture_size = 2 + +[resource] + +background_mode = 2 +background_sky = SubResource( 1 ) +background_sky_custom_fov = 0.0 +background_color = Color( 0, 0, 0, 1 ) +background_energy = 1.0 +background_canvas_max_layer = 0 +ambient_light_color = Color( 0, 0, 0, 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" ] + diff --git a/assets/maujoe.camera_control/demo/demo.tscn b/assets/maujoe.camera_control/demo/demo.tscn new file mode 100644 index 0000000..6af8ab6 --- /dev/null +++ b/assets/maujoe.camera_control/demo/demo.tscn @@ -0,0 +1,270 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://assets/maujoe.camera_control/scripts/camera_control.gd" type="Script" id=1] + +[sub_resource type="SpatialMaterial" id=1] + +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 +flags_albedo_tex_force_srgb = false +vertex_color_use_as_albedo = false +vertex_color_is_srgb = false +params_diffuse_mode = 0 +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 ) +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 + +[sub_resource type="PlaneMesh" id=2] + +custom_aabb = AABB( 0, 0, 0, 0, 0, 0 ) +size = Vector2( 10, 10 ) +subdivide_width = 0 +subdivide_depth = 0 + +[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 +flags_albedo_tex_force_srgb = false +vertex_color_use_as_albedo = false +vertex_color_is_srgb = false +params_diffuse_mode = 0 +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 ) +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 + +[sub_resource type="CubeMesh" id=4] + +custom_aabb = AABB( 0, 0, 0, 0, 0, 0 ) +size = Vector3( 2, 2, 2 ) +subdivide_width = 0 +subdivide_height = 0 +subdivide_depth = 0 + +[sub_resource type="ConcavePolygonShape" id=5] + +data = PoolVector3Array( -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1 ) + +[sub_resource type="CubeMesh" id=6] + +custom_aabb = AABB( 0, 0, 0, 0, 0, 0 ) +size = Vector3( 1, 2, 1 ) +subdivide_width = 0 +subdivide_height = 0 +subdivide_depth = 0 + +[node name="Node" type="Node" index="0"] + +[node name="Camera" type="Camera" parent="." index="0"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 5 ) +keep_aspect = 1 +cull_mask = 1048575 +environment = null +h_offset = 0.0 +v_offset = 0.0 +doppler_tracking = 0 +projection = 0 +current = false +fov = 70.0 +size = 1.0 +near = 0.05 +far = 100.0 +script = ExtResource( 1 ) +enabled = true +mouse_mode = 2 +mouselook = true +sensitivity = 0.5 +smoothness = 0.5 +privot = null +distance = 6.0 +rotate_privot = false +collisions = false +yaw_limit = 360 +pitch_limit = 360 +movement = true +acceleration = 1.0 +deceleration = 0.1 +max_speed = Vector3( 1, 1, 1 ) +local = true +forward_action = "ui_up" +backward_action = "ui_down" +left_action = "ui_left" +right_action = "ui_right" +up_action = "ui_page_up" +down_action = "ui_page_down" +use_gui = true +gui_action = "ui_cancel" + +[node name="DirectionalLight" type="DirectionalLight" parent="." index="1"] + +transform = Transform( 1, 0, 0, 0, 0.866025, 0.5, 0, -0.5, 0.866025, 0, 8, 0 ) +layers = 1 +light_color = Color( 1, 1, 1, 1 ) +light_energy = 1.0 +light_indirect_energy = 1.0 +light_negative = false +light_specular = 0.5 +light_bake_mode = 1 +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 + +[node name="Ground" type="MeshInstance" parent="." index="2"] + +layers = 1 +material_override = SubResource( 1 ) +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 = null +_sections_unfolded = [ "Geometry" ] + +[node name="Cube" type="MeshInstance" parent="." index="3"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 1, -4 ) +layers = 1 +material_override = SubResource( 3 ) +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 = null +_sections_unfolded = [ "Geometry" ] + +[node name="StaticBody" type="StaticBody" parent="Cube" index="0"] + +input_ray_pickable = true +input_capture_on_drag = false +collision_layer = 1 +collision_mask = 1 +friction = 1.0 +bounce = 0.0 +constant_linear_velocity = Vector3( 0, 0, 0 ) +constant_angular_velocity = Vector3( 0, 0, 0 ) + +[node name="CollisionShape" type="CollisionShape" parent="Cube/StaticBody" index="0"] + +shape = SubResource( 5 ) +disabled = false + +[node name="Cube2" type="MeshInstance" parent="." index="4"] + +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0 ) +layers = 1 +material_override = SubResource( 3 ) +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( 6 ) +skeleton = NodePath("..") +material/0 = null +_sections_unfolded = [ "Geometry" ] + + diff --git a/assets/maujoe.camera_control/icon.png b/assets/maujoe.camera_control/icon.png new file mode 100644 index 0000000..c060f52 Binary files /dev/null and b/assets/maujoe.camera_control/icon.png differ diff --git a/assets/maujoe.camera_control/screenshots/editor_settings.png b/assets/maujoe.camera_control/screenshots/editor_settings.png new file mode 100644 index 0000000..5cbe7ae Binary files /dev/null and b/assets/maujoe.camera_control/screenshots/editor_settings.png differ diff --git a/assets/maujoe.camera_control/screenshots/gui_settings.png b/assets/maujoe.camera_control/screenshots/gui_settings.png new file mode 100644 index 0000000..4009468 Binary files /dev/null and b/assets/maujoe.camera_control/screenshots/gui_settings.png differ diff --git a/assets/maujoe.camera_control/screenshots/ingame_gui.png b/assets/maujoe.camera_control/screenshots/ingame_gui.png new file mode 100644 index 0000000..254da80 Binary files /dev/null and b/assets/maujoe.camera_control/screenshots/ingame_gui.png differ diff --git a/assets/maujoe.camera_control/scripts/camera_control.gd b/assets/maujoe.camera_control/scripts/camera_control.gd new file mode 100644 index 0000000..484edd0 --- /dev/null +++ b/assets/maujoe.camera_control/scripts/camera_control.gd @@ -0,0 +1,208 @@ +# Licensed under the MIT License. +# Copyright (c) 2018 Jaccomo Lorenz (Maujoe) + +extends Camera + +# User settings: +# General settings +export var enabled = true setget set_enabled +export(int, "Visible", "Hidden", "Caputered, Confined") var mouse_mode = 2 + +# Mouslook settings +export var mouselook = true +export (float, 0.0, 1.0) var sensitivity = 0.5 +export (float, 0.0, 0.999, 0.001) var smoothness = 0.5 setget set_smoothness +export(NodePath) var privot setget set_privot +export var distance = 5.0 setget set_distance +export var rotate_privot = false +export var collisions = true setget set_collisions +export (int, 0, 360) var yaw_limit = 360 +export (int, 0, 360) var pitch_limit = 360 + +# Movement settings +export var movement = true +export (float, 0.0, 1.0) var acceleration = 1.0 +export (float, 0.0, 0.0, 1.0) var deceleration = 1.0 +export var max_speed = Vector3(1.0, 1.0, 1.0) +export var local = true +export var forward_action = "ui_up" +export var backward_action = "ui_down" +export var left_action = "ui_left" +export var right_action = "ui_right" +export var up_action = "ui_page_up" +export var down_action = "ui_page_down" + +# Gui settings +export var use_gui = true +export var gui_action = "ui_cancel" + +# Intern variables. +var _mouse_position = Vector2(0.0, 0.0) +var _yaw = 0.0 +var _pitch = 0.0 +var _total_yaw = 0.0 +var _total_pitch = 0.0 + +var _direction = Vector3(0.0, 0.0, 0.0) +var _speed = Vector3(0.0, 0.0, 0.0) +var _gui + +func _ready(): + _check_actions([forward_action, backward_action, left_action, right_action, gui_action, up_action, down_action]) + + if privot: + privot = get_node(privot) + else: + privot = null + + set_enabled(enabled) + + if use_gui: + _gui = preload("camera_control_gui.gd") + _gui = _gui.new(self, gui_action) + add_child(_gui) + +func _input(event): + if mouselook: + if event is InputEventMouseMotion: + _mouse_position = event.relative + + if movement: + if event.is_action_pressed(forward_action): + _direction.z = -1 + elif event.is_action_pressed(backward_action): + _direction.z = 1 + elif not Input.is_action_pressed(forward_action) and not Input.is_action_pressed(backward_action): + _direction.z = 0 + + if event.is_action_pressed(left_action): + _direction.x = -1 + elif event.is_action_pressed(right_action): + _direction.x = 1 + elif not Input.is_action_pressed(left_action) and not Input.is_action_pressed(right_action): + _direction.x = 0 + + if event.is_action_pressed(up_action): + _direction.y = 1 + if event.is_action_pressed(down_action): + _direction.y = -1 + elif not Input.is_action_pressed(up_action) and not Input.is_action_pressed(down_action): + _direction.y = 0 + +func _process(delta): + if privot: + _update_distance() + if mouselook: + _update_mouselook() + if movement: + _update_movement(delta) + +func _physics_process(delta): + # Called when collision are enabled + _update_distance() + if mouselook: + _update_mouselook() + + var space_state = get_world().get_direct_space_state() + var obstacle = space_state.intersect_ray(privot.get_translation(), get_translation()) + if not obstacle.empty(): + set_translation(obstacle.position) + +func _update_movement(delta): + var offset = max_speed * acceleration * _direction + + _speed.x = clamp(_speed.x + offset.x, -max_speed.x, max_speed.x) + _speed.y = clamp(_speed.y + offset.y, -max_speed.y, max_speed.y) + _speed.z = clamp(_speed.z + offset.z, -max_speed.z, max_speed.z) + + # Apply deceleration if no input + if _direction.x == 0: + _speed.x *= (1.0 - deceleration) + if _direction.y == 0: + _speed.y *= (1.0 - deceleration) + if _direction.z == 0: + _speed.z *= (1.0 - deceleration) + + if local: + translate(_speed * delta) + else: + global_translate(_speed * delta) + +func _update_mouselook(): + _mouse_position *= sensitivity + _yaw = _yaw * smoothness + _mouse_position.x * (1.0 - smoothness) + _pitch = _pitch * smoothness + _mouse_position.y * (1.0 - smoothness) + _mouse_position = Vector2(0, 0) + + if yaw_limit < 360: + _yaw = clamp(_yaw, -yaw_limit - _total_yaw, yaw_limit - _total_yaw) + if pitch_limit < 360: + _pitch = clamp(_pitch, -pitch_limit - _total_pitch, pitch_limit - _total_pitch) + + _total_yaw += _yaw + _total_pitch += _pitch + + if privot: + var target = privot.get_translation() + var offset = get_translation().distance_to(target) + + set_translation(target) + rotate_y(deg2rad(-_yaw)) + rotate_object_local(Vector3(1,0,0), deg2rad(-_pitch)) + translate(Vector3(0.0, 0.0, offset)) + + if rotate_privot: + privot.rotate_y(deg2rad(-_yaw)) + else: + rotate_y(deg2rad(-_yaw)) + rotate_object_local(Vector3(1,0,0), deg2rad(-_pitch)) + +func _update_distance(): + var t = privot.get_translation() + t.z -= distance + set_translation(t) + +func _update_process_func(): + # Use physics process if collision are enabled + if collisions and privot: + set_physics_process(true) + set_process(false) + else: + set_physics_process(false) + set_process(true) + +func _check_actions(actions=[]): + if OS.is_debug_build(): + for action in actions: + if not InputMap.has_action(action): + print('WARNING: No action "' + action + '"') + +func set_privot(value): + privot = value + # TODO: fix parenting. +# if privot: +# if get_parent(): +# get_parent().remove_child(self) +# privot.add_child(self) + _update_process_func() + +func set_collisions(value): + collisions = value + _update_process_func() + +func set_enabled(value): + enabled = value + if enabled: + Input.set_mouse_mode(mouse_mode) + set_process_input(true) + _update_process_func() + else: + set_process(false) + set_process_input(false) + set_physics_process(false) + +func set_smoothness(value): + smoothness = clamp(value, 0.001, 0.999) + +func set_distance(value): + distance = max(0, value) diff --git a/assets/maujoe.camera_control/scripts/camera_control_gui.gd b/assets/maujoe.camera_control/scripts/camera_control_gui.gd new file mode 100644 index 0000000..140c2aa --- /dev/null +++ b/assets/maujoe.camera_control/scripts/camera_control_gui.gd @@ -0,0 +1,296 @@ +# Licensed under the MIT License. +# Copyright (c) 2018 Jaccomo Lorenz (Maujoe) + +extends Control + +# Constant Gui Settings +#******************************************************************************* +const GUI_POS = Vector2(10, 10) +const GUI_SIZE = Vector2(200, 0) +const DRAGGABLE = true + +const CUSTOM_BACKGROUND = false +const BACKGROUND_COLOR = Color(0.15, 0.17, 0.23, 0.75) + +const MAX_SPEED = 50 +#******************************************************************************* + +var camera +var shortcut +var node_list +var privot +var panel + +var mouse_over = false +var mouse_pressed = false + +func _init(camera, shortcut): + self.camera = camera + self.shortcut = shortcut + +func _ready(): + if camera.enabled: + set_process_input(true) + + # Create Gui + panel = PanelContainer.new() + panel.set_begin(GUI_POS) + panel.set_custom_minimum_size(GUI_SIZE) + + if CUSTOM_BACKGROUND: + var style = StyleBoxFlat.new() + style.set_bg_color(BACKGROUND_COLOR) + style.set_expand_margin_all(5) + panel.add_stylebox_override("panel", style) + + var container = VBoxContainer.new() + + var lbl_mouse = Label.new() + lbl_mouse.set_text("Mousemode") + + var mouse = OptionButton.new() + mouse.add_item("Visible") + mouse.add_item("Hidden") + mouse.add_item("Captured") + mouse.add_item("Confined") + mouse.select(camera.mouse_mode) + mouse.connect("item_selected",self,"_on_opt_mouse_item_selected") + + # Mouselook + var mouselook = CheckButton.new() + mouselook.set_text("Mouselook") + mouselook.set_toggle_mode(true) + mouselook.set_pressed(camera.mouselook) + mouselook.connect("toggled",self,"_on_btn_mouselook_toggled") + + var lbl_sensitivity = Label.new() + lbl_sensitivity.set_text("Sensitivity") + + var sensitivity = HScrollBar.new() + sensitivity.set_max(1) + sensitivity.set_value(camera.sensitivity) + sensitivity.connect("value_changed",self,"_on_hsb_sensitivity_value_changed") + + var lbl_smoothless = Label.new() + lbl_smoothless.set_text("Smoothness") + + var smoothness = HScrollBar.new() + smoothness.set_max(0.999) + smoothness.set_min(0.5) + smoothness.set_value(camera.smoothness) + smoothness.connect("value_changed",self,"_on_hsb_smoothness_value_changed") + + var lbl_privot = Label.new() + lbl_privot.set_text("Privot") + + privot = OptionButton.new() + privot.set_text("Privot") + _update_privots(privot) + privot.connect("item_selected",self,"_on_opt_privot_item_selected") + privot.connect("pressed",self,"_on_opt_privot_pressed") + + var btn_rot_privot = CheckButton.new() + btn_rot_privot.set_text("Rotate Privot") + btn_rot_privot.set_toggle_mode(true) + btn_rot_privot.set_pressed(camera.rotate_privot) + btn_rot_privot.connect("toggled",self,"_on_btn_rot_privot_toggled") + + var lbl_distance = Label.new() + lbl_distance.set_text("Distance") + + var distance = SpinBox.new() + distance.set_value(camera.distance) + distance.connect("value_changed",self,"_on_box_distance_value_changed") + + var lbl_yaw = Label.new() + lbl_yaw.set_text("Yaw Limit") + + var yaw = SpinBox.new() + yaw.set_max(360) + yaw.set_value(camera.yaw_limit) + yaw.connect("value_changed",self,"_on_box_yaw_value_changed") + + var lbl_pitch = Label.new() + lbl_pitch.set_text("Pitch Limit") + + var pitch = SpinBox.new() + pitch.set_max(360) + pitch.set_value(camera.pitch_limit) + pitch.connect("value_changed",self,"_on_box_pitch_value_changed") + + var collisions = CheckButton.new() + collisions.set_text("Collisions") + collisions.set_toggle_mode(true) + collisions.set_pressed(camera.collisions) + collisions.connect("toggled",self,"_on_btn_collisions_toggled") + + # Movement + var lbl_movement = Label.new() + lbl_movement.set_text("Movement") + + var movement = CheckButton.new() + movement.set_pressed(camera.movement) + movement.connect("toggled",self,"_on_btn_movement_toggled") + + var lbl_speed = Label.new() + lbl_speed.set_text("Max Speed") + + var speed = HScrollBar.new() + speed.set_max(MAX_SPEED) + speed.set_value(camera.max_speed.x) + speed.connect("value_changed",self,"_on_hsb_speed_value_changed") + + var lbl_acceleration = Label.new() + lbl_acceleration.set_text("Acceleration") + + var acceleration = HScrollBar.new() + acceleration.set_max(1.0) + acceleration.set_value(camera.acceleration) + acceleration.connect("value_changed", self, "_in_hsb_acceleration_value_changed") + + var lbl_deceleration = Label.new() + lbl_deceleration.set_text("Deceleration") + + var deceleration = HScrollBar.new() + deceleration.set_max(1.0) + deceleration.set_value(camera.deceleration) + deceleration.connect("value_changed", self, "_in_hsb_deceleration_value_changed") + + add_child(panel) + panel.add_child(container) + container.add_child(lbl_mouse) + container.add_child(mouse) + container.add_child(mouselook) + container.add_child(lbl_sensitivity) + container.add_child(sensitivity) + container.add_child(lbl_smoothless) + container.add_child(smoothness) + container.add_child(lbl_privot) + container.add_child(privot) + container.add_child(btn_rot_privot) + container.add_child(lbl_distance) + container.add_child(distance) + container.add_child(lbl_yaw) + container.add_child(yaw) + container.add_child(lbl_pitch) + container.add_child(pitch) + container.add_child(collisions) + container.add_child(lbl_movement) + container.add_child(movement) + container.add_child(lbl_speed) + container.add_child(speed) + container.add_child(lbl_acceleration) + container.add_child(acceleration) + container.add_child(lbl_deceleration) + container.add_child(deceleration) + + if DRAGGABLE: + panel.connect("mouse_entered", self, "_panel_entered") + panel.connect("mouse_exited", self, "_panel_exited") + container.connect("mouse_entered", self, "_panel_entered") + container.connect("mouse_exited", self, "_panel_exited") + + self.hide() + else: + set_process_input(false) + +func _input(event): + if event.is_action_pressed(shortcut): + if camera.enabled: + camera.enabled = false + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + self.show() + else: + camera.enabled = true + self.hide() + + if DRAGGABLE: + if event is InputEventMouseButton and event.button_index == BUTTON_LEFT: + mouse_pressed = event.pressed + + elif event is InputEventMouseMotion and mouse_over and mouse_pressed: + panel.set_begin(panel.get_begin() + event.relative) + +func _update_privots(privot): + privot.clear() + privot.add_item("None") + node_list = _get_spatials_recusiv(get_tree().get_root(), [get_name(), camera.get_name()]) + + var size = node_list.size() + for i in range(0, size): + var node = node_list[i] + privot.add_item(node.get_name()) + if node == camera.privot: + privot.select(i+1) + + if not camera.privot: + privot.select(0) + + +func _get_spatials_recusiv(node, exceptions=[]): + var list = [] + for child in node.get_children(): + if not child.get_name() in exceptions: + if child is Spatial: + list.append(child) + if not child.get_children().empty(): + for subchild in _get_spatials_recusiv(child, exceptions): + list.append(subchild) + return list + +func _panel_entered(): + mouse_over = true + +func _panel_exited(): + mouse_over = false + +func _on_opt_mouse_item_selected(id): + camera.mouse_mode = id + +func _on_btn_mouselook_toggled(pressed): + camera.mouselook = pressed + +func _on_hsb_sensitivity_value_changed(value): + camera.sensitivity = value + +func _on_hsb_smoothness_value_changed(value): + camera.smoothness = value + +func _on_opt_privot_pressed(): + _update_privots(privot) + +func _on_opt_privot_item_selected(id): + if id > 0: + camera.privot = node_list[id-1] + else: + camera.privot = null + privot.select(id) + +func _on_btn_rot_privot_toggled(pressed): + camera.rotate_privot = pressed + +func _on_box_distance_value_changed(value): + camera.distance = value + +func _on_box_yaw_value_changed(value): + camera.yaw_limit = value + +func _on_box_pitch_value_changed(value): + camera.pitch_limit = value + +func _on_btn_collisions_toggled(pressed): + camera.collisions = pressed + +func _on_btn_movement_toggled(pressed): + camera.movement = pressed + +func _on_hsb_speed_value_changed(value): + camera.max_speed.x = value + camera.max_speed.y = value + camera.max_speed.z = value + +func _in_hsb_acceleration_value_changed(value): + camera.acceleration = value + +func _in_hsb_deceleration_value_changed(value): + camera.deceleration = value diff --git a/default_env.tres b/default_env.tres new file mode 100644 index 0000000..615551c --- /dev/null +++ b/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="PanoramaSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/grass-1024.jpg b/grass-1024.jpg new file mode 100644 index 0000000..6e00de9 Binary files /dev/null and b/grass-1024.jpg differ diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..2b65815 Binary files /dev/null and b/icon.png differ diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..d3d813f --- /dev/null +++ b/project.godot @@ -0,0 +1,72 @@ +; 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=4 + +_global_script_classes=[ { +"base": "Node", +"class": "PlanetFace", +"language": "GDScript", +"path": "res://oldscripts/PlanetFace.gd" +}, { +"base": "Node", +"class": "PlanetFaceGenerator", +"language": "GDScript", +"path": "res://oldscripts/PlanetFaceGenerator.gd" +}, { +"base": "Spatial", +"class": "PlanetTerrain", +"language": "GDScript", +"path": "res://oldscripts/PlanetTerrain.gd" +} ] +_global_script_class_icons={ +"PlanetFace": "", +"PlanetFaceGenerator": "", +"PlanetTerrain": "" +} + +[application] + +config/name="Planet" +run/main_scene="res://scenes/World.tscn" +config/icon="res://icon.png" + +[input] + +ui_left={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null) + ] +} +ui_right={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null) + ] +} +ui_up={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null) + ] +} +ui_down={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"unicode":0,"echo":false,"script":null) + ] +} + +[rendering] + +environment/default_environment="res://default_env.tres" diff --git a/scenes/Planet.tscn b/scenes/Planet.tscn new file mode 100644 index 0000000..73cbd1e --- /dev/null +++ b/scenes/Planet.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://oldscripts/Planet.gd" type="Script" id=1] + + +[node name="Planet" type="Spatial"] +script = ExtResource( 1 ) + diff --git a/scenes/SpaceEnvironment.tres b/scenes/SpaceEnvironment.tres new file mode 100644 index 0000000..319de41 --- /dev/null +++ b/scenes/SpaceEnvironment.tres @@ -0,0 +1,10 @@ +[gd_resource type="Environment" load_steps=3 format=2] + +[ext_resource path="res://space.png" type="Texture" id=1] + +[sub_resource type="PanoramaSky" id=1] +panorama = ExtResource( 1 ) + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/scenes/World.tscn b/scenes/World.tscn new file mode 100644 index 0000000..631e6c5 --- /dev/null +++ b/scenes/World.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://scenes/Planet.tscn" type="PackedScene" id=1] +[ext_resource path="res://scripts/Planet.gd" type="Script" id=2] +[ext_resource path="res://assets/maujoe.camera_control/scripts/camera_control.gd" type="Script" id=3] +[ext_resource path="res://default_env.tres" type="Environment" id=4] + +[sub_resource type="SpatialMaterial" id=1] +albedo_color = Color( 0.00392157, 0.466667, 0, 1 ) +metallic = 0.56 + +[node name="World" type="WorldEnvironment"] +environment = ExtResource( 4 ) + +[node name="Planet" parent="." instance=ExtResource( 1 )] +script = ExtResource( 2 ) +face_resolution = 64 +face_material = SubResource( 1 ) + +[node name="Camera" type="Camera" parent="."] +transform = Transform( 1, 0, 0, 0, 0.906308, 0.422618, 0, -0.422618, 0.906308, 0, 106.609, 211.095 ) +far = 1000.0 +script = ExtResource( 3 ) +max_speed = Vector3( 100, 100, 100 ) + +[node name="DirectionalLight" type="DirectionalLight" parent="."] +transform = Transform( 1, 0, 0, 0, -0.736719, 0.676199, 0, -0.676199, -0.736719, -0.0353088, 35.3451, 41.178 ) diff --git a/scripts/Planet.gd b/scripts/Planet.gd new file mode 100644 index 0000000..527ae64 --- /dev/null +++ b/scripts/Planet.gd @@ -0,0 +1,290 @@ +extends Spatial + +export(int) var planet_radius = 128 +export(int) var face_resolution = 16 +export(Material) var face_material = null +export(Material) var atmosphere_material = null + +export(float) var planet_terrain_seed = 0.0 + +export(int) var terrain_octaves = 3 +export(float) var terrain_period = 64.0 +export(float) var terrain_persistence = 0.5 +export(float) var terrain_lacunarity = 2.0 + +const LOD_MAX = 5 +const LOD_ENABLE = false +const WIREFRAME = false + +class PlanetThreading: + var planet + + func _init(planet): + self.planet = planet + + func _recursive_generate(face): + var generated = false + for child in face.get_children(): + if generated: + break + if child.is_leaf() and not child.generated: + child.generate_mesh() + generated = true + break + elif not child.is_leaf(): + generated = self._recursive_generate(child) + return generated + + func _recursive_tick(face, camera): + for child in face.get_children(): + child.process_lod(camera) + if not child.is_leaf(): + self._recursive_tick(child, camera) + + func _tick(): + var generated = false + for i in self.planet.get_children(): + if generated: continue + generated = self._recursive_generate(self.planet) + + if generated or not LOD_ENABLE: + return + + var camera = self.planet.get_viewport().get_camera() + self._recursive_tick(self.planet, camera) + +class PlanetMetadata: + var resolution + var radius + var material + var lods + var noise + + func _init(resolution, radius, material, lods, noise): + self.resolution = resolution + self.radius = radius + self.material = material + self.lods = lods + self.noise = noise + + func get_radius(): + return self.radius + + func get_resolution(): + return self.resolution + + func get_material(): + return self.material + + func get_detail_levels(): + return self.lods + + func get_noise(): + return self.noise + +class CubeFace extends MeshInstance: + var position + var normal + var left + var forward + var resolution + var radius + var level + var meta + var center + + var generated = false + + func _init(level, pos, normal, meta): + self.meta = meta + self.normal = normal + self.resolution = meta.get_resolution() + self.radius = meta.get_radius() + + self.level = level + + self.generated = false + + # Calculate left (x) and forward (z) vectors from the normal (y) + self.left = Vector3(normal.y, normal.z, normal.x) + self.forward = normal.cross(self.left) + + self.position = pos + + # Center the first face + if level == 0: + self.position = self.position - (self.left * (self.radius / max(2.0, pow(2, self.level)))) + self.position = self.position - (self.forward * (self.radius / max(2.0, pow(2, self.level)))) + + func process_lod(camera): + if not self.center: + return + var camera_pos_local = self.to_local(camera.get_translation()) + var camera_dist_center = (camera_pos_local - self.center).length() + + var divisionLevel = pow(2, self.level) + var split_distance = float(float(self.radius) / divisionLevel) + + if camera_dist_center < split_distance * 1.5 and self.is_leaf(): + self.subdivide() + elif camera_dist_center > split_distance * 2 and not self.is_leaf(): + self.merge() + + func is_leaf(): + return self.level == self.meta.get_detail_levels() or self.get_child_count() == 0 + + func generate_mesh(): + if (self.generated): + return + + var vertices = self.resolution + var noise = self.meta.get_noise() + + var st = SurfaceTool.new() + var mode = Mesh.PRIMITIVE_TRIANGLES + if WIREFRAME: + mode = Mesh.PRIMITIVE_LINES + st.begin(mode) + st.set_material(self.meta.get_material()) + + var divisionLevel = pow(2, self.level) + + for i in range(0.0, vertices): + for j in range (0.0, vertices): + # Vertex index (0 to 1) + var iindex = i / (vertices - 1.0) + var jindex = j / (vertices - 1.0) + + # From the left and forward vectors, we can calculate an oriented vertex + var iv = ((self.left * iindex) * self.radius) / divisionLevel + var jv = ((self.forward * jindex) * self.radius) / divisionLevel + + # Add the scaled left and forward to the centered origin + var vertex = self.position + (iv + jv) + + # Normalize and multiply by radius to create a spherical mesh + var vertNormal = vertex.normalized() + #var pos = vertNormal * (noise.get_noise_3dv(vertex) + self.radius) + var pos = vertNormal * self.radius + + # Add to ST + st.add_uv(Vector2(j * (1 / vertices), i * (1 / vertices))) + st.add_vertex(pos) + + # Set centerpoint + if (i == int(vertices / 2) and j == int(vertices / 2)): + self.center = pos + + # Arrange planet face triangles + for gz in range(0, vertices - 1): + for gx in range(0, vertices - 1): + var topLeft = (gz * vertices) + gx + var topRight = topLeft + 1 + var bottomLeft = ((gz + 1) * vertices) + gx + var bottomRight = bottomLeft + 1 + + #st.add_index(topRight) + #st.add_index(bottomRight) + #st.add_index(topLeft) + #st.add_index(topLeft) + #st.add_index(bottomRight) + #st.add_index(bottomLeft) + + st.add_index(topLeft) + st.add_index(topRight) + st.add_index(bottomLeft) + st.add_index(bottomLeft) + st.add_index(topRight) + st.add_index(bottomRight) + + if not WIREFRAME: + st.generate_normals() + self.mesh = st.commit() + + self.generated = true + + func dispose(): + if self.mesh: + self.mesh = null + self.generated = false + + func merge(): + if self.level == 0: + return + + if self.get_child_count() == 0: + return + + for child in self.get_children(): + child.merge() + child.dispose() + child.queue_free() + + func subdivide(): + if self.level == self.meta.get_detail_levels(): + return + + var lv = self.level + 1 + + var stepLeft = self.left * (self.radius / pow(2, lv)) + var stepForward = self.forward * (self.radius / pow(2, lv)) + + self.add_child(CubeFace.new(lv, self.position + stepForward, self.normal, self.meta)) + self.add_child(CubeFace.new(lv, (self.position + stepLeft) + stepForward, self.normal, self.meta)) + self.add_child(CubeFace.new(lv, self.position, self.normal, self.meta)) + self.add_child(CubeFace.new(lv, (self.position + stepLeft), self.normal, self.meta)) + + self.dispose() + +class CubePlanet extends Spatial: + var faces = [] + + var meta + + func _init(meta): + self.meta = meta + + var hs = meta.get_radius() / 2.0 + + self.set_name("CubePlanet") + + self.add_child(CubeFace.new(0, Vector3(0,0,-hs), Vector3(0,0,-1), self.meta)) # front + self.add_child(CubeFace.new(0, Vector3(0,0, hs), Vector3(0,0,1), self.meta)) # back + + self.add_child(CubeFace.new(0, Vector3(-hs,0, 0), Vector3(-1,0,0), self.meta)) # left + self.add_child(CubeFace.new(0, Vector3(hs,0, 0), Vector3(1,0,0), self.meta)) # right + + self.add_child(CubeFace.new(0, Vector3(0,hs,0), Vector3(0,1,0), self.meta)) # top + self.add_child(CubeFace.new(0, Vector3(0,-hs,0), Vector3(0,-1,0), self.meta)) # bottom + + #self.get_child(0).subdivide() + +var thread + +# Called when the node enters the scene tree for the first time. +func _ready(): + var noise = OpenSimplexNoise.new() + noise.seed = planet_terrain_seed + noise.octaves = terrain_octaves + noise.period = terrain_period + noise.persistence = terrain_period + noise.lacunarity = terrain_lacunarity + + #var atmo = MeshInstance.new() + #var atmo_sphere = SphereMesh.new() + #var atmo_radius = planet_radius + 10 + #atmo_sphere.set_radius(-atmo_radius) + #atmo_sphere.set_height(-atmo_radius * 2) + #atmo_sphere.material = atmosphere_material + #atmo_sphere.material.set_shader_param("ground_radius", atmo_radius) + #atmo_sphere.material.set_shader_param("atmosphere_radius", atmo_radius + .15) + #atmo.mesh = atmo_sphere + #add_child(atmo) + + var planet = CubePlanet.new(PlanetMetadata.new(face_resolution, planet_radius, face_material, LOD_MAX, noise)) + thread = PlanetThreading.new(planet) + add_child(planet) + +func _process(delta): + if thread: + thread._tick() diff --git a/space.png b/space.png new file mode 100644 index 0000000..1174895 Binary files /dev/null and b/space.png differ diff --git a/up.png b/up.png new file mode 100644 index 0000000..950dbfa Binary files /dev/null and b/up.png differ