feat/vtk-3d-view #7
Binary file not shown.
|
After Width: | Height: | Size: 253 KiB |
|
|
@ -2292,6 +2292,90 @@ int cmdFpsBudget(int argc, char** argv) {
|
|||
return textureErr ? 1 : 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 视觉调参画廊(Task 12d gallery):view --preview --variant N
|
||||
// ============================================================================
|
||||
//
|
||||
// 同一局部段(沿线中段 kViewDefaultLocalBricks 列全分辨率) + 同一相机框法
|
||||
// (ResetCamera→Elevation/Azimuth→Zoom),只换「不透明度包络 / 配色 / 取景角度 /
|
||||
// 背景」四组视觉参数,各存一张 PNG 供控制方挑选。fps 对视觉调参近乎中性,每组实测验证。
|
||||
//
|
||||
// 注:交互窗口(无 flag 的 view)默认即采用 var4(kViewDefaultVariant)——配色/不透明度
|
||||
// 包络/取景/exagg/背景全部走同一份 var4 参数,故「交互默认画面 == view-var4」。
|
||||
enum class OpacityProfile {
|
||||
kSolid, // V 形实体感:中高值段普遍可见,半透明实心块
|
||||
kStructural, // 现有双端斜坡:仅正负两端不透明(对照基线)
|
||||
};
|
||||
enum class ColorChoice { kStructural, kSeismic, kJet };
|
||||
|
||||
struct GalleryVariant {
|
||||
const char* name; // 文件名后缀:view-<name>.png
|
||||
OpacityProfile profile;
|
||||
ColorChoice color;
|
||||
double floorOpacity; // 近零背景不透明度(kSolid 用)
|
||||
double midOpacity; // 中值段不透明度(kSolid 用)
|
||||
double maxOpacity; // 两端峰值不透明度
|
||||
double exagg; // 垂向夸张
|
||||
double elevation; // ResetCamera 后 Elevation
|
||||
double azimuth; // 再 Azimuth
|
||||
double zoom; // 再 Zoom 填满画面
|
||||
double bg[3]; // 背景 RGB
|
||||
const char* desc; // 报告用中文说明
|
||||
};
|
||||
|
||||
// 4 组视觉参数。值经离屏实跑挑出(详见报告)。
|
||||
const GalleryVariant kGalleryVariants[] = {
|
||||
// var1:高不透明度实体感——seismic 亮配色 + V 形包络(中段 0.40/两端 0.85),
|
||||
// floor 压到 0.04:近零层间隙近透明,亮层面浮出 → 内部层状结构可读。
|
||||
{"var1", OpacityProfile::kSolid, ColorChoice::kSeismic,
|
||||
0.04, 0.40, 0.85, 8.0, 22.0, 28.0, 1.9, {0.05, 0.05, 0.09},
|
||||
"高不透明度实体感:V形包络(floor0.04/mid0.40/max0.85)+seismic 亮配色,"
|
||||
"半透明实心、内部层次可见"},
|
||||
// var2:高对比配色——jet 全程高饱和 + 中等不透明度 V 形包络。
|
||||
{"var2", OpacityProfile::kSolid, ColorChoice::kJet,
|
||||
0.04, 0.32, 0.70, 8.0, 22.0, 28.0, 1.9, {0.06, 0.06, 0.10},
|
||||
"高对比配色:jet 蓝青绿黄红全程高饱和 + 中等 V 形包络(mid0.32/max0.70)"},
|
||||
// var3:居中正对纵截面——低 Elevation/Azimuth 摆平、正对 X-Z 长侧面(层状反射沿
|
||||
// X 延展最清晰)、Zoom2.0 填满 ~70%;floor 压更低让层间隙透明、层面立体。
|
||||
{"var3", OpacityProfile::kSolid, ColorChoice::kSeismic,
|
||||
0.03, 0.38, 0.82, 9.0, 10.0, 12.0, 2.0, {0.05, 0.05, 0.09},
|
||||
"居中正对纵截面:低 El10/Az12 摆平正对 X-Z 长侧面、Zoom2.0 填满视野,"
|
||||
"floor0.03 凸显层面,exagg9 放大薄轴"},
|
||||
// var4:最像真实 GPR 三维图——seismic + 略提背景亮 + 微立体角 + 实体包络。
|
||||
// 综合最佳,选作交互窗口默认(kViewDefaultVariant)。
|
||||
{"var4", OpacityProfile::kSolid, ColorChoice::kSeismic,
|
||||
0.035, 0.38, 0.84, 8.0, 18.0, 22.0, 2.0, {0.07, 0.08, 0.11},
|
||||
"综合最佳:seismic + 实体包络(floor0.035/mid0.38/max0.84) + 微立体取景"
|
||||
"(El18/Az22/Zoom2.0) + 略亮冷灰背景"},
|
||||
};
|
||||
|
||||
// 交互窗口(无 flag 的 view)的默认视觉变体 = var4(kGalleryVariants 末项)。
|
||||
// 交互默认与 view-var4 走同一份参数 → 二者画面一致(DRY,不复制粘贴漂移)。
|
||||
const GalleryVariant& kViewDefaultVariant =
|
||||
kGalleryVariants[sizeof(kGalleryVariants) / sizeof(kGalleryVariants[0]) - 1];
|
||||
|
||||
geopro::core::ColorScale pickColor(ColorChoice c, double vmin, double vmax) {
|
||||
switch (c) {
|
||||
case ColorChoice::kSeismic: return makeSeismicColorScale(vmin, vmax);
|
||||
case ColorChoice::kJet: return makeJetColorScale(vmin, vmax);
|
||||
case ColorChoice::kStructural:
|
||||
default: return makeStructuralColorScale(vmin, vmax);
|
||||
}
|
||||
}
|
||||
|
||||
// 按变体的不透明度包络建体属性(gallery / 交互默认共用,DRY)。kSolid 走 V 形实体
|
||||
// 包络(floor/mid/max),kStructural 走双端斜坡(仅 maxOpacity)。
|
||||
vtkSmartPointer<vtkVolumeProperty> makeVariantProperty(
|
||||
const GalleryVariant& v, const geopro::core::Quant& q,
|
||||
const geopro::core::ColorScale& cs, double vmin, double vmax,
|
||||
double maxOpacity) {
|
||||
if (v.profile == OpacityProfile::kSolid) {
|
||||
return makeSolidVolumeProperty(q, cs, vmin, vmax, v.floorOpacity,
|
||||
v.midOpacity, maxOpacity);
|
||||
}
|
||||
return makeTunedVolumeProperty(q, cs, vmin, vmax, maxOpacity);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ③ view:真窗口可交互(给用户肉眼测 + 最低配机跑)(Task 12d)
|
||||
// ============================================================================
|
||||
|
|
@ -2422,12 +2506,11 @@ void viewOnInteract(vtkObject*, unsigned long, void* clientData, void*) {
|
|||
// 越填不满画面;256 道是 ① cmdTune 出 lod-tuned-local.png(有清晰层状结构)的取景,
|
||||
// 沿用之以保证首帧同等可读。
|
||||
constexpr int kViewDefaultLocalBricks = 4;
|
||||
// ResetCamera 后再 Zoom 拉近填满画面(同 ① cmdTune 的 1.7×:默认框得偏松,留白多)。
|
||||
constexpr double kViewDefaultZoom = 1.7;
|
||||
|
||||
// 建立 view 的「默认取景」:把 level0 一段局部体(沿线中段)整卷单块喂 mapper,再
|
||||
// ResetCamera 到该局部段(actor 已 SetScale(1,exagg,exagg)),置相机为能看出层状
|
||||
// 结构的角度。真窗口 / --smoke / --preview 三条路径共用此函数 → 渲的是同一画面。
|
||||
// 取景角度(Elevation/Azimuth/Zoom)取自 kViewDefaultVariant(var4),与 view-var4 一致。
|
||||
//
|
||||
// 返回喂给 mapper 的块数(=1)。同步更新 st->lastLevel=0(默认即全分辨率局部段)。
|
||||
std::size_t viewSetupDefaultFrame(ViewState* st, vtkRenderer* ren) {
|
||||
|
|
@ -2452,75 +2535,13 @@ std::size_t viewSetupDefaultFrame(ViewState* st, vtkRenderer* ren) {
|
|||
// 相机角度沿用能看出结构的 Elevation/Azimuth,再 Zoom 拉近填满画面。
|
||||
ren->ResetCamera();
|
||||
st->cam = ren->GetActiveCamera();
|
||||
st->cam->Elevation(28.0); // 同 ① cmdTune 的取景角度
|
||||
st->cam->Azimuth(30.0);
|
||||
st->cam->Zoom(kViewDefaultZoom); // 拉近填满画面,避免局部段缩在角落
|
||||
st->cam->Elevation(kViewDefaultVariant.elevation); // var4 取景:El18
|
||||
st->cam->Azimuth(kViewDefaultVariant.azimuth); // var4 取景:Az22
|
||||
st->cam->Zoom(kViewDefaultVariant.zoom); // var4 取景:Zoom2.0 填满画面
|
||||
ren->ResetCameraClippingRange();
|
||||
return one.size();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 视觉调参画廊(Task 12d gallery):view --preview --variant N
|
||||
// ============================================================================
|
||||
//
|
||||
// 同一局部段(沿线中段 kViewDefaultLocalBricks 列全分辨率) + 同一相机框法
|
||||
// (ResetCamera→Elevation/Azimuth→Zoom),只换「不透明度包络 / 配色 / 取景角度 /
|
||||
// 背景」四组视觉参数,各存一张 PNG 供控制方挑选。fps 对视觉调参近乎中性,每组实测验证。
|
||||
enum class OpacityProfile {
|
||||
kSolid, // V 形实体感:中高值段普遍可见,半透明实心块
|
||||
kStructural, // 现有双端斜坡:仅正负两端不透明(对照基线)
|
||||
};
|
||||
enum class ColorChoice { kStructural, kSeismic, kJet };
|
||||
|
||||
struct GalleryVariant {
|
||||
const char* name; // 文件名后缀:view-<name>.png
|
||||
OpacityProfile profile;
|
||||
ColorChoice color;
|
||||
double floorOpacity; // 近零背景不透明度(kSolid 用)
|
||||
double midOpacity; // 中值段不透明度(kSolid 用)
|
||||
double maxOpacity; // 两端峰值不透明度
|
||||
double exagg; // 垂向夸张
|
||||
double elevation; // ResetCamera 后 Elevation
|
||||
double azimuth; // 再 Azimuth
|
||||
double zoom; // 再 Zoom 填满画面
|
||||
double bg[3]; // 背景 RGB
|
||||
const char* desc; // 报告用中文说明
|
||||
};
|
||||
|
||||
// 4 组视觉参数。值经离屏实跑挑出(详见报告)。
|
||||
const GalleryVariant kGalleryVariants[] = {
|
||||
// var1:高不透明度实体感——seismic 亮配色 + V 形包络(中段 0.40/两端 0.85),
|
||||
// floor 压到 0.04:近零层间隙近透明,亮层面浮出 → 内部层状结构可读。
|
||||
{"var1", OpacityProfile::kSolid, ColorChoice::kSeismic,
|
||||
0.04, 0.40, 0.85, 8.0, 22.0, 28.0, 1.9, {0.05, 0.05, 0.09},
|
||||
"高不透明度实体感:V形包络(floor0.04/mid0.40/max0.85)+seismic 亮配色,"
|
||||
"半透明实心、内部层次可见"},
|
||||
// var2:高对比配色——jet 全程高饱和 + 中等不透明度 V 形包络。
|
||||
{"var2", OpacityProfile::kSolid, ColorChoice::kJet,
|
||||
0.04, 0.32, 0.70, 8.0, 22.0, 28.0, 1.9, {0.06, 0.06, 0.10},
|
||||
"高对比配色:jet 蓝青绿黄红全程高饱和 + 中等 V 形包络(mid0.32/max0.70)"},
|
||||
// var3:居中正对纵截面——低 Elevation/Azimuth 摆平、正对 X-Z 长侧面(层状反射沿
|
||||
// X 延展最清晰)、Zoom2.0 填满 ~70%;floor 压更低让层间隙透明、层面立体。
|
||||
{"var3", OpacityProfile::kSolid, ColorChoice::kSeismic,
|
||||
0.03, 0.38, 0.82, 9.0, 10.0, 12.0, 2.0, {0.05, 0.05, 0.09},
|
||||
"居中正对纵截面:低 El10/Az12 摆平正对 X-Z 长侧面、Zoom2.0 填满视野,"
|
||||
"floor0.03 凸显层面,exagg9 放大薄轴"},
|
||||
// var4:最像真实 GPR 三维图——seismic + 略提背景亮 + 微立体角 + 实体包络。
|
||||
{"var4", OpacityProfile::kSolid, ColorChoice::kSeismic,
|
||||
0.035, 0.38, 0.84, 8.0, 18.0, 22.0, 2.0, {0.07, 0.08, 0.11},
|
||||
"综合最佳:seismic + 实体包络(floor0.035/mid0.38/max0.84) + 微立体取景"
|
||||
"(El18/Az22/Zoom2.0) + 略亮冷灰背景"},
|
||||
};
|
||||
|
||||
geopro::core::ColorScale pickColor(ColorChoice c, double vmin, double vmax) {
|
||||
switch (c) {
|
||||
case ColorChoice::kSeismic: return makeSeismicColorScale(vmin, vmax);
|
||||
case ColorChoice::kJet: return makeJetColorScale(vmin, vmax);
|
||||
case ColorChoice::kStructural:
|
||||
default: return makeStructuralColorScale(vmin, vmax);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲一组画廊变体并存 PNG,报告 结构像素 / 平均亮度 / fps。返回 0=OK。
|
||||
int runGalleryVariant(const std::string& dir, const GalleryVariant& v,
|
||||
int frames) {
|
||||
|
|
@ -2530,13 +2551,8 @@ int runGalleryVariant(const std::string& dir, const GalleryVariant& v,
|
|||
const double vmin = m.vminPhys, vmax = m.vmaxPhys;
|
||||
const geopro::core::ColorScale cs = pickColor(v.color, vmin, vmax);
|
||||
|
||||
vtkSmartPointer<vtkVolumeProperty> prop;
|
||||
if (v.profile == OpacityProfile::kSolid) {
|
||||
prop = makeSolidVolumeProperty(m.quant, cs, vmin, vmax, v.floorOpacity,
|
||||
v.midOpacity, v.maxOpacity);
|
||||
} else {
|
||||
prop = makeTunedVolumeProperty(m.quant, cs, vmin, vmax, v.maxOpacity);
|
||||
}
|
||||
vtkSmartPointer<vtkVolumeProperty> prop =
|
||||
makeVariantProperty(v, m.quant, cs, vmin, vmax, v.maxOpacity);
|
||||
|
||||
auto rw = makeOffscreenWindow(winW, winH);
|
||||
vtkNew<vtkRenderer> ren;
|
||||
|
|
@ -2661,8 +2677,15 @@ int cmdView(int argc, char** argv) {
|
|||
return 2;
|
||||
}
|
||||
const std::string dir = a.positional[0];
|
||||
const double exagg = std::stod(a.get("exagg", "8"));
|
||||
const double opacity = std::stod(a.get("opacity", "0.5"));
|
||||
// 交互/preview/smoke 默认视觉参数 = kViewDefaultVariant(var4):配色/不透明度包络/
|
||||
// exagg/背景全部走 var4,故默认画面 == view-var4(DRY,与画廊同源)。命令行 --exagg /
|
||||
// --opacity 若用户显式传则覆盖 var4 对应值,否则用 var4 的 exagg / maxOpacity。
|
||||
const GalleryVariant& dv = kViewDefaultVariant;
|
||||
const double exagg =
|
||||
a.kv.count("exagg") ? std::stod(a.get("exagg", "8")) : dv.exagg;
|
||||
const double opacity = a.kv.count("opacity")
|
||||
? std::stod(a.get("opacity", "0.5"))
|
||||
: dv.maxOpacity;
|
||||
const std::size_t budget =
|
||||
static_cast<std::size_t>(std::stoul(a.get("budget", "64")));
|
||||
const int frames = std::stoi(a.get("frames", "90"));
|
||||
|
|
@ -2709,9 +2732,10 @@ int cmdView(int argc, char** argv) {
|
|||
const auto& m = src.meta();
|
||||
src.setAspect(static_cast<double>(winW) / winH);
|
||||
const double vmin = m.vminPhys, vmax = m.vmaxPhys;
|
||||
const geopro::core::ColorScale cs = makeStructuralColorScale(vmin, vmax);
|
||||
// 配色/不透明度包络取自 var4:seismic + V 形实体包络(floor/mid + opacity 作峰值)。
|
||||
const geopro::core::ColorScale cs = pickColor(dv.color, vmin, vmax);
|
||||
vtkSmartPointer<vtkVolumeProperty> prop =
|
||||
makeTunedVolumeProperty(m.quant, cs, vmin, vmax, opacity);
|
||||
makeVariantProperty(dv, m.quant, cs, vmin, vmax, opacity);
|
||||
|
||||
// 渲染窗口:preview/smoke 走离屏,否则真窗口。
|
||||
vtkSmartPointer<vtkRenderWindow> rw;
|
||||
|
|
@ -2724,7 +2748,7 @@ int cmdView(int argc, char** argv) {
|
|||
}
|
||||
|
||||
vtkNew<vtkRenderer> ren;
|
||||
ren->SetBackground(0.04, 0.04, 0.08);
|
||||
ren->SetBackground(dv.bg[0], dv.bg[1], dv.bg[2]); // var4 略亮冷灰背景
|
||||
rw->AddRenderer(ren);
|
||||
|
||||
vtkNew<vtkMultiBlockVolumeMapper> mapper;
|
||||
|
|
@ -2733,7 +2757,7 @@ int cmdView(int argc, char** argv) {
|
|||
auto volume = vtkSmartPointer<vtkVolume>::New();
|
||||
volume->SetMapper(mapper);
|
||||
volume->SetProperty(prop);
|
||||
volume->SetScale(1.0, exagg, exagg); // 垂向夸张(同 ①)
|
||||
volume->SetScale(1.0, exagg, exagg); // 垂向夸张(默认 var4 exagg)
|
||||
ren->AddVolume(volume);
|
||||
|
||||
// 屏幕左上角实时 fps 文本。
|
||||
|
|
|
|||
Loading…
Reference in New Issue