7#include <Poco/JSON/Array.h>
8#include <Poco/JSON/Object.h>
9#include <Poco/JSON/Parser.h>
10#include <Poco/JSON/Stringifier.h>
24std::string writeTextFile(
const std::string&
path,
const std::string&
text) {
25 const std::filesystem::path
p(
path);
27 std::filesystem::create_directories(
p.parent_path(), ec);
28 std::ofstream out(
p, std::ios::binary);
29 if (!out.good())
return "cannot open output file: " +
path;
30 out.write(
text.data(),
static_cast<std::streamsize
>(
text.size()));
32 return out.good() ? std::string() :
"failed writing: " +
path;
42eve::IRenderCapture* SceneInspect::captureIface() {
return eve::cap::query<eve::IRenderCapture>(); }
44eve::ISceneQuery* SceneInspect::scene() {
return eve::cap::query<eve::ISceneQuery>(); }
46bool SceneInspect::ensureCamera() {
47 auto* cap = captureIface();
48 return cap && cap->ensureCamera();
52 std::vector<InspectView> out;
53 const float base = fov > 0.f ? fov : 60.f;
57 v.
name =
"along_road";
59 v.eye =
center + glm::vec3(0.f, 1.8f, -6.f);
60 v.target =
center + glm::vec3(0.f, 1.2f, 0.f);
68 v.eye =
center + glm::vec3(0.f, 30.f, 0.f);
70 v.fovYDeg = std::min(base * 1.2f, 100.f);
75 v.
name =
"corner_close";
77 v.eye =
center + glm::vec3(2.4f, 1.2f, 2.4f);
78 v.target =
center + glm::vec3(0.f, 0.8f, 0.f);
79 v.fovYDeg = std::max(base * 0.8f, 25.f);
86 v.eye =
center + glm::vec3(0.f, 14.f, -22.f);
88 v.fovYDeg = std::max(base * 0.85f, 35.f);
96 auto* cap = captureIface();
97 if (!cap)
return false;
98 return cap->setCameraPoseYawPitch(
eye.x,
eye.y,
eye.z, rotYawPitch.x, rotYawPitch.y, fov);
102 auto* cap = captureIface();
103 if (!cap)
return false;
104 return cap->setCameraPose(
v.eye.x,
v.eye.y,
v.eye.z,
v.target.x,
v.target.y,
v.target.z,
v.fovYDeg);
108 std::string
root = std::filesystem::current_path().string();
110 if (
c ==
'\\')
c =
'/';
111 if (!
root.empty() &&
root.back() ==
'/')
root.pop_back();
112 return root +
"/eve_inspect_cache";
116 const std::vector<std::string>& buffers) {
118 auto* cap = captureIface();
120 result.
error =
"Graphics module not available";
124 bool wantColor = buffers.empty();
125 bool wantDepth =
false, wantNormal =
false, wantId =
false, wantShadow =
false;
126 for (
const auto&
b : buffers) {
127 if (
b ==
"color") wantColor =
true;
128 else if (
b ==
"depth") wantDepth =
true;
129 else if (
b ==
"normal") wantNormal =
true;
130 else if (
b ==
"id") wantId =
true;
131 else if (
b ==
"shadow") wantShadow =
true;
133 if (!wantColor) wantColor =
true;
136 cap->setReadbackEnabled(
true);
138 std::string
dir = outDir;
144 if (
c ==
'\\')
c =
'/';
146 const std::string safeTag =
tag.empty() ?
"frame" :
tag;
147 const std::string pngPath =
dir +
"/" + safeTag +
".png";
148 const std::string jsonPath =
dir +
"/" + safeTag +
".json";
149 const std::string depthPngPath =
dir +
"/" + safeTag +
"_depth.png";
150 const std::string normalPngPath =
dir +
"/" + safeTag +
"_normal.png";
151 const std::string idPngPath =
dir +
"/" + safeTag +
"_id.png";
152 const std::string idJsonPath =
dir +
"/" + safeTag +
"_id.json";
155 if (!cap->savePng(pngPath, &result.
width, &result.
height, &err)) {
161 if (
const std::string werr = writeTextFile(jsonPath, geoJson); !werr.empty()) {
166 const auto pos = geoJson.find(
"\"count\":");
167 if (
pos != std::string::npos) result.
entityCount = std::atoi(geoJson.c_str() +
pos + 9);
171 if (cap->gbufferPng(
"depth", depthPngPath, &berr))
178 if (cap->gbufferPng(
"normal", normalPngPath, &berr))
183 if (wantShadow) result.
unsupported.push_back(
"shadow");
188 const std::string idJson = cap->entityIdMaskJson(&iw, &ih, &
ok);
193 if (cap->entityIdMaskPng(idPngPath, &perr)) result.
idPngPath = idPngPath;
194 if (writeTextFile(idJsonPath, idJson).empty()) result.
idJsonPath = idJsonPath;
201 lastPngPath_ = pngPath;
202 lastJsonPath_ = jsonPath;
207 auto* cap = captureIface();
208 return cap ? cap->cameraPoseJson() :
"{\"error\":\"Graphics module not available\"}";
213 auto* cap = captureIface();
214 if (!cap)
return "{\"error\":\"Graphics module not available\"}";
218 return cap->visibleEntitiesJson(fov, &
ok);
Frame capture + camera + visible-entity inspection (graphics).
Scene graph query/mutation surface (provided by the scene module).
std::string currentPoseJson()
当前激活相机位姿 JSON(eye/target/fov/viewport)。
const std::string & cacheDir() const
std::string defaultCacheDir() const
默认缓存目录:<gameRoot>/eve_inspect_cache。
std::string visibleEntitiesJson(const glm::vec3 *eye=nullptr, const glm::vec3 *target=nullptr, float fov=0.f)
生成当前视锥内可见实体的结构化 JSON: { camera, viewport, entities:[ { id, asset, world_aabb:{min,...
InspectCapture capture(const std::string &outDir={}, const std::string &tag="frame", const std::vector< std::string > &buffers={})
锁定当前相机 → 捕获渲染帧 PNG → 立刻导出配套可见实体几何 JSON。 两者共享同一相机位姿,杜绝图片与实体数据错位。 outDir 为空时使用缓存目录。返回文件路径与图像尺寸。 buffers...
bool setCameraView(const InspectView &v)
static SceneInspect & instance()
bool setCameraPose(const glm::vec3 &eye, const glm::vec3 &rotYawPitch, float fov=0.f)
以 pos + 欧拉角 rot 设置相机位姿。 rot = [yawDeg, pitchDeg](与 firstperson 约定一致,Y-up)。 fov <= 0 时保持当前 FOV。
static std::vector< InspectView > generateViews(const glm::vec3 ¢er, float fov=60.f)
围绕 center 自动生成一组标准化巡检机位:
一次原子快照的结果:PNG 渲染帧 + 配套几何 JSON。
std::string normalPngPath
std::vector< std::string > unsupported