mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Support Drop file and reload scene.
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
BIN
models/cube.usdc
Normal file
Binary file not shown.
Reference in New Issue
Block a user