Making the Hue Correct Curves Wrap #117114

Merged
Omar Emara merged 31 commits from JonasDichelle/blender:hue-correct-bezier-wrap into main 2024-03-21 15:35:13 +01:00
27 changed files with 230 additions and 86 deletions
Showing only changes of commit e36e1a774a - Show all commits

View File

@ -10,6 +10,7 @@
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <string>
@ -45,6 +46,8 @@ class AssetCatalogService {
* Cached catalog tree storage. Lazy-created by #AssetCatalogService::catalog_tree().
*/
std::unique_ptr<AssetCatalogTree> catalog_tree_;
std::mutex catalog_tree_mutex_;
CatalogFilePath asset_library_root_;
Vector<std::unique_ptr<AssetCatalogCollection>> undo_snapshots_;
@ -177,6 +180,9 @@ class AssetCatalogService {
*/
void update_catalog_path(CatalogID catalog_id, const AssetCatalogPath &new_catalog_path);
/**
* May be called from multiple threads.
*/
const AssetCatalogTree &catalog_tree();
/** Return true only if there are no catalogs known. */
@ -250,8 +256,11 @@ class AssetCatalogService {
const CatalogFilePath &blend_file_path);
std::unique_ptr<AssetCatalogTree> read_into_tree() const;
/** Ensure a #catalog_tree() will update the tree. Must be called whenever the contained user
* visible catalogs change. */
/**
* Ensure a #catalog_tree() will update the tree. Must be called whenever the contained user
* visible catalogs change.
* May be called from multiple threads.
*/
void invalidate_catalog_tree();
/**
@ -265,9 +274,9 @@ class AssetCatalogService {
void tag_all_catalogs_as_unsaved_changes();
/* For access by subclasses, as those will not be marked as friend by #AssetCatalogCollection. */
AssetCatalogDefinitionFile *get_catalog_definition_file() const;
OwningAssetCatalogMap &get_catalogs() const;
OwningAssetCatalogMap &get_deleted_catalogs() const;
const AssetCatalogDefinitionFile *get_catalog_definition_file() const;
const OwningAssetCatalogMap &get_catalogs() const;
const OwningAssetCatalogMap &get_deleted_catalogs() const;
};
/**

View File

@ -115,16 +115,16 @@ bool AssetCatalogService::is_empty() const
return catalog_collection_->catalogs_.is_empty();
}
OwningAssetCatalogMap &AssetCatalogService::get_catalogs() const
const OwningAssetCatalogMap &AssetCatalogService::get_catalogs() const
{
return catalog_collection_->catalogs_;
}
OwningAssetCatalogMap &AssetCatalogService::get_deleted_catalogs() const
const OwningAssetCatalogMap &AssetCatalogService::get_deleted_catalogs() const
{
return catalog_collection_->deleted_catalogs_;
}
AssetCatalogDefinitionFile *AssetCatalogService::get_catalog_definition_file() const
const AssetCatalogDefinitionFile *AssetCatalogService::get_catalog_definition_file() const
{
return catalog_collection_->catalog_definition_file_.get();
}
@ -589,11 +589,13 @@ std::unique_ptr<AssetCatalogTree> AssetCatalogService::read_into_tree() const
void AssetCatalogService::invalidate_catalog_tree()
{
std::lock_guard lock{catalog_tree_mutex_};
this->catalog_tree_ = nullptr;
}
const AssetCatalogTree &AssetCatalogService::catalog_tree()
{
std::lock_guard lock{catalog_tree_mutex_};
if (!catalog_tree_) {
/* Ensure all catalog paths lead to valid catalogs. This is important for the catalog tree to
* be usable, e.g. it makes sure every item in the tree maps to an actual catalog. */

View File

@ -44,12 +44,12 @@ class TestableAssetCatalogService : public AssetCatalogService {
{
}
AssetCatalogDefinitionFile *get_catalog_definition_file()
const AssetCatalogDefinitionFile *get_catalog_definition_file()
{
return AssetCatalogService::get_catalog_definition_file();
}
OwningAssetCatalogMap &get_deleted_catalogs() const
const OwningAssetCatalogMap &get_deleted_catalogs() const
{
return AssetCatalogService::get_deleted_catalogs();
}
@ -67,7 +67,7 @@ class TestableAssetCatalogService : public AssetCatalogService {
int64_t count_catalogs_with_path(const CatalogFilePath &path)
{
int64_t count = 0;
for (auto &catalog_uptr : get_catalogs().values()) {
for (const auto &catalog_uptr : get_catalogs().values()) {
if (catalog_uptr->path == path) {
count++;
}
@ -124,9 +124,10 @@ class AssetCatalogTest : public AssetLibraryTestBase {
<< "Overwritten CDF should have been backed up.";
/* Test that the in-memory CDF has the expected file path. */
AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
BLI_path_slash_native(cdf->file_path.data());
EXPECT_EQ(cdf_toplevel, cdf->file_path);
const AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
std::string native_cdf_path = cdf->file_path;
BLI_path_slash_native(native_cdf_path.data());
EXPECT_EQ(cdf_toplevel, native_cdf_path);
/* Test that the in-memory catalogs have been merged with the on-disk one. */
AssetCatalogService loaded_service(cdf_toplevel);
@ -265,7 +266,7 @@ TEST_F(AssetCatalogTest, write_single_file)
const CatalogFilePath save_to_path = use_temp_path() +
AssetCatalogService::DEFAULT_CATALOG_FILENAME;
AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
const AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
cdf->write_to_disk(save_to_path);
AssetCatalogService loaded_service(save_to_path);
@ -293,7 +294,7 @@ TEST_F(AssetCatalogTest, read_write_unicode_filepath)
service.load_from_disk(load_from_path);
const CatalogFilePath save_to_path = use_temp_path() + "новый.cats.txt";
AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
const AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
ASSERT_NE(nullptr, cdf) << "unable to load " << load_from_path;
EXPECT_TRUE(cdf->write_to_disk(save_to_path));
@ -375,7 +376,7 @@ TEST_F(AssetCatalogTest, on_blendfile_save__from_memory_into_empty_directory)
EXPECT_TRUE(BLI_exists(expected_cdf_path.c_str()));
/* Test that the in-memory CDF has been created, and contains the expected catalog. */
AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
const AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
ASSERT_NE(nullptr, cdf);
EXPECT_TRUE(cdf->contains(cat->catalog_id));
@ -410,7 +411,7 @@ TEST_F(AssetCatalogTest, on_blendfile_save__from_memory_into_existing_cdf_and_me
<< "Overwritten CDF should have been backed up.";
/* Test that the in-memory CDF has the expected file path. */
AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
const AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
ASSERT_NE(nullptr, cdf);
EXPECT_EQ(writable_cdf_file, cdf->file_path);
@ -633,7 +634,7 @@ TEST_F(AssetCatalogTest, delete_catalog_write_to_disk)
service.delete_catalog_by_id_soft(UUID_POSES_ELLIE);
const CatalogFilePath save_to_path = use_temp_path();
AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
const AssetCatalogDefinitionFile *cdf = service.get_catalog_definition_file();
cdf->write_to_disk(save_to_path + SEP_STR + AssetCatalogService::DEFAULT_CATALOG_FILENAME);
AssetCatalogService loaded_service(save_to_path);
@ -1022,7 +1023,7 @@ TEST_F(AssetCatalogTest, create_missing_catalogs_after_loading)
EXPECT_TRUE(cat_ruzena->flags.has_unsaved_changes)
<< "Missing parents should be marked as having changes.";
AssetCatalogDefinitionFile *cdf = loaded_service.get_catalog_definition_file();
const AssetCatalogDefinitionFile *cdf = loaded_service.get_catalog_definition_file();
ASSERT_NE(nullptr, cdf);
EXPECT_TRUE(cdf->contains(cat_char->catalog_id)) << "Missing parents should be saved to a CDF.";
EXPECT_TRUE(cdf->contains(cat_ellie->catalog_id)) << "Missing parents should be saved to a CDF.";

View File

@ -106,6 +106,8 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
export_params.export_smooth_groups = RNA_boolean_get(op->ptr, "export_smooth_groups");
export_params.smooth_groups_bitflags = RNA_boolean_get(op->ptr, "smooth_group_bitflags");
export_params.reports = op->reports;
OBJ_export(C, &export_params);
return OPERATOR_FINISHED;
@ -404,6 +406,8 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op)
import_params.relative_paths = ((U.flag & USER_RELPATHS) != 0);
import_params.clear_selection = true;
import_params.reports = op->reports;
const auto paths = blender::ed::io::paths_from_operator_properties(op->ptr);
if (paths.is_empty()) {

View File

@ -67,7 +67,7 @@ static int wm_ply_export_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No filepath given");
return OPERATOR_CANCELLED;
}
PLYExportParams export_params = {"\0"};
PLYExportParams export_params{};
export_params.file_base_for_tests[0] = '\0';
RNA_string_get(op->ptr, "filepath", export_params.filepath);
export_params.blen_filepath = CTX_data_main(C)->filepath;
@ -85,6 +85,8 @@ static int wm_ply_export_exec(bContext *C, wmOperator *op)
export_params.export_triangulated_mesh = RNA_boolean_get(op->ptr, "export_triangulated_mesh");
export_params.ascii_format = RNA_boolean_get(op->ptr, "ascii_format");
export_params.reports = op->reports;
PLY_export(C, &export_params);
return OPERATOR_FINISHED;
@ -248,6 +250,8 @@ static int wm_ply_import_exec(bContext *C, wmOperator *op)
params.import_attributes = RNA_boolean_get(op->ptr, "import_attributes");
params.vertex_colors = ePLYVertexColorMode(RNA_enum_get(op->ptr, "import_colors"));
params.reports = op->reports;
const auto paths = blender::ed::io::paths_from_operator_properties(op->ptr);
if (paths.is_empty()) {
@ -256,7 +260,7 @@ static int wm_ply_import_exec(bContext *C, wmOperator *op)
}
for (const auto &path : paths) {
STRNCPY(params.filepath, path.c_str());
PLY_import(C, &params, op);
PLY_import(C, &params);
};
Scene *scene = CTX_data_scene(C);

View File

@ -48,7 +48,7 @@ static int wm_stl_export_execute(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No filename given");
return OPERATOR_CANCELLED;
}
STLExportParams export_params;
STLExportParams export_params{};
RNA_string_get(op->ptr, "filepath", export_params.filepath);
export_params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
export_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
@ -59,6 +59,8 @@ static int wm_stl_export_execute(bContext *C, wmOperator *op)
export_params.ascii_format = RNA_boolean_get(op->ptr, "ascii_format");
export_params.use_batch = RNA_boolean_get(op->ptr, "use_batch");
export_params.reports = op->reports;
STL_export(C, &export_params);
return OPERATOR_FINISHED;
@ -189,6 +191,8 @@ static int wm_stl_import_exec(bContext *C, wmOperator *op)
params.global_scale = RNA_float_get(op->ptr, "global_scale");
params.use_mesh_validate = RNA_boolean_get(op->ptr, "use_mesh_validate");
params.reports = op->reports;
const auto paths = blender::ed::io::paths_from_operator_properties(op->ptr);
if (paths.is_empty()) {

View File

@ -5,6 +5,8 @@
#include "BLI_bounds.hh"
#include "BLI_function_ref.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_string_ref.hh"
#include "DNA_modifier_types.h"
@ -47,7 +49,9 @@ float volume_compute_voxel_size(const Depsgraph *depsgraph,
*/
bke::VolumeGridData *fog_volume_grid_add_from_mesh(Volume *volume,
StringRefNull name,
const Mesh *mesh,
Span<float3> positions,
Span<int> corner_verts,
Span<int3> corner_tris,
const float4x4 &mesh_to_volume_space_transform,
float voxel_size,
float interior_band_width,
@ -55,7 +59,12 @@ bke::VolumeGridData *fog_volume_grid_add_from_mesh(Volume *volume,
/**
* Add a new SDF VolumeGrid to the Volume by converting the supplied mesh.
*/
bke::VolumeGridData *sdf_volume_grid_add_from_mesh(
Volume *volume, StringRefNull name, const Mesh &mesh, float voxel_size, float half_band_width);
bke::VolumeGridData *sdf_volume_grid_add_from_mesh(Volume *volume,
StringRefNull name,
Span<float3> positions,
Span<int> corner_verts,
Span<int3> corner_tris,
float voxel_size,
float half_band_width);
#endif
} // namespace blender::geometry

View File

@ -5,7 +5,6 @@
#include "BLI_math_matrix.hh"
#include "BLI_task.hh"
#include "BKE_mesh.hh"
#include "BKE_volume.hh"
#include "BKE_volume_openvdb.hh"
@ -29,17 +28,23 @@ class OpenVDBMeshAdapter {
float4x4 transform_;
public:
OpenVDBMeshAdapter(const Mesh &mesh, float4x4 transform);
OpenVDBMeshAdapter(const Span<float3> positions,
const Span<int> corner_verts,
const Span<int3> corner_tris,
const float4x4 &transform);
size_t polygonCount() const;
size_t pointCount() const;
size_t vertexCount(size_t /*polygon_index*/) const;
void getIndexSpacePoint(size_t polygon_index, size_t vertex_index, openvdb::Vec3d &pos) const;
};
OpenVDBMeshAdapter::OpenVDBMeshAdapter(const Mesh &mesh, float4x4 transform)
: positions_(mesh.vert_positions()),
corner_verts_(mesh.corner_verts()),
corner_tris_(mesh.corner_tris()),
OpenVDBMeshAdapter::OpenVDBMeshAdapter(const Span<float3> positions,
const Span<int> corner_verts,
const Span<int3> corner_tris,
const float4x4 &transform)
: positions_(positions),
corner_verts_(corner_verts),
corner_tris_(corner_tris),
transform_(transform)
{
}
@ -105,7 +110,9 @@ float volume_compute_voxel_size(const Depsgraph *depsgraph,
}
static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid(
const Mesh *mesh,
const Span<float3> positions,
const Span<int> corner_verts,
const Span<int3> corner_tris,
const float4x4 &mesh_to_volume_space_transform,
const float voxel_size,
const float interior_band_width,
@ -120,7 +127,8 @@ static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid(
/* Better align generated grid with the source mesh. */
mesh_to_index_space_transform.location() -= 0.5f;
OpenVDBMeshAdapter mesh_adapter{*mesh, mesh_to_index_space_transform};
OpenVDBMeshAdapter mesh_adapter{
positions, corner_verts, corner_tris, mesh_to_index_space_transform};
const float interior = std::max(1.0f, interior_band_width / voxel_size);
openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(
@ -139,7 +147,9 @@ static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid(
return new_grid;
}
static openvdb::FloatGrid::Ptr mesh_to_sdf_volume_grid(const Mesh &mesh,
static openvdb::FloatGrid::Ptr mesh_to_sdf_volume_grid(const Span<float3> positions,
const Span<int> corner_verts,
const Span<int3> corner_tris,
const float voxel_size,
const float half_band_width)
{
@ -147,10 +157,6 @@ static openvdb::FloatGrid::Ptr mesh_to_sdf_volume_grid(const Mesh &mesh,
return nullptr;
}
const Span<float3> positions = mesh.vert_positions();
const Span<int> corner_verts = mesh.corner_verts();
const Span<int3> corner_tris = mesh.corner_tris();
std::vector<openvdb::Vec3s> points(positions.size());
std::vector<openvdb::Vec3I> triangles(corner_tris.size());
@ -179,24 +185,34 @@ static openvdb::FloatGrid::Ptr mesh_to_sdf_volume_grid(const Mesh &mesh,
bke::VolumeGridData *fog_volume_grid_add_from_mesh(Volume *volume,
const StringRefNull name,
const Mesh *mesh,
const Span<float3> positions,
const Span<int> corner_verts,
const Span<int3> corner_tris,
const float4x4 &mesh_to_volume_space_transform,
const float voxel_size,
const float interior_band_width,
const float density)
{
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_fog_volume_grid(
mesh, mesh_to_volume_space_transform, voxel_size, interior_band_width, density);
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_fog_volume_grid(positions,
corner_verts,
corner_tris,
mesh_to_volume_space_transform,
voxel_size,
interior_band_width,
density);
return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr;
}
bke::VolumeGridData *sdf_volume_grid_add_from_mesh(Volume *volume,
const StringRefNull name,
const Mesh &mesh,
const Span<float3> positions,
const Span<int> corner_verts,
const Span<int3> corner_tris,
const float voxel_size,
const float half_band_width)
{
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_sdf_volume_grid(mesh, voxel_size, half_band_width);
openvdb::FloatGrid::Ptr mesh_grid = mesh_to_sdf_volume_grid(
positions, corner_verts, corner_tris, voxel_size, half_band_width);
return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr;
}
} // namespace blender::geometry

View File

@ -32,9 +32,9 @@ void PLY_export(bContext *C, const PLYExportParams *export_params)
report_duration("export", start_time, export_params->filepath);
}
void PLY_import(bContext *C, const PLYImportParams *import_params, wmOperator *op)
void PLY_import(bContext *C, const PLYImportParams *import_params)
{
TimePoint start_time = Clock::now();
blender::io::ply::importer_main(C, *import_params, op);
blender::io::ply::importer_main(C, *import_params);
report_duration("import", start_time, import_params->filepath);
}

View File

@ -45,6 +45,8 @@ struct PLYExportParams {
ePLYVertexColorMode vertex_colors;
bool export_attributes;
bool export_triangulated_mesh;
ReportList *reports = nullptr;
};
struct PLYImportParams {
@ -57,6 +59,8 @@ struct PLYImportParams {
ePLYVertexColorMode vertex_colors;
bool import_attributes;
bool merge_verts;
ReportList *reports = nullptr;
};
/**
@ -64,4 +68,4 @@ struct PLYImportParams {
*/
void PLY_export(bContext *C, const PLYExportParams *export_params);
void PLY_import(bContext *C, const PLYImportParams *import_params, wmOperator *op);
void PLY_import(bContext *C, const PLYImportParams *import_params);

View File

@ -6,7 +6,10 @@
* \ingroup ply
*/
#include <cstdio>
#include "BKE_layer.hh"
#include "BKE_report.hh"
#include "DNA_collection_types.h"
#include "DNA_scene_types.h"
@ -32,11 +35,21 @@ void exporter_main(bContext *C, const PLYExportParams &export_params)
std::unique_ptr<FileBuffer> buffer;
if (export_params.ascii_format) {
buffer = std::make_unique<FileBufferAscii>(export_params.filepath);
try {
if (export_params.ascii_format) {
buffer = std::make_unique<FileBufferAscii>(export_params.filepath);
}
else {
buffer = std::make_unique<FileBufferBinary>(export_params.filepath);
}
}
else {
buffer = std::make_unique<FileBufferBinary>(export_params.filepath);
catch (const std::system_error &ex) {
fprintf(stderr, "%s\n", ex.what());
BKE_reportf(export_params.reports,
RPT_ERROR,
"PLY Export: Cannot open file '%s'",
export_params.filepath);
return;
}
write_header(*buffer.get(), *plyData.get(), export_params);

View File

@ -6,6 +6,7 @@
* \ingroup ply
*/
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_lib_id.hh"
#include "BKE_mesh.hh"
@ -161,19 +162,18 @@ const char *read_header(PlyReadBuffer &file, PlyHeader &r_header)
return nullptr;
}
void importer_main(bContext *C, const PLYImportParams &import_params, wmOperator *op)
void importer_main(bContext *C, const PLYImportParams &import_params)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
importer_main(bmain, scene, view_layer, import_params, op);
importer_main(bmain, scene, view_layer, import_params);
}
void importer_main(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
const PLYImportParams &import_params,
wmOperator *op)
const PLYImportParams &import_params)
{
/* File base name used for both mesh and object. */
char ob_name[FILE_MAX];
@ -187,7 +187,7 @@ void importer_main(Main *bmain,
const char *err = read_header(file, header);
if (err != nullptr) {
fprintf(stderr, "PLY Importer: %s: %s\n", ob_name, err);
BKE_reportf(op->reports, RPT_ERROR, "PLY Importer: %s: %s", ob_name, err);
BKE_reportf(import_params.reports, RPT_ERROR, "PLY Importer: %s: %s", ob_name, err);
return;
}
@ -195,17 +195,17 @@ void importer_main(Main *bmain,
std::unique_ptr<PlyData> data = import_ply_data(file, header);
if (data == nullptr) {
fprintf(stderr, "PLY Importer: failed importing %s, unknown error\n", ob_name);
BKE_report(op->reports, RPT_ERROR, "PLY Importer: failed importing, unknown error");
BKE_report(import_params.reports, RPT_ERROR, "PLY Importer: failed importing, unknown error");
return;
}
if (!data->error.empty()) {
fprintf(stderr, "PLY Importer: failed importing %s: %s\n", ob_name, data->error.c_str());
BKE_report(op->reports, RPT_ERROR, "PLY Importer: failed importing, unknown error");
BKE_report(import_params.reports, RPT_ERROR, "PLY Importer: failed importing, unknown error");
return;
}
if (data->vertices.is_empty()) {
fprintf(stderr, "PLY Importer: file %s contains no vertices\n", ob_name);
BKE_report(op->reports, RPT_ERROR, "PLY Importer: failed importing, no vertices");
BKE_report(import_params.reports, RPT_ERROR, "PLY Importer: failed importing, no vertices");
return;
}

View File

@ -15,17 +15,14 @@ namespace blender::io::ply {
class PlyReadBuffer;
void splitstr(std::string str, Vector<std::string> &words, const StringRef &deli);
/* Main import function used from within Blender. */
void importer_main(bContext *C, const PLYImportParams &import_params, wmOperator *op);
void importer_main(bContext *C, const PLYImportParams &import_params);
/* Used from tests, where full bContext does not exist. */
void importer_main(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
const PLYImportParams &import_params,
wmOperator *op);
const PLYImportParams &import_params);
const char *read_header(PlyReadBuffer &file, PlyHeader &r_header);

View File

@ -21,6 +21,8 @@ struct STLImportParams {
bool use_scene_unit;
float global_scale;
bool use_mesh_validate;
ReportList *reports = nullptr;
};
struct STLExportParams {
@ -34,6 +36,8 @@ struct STLExportParams {
bool apply_modifiers;
bool ascii_format;
bool use_batch;
ReportList *reports = nullptr;
};
void STL_import(bContext *C, const STLImportParams *import_params);

View File

@ -10,8 +10,10 @@
#include <memory>
#include <string>
#include "BKE_context.hh"
#include "BKE_mesh.hh"
#include "BKE_object.hh"
#include "BKE_report.hh"
#include "BLI_string.h"
@ -40,7 +42,17 @@ void export_frame(Depsgraph *depsgraph,
/* If not exporting in batch, create single writer for all objects. */
if (!export_params.use_batch) {
writer = std::make_unique<FileWriter>(export_params.filepath, export_params.ascii_format);
try {
writer = std::make_unique<FileWriter>(export_params.filepath, export_params.ascii_format);
}
catch (const std::runtime_error &ex) {
fprintf(stderr, "%s\n", ex.what());
BKE_reportf(export_params.reports,
RPT_ERROR,
"STL Export: Cannot open file '%s'",
export_params.filepath);
return;
}
}
DEGObjectIterSettings deg_iter_settings{};
@ -70,7 +82,15 @@ void export_frame(Depsgraph *depsgraph,
char filepath[FILE_MAX];
STRNCPY(filepath, export_params.filepath);
BLI_path_extension_replace(filepath, FILE_MAX, suffix.c_str());
writer = std::make_unique<FileWriter>(filepath, export_params.ascii_format);
try {
writer = std::make_unique<FileWriter>(filepath, export_params.ascii_format);
}
catch (const std::runtime_error &ex) {
fprintf(stderr, "%s\n", ex.what());
BKE_reportf(
export_params.reports, RPT_ERROR, "STL Export: Cannot open file '%s'", filepath);
return;
}
}
Object *obj_eval = DEG_get_evaluated_object(depsgraph, object);

View File

@ -8,12 +8,14 @@
#include <cstdio>
#include "BKE_customdata.hh"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_mesh.hh"
#include "BKE_object.hh"
#include "BKE_report.hh"
#include "DNA_collection_types.h"
#include "DNA_layer_types.h"
#include "DNA_scene_types.h"
#include "BLI_fileops.hh"
@ -61,6 +63,10 @@ void importer_main(Main *bmain,
FILE *file = BLI_fopen(import_params.filepath, "rb");
if (!file) {
fprintf(stderr, "Failed to open STL file:'%s'.\n", import_params.filepath);
BKE_reportf(import_params.reports,
RPT_ERROR,
"STL Import: Cannot open file '%s'",
import_params.filepath);
return;
}
BLI_SCOPED_DEFER([&]() { fclose(file); });
@ -74,6 +80,10 @@ void importer_main(Main *bmain,
fseek(file, BINARY_HEADER_SIZE, SEEK_SET);
if (fread(&num_tri, sizeof(uint32_t), 1, file) != 1) {
stl_import_report_error(file);
BKE_reportf(import_params.reports,
RPT_ERROR,
"STL Import: Failed to read file '%s'",
import_params.filepath);
return;
}
bool is_ascii_stl = (file_size != (BINARY_HEADER_SIZE + 4 + BINARY_STRIDE * num_tri));
@ -89,6 +99,10 @@ void importer_main(Main *bmain,
if (mesh == nullptr) {
fprintf(stderr, "STL Importer: Failed to import mesh '%s'\n", import_params.filepath);
BKE_reportf(import_params.reports,
RPT_ERROR,
"STL Import: Failed to import mesh from file '%s'",
import_params.filepath);
return;
}

View File

@ -14,6 +14,8 @@
#include "DEG_depsgraph.hh"
#include "MEM_guardedalloc.h"
#include "IO_stl.hh"
#include "stl_export.hh"

View File

@ -59,6 +59,8 @@ struct OBJExportParams {
bool export_smooth_groups;
/* Create bitflags instead of the default "0"/"1" group IDs. */
bool smooth_groups_bitflags;
ReportList *reports = nullptr;
};
struct OBJImportParams {
@ -76,6 +78,8 @@ struct OBJImportParams {
bool validate_meshes = false;
bool relative_paths = true;
bool clear_selection = true;
ReportList *reports = nullptr;
};
/**

View File

@ -7,9 +7,11 @@
*/
#include <cstdio>
#include <exception>
#include <memory>
#include <system_error>
#include "BKE_context.hh"
#include "BKE_report.hh"
#include "BKE_scene.hh"
#include "BLI_path_util.h"
@ -259,6 +261,7 @@ void export_frame(Depsgraph *depsgraph, const OBJExportParams &export_params, co
}
catch (const std::system_error &ex) {
print_exception_error(ex);
BKE_reportf(export_params.reports, RPT_ERROR, "OBJ Export: Cannot open file '%s'", filepath);
return;
}
if (!frame_writer) {
@ -272,6 +275,10 @@ void export_frame(Depsgraph *depsgraph, const OBJExportParams &export_params, co
}
catch (const std::system_error &ex) {
print_exception_error(ex);
BKE_reportf(export_params.reports,
RPT_WARNING,
"OBJ Export: Cannot create mtl file for '%s'",
filepath);
}
}

View File

@ -6,6 +6,8 @@
* \ingroup obj
*/
#include "BKE_report.hh"
#include "BLI_map.hh"
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
@ -441,6 +443,10 @@ OBJParser::OBJParser(const OBJImportParams &import_params, size_t read_buffer_si
obj_file_ = BLI_fopen(import_params_.filepath, "rb");
if (!obj_file_) {
fprintf(stderr, "Cannot read from OBJ file:'%s'.\n", import_params_.filepath);
BKE_reportf(import_params_.reports,
RPT_ERROR,
"OBJ Import: Cannot open file '%s'",
import_params_.filepath);
return;
}
}

View File

@ -15,6 +15,7 @@
#include "BLI_string.h"
#include "BLI_string_ref.hh"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_scene.hh"

View File

@ -40,6 +40,8 @@ struct OBJExportParamsDefault {
params.export_vertex_groups = false;
params.export_smooth_groups = true;
params.smooth_groups_bitflags = false;
params.reports = nullptr;
}
};

View File

@ -11,6 +11,7 @@
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.hh"
#include "BKE_lib_query.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.hh"
#include "BKE_modifier.hh"
#include "BKE_volume.hh"
@ -158,7 +159,9 @@ static Volume *mesh_to_volume(ModifierData *md,
/* Convert mesh to grid and add to volume. */
geometry::fog_volume_grid_add_from_mesh(volume,
"density",
mesh,
mesh->vert_positions(),
mesh->corner_verts(),
mesh->corner_tris(),
mesh_to_own_object_space_transform,
voxel_size,
mvmd->interior_band_width,

View File

@ -421,8 +421,8 @@ DefNode(GeometryNode, GEO_NODE_REPLACE_MATERIAL, 0, "REPLACE_MATERIAL", ReplaceM
DefNode(GeometryNode, GEO_NODE_RESAMPLE_CURVE, 0, "RESAMPLE_CURVE", ResampleCurve, "Resample Curve", "Generate a poly spline for each input spline")
DefNode(GeometryNode, GEO_NODE_REVERSE_CURVE, 0, "REVERSE_CURVE", ReverseCurve, "Reverse Curve", "Change the direction of curves by swapping their start and end data")
DefNode(GeometryNode, GEO_NODE_ROTATE_INSTANCES, 0, "ROTATE_INSTANCES", RotateInstances, "Rotate Instances", "Rotate geometry instances in local or global space")
DefNode(GeometryNode, GEO_NODE_SAMPLE_GRID, 0, "SAMPLE_GRID", SampleGrid, "Sample Grid", "")
DefNode(GeometryNode, GEO_NODE_SAMPLE_CURVE, def_geo_curve_sample, "SAMPLE_CURVE", SampleCurve, "Sample Curve", "Retrieve data from a point on a curve at a certain distance from its start")
DefNode(GeometryNode, GEO_NODE_SAMPLE_GRID, 0, "SAMPLE_GRID", SampleGrid, "Sample Grid", "")
DefNode(GeometryNode, GEO_NODE_SAMPLE_INDEX, def_geo_sample_index, "SAMPLE_INDEX", SampleIndex, "Sample Index", "Retrieve values from specific geometry elements")
DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST_SURFACE, 0, "SAMPLE_NEAREST_SURFACE", SampleNearestSurface, "Sample Nearest Surface", "Calculate the interpolated value of a mesh attribute on the closest point of its surface")
DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST, 0, "SAMPLE_NEAREST", SampleNearest, "Sample Nearest", "Find the element of a geometry closest to a position. Similar to the \"Index of Nearest\" node")

View File

@ -108,7 +108,9 @@ static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams &para
/* Convert mesh to grid and add to volume. */
geometry::fog_volume_grid_add_from_mesh(volume,
"density",
&mesh,
mesh.vert_positions(),
mesh.corner_verts(),
mesh.corner_tris(),
mesh_to_volume_space_transform,
voxel_size,
interior_band_width,

View File

@ -88,8 +88,7 @@ static void convert_to_grid_index_space(const float voxel_size,
*/
static void initialize_volume_component_from_points(GeoNodeExecParams &params,
const NodeGeometryPointsToVolume &storage,
GeometrySet &r_geometry_set,
openvdb::GridClass gridClass)
GeometrySet &r_geometry_set)
{
Vector<float3> positions;
Vector<float> radii;
@ -131,15 +130,10 @@ static void initialize_volume_component_from_points(GeoNodeExecParams &params,
convert_to_grid_index_space(voxel_size, positions, radii);
if (gridClass == openvdb::GRID_FOG_VOLUME) {
const float density = params.get_input<float>("Density");
blender::geometry::fog_volume_grid_add_from_points(
volume, "density", positions, radii, voxel_size, density);
}
else if (gridClass == openvdb::GRID_LEVEL_SET) {
blender::geometry::sdf_volume_grid_add_from_points(
volume, "distance", positions, radii, voxel_size);
}
const float density = params.get_input<float>("Density");
blender::geometry::fog_volume_grid_add_from_points(
volume, "density", positions, radii, voxel_size, density);
r_geometry_set.keep_only_during_modify({GeometryComponent::Type::Volume});
r_geometry_set.replace_volume(volume);
}
@ -208,8 +202,7 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Points");
const NodeGeometryPointsToVolume &storage = node_storage(params.node());
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
initialize_volume_component_from_points(
params, storage, geometry_set, openvdb::GRID_FOG_VOLUME);
initialize_volume_component_from_points(params, storage, geometry_set);
});
params.set_output("Volume", std::move(geometry_set));
#else

View File

@ -34,8 +34,31 @@ static void node_declare(NodeDeclarationBuilder &b)
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
nodes::search_link_ops_for_basic_node(params);
if (!U.experimental.use_new_volume_nodes) {
return;
}
params.add_item(IFACE_("Volume"), [](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeStoreNamedGrid");
params.update_and_connect_available_socket(node, "Volume");
});
if (params.in_out() == SOCK_IN) {
if (params.other_socket().type == SOCK_STRING) {
params.add_item(IFACE_("Name"), [](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeStoreNamedGrid");
params.update_and_connect_available_socket(node, "Name");
});
}
if (const std::optional<eCustomDataType> data_type = bke::socket_type_to_custom_data_type(
eNodeSocketDatatype(params.other_socket().type)))
{
if (grid_type_supported(*data_type)) {
params.add_item(IFACE_("Grid"), [data_type](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeStoreNamedGrid");
node.custom1 = *data_type;
params.update_and_connect_available_socket(node, "Grid");
});
}
}
}
}