diff --git a/src/akari/core/image.cpp b/src/akari/core/image.cpp index 619b6707..ed21730a 100644 --- a/src/akari/core/image.cpp +++ b/src/akari/core/image.cpp @@ -118,7 +118,6 @@ namespace akari { stbi_image_free((void *)data); } else { const auto *data = stbi_load(path.string().c_str(), &x, &y, &channel, 0); - info("channel={}", channel); image = std::make_shared(ivec2(x, y)); parallel_for( image->resolution().y, diff --git a/src/akari/core/parser.cpp b/src/akari/core/parser.cpp index d465f0bc..4fed8b58 100644 --- a/src/akari/core/parser.cpp +++ b/src/akari/core/parser.cpp @@ -195,6 +195,7 @@ namespace akari::sdl { ctx.expect("export"); expect_space(ctx); auto var = parse_identifier(ctx); + ctx.cur_var = var; if (ctx.cur_mod()->exports.find(var) != ctx.cur_mod()->exports.end()) { ctx.report_error(fmt::format("{} is already defined", var), ctx.loc); } @@ -204,11 +205,13 @@ namespace akari::sdl { auto val = parse(ctx); ctx.cur_mod()->exports[var] = val; expect_newline(ctx); + ctx.cur_var = ""; } void Parser::parse_let(ParserContext &ctx) { ctx.expect("let"); expect_space(ctx); auto var = parse_identifier(ctx); + ctx.cur_var = var; if (ctx.cur_mod()->locals.find(var) != ctx.cur_mod()->locals.end()) { ctx.report_error(fmt::format("{} is already defined", var), ctx.loc); } @@ -218,6 +221,7 @@ namespace akari::sdl { auto val = parse(ctx); ctx.cur_mod()->locals[var] = val; expect_newline(ctx); + ctx.cur_var = ""; } Value Parser::parse(ParserContext &ctx) { auto c = ctx.peek(); diff --git a/src/akari/core/parser.h b/src/akari/core/parser.h index cb3a508a..5b9c86fd 100644 --- a/src/akari/core/parser.h +++ b/src/akari/core/parser.h @@ -164,7 +164,7 @@ namespace akari::sdl { struct AKR_EXPORT ParserContext { std::vector> mod_stack; P main; - + std::string cur_var; SourceLoc loc; const std::string &source; size_t pos = 0; diff --git a/src/akari/render/lights/area.cpp b/src/akari/render/lights/area.cpp index 2a2bf00d..4669fb7b 100644 --- a/src/akari/render/lights/area.cpp +++ b/src/akari/render/lights/area.cpp @@ -87,6 +87,9 @@ namespace akari::render { AKR_ASSERT_THROW(color); } } + void finalize()override{ + color->finalize(); + } }; AKR_EXPORT_NODE(AreaLight, AreaLightNode); } // namespace akari::render \ No newline at end of file diff --git a/src/akari/render/lights/envmap.cpp b/src/akari/render/lights/envmap.cpp index 56137b7b..7a61af14 100644 --- a/src/akari/render/lights/envmap.cpp +++ b/src/akari/render/lights/envmap.cpp @@ -140,6 +140,7 @@ namespace akari::render { AKR_CHECK(!triangle.has_value()); return InfiniteAreaLight::create(*scene, transform, envmap->create_texture(allocator), allocator); } + void finalize() override { envmap->finalize(); } }; AKR_EXPORT_NODE(EnvMap, EnvMapNode); } // namespace akari::render \ No newline at end of file diff --git a/src/akari/render/material.cpp b/src/akari/render/material.cpp index 913add9a..92c215da 100644 --- a/src/akari/render/material.cpp +++ b/src/akari/render/material.cpp @@ -58,13 +58,18 @@ namespace akari::render { if (field == "fraction" || field == "frac") { fraction = resolve_texture(value); } else if (field == "first") { - mat_A = dyn_cast(value.object()); + mat_A = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(mat_A); } else if (field == "second") { - mat_B = dyn_cast(value.object()); + mat_B = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(mat_B); } } + void finalize() override { + fraction->finalize(); + mat_A->finalize(); + mat_B->finalize(); + } std::shared_ptr create_material(Allocator<> allocator) override { return make_pmr_shared(allocator, fraction->create_texture(allocator), mat_A->create_material(allocator), @@ -82,13 +87,14 @@ namespace akari::render { void object_field(sdl::Parser &parser, sdl::ParserContext &ctx, const std::string &field, const sdl::Value &value) override { if (field == "light") { - light_ = dyn_cast(value.object()); + light_ = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(light_); } } std::shared_ptr create_material(Allocator<> allocator) override { return make_pmr_shared(allocator, light_); } + void finalize() override { light_->finalize(); } }; AKR_EXPORT std::shared_ptr create_emissive_material() { return std::make_shared(); diff --git a/src/akari/render/material.h b/src/akari/render/material.h index 0b521485..30f7973e 100644 --- a/src/akari/render/material.h +++ b/src/akari/render/material.h @@ -127,7 +127,7 @@ namespace akari::render { class AKR_EXPORT EmissiveMaterialNode : public MaterialNode { public: [[nodiscard]] std::shared_ptr as_emissive() override { - return dyn_cast(shared_from_this()); + return sg_dyn_cast(shared_from_this()); } [[nodiscard]] virtual std::shared_ptr light() = 0; }; @@ -147,7 +147,7 @@ namespace akari::render { return create_image_texture(path); } else { AKR_ASSERT_THROW(value.is_object()); - auto tex = dyn_cast(value.object()); + auto tex = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(tex); return tex; } diff --git a/src/akari/render/materials/diffuse.cpp b/src/akari/render/materials/diffuse.cpp index 54d33bdc..92ca8a09 100644 --- a/src/akari/render/materials/diffuse.cpp +++ b/src/akari/render/materials/diffuse.cpp @@ -55,6 +55,9 @@ namespace akari::render { std::shared_ptr create_material(Allocator<> allocator) override { return make_pmr_shared(allocator, color->create_texture(allocator)); } + void finalize() override { + color->finalize(); + } }; AKR_EXPORT_NODE(DiffuseMaterial, DiffuseMaterialNode) } // namespace akari::render \ No newline at end of file diff --git a/src/akari/render/materials/glossy.cpp b/src/akari/render/materials/glossy.cpp index e36d0ebd..2fb2114e 100644 --- a/src/akari/render/materials/glossy.cpp +++ b/src/akari/render/materials/glossy.cpp @@ -41,9 +41,7 @@ namespace akari::render { auto R = color->evaluate(sp); return R; } - Float tr(const ShadingPoint &sp) const override { - return color->tr(sp); - } + Float tr(const ShadingPoint &sp) const override { return color->tr(sp); } }; class GlossyMaterialNode final : public MaterialNode { @@ -64,6 +62,10 @@ namespace akari::render { return make_pmr_shared(allocator, color->create_texture(allocator), roughness->create_texture(allocator)); } + void finalize() override { + color->finalize(); + roughness->finalize(); + } }; AKR_EXPORT_NODE(GlossyMaterial, GlossyMaterialNode) } // namespace akari::render \ No newline at end of file diff --git a/src/akari/render/scene.cpp b/src/akari/render/scene.cpp index fdf4ab89..0dfc3e38 100644 --- a/src/akari/render/scene.cpp +++ b/src/akari/render/scene.cpp @@ -171,26 +171,26 @@ namespace akari::render { void SceneNode::object_field(sdl::Parser &parser, sdl::ParserContext &ctx, const std::string &field, const sdl::Value &value) { if (field == "camera") { - camera = dyn_cast(value.object()); + camera = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(camera); } else if (field == "output") { output = value.get().value(); } else if (field == "integrator") { - integrator = dyn_cast(value.object()); + integrator = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(integrator); } else if (field == "shapes") { AKR_ASSERT_THROW(value.is_array()); for (auto shape : value) { - shapes.emplace_back(dyn_cast(shape.object())); + shapes.emplace_back(sg_dyn_cast(shape.object())); } } else if (field == "sampler") { - sampler = dyn_cast(value.object()); + sampler = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(sampler); } else if (field == "accelerator") { - accel = dyn_cast(value.object()); + accel = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(accel); } else if (field == "envmap") { - envmap = dyn_cast(value.object()); + envmap = sg_dyn_cast(value.object()); AKR_ASSERT_THROW(envmap); } } diff --git a/src/akari/render/scenegraph.cpp b/src/akari/render/scenegraph.cpp index ea399e55..6f9c3768 100644 --- a/src/akari/render/scenegraph.cpp +++ b/src/akari/render/scenegraph.cpp @@ -59,7 +59,11 @@ namespace akari::render { if (!pi) { throw std::runtime_error("failed to load plugin"); } - return pi->make_shared(); + auto object = pi->make_shared(); + if(!ctx.cur_var.empty()){ + return std::make_shared(ctx.cur_var, object); + } + return object; } }; std::shared_ptr SceneGraphParser::create_parser() { diff --git a/src/akari/render/scenegraph.h b/src/akari/render/scenegraph.h index 96a62e26..15661f11 100644 --- a/src/akari/render/scenegraph.h +++ b/src/akari/render/scenegraph.h @@ -44,6 +44,7 @@ namespace akari::render { virtual void enter(SceneGraphNode *) const {} virtual void leave(SceneGraphNode *) const {} }; + class NamedNode; class AKR_EXPORT SceneGraphNode : public sdl::Object { protected: virtual void do_traverse(TraversalCallback *cb) {} @@ -51,6 +52,7 @@ namespace akari::render { public: void object_field(sdl::Parser &parser, sdl::ParserContext &ctx, const std::string &field, const sdl::Value &value) override {} + virtual bool is_named() const { return false; } virtual void on_parameter_change(const std::string &field, const sdl::Value &value) {} virtual void commit() {} virtual const char *description() { return "unknown"; } @@ -61,23 +63,57 @@ namespace akari::render { } virtual void finalize() {} + template + inline std::shared_ptr cast() const; + + template + inline std::shared_ptr cast(); + typedef std::shared_ptr (*CreateFunc)(void); }; class AKR_EXPORT NamedNode : public SceneGraphNode { - std::shared_ptr underlying; std::string name_; + std::shared_ptr underlying_; public: + NamedNode(std::string name, std::shared_ptr underlying_) + : name_(name), underlying_(underlying_) {} const std::string &name() { return name_; } void object_field(sdl::Parser &parser, sdl::ParserContext &ctx, const std::string &field, const sdl::Value &value) override { - return underlying->object_field(parser, ctx, field, value); + return underlying_->object_field(parser, ctx, field, value); } - void commit() override { underlying->commit(); } - const char *description() override { return underlying->description(); } - void traverse(TraversalCallback *cb) override { underlying->traverse(cb); } - void finalize() override { underlying->finalize(); } + void commit() override { underlying_->commit(); } + const char *description() override { return underlying_->description(); } + void traverse(TraversalCallback *cb) override { underlying_->traverse(cb); } + void finalize() override { underlying_->finalize(); } + bool is_named() const final override { return true; } + std::shared_ptr underlying() { return underlying_; } }; + + template + inline std::shared_ptr SceneGraphNode::cast() const { + if (is_named()) { + return dyn_cast(shared_from_this())->underlying(); + } else { + return dyn_cast(shared_from_this()); + } + } + + template + inline std::shared_ptr SceneGraphNode::cast() { + if (is_named()) { + return dyn_cast(dyn_cast(shared_from_this())->underlying()); + } else { + return dyn_cast(shared_from_this()); + } + } + template + std::shared_ptr sg_dyn_cast(const std::shared_ptr &_p) { + auto p = dyn_cast(_p); + static_assert(std::is_base_of_v); + return p == nullptr ? nullptr : p->cast(); + } class AKR_EXPORT SceneGraphParser : public sdl::Parser { public: virtual void register_node(const std::string &name, SceneGraphNode::CreateFunc) = 0; diff --git a/src/akari/render/shapes/akari-mesh.cpp b/src/akari/render/shapes/akari-mesh.cpp index 5816f823..c04f2e59 100644 --- a/src/akari/render/shapes/akari-mesh.cpp +++ b/src/akari/render/shapes/akari-mesh.cpp @@ -75,7 +75,7 @@ namespace akari::render { } else if (field == "materials") { AKR_ASSERT_THROW(value.is_array()); for (auto mat : value) { - auto m = dyn_cast(mat.object()); + auto m = sg_dyn_cast(mat.object()); AKR_ASSERT(m); materials.emplace_back(m); }