Terrain des sites de plongée : champ de hauteur authoré, Banc du Vigilant, formes variées et rendu sous-marin #4
No files matched your search
@@ -9,15 +9,15 @@
|
|||||||
script = ExtResource("1_n3xpu")
|
script = ExtResource("1_n3xpu")
|
||||||
placement_id = &"prospection_vessel"
|
placement_id = &"prospection_vessel"
|
||||||
kind = 0
|
kind = 0
|
||||||
position_m = Vector3(-12, -37.10001, 108)
|
position_m = Vector3(-14.154642, -37.198338, 98.39586)
|
||||||
yaw_radians = 0.35
|
yaw_radians = -1.380808047881126
|
||||||
footprint_m = Vector3(28, 8, 9)
|
footprint_m = Vector3(28, 8, 9)
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_xcojm"]
|
[sub_resource type="Resource" id="Resource_xcojm"]
|
||||||
script = ExtResource("1_n3xpu")
|
script = ExtResource("1_n3xpu")
|
||||||
placement_id = &"decoy_yacht"
|
placement_id = &"decoy_yacht"
|
||||||
kind = 1
|
kind = 1
|
||||||
position_m = Vector3(-40, -24.655516, -200)
|
position_m = Vector3(-30, -25.199738, -150)
|
||||||
yaw_radians = 1.1
|
yaw_radians = 1.1
|
||||||
footprint_m = Vector3(12, 3, 4)
|
footprint_m = Vector3(12, 3, 4)
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ footprint_m = Vector3(4, 1.5, 1.5)
|
|||||||
script = ExtResource("1_n3xpu")
|
script = ExtResource("1_n3xpu")
|
||||||
placement_id = &"vessel_anchor"
|
placement_id = &"vessel_anchor"
|
||||||
kind = 5
|
kind = 5
|
||||||
position_m = Vector3(0, -14, -250)
|
position_m = Vector3(0, -14, -210)
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_e72vy"]
|
[sub_resource type="Resource" id="Resource_e72vy"]
|
||||||
script = ExtResource("1_n3xpu")
|
script = ExtResource("1_n3xpu")
|
||||||
@@ -101,13 +101,13 @@ position_m = Vector3(40, -40, 125)
|
|||||||
[sub_resource type="Resource" id="Resource_xvesq"]
|
[sub_resource type="Resource" id="Resource_xvesq"]
|
||||||
script = ExtResource("2_36hd6")
|
script = ExtResource("2_36hd6")
|
||||||
route_id = &"safe_ridge"
|
route_id = &"safe_ridge"
|
||||||
waypoints_m = PackedVector3Array(0, -14, -250, 70, -16, -200, 76, -16, -100, 78, -16, 0, 76, -18, 80, 40, -24, 105, 0, -26, 100, -14, -30, 98)
|
waypoints_m = PackedVector3Array(0, -14, -210, 70, -16, -200, 76, -16, -100, 78, -16, 0, 76, -18, 80, 40, -24, 105, 0, -26, 100, -14, -30, 98)
|
||||||
maximum_depth_m = 32.0
|
maximum_depth_m = 32.0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_lcu7s"]
|
[sub_resource type="Resource" id="Resource_lcu7s"]
|
||||||
script = ExtResource("2_36hd6")
|
script = ExtResource("2_36hd6")
|
||||||
route_id = &"risky_groove"
|
route_id = &"risky_groove"
|
||||||
waypoints_m = PackedVector3Array(0, -14, -250, -60, -20, -150, -50, -31, -100, -35, -33, -20, -22, -34, 60, -14, -33, 98)
|
waypoints_m = PackedVector3Array(0, -14, -210, -60, -20, -150, -50, -31, -100, -35, -33, -20, -22, -34, 60, -14, -33, 98)
|
||||||
maximum_depth_m = 48.0
|
maximum_depth_m = 48.0
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
@@ -116,6 +116,7 @@ site_id = &"zone1_vigilant"
|
|||||||
display_name = "Banc du Vigilant"
|
display_name = "Banc du Vigilant"
|
||||||
terrain = ExtResource("4_i0v8k")
|
terrain = ExtResource("4_i0v8k")
|
||||||
playable_bounds_m = Rect2(-300, -300, 600, 600)
|
playable_bounds_m = Rect2(-300, -300, 600, 600)
|
||||||
spawn_position_m = Vector3(0, -10, -250)
|
spawn_position_m = Vector3(0, -10, -210)
|
||||||
|
spawn_yaw_radians = 3.141592653589793
|
||||||
placements = Array[ExtResource("1_n3xpu")]([SubResource("Resource_rqt47"), SubResource("Resource_xcojm"), SubResource("Resource_yljal"), SubResource("Resource_aqgwj"), SubResource("Resource_aervf"), SubResource("Resource_qgawl"), SubResource("Resource_q0ace"), SubResource("Resource_hd5cl"), SubResource("Resource_wy8hl"), SubResource("Resource_e72vy"), SubResource("Resource_3n33i"), SubResource("Resource_cdmnh"), SubResource("Resource_u8dqp"), SubResource("Resource_3uttw")])
|
placements = Array[ExtResource("1_n3xpu")]([SubResource("Resource_rqt47"), SubResource("Resource_xcojm"), SubResource("Resource_yljal"), SubResource("Resource_aqgwj"), SubResource("Resource_aervf"), SubResource("Resource_qgawl"), SubResource("Resource_q0ace"), SubResource("Resource_hd5cl"), SubResource("Resource_wy8hl"), SubResource("Resource_e72vy"), SubResource("Resource_3n33i"), SubResource("Resource_cdmnh"), SubResource("Resource_u8dqp"), SubResource("Resource_3uttw")])
|
||||||
routes = Array[ExtResource("2_36hd6")]([SubResource("Resource_xvesq"), SubResource("Resource_lcu7s")])
|
routes = Array[ExtResource("2_36hd6")]([SubResource("Resource_xvesq"), SubResource("Resource_lcu7s")])
|
||||||
@@ -86,7 +86,7 @@ crédibilité, conformément à la direction artistique.
|
|||||||
| Champ de hauteur | 513 × 513 cellules, 1,5 m par cellule, élévations float32 (`SiteTerrainData`) |
|
| Champ de hauteur | 513 × 513 cellules, 1,5 m par cellule, élévations float32 (`SiteTerrainData`) |
|
||||||
| Profondeur min / max du terrain | 20 m / 88 m |
|
| Profondeur min / max du terrain | 20 m / 88 m |
|
||||||
| Profondeur d'écrasement coque I | hors terrain : le fond ne tue jamais par lui-même |
|
| Profondeur d'écrasement coque I | hors terrain : le fond ne tue jamais par lui-même |
|
||||||
| Mouillage du navire | centre nord du plateau, 24 m de fond |
|
| Mouillage du navire | centre nord du plateau, 25 m de fond |
|
||||||
| Point de départ du sous-marin | sous le navire, 10 m de profondeur |
|
| Point de départ du sous-marin | sous le navire, 10 m de profondeur |
|
||||||
|
|
||||||
Les distances sont dimensionnées pour l'autonomie Standard (environ 1,2 km,
|
Les distances sont dimensionnées pour l'autonomie Standard (environ 1,2 km,
|
||||||
@@ -150,14 +150,14 @@ correspond pas au rapport.
|
|||||||
|
|
||||||
### 4.4 Les deux routes vers la cible
|
### 4.4 Les deux routes vers la cible
|
||||||
|
|
||||||
**Route sûre — par l'Échine (≈ 470 m, 26–32 m).** Depuis le navire, suivre la
|
**Route sûre — par l'Échine (≈ 450 m, 26–32 m).** Depuis le navire, suivre la
|
||||||
crête longue vers le sud. Elle est lumineuse, large, sans obstacle, et se lit
|
crête longue vers le sud. Elle est lumineuse, large, sans obstacle, et se lit
|
||||||
d'un seul scan. Elle mène au bord du plateau au-dessus de la Saignée : il
|
d'un seul scan. Elle mène au bord du plateau au-dessus de la Saignée : il
|
||||||
faut ensuite descendre dans le sillon par son extrémité nord, à faible
|
faut ensuite descendre dans le sillon par son extrémité nord, à faible
|
||||||
pente. Coût : temps et batterie. Récompense : zéro dégât, retour facile à
|
pente. Coût : temps et batterie. Récompense : zéro dégât, retour facile à
|
||||||
estimer.
|
estimer.
|
||||||
|
|
||||||
**Route risquée — par la Saignée (≈ 370 m, 36–48 m).** Un sillon de 12 à
|
**Route risquée — par la Saignée (≈ 340 m, 36–48 m).** Un sillon de 12 à
|
||||||
18 m de large, aux parois de 8 à 10 m, qui coupe le plateau en diagonale et
|
18 m de large, aux parois de 8 à 10 m, qui coupe le plateau en diagonale et
|
||||||
débouche directement sur la proue de la cible. Sombre (les projecteurs
|
débouche directement sur la proue de la cible. Sombre (les projecteurs
|
||||||
deviennent nécessaires), étroit (collisions), en pente (la batterie de
|
deviennent nécessaires), étroit (collisions), en pente (la batterie de
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ const DiveRulesResolver = preload("res://game/domain/rules/dive_rules_resolver.g
|
|||||||
const SITE_PATH := "res://content/sites/zone1_vigilant.tres"
|
const SITE_PATH := "res://content/sites/zone1_vigilant.tres"
|
||||||
const ROUTE_CLEARANCE_M := 3.0
|
const ROUTE_CLEARANCE_M := 3.0
|
||||||
const MINIMUM_LANDMARK_SPACING_M := 60.0
|
const MINIMUM_LANDMARK_SPACING_M := 60.0
|
||||||
const TEST_COUNT := 30
|
const MAXIMUM_ANCHOR_TO_WRECK_M := 320.0
|
||||||
|
const MAXIMUM_WRECK_SPACING_M := 260.0
|
||||||
|
const HULL_HALF_LENGTH_M := 14.0
|
||||||
|
const HULL_SEABED_TOLERANCE_M := 2.0
|
||||||
|
const TEST_COUNT := 34
|
||||||
|
|
||||||
var _failures: Array[String] = []
|
var _failures: Array[String] = []
|
||||||
|
|
||||||
@@ -107,6 +111,26 @@ func _test_zone1_content() -> void:
|
|||||||
spaced = false
|
spaced = false
|
||||||
_expect(spaced, "landmarks are at least 60 m apart")
|
_expect(spaced, "landmarks are at least 60 m apart")
|
||||||
|
|
||||||
|
var wrecks := targets + decoys
|
||||||
|
if anchors.size() == 1:
|
||||||
|
var anchor := anchors[0].position_m
|
||||||
|
var farthest := 0.0
|
||||||
|
for wreck: SitePlacement in wrecks:
|
||||||
|
farthest = maxf(farthest, _xz_distance(anchor, wreck.position_m))
|
||||||
|
_expect(farthest <= MAXIMUM_ANCHOR_TO_WRECK_M, "every wreck lies within 320 m of the mooring (farthest %.0f m)" % farthest)
|
||||||
|
var widest := 0.0
|
||||||
|
for i in wrecks.size():
|
||||||
|
for j in range(i + 1, wrecks.size()):
|
||||||
|
widest = maxf(widest, _xz_distance(wrecks[i].position_m, wrecks[j].position_m))
|
||||||
|
_expect(widest <= MAXIMUM_WRECK_SPACING_M, "every pair of wrecks lies within 260 m (widest %.0f m)" % widest)
|
||||||
|
if targets.size() == 1:
|
||||||
|
var target_xz := Vector2(targets[0].position_m.x, targets[0].position_m.z)
|
||||||
|
var spawn_xz := Vector2(spawn.x, spawn.z)
|
||||||
|
var yaw := definition.spawn_yaw_radians
|
||||||
|
var spawn_forward := Vector2(-sin(yaw), -cos(yaw))
|
||||||
|
_expect(spawn_forward.dot(target_xz - spawn_xz) > 0.0, "the spawn faces the target wreck")
|
||||||
|
_expect(_hull_lies_along_seabed(field, targets[0]), "the target hull lies along the groove floor")
|
||||||
|
|
||||||
|
|
||||||
func _rests_on_terrain(field: TerrainHeightField, placement: SitePlacement) -> bool:
|
func _rests_on_terrain(field: TerrainHeightField, placement: SitePlacement) -> bool:
|
||||||
var seabed := field.elevation_at(placement.position_m.x, placement.position_m.z)
|
var seabed := field.elevation_at(placement.position_m.x, placement.position_m.z)
|
||||||
@@ -114,6 +138,17 @@ func _rests_on_terrain(field: TerrainHeightField, placement: SitePlacement) -> b
|
|||||||
return bottom >= seabed - placement.footprint_m.y and bottom <= seabed + 1.0
|
return bottom >= seabed - placement.footprint_m.y and bottom <= seabed + 1.0
|
||||||
|
|
||||||
|
|
||||||
|
func _hull_lies_along_seabed(field: TerrainHeightField, hull: SitePlacement) -> bool:
|
||||||
|
var centre := Vector2(hull.position_m.x, hull.position_m.z)
|
||||||
|
var long_axis := Vector2(cos(hull.yaw_radians), -sin(hull.yaw_radians))
|
||||||
|
var centre_seabed := field.elevation_at(centre.x, centre.y)
|
||||||
|
for side: float in [-1.0, 1.0]:
|
||||||
|
var end := centre + long_axis * HULL_HALF_LENGTH_M * side
|
||||||
|
if absf(field.elevation_at(end.x, end.y) - centre_seabed) > HULL_SEABED_TOLERANCE_M:
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
||||||
func _route_clears_terrain(field: TerrainHeightField, route: SiteRoute) -> bool:
|
func _route_clears_terrain(field: TerrainHeightField, route: SiteRoute) -> bool:
|
||||||
for i in range(route.waypoints_m.size() - 1):
|
for i in range(route.waypoints_m.size() - 1):
|
||||||
var a := route.waypoints_m[i]
|
var a := route.waypoints_m[i]
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ const GROOVE_END := Vector2(-10.0, 120.0)
|
|||||||
const RIDGE_START := Vector2(70.0, -150.0)
|
const RIDGE_START := Vector2(70.0, -150.0)
|
||||||
const RIDGE_END := Vector2(80.0, 90.0)
|
const RIDGE_END := Vector2(80.0, 90.0)
|
||||||
const BREAK_Z := 125.0
|
const BREAK_Z := 125.0
|
||||||
|
# The target's centre sits this far up the groove from GROOVE_END, so its 28 m hull
|
||||||
|
# stops one groove half-width short of the end cap and rests on the flat groove floor.
|
||||||
|
const TARGET_SET_BACK_M := 22.0
|
||||||
|
|
||||||
|
|
||||||
static func recipe() -> SiteTerrainBaker.Recipe:
|
static func recipe() -> SiteTerrainBaker.Recipe:
|
||||||
@@ -30,7 +33,7 @@ static func recipe() -> SiteTerrainBaker.Recipe:
|
|||||||
result.rock_reflectivity = 0.72
|
result.rock_reflectivity = 0.72
|
||||||
result.sand_reflectivity = 0.45
|
result.sand_reflectivity = 0.45
|
||||||
result.primitives = [
|
result.primitives = [
|
||||||
# Plateau: 24 m deep at the vessel (z = -300), 6 m deeper over 400 m toward the south.
|
# Plateau: 24 m deep at z = -300 (about 25 m at the mooring), 6 m deeper over 400 m toward the south.
|
||||||
SiteTerrainBaker.SlopedPlane.new(24.0, 0.0, -0.015, 0.0, -300.0),
|
SiteTerrainBaker.SlopedPlane.new(24.0, 0.0, -0.015, 0.0, -300.0),
|
||||||
# L'Échine: long north-south rock ridge, 6 m high, flanks steeper than 20°.
|
# L'Échine: long north-south rock ridge, 6 m high, flanks steeper than 20°.
|
||||||
SiteTerrainBaker.Ridge.new(RIDGE_START, RIDGE_END, 12.0, 6.0, 25.0),
|
SiteTerrainBaker.Ridge.new(RIDGE_START, RIDGE_END, 12.0, 6.0, 25.0),
|
||||||
@@ -63,18 +66,23 @@ static func recipe() -> SiteTerrainBaker.Recipe:
|
|||||||
|
|
||||||
static func definition(terrain: SiteTerrainData) -> DiveSiteDefinition:
|
static func definition(terrain: SiteTerrainData) -> DiveSiteDefinition:
|
||||||
var field := TerrainHeightField.from_data(terrain)
|
var field := TerrainHeightField.from_data(terrain)
|
||||||
|
# The target hull's long axis (local +X) lies along la Saignée.
|
||||||
|
var groove_axis := (GROOVE_END - GROOVE_START).normalized()
|
||||||
|
var groove_yaw := atan2(-groove_axis.y, groove_axis.x)
|
||||||
|
var target_xz := GROOVE_END - groove_axis * TARGET_SET_BACK_M
|
||||||
var result := DiveSiteDefinition.new()
|
var result := DiveSiteDefinition.new()
|
||||||
result.site_id = &"zone1_vigilant"
|
result.site_id = &"zone1_vigilant"
|
||||||
result.display_name = "Banc du Vigilant"
|
result.display_name = "Banc du Vigilant"
|
||||||
result.terrain = terrain
|
result.terrain = terrain
|
||||||
result.playable_bounds_m = Rect2(-300.0, -300.0, 600.0, 600.0)
|
result.playable_bounds_m = Rect2(-300.0, -300.0, 600.0, 600.0)
|
||||||
result.spawn_position_m = Vector3(0.0, -10.0, -250.0)
|
# Spawn beside the mooring, facing south toward the site.
|
||||||
result.spawn_yaw_radians = 0.0
|
result.spawn_position_m = Vector3(0.0, -10.0, -210.0)
|
||||||
|
result.spawn_yaw_radians = PI
|
||||||
result.placements = [
|
result.placements = [
|
||||||
_on_seabed(field, &"prospection_vessel", SitePlacement.Kind.WRECK_TARGET,
|
_on_seabed(field, &"prospection_vessel", SitePlacement.Kind.WRECK_TARGET,
|
||||||
Vector2(-12.0, 108.0), 0.35, Vector3(28.0, 8.0, 9.0), 2.0),
|
target_xz, groove_yaw, Vector3(28.0, 8.0, 9.0), 2.0),
|
||||||
_on_seabed(field, &"decoy_yacht", SitePlacement.Kind.WRECK_DECOY,
|
_on_seabed(field, &"decoy_yacht", SitePlacement.Kind.WRECK_DECOY,
|
||||||
Vector2(-40.0, -200.0), 1.1, Vector3(12.0, 3.0, 4.0), 0.5),
|
Vector2(-30.0, -150.0), 1.1, Vector3(12.0, 3.0, 4.0), 0.5),
|
||||||
_on_seabed(field, &"decoy_coaster", SitePlacement.Kind.WRECK_DECOY,
|
_on_seabed(field, &"decoy_coaster", SitePlacement.Kind.WRECK_DECOY,
|
||||||
Vector2(140.0, 40.0), -0.6, Vector3(26.0, 6.0, 8.0), 1.2),
|
Vector2(140.0, 40.0), -0.6, Vector3(26.0, 6.0, 8.0), 1.2),
|
||||||
_on_seabed(field, &"secondary_item", SitePlacement.Kind.SECONDARY_ITEM,
|
_on_seabed(field, &"secondary_item", SitePlacement.Kind.SECONDARY_ITEM,
|
||||||
@@ -87,7 +95,7 @@ static func definition(terrain: SiteTerrainData) -> DiveSiteDefinition:
|
|||||||
Vector2(-9.0, 146.0), 0.0, Vector3(2.0, 1.5, 2.0), 0.2),
|
Vector2(-9.0, 146.0), 0.0, Vector3(2.0, 1.5, 2.0), 0.2),
|
||||||
_on_seabed(field, &"debris_4", SitePlacement.Kind.DEBRIS,
|
_on_seabed(field, &"debris_4", SitePlacement.Kind.DEBRIS,
|
||||||
Vector2(-7.0, 152.0), 2.0, Vector3(4.0, 1.5, 1.5), 0.3),
|
Vector2(-7.0, 152.0), 2.0, Vector3(4.0, 1.5, 1.5), 0.3),
|
||||||
_marker(&"vessel_anchor", SitePlacement.Kind.VESSEL_ANCHOR, Vector3(0.0, -14.0, -250.0)),
|
_marker(&"vessel_anchor", SitePlacement.Kind.VESSEL_ANCHOR, Vector3(0.0, -14.0, -210.0)),
|
||||||
_marker(&"echine", SitePlacement.Kind.LANDMARK, Vector3(75.0, -20.0, -50.0)),
|
_marker(&"echine", SitePlacement.Kind.LANDMARK, Vector3(75.0, -20.0, -50.0)),
|
||||||
_marker(&"deux_freres", SitePlacement.Kind.LANDMARK, Vector3(-151.0, -18.0, -125.0)),
|
_marker(&"deux_freres", SitePlacement.Kind.LANDMARK, Vector3(-151.0, -18.0, -125.0)),
|
||||||
_marker(&"rides", SitePlacement.Kind.LANDMARK, Vector3(0.0, -25.0, -230.0)),
|
_marker(&"rides", SitePlacement.Kind.LANDMARK, Vector3(0.0, -25.0, -230.0)),
|
||||||
@@ -96,12 +104,12 @@ static func definition(terrain: SiteTerrainData) -> DiveSiteDefinition:
|
|||||||
]
|
]
|
||||||
result.routes = [
|
result.routes = [
|
||||||
_route(&"safe_ridge", 32.0, [
|
_route(&"safe_ridge", 32.0, [
|
||||||
Vector3(0.0, -14.0, -250.0), Vector3(70.0, -16.0, -200.0), Vector3(76.0, -16.0, -100.0),
|
Vector3(0.0, -14.0, -210.0), Vector3(70.0, -16.0, -200.0), Vector3(76.0, -16.0, -100.0),
|
||||||
Vector3(78.0, -16.0, 0.0), Vector3(76.0, -18.0, 80.0), Vector3(40.0, -24.0, 105.0),
|
Vector3(78.0, -16.0, 0.0), Vector3(76.0, -18.0, 80.0), Vector3(40.0, -24.0, 105.0),
|
||||||
Vector3(0.0, -26.0, 100.0), Vector3(-14.0, -30.0, 98.0),
|
Vector3(0.0, -26.0, 100.0), Vector3(-14.0, -30.0, 98.0),
|
||||||
]),
|
]),
|
||||||
_route(&"risky_groove", 48.0, [
|
_route(&"risky_groove", 48.0, [
|
||||||
Vector3(0.0, -14.0, -250.0), Vector3(-60.0, -20.0, -150.0), Vector3(-50.0, -31.0, -100.0),
|
Vector3(0.0, -14.0, -210.0), Vector3(-60.0, -20.0, -150.0), Vector3(-50.0, -31.0, -100.0),
|
||||||
Vector3(-35.0, -33.0, -20.0), Vector3(-22.0, -34.0, 60.0), Vector3(-14.0, -33.0, 98.0),
|
Vector3(-35.0, -33.0, -20.0), Vector3(-22.0, -34.0, 60.0), Vector3(-14.0, -33.0, 98.0),
|
||||||
]),
|
]),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in new issue
Block a user