From c1b7d1b15f394a0f922ec7503831d54b268cf8ff Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Fri, 22 Nov 2024 21:15:54 -0700 Subject: [PATCH] Generalized handling of terrain & material audio --- asset_dev/terrain/grass_green.xcf | Bin 0 -> 25920 bytes .../grass_green/grass_green_albedo.dds | 3 + .../grass_green/grass_green_normal.dds | 3 + levels/debug_level/debug_level.tscn | 2 +- .../terrain_3d_data/terrain3d_00_00.res | 4 +- levels/debug_level/terrain_assets.res | 4 +- project.godot | 7 +- src/equipment/balls/physics_ball/ball_sfx.gd | 34 +++------ src/equipment/balls/physics_ball/game_ball.gd | 13 +--- src/props/scenery/beach/sailboat.tscn | 1 + src/world/terrain.gd | 69 ++++++++++++++++++ 11 files changed, 99 insertions(+), 41 deletions(-) create mode 100644 asset_dev/terrain/grass_green.xcf create mode 100644 assets/textures/grass_green/grass_green_albedo.dds create mode 100644 assets/textures/grass_green/grass_green_normal.dds create mode 100644 src/world/terrain.gd diff --git a/asset_dev/terrain/grass_green.xcf b/asset_dev/terrain/grass_green.xcf new file mode 100644 index 0000000000000000000000000000000000000000..736a54f21361be449dfca4b88896120482884610 GIT binary patch literal 25920 zcmeHPOKVd>6rMJz)z)%bpBqcARv}#k8>j^lvA!sR1<{oh(KNZay^u#uqPC#4YeA4M z#D(s}mF|SD+_-Zg_y_bC=*pcS^_X|y&g3> zlO__BQPNoo=dR7);F{5H)1+RCqe9$DD!tb4^6k!QEehMsT2h%D%2(rZ zv({{d`7RV%@nR{Q>b{DTRK2)MbusL|xO%0%Tq-AxIGmZL-0F^;WC{-&NheGi<)x_2 z?`T%5?Whw@aeIeby0bC=&ra%V*-ZATQz&$Mj+qQLnyq@N##KC%JfmA=$C+PPr@u7o zWL(Z^A6bu|aQHEY4>>$^_^`wGJAB090delHmj;P&e|-H@!U@bt=3A5qCmims3M%fU z{`)=VEHN2J|7%;9EeM|7r7aa@q&{=r)@SAg?+Dffp9nq^l>!Q5i^e%0wXpem4hJV}ou^$$Xez!RO)#Ah_i<2KLo_=fb%u9>s zo?5*4*y3En;`}{}w{BXzeZ}J48H>gQZ-Nay%PIC9Y~(y1JKgio!KR+&6#EV~a~_YK z?s+X((6gLk-@!u8bY5TgmelDUqictkbbyUw0^wgeJR@cu(RL5687m5$X*E+e@J;R{; zjyS&3>9Ou^hp3LPyB(rBi0bI6zOL%Q$M;qB;N!!`hmY@HEE|ds#ZUYEg8S1w!+?(u zA0Ixxf4d!`I==39P<$vp6d#J8wy&$}=OU_us1Bk!{;3|KI==e3P<$vp6d#J8?z4{W zsWqZHzV3F2>L99~Uy$M;qB;N!!`hmY?naatUTueaOkslER9RiOA#d?^x9>C_WV5RpPWb6d#HY#ZUWtQv7Sl^gH?MV*Hc&vts5imUvui literal 0 HcmV?d00001 diff --git a/assets/textures/grass_green/grass_green_albedo.dds b/assets/textures/grass_green/grass_green_albedo.dds new file mode 100644 index 0000000..7543696 --- /dev/null +++ b/assets/textures/grass_green/grass_green_albedo.dds @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07a81d998f0946524dfe7106bb099561ca50a0e6818dcb1e8ae4c08b0b663407 +size 87536 diff --git a/assets/textures/grass_green/grass_green_normal.dds b/assets/textures/grass_green/grass_green_normal.dds new file mode 100644 index 0000000..38c422d --- /dev/null +++ b/assets/textures/grass_green/grass_green_normal.dds @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94ac31a166456ed25b87c332c2f0a93f144aae1a0e91e9c8fba055bc11ef8d4d +size 87536 diff --git a/levels/debug_level/debug_level.tscn b/levels/debug_level/debug_level.tscn index e6cd11e..0ebcf9e 100644 --- a/levels/debug_level/debug_level.tscn +++ b/levels/debug_level/debug_level.tscn @@ -27,7 +27,7 @@ noise = SubResource("FastNoiseLite_rpgb7") [sub_resource type="Terrain3DMaterial" id="Terrain3DMaterial_woy2k"] _shader_parameters = { -"auto_base_texture": 3, +"auto_base_texture": 4, "auto_height_reduction": 0.1, "auto_overlay_texture": 0, "auto_slope": 0.41, diff --git a/levels/debug_level/terrain_3d_data/terrain3d_00_00.res b/levels/debug_level/terrain_3d_data/terrain3d_00_00.res index 1b0a5aa..78db045 100644 --- a/levels/debug_level/terrain_3d_data/terrain3d_00_00.res +++ b/levels/debug_level/terrain_3d_data/terrain3d_00_00.res @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:856b688276a678e328c69379ba04b5b98b8833a4872fc649bd8f1c037e8e6f6a -size 546199 +oid sha256:3633fe2ef5b54d9311e490436429376909b308ecb2769ec8563071822c26c9b4 +size 547143 diff --git a/levels/debug_level/terrain_assets.res b/levels/debug_level/terrain_assets.res index 923f8f6..85ba872 100644 --- a/levels/debug_level/terrain_assets.res +++ b/levels/debug_level/terrain_assets.res @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cac6bd6fb7f3c8a67944fb14f15cb05dc12c164460b8c2d8340a1c95f5c942b -size 1657 +oid sha256:e300ec5067dd4ebe0c89e3834e1b9c1967847887bcde18d7ea3a7ff743e5864a +size 1660 diff --git a/project.godot b/project.godot index ac685ba..0a9a015 100644 --- a/project.godot +++ b/project.godot @@ -197,7 +197,12 @@ ball_previous={ 3d_physics/layer_1="Collision Geometry" 3d_physics/layer_2="Layer 3" -3d_physics/layer_32="Grass Audio" +3d_physics/layer_27="Glass Material" +3d_physics/layer_28="Metal Material" +3d_physics/layer_29="Rock Material" +3d_physics/layer_30="Wood Material" +3d_physics/layer_31="Sand Material" +3d_physics/layer_32="Grass Material" [physics] diff --git a/src/equipment/balls/physics_ball/ball_sfx.gd b/src/equipment/balls/physics_ball/ball_sfx.gd index 9f08411..dc723ea 100644 --- a/src/equipment/balls/physics_ball/ball_sfx.gd +++ b/src/equipment/balls/physics_ball/ball_sfx.gd @@ -5,9 +5,6 @@ const BASE_VOLUME := -36.0 const MAX_VOLUME := 3.0 const VELOCITY_ATTENUATION_SCALE := 400.0 -const GRASS_PHYSICAL_LAYER := 1 << 32 -const SAND_PHYSICAL_LAYER := 1 << 31 - @onready var parent: GameBall = $".." @onready var grass_sfx_player: AudioStreamPlayer3D = %GrassSFXPlayer @@ -24,30 +21,17 @@ func _force_attenuated_volume() -> float: ) -func _play_sfx(player: AudioStreamPlayer3D) -> void: +func _play(player: AudioStreamPlayer3D) -> void: player.volume_db = _force_attenuated_volume() print("PLAYING: ", player, "... VOLUME: ", player.volume_db) player.play() -func play_terrain_sfx(tex_id: int) -> void: - var player := grass_sfx_player - match tex_id: - 2: # sand - player = sand_sfx_player - 3: # rock - player = concrete_sfx_player - - _play_sfx(player) - - -## Select the appropriate SFX to play based on the collision layer of the collider. -## -## We use the upper bits of the collision layer to indicate standard SFX. -func play_physical_sfx(collision_mask: int) -> void: - var player := concrete_sfx_player - if collision_mask & GRASS_PHYSICAL_LAYER: - player = grass_sfx_player - elif collision_mask & SAND_PHYSICAL_LAYER: - player = sand_sfx_player - _play_sfx(player) +func play_sfx(terrain: Terrain.Type) -> void: + match terrain: + Terrain.Type.ROUGH, Terrain.Type.GREEN, Terrain.Type.FAIRWAY: + _play(grass_sfx_player) + Terrain.Type.CONCRETE, Terrain.Type.ROCK: + _play(concrete_sfx_player) + Terrain.Type.SAND: + _play(sand_sfx_player) diff --git a/src/equipment/balls/physics_ball/game_ball.gd b/src/equipment/balls/physics_ball/game_ball.gd index 3db9f12..3c4bf9d 100644 --- a/src/equipment/balls/physics_ball/game_ball.gd +++ b/src/equipment/balls/physics_ball/game_ball.gd @@ -148,17 +148,10 @@ func _on_sleeping_state_changed() -> void: func _on_collision(body: Node) -> void: if body is Terrain3D: - var texture_blend: Vector3 = (body as Terrain3D).data.get_texture_id(global_position) - print("T3D texture blend: ", texture_blend) - # TODO maybe blend audio? - - # Figure out audio for autoshader - var tex_id: float = 0 if texture_blend.x == 3 and texture_blend.z == 0 else texture_blend.x - - sfx.play_terrain_sfx(tex_id) + sfx.play_sfx(Terrain.at_position(global_position, body as Terrain3D)) elif body is CSGShape3D: - sfx.play_physical_sfx((body as CSGShape3D).collision_layer) + sfx.play_sfx(Terrain.from_physical_layer((body as CSGShape3D).collision_layer)) elif body is CollisionObject3D: - sfx.play_physical_sfx((body as CollisionObject3D).collision_layer) + sfx.play_sfx(Terrain.from_physical_layer((body as CollisionObject3D).collision_layer)) else: print_debug("COLLIDER: ", body) diff --git a/src/props/scenery/beach/sailboat.tscn b/src/props/scenery/beach/sailboat.tscn index a8bd583..5c02636 100644 --- a/src/props/scenery/beach/sailboat.tscn +++ b/src/props/scenery/beach/sailboat.tscn @@ -8,6 +8,7 @@ data = PackedVector3Array(0, 0, -5.2392, -1.2315, 0, -2.5941, 1.2315, 0, -2.5941 [node name="Sailboat" instance=ExtResource("1_ivu5q")] [node name="StaticBody3D" type="StaticBody3D" parent="." index="1"] +collision_layer = 536870913 [node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D" index="0"] shape = SubResource("ConcavePolygonShape3D_mrf68") diff --git a/src/world/terrain.gd b/src/world/terrain.gd new file mode 100644 index 0000000..41f3ace --- /dev/null +++ b/src/world/terrain.gd @@ -0,0 +1,69 @@ +class_name Terrain +## Tools for working with different terrain types. +## This provides a unified interface to Terrain3D and regular meshes. + +## Basic terrain materials +enum Type { + NONE, + ROUGH, + FAIRWAY, + GREEN, + SAND, + CONCRETE, + ROCK, + WOOD, + METAL, + GLASS, +} + +## We use the upper bits of collision layers to encode material data +const PHYSICAL_LAYERS := { + 1 << 31: Type.ROUGH, + 1 << 30: Type.SAND, + 1 << 29: Type.WOOD, + 1 << 28: Type.ROCK, + 1 << 27: Type.METAL, + 1 << 26: Type.GLASS, +} + + +## Get the `Terrain.Type` value which corresponds to the given Terrain3D texture ID. +## +## Note that this relies on the ordering of textures in our Terrain3DAsset resource! +## If the order textures are defined in changes, this will break! +static func from_texture_id(tex_id: int) -> Type: + match tex_id: + 0: + return Type.ROUGH + 1: + return Type.FAIRWAY + 2: + return Type.SAND + 3: + return Type.GREEN + 4: + return Type.ROCK + _: + return Type.NONE + + +## Get the `Terrain.Type` value encoded in the given collision layer setting. +## +## We use the upper bits in the collision layer to encode material data. +## Check the collision layer descriptions for more information. +static func from_physical_layer(collision_layer: int) -> Type: + for bit: int in PHYSICAL_LAYERS: + if collision_layer & bit: + return PHYSICAL_LAYERS[bit] + return Type.CONCRETE + + +## Get the `Terrain.Type` value at the given position in a Terrain3D node. +static func at_position(global_position: Vector3, terrain3d: Terrain3D) -> Type: + var blend := terrain3d.data.get_texture_id(global_position) + var id: int + if terrain3d.data.get_control_auto(global_position): + id = blend.x if blend.z > 0 else blend.y + else: + id = blend.x + return from_texture_id(id)