Support Drop file and reload scene.

This commit is contained in:
Syoyo Fujita
2021-08-01 03:22:55 +09:00
parent 05d378620b
commit a730b1b725
3 changed files with 203 additions and 136 deletions

View File

@@ -37,7 +37,7 @@
#include "nfd.h"
#endif
#define EMULATE_EMSCRIPTEN
//#define EMULATE_EMSCRIPTEN
#if defined(EMULATE_EMSCRIPTEN)
#define EM_BOOL int
@@ -58,6 +58,7 @@ struct GUIContext {
};
int aov_mode{AOV_COLOR};
example::AOV aov; // framebuffer
int width = 1024;
@@ -95,6 +96,11 @@ struct GUIContext {
int render_width = 512;
int render_height = 512;
// scene reload
tinyusdz::Scene scene;
std::atomic<bool> request_reload{false};
std::string filename;
#if __EMSCRIPTEN__ || defined(EMULATE_EMSCRIPTEN)
bool render_finished{false};
int current_render_line = 0;
@@ -274,6 +280,45 @@ static void ScreenActivate(SDL_Window* window) {
#endif
}
bool LoadModel(const std::string& filename, tinyusdz::Scene* scene) {
std::string ext = str_tolower(GetFileExtension(filename));
std::string warn;
std::string err;
if (ext.compare("usdz") == 0) {
std::cout << "usdz\n";
bool ret = tinyusdz::LoadUSDZFromFile(filename, scene, &warn, &err);
if (!warn.empty()) {
std::cerr << "WARN : " << warn << "\n";
}
if (!err.empty()) {
std::cerr << "ERR : " << err << "\n";
}
if (!ret) {
std::cerr << "Failed to load USDZ file: " << filename << "\n";
return false;
}
} else { // assume usdc
bool ret = tinyusdz::LoadUSDCFromFile(filename, scene, &warn, &err);
if (!warn.empty()) {
std::cerr << "WARN : " << warn << "\n";
}
if (!err.empty()) {
std::cerr << "ERR : " << err << "\n";
}
if (!ret) {
std::cerr << "Failed to load USDC file: " << filename << "\n";
return false;
}
}
return true;
}
void RenderThread(GUIContext* ctx) {
bool done = false;
@@ -282,6 +327,35 @@ void RenderThread(GUIContext* ctx) {
return;
}
if (ctx->request_reload) {
ctx->scene = tinyusdz::Scene(); // reset
if (LoadModel(ctx->filename, &ctx->scene)) {
Proc(ctx->scene);
if (ctx->scene.geom_meshes.empty()) {
std::cerr << "The scene contains no GeomMesh\n";
} else {
ctx->render_scene.draw_meshes.clear();
for (size_t i = 0; i < ctx->scene.geom_meshes.size(); i++) {
example::DrawGeomMesh draw_mesh(&ctx->scene.geom_meshes[i]);
ctx->render_scene.draw_meshes.push_back(draw_mesh);
}
// Setup render mesh
if (!ctx->render_scene.Setup()) {
std::cerr << "Failed to setup render mesh.\n";
ctx->render_scene.draw_meshes.clear();
}
std::cout << "Setup render mesh\n";
}
}
ctx->request_reload = false;
ctx->redraw = true;
}
if (!ctx->redraw) {
// Give CPU some cycles.
std::this_thread::sleep_for(std::chrono::milliseconds(33));
@@ -484,6 +558,7 @@ EM_BOOL em_main_loop_frame(double tm, void* user) {
#endif
} // namespace
int main(int argc, char** argv) {
@@ -526,68 +601,44 @@ int main(int argc, char** argv) {
if (argc > 1) {
filename = std::string(argv[1]);
} else {
}
std::cout << "Loading file " << filename << "\n";
std::string ext = str_tolower(GetFileExtension(filename));
std::string warn;
std::string err;
tinyusdz::Scene scene;
//tinyusdz::Scene scene;
if (ext.compare("usdz") == 0) {
std::cout << "usdz\n";
bool ret = tinyusdz::LoadUSDZFromFile(filename, &scene, &warn, &err);
if (!warn.empty()) {
std::cerr << "WARN : " << warn << "\n";
}
if (!err.empty()) {
std::cerr << "ERR : " << err << "\n";
return EXIT_FAILURE;
}
bool init_with_empty = false;
if (!ret) {
std::cerr << "Failed to load USDZ file: " << filename << "\n";
return EXIT_FAILURE;
}
} else { // assume usdc
bool ret = tinyusdz::LoadUSDCFromFile(filename, &scene, &warn, &err);
if (!warn.empty()) {
std::cerr << "WARN : " << warn << "\n";
}
if (!err.empty()) {
std::cerr << "ERR : " << err << "\n";
return EXIT_FAILURE;
}
if (!ret) {
std::cerr << "Failed to load USDC file: " << filename << "\n";
return EXIT_FAILURE;
}
if (!LoadModel(filename, &g_gui_ctx.scene)) {
init_with_empty = true;
}
std::cout << "Loaded USDC file\n";
if (!init_with_empty) {
std::cout << "Loaded USDC file\n";
Proc(scene);
if (scene.geom_meshes.empty()) {
exit(-1);
Proc(g_gui_ctx.scene);
if (g_gui_ctx.scene.geom_meshes.empty()) {
std::cerr << "The scene contains no GeomMesh\n";
exit(-1);
}
}
GUIContext& gui_ctx = g_gui_ctx;
gui_ctx.renderer = renderer;
for (size_t i = 0; i < scene.geom_meshes.size(); i++) {
example::DrawGeomMesh draw_mesh(&scene.geom_meshes[i]);
gui_ctx.render_scene.draw_meshes.push_back(draw_mesh);
}
if (!init_with_empty) {
for (size_t i = 0; i < g_gui_ctx.scene.geom_meshes.size(); i++) {
example::DrawGeomMesh draw_mesh(&g_gui_ctx.scene.geom_meshes[i]);
gui_ctx.render_scene.draw_meshes.push_back(draw_mesh);
}
// Setup render mesh
if (!gui_ctx.render_scene.Setup()) {
std::cerr << "Failed to setup render mesh.\n";
exit(-1);
// Setup render mesh
if (!gui_ctx.render_scene.Setup()) {
std::cerr << "Failed to setup render mesh.\n";
exit(-1);
}
std::cout << "Setup render mesh\n";
}
std::cout << "Setup render mesh\n";
bool done = false;
@@ -695,6 +746,14 @@ int main(int argc, char** argv) {
printf("File dropped: %s\n", filepath);
std::string fname = filepath;
// Scene reloading is done in render thread.
g_gui_ctx.filename = fname;
g_gui_ctx.request_reload = true;
SDL_free(filepath);
} else if (e.type == SDL_WINDOWEVENT) {

View File

@@ -369,105 +369,113 @@ bool Render(const RenderScene& scene, const Camera& cam, AOV* output) {
size_t pixel_idx = y * width + x;
// HACK. Use the first mesh
const DrawGeomMesh& mesh = scene.draw_meshes[0];
bool hit = false;
// Intersector functor.
nanort::TriangleIntersector<> triangle_intersector(
mesh.vertices.data(), mesh.facevarying_indices.data(),
sizeof(float) * 3);
nanort::TriangleIntersection<> isect; // stores isect info
bool hit = mesh.accel.Traverse(ray, triangle_intersector, &isect);
if (scene.draw_meshes.size()) {
// HACK. Use the first mesh
const DrawGeomMesh& mesh = scene.draw_meshes[0];
if (hit) {
float3 Ng;
{
// geometric normal.
float3 v0;
float3 v1;
float3 v2;
// Intersector functor.
nanort::TriangleIntersector<> triangle_intersector(
mesh.vertices.data(), mesh.facevarying_indices.data(),
sizeof(float) * 3);
size_t vid0 = mesh.facevarying_indices[3 * isect.prim_id + 0];
size_t vid1 = mesh.facevarying_indices[3 * isect.prim_id + 1];
size_t vid2 = mesh.facevarying_indices[3 * isect.prim_id + 2];
nanort::TriangleIntersection<> isect; // stores isect info
v0[0] = mesh.vertices[3 * vid0 + 0];
v0[1] = mesh.vertices[3 * vid0 + 1];
v0[2] = mesh.vertices[3 * vid0 + 2];
hit = mesh.accel.Traverse(ray, triangle_intersector, &isect);
v1[0] = mesh.vertices[3 * vid1 + 0];
v1[1] = mesh.vertices[3 * vid1 + 1];
v1[2] = mesh.vertices[3 * vid1 + 2];
if (hit) {
float3 Ng;
{
// geometric normal.
float3 v0;
float3 v1;
float3 v2;
v2[0] = mesh.vertices[3 * vid2 + 0];
v2[1] = mesh.vertices[3 * vid2 + 1];
v2[2] = mesh.vertices[3 * vid2 + 2];
size_t vid0 = mesh.facevarying_indices[3 * isect.prim_id + 0];
size_t vid1 = mesh.facevarying_indices[3 * isect.prim_id + 1];
size_t vid2 = mesh.facevarying_indices[3 * isect.prim_id + 2];
CalcNormal(Ng, v0, v1, v2);
v0[0] = mesh.vertices[3 * vid0 + 0];
v0[1] = mesh.vertices[3 * vid0 + 1];
v0[2] = mesh.vertices[3 * vid0 + 2];
v1[0] = mesh.vertices[3 * vid1 + 0];
v1[1] = mesh.vertices[3 * vid1 + 1];
v1[2] = mesh.vertices[3 * vid1 + 2];
v2[0] = mesh.vertices[3 * vid2 + 0];
v2[1] = mesh.vertices[3 * vid2 + 1];
v2[2] = mesh.vertices[3 * vid2 + 2];
CalcNormal(Ng, v0, v1, v2);
}
float3 Ns;
if (mesh.facevarying_normals.size()) {
float3 n0;
float3 n1;
float3 n2;
n0[0] = mesh.facevarying_normals[9 * isect.prim_id + 0];
n0[1] = mesh.facevarying_normals[9 * isect.prim_id + 1];
n0[2] = mesh.facevarying_normals[9 * isect.prim_id + 2];
n1[0] = mesh.facevarying_normals[9 * isect.prim_id + 3];
n1[1] = mesh.facevarying_normals[9 * isect.prim_id + 4];
n1[2] = mesh.facevarying_normals[9 * isect.prim_id + 5];
n2[0] = mesh.facevarying_normals[9 * isect.prim_id + 6];
n2[1] = mesh.facevarying_normals[9 * isect.prim_id + 7];
n2[2] = mesh.facevarying_normals[9 * isect.prim_id + 8];
// lerp normal.
Ns = vnormalize(Lerp3(n0, n1, n2, isect.u, isect.v));
} else {
Ns = Ng;
}
float3 texcoord = {0.0f, 0.0f, 0.0f};
if (mesh.facevarying_texcoords.size()) {
float3 t0;
float3 t1;
float3 t2;
t0[0] = mesh.facevarying_texcoords[6 * isect.prim_id + 0];
t0[1] = mesh.facevarying_texcoords[6 * isect.prim_id + 1];
t0[2] = 0.0f;
t1[0] = mesh.facevarying_texcoords[6 * isect.prim_id + 2];
t1[1] = mesh.facevarying_texcoords[6 * isect.prim_id + 3];
t1[2] = 0.0f;
t2[0] = mesh.facevarying_texcoords[6 * isect.prim_id + 4];
t2[1] = mesh.facevarying_texcoords[6 * isect.prim_id + 5];
t2[2] = 0.0f;
texcoord = Lerp3(t0, t1, t2, isect.u, isect.v);
}
output->rgb[3 * pixel_idx + 0] = 0.5f * Ns[0] + 0.5f;
output->rgb[3 * pixel_idx + 1] = 0.5f * Ns[1] + 0.5f;
output->rgb[3 * pixel_idx + 2] = 0.5f * Ns[2] + 0.5f;
output->geometric_normal[3 * pixel_idx + 0] = 0.5f * Ns[0] + 0.5f;
output->geometric_normal[3 * pixel_idx + 1] = 0.5f * Ns[1] + 0.5f;
output->geometric_normal[3 * pixel_idx + 2] = 0.5f * Ns[2] + 0.5f;
output->shading_normal[3 * pixel_idx + 0] = 0.5f * Ns[0] + 0.5f;
output->shading_normal[3 * pixel_idx + 1] = 0.5f * Ns[1] + 0.5f;
output->shading_normal[3 * pixel_idx + 2] = 0.5f * Ns[2] + 0.5f;
output->texcoords[2 * pixel_idx + 0] = texcoord[0];
output->texcoords[2 * pixel_idx + 1] = texcoord[1];
}
}
float3 Ns;
if (mesh.facevarying_normals.size()) {
float3 n0;
float3 n1;
float3 n2;
n0[0] = mesh.facevarying_normals[9 * isect.prim_id + 0];
n0[1] = mesh.facevarying_normals[9 * isect.prim_id + 1];
n0[2] = mesh.facevarying_normals[9 * isect.prim_id + 2];
n1[0] = mesh.facevarying_normals[9 * isect.prim_id + 3];
n1[1] = mesh.facevarying_normals[9 * isect.prim_id + 4];
n1[2] = mesh.facevarying_normals[9 * isect.prim_id + 5];
n2[0] = mesh.facevarying_normals[9 * isect.prim_id + 6];
n2[1] = mesh.facevarying_normals[9 * isect.prim_id + 7];
n2[2] = mesh.facevarying_normals[9 * isect.prim_id + 8];
// lerp normal.
Ns = vnormalize(Lerp3(n0, n1, n2, isect.u, isect.v));
} else {
Ns = Ng;
}
float3 texcoord = {0.0f, 0.0f, 0.0f};
if (mesh.facevarying_texcoords.size()) {
float3 t0;
float3 t1;
float3 t2;
t0[0] = mesh.facevarying_texcoords[6 * isect.prim_id + 0];
t0[1] = mesh.facevarying_texcoords[6 * isect.prim_id + 1];
t0[2] = 0.0f;
t1[0] = mesh.facevarying_texcoords[6 * isect.prim_id + 2];
t1[1] = mesh.facevarying_texcoords[6 * isect.prim_id + 3];
t1[2] = 0.0f;
t2[0] = mesh.facevarying_texcoords[6 * isect.prim_id + 4];
t2[1] = mesh.facevarying_texcoords[6 * isect.prim_id + 5];
t2[2] = 0.0f;
texcoord = Lerp3(t0, t1, t2, isect.u, isect.v);
}
output->rgb[3 * pixel_idx + 0] = 0.5f * Ns[0] + 0.5f;
output->rgb[3 * pixel_idx + 1] = 0.5f * Ns[1] + 0.5f;
output->rgb[3 * pixel_idx + 2] = 0.5f * Ns[2] + 0.5f;
output->geometric_normal[3 * pixel_idx + 0] = 0.5f * Ns[0] + 0.5f;
output->geometric_normal[3 * pixel_idx + 1] = 0.5f * Ns[1] + 0.5f;
output->geometric_normal[3 * pixel_idx + 2] = 0.5f * Ns[2] + 0.5f;
output->shading_normal[3 * pixel_idx + 0] = 0.5f * Ns[0] + 0.5f;
output->shading_normal[3 * pixel_idx + 1] = 0.5f * Ns[1] + 0.5f;
output->shading_normal[3 * pixel_idx + 2] = 0.5f * Ns[2] + 0.5f;
output->texcoords[2 * pixel_idx + 0] = texcoord[0];
output->texcoords[2 * pixel_idx + 1] = texcoord[1];
} else {
if (!hit) {
output->rgb[3 * pixel_idx + 0] = 0.0f;
output->rgb[3 * pixel_idx + 1] = 0.0f;
output->rgb[3 * pixel_idx + 2] = 0.0f;

BIN
models/cube.usdc Normal file

Binary file not shown.