diff options
Diffstat (limited to 'source/blender/io')
47 files changed, 322 insertions, 188 deletions
diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h index 9785f6d68ab..5664a43233a 100644 --- a/source/blender/io/alembic/ABC_alembic.h +++ b/source/blender/io/alembic/ABC_alembic.h @@ -49,6 +49,7 @@ struct AlembicExportParams { bool uvs; bool normals; bool vcolors; + bool orcos; bool apply_subdiv; bool curves_as_mesh; bool flatten_hierarchy; diff --git a/source/blender/io/alembic/exporter/abc_custom_props.cc b/source/blender/io/alembic/exporter/abc_custom_props.cc index 382afdc294d..f5593e7ee30 100644 --- a/source/blender/io/alembic/exporter/abc_custom_props.cc +++ b/source/blender/io/alembic/exporter/abc_custom_props.cc @@ -51,10 +51,6 @@ CustomPropertiesExporter::CustomPropertiesExporter(ABCAbstractWriter *owner) : o { } -CustomPropertiesExporter::~CustomPropertiesExporter() -{ -} - void CustomPropertiesExporter::write_all(const IDProperty *group) { if (group == nullptr) { diff --git a/source/blender/io/alembic/exporter/abc_custom_props.h b/source/blender/io/alembic/exporter/abc_custom_props.h index d3f9b2fc43c..fcd47382d96 100644 --- a/source/blender/io/alembic/exporter/abc_custom_props.h +++ b/source/blender/io/alembic/exporter/abc_custom_props.h @@ -61,7 +61,7 @@ class CustomPropertiesExporter { public: CustomPropertiesExporter(ABCAbstractWriter *owner); - virtual ~CustomPropertiesExporter(); + virtual ~CustomPropertiesExporter() = default; void write_all(const IDProperty *group); diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.cc b/source/blender/io/alembic/exporter/abc_writer_abstract.cc index e99048cc0ee..27b5c2fa2a4 100644 --- a/source/blender/io/alembic/exporter/abc_writer_abstract.cc +++ b/source/blender/io/alembic/exporter/abc_writer_abstract.cc @@ -45,10 +45,6 @@ ABCAbstractWriter::ABCAbstractWriter(const ABCWriterConstructorArgs &args) { } -ABCAbstractWriter::~ABCAbstractWriter() -{ -} - bool ABCAbstractWriter::is_supported(const HierarchyContext * /*context*/) const { return true; diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.h b/source/blender/io/alembic/exporter/abc_writer_abstract.h index 4997e498199..d3500394555 100644 --- a/source/blender/io/alembic/exporter/abc_writer_abstract.h +++ b/source/blender/io/alembic/exporter/abc_writer_abstract.h @@ -50,7 +50,6 @@ class ABCAbstractWriter : public AbstractHierarchyWriter { public: explicit ABCAbstractWriter(const ABCWriterConstructorArgs &args); - virtual ~ABCAbstractWriter(); virtual void write(HierarchyContext &context) override; diff --git a/source/blender/io/alembic/exporter/abc_writer_instance.cc b/source/blender/io/alembic/exporter/abc_writer_instance.cc index 7f3b044cb8b..1737e8c091e 100644 --- a/source/blender/io/alembic/exporter/abc_writer_instance.cc +++ b/source/blender/io/alembic/exporter/abc_writer_instance.cc @@ -35,10 +35,6 @@ ABCInstanceWriter::ABCInstanceWriter(const ABCWriterConstructorArgs &args) { } -ABCInstanceWriter::~ABCInstanceWriter() -{ -} - void ABCInstanceWriter::create_alembic_objects(const HierarchyContext *context) { OObject original = args_.hierarchy_iterator->get_alembic_object(context->original_export_path); diff --git a/source/blender/io/alembic/exporter/abc_writer_instance.h b/source/blender/io/alembic/exporter/abc_writer_instance.h index f7d6450055a..1e4285d5e02 100644 --- a/source/blender/io/alembic/exporter/abc_writer_instance.h +++ b/source/blender/io/alembic/exporter/abc_writer_instance.h @@ -31,7 +31,6 @@ namespace blender::io::alembic { class ABCInstanceWriter : public ABCAbstractWriter { public: explicit ABCInstanceWriter(const ABCWriterConstructorArgs &args); - virtual ~ABCInstanceWriter(); virtual void create_alembic_objects(const HierarchyContext *context) override; virtual Alembic::Abc::OObject get_alembic_object() const override; diff --git a/source/blender/io/alembic/exporter/abc_writer_mball.cc b/source/blender/io/alembic/exporter/abc_writer_mball.cc index a797310f864..ad78f8ce802 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mball.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mball.cc @@ -69,7 +69,7 @@ Mesh *ABCMetaballWriter::get_export_mesh(Object *object_eval, bool &r_needsfree) return mesh_eval; } r_needsfree = true; - return BKE_mesh_new_from_object(args_.depsgraph, object_eval, false); + return BKE_mesh_new_from_object(args_.depsgraph, object_eval, false, false); } void ABCMetaballWriter::free_export_mesh(Mesh *mesh) diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index fbc662113cc..fd7db005dd2 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -113,10 +113,6 @@ void ABCGenericMeshWriter::create_alembic_objects(const HierarchyContext *contex liquid_sim_modifier_ = get_liquid_sim_modifier(scene_eval, context->object); } -ABCGenericMeshWriter::~ABCGenericMeshWriter() -{ -} - Alembic::Abc::OObject ABCGenericMeshWriter::get_alembic_object() const { if (is_subd_) { @@ -204,6 +200,7 @@ void ABCGenericMeshWriter::do_write(HierarchyContext &context) } m_custom_data_config.pack_uvs = args_.export_params->packuv; + m_custom_data_config.mesh = mesh; m_custom_data_config.mpoly = mesh->mpoly; m_custom_data_config.mloop = mesh->mloop; m_custom_data_config.totpoly = mesh->totpoly; @@ -254,7 +251,7 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) UVSample uvs_and_indices; - if (!frame_has_been_written_ && args_.export_params->uvs) { + if (args_.export_params->uvs) { const char *name = get_uv_sample(uvs_and_indices, m_custom_data_config, &mesh->ldata); if (!uvs_and_indices.indices.empty() && !uvs_and_indices.uvs.empty()) { @@ -283,6 +280,10 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) mesh_sample.setNormals(normals_sample); } + if (args_.export_params->orcos) { + write_generated_coordinates(abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config); + } + if (liquid_sim_modifier_ != nullptr) { get_velocities(mesh, velocities); mesh_sample.setVelocities(V3fArraySample(velocities)); @@ -316,7 +317,7 @@ void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *me V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts)); UVSample sample; - if (!frame_has_been_written_ && args_.export_params->uvs) { + if (args_.export_params->uvs) { const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata); if (!sample.indices.empty() && !sample.uvs.empty()) { @@ -333,6 +334,10 @@ void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *me abc_subdiv_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV); } + if (args_.export_params->orcos) { + write_generated_coordinates(abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config); + } + if (!crease_indices.empty()) { subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices)); subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths)); diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.h b/source/blender/io/alembic/exporter/abc_writer_mesh.h index ed4fb4e4514..0e1792b9dab 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.h +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.h @@ -51,7 +51,6 @@ class ABCGenericMeshWriter : public ABCAbstractWriter { public: explicit ABCGenericMeshWriter(const ABCWriterConstructorArgs &args); - virtual ~ABCGenericMeshWriter(); virtual void create_alembic_objects(const HierarchyContext *context) override; virtual Alembic::Abc::OObject get_alembic_object() const override; diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index 66e05504303..ccf353595c9 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -22,12 +22,14 @@ */ #include "abc_customdata.h" +#include "abc_axis_conversion.h" #include <Alembic/AbcGeom/All.h> #include <algorithm> #include <unordered_map> #include "DNA_customdata_types.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "BLI_math_base.h" @@ -50,8 +52,13 @@ using Alembic::Abc::V2fArraySample; using Alembic::AbcGeom::OC4fGeomParam; using Alembic::AbcGeom::OV2fGeomParam; +using Alembic::AbcGeom::OV3fGeomParam; namespace blender::io::alembic { +/* ORCO, Generated Coordinates, and Reference Points ("Pref") are all terms for the same thing. + * Other applications (Maya, Houdini) write these to a property called "Pref". */ +static const std::string propNameOriginalCoordinates("Pref"); + static void get_uvs(const CDStreamConfig &config, std::vector<Imath::V2f> &uvs, std::vector<uint32_t> &uvidx, @@ -222,6 +229,32 @@ static void write_mcol(const OCompoundProperty &prop, param.set(sample); } +void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config) +{ + const void *customdata = CustomData_get_layer(&config.mesh->vdata, CD_ORCO); + if (customdata == nullptr) { + /* Data not available, so don't even bother creating an Alembic property for it. */ + return; + } + const float(*orcodata)[3] = static_cast<const float(*)[3]>(customdata); + + /* Convert 3D vertices from float[3] z=up to V3f y=up. */ + std::vector<Imath::V3f> coords(config.totvert); + float orco_yup[3]; + for (int vertex_idx = 0; vertex_idx < config.totvert; vertex_idx++) { + copy_yup_from_zup(orco_yup, orcodata[vertex_idx]); + coords[vertex_idx].setValue(orco_yup[0], orco_yup[1], orco_yup[2]); + } + + if (!config.abc_ocro.valid()) { + /* Create the Alembic property and keep a reference so future frames can reuse it. */ + config.abc_ocro = OV3fGeomParam(prop, propNameOriginalCoordinates, false, kVertexScope, 1); + } + + OV3fGeomParam::Sample sample(coords, kVertexScope); + config.abc_ocro.set(sample); +} + void write_custom_data(const OCompoundProperty &prop, CDStreamConfig &config, CustomData *data, @@ -263,6 +296,7 @@ using Alembic::Abc::PropertyHeader; using Alembic::AbcGeom::IC3fGeomParam; using Alembic::AbcGeom::IC4fGeomParam; using Alembic::AbcGeom::IV2fGeomParam; +using Alembic::AbcGeom::IV3fGeomParam; static void read_uvs(const CDStreamConfig &config, void *data, @@ -448,6 +482,44 @@ static void read_custom_data_uvs(const ICompoundProperty &prop, read_uvs(config, cd_data, sample.getVals(), sample.getIndices()); } +void read_generated_coordinates(const ICompoundProperty &prop, + const CDStreamConfig &config, + const Alembic::Abc::ISampleSelector &iss) +{ + if (prop.getPropertyHeader(propNameOriginalCoordinates) == nullptr) { + /* The ORCO property isn't there, so don't bother trying to process it. */ + return; + } + + IV3fGeomParam param(prop, propNameOriginalCoordinates); + if (!param.valid() || param.isIndexed()) { + /* Invalid or indexed coordinates aren't supported. */ + return; + } + if (param.getScope() != kVertexScope) { + /* These are original vertex coordinates, so must be vertex-scoped. */ + return; + } + + IV3fGeomParam::Sample sample = param.getExpandedValue(iss); + Alembic::AbcGeom::V3fArraySamplePtr abc_ocro = sample.getVals(); + const size_t totvert = abc_ocro.get()->size(); + + void *cd_data; + if (CustomData_has_layer(&config.mesh->vdata, CD_ORCO)) { + cd_data = CustomData_get_layer(&config.mesh->vdata, CD_ORCO); + } + else { + cd_data = CustomData_add_layer(&config.mesh->vdata, CD_ORCO, CD_CALLOC, nullptr, totvert); + } + + float(*orcodata)[3] = static_cast<float(*)[3]>(cd_data); + for (int vertex_idx = 0; vertex_idx < totvert; ++vertex_idx) { + const Imath::V3f &abc_coords = (*abc_ocro)[vertex_idx]; + copy_zup_from_yup(orcodata[vertex_idx], abc_coords.getValue()); + } +} + void read_custom_data(const std::string &iobject_full_name, const ICompoundProperty &prop, const CDStreamConfig &config, diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index 4eb515f132c..9ee964c0545 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -72,12 +72,16 @@ struct CDStreamConfig { const char **modifier_error_message; - /* Alembic needs Blender to keep references to C++ objects (the destructors - * finalize the writing to ABC). This map stores OV2fGeomParam objects for the - * 2nd and subsequent UV maps; the primary UV map is kept alive by the Alembic - * mesh sample itself. */ + /* Alembic needs Blender to keep references to C++ objects (the destructors finalize the writing + * to ABC). The following fields are all used to keep these references. */ + + /* Mapping from UV map name to its ABC property, for the 2nd and subsequent UV maps; the primary + * UV map is kept alive by the Alembic mesh sample itself. */ std::map<std::string, Alembic::AbcGeom::OV2fGeomParam> abc_uv_maps; + /* OCRO coordinates, aka Generated Coordinates. */ + Alembic::AbcGeom::OV3fGeomParam abc_ocro; + CDStreamConfig() : mloop(NULL), totloop(0), @@ -102,6 +106,12 @@ struct CDStreamConfig { * For now the active layer is used, maybe needs a better way to choose this. */ const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data); +void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config); + +void read_generated_coordinates(const ICompoundProperty &prop, + const CDStreamConfig &config, + const Alembic::Abc::ISampleSelector &iss); + void write_custom_data(const OCompoundProperty &prop, CDStreamConfig &config, CustomData *data, diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 8133f615080..11b6c1c18ca 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -439,6 +439,7 @@ static void read_mesh_sample(const std::string &iobject_full_name, if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { read_mverts(config, abc_mesh_data); + read_generated_coordinates(schema.getArbGeomParams(), config, selector); } if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { @@ -558,7 +559,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_nomain_to_mesh() */ /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ short autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); mesh->flag |= autosmooth; } @@ -868,7 +869,7 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, nullptr); if (read_mesh != mesh) { - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); } ISubDSchema::Sample sample; diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc index 5ca7022bb36..d428d98fdb9 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.cc +++ b/source/blender/io/alembic/intern/abc_reader_object.cc @@ -97,10 +97,6 @@ void AbcObjectReader::determine_inherits_xform() } } -AbcObjectReader::~AbcObjectReader() -{ -} - const IObject &AbcObjectReader::iobject() const { return m_iobject; diff --git a/source/blender/io/alembic/intern/abc_reader_object.h b/source/blender/io/alembic/intern/abc_reader_object.h index 8e00ed42777..dacdcf3f722 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.h +++ b/source/blender/io/alembic/intern/abc_reader_object.h @@ -100,7 +100,7 @@ class AbcObjectReader { public: explicit AbcObjectReader(const Alembic::Abc::IObject &object, ImportSettings &settings); - virtual ~AbcObjectReader(); + virtual ~AbcObjectReader() = default; const Alembic::Abc::IObject &iobject() const; diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 214b5207a96..beadfc98c74 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -817,6 +817,8 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia matNode.set_ambient(ef->getAmbient()); matNode.set_specular(ef->getSpecular()); matNode.set_reflective(ef->getReflective()); + + matNode.update_material_nodetree(); } /** diff --git a/source/blender/io/collada/ErrorHandler.cpp b/source/blender/io/collada/ErrorHandler.cpp index 844065e3ba3..86349e04ff6 100644 --- a/source/blender/io/collada/ErrorHandler.cpp +++ b/source/blender/io/collada/ErrorHandler.cpp @@ -36,11 +36,6 @@ ErrorHandler::ErrorHandler() : mError(false) } //-------------------------------------------------------------------- -ErrorHandler::~ErrorHandler() -{ -} - -//-------------------------------------------------------------------- bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) { /* This method must return false when Collada should continue. diff --git a/source/blender/io/collada/ErrorHandler.h b/source/blender/io/collada/ErrorHandler.h index 1da17dbed42..f5fa9a4ad91 100644 --- a/source/blender/io/collada/ErrorHandler.h +++ b/source/blender/io/collada/ErrorHandler.h @@ -34,8 +34,6 @@ class ErrorHandler : public COLLADASaxFWL::IErrorHandler { /** Constructor. */ ErrorHandler(); - /** Destructor. */ - virtual ~ErrorHandler(); /** handle any error thrown by the parser. */ bool virtual handleError(const COLLADASaxFWL::IError *error); /** True if there was an error during parsing. */ diff --git a/source/blender/io/collada/ExtraHandler.cpp b/source/blender/io/collada/ExtraHandler.cpp index 11cb75fb5e9..78785e9aead 100644 --- a/source/blender/io/collada/ExtraHandler.cpp +++ b/source/blender/io/collada/ExtraHandler.cpp @@ -30,10 +30,6 @@ ExtraHandler::ExtraHandler(DocumentImporter *dimp, AnimationImporter *aimp) this->aimp = aimp; } -ExtraHandler::~ExtraHandler() -{ -} - bool ExtraHandler::elementBegin(const char *elementName, const char **attributes) { /* \todo attribute handling for profile tags */ diff --git a/source/blender/io/collada/ExtraHandler.h b/source/blender/io/collada/ExtraHandler.h index 4b13aaca2aa..98e30318aad 100644 --- a/source/blender/io/collada/ExtraHandler.h +++ b/source/blender/io/collada/ExtraHandler.h @@ -40,9 +40,6 @@ class ExtraHandler : public COLLADASaxFWL::IExtraDataCallbackHandler { /** Constructor. */ ExtraHandler(DocumentImporter *dimp, AnimationImporter *aimp); - /** Destructor. */ - virtual ~ExtraHandler(); - /** Handle the beginning of an element. */ bool elementBegin(const char *elementName, const char **attributes); diff --git a/source/blender/io/collada/ExtraTags.cpp b/source/blender/io/collada/ExtraTags.cpp index 8c63a21f88a..f38b0d769d7 100644 --- a/source/blender/io/collada/ExtraTags.cpp +++ b/source/blender/io/collada/ExtraTags.cpp @@ -32,9 +32,7 @@ ExtraTags::ExtraTags(std::string profile) this->tags = std::map<std::string, std::string>(); } -ExtraTags::~ExtraTags() -{ -} +ExtraTags::~ExtraTags() = default; bool ExtraTags::isProfile(std::string profile) { diff --git a/source/blender/io/collada/Materials.cpp b/source/blender/io/collada/Materials.cpp index 6ba31599fcd..ac4c65464c8 100644 --- a/source/blender/io/collada/Materials.cpp +++ b/source/blender/io/collada/Materials.cpp @@ -25,8 +25,6 @@ MaterialNode::MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map shader_node = add_node(SH_NODE_BSDF_PRINCIPLED, 0, 300, ""); output_node = add_node(SH_NODE_OUTPUT_MATERIAL, 300, 300, ""); add_link(shader_node, 0, output_node, 0); - - ntreeUpdateTree(CTX_data_main(C), ntree); } } @@ -61,8 +59,6 @@ MaterialNode::MaterialNode(bContext *C, shader_node = add_node(SH_NODE_BSDF_PRINCIPLED, 0, 300, ""); output_node = add_node(SH_NODE_OUTPUT_MATERIAL, 300, 300, ""); add_link(shader_node, 0, output_node, 0); - - ntreeUpdateTree(CTX_data_main(C), ntree); #endif } @@ -109,6 +105,11 @@ bNodeTree *MaterialNode::prepare_material_nodetree() return ntree; } +void MaterialNode::update_material_nodetree() +{ + ntreeUpdateTree(CTX_data_main(mContext), ntree); +} + bNode *MaterialNode::add_node(int node_type, int locx, int locy, std::string label) { bNode *node = nodeAddStaticNode(mContext, ntree, node_type); @@ -132,6 +133,19 @@ void MaterialNode::add_link(bNode *from_node, int from_index, bNode *to_node, in nodeAddLink(ntree, from_node, from_socket, to_node, to_socket); } +void MaterialNode::add_link(bNode *from_node, + const char *from_label, + bNode *to_node, + const char *to_label) +{ + bNodeSocket *from_socket = nodeFindSocket(from_node, SOCK_OUT, from_label); + bNodeSocket *to_socket = nodeFindSocket(to_node, SOCK_IN, to_label); + + if (from_socket && to_socket) { + nodeAddLink(ntree, from_node, from_socket, to_node, to_socket); + } +} + void MaterialNode::set_reflectivity(COLLADAFW::FloatOrParam &val) { float reflectivity = val.getFloatValue(); @@ -217,22 +231,32 @@ void MaterialNode::set_alpha(COLLADAFW::EffectCommon::OpaqueMode mode, void MaterialNode::set_diffuse(COLLADAFW::ColorOrTexture &cot) { int locy = -300 * (node_map.size() - 2); - if (cot.isColor()) { - COLLADAFW::Color col = cot.getColor(); - bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Base Color"); - float *fcol = (float *)socket->default_value; - fcol[0] = material->r = col.getRed(); - fcol[1] = material->g = col.getGreen(); - fcol[2] = material->b = col.getBlue(); - fcol[3] = material->a = col.getAlpha(); - } - else if (cot.isTexture()) { + if (cot.isTexture()) { bNode *texture_node = add_texture_node(cot, -300, locy, "Base Color"); if (texture_node != nullptr) { add_link(texture_node, 0, shader_node, 0); } } + else { + bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Base Color"); + float *fcol = (float *)socket->default_value; + + if (cot.isColor()) { + COLLADAFW::Color col = cot.getColor(); + fcol[0] = material->r = col.getRed(); + fcol[1] = material->g = col.getGreen(); + fcol[2] = material->b = col.getBlue(); + fcol[3] = material->a = col.getAlpha(); + } + else { + /* no diffuse term = same as black */ + fcol[0] = material->r = 0.0f; + fcol[1] = material->g = 0.0f; + fcol[2] = material->b = 0.0f; + fcol[3] = material->a = 1.0f; + } + } } Image *MaterialNode::get_diffuse_image() @@ -325,7 +349,7 @@ void MaterialNode::set_emission(COLLADAFW::ColorOrTexture &cot) else if (cot.isTexture()) { bNode *texture_node = add_texture_node(cot, -300, locy, "Emission"); if (texture_node != nullptr) { - add_link(texture_node, 0, shader_node, 0); + add_link(texture_node, "Color", shader_node, "Emission"); } } @@ -362,18 +386,38 @@ void MaterialNode::set_opacity(COLLADAFW::ColorOrTexture &cot) void MaterialNode::set_specular(COLLADAFW::ColorOrTexture &cot) { + bool has_specularity = true; int locy = -300 * (node_map.size() - 2); if (cot.isColor()) { COLLADAFW::Color col = cot.getColor(); - bNode *node = add_node(SH_NODE_RGB, -300, locy, "Specular"); - set_color(node, col); - /* TODO: Connect node */ + + if (col.getRed() == 0 && col.getGreen() == 0 && col.getBlue() == 0) { + has_specularity = false; + } + else { + bNode *node = add_node(SH_NODE_RGB, -300, locy, "Specular"); + set_color(node, col); + /* TODO: Connect node */ + } } - /* texture */ else if (cot.isTexture()) { add_texture_node(cot, -300, locy, "Specular"); /* TODO: Connect node */ } + else { + /* no specular term) */ + has_specularity = false; + } + + if (!has_specularity) { + /* If specularity is black or not defined reset the Specular value to 0 + TODO: This is a solution only for a corner case. We must find a better + way to handle specularity in general. Also note that currently we + do not export specularity values, see EffectExporter::operator() + */ + bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Specular"); + ((bNodeSocketValueFloat *)socket->default_value)->value = 0.0f; + } } bNode *MaterialNode::add_texture_node(COLLADAFW::ColorOrTexture &cot, diff --git a/source/blender/io/collada/Materials.h b/source/blender/io/collada/Materials.h index f671a00758d..1886acb7a6a 100644 --- a/source/blender/io/collada/Materials.h +++ b/source/blender/io/collada/Materials.h @@ -48,6 +48,7 @@ class MaterialNode { bNodeTree *prepare_material_nodetree(); bNode *add_node(int node_type, int locx, int locy, std::string label); void add_link(bNode *from_node, int from_index, bNode *to_node, int to_index); + void add_link(bNode *from_node, const char *from_label, bNode *to_node, const char *to_label); bNode *add_texture_node(COLLADAFW::ColorOrTexture &cot, int locx, int locy, std::string label); void setShaderType(); @@ -68,4 +69,6 @@ class MaterialNode { void set_alpha(COLLADAFW::EffectCommon::OpaqueMode mode, COLLADAFW::ColorOrTexture &cot, COLLADAFW::FloatOrParam &val); + + void update_material_nodetree(); }; diff --git a/source/blender/io/collada/SkinInfo.cpp b/source/blender/io/collada/SkinInfo.cpp index 8f6f1e467d9..12dee388a58 100644 --- a/source/blender/io/collada/SkinInfo.cpp +++ b/source/blender/io/collada/SkinInfo.cpp @@ -55,10 +55,7 @@ template<class T> static const char *bc_get_joint_name(T *node) /* This is used to store data passed in write_controller_data. * Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members * so that arrays don't get freed until we free them explicitly. */ -SkinInfo::SkinInfo() -{ - /* pass */ -} +SkinInfo::SkinInfo() = default; SkinInfo::SkinInfo(const SkinInfo &skin) : weights(skin.weights), diff --git a/source/blender/io/common/IO_abstract_hierarchy_iterator.h b/source/blender/io/common/IO_abstract_hierarchy_iterator.h index 300c555ac8f..0bebc4384a9 100644 --- a/source/blender/io/common/IO_abstract_hierarchy_iterator.h +++ b/source/blender/io/common/IO_abstract_hierarchy_iterator.h @@ -123,7 +123,7 @@ struct HierarchyContext { */ class AbstractHierarchyWriter { public: - virtual ~AbstractHierarchyWriter(); + virtual ~AbstractHierarchyWriter() = default; virtual void write(HierarchyContext &context) = 0; /* TODO(Sybren): add function like absent() that's called when a writer was previously created, * but wasn't used while exporting the current frame (for example, a particle-instanced mesh of @@ -186,9 +186,6 @@ class ObjectIdentifier { ObjectIdentifier(Object *object, Object *duplicated_by, const PersistentID &persistent_id); public: - ObjectIdentifier(const ObjectIdentifier &other); - ~ObjectIdentifier(); - static ObjectIdentifier for_graph_root(); static ObjectIdentifier for_real_object(Object *object); static ObjectIdentifier for_hierarchy_context(const HierarchyContext *context); diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc index a33d636500f..3cda4d125d0 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc @@ -137,10 +137,6 @@ AbstractHierarchyWriter *EnsuredWriter::operator->() return writer_; } -AbstractHierarchyWriter::~AbstractHierarchyWriter() -{ -} - bool AbstractHierarchyWriter::check_is_animated(const HierarchyContext &context) const { const Object *object = context.object; diff --git a/source/blender/io/common/intern/dupli_parent_finder.cc b/source/blender/io/common/intern/dupli_parent_finder.cc index 73e33eff164..221e70ed587 100644 --- a/source/blender/io/common/intern/dupli_parent_finder.cc +++ b/source/blender/io/common/intern/dupli_parent_finder.cc @@ -25,14 +25,6 @@ namespace blender::io { -DupliParentFinder::DupliParentFinder() -{ -} - -DupliParentFinder::~DupliParentFinder() -{ -} - void DupliParentFinder::insert(const DupliObject *dupli_ob) { dupli_set_.insert(dupli_ob->ob); diff --git a/source/blender/io/common/intern/dupli_parent_finder.hh b/source/blender/io/common/intern/dupli_parent_finder.hh index 3dcf037bb5e..b7632a72222 100644 --- a/source/blender/io/common/intern/dupli_parent_finder.hh +++ b/source/blender/io/common/intern/dupli_parent_finder.hh @@ -43,9 +43,6 @@ class DupliParentFinder final { InstancerPIDToDuplisMap instancer_pid_to_duplis_; public: - DupliParentFinder(); - ~DupliParentFinder(); - void insert(const DupliObject *dupli_ob); bool is_duplicated(const Object *object) const; diff --git a/source/blender/io/common/intern/object_identifier.cc b/source/blender/io/common/intern/object_identifier.cc index 5d0b89b0630..2df1befcd69 100644 --- a/source/blender/io/common/intern/object_identifier.cc +++ b/source/blender/io/common/intern/object_identifier.cc @@ -35,15 +35,6 @@ ObjectIdentifier::ObjectIdentifier(Object *object, { } -ObjectIdentifier::ObjectIdentifier(const ObjectIdentifier &other) - : object(other.object), duplicated_by(other.duplicated_by), persistent_id(other.persistent_id) -{ -} - -ObjectIdentifier::~ObjectIdentifier() -{ -} - ObjectIdentifier ObjectIdentifier::for_real_object(Object *object) { return ObjectIdentifier(object, nullptr, PersistentID()); diff --git a/source/blender/io/gpencil/CMakeLists.txt b/source/blender/io/gpencil/CMakeLists.txt index 11c9affbe5a..fec95be6aa8 100644 --- a/source/blender/io/gpencil/CMakeLists.txt +++ b/source/blender/io/gpencil/CMakeLists.txt @@ -39,22 +39,19 @@ set(INC_SYS ) set(SRC - intern/gpencil_io_capi.cc + intern/gpencil_io_base.cc + intern/gpencil_io_capi.cc + intern/gpencil_io_import_base.cc + intern/gpencil_io_import_svg.cc - # This line must be removed if NanoSVG is moved to extern - nanosvg/nanosvg.h + # This line must be removed if NanoSVG is moved to extern + nanosvg/nanosvg.h - gpencil_io.h - - intern/gpencil_io_base.h - intern/gpencil_io_base.cc - - intern/gpencil_io_import_base.h - intern/gpencil_io_import_svg.h - intern/gpencil_io_import_base.cc - intern/gpencil_io_import_svg.cc - - intern/gpencil_io_export_base.h + gpencil_io.h + intern/gpencil_io_base.hh + intern/gpencil_io_export_base.hh + intern/gpencil_io_import_base.hh + intern/gpencil_io_import_svg.hh ) set(LIB @@ -65,8 +62,9 @@ set(LIB if(WITH_PUGIXML) list(APPEND SRC - intern/gpencil_io_export_svg.h intern/gpencil_io_export_svg.cc + + intern/gpencil_io_export_svg.hh ) list(APPEND INC_SYS ${PUGIXML_INCLUDE_DIR} @@ -79,8 +77,9 @@ endif() if(WITH_HARU) list(APPEND SRC - intern/gpencil_io_export_pdf.h intern/gpencil_io_export_pdf.cc + + intern/gpencil_io_export_pdf.hh ) list(APPEND INC_SYS ${HARU_INCLUDE_DIRS} diff --git a/source/blender/io/gpencil/gpencil_io.h b/source/blender/io/gpencil/gpencil_io.h index f4b2e59f8c5..24b13479359 100644 --- a/source/blender/io/gpencil/gpencil_io.h +++ b/source/blender/io/gpencil/gpencil_io.h @@ -78,7 +78,7 @@ typedef enum eGpencilExportSelect { GP_EXPORT_VISIBLE = 2, } eGpencilExportSelect; -/* Framerange to be exported. */ +/** Frame-range to be exported. */ typedef enum eGpencilExportFrame { GP_EXPORT_FRAME_ACTIVE = 0, GP_EXPORT_FRAME_SELECTED = 1, diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc index 855252e648c..a2c1b8f5af6 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc @@ -41,6 +41,7 @@ #include "BKE_gpencil_geom.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_scene.h" #include "UI_view2d.h" @@ -49,7 +50,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" -#include "gpencil_io_base.h" +#include "gpencil_io_base.hh" using blender::Span; @@ -69,7 +70,21 @@ GpencilIO::GpencilIO(const GpencilIOParams *iparams) cfra_ = iparams->frame_cur; /* Calculate camera matrix. */ - Object *cam_ob = params_.v3d->camera; + prepare_camera_params(scene_, iparams); +} + +void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *iparams) +{ + params_ = *iparams; + const bool is_pdf = params_.mode == GP_EXPORT_TO_PDF; + const bool any_camera = (params_.v3d->camera != nullptr); + const bool force_camera_view = is_pdf && any_camera; + + /* Ensure camera switch is applied. */ + BKE_scene_camera_switch_update(scene); + + /* Calculate camera matrix. */ + Object *cam_ob = scene->camera; if (cam_ob != nullptr) { /* Set up parameters. */ CameraParams params; @@ -85,16 +100,18 @@ GpencilIO::GpencilIO(const GpencilIOParams *iparams) invert_m4_m4(viewmat, cam_ob->obmat); mul_m4_m4m4(persmat_, params.winmat, viewmat); + is_ortho_ = params.is_ortho; } else { unit_m4(persmat_); + is_ortho_ = false; } winx_ = params_.region->winx; winy_ = params_.region->winy; /* Camera rectangle. */ - if (rv3d_->persp == RV3D_CAMOB) { + if ((rv3d_->persp == RV3D_CAMOB) || (force_camera_view)) { render_x_ = (scene_->r.xsch * scene_->r.size) / 100; render_y_ = (scene_->r.ysch * scene_->r.size) / 100; @@ -112,11 +129,14 @@ GpencilIO::GpencilIO(const GpencilIOParams *iparams) } else { is_camera_ = false; + is_ortho_ = false; /* Calc selected object boundbox. Need set initial value to some variables. */ camera_ratio_ = 1.0f; offset_.x = 0.0f; offset_.y = 0.0f; + create_object_list(); + selected_objects_boundbox_calc(); rctf boundbox; selected_objects_boundbox_get(&boundbox); @@ -228,13 +248,15 @@ bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co) } /** Convert to render space. */ -float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co) +float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho) { float3 parent_co = diff_mat_ * co; mul_m4_v3(persmat_, parent_co); - parent_co.x = parent_co.x / max_ff(FLT_MIN, parent_co[2]); - parent_co.y = parent_co.y / max_ff(FLT_MIN, parent_co[2]); + if (!is_ortho) { + parent_co.x = parent_co.x / max_ff(FLT_MIN, parent_co.z); + parent_co.y = parent_co.y / max_ff(FLT_MIN, parent_co.z); + } float2 r_co; r_co.x = (parent_co.x + 1.0f) / 2.0f * (float)render_x_; @@ -257,7 +279,7 @@ float2 GpencilIO::gpencil_3D_point_to_2D(const float3 co) { const bool is_camera = (bool)(rv3d_->persp == RV3D_CAMOB); if (is_camera) { - return gpencil_3D_point_to_render_space(co); + return gpencil_3D_point_to_render_space(co, is_orthographic()); } float2 result; gpencil_3D_point_to_screen_space(co, result); @@ -296,7 +318,7 @@ void GpencilIO::prepare_stroke_export_colors(Object *ob, bGPDstroke *gps) /* Stroke color. */ copy_v4_v4(stroke_color_, gp_style->stroke_rgba); - avg_opacity_ = 0; + avg_opacity_ = 0.0f; /* Get average vertex color and apply. */ float avg_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) { @@ -324,6 +346,11 @@ bool GpencilIO::is_camera_mode() return is_camera_; } +bool GpencilIO::is_orthographic() +{ + return is_ortho_; +} + /* Calculate selected strokes boundbox. */ void GpencilIO::selected_objects_boundbox_calc() { diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.h b/source/blender/io/gpencil/intern/gpencil_io_base.hh index 986221618b7..c3c6f1156bb 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.h +++ b/source/blender/io/gpencil/intern/gpencil_io_base.hh @@ -50,6 +50,7 @@ class GpencilIO { GpencilIO(const GpencilIOParams *iparams); void frame_number_set(const int value); + void prepare_camera_params(Scene *scene, const GpencilIOParams *iparams); protected: GpencilIOParams params_; @@ -87,13 +88,14 @@ class GpencilIO { /* Geometry functions. */ bool gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co); - float2 gpencil_3D_point_to_render_space(const float3 co); + float2 gpencil_3D_point_to_render_space(const float3 co, const bool is_ortho); float2 gpencil_3D_point_to_2D(const float3 co); float stroke_point_radius_get(struct bGPDlayer *gpl, struct bGPDstroke *gps); void create_object_list(); bool is_camera_mode(); + bool is_orthographic(); float stroke_average_opacity_get(); @@ -107,6 +109,7 @@ class GpencilIO { private: float avg_opacity_; bool is_camera_; + bool is_ortho_; rctf select_boundbox_; /* Camera matrix. */ diff --git a/source/blender/io/gpencil/intern/gpencil_io_capi.cc b/source/blender/io/gpencil/intern/gpencil_io_capi.cc index 231d23948ef..544c51e0b4f 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_capi.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_capi.cc @@ -21,7 +21,7 @@ * \ingroup bgpencil */ -#include <stdio.h> +#include <cstdio> #include "BLI_listbase.h" @@ -40,14 +40,14 @@ #include "../gpencil_io.h" #ifdef WITH_HARU -# include "gpencil_io_export_pdf.h" +# include "gpencil_io_export_pdf.hh" #endif #ifdef WITH_PUGIXML -# include "gpencil_io_export_svg.h" +# include "gpencil_io_export_svg.hh" #endif -#include "gpencil_io_import_svg.h" +#include "gpencil_io_import_svg.hh" #ifdef WITH_HARU using blender::io::gpencil::GpencilExporterPDF; @@ -121,6 +121,7 @@ static bool gpencil_io_export_pdf(Depsgraph *depsgraph, CFRA = i; BKE_scene_graph_update_for_newframe(depsgraph); + exporter->prepare_camera_params(scene, iparams); exporter->frame_number_set(i); exporter->add_newpage(); exporter->add_body(); @@ -129,9 +130,11 @@ static bool gpencil_io_export_pdf(Depsgraph *depsgraph, /* Back to original frame. */ exporter->frame_number_set(iparams->frame_cur); CFRA = iparams->frame_cur; + BKE_scene_camera_switch_update(scene); BKE_scene_graph_update_for_newframe(depsgraph); } else { + exporter->prepare_camera_params(scene, iparams); exporter->add_newpage(); exporter->add_body(); result = exporter->write(); @@ -144,6 +147,7 @@ static bool gpencil_io_export_pdf(Depsgraph *depsgraph, /* Export current frame in SVG. */ #ifdef WITH_PUGIXML static bool gpencil_io_export_frame_svg(GpencilExporterSVG *exporter, + Scene *scene, const GpencilIOParams *iparams, const bool newpage, const bool body, @@ -151,6 +155,8 @@ static bool gpencil_io_export_frame_svg(GpencilExporterSVG *exporter, { bool result = false; exporter->frame_number_set(iparams->frame_cur); + exporter->prepare_camera_params(scene, iparams); + if (newpage) { result |= exporter->add_newpage(); } @@ -185,7 +191,7 @@ bool gpencil_io_export(const char *filename, GpencilIOParams *iparams) #ifdef WITH_PUGIXML case GP_EXPORT_TO_SVG: { GpencilExporterSVG exporter = GpencilExporterSVG(filename, iparams); - return gpencil_io_export_frame_svg(&exporter, iparams, true, true, true); + return gpencil_io_export_frame_svg(&exporter, scene_, iparams, true, true, true); break; } #endif diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_base.h b/source/blender/io/gpencil/intern/gpencil_io_export_base.hh index 19a24a75fd2..ffb1c6ce262 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_base.h +++ b/source/blender/io/gpencil/intern/gpencil_io_export_base.hh @@ -21,7 +21,7 @@ /** \file * \ingroup bgpencil */ -#include "gpencil_io_base.h" +#include "gpencil_io_base.hh" namespace blender::io::gpencil { diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc index ba16d635c2d..0f90855dcb8 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc @@ -49,7 +49,7 @@ #include "UI_view2d.h" #include "gpencil_io.h" -#include "gpencil_io_export_pdf.h" +#include "gpencil_io_export_pdf.hh" namespace blender ::io ::gpencil { @@ -69,7 +69,6 @@ GpencilExporterPDF::GpencilExporterPDF(const char *filename, const GpencilIOPara pdf_ = nullptr; page_ = nullptr; - gstate_ = nullptr; } bool GpencilExporterPDF::new_document() @@ -169,16 +168,29 @@ void GpencilExporterPDF::export_gpencil_layers() if (!ED_gpencil_stroke_material_visible(ob, gps)) { continue; } - /* Duplicate the stroke to apply any layer thickness change. */ - bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false); - MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, - gps_duplicate->mat_nr + 1); + /* Skip invisible lines. */ + prepare_stroke_export_colors(ob, gps); + const float fill_opacity = fill_color_[3] * gpl->opacity; + const float stroke_opacity = stroke_color_[3] * stroke_average_opacity_get() * + gpl->opacity; + if ((fill_opacity < GPENCIL_ALPHA_OPACITY_THRESH) && + (stroke_opacity < GPENCIL_ALPHA_OPACITY_THRESH)) { + continue; + } + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); const bool is_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) && - (gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH)); + (gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) && + (stroke_opacity > GPENCIL_ALPHA_OPACITY_THRESH)); const bool is_fill = ((gp_style->flag & GP_MATERIAL_FILL_SHOW) && (gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH)); - prepare_stroke_export_colors(ob, gps_duplicate); + + if ((!is_stroke) && (!is_fill)) { + continue; + } + + /* Duplicate the stroke to apply any layer thickness change. */ + bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false); /* Apply layer thickness change. */ gps_duplicate->thickness += gpl->line_change; @@ -283,29 +295,35 @@ void GpencilExporterPDF::color_set(bGPDlayer *gpl, const bool do_fill) { const float fill_opacity = fill_color_[3] * gpl->opacity; const float stroke_opacity = stroke_color_[3] * stroke_average_opacity_get() * gpl->opacity; + const bool need_state = (do_fill && fill_opacity < 1.0f) || (stroke_opacity < 1.0f); HPDF_Page_GSave(page_); - gstate_ = HPDF_CreateExtGState(pdf_); + HPDF_ExtGState gstate = (need_state) ? HPDF_CreateExtGState(pdf_) : nullptr; float col[3]; if (do_fill) { interp_v3_v3v3(col, fill_color_, gpl->tintcolor, gpl->tintcolor[3]); linearrgb_to_srgb_v3_v3(col, col); CLAMP3(col, 0.0f, 1.0f); - - HPDF_ExtGState_SetAlphaFill(gstate_, clamp_f(fill_opacity, 0.0f, 1.0f)); HPDF_Page_SetRGBFill(page_, col[0], col[1], col[2]); + if (gstate) { + HPDF_ExtGState_SetAlphaFill(gstate, clamp_f(fill_opacity, 0.0f, 1.0f)); + } } else { interp_v3_v3v3(col, stroke_color_, gpl->tintcolor, gpl->tintcolor[3]); linearrgb_to_srgb_v3_v3(col, col); CLAMP3(col, 0.0f, 1.0f); - HPDF_ExtGState_SetAlphaFill(gstate_, clamp_f(stroke_opacity, 0.0f, 1.0f)); - HPDF_ExtGState_SetAlphaStroke(gstate_, clamp_f(stroke_opacity, 0.0f, 1.0f)); HPDF_Page_SetRGBFill(page_, col[0], col[1], col[2]); HPDF_Page_SetRGBStroke(page_, col[0], col[1], col[2]); + if (gstate) { + HPDF_ExtGState_SetAlphaFill(gstate, clamp_f(stroke_opacity, 0.0f, 1.0f)); + HPDF_ExtGState_SetAlphaStroke(gstate, clamp_f(stroke_opacity, 0.0f, 1.0f)); + } + } + if (gstate) { + HPDF_Page_SetExtGState(page_, gstate); } - HPDF_Page_SetExtGState(page_, gstate_); } } // namespace blender::io::gpencil diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.h b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.hh index 009c05a8b49..89d97f79783 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.h +++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.hh @@ -22,7 +22,7 @@ * \ingroup bgpencil */ -#include "gpencil_io_export_base.h" +#include "gpencil_io_export_base.hh" #include "hpdf.h" struct GpencilIOParams; @@ -49,8 +49,6 @@ class GpencilExporterPDF : public GpencilExporter { HPDF_Doc pdf_; /* PDF page. */ HPDF_Page page_; - /* State. */ - HPDF_ExtGState gstate_; bool create_document(); bool add_page(); diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc index 89584cd242f..c62764cca06 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc @@ -49,7 +49,7 @@ #include "UI_view2d.h" #include "gpencil_io.h" -#include "gpencil_io_export_svg.h" +#include "gpencil_io_export_svg.hh" #include "pugixml.hpp" @@ -119,6 +119,7 @@ void GpencilExporterSVG::create_document_header() main_node_.append_attribute("version").set_value("1.0"); main_node_.append_attribute("x").set_value("0px"); main_node_.append_attribute("y").set_value("0px"); + main_node_.append_attribute("xmlns").set_value("http://www.w3.org/2000/svg"); std::string width; std::string height; @@ -396,7 +397,7 @@ void GpencilExporterSVG::color_string_set(bGPDlayer *gpl, * \param node: Parent node * \param x: X location * \param y: Y location - * \param width: width of the recntagle + * \param width: width of the rectangle * \param height: Height of the rectangle * \param thickness: Thickness of the line * \param hexcolor: Color of the line @@ -427,7 +428,7 @@ void GpencilExporterSVG::add_rect(pugi::xml_node node, * \param x: X location * \param y: Y location * \param text: Text to include - * \param size: Size of th etext + * \param size: Size of the text * \param hexcolor: Color of the text */ void GpencilExporterSVG::add_text(pugi::xml_node node, @@ -448,7 +449,7 @@ void GpencilExporterSVG::add_text(pugi::xml_node node, } /** Convert a color to Hex value (#FFFFFF). */ -std::string GpencilExporterSVG::rgb_to_hexstr(float color[3]) +std::string GpencilExporterSVG::rgb_to_hexstr(const float color[3]) { uint8_t r = color[0] * 255.0f; uint8_t g = color[1] * 255.0f; diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.h b/source/blender/io/gpencil/intern/gpencil_io_export_svg.hh index f564736c16e..3bff31f20bf 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.h +++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.hh @@ -23,7 +23,7 @@ */ #include "BLI_path_util.h" -#include "gpencil_io_export_base.h" +#include "gpencil_io_export_base.hh" #include "pugixml.hpp" struct GpencilIOParams; @@ -70,20 +70,20 @@ class GpencilExporterSVG : public GpencilExporter { void export_stroke_to_path(struct bGPDlayer *gpl, struct bGPDstroke *gps, pugi::xml_node node_gpl, - const bool is_fill); + const bool do_fill); void export_stroke_to_polyline(struct bGPDlayer *gpl, struct bGPDstroke *gps, pugi::xml_node node_gpl, const bool is_stroke, - const bool is_fill); + const bool do_fill); void color_string_set(struct bGPDlayer *gpl, struct bGPDstroke *gps, pugi::xml_node node_gps, - const bool is_fill); + const bool do_fill); - std::string rgb_to_hexstr(float color[3]); + std::string rgb_to_hexstr(const float color[3]); }; } // namespace blender::io::gpencil diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_base.cc b/source/blender/io/gpencil/intern/gpencil_io_import_base.cc index 2e7cfdeb5cd..d0b6e20bda2 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_base.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_import_base.cc @@ -33,7 +33,7 @@ #include "ED_gpencil.h" -#include "gpencil_io_import_base.h" +#include "gpencil_io_import_base.hh" namespace blender::io::gpencil { diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_base.h b/source/blender/io/gpencil/intern/gpencil_io_import_base.hh index efe6264e4e9..7d6fad2340b 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_base.h +++ b/source/blender/io/gpencil/intern/gpencil_io_import_base.hh @@ -21,7 +21,7 @@ /** \file * \ingroup bgpencil */ -#include "gpencil_io_base.h" +#include "gpencil_io_base.hh" namespace blender::io::gpencil { diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc index 7f450477ac2..52fcc017ffb 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc @@ -36,7 +36,7 @@ #include "ED_gpencil.h" #include "gpencil_io.h" -#include "gpencil_io_import_svg.h" +#include "gpencil_io_import_svg.hh" /* Custom flags for NanoSVG. */ #define NANOSVG_ALL_COLOR_KEYWORDS @@ -69,9 +69,7 @@ bool GpencilImporterSVG::read() params_.ob = create_object(); if (params_.ob == nullptr) { std::cout << "Unable to create new object.\n"; - if (svg_data) { - nsvgDelete(svg_data); - } + nsvgDelete(svg_data); return false; } @@ -102,7 +100,7 @@ bool GpencilImporterSVG::read() bGPDlayer *gpl = (bGPDlayer *)BLI_findstring( &gpd_->layers, layer_id, offsetof(bGPDlayer, info)); if (gpl == nullptr) { - gpl = BKE_gpencil_layer_addnew(gpd_, layer_id, true); + gpl = BKE_gpencil_layer_addnew(gpd_, layer_id, true, false); /* Disable lights. */ gpl->flag &= ~GP_LAYER_USE_LIGHTS; } @@ -118,15 +116,17 @@ bool GpencilImporterSVG::read() } /* Create_shape materials. */ - const char *const mat_names[] = {"Stroke", "Fill"}; + const char *const mat_names[] = {"Stroke", "Fill", "Both"}; int index = 0; - if ((is_stroke) && (is_fill)) { + if ((is_stroke) && (!is_fill)) { index = 0; - is_fill = false; } else if ((!is_stroke) && (is_fill)) { index = 1; } + else if ((is_stroke) && (is_fill)) { + index = 2; + } int32_t mat_index = create_material(mat_names[index], is_stroke, is_fill); /* Loop all paths to create the stroke data. */ @@ -196,10 +196,10 @@ void GpencilImporterSVG::create_stroke(bGPdata *gpd, pt->strength = shape->opacity; pt->pressure = 1.0f; pt->z = 0.0f; - /* TODO: (antoniov) Can be improved loading curve data instead of loading strokes. */ + /* TODO(antoniov): Can be improved loading curve data instead of loading strokes. */ interp_v2_v2v2v2v2_cubic(&pt->x, &p[0], &p[2], &p[4], &p[6], a); - /* Scale from milimeters. */ + /* Scale from millimeters. */ mul_v3_fl(&pt->x, 0.001f); mul_m4_v3(matrix, &pt->x); diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.h b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh index 6a34ec8423b..0e9271dd2c6 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_svg.h +++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.hh @@ -21,7 +21,7 @@ /** \file * \ingroup bgpencil */ -#include "gpencil_io_import_base.h" +#include "gpencil_io_import_base.hh" struct GpencilIOParams; struct NSVGshape; diff --git a/source/blender/io/gpencil/nanosvg/nanosvg.h b/source/blender/io/gpencil/nanosvg/nanosvg.h index 1009d684f7c..94dad37861a 100644 --- a/source/blender/io/gpencil/nanosvg/nanosvg.h +++ b/source/blender/io/gpencil/nanosvg/nanosvg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-14 Mikko Mononen memon@inside.org + * Copyright (c) 2013-14 `Mikko Mononen <memon@inside.org>` * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages @@ -459,9 +459,9 @@ typedef struct NSVGparser { float dpi; char pathFlag; char defsFlag; - /** Blender breadscrum for layers. */ + /** Blender breadcrumb for layers. */ char breadcrumb[NSVG_MAX_BREADCRUMB][64]; - /** Blender number of elements in breadscrum. */ + /** Blender number of elements in breadcrumb. */ int breadcrumb_len; } NSVGparser; @@ -1289,7 +1289,7 @@ static const char *nsvg__parseNumber(const char *s, char *it, const int size) return s; } -static const char *nsvg__getNextPathItem(const char *s, char *it) +static const char *nsvg__getNextPathItem(const char *s, char *it, char cmd, int nargs) { it[0] = '\0'; // Skip white spaces and commas @@ -1297,6 +1297,15 @@ static const char *nsvg__getNextPathItem(const char *s, char *it) s++; if (!*s) return s; + + /* Blender: Special case for arc command's 4th and 5th arguments. */ + if (ELEM(cmd, 'a', 'A') && ELEM(nargs, 3, 4)) { + it[0] = s[0]; + it[1] = '\0'; + s++; + return s; + } + if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) { s = nsvg__parseNumber(s, it, 64); } @@ -1576,8 +1585,8 @@ static int nsvg__isCoordinate(const char *s) // optional sign if (*s == '-' || *s == '+') s++; - // must have at least one digit - return nsvg__isdigit(*s); + // must have at least one digit, or start by a dot + return (nsvg__isdigit(*s) || *s == '.'); } static NSVGcoordinate nsvg__parseCoordinateRaw(const char *str) @@ -2353,7 +2362,12 @@ static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args, // The loop assumes an iteration per end point (including start and end), this +1. ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 1.0f); hda = (da / (float)ndivs) / 2.0f; - kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda)); + // Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite) + if ((hda < 1e-3f) && (hda > -1e-3f)) + hda *= 0.5f; + else + hda = (1.0f - cosf(hda)) / sinf(hda); + kappa = fabsf(4.0f / 3.0f * hda); if (da < 0.0f) kappa = -kappa; @@ -2413,7 +2427,7 @@ static void nsvg__parsePath(NSVGparser *p, const char **attr) nargs = 0; while (*s) { - s = nsvg__getNextPathItem(s, item); + s = nsvg__getNextPathItem(s, item, cmd, nargs); if (!*item) break; if (cmd != '\0' && nsvg__isCoordinate(item)) { @@ -2740,7 +2754,7 @@ static void nsvg__parsePoly(NSVGparser *p, const char **attr, int closeFlag) s = attr[i + 1]; nargs = 0; while (*s) { - s = nsvg__getNextPathItem(s, item); + s = nsvg__getNextPathItem(s, item, '\0', nargs); args[nargs++] = (float)nsvg__atof(item); if (nargs >= 2) { if (npts == 0) diff --git a/source/blender/io/usd/intern/usd_writer_abstract.cc b/source/blender/io/usd/intern/usd_writer_abstract.cc index 694fc76a446..5e66136abf1 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.cc +++ b/source/blender/io/usd/intern/usd_writer_abstract.cc @@ -41,10 +41,6 @@ USDAbstractWriter::USDAbstractWriter(const USDExporterContext &usd_export_contex { } -USDAbstractWriter::~USDAbstractWriter() -{ -} - bool USDAbstractWriter::is_supported(const HierarchyContext * /*context*/) const { return true; diff --git a/source/blender/io/usd/intern/usd_writer_abstract.h b/source/blender/io/usd/intern/usd_writer_abstract.h index 2143164e3dd..6f143a7e241 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.h +++ b/source/blender/io/usd/intern/usd_writer_abstract.h @@ -49,7 +49,6 @@ class USDAbstractWriter : public AbstractHierarchyWriter { public: USDAbstractWriter(const USDExporterContext &usd_export_context); - virtual ~USDAbstractWriter(); virtual void write(HierarchyContext &context) override; diff --git a/source/blender/io/usd/intern/usd_writer_metaball.cc b/source/blender/io/usd/intern/usd_writer_metaball.cc index 8e32bd4705a..28c96c3a511 100644 --- a/source/blender/io/usd/intern/usd_writer_metaball.cc +++ b/source/blender/io/usd/intern/usd_writer_metaball.cc @@ -62,7 +62,7 @@ Mesh *USDMetaballWriter::get_export_mesh(Object *object_eval, bool &r_needsfree) return mesh_eval; } r_needsfree = true; - return BKE_mesh_new_from_object(usd_export_context_.depsgraph, object_eval, false); + return BKE_mesh_new_from_object(usd_export_context_.depsgraph, object_eval, false, false); } void USDMetaballWriter::free_export_mesh(Mesh *mesh) |