feat: wire vertical exaggeration through the shell #13
@@ -25,6 +25,7 @@ cargo run -- scene export --output /tmp/openvistapro-default.ovp.toml
|
|||||||
cargo run -- render --preset hill --width 256 --height 256 --output /tmp/openvistapro-hill.png
|
cargo run -- render --preset hill --width 256 --height 256 --output /tmp/openvistapro-hill.png
|
||||||
cargo run -- render --preset hill --scene /tmp/openvistapro-default.ovp.toml --width 256 --height 256 --output /tmp/openvistapro-hill-from-scene.png
|
cargo run -- render --preset hill --scene /tmp/openvistapro-default.ovp.toml --width 256 --height 256 --output /tmp/openvistapro-hill-from-scene.png
|
||||||
cargo run -- render --preset hill --camera-demo --width 256 --height 192 --output /tmp/openvistapro-perspective.png
|
cargo run -- render --preset hill --camera-demo --width 256 --height 192 --output /tmp/openvistapro-perspective.png
|
||||||
|
cargo run -- render --preset hill --quality final --output /tmp/openvistapro-renders/
|
||||||
cargo run --features app --bin openvistapro_app
|
cargo run --features app --bin openvistapro_app
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ cargo test --all-features
|
|||||||
```
|
```
|
||||||
|
|
||||||
The default `render` mode writes a deterministic top-down elevation preview.
|
The default `render` mode writes a deterministic top-down elevation preview.
|
||||||
|
Passing `--quality preview|balanced|final` selects the project-owned quality profile; if `--output` points to an existing directory, the renderer derives a quality-specific PNG name there.
|
||||||
Passing `--camera-demo` switches to the current CPU perspective renderer spike:
|
Passing `--camera-demo` switches to the current CPU perspective renderer spike:
|
||||||
a simple pinhole-camera raymarcher with bilinear height sampling, fixed step
|
a simple pinhole-camera raymarcher with bilinear height sampling, fixed step
|
||||||
size, sky gradient, and distance haze. It is intended as a readable reference
|
size, sky gradient, and distance haze. It is intended as a readable reference
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Notes:
|
|||||||
| Vertical exaggeration | VistaPro manuals describe vertical scaling / scene exaggeration controls. | Implemented | `src/scene.rs` (`Scene.vertical_exaggeration`), `src/app.rs`, `src/app_state.rs`, `src/render.rs`, tests in `src/render.rs`, and scene-file round-trips in `src/scene_file.rs`. | The basic scene-level exaggeration slice is now wired through the shell, renderer, and scene files; future work can explore per-tool or legacy-style exaggeration workflows. |
|
| Vertical exaggeration | VistaPro manuals describe vertical scaling / scene exaggeration controls. | Implemented | `src/scene.rs` (`Scene.vertical_exaggeration`), `src/app.rs`, `src/app_state.rs`, `src/render.rs`, tests in `src/render.rs`, and scene-file round-trips in `src/scene_file.rs`. | The basic scene-level exaggeration slice is now wired through the shell, renderer, and scene files; future work can explore per-tool or legacy-style exaggeration workflows. |
|
||||||
| Color maps / palettes / texture image loading | VistaPro 3 manual includes loading PCX images, adding texture, and saving/loading color maps. | Implemented | `src/scene.rs` (`Palette` thresholds/bands + colors), `src/app.rs` color-map editor, `src/colormap.rs`, `src/render.rs`, `src/script_exec.rs`, `src/scene_file.rs`. | Palette import/export and PCX/texture loading remain future clean-room work. |
|
| Color maps / palettes / texture image loading | VistaPro 3 manual includes loading PCX images, adding texture, and saving/loading color maps. | Implemented | `src/scene.rs` (`Palette` thresholds/bands + colors), `src/app.rs` color-map editor, `src/colormap.rs`, `src/render.rs`, `src/script_exec.rs`, `src/scene_file.rs`. | Palette import/export and PCX/texture loading remain future clean-room work. |
|
||||||
| Preview / final render workflow | VistaPro manuals describe rough preview rendering and full render output. | Implemented | `src/render.rs` (`render_top_down`, `render_perspective`), `src/cli.rs` (`render`), tests in `src/render.rs`. | The preview/final split is still simplified, but the core render outputs are working. |
|
| Preview / final render workflow | VistaPro manuals describe rough preview rendering and full render output. | Implemented | `src/render.rs` (`render_top_down`, `render_perspective`), `src/cli.rs` (`render`), tests in `src/render.rs`. | The preview/final split is still simplified, but the core render outputs are working. |
|
||||||
| Render quality presets / smoothing / detail tradeoffs | VistaPro manuals describe quality menus and poly/detail tradeoffs. | Planned | No dedicated quality preset system in current code. | Add explicit quality presets or a render-quality profile object. |
|
| Render quality presets / smoothing / detail tradeoffs | VistaPro manuals describe quality menus and poly/detail tradeoffs. | Implemented | `src/render.rs` (`RenderQualityPreset`, quality-aware top-down/perspective render helpers), `src/cli.rs` (`--quality`, output-path resolution), `src/app_state.rs`, `src/app.rs`, tests in `src/render.rs`, `src/app_state.rs`, and `src/cli.rs`. | The project-owned quality profile slice now toggles preview/balanced/final tradeoffs for both the CLI spike and the egui shell. |
|
||||||
| Scene file save/load (`.ovp.toml`) | Not a VistaPro legacy format; this is the clean-room OpenVistaPro scene format. | Implemented | `src/scene_file.rs`, `src/cli.rs` (`scene export`), tests in `src/scene_file.rs`. | No gap for the project-owned scene format slice. |
|
| Scene file save/load (`.ovp.toml`) | Not a VistaPro legacy format; this is the clean-room OpenVistaPro scene format. | Implemented | `src/scene_file.rs`, `src/cli.rs` (`scene export`), tests in `src/scene_file.rs`. | No gap for the project-owned scene format slice. |
|
||||||
| Script language parser | MakePath guide and VistaPro manual describe scripts and “Run Script” workflows. | Implemented | `src/script.rs`, `src/script_exec.rs`, `src/cli.rs` (`script run`), `src/app_state.rs` script preview, `README.md` script section, tests in `src/script.rs` and `src/script_exec.rs`. | The project-owned grammar is now parsed and executed; any future work should focus on richer syntax or animation export, not basic parser support. |
|
| Script language parser | MakePath guide and VistaPro manual describe scripts and “Run Script” workflows. | Implemented | `src/script.rs`, `src/script_exec.rs`, `src/cli.rs` (`script run`), `src/app_state.rs` script preview, `README.md` script section, tests in `src/script.rs` and `src/script_exec.rs`. | The project-owned grammar is now parsed and executed; any future work should focus on richer syntax or animation export, not basic parser support. |
|
||||||
| Script execution and animation frames | MakePath guide says scripts should render full animations and VistaPro can run scripts from the Script menu. | Implemented | `src/script_exec.rs` (`run_script` / `run_script_source`), `src/cli.rs` (`script run`), `src/app.rs` script controls, `src/app_state.rs`, tests in `src/script_exec.rs`. | The executor now runs preset/import/render slices; animation-frame sequencing is still a future extension. |
|
| Script execution and animation frames | MakePath guide says scripts should render full animations and VistaPro can run scripts from the Script menu. | Implemented | `src/script_exec.rs` (`run_script` / `run_script_source`), `src/cli.rs` (`script run`), `src/app.rs` script controls, `src/app_state.rs`, tests in `src/script_exec.rs`. | The executor now runs preset/import/render slices; animation-frame sequencing is still a future extension. |
|
||||||
@@ -39,4 +39,4 @@ Notes:
|
|||||||
|
|
||||||
## Current reconciliation summary
|
## Current reconciliation summary
|
||||||
|
|
||||||
OpenVistaPro already covers the core clean-room pipeline: terrain grids, open importers, scene state, preview/final rendering, project-owned scene files, script execution, MakePath-style path generation, editable color-map thresholds/bands, and scene-level vertical exaggeration. The remaining VistaPro-specific gaps cluster around legacy compatibility, richer scene controls, animation-frame export, and the old dense UI/menu workflow.
|
OpenVistaPro already covers the core clean-room pipeline: terrain grids, open importers, scene state, preview/final rendering, quality-profile tradeoffs, project-owned scene files, script execution, MakePath-style path generation, editable color-map thresholds/bands, and scene-level vertical exaggeration. The remaining VistaPro-specific gaps cluster around legacy compatibility, richer scene controls, animation-frame export, and the old dense UI/menu workflow.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ This is a normalized modern shell map derived from the VistaPro manuals, screens
|
|||||||
| Viewport / preview | Main render window, map preview, perspective view, preview/final render output | Center dock | Partial | `src/app.rs` renders the CPU preview into `CentralPanel`; perspective and top-down preview modes exist, but there is no GPU viewport or direct manipulation overlay yet. |
|
| Viewport / preview | Main render window, map preview, perspective view, preview/final render output | Center dock | Partial | `src/app.rs` renders the CPU preview into `CentralPanel`; perspective and top-down preview modes exist, but there is no GPU viewport or direct manipulation overlay yet. |
|
||||||
| Terrain / import | Load Landscape, Import, terrain source selection, generated terrain presets | Left dock or collapsible section | Partial | The current shell exposes project-owned terrain presets (`Plane`, `RadialHill`) and a working heightmap import action; legacy format import UI is still absent. |
|
| Terrain / import | Load Landscape, Import, terrain source selection, generated terrain presets | Left dock or collapsible section | Partial | The current shell exposes project-owned terrain presets (`Plane`, `RadialHill`) and a working heightmap import action; legacy format import UI is still absent. |
|
||||||
| Scene / camera | Camera and target gadgets, lens/range, bank/heading/pitch, water/tree/snow/haze controls | Left dock or inspector stack | Partial | Position/target, explicit heading/pitch/bank controls, lens/FOV/clip range controls, vertical exaggeration, color-map editing, and hydrology overlays now live in `src/app.rs` and `src/app_state.rs`; `src/scene.rs`, `src/render.rs`, and `src/script_exec.rs` carry the model/render semantics. The shell covers the main VistaPro scene controls, but its camera semantics are intentionally simplified and not yet tied to any map-click placement workflow. |
|
| Scene / camera | Camera and target gadgets, lens/range, bank/heading/pitch, water/tree/snow/haze controls | Left dock or inspector stack | Partial | Position/target, explicit heading/pitch/bank controls, lens/FOV/clip range controls, vertical exaggeration, color-map editing, and hydrology overlays now live in `src/app.rs` and `src/app_state.rs`; `src/scene.rs`, `src/render.rs`, and `src/script_exec.rs` carry the model/render semantics. The shell covers the main VistaPro scene controls, but its camera semantics are intentionally simplified and not yet tied to any map-click placement workflow. |
|
||||||
| Render | Preview vs final render, quality/smoothing, detail tradeoffs | Left dock, toolbar, or render tab | Partial | Current code toggles top-down vs perspective render mode, but there is no dedicated quality profile or render preset UI. |
|
| Render | Preview vs final render, quality/smoothing, detail tradeoffs | Left dock, toolbar, or render tab | Partial | Current code now exposes preview/balanced/final quality presets alongside top-down vs perspective render mode; the shell still lacks the full legacy menu chrome and fine-grained smoothing sliders. |
|
||||||
| Scripts / paths | Script menu, Run Script, MakePath path tools, animation-frame workflows | Right dock or modal workflow | Partial | Script parsing/execution and MakePath-style path generation now run end-to-end in the backend; the shell surfaces a script editor, Run Script, and Make Path controls, but animation-frame export and richer path editing are still future work. |
|
| Scripts / paths | Script menu, Run Script, MakePath path tools, animation-frame workflows | Right dock or modal workflow | Partial | Script parsing/execution and MakePath-style path generation now run end-to-end in the backend; the shell surfaces a script editor, Run Script, and Make Path controls, but animation-frame export and richer path editing are still future work. |
|
||||||
| File / project actions | New/Open/Save landscape, scene load/save, export commands | Top bar / file menu | Partial | The shell now shows scene-file status and working New/Open/Save controls; legacy menu chrome and export dialogs are still missing. |
|
| File / project actions | New/Open/Save landscape, scene load/save, export commands | Top bar / file menu | Partial | The shell now shows scene-file status and working New/Open/Save controls; legacy menu chrome and export dialogs are still missing. |
|
||||||
| Status / feedback | Coordinate readouts, render state, file path, progress, messages | Bottom status bar | Present | The shell now has a bottom status bar driven by `AppData::ui_snapshot()`. |
|
| Status / feedback | Coordinate readouts, render state, file path, progress, messages | Bottom status bar | Present | The shell now has a bottom status bar driven by `AppData::ui_snapshot()`. |
|
||||||
|
|||||||
@@ -508,6 +508,21 @@ mod tests {
|
|||||||
assert_eq!(preview.height(), 64);
|
assert_eq!(preview.height(), 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_quality_changes_preview_output() {
|
||||||
|
let mut app = AppData::default();
|
||||||
|
app.apply(AppAction::SetPreviewSize {
|
||||||
|
width: 33,
|
||||||
|
height: 33,
|
||||||
|
});
|
||||||
|
|
||||||
|
let preview = app.render_preview().unwrap();
|
||||||
|
app.apply(AppAction::SetRenderQuality(RenderQuality::Final));
|
||||||
|
let final_img = app.render_preview().unwrap();
|
||||||
|
|
||||||
|
assert_ne!(preview.as_raw(), final_img.as_raw());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ui_snapshot_exposes_existing_controls_and_new_entry_points() {
|
fn ui_snapshot_exposes_existing_controls_and_new_entry_points() {
|
||||||
let app = AppData::default();
|
let app = AppData::default();
|
||||||
@@ -524,6 +539,7 @@ mod tests {
|
|||||||
assert!(shell.import_path.is_some());
|
assert!(shell.import_path.is_some());
|
||||||
assert!(shell.path_target.is_none());
|
assert!(shell.path_target.is_none());
|
||||||
assert!(shell.status_line.contains("CPU preview"));
|
assert!(shell.status_line.contains("CPU preview"));
|
||||||
|
assert!(shell.status_line.contains("Preview"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
+33
-104
@@ -8,6 +8,8 @@ use crate::render::{
|
|||||||
render_top_down_with_quality,
|
render_top_down_with_quality,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::scene::Scene;
|
||||||
|
|
||||||
use crate::scene_file::{self, SceneFileError};
|
use crate::scene_file::{self, SceneFileError};
|
||||||
use crate::script_exec::{self, ScriptError};
|
use crate::script_exec::{self, ScriptError};
|
||||||
use crate::terrain::{HeightGrid, TerrainError};
|
use crate::terrain::{HeightGrid, TerrainError};
|
||||||
@@ -169,6 +171,22 @@ pub fn supported_quality_presets() -> &'static [&'static str] {
|
|||||||
&["preview", "balanced", "final"]
|
&["preview", "balanced", "final"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_render_output_path(
|
||||||
|
output: &std::path::Path,
|
||||||
|
preset: Preset,
|
||||||
|
quality: RenderQualityPreset,
|
||||||
|
) -> PathBuf {
|
||||||
|
if output.is_dir() {
|
||||||
|
output.join(format!(
|
||||||
|
"openvistapro-{}-{}.png",
|
||||||
|
preset.slug(),
|
||||||
|
quality.output_tag()
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
output.to_path_buf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn supported_importers() -> &'static [&'static str] {
|
pub fn supported_importers() -> &'static [&'static str] {
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "hgt",
|
feature = "hgt",
|
||||||
@@ -242,24 +260,13 @@ pub fn info_text() -> String {
|
|||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
writeln!(&mut text, "openvistapro {}", env!("CARGO_PKG_VERSION")).unwrap();
|
writeln!(&mut text, "openvistapro {}", env!("CARGO_PKG_VERSION")).unwrap();
|
||||||
writeln!(&mut text, "presets: {}", supported_presets().join(", ")).unwrap();
|
writeln!(&mut text, "presets: {}", supported_presets().join(", ")).unwrap();
|
||||||
writeln!(
|
|
||||||
&mut text,
|
|
||||||
"quality presets: {}",
|
|
||||||
supported_quality_presets().join(", ")
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let importers = supported_importers();
|
let importers = supported_importers();
|
||||||
if importers.is_empty() {
|
if importers.is_empty() {
|
||||||
writeln!(&mut text, "importers: (none)").unwrap();
|
writeln!(&mut text, "importers: (none)").unwrap();
|
||||||
} else {
|
} else {
|
||||||
writeln!(&mut text, "importers: {}", importers.join(", ")).unwrap();
|
writeln!(&mut text, "importers: {}", importers.join(", ")).unwrap();
|
||||||
}
|
}
|
||||||
writeln!(
|
writeln!(&mut text, "scene files: .ovp.toml").unwrap();
|
||||||
&mut text,
|
|
||||||
"scene file: project-owned .ovp.toml (schema {})",
|
|
||||||
scene_file::SCENE_SCHEMA
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
text
|
text
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,6 +281,7 @@ pub fn execute(cli: Cli) -> Result<(), CliError> {
|
|||||||
Preset::Plane => HeightGrid::plane(args.width, args.height)?,
|
Preset::Plane => HeightGrid::plane(args.width, args.height)?,
|
||||||
Preset::Hill => HeightGrid::radial_hill(args.width, args.height, HILL_PEAK_HEIGHT)?,
|
Preset::Hill => HeightGrid::radial_hill(args.width, args.height, HILL_PEAK_HEIGHT)?,
|
||||||
};
|
};
|
||||||
|
let output = resolve_render_output_path(&args.output, args.preset, args.quality);
|
||||||
let mut scene = if let Some(path) = args.scene.as_deref() {
|
let mut scene = if let Some(path) = args.scene.as_deref() {
|
||||||
scene_file::load_from_path(path)?
|
scene_file::load_from_path(path)?
|
||||||
} else {
|
} else {
|
||||||
@@ -281,24 +289,23 @@ pub fn execute(cli: Cli) -> Result<(), CliError> {
|
|||||||
};
|
};
|
||||||
if args.camera_demo {
|
if args.camera_demo {
|
||||||
scene.camera = demo_camera_for(&grid);
|
scene.camera = demo_camera_for(&grid);
|
||||||
render_perspective_to_path(&grid, &scene, args.width, args.height, &args.output)?;
|
let image = render_perspective_with_quality(
|
||||||
} else if args.quality == RenderQualityPreset::Preview {
|
|
||||||
render_top_down_to_path(&grid, &scene, &args.output)?;
|
|
||||||
} else {
|
|
||||||
let img = render_perspective_with_quality(
|
|
||||||
&grid,
|
&grid,
|
||||||
&scene,
|
&scene,
|
||||||
args.width,
|
args.width,
|
||||||
args.height,
|
args.height,
|
||||||
args.quality,
|
args.quality,
|
||||||
);
|
);
|
||||||
img.save(&args.output)?;
|
image.save(&output)?;
|
||||||
|
} else {
|
||||||
|
let image = render_top_down_with_quality(&grid, &scene, args.quality);
|
||||||
|
image.save(&output)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Command::Scene(args) => match args.action {
|
Command::Scene(args) => match args.action {
|
||||||
SceneAction::Export(export) => {
|
SceneAction::Export(export) => {
|
||||||
scene_file::save_to_path(&Scene::default(), &export.output)?;
|
scene_file::save_to_path(&crate::scene::Scene::default(), &export.output)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -317,6 +324,7 @@ pub fn execute(cli: Cli) -> Result<(), CliError> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::scene::Scene;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parses_info_command() {
|
fn parses_info_command() {
|
||||||
@@ -469,55 +477,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn info_text_lists_quality_presets() {
|
|
||||||
let text = info_text();
|
|
||||||
assert!(text.contains("preview"));
|
|
||||||
assert!(text.contains("balanced"));
|
|
||||||
assert!(text.contains("final"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn supported_quality_presets_lists_preview_balanced_and_final() {
|
|
||||||
let qualities = supported_quality_presets();
|
|
||||||
assert!(qualities.contains(&"preview"));
|
|
||||||
assert!(qualities.contains(&"balanced"));
|
|
||||||
assert!(qualities.contains(&"final"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn resolve_render_output_path_uses_quality_suffix_for_directories() {
|
|
||||||
let dir = temp_output_dir("quality-path");
|
|
||||||
let preview = resolve_render_output_path(&dir, Preset::Hill, RenderQualityPreset::Preview);
|
|
||||||
let final_path = resolve_render_output_path(&dir, Preset::Hill, RenderQualityPreset::Final);
|
|
||||||
|
|
||||||
assert_ne!(preview, final_path);
|
|
||||||
assert_eq!(preview.file_name().and_then(|s| s.to_str()), Some("openvistapro-hill-preview.png"));
|
|
||||||
assert_eq!(final_path.file_name().and_then(|s| s.to_str()), Some("openvistapro-hill-final.png"));
|
|
||||||
std::fs::remove_dir_all(&dir).ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parses_render_with_quality_preset() {
|
|
||||||
let cli = Cli::try_parse_from([
|
|
||||||
"openvistapro",
|
|
||||||
"render",
|
|
||||||
"--preset",
|
|
||||||
"hill",
|
|
||||||
"--quality",
|
|
||||||
"final",
|
|
||||||
"--output",
|
|
||||||
"/tmp/out.png",
|
|
||||||
])
|
|
||||||
.unwrap();
|
|
||||||
match cli.command {
|
|
||||||
Command::Render(args) => {
|
|
||||||
assert_eq!(args.quality, RenderQualityPreset::Final);
|
|
||||||
}
|
|
||||||
_ => panic!("expected render"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn temp_output_path(tag: &str) -> PathBuf {
|
fn temp_output_path(tag: &str) -> PathBuf {
|
||||||
let mut path = std::env::temp_dir();
|
let mut path = std::env::temp_dir();
|
||||||
path.push(format!(
|
path.push(format!(
|
||||||
@@ -529,18 +488,6 @@ mod tests {
|
|||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
fn temp_output_dir(tag: &str) -> PathBuf {
|
|
||||||
let mut dir = std::env::temp_dir();
|
|
||||||
dir.push(format!(
|
|
||||||
"openvistapro-cli-{}-{}-dir",
|
|
||||||
tag,
|
|
||||||
std::process::id()
|
|
||||||
));
|
|
||||||
let _ = std::fs::remove_dir_all(&dir);
|
|
||||||
std::fs::create_dir_all(&dir).unwrap();
|
|
||||||
dir
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn execute_render_plane_writes_png_with_requested_dimensions() {
|
fn execute_render_plane_writes_png_with_requested_dimensions() {
|
||||||
let path = temp_output_path("plane");
|
let path = temp_output_path("plane");
|
||||||
@@ -588,30 +535,6 @@ mod tests {
|
|||||||
std::fs::remove_file(&path).ok();
|
std::fs::remove_file(&path).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn execute_render_uses_quality_specific_filename_for_output_directories() {
|
|
||||||
let dir = temp_output_dir("quality-exec");
|
|
||||||
let cli = Cli::try_parse_from([
|
|
||||||
"openvistapro",
|
|
||||||
"render",
|
|
||||||
"--preset",
|
|
||||||
"hill",
|
|
||||||
"--quality",
|
|
||||||
"final",
|
|
||||||
"--width",
|
|
||||||
"8",
|
|
||||||
"--height",
|
|
||||||
"8",
|
|
||||||
"--output",
|
|
||||||
dir.to_str().unwrap(),
|
|
||||||
])
|
|
||||||
.unwrap();
|
|
||||||
execute(cli).expect("execute should succeed");
|
|
||||||
let derived = dir.join("openvistapro-hill-final.png");
|
|
||||||
assert!(derived.exists(), "expected derived output path {derived:?}");
|
|
||||||
std::fs::remove_dir_all(&dir).ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parses_render_with_camera_demo_flag() {
|
fn parses_render_with_camera_demo_flag() {
|
||||||
let cli = Cli::try_parse_from([
|
let cli = Cli::try_parse_from([
|
||||||
@@ -831,6 +754,12 @@ mod tests {
|
|||||||
water_level: 1000.0,
|
water_level: 1000.0,
|
||||||
tree_line: 1001.0,
|
tree_line: 1001.0,
|
||||||
snow_line: 1002.0,
|
snow_line: 1002.0,
|
||||||
|
hydrology: crate::scene::Hydrology {
|
||||||
|
lake_radius: 0.0,
|
||||||
|
river_width: 0.0,
|
||||||
|
river_bend: 0.0,
|
||||||
|
..crate::scene::Hydrology::default()
|
||||||
|
},
|
||||||
..Scene::default()
|
..Scene::default()
|
||||||
};
|
};
|
||||||
crate::scene_file::save_to_path(&custom, &scene_path).expect("save scene");
|
crate::scene_file::save_to_path(&custom, &scene_path).expect("save scene");
|
||||||
|
|||||||
@@ -526,6 +526,30 @@ mod tests {
|
|||||||
assert_eq!(a.as_raw(), b.as_raw());
|
assert_eq!(a.as_raw(), b.as_raw());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_quality_presets_change_sampling_and_blur() {
|
||||||
|
let preview = RenderQualityPreset::Preview.profile();
|
||||||
|
let balanced = RenderQualityPreset::Balanced.profile();
|
||||||
|
let final_profile = RenderQualityPreset::Final.profile();
|
||||||
|
|
||||||
|
assert_eq!(preview.label, "Preview");
|
||||||
|
assert_eq!(preview.top_down_blur_passes, 0);
|
||||||
|
assert!(preview.perspective_step > balanced.perspective_step);
|
||||||
|
assert!(balanced.perspective_step > final_profile.perspective_step);
|
||||||
|
assert!(balanced.top_down_blur_passes > preview.top_down_blur_passes);
|
||||||
|
assert!(final_profile.top_down_blur_passes > balanced.top_down_blur_passes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_top_down_quality_changes_output_for_detail_presets() {
|
||||||
|
let grid = HeightGrid::radial_hill(33, 33, 10.0).unwrap();
|
||||||
|
let scene = fixture_scene();
|
||||||
|
let preview = render_top_down_with_quality(&grid, &scene, RenderQualityPreset::Preview);
|
||||||
|
let final_img = render_top_down_with_quality(&grid, &scene, RenderQualityPreset::Final);
|
||||||
|
|
||||||
|
assert_ne!(preview.as_raw(), final_img.as_raw());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn render_to_path_writes_png_file() {
|
fn render_to_path_writes_png_file() {
|
||||||
let grid = HeightGrid::radial_hill(8, 8, 10.0).unwrap();
|
let grid = HeightGrid::radial_hill(8, 8, 10.0).unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user