diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2022-06-21 20:09:54 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2022-06-21 20:09:54 +0300 |
commit | dd6d0aefcc56288bfe154fe06df56163d6961372 (patch) | |
tree | 7b74c26bcd48d0fbd844fd8b286c9a399813b203 | |
parent | c27a395d8cd8b58b3155cfdc26ae35198fbcdb14 (diff) | |
parent | 714001683888770f9d870ba73edd65f4c2757bda (diff) |
Merge branch 'master' into asset-greasepencilasset-greasepencil
438 files changed, 6909 insertions, 4409 deletions
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index b63e86a3ac2..1cf63f2d332 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -57,7 +57,6 @@ include(cmake/alembic.cmake) include(cmake/opensubdiv.cmake) include(cmake/sdl.cmake) include(cmake/opencollada.cmake) -include(cmake/llvm.cmake) if(APPLE) include(cmake/openmp.cmake) endif() @@ -75,6 +74,7 @@ include(cmake/osl.cmake) include(cmake/tbb.cmake) include(cmake/openvdb.cmake) include(cmake/python.cmake) +include(cmake/llvm.cmake) option(USE_PIP_NUMPY "Install NumPy using pip wheel instead of building from source" OFF) if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")) set(USE_PIP_NUMPY ON) diff --git a/build_files/build_environment/cmake/ispc.cmake b/build_files/build_environment/cmake/ispc.cmake index 160088bc16f..86dc1d9efa8 100644 --- a/build_files/build_environment/cmake/ispc.cmake +++ b/build_files/build_environment/cmake/ispc.cmake @@ -6,6 +6,7 @@ if(WIN32) -DBISON_EXECUTABLE=${LIBDIR}/flexbison/win_bison.exe -DM4_EXECUTABLE=${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/m4.exe -DARM_ENABLED=Off + -DPython3_FIND_REGISTRY=NEVER ) elseif(APPLE) # Use bison and flex installed via Homebrew. @@ -43,6 +44,8 @@ set(ISPC_EXTRA_ARGS -DISPC_INCLUDE_TESTS=Off -DCLANG_LIBRARY_DIR=${LIBDIR}/llvm/lib -DCLANG_INCLUDE_DIRS=${LIBDIR}/llvm/include + -DPython3_ROOT_DIR=${LIBDIR}/python/ + -DPython3_EXECUTABLE=${PYTHON_BINARY} ${ISPC_EXTRA_ARGS_WIN} ${ISPC_EXTRA_ARGS_APPLE} ${ISPC_EXTRA_ARGS_UNIX} @@ -61,6 +64,7 @@ ExternalProject_Add(external_ispc add_dependencies( external_ispc ll + external_python ) if(WIN32) diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake index cf92a5175a3..df4cd8b71e9 100644 --- a/build_files/build_environment/cmake/llvm.cmake +++ b/build_files/build_environment/cmake/llvm.cmake @@ -25,11 +25,14 @@ set(LLVM_EXTRA_ARGS -DLLVM_BUILD_LLVM_C_DYLIB=OFF -DLLVM_ENABLE_UNWIND_TABLES=OFF -DLLVM_ENABLE_PROJECTS=clang${LLVM_BUILD_CLANG_TOOLS_EXTRA} + -DPython3_ROOT_DIR=${LIBDIR}/python/ + -DPython3_EXECUTABLE=${PYTHON_BINARY} ${LLVM_XML2_ARGS} ) if(WIN32) set(LLVM_GENERATOR "Ninja") + list(APPEND LLVM_EXTRA_ARGS -DPython3_FIND_REGISTRY=NEVER) else() set(LLVM_GENERATOR "Unix Makefiles") endif() @@ -74,3 +77,9 @@ if(APPLE) external_xml2 ) endif() + +add_dependencies( + ll + external_python +) + diff --git a/build_files/build_environment/cmake/openimagedenoise.cmake b/build_files/build_environment/cmake/openimagedenoise.cmake index 3612e91a690..14a730d69b6 100644 --- a/build_files/build_environment/cmake/openimagedenoise.cmake +++ b/build_files/build_environment/cmake/openimagedenoise.cmake @@ -9,6 +9,7 @@ set(OIDN_EXTRA_ARGS -DOIDN_STATIC_RUNTIME=OFF -DISPC_EXECUTABLE=${LIBDIR}/ispc/bin/ispc -DOIDN_FILTER_RTLIGHTMAP=OFF + -DPYTHON_EXECUTABLE=${PYTHON_BINARY} ) if(WIN32) @@ -38,6 +39,7 @@ add_dependencies( external_openimagedenoise external_tbb external_ispc + external_python ) if(WIN32) diff --git a/extern/draco/README.blender b/extern/draco/README.blender index b9c3bbb967d..a879ded978b 100644 --- a/extern/draco/README.blender +++ b/extern/draco/README.blender @@ -1,5 +1,5 @@ Project: Draco URL: https://google.github.io/draco/ License: Apache 2.0 -Upstream version: 1.3.6 -Local modifications: None +Upstream version: 1.5.2 +Local modifications: Apply patches/blender.patch diff --git a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc index 283a21251f4..51c3bb6c872 100644 --- a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc +++ b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc @@ -38,6 +38,46 @@ void AttributeOctahedronTransform::CopyToAttributeTransformData( out_data->AppendParameterValue(quantization_bits_); } +bool AttributeOctahedronTransform::TransformAttribute( + const PointAttribute &attribute, const std::vector<PointIndex> &point_ids, + PointAttribute *target_attribute) { + return GeneratePortableAttribute(attribute, point_ids, + target_attribute->size(), target_attribute); +} + +bool AttributeOctahedronTransform::InverseTransformAttribute( + const PointAttribute &attribute, PointAttribute *target_attribute) { + if (target_attribute->data_type() != DT_FLOAT32) { + return false; + } + + const int num_points = target_attribute->size(); + const int num_components = target_attribute->num_components(); + if (num_components != 3) { + return false; + } + constexpr int kEntrySize = sizeof(float) * 3; + float att_val[3]; + const int32_t *source_attribute_data = reinterpret_cast<const int32_t *>( + attribute.GetAddress(AttributeValueIndex(0))); + uint8_t *target_address = + target_attribute->GetAddress(AttributeValueIndex(0)); + OctahedronToolBox octahedron_tool_box; + if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_)) { + return false; + } + for (uint32_t i = 0; i < num_points; ++i) { + const int32_t s = *source_attribute_data++; + const int32_t t = *source_attribute_data++; + octahedron_tool_box.QuantizedOctahedralCoordsToUnitVector(s, t, att_val); + + // Store the decoded floating point values into the attribute buffer. + std::memcpy(target_address, att_val, kEntrySize); + target_address += kEntrySize; + } + return true; +} + void AttributeOctahedronTransform::SetParameters(int quantization_bits) { quantization_bits_ = quantization_bits; } @@ -51,38 +91,55 @@ bool AttributeOctahedronTransform::EncodeParameters( return false; } -std::unique_ptr<PointAttribute> -AttributeOctahedronTransform::GeneratePortableAttribute( +bool AttributeOctahedronTransform::DecodeParameters( + const PointAttribute &attribute, DecoderBuffer *decoder_buffer) { + uint8_t quantization_bits; + if (!decoder_buffer->Decode(&quantization_bits)) { + return false; + } + quantization_bits_ = quantization_bits; + return true; +} + +bool AttributeOctahedronTransform::GeneratePortableAttribute( const PointAttribute &attribute, const std::vector<PointIndex> &point_ids, - int num_points) const { + int num_points, PointAttribute *target_attribute) const { DRACO_DCHECK(is_initialized()); - // Allocate portable attribute. - const int num_entries = static_cast<int>(point_ids.size()); - std::unique_ptr<PointAttribute> portable_attribute = - InitPortableAttribute(num_entries, 2, num_points, attribute, true); - // Quantize all values in the order given by point_ids into portable // attribute. int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>( - portable_attribute->GetAddress(AttributeValueIndex(0))); + target_attribute->GetAddress(AttributeValueIndex(0))); float att_val[3]; int32_t dst_index = 0; OctahedronToolBox converter; if (!converter.SetQuantizationBits(quantization_bits_)) { - return nullptr; + return false; } - for (uint32_t i = 0; i < point_ids.size(); ++i) { - const AttributeValueIndex att_val_id = attribute.mapped_index(point_ids[i]); - attribute.GetValue(att_val_id, att_val); - // Encode the vector into a s and t octahedral coordinates. - int32_t s, t; - converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t); - portable_attribute_data[dst_index++] = s; - portable_attribute_data[dst_index++] = t; + if (!point_ids.empty()) { + for (uint32_t i = 0; i < point_ids.size(); ++i) { + const AttributeValueIndex att_val_id = + attribute.mapped_index(point_ids[i]); + attribute.GetValue(att_val_id, att_val); + // Encode the vector into a s and t octahedral coordinates. + int32_t s, t; + converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t); + portable_attribute_data[dst_index++] = s; + portable_attribute_data[dst_index++] = t; + } + } else { + for (PointIndex i(0); i < num_points; ++i) { + const AttributeValueIndex att_val_id = attribute.mapped_index(i); + attribute.GetValue(att_val_id, att_val); + // Encode the vector into a s and t octahedral coordinates. + int32_t s, t; + converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t); + portable_attribute_data[dst_index++] = s; + portable_attribute_data[dst_index++] = t; + } } - return portable_attribute; + return true; } } // namespace draco diff --git a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h index 6e4e74284f0..21a1725bb52 100644 --- a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h +++ b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h @@ -37,19 +37,40 @@ class AttributeOctahedronTransform : public AttributeTransform { void CopyToAttributeTransformData( AttributeTransformData *out_data) const override; + bool TransformAttribute(const PointAttribute &attribute, + const std::vector<PointIndex> &point_ids, + PointAttribute *target_attribute) override; + + bool InverseTransformAttribute(const PointAttribute &attribute, + PointAttribute *target_attribute) override; + // Set number of quantization bits. void SetParameters(int quantization_bits); // Encode relevant parameters into buffer. - bool EncodeParameters(EncoderBuffer *encoder_buffer) const; + bool EncodeParameters(EncoderBuffer *encoder_buffer) const override; + + bool DecodeParameters(const PointAttribute &attribute, + DecoderBuffer *decoder_buffer) override; bool is_initialized() const { return quantization_bits_ != -1; } int32_t quantization_bits() const { return quantization_bits_; } - // Create portable attribute. - std::unique_ptr<PointAttribute> GeneratePortableAttribute( - const PointAttribute &attribute, const std::vector<PointIndex> &point_ids, - int num_points) const; + protected: + DataType GetTransformedDataType( + const PointAttribute &attribute) const override { + return DT_UINT32; + } + int GetTransformedNumComponents( + const PointAttribute &attribute) const override { + return 2; + } + + // Perform the actual transformation. + bool GeneratePortableAttribute(const PointAttribute &attribute, + const std::vector<PointIndex> &point_ids, + int num_points, + PointAttribute *target_attribute) const; private: int32_t quantization_bits_; diff --git a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc index daa634ed03f..a7f93a488d7 100644 --- a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc +++ b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc @@ -1,4 +1,3 @@ - // Copyright 2017 The Draco Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -51,13 +50,74 @@ void AttributeQuantizationTransform::CopyToAttributeTransformData( out_data->AppendParameterValue(range_); } -void AttributeQuantizationTransform::SetParameters(int quantization_bits, +bool AttributeQuantizationTransform::TransformAttribute( + const PointAttribute &attribute, const std::vector<PointIndex> &point_ids, + PointAttribute *target_attribute) { + if (point_ids.empty()) { + GeneratePortableAttribute(attribute, target_attribute->size(), + target_attribute); + } else { + GeneratePortableAttribute(attribute, point_ids, target_attribute->size(), + target_attribute); + } + return true; +} + +bool AttributeQuantizationTransform::InverseTransformAttribute( + const PointAttribute &attribute, PointAttribute *target_attribute) { + if (target_attribute->data_type() != DT_FLOAT32) { + return false; + } + + // Convert all quantized values back to floats. + const int32_t max_quantized_value = + (1u << static_cast<uint32_t>(quantization_bits_)) - 1; + const int num_components = target_attribute->num_components(); + const int entry_size = sizeof(float) * num_components; + const std::unique_ptr<float[]> att_val(new float[num_components]); + int quant_val_id = 0; + int out_byte_pos = 0; + Dequantizer dequantizer; + if (!dequantizer.Init(range_, max_quantized_value)) { + return false; + } + const int32_t *const source_attribute_data = + reinterpret_cast<const int32_t *>( + attribute.GetAddress(AttributeValueIndex(0))); + + const int num_values = target_attribute->size(); + + for (uint32_t i = 0; i < num_values; ++i) { + for (int c = 0; c < num_components; ++c) { + float value = + dequantizer.DequantizeFloat(source_attribute_data[quant_val_id++]); + value = value + min_values_[c]; + att_val[c] = value; + } + // Store the floating point value into the attribute buffer. + target_attribute->buffer()->Write(out_byte_pos, att_val.get(), entry_size); + out_byte_pos += entry_size; + } + return true; +} + +bool AttributeQuantizationTransform::IsQuantizationValid( + int quantization_bits) { + // Currently we allow only up to 30 bit quantization. + return quantization_bits >= 1 && quantization_bits <= 30; +} + +bool AttributeQuantizationTransform::SetParameters(int quantization_bits, const float *min_values, int num_components, float range) { + if (!IsQuantizationValid(quantization_bits)) { + return false; + } quantization_bits_ = quantization_bits; min_values_.assign(min_values, min_values + num_components); range_ = range; + return true; } bool AttributeQuantizationTransform::ComputeParameters( @@ -65,6 +125,9 @@ bool AttributeQuantizationTransform::ComputeParameters( if (quantization_bits_ != -1) { return false; // already initialized. } + if (!IsQuantizationValid(quantization_bits)) { + return false; + } quantization_bits_ = quantization_bits; const int num_components = attribute.num_components(); @@ -121,20 +184,37 @@ bool AttributeQuantizationTransform::EncodeParameters( return false; } -std::unique_ptr<PointAttribute> -AttributeQuantizationTransform::GeneratePortableAttribute( - const PointAttribute &attribute, int num_points) const { +bool AttributeQuantizationTransform::DecodeParameters( + const PointAttribute &attribute, DecoderBuffer *decoder_buffer) { + min_values_.resize(attribute.num_components()); + if (!decoder_buffer->Decode(&min_values_[0], + sizeof(float) * min_values_.size())) { + return false; + } + if (!decoder_buffer->Decode(&range_)) { + return false; + } + uint8_t quantization_bits; + if (!decoder_buffer->Decode(&quantization_bits)) { + return false; + } + if (!IsQuantizationValid(quantization_bits)) { + return false; + } + quantization_bits_ = quantization_bits; + return true; +} + +void AttributeQuantizationTransform::GeneratePortableAttribute( + const PointAttribute &attribute, int num_points, + PointAttribute *target_attribute) const { DRACO_DCHECK(is_initialized()); - // Allocate portable attribute. - const int num_entries = num_points; const int num_components = attribute.num_components(); - std::unique_ptr<PointAttribute> portable_attribute = - InitPortableAttribute(num_entries, num_components, 0, attribute, true); // Quantize all values using the order given by point_ids. int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>( - portable_attribute->GetAddress(AttributeValueIndex(0))); + target_attribute->GetAddress(AttributeValueIndex(0))); const uint32_t max_quantized_value = (1 << (quantization_bits_)) - 1; Quantizer quantizer; quantizer.Init(range(), max_quantized_value); @@ -149,24 +229,18 @@ AttributeQuantizationTransform::GeneratePortableAttribute( portable_attribute_data[dst_index++] = q_val; } } - return portable_attribute; } -std::unique_ptr<PointAttribute> -AttributeQuantizationTransform::GeneratePortableAttribute( +void AttributeQuantizationTransform::GeneratePortableAttribute( const PointAttribute &attribute, const std::vector<PointIndex> &point_ids, - int num_points) const { + int num_points, PointAttribute *target_attribute) const { DRACO_DCHECK(is_initialized()); - // Allocate portable attribute. - const int num_entries = static_cast<int>(point_ids.size()); const int num_components = attribute.num_components(); - std::unique_ptr<PointAttribute> portable_attribute = InitPortableAttribute( - num_entries, num_components, num_points, attribute, true); // Quantize all values using the order given by point_ids. int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>( - portable_attribute->GetAddress(AttributeValueIndex(0))); + target_attribute->GetAddress(AttributeValueIndex(0))); const uint32_t max_quantized_value = (1 << (quantization_bits_)) - 1; Quantizer quantizer; quantizer.Init(range(), max_quantized_value); @@ -181,7 +255,6 @@ AttributeQuantizationTransform::GeneratePortableAttribute( portable_attribute_data[dst_index++] = q_val; } } - return portable_attribute; } } // namespace draco diff --git a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h index 934856f2db7..f1122b680ab 100644 --- a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h +++ b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h @@ -37,14 +37,24 @@ class AttributeQuantizationTransform : public AttributeTransform { void CopyToAttributeTransformData( AttributeTransformData *out_data) const override; - void SetParameters(int quantization_bits, const float *min_values, + bool TransformAttribute(const PointAttribute &attribute, + const std::vector<PointIndex> &point_ids, + PointAttribute *target_attribute) override; + + bool InverseTransformAttribute(const PointAttribute &attribute, + PointAttribute *target_attribute) override; + + bool SetParameters(int quantization_bits, const float *min_values, int num_components, float range); bool ComputeParameters(const PointAttribute &attribute, const int quantization_bits); // Encode relevant parameters into buffer. - bool EncodeParameters(EncoderBuffer *encoder_buffer) const; + bool EncodeParameters(EncoderBuffer *encoder_buffer) const override; + + bool DecodeParameters(const PointAttribute &attribute, + DecoderBuffer *decoder_buffer) override; int32_t quantization_bits() const { return quantization_bits_; } float min_value(int axis) const { return min_values_[axis]; } @@ -52,16 +62,30 @@ class AttributeQuantizationTransform : public AttributeTransform { float range() const { return range_; } bool is_initialized() const { return quantization_bits_ != -1; } + protected: // Create portable attribute using 1:1 mapping between points in the input and // output attribute. - std::unique_ptr<PointAttribute> GeneratePortableAttribute( - const PointAttribute &attribute, int num_points) const; + void GeneratePortableAttribute(const PointAttribute &attribute, + int num_points, + PointAttribute *target_attribute) const; // Create portable attribute using custom mapping between input and output // points. - std::unique_ptr<PointAttribute> GeneratePortableAttribute( - const PointAttribute &attribute, const std::vector<PointIndex> &point_ids, - int num_points) const; + void GeneratePortableAttribute(const PointAttribute &attribute, + const std::vector<PointIndex> &point_ids, + int num_points, + PointAttribute *target_attribute) const; + + DataType GetTransformedDataType( + const PointAttribute &attribute) const override { + return DT_UINT32; + } + int GetTransformedNumComponents( + const PointAttribute &attribute) const override { + return attribute.num_components(); + } + + static bool IsQuantizationValid(int quantization_bits); private: int32_t quantization_bits_; diff --git a/extern/draco/draco/src/draco/attributes/attribute_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_transform.cc index 55af630ac07..fb2ed18297a 100644 --- a/extern/draco/draco/src/draco/attributes/attribute_transform.cc +++ b/extern/draco/draco/src/draco/attributes/attribute_transform.cc @@ -24,21 +24,18 @@ bool AttributeTransform::TransferToAttribute(PointAttribute *attribute) const { return true; } -std::unique_ptr<PointAttribute> AttributeTransform::InitPortableAttribute( - int num_entries, int num_components, int num_points, - const PointAttribute &attribute, bool is_unsigned) const { - const DataType dt = is_unsigned ? DT_UINT32 : DT_INT32; - GeometryAttribute va; - va.Init(attribute.attribute_type(), nullptr, num_components, dt, false, +std::unique_ptr<PointAttribute> AttributeTransform::InitTransformedAttribute( + const PointAttribute &src_attribute, int num_entries) { + const int num_components = GetTransformedNumComponents(src_attribute); + const DataType dt = GetTransformedDataType(src_attribute); + GeometryAttribute ga; + ga.Init(src_attribute.attribute_type(), nullptr, num_components, dt, false, num_components * DataTypeLength(dt), 0); - std::unique_ptr<PointAttribute> portable_attribute(new PointAttribute(va)); - portable_attribute->Reset(num_entries); - if (num_points) { - portable_attribute->SetExplicitMapping(num_points); - } else { - portable_attribute->SetIdentityMapping(); - } - return portable_attribute; + std::unique_ptr<PointAttribute> transformed_attribute(new PointAttribute(ga)); + transformed_attribute->Reset(num_entries); + transformed_attribute->SetIdentityMapping(); + transformed_attribute->set_unique_id(src_attribute.unique_id()); + return transformed_attribute; } } // namespace draco diff --git a/extern/draco/draco/src/draco/attributes/attribute_transform.h b/extern/draco/draco/src/draco/attributes/attribute_transform.h index d746fbf6eea..62aad60db91 100644 --- a/extern/draco/draco/src/draco/attributes/attribute_transform.h +++ b/extern/draco/draco/src/draco/attributes/attribute_transform.h @@ -17,6 +17,8 @@ #include "draco/attributes/attribute_transform_data.h" #include "draco/attributes/point_attribute.h" +#include "draco/core/decoder_buffer.h" +#include "draco/core/encoder_buffer.h" namespace draco { @@ -35,10 +37,38 @@ class AttributeTransform { AttributeTransformData *out_data) const = 0; bool TransferToAttribute(PointAttribute *attribute) const; + // Applies the transform to |attribute| and stores the result in + // |target_attribute|. |point_ids| is an optional vector that can be used to + // remap values during the transform. + virtual bool TransformAttribute(const PointAttribute &attribute, + const std::vector<PointIndex> &point_ids, + PointAttribute *target_attribute) = 0; + + // Applies an inverse transform to |attribute| and stores the result in + // |target_attribute|. In this case, |attribute| is an attribute that was + // already transformed (e.g. quantized) and |target_attribute| is the + // attribute before the transformation. + virtual bool InverseTransformAttribute(const PointAttribute &attribute, + PointAttribute *target_attribute) = 0; + + // Encodes all data needed by the transformation into the |encoder_buffer|. + virtual bool EncodeParameters(EncoderBuffer *encoder_buffer) const = 0; + + // Decodes all data needed to transform |attribute| back to the original + // format. + virtual bool DecodeParameters(const PointAttribute &attribute, + DecoderBuffer *decoder_buffer) = 0; + + // Initializes a transformed attribute that can be used as target in the + // TransformAttribute() function call. + virtual std::unique_ptr<PointAttribute> InitTransformedAttribute( + const PointAttribute &src_attribute, int num_entries); + protected: - std::unique_ptr<PointAttribute> InitPortableAttribute( - int num_entries, int num_components, int num_points, - const PointAttribute &attribute, bool is_unsigned) const; + virtual DataType GetTransformedDataType( + const PointAttribute &attribute) const = 0; + virtual int GetTransformedNumComponents( + const PointAttribute &attribute) const = 0; }; } // namespace draco diff --git a/extern/draco/draco/src/draco/attributes/geometry_attribute.cc b/extern/draco/draco/src/draco/attributes/geometry_attribute.cc index f7ed6a86915..b624784261d 100644 --- a/extern/draco/draco/src/draco/attributes/geometry_attribute.cc +++ b/extern/draco/draco/src/draco/attributes/geometry_attribute.cc @@ -43,10 +43,6 @@ void GeometryAttribute::Init(GeometryAttribute::Type attribute_type, } bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) { - if (buffer_ == nullptr || src_att.buffer_ == nullptr) { - return false; - } - buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size()); num_components_ = src_att.num_components_; data_type_ = src_att.data_type_; normalized_ = src_att.normalized_; @@ -55,6 +51,14 @@ bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) { attribute_type_ = src_att.attribute_type_; buffer_descriptor_ = src_att.buffer_descriptor_; unique_id_ = src_att.unique_id_; + if (src_att.buffer_ == nullptr) { + buffer_ = nullptr; + } else { + if (buffer_ == nullptr) { + return false; + } + buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size()); + } return true; } diff --git a/extern/draco/draco/src/draco/attributes/geometry_attribute.h b/extern/draco/draco/src/draco/attributes/geometry_attribute.h index b94ba8e22dd..c5faccc1b83 100644 --- a/extern/draco/draco/src/draco/attributes/geometry_attribute.h +++ b/extern/draco/draco/src/draco/attributes/geometry_attribute.h @@ -21,6 +21,7 @@ #include "draco/attributes/geometry_indices.h" #include "draco/core/data_buffer.h" #include "draco/core/hash_utils.h" +#include "draco/draco_features.h" namespace draco { @@ -51,6 +52,16 @@ class GeometryAttribute { // predefined use case. Such attributes are often used for a shader specific // data. GENERIC, +#ifdef DRACO_TRANSCODER_SUPPORTED + // TODO(ostava): Adding a new attribute would be bit-stream change for GLTF. + // Older decoders wouldn't know what to do with this attribute type. This + // should be open-sourced only when we are ready to increase our bit-stream + // version. + TANGENT, + MATERIAL, + JOINTS, + WEIGHTS, +#endif // Total number of different attribute types. // Always keep behind all named attributes. NAMED_ATTRIBUTES_COUNT, @@ -111,6 +122,9 @@ class GeometryAttribute { const int64_t byte_pos = GetBytePos(att_index); return buffer_->data() + byte_pos; } + inline bool IsAddressValid(const uint8_t *address) const { + return ((buffer_->data() + buffer_->data_size()) > address); + } // Fills out_data with the raw value of the requested attribute entry. // out_data must be at least byte_stride_ long. @@ -263,7 +277,35 @@ class GeometryAttribute { // Convert all components available in both the original and output formats. for (int i = 0; i < std::min(num_components_, out_num_components); ++i) { + if (!IsAddressValid(src_address)) { + return false; + } const T in_value = *reinterpret_cast<const T *>(src_address); + + // Make sure the in_value fits within the range of values that OutT + // is able to represent. Perform the check only for integral types. + if (std::is_integral<T>::value && std::is_integral<OutT>::value) { +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4804) +#endif +#if defined(__GNUC__) && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wbool-compare" +#endif + static constexpr OutT kOutMin = + std::is_signed<T>::value ? std::numeric_limits<OutT>::lowest() : 0; + if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) { + return false; + } +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif +#ifdef _MSC_VER +# pragma warning(pop) +#endif + } + out_value[i] = static_cast<OutT>(in_value); // When converting integer to floating point, normalize the value if // necessary. diff --git a/extern/draco/draco/src/draco/attributes/point_attribute.cc b/extern/draco/draco/src/draco/attributes/point_attribute.cc index b28f860c15d..e54ab54278f 100644 --- a/extern/draco/draco/src/draco/attributes/point_attribute.cc +++ b/extern/draco/draco/src/draco/attributes/point_attribute.cc @@ -222,4 +222,47 @@ AttributeValueIndex::ValueType PointAttribute::DeduplicateFormattedValues( } #endif +#ifdef DRACO_TRANSCODER_SUPPORTED +void PointAttribute::RemoveUnusedValues() { + if (is_mapping_identity()) { + return; // For identity mapping, all values are always used. + } + // For explicit mapping we need to check if any point is mapped to a value. + // If not we can delete the value. + IndexTypeVector<AttributeValueIndex, bool> is_value_used(size(), false); + int num_used_values = 0; + for (PointIndex pi(0); pi < indices_map_.size(); ++pi) { + const AttributeValueIndex avi = indices_map_[pi]; + if (!is_value_used[avi]) { + is_value_used[avi] = true; + num_used_values++; + } + } + if (num_used_values == size()) { + return; // All values are used. + } + + // Remap the values and update the point to value mapping. + IndexTypeVector<AttributeValueIndex, AttributeValueIndex> + old_to_new_value_map(size(), kInvalidAttributeValueIndex); + AttributeValueIndex new_avi(0); + for (AttributeValueIndex avi(0); avi < size(); ++avi) { + if (!is_value_used[avi]) { + continue; + } + if (avi != new_avi) { + SetAttributeValue(new_avi, GetAddress(avi)); + } + old_to_new_value_map[avi] = new_avi++; + } + + // Remap all points to the new attribute values. + for (PointIndex pi(0); pi < indices_map_.size(); ++pi) { + indices_map_[pi] = old_to_new_value_map[indices_map_[pi]]; + } + + num_unique_entries_ = num_used_values; +} +#endif + } // namespace draco diff --git a/extern/draco/draco/src/draco/attributes/point_attribute.h b/extern/draco/draco/src/draco/attributes/point_attribute.h index ee36620313e..d55c50c8a57 100644 --- a/extern/draco/draco/src/draco/attributes/point_attribute.h +++ b/extern/draco/draco/src/draco/attributes/point_attribute.h @@ -133,6 +133,12 @@ class PointAttribute : public GeometryAttribute { return attribute_transform_data_.get(); } +#ifdef DRACO_TRANSCODER_SUPPORTED + // Removes unused values from the attribute. Value is unused when no point + // is mapped to the value. Only applicable when the mapping is not identity. + void RemoveUnusedValues(); +#endif + private: #ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED template <typename T> diff --git a/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc index ce5b8b9c756..007dd2f4303 100644 --- a/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc @@ -43,9 +43,18 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) { return false; } } + + // Check that decoded number of attributes is valid. if (num_attributes == 0) { return false; } + if (num_attributes > 5 * in_buffer->remaining_size()) { + // The decoded number of attributes is unreasonably high, because at least + // five bytes of attribute descriptor data per attribute are expected. + return false; + } + + // Decode attribute descriptor data. point_attribute_ids_.resize(num_attributes); PointCloud *pc = point_cloud_; for (uint32_t i = 0; i < num_attributes; ++i) { @@ -69,9 +78,14 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) { if (data_type == DT_INVALID || data_type >= DT_TYPES_COUNT) { return false; } - const DataType draco_dt = static_cast<DataType>(data_type); - // Add the attribute to the point cloud + // Check decoded attribute descriptor data. + if (num_components == 0) { + return false; + } + + // Add the attribute to the point cloud. + const DataType draco_dt = static_cast<DataType>(data_type); GeometryAttribute ga; ga.Init(static_cast<GeometryAttribute::Type>(att_type), nullptr, num_components, draco_dt, normalized > 0, @@ -90,7 +104,9 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) { } else #endif { - DecodeVarint(&unique_id, in_buffer); + if (!DecodeVarint(&unique_id, in_buffer)) { + return false; + } ga.set_unique_id(unique_id); } const int att_id = pc->AddAttribute( diff --git a/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc index 797c62f30aa..480e3ff3436 100644 --- a/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc @@ -15,14 +15,16 @@ #include "draco/compression/attributes/attributes_encoder.h" #include "draco/core/varint_encoding.h" +#include "draco/draco_features.h" namespace draco { AttributesEncoder::AttributesEncoder() : point_cloud_encoder_(nullptr), point_cloud_(nullptr) {} -AttributesEncoder::AttributesEncoder(int att_id) : AttributesEncoder() { - AddAttributeId(att_id); +AttributesEncoder::AttributesEncoder(int point_attrib_id) + : AttributesEncoder() { + AddAttributeId(point_attrib_id); } bool AttributesEncoder::Init(PointCloudEncoder *encoder, const PointCloud *pc) { @@ -37,7 +39,15 @@ bool AttributesEncoder::EncodeAttributesEncoderData(EncoderBuffer *out_buffer) { for (uint32_t i = 0; i < num_attributes(); ++i) { const int32_t att_id = point_attribute_ids_[i]; const PointAttribute *const pa = point_cloud_->attribute(att_id); - out_buffer->Encode(static_cast<uint8_t>(pa->attribute_type())); + GeometryAttribute::Type type = pa->attribute_type(); +#ifdef DRACO_TRANSCODER_SUPPORTED + // Attribute types TANGENT, MATERIAL, JOINTS, and WEIGHTS are not supported + // in the official bitstream. They will be encoded as GENERIC. + if (type > GeometryAttribute::GENERIC) { + type = GeometryAttribute::GENERIC; + } +#endif + out_buffer->Encode(static_cast<uint8_t>(type)); out_buffer->Encode(static_cast<uint8_t>(pa->data_type())); out_buffer->Encode(static_cast<uint8_t>(pa->num_components())); out_buffer->Encode(static_cast<uint8_t>(pa->normalized())); diff --git a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc index 99469f94590..c7c96d77007 100644 --- a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc @@ -72,7 +72,7 @@ class PointAttributeVectorOutputIterator { Self &operator*() { return *this; } // Still needed in some cases. - // TODO(hemmer): remove. + // TODO(b/199760123): Remove. // hardcoded to 3 based on legacy usage. const Self &operator=(const VectorD<CoeffT, 3> &val) { DRACO_DCHECK_EQ(attributes_.size(), 1); // Expect only ONE attribute. @@ -278,8 +278,10 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( return false; } AttributeQuantizationTransform transform; - transform.SetParameters(quantization_bits, min_value.data(), - num_components, max_value_dif); + if (!transform.SetParameters(quantization_bits, min_value.data(), + num_components, max_value_dif)) { + return false; + } const int num_transforms = static_cast<int>(attribute_quantization_transforms_.size()); if (!transform.TransferToAttribute( @@ -293,7 +295,9 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( // Decode transform data for signed integer attributes. for (int i = 0; i < min_signed_values_.size(); ++i) { int32_t val; - DecodeVarint(&val, in_buffer); + if (!DecodeVarint(&val, in_buffer)) { + return false; + } min_signed_values_[i] = val; } return true; @@ -353,8 +357,9 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( return false; } if (6 < compression_level) { - LOGE("KdTreeAttributesDecoder: compression level %i not supported.\n", - compression_level); + DRACO_LOGE( + "KdTreeAttributesDecoder: compression level %i not supported.\n", + compression_level); return false; } @@ -371,7 +376,7 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms( GetDecoder()->point_cloud()->attribute(att_id); attr->Reset(num_points); attr->SetIdentityMapping(); - }; + } PointAttributeVectorOutputIterator<uint32_t> out_it(atts); diff --git a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc index 0f9c31565e5..b70deb9e01f 100644 --- a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc @@ -71,16 +71,21 @@ bool KdTreeAttributesEncoder::TransformAttributesToPortableFormat() { att->num_components(), range); } else { // Compute quantization settings from the attribute values. - attribute_quantization_transform.ComputeParameters(*att, - quantization_bits); + if (!attribute_quantization_transform.ComputeParameters( + *att, quantization_bits)) { + return false; + } } attribute_quantization_transforms_.push_back( attribute_quantization_transform); // Store the quantized attribute in an array that will be used when we do // the actual encoding of the data. - quantized_portable_attributes_.push_back( - attribute_quantization_transform.GeneratePortableAttribute( - *att, static_cast<int>(num_points))); + auto portable_att = + attribute_quantization_transform.InitTransformedAttribute(*att, + num_points); + attribute_quantization_transform.TransformAttribute(*att, {}, + portable_att.get()); + quantized_portable_attributes_.push_back(std::move(portable_att)); } else if (att->data_type() == DT_INT32 || att->data_type() == DT_INT16 || att->data_type() == DT_INT8) { // For signed types, find the minimum value for each component. These diff --git a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h index 8b4c4e2faab..80748e0bf5d 100644 --- a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_ -#define DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_ +#ifndef DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_ +#define DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_ #include "draco/attributes/attribute_quantization_transform.h" #include "draco/compression/attributes/attributes_encoder.h" @@ -48,4 +48,4 @@ class KdTreeAttributesEncoder : public AttributesEncoder { } // namespace draco -#endif // DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_ +#endif // DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_ diff --git a/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h index 32e27c711e3..be5ee5b09e3 100644 --- a/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h +++ b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h @@ -53,6 +53,7 @@ class OctahedronToolBox { : quantization_bits_(-1), max_quantized_value_(-1), max_value_(-1), + dequantization_scale_(1.f), center_value_(-1) {} bool SetQuantizationBits(int32_t q) { @@ -62,6 +63,7 @@ class OctahedronToolBox { quantization_bits_ = q; max_quantized_value_ = (1 << quantization_bits_) - 1; max_value_ = max_quantized_value_ - 1; + dequantization_scale_ = 2.f / max_value_; center_value_ = max_value_ / 2; return true; } @@ -192,64 +194,11 @@ class OctahedronToolBox { } } - // TODO(b/149328891): Change function to not use templates as |T| is only - // float. - template <typename T> - void OctaherdalCoordsToUnitVector(T in_s, T in_t, T *out_vector) const { - DRACO_DCHECK_GE(in_s, 0); - DRACO_DCHECK_GE(in_t, 0); - DRACO_DCHECK_LE(in_s, 1); - DRACO_DCHECK_LE(in_t, 1); - T s = in_s; - T t = in_t; - T spt = s + t; - T smt = s - t; - T x_sign = 1.0; - if (spt >= 0.5 && spt <= 1.5 && smt >= -0.5 && smt <= 0.5) { - // Right hemisphere. Don't do anything. - } else { - // Left hemisphere. - x_sign = -1.0; - if (spt <= 0.5) { - s = 0.5 - in_t; - t = 0.5 - in_s; - } else if (spt >= 1.5) { - s = 1.5 - in_t; - t = 1.5 - in_s; - } else if (smt <= -0.5) { - s = in_t - 0.5; - t = in_s + 0.5; - } else { - s = in_t + 0.5; - t = in_s - 0.5; - } - spt = s + t; - smt = s - t; - } - const T y = 2.0 * s - 1.0; - const T z = 2.0 * t - 1.0; - const T x = std::min(std::min(2.0 * spt - 1.0, 3.0 - 2.0 * spt), - std::min(2.0 * smt + 1.0, 1.0 - 2.0 * smt)) * - x_sign; - // Normalize the computed vector. - const T normSquared = x * x + y * y + z * z; - if (normSquared < 1e-6) { - out_vector[0] = 0; - out_vector[1] = 0; - out_vector[2] = 0; - } else { - const T d = 1.0 / std::sqrt(normSquared); - out_vector[0] = x * d; - out_vector[1] = y * d; - out_vector[2] = z * d; - } - } - - template <typename T> - void QuantizedOctaherdalCoordsToUnitVector(int32_t in_s, int32_t in_t, - T *out_vector) const { - T scale = 1.0 / static_cast<T>(max_value_); - OctaherdalCoordsToUnitVector(in_s * scale, in_t * scale, out_vector); + inline void QuantizedOctahedralCoordsToUnitVector(int32_t in_s, int32_t in_t, + float *out_vector) const { + OctahedralCoordsToUnitVector(in_s * dequantization_scale_ - 1.f, + in_t * dequantization_scale_ - 1.f, + out_vector); } // |s| and |t| are expected to be signed values. @@ -333,9 +282,77 @@ class OctahedronToolBox { int32_t center_value() const { return center_value_; } private: + inline void OctahedralCoordsToUnitVector(float in_s_scaled, float in_t_scaled, + float *out_vector) const { + // Background about the encoding: + // A normal is encoded in a normalized space <s, t> depicted below. The + // encoding correponds to an octahedron that is unwrapped to a 2D plane. + // During encoding, a normal is projected to the surface of the octahedron + // and the projection is then unwrapped to the 2D plane. Decoding is the + // reverse of this process. + // All points in the central diamond are located on triangles on the + // right "hemisphere" of the octahedron while all points outside of the + // diamond are on the left hemisphere (basically, they would have to be + // wrapped along the diagonal edges to form the octahedron). The central + // point corresponds to the right most vertex of the octahedron and all + // corners of the plane correspond to the left most vertex of the + // octahedron. + // + // t + // ^ *-----*-----* + // | | /|\ | + // | / | \ | + // | / | \ | + // | / | \ | + // *-----*---- * + // | \ | / | + // | \ | / | + // | \ | / | + // | \|/ | + // *-----*-----* --> s + + // Note that the input |in_s_scaled| and |in_t_scaled| are already scaled to + // <-1, 1> range. This way, the central point is at coordinate (0, 0). + float y = in_s_scaled; + float z = in_t_scaled; + + // Remaining coordinate can be computed by projecting the (y, z) values onto + // the surface of the octahedron. + const float x = 1.f - std::abs(y) - std::abs(z); + + // |x| is essentially a signed distance from the diagonal edges of the + // diamond shown on the figure above. It is positive for all points in the + // diamond (right hemisphere) and negative for all points outside the + // diamond (left hemisphere). For all points on the left hemisphere we need + // to update their (y, z) coordinates to account for the wrapping along + // the edges of the diamond. + float x_offset = -x; + x_offset = x_offset < 0 ? 0 : x_offset; + + // This will do nothing for the points on the right hemisphere but it will + // mirror the (y, z) location along the nearest diagonal edge of the + // diamond. + y += y < 0 ? x_offset : -x_offset; + z += z < 0 ? x_offset : -x_offset; + + // Normalize the computed vector. + const float norm_squared = x * x + y * y + z * z; + if (norm_squared < 1e-6) { + out_vector[0] = 0; + out_vector[1] = 0; + out_vector[2] = 0; + } else { + const float d = 1.0f / std::sqrt(norm_squared); + out_vector[0] = x * d; + out_vector[1] = y * d; + out_vector[2] = z * d; + } + } + int32_t quantization_bits_; int32_t max_quantized_value_; int32_t max_value_; + float dequantization_scale_; int32_t center_value_; }; } // namespace draco diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h index f712952556a..2960a5e71b4 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_COMPRESSION_ATTRIBUTES_MESH_PREDICTION_SCHEMES_PREDICTION_SCHEME_DATA_H_ -#define DRACO_COMPRESSION_ATTRIBUTES_MESH_PREDICTION_SCHEMES_PREDICTION_SCHEME_DATA_H_ +#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_DATA_H_ +#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_DATA_H_ #include "draco/mesh/corner_table.h" #include "draco/mesh/mesh.h" diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h index bf1a6146111..775eded6b55 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h @@ -69,7 +69,14 @@ class MeshPredictionSchemeGeometricNormalPredictorArea // Computing cross product. const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev); - normal = normal + cross; + + // Prevent signed integer overflows by doing math as unsigned. + auto normal_data = reinterpret_cast<uint64_t *>(normal.data()); + auto cross_data = reinterpret_cast<const uint64_t *>(cross.data()); + normal_data[0] = normal_data[0] + cross_data[0]; + normal_data[1] = normal_data[1] + cross_data[1]; + normal_data[2] = normal_data[2] + cross_data[2]; + cit.Next(); } diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h index 485d457ccf6..fd10fb524b3 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h @@ -60,8 +60,13 @@ inline bool ComputeParallelogramPrediction( const int v_next_off = vert_next * num_components; const int v_prev_off = vert_prev * num_components; for (int c = 0; c < num_components; ++c) { - out_prediction[c] = (in_data[v_next_off + c] + in_data[v_prev_off + c]) - - in_data[v_opp_off + c]; + const int64_t in_data_next_off = in_data[v_next_off + c]; + const int64_t in_data_prev_off = in_data[v_prev_off + c]; + const int64_t in_data_opp_off = in_data[v_opp_off + c]; + const int64_t result = + (in_data_next_off + in_data_prev_off) - in_data_opp_off; + + out_prediction[c] = static_cast<DataTypeT>(result); } return true; } diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h index 5d8a5060133..f05e5ddd713 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h @@ -156,6 +156,13 @@ bool MeshPredictionSchemeTexCoordsPortablePredictor< const VectorD<int64_t, 2> x_uv = n_uv * pn_norm2_squared + (cn_dot_pn * pn_uv); + const int64_t pn_absmax_element = + std::max(std::max(std::abs(pn[0]), std::abs(pn[1])), std::abs(pn[2])); + if (cn_dot_pn > std::numeric_limits<int64_t>::max() / pn_absmax_element) { + // return false if squared length calculation would overflow. + return false; + } + // Compute squared length of vector CX in position coordinate system: const VectorD<int64_t, 3> x_pos = next_pos + (cn_dot_pn * pn) / pn_norm2_squared; diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc index 428340da013..60429d5c779 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc @@ -18,34 +18,51 @@ namespace draco { PredictionSchemeMethod SelectPredictionMethod( int att_id, const PointCloudEncoder *encoder) { - if (encoder->options()->GetSpeed() >= 10) { + return SelectPredictionMethod(att_id, *encoder->options(), encoder); +} + +PredictionSchemeMethod SelectPredictionMethod( + int att_id, const EncoderOptions &options, + const PointCloudEncoder *encoder) { + if (options.GetSpeed() >= 10) { // Selected fastest, though still doing some compression. return PREDICTION_DIFFERENCE; } if (encoder->GetGeometryType() == TRIANGULAR_MESH) { // Use speed setting to select the best encoding method. const PointAttribute *const att = encoder->point_cloud()->attribute(att_id); - if (att->attribute_type() == GeometryAttribute::TEX_COORD) { - if (encoder->options()->GetSpeed() < 4) { + if (att->attribute_type() == GeometryAttribute::TEX_COORD && + att->num_components() == 2) { + if (options.GetSpeed() < 4) { // Use texture coordinate prediction for speeds 0, 1, 2, 3. return MESH_PREDICTION_TEX_COORDS_PORTABLE; } } if (att->attribute_type() == GeometryAttribute::NORMAL) { #ifdef DRACO_NORMAL_ENCODING_SUPPORTED - if (encoder->options()->GetSpeed() < 4) { + if (options.GetSpeed() < 4) { // Use geometric normal prediction for speeds 0, 1, 2, 3. - return MESH_PREDICTION_GEOMETRIC_NORMAL; + // For this prediction, the position attribute needs to be either + // integer or quantized as well. + const int pos_att_id = encoder->point_cloud()->GetNamedAttributeId( + GeometryAttribute::POSITION); + const PointAttribute *const pos_att = + encoder->point_cloud()->GetNamedAttribute( + GeometryAttribute::POSITION); + if (pos_att && (IsDataTypeIntegral(pos_att->data_type()) || + options.GetAttributeInt(pos_att_id, "quantization_bits", + -1) > 0)) { + return MESH_PREDICTION_GEOMETRIC_NORMAL; + } } #endif return PREDICTION_DIFFERENCE; // default } // Handle other attribute types. - if (encoder->options()->GetSpeed() >= 8) { + if (options.GetSpeed() >= 8) { return PREDICTION_DIFFERENCE; } - if (encoder->options()->GetSpeed() >= 2 || - encoder->point_cloud()->num_points() < 40) { + if (options.GetSpeed() >= 2 || encoder->point_cloud()->num_points() < 40) { // Parallelogram prediction is used for speeds 2 - 7 or when the overhead // of using constrained multi-parallelogram would be too high. return MESH_PREDICTION_PARALLELOGRAM; diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h index 40a7683aa0d..b7e21224fad 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h @@ -38,6 +38,10 @@ namespace draco { PredictionSchemeMethod SelectPredictionMethod(int att_id, const PointCloudEncoder *encoder); +PredictionSchemeMethod SelectPredictionMethod(int att_id, + const EncoderOptions &options, + const PointCloudEncoder *encoder); + // Factory class for creating mesh prediction schemes. template <typename DataTypeT> struct MeshPredictionSchemeEncoderFactory { diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h index ab64bce7114..37aa9f76a9c 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_ -#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_ +#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_ +#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_ #include "draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h" #include "draco/core/encoder_buffer.h" @@ -52,4 +52,4 @@ class PredictionSchemeTypedEncoderInterface } // namespace draco -#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_ +#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_ diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h index 0a14d0d9ba4..e100c738a6c 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h @@ -36,9 +36,25 @@ class PredictionSchemeWrapDecodingTransform inline void ComputeOriginalValue(const DataTypeT *predicted_vals, const CorrTypeT *corr_vals, DataTypeT *out_original_vals) const { + // For now we assume both |DataTypeT| and |CorrTypeT| are equal. + static_assert(std::is_same<DataTypeT, CorrTypeT>::value, + "Predictions and corrections must have the same type."); + + // The only valid implementation right now is for int32_t. + static_assert(std::is_same<DataTypeT, int32_t>::value, + "Only int32_t is supported for predicted values."); + predicted_vals = this->ClampPredictedValue(predicted_vals); + + // Perform the wrapping using unsigned coordinates to avoid potential signed + // integer overflows caused by malformed input. + const uint32_t *const uint_predicted_vals = + reinterpret_cast<const uint32_t *>(predicted_vals); + const uint32_t *const uint_corr_vals = + reinterpret_cast<const uint32_t *>(corr_vals); for (int i = 0; i < this->num_components(); ++i) { - out_original_vals[i] = predicted_vals[i] + corr_vals[i]; + out_original_vals[i] = + static_cast<DataTypeT>(uint_predicted_vals[i] + uint_corr_vals[i]); if (out_original_vals[i] > this->max_value()) { out_original_vals[i] -= this->max_dif(); } else if (out_original_vals[i] < this->min_value()) { diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h index 26f61fbaf6a..979c63c3d11 100644 --- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h +++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h @@ -73,7 +73,7 @@ class PredictionSchemeWrapTransformBase { return &clamped_value_[0]; } - // TODO(hemmer): Consider refactoring to avoid this dummy. + // TODO(b/199760123): Consider refactoring to avoid this dummy. int quantization_bits() const { DRACO_DCHECK(false); return -1; diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc index 521935c1e99..7d5d1eeff26 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc @@ -26,8 +26,8 @@ SequentialAttributeEncodersController::SequentialAttributeEncodersController( : sequencer_(std::move(sequencer)) {} SequentialAttributeEncodersController::SequentialAttributeEncodersController( - std::unique_ptr<PointsSequencer> sequencer, int att_id) - : AttributesEncoder(att_id), sequencer_(std::move(sequencer)) {} + std::unique_ptr<PointsSequencer> sequencer, int point_attrib_id) + : AttributesEncoder(point_attrib_id), sequencer_(std::move(sequencer)) {} bool SequentialAttributeEncodersController::Init(PointCloudEncoder *encoder, const PointCloud *pc) { diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc index d01fb26aad4..17f32fc1612 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc @@ -53,6 +53,11 @@ bool SequentialIntegerAttributeDecoder::DecodeValues( if (!in_buffer->Decode(&prediction_transform_type)) { return false; } + // Check that decoded prediction scheme transform type is valid. + if (prediction_transform_type < PREDICTION_TRANSFORM_NONE || + prediction_transform_type >= NUM_PREDICTION_SCHEME_TRANSFORM_TYPES) { + return false; + } prediction_scheme_ = CreateIntPredictionScheme( static_cast<PredictionSchemeMethod>(prediction_scheme_method), static_cast<PredictionSchemeTransformType>(prediction_transform_type)); @@ -143,8 +148,9 @@ bool SequentialIntegerAttributeDecoder::DecodeIntegerValues( return false; } for (size_t i = 0; i < num_values; ++i) { - if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) + if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) { return false; + } } } } @@ -223,12 +229,13 @@ void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) { void SequentialIntegerAttributeDecoder::PreparePortableAttribute( int num_entries, int num_components) { - GeometryAttribute va; - va.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32, + GeometryAttribute ga; + ga.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32, false, num_components * DataTypeLength(DT_INT32), 0); - std::unique_ptr<PointAttribute> port_att(new PointAttribute(va)); + std::unique_ptr<PointAttribute> port_att(new PointAttribute(ga)); port_att->SetIdentityMapping(); port_att->Reset(num_entries); + port_att->set_unique_id(attribute()->unique_id()); SetPortableAttribute(std::move(port_att)); } diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc index 2889e0521a0..e66a0a8a40a 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc @@ -81,6 +81,9 @@ bool SequentialIntegerAttributeEncoder::TransformAttributeToPortableFormat( value_to_value_map[orig_att->mapped_index(point_ids[i])] = AttributeValueIndex(i); } + if (portable_att->is_mapping_identity()) { + portable_att->SetExplicitMapping(encoder()->point_cloud()->num_points()); + } // Go over all points of the original attribute and update the mapping in // the portable attribute. for (PointIndex i(0); i < encoder()->point_cloud()->num_points(); ++i) { diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc index 017344393dc..de36c1c36f2 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc @@ -14,18 +14,17 @@ // #include "draco/compression/attributes/sequential_normal_attribute_decoder.h" -#include "draco/attributes/attribute_octahedron_transform.h" #include "draco/compression/attributes/normal_compression_utils.h" namespace draco { -SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder() - : quantization_bits_(-1) {} +SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder() {} bool SequentialNormalAttributeDecoder::Init(PointCloudDecoder *decoder, int attribute_id) { - if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) + if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) { return false; + } // Currently, this encoder works only for 3-component normal vectors. if (attribute()->num_components() != 3) { return false; @@ -41,11 +40,13 @@ bool SequentialNormalAttributeDecoder::DecodeIntegerValues( const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { - uint8_t quantization_bits; - if (!in_buffer->Decode(&quantization_bits)) { + // Note: in older bitstreams, we do not have a PortableAttribute() decoded + // at this stage so we cannot pass it down to the DecodeParameters() call. + // It still works fine for octahedral transform because it does not need to + // use any data from the attribute. + if (!octahedral_transform_.DecodeParameters(*attribute(), in_buffer)) { return false; } - quantization_bits_ = quantization_bits; } #endif return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids, @@ -56,39 +57,20 @@ bool SequentialNormalAttributeDecoder::DecodeDataNeededByPortableTransform( const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) { if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) { // For newer file version, decode attribute transform data here. - uint8_t quantization_bits; - if (!in_buffer->Decode(&quantization_bits)) { + if (!octahedral_transform_.DecodeParameters(*GetPortableAttribute(), + in_buffer)) { return false; } - quantization_bits_ = quantization_bits; } // Store the decoded transform data in portable attribute. - AttributeOctahedronTransform octahedral_transform; - octahedral_transform.SetParameters(quantization_bits_); - return octahedral_transform.TransferToAttribute(portable_attribute()); + return octahedral_transform_.TransferToAttribute(portable_attribute()); } bool SequentialNormalAttributeDecoder::StoreValues(uint32_t num_points) { // Convert all quantized values back to floats. - const int num_components = attribute()->num_components(); - const int entry_size = sizeof(float) * num_components; - float att_val[3]; - int quant_val_id = 0; - int out_byte_pos = 0; - const int32_t *const portable_attribute_data = GetPortableAttributeData(); - OctahedronToolBox octahedron_tool_box; - if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_)) - return false; - for (uint32_t i = 0; i < num_points; ++i) { - const int32_t s = portable_attribute_data[quant_val_id++]; - const int32_t t = portable_attribute_data[quant_val_id++]; - octahedron_tool_box.QuantizedOctaherdalCoordsToUnitVector(s, t, att_val); - // Store the decoded floating point value into the attribute buffer. - attribute()->buffer()->Write(out_byte_pos, att_val, entry_size); - out_byte_pos += entry_size; - } - return true; + return octahedral_transform_.InverseTransformAttribute( + *GetPortableAttribute(), attribute()); } } // namespace draco diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h index 860eacb4c84..8c2d801b763 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h @@ -15,6 +15,7 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_ +#include "draco/attributes/attribute_octahedron_transform.h" #include "draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h" #include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h" #include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h" @@ -42,7 +43,7 @@ class SequentialNormalAttributeDecoder bool StoreValues(uint32_t num_points) override; private: - int32_t quantization_bits_; + AttributeOctahedronTransform octahedral_transform_; std::unique_ptr<PredictionSchemeTypedDecoderInterface<int32_t>> CreateIntPredictionScheme( diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc index 23fa8bb7b39..3c5ef0ebcbc 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc @@ -20,8 +20,9 @@ namespace draco { bool SequentialNormalAttributeEncoder::Init(PointCloudEncoder *encoder, int attribute_id) { - if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id)) + if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id)) { return false; + } // Currently this encoder works only for 3-component normal vectors. if (attribute()->num_components() != 3) { return false; @@ -44,9 +45,13 @@ bool SequentialNormalAttributeEncoder::EncodeDataNeededByPortableTransform( bool SequentialNormalAttributeEncoder::PrepareValues( const std::vector<PointIndex> &point_ids, int num_points) { - SetPortableAttribute( - attribute_octahedron_transform_.GeneratePortableAttribute( - *(attribute()), point_ids, num_points)); + auto portable_att = attribute_octahedron_transform_.InitTransformedAttribute( + *(attribute()), point_ids.size()); + if (!attribute_octahedron_transform_.TransformAttribute( + *(attribute()), point_ids, portable_att.get())) { + return false; + } + SetPortableAttribute(std::move(portable_att)); return true; } diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc index bf925c4a595..3d306e7dae6 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc @@ -14,13 +14,12 @@ // #include "draco/compression/attributes/sequential_quantization_attribute_decoder.h" -#include "draco/attributes/attribute_quantization_transform.h" #include "draco/core/quantization_utils.h" namespace draco { -SequentialQuantizationAttributeDecoder::SequentialQuantizationAttributeDecoder() - : quantization_bits_(-1), max_value_dif_(0.f) {} +SequentialQuantizationAttributeDecoder:: + SequentialQuantizationAttributeDecoder() {} bool SequentialQuantizationAttributeDecoder::Init(PointCloudDecoder *decoder, int attribute_id) { @@ -59,62 +58,31 @@ bool SequentialQuantizationAttributeDecoder:: } // Store the decoded transform data in portable attribute; - AttributeQuantizationTransform transform; - transform.SetParameters(quantization_bits_, min_value_.get(), - attribute()->num_components(), max_value_dif_); - return transform.TransferToAttribute(portable_attribute()); + return quantization_transform_.TransferToAttribute(portable_attribute()); } -bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_values) { - return DequantizeValues(num_values); +bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_points) { + return DequantizeValues(num_points); } bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() { - const int num_components = attribute()->num_components(); - min_value_ = std::unique_ptr<float[]>(new float[num_components]); - if (!decoder()->buffer()->Decode(min_value_.get(), - sizeof(float) * num_components)) { - return false; - } - if (!decoder()->buffer()->Decode(&max_value_dif_)) { - return false; + // Get attribute used as source for decoding. + auto att = GetPortableAttribute(); + if (att == nullptr) { + // This should happen only in the backward compatibility mode. It will still + // work fine for this case because the only thing the quantization transform + // cares about is the number of components that is the same for both source + // and target attributes. + att = attribute(); } - uint8_t quantization_bits; - if (!decoder()->buffer()->Decode(&quantization_bits) || - quantization_bits > 31) { - return false; - } - quantization_bits_ = quantization_bits; - return true; + return quantization_transform_.DecodeParameters(*att, decoder()->buffer()); } bool SequentialQuantizationAttributeDecoder::DequantizeValues( uint32_t num_values) { // Convert all quantized values back to floats. - const int32_t max_quantized_value = - (1u << static_cast<uint32_t>(quantization_bits_)) - 1; - const int num_components = attribute()->num_components(); - const int entry_size = sizeof(float) * num_components; - const std::unique_ptr<float[]> att_val(new float[num_components]); - int quant_val_id = 0; - int out_byte_pos = 0; - Dequantizer dequantizer; - if (!dequantizer.Init(max_value_dif_, max_quantized_value)) { - return false; - } - const int32_t *const portable_attribute_data = GetPortableAttributeData(); - for (uint32_t i = 0; i < num_values; ++i) { - for (int c = 0; c < num_components; ++c) { - float value = - dequantizer.DequantizeFloat(portable_attribute_data[quant_val_id++]); - value = value + min_value_[c]; - att_val[c] = value; - } - // Store the floating point value into the attribute buffer. - attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size); - out_byte_pos += entry_size; - } - return true; + return quantization_transform_.InverseTransformAttribute( + *GetPortableAttribute(), attribute()); } } // namespace draco diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h index c0b7637a750..ad372dcd8a6 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h @@ -15,6 +15,7 @@ #ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_ #define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_ +#include "draco/attributes/attribute_quantization_transform.h" #include "draco/compression/attributes/sequential_integer_attribute_decoder.h" #include "draco/draco_features.h" @@ -43,12 +44,7 @@ class SequentialQuantizationAttributeDecoder virtual bool DequantizeValues(uint32_t num_values); private: - // Max number of quantization bits used to encode each component of the - // attribute. - int32_t quantization_bits_; - - std::unique_ptr<float[]> min_value_; - float max_value_dif_; + AttributeQuantizationTransform quantization_transform_; }; } // namespace draco diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc index cd5b8b141e0..d3666f7a411 100644 --- a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc +++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc @@ -50,9 +50,11 @@ bool SequentialQuantizationAttributeEncoder::Init(PointCloudEncoder *encoder, &quantization_origin[0]); const float range = encoder->options()->GetAttributeFloat( attribute_id, "quantization_range", 1.f); - attribute_quantization_transform_.SetParameters( - quantization_bits, quantization_origin.data(), - attribute->num_components(), range); + if (!attribute_quantization_transform_.SetParameters( + quantization_bits, quantization_origin.data(), + attribute->num_components(), range)) { + return false; + } } else { // Compute quantization settings from the attribute values. if (!attribute_quantization_transform_.ComputeParameters( @@ -70,9 +72,14 @@ bool SequentialQuantizationAttributeEncoder:: bool SequentialQuantizationAttributeEncoder::PrepareValues( const std::vector<PointIndex> &point_ids, int num_points) { - SetPortableAttribute( - attribute_quantization_transform_.GeneratePortableAttribute( - *(attribute()), point_ids, num_points)); + auto portable_attribute = + attribute_quantization_transform_.InitTransformedAttribute( + *attribute(), point_ids.size()); + if (!attribute_quantization_transform_.TransformAttribute( + *(attribute()), point_ids, portable_attribute.get())) { + return false; + } + SetPortableAttribute(std::move(portable_attribute)); return true; } diff --git a/extern/draco/draco/src/draco/compression/config/compression_shared.h b/extern/draco/draco/src/draco/compression/config/compression_shared.h index 40061d3cd48..c43f303bd15 100644 --- a/extern/draco/draco/src/draco/compression/config/compression_shared.h +++ b/extern/draco/draco/src/draco/compression/config/compression_shared.h @@ -42,6 +42,7 @@ enum EncodedGeometryType { INVALID_GEOMETRY_TYPE = -1, POINT_CLOUD = 0, TRIANGULAR_MESH, + NUM_ENCODED_GEOMETRY_TYPES }; // List of encoding methods for point clouds. @@ -105,6 +106,8 @@ enum PredictionSchemeTransformType { // Specialized transform for normal coordinates using canonicalized inverted // tiles. PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED = 3, + // The number of valid (non-negative) prediction scheme transform types. + NUM_PREDICTION_SCHEME_TRANSFORM_TYPES }; // List of all mesh traversal methods supported by Draco framework. diff --git a/extern/draco/draco/src/draco/compression/config/draco_options.h b/extern/draco/draco/src/draco/compression/config/draco_options.h index 0d1247b2ad1..2bd4a3b6761 100644 --- a/extern/draco/draco/src/draco/compression/config/draco_options.h +++ b/extern/draco/draco/src/draco/compression/config/draco_options.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_ -#define DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_ +#ifndef DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_ +#define DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_ #include <map> #include <memory> @@ -246,4 +246,4 @@ void DracoOptions<AttributeKeyT>::SetAttributeOptions( } // namespace draco -#endif // DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_ +#endif // DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_ diff --git a/extern/draco/draco/src/draco/compression/decode.cc b/extern/draco/draco/src/draco/compression/decode.cc index ab70ef1ec60..92ae4ff66f9 100644 --- a/extern/draco/draco/src/draco/compression/decode.cc +++ b/extern/draco/draco/src/draco/compression/decode.cc @@ -56,7 +56,10 @@ StatusOr<EncodedGeometryType> Decoder::GetEncodedGeometryType( DecoderBuffer *in_buffer) { DecoderBuffer temp_buffer(*in_buffer); DracoHeader header; - DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header)) + DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header)); + if (header.encoder_type >= NUM_ENCODED_GEOMETRY_TYPES) { + return Status(Status::DRACO_ERROR, "Unsupported geometry type."); + } return static_cast<EncodedGeometryType>(header.encoder_type); } diff --git a/extern/draco/draco/src/draco/compression/encode_base.h b/extern/draco/draco/src/draco/compression/encode_base.h index 0c63a972bf4..6211efc221b 100644 --- a/extern/draco/draco/src/draco/compression/encode_base.h +++ b/extern/draco/draco/src/draco/compression/encode_base.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_ -#define DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_ +#ifndef DRACO_COMPRESSION_ENCODE_BASE_H_ +#define DRACO_COMPRESSION_ENCODE_BASE_H_ #include "draco/attributes/geometry_attribute.h" #include "draco/compression/config/compression_shared.h" @@ -98,7 +98,7 @@ class EncoderBase { "Invalid prediction scheme for attribute type."); } } - // TODO(hemmer): Try to enable more prediction schemes for normals. + // TODO(b/199760123): Try to enable more prediction schemes for normals. if (att_type == GeometryAttribute::NORMAL) { if (!(prediction_scheme == PREDICTION_DIFFERENCE || prediction_scheme == MESH_PREDICTION_GEOMETRIC_NORMAL)) { @@ -128,4 +128,4 @@ void EncoderBase<EncoderOptionsT>::SetTrackEncodedProperties(bool flag) { } // namespace draco -#endif // DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_ +#endif // DRACO_COMPRESSION_ENCODE_BASE_H_ diff --git a/extern/draco/draco/src/draco/compression/entropy/ans.h b/extern/draco/draco/src/draco/compression/entropy/ans.h index c765256b96e..313546fee20 100644 --- a/extern/draco/draco/src/draco/compression/entropy/ans.h +++ b/extern/draco/draco/src/draco/compression/entropy/ans.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_CORE_ANS_H_ -#define DRACO_CORE_ANS_H_ +#ifndef DRACO_COMPRESSION_ENTROPY_ANS_H_ +#define DRACO_COMPRESSION_ENTROPY_ANS_H_ // An implementation of Asymmetric Numeral Systems (rANS). // See http://arxiv.org/abs/1311.2540v2 for more information on rANS. // This file is based off libvpx's ans.h. @@ -391,7 +391,6 @@ class RAnsEncoder { ans_.buf[ans_.buf_offset++] = ans_.state % DRACO_ANS_IO_BASE; ans_.state /= DRACO_ANS_IO_BASE; } - // TODO(ostava): The division and multiplication should be optimized. ans_.state = (ans_.state / p) * rans_precision + ans_.state % p + sym->cum_prob; } @@ -524,4 +523,4 @@ class RAnsDecoder { } // namespace draco -#endif // DRACO_CORE_ANS_H_ +#endif // DRACO_COMPRESSION_ENTROPY_ANS_H_ diff --git a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h index 0a68e29fe26..cd4271193bf 100644 --- a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h +++ b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h @@ -31,11 +31,10 @@ constexpr int ComputeRAnsUnclampedPrecision(int symbols_bit_length) { // our rANS library (which is between 12 to 20 bits). constexpr int ComputeRAnsPrecisionFromUniqueSymbolsBitLength( int symbols_bit_length) { - return ComputeRAnsUnclampedPrecision(symbols_bit_length) < 12 - ? 12 - : ComputeRAnsUnclampedPrecision(symbols_bit_length) > 20 - ? 20 - : ComputeRAnsUnclampedPrecision(symbols_bit_length); + return ComputeRAnsUnclampedPrecision(symbols_bit_length) < 12 ? 12 + : ComputeRAnsUnclampedPrecision(symbols_bit_length) > 20 + ? 20 + : ComputeRAnsUnclampedPrecision(symbols_bit_length); } // Compute approximate frequency table size needed for storing the provided diff --git a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h index 4e07ec87123..4b738b50a9d 100644 --- a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h +++ b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h @@ -125,8 +125,8 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create( for (int i = 0; i < num_symbols; ++i) { sorted_probabilities[i] = i; } - std::sort(sorted_probabilities.begin(), sorted_probabilities.end(), - ProbabilityLess(&probability_table_)); + std::stable_sort(sorted_probabilities.begin(), sorted_probabilities.end(), + ProbabilityLess(&probability_table_)); if (total_rans_prob < rans_precision_) { // This happens rather infrequently, just add the extra needed precision // to the most frequent symbol. diff --git a/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc index 93d29971c89..79e81181830 100644 --- a/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc +++ b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc @@ -72,7 +72,7 @@ bool DecodeTaggedSymbols(uint32_t num_values, int num_components, int value_id = 0; for (uint32_t i = 0; i < num_values; i += num_components) { // Decode the tag. - const int bit_length = tag_decoder.DecodeSymbol(); + const uint32_t bit_length = tag_decoder.DecodeSymbol(); // Decode the actual value. for (int j = 0; j < num_components; ++j) { uint32_t val; diff --git a/extern/draco/draco/src/draco/compression/expert_encode.cc b/extern/draco/draco/src/draco/compression/expert_encode.cc index 4c70a72a765..f9aec15eb27 100644 --- a/extern/draco/draco/src/draco/compression/expert_encode.cc +++ b/extern/draco/draco/src/draco/compression/expert_encode.cc @@ -67,7 +67,7 @@ Status ExpertEncoder::EncodePointCloudToBuffer(const PointCloud &pc, kd_tree_possible = false; } if (kd_tree_possible && att->data_type() == DT_FLOAT32 && - options().GetAttributeInt(0, "quantization_bits", -1) <= 0) { + options().GetAttributeInt(i, "quantization_bits", -1) <= 0) { kd_tree_possible = false; // Quantization not enabled. } if (!kd_tree_possible) { diff --git a/extern/draco/draco/src/draco/compression/expert_encode.h b/extern/draco/draco/src/draco/compression/expert_encode.h index a1aa7b8b3a8..ea59393d3d2 100644 --- a/extern/draco/draco/src/draco/compression/expert_encode.h +++ b/extern/draco/draco/src/draco/compression/expert_encode.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_ -#define DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_ +#ifndef DRACO_COMPRESSION_EXPERT_ENCODE_H_ +#define DRACO_COMPRESSION_EXPERT_ENCODE_H_ #include "draco/compression/config/compression_shared.h" #include "draco/compression/config/encoder_options.h" @@ -144,4 +144,4 @@ class ExpertEncoder : public EncoderBase<EncoderOptions> { } // namespace draco -#endif // DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_ +#endif // DRACO_COMPRESSION_EXPERT_ENCODE_H_ diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc index 50d1971c15b..6d22e2f2a32 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc @@ -162,6 +162,10 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder( if (!decoder_->buffer()->Decode(&traversal_method_encoded)) { return false; } + // Check that decoded traversal method is valid. + if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) { + return false; + } traversal_method = static_cast<MeshTraversalMethod>(traversal_method_encoded); } @@ -450,7 +454,7 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { #endif // Decode connectivity of non-position attributes. - if (attribute_data_.size() > 0) { + if (!attribute_data_.empty()) { #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) { for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) { @@ -577,11 +581,16 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( SetOppositeCorners(corner_b, corner + 2); // Update vertex mapping. - corner_table_->MapCornerToVertex(corner, vertex_x); - corner_table_->MapCornerToVertex( - corner + 1, corner_table_->Vertex(corner_table_->Next(corner_b))); const VertexIndex vert_a_prev = corner_table_->Vertex(corner_table_->Previous(corner_a)); + const VertexIndex vert_b_next = + corner_table_->Vertex(corner_table_->Next(corner_b)); + if (vertex_x == vert_a_prev || vertex_x == vert_b_next) { + // Encoding is invalid, because face vertices are degenerate. + return -1; + } + corner_table_->MapCornerToVertex(corner, vertex_x); + corner_table_->MapCornerToVertex(corner + 1, vert_b_next); corner_table_->MapCornerToVertex(corner + 2, vert_a_prev); corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2); // Mark the vertex |x| as interior. @@ -791,7 +800,7 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity( return -1; // Unexpected number of decoded vertices. } // Decode start faces and connect them to the faces from the active stack. - while (active_corner_stack.size() > 0) { + while (!active_corner_stack.empty()) { const CornerIndex corner = active_corner_stack.back(); active_corner_stack.pop_back(); const bool interior_face = @@ -952,9 +961,13 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( for (uint32_t i = 0; i < num_topology_splits; ++i) { TopologySplitEventData event_data; uint32_t delta; - DecodeVarint<uint32_t>(&delta, decoder_buffer); + if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) { + return -1; + } event_data.source_symbol_id = delta + last_source_symbol_id; - DecodeVarint<uint32_t>(&delta, decoder_buffer); + if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) { + return -1; + } if (delta > event_data.source_symbol_id) { return -1; } @@ -1009,7 +1022,9 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( for (uint32_t i = 0; i < num_hole_events; ++i) { HoleEventData event_data; uint32_t delta; - DecodeVarint<uint32_t>(&delta, decoder_buffer); + if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) { + return -1; + } event_data.symbol_id = delta + last_symbol_id; last_symbol_id = event_data.symbol_id; hole_event_data_.push_back(event_data); diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc index 5aff5d8cc10..a7f381480f1 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc @@ -31,7 +31,6 @@ bool MeshEdgebreakerEncoder::InitializeEncoder() { impl_ = nullptr; // For tiny meshes it's usually better to use the basic edgebreaker as the // overhead of the predictive one may turn out to be too big. - // TODO(b/111065939): Check if this can be improved. const bool is_tiny_mesh = mesh()->num_faces() < 1000; int selected_edgebreaker_method = diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc index 0791dc6705a..4bf6aa92070 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc @@ -408,7 +408,7 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { init_face_connectivity_corners.begin(), init_face_connectivity_corners.end()); // Encode connectivity for all non-position attributes. - if (attribute_data_.size() > 0) { + if (!attribute_data_.empty()) { // Use the same order of corner that will be used by the decoder. visited_faces_.assign(mesh_->num_faces(), false); for (CornerIndex ci : processed_connectivity_corners_) { diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h index fb33771637e..979e1d373d8 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h @@ -177,7 +177,6 @@ class MeshEdgebreakerEncoderImpl : public MeshEdgebreakerEncoderImplInterface { uint32_t num_split_symbols_; // Struct holding data used for encoding each non-position attribute. - // TODO(ostava): This should be probably renamed to something better. struct AttributeData { AttributeData() : attribute_index(-1), is_connectivity_used(true) {} int attribute_index; diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h index cb3c29dd669..c650bc35210 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h @@ -50,8 +50,6 @@ namespace draco { // \ / S \ / / E \ // *-------* *-------* // -// TODO(ostava): Get rid of the topology bit pattern. It's important only for -// encoding but the algorithms should use EdgebreakerSymbol instead. enum EdgebreakerTopologyBitPattern { TOPOLOGY_C = 0x0, // 0 TOPOLOGY_S = 0x1, // 1 0 0 diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h index 621883a5f1f..c00373727df 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h @@ -106,7 +106,12 @@ class MeshEdgebreakerTraversalValenceDecoder context_counters_.resize(context_symbols_.size()); for (int i = 0; i < context_symbols_.size(); ++i) { uint32_t num_symbols; - DecodeVarint<uint32_t>(&num_symbols, out_buffer); + if (!DecodeVarint<uint32_t>(&num_symbols, out_buffer)) { + return false; + } + if (num_symbols > static_cast<uint32_t>(corner_table_->num_faces())) { + return false; + } if (num_symbols > 0) { context_symbols_[i].resize(num_symbols); DecodeSymbols(num_symbols, 1, out_buffer, context_symbols_[i].data()); diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc index 53f5e8651b8..fbc7383eef1 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc @@ -53,6 +53,11 @@ bool MeshSequentialDecoder::DecodeConnectivity() { if (faces_64 > 0xffffffff / 3) { return false; } + if (faces_64 > buffer()->remaining_size() / 3) { + // The number of faces is unreasonably high, because face indices do not + // fit in the remaining size of the buffer. + return false; + } if (points_64 > faces_64 * 3) { return false; } @@ -91,7 +96,7 @@ bool MeshSequentialDecoder::DecodeConnectivity() { } mesh()->AddFace(face); } - } else if (mesh()->num_points() < (1 << 21) && + } else if (num_points < (1 << 21) && bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 2)) { // Decode indices as uint32_t. for (uint32_t i = 0; i < num_faces; ++i) { diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc index 02ac7779ea3..fd8b1139253 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc @@ -32,8 +32,6 @@ Status MeshSequentialEncoder::EncodeConnectivity() { EncodeVarint(static_cast<uint32_t>(mesh()->num_points()), buffer()); // We encode all attributes in the original (possibly duplicated) format. - // TODO(ostava): This may not be optimal if we have only one attribute or if - // all attributes share the same index mapping. if (options()->GetGlobalBool("compress_connectivity", false)) { // 0 = Encode compressed indices. buffer()->Encode(static_cast<uint8_t>(0)); @@ -44,8 +42,6 @@ Status MeshSequentialEncoder::EncodeConnectivity() { // 1 = Encode indices directly. buffer()->Encode(static_cast<uint8_t>(1)); // Store vertex indices using a smallest data type that fits their range. - // TODO(ostava): This can be potentially improved by using a tighter - // fit that is not bound by a bit-length of any particular data type. if (mesh()->num_points() < 256) { // Serialize indices as uint8_t. for (FaceIndex i(0); i < num_faces; ++i) { diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h index 672609642b0..6e2b05877ab 100644 --- a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h @@ -33,7 +33,6 @@ namespace draco { // Class that encodes mesh data using a simple binary representation of mesh's // connectivity and geometry. -// TODO(ostava): Use a better name. class MeshSequentialEncoder : public MeshEncoder { public: MeshSequentialEncoder(); diff --git a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h index e66dd14b238..dd9738ba2d5 100644 --- a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h +++ b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h @@ -25,7 +25,7 @@ namespace draco { // values based on the traversal of the encoded mesh. The class should be used // as the TraversalObserverT member of a Traverser class such as the // DepthFirstTraverser (depth_first_traverser.h). -// TODO(hemmer): rename to AttributeIndicesCodingTraverserObserver +// TODO(b/199760123): Rename to AttributeIndicesCodingTraverserObserver. template <class CornerTableT> class MeshAttributeIndicesEncodingObserver { public: diff --git a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h index ebe1d5f7a9e..e55c93a7969 100644 --- a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h +++ b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h @@ -25,7 +25,7 @@ namespace draco { // Sequencer that generates point sequence in an order given by a deterministic // traversal on the mesh surface. Note that all attributes encoded with this // sequence must share the same connectivity. -// TODO(hemmer): Consider refactoring such that this is an observer. +// TODO(b/199760123): Consider refactoring such that this is an observer. template <class TraverserT> class MeshTraversalSequencer : public PointsSequencer { public: diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h index 87bc2b7ef3e..fa1b1e203e5 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h @@ -227,7 +227,7 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal( std::stack<Status> status_stack; status_stack.push(init_status); - // TODO(hemmer): use preallocated vector instead of stack. + // TODO(b/199760123): Use preallocated vector instead of stack. while (!status_stack.empty()) { const DecodingStatus status = status_stack.top(); status_stack.pop(); @@ -263,7 +263,8 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal( // Fast decoding of remaining bits if number of points is 1 or 2. if (num_remaining_points <= 2) { - // TODO(hemmer): axes_ not necessary, remove would change bitstream! + // TODO(b/199760123): |axes_| not necessary, remove would change + // bitstream! axes_[0] = axis; for (uint32_t i = 1; i < dimension_; i++) { axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_); diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h index 14fa32d7083..65b3d07a6ad 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h @@ -280,7 +280,7 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal( std::stack<Status> status_stack; status_stack.push(init_status); - // TODO(hemmer): use preallocated vector instead of stack. + // TODO(b/199760123): Use preallocated vector instead of stack. while (!status_stack.empty()) { Status status = status_stack.top(); status_stack.pop(); @@ -305,7 +305,8 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal( // Fast encoding of remaining bits if number of points is 1 or 2. // Doing this also for 2 gives a slight additional speed up. if (num_remaining_points <= 2) { - // TODO(hemmer): axes_ not necessary, remove would change bitstream! + // TODO(b/199760123): |axes_| not necessary, remove would change + // bitstream! axes_[0] = axis; for (uint32_t i = 1; i < dimension_; i++) { axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_); diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc index 9e8d895f176..dffaa4c8d20 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc @@ -69,18 +69,29 @@ FloatPointsTreeDecoder::FloatPointsTreeDecoder() bool FloatPointsTreeDecoder::DecodePointCloudKdTreeInternal( DecoderBuffer *buffer, std::vector<Point3ui> *qpoints) { - if (!buffer->Decode(&qinfo_.quantization_bits)) return false; - if (qinfo_.quantization_bits > 31) return false; - if (!buffer->Decode(&qinfo_.range)) return false; - if (!buffer->Decode(&num_points_)) return false; - if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_) + if (!buffer->Decode(&qinfo_.quantization_bits)) { return false; - if (!buffer->Decode(&compression_level_)) return false; + } + if (qinfo_.quantization_bits > 31) { + return false; + } + if (!buffer->Decode(&qinfo_.range)) { + return false; + } + if (!buffer->Decode(&num_points_)) { + return false; + } + if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_) { + return false; + } + if (!buffer->Decode(&compression_level_)) { + return false; + } // Only allow compression level in [0..6]. if (6 < compression_level_) { - LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n", - compression_level_); + DRACO_LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n", + compression_level_); return false; } diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h index 26ba94f1f59..44c1b3d3a97 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h @@ -44,7 +44,7 @@ namespace draco { // there are more leading zeros, which is then compressed better by the // arithmetic encoding. -// TODO(hemmer): Remove class because it duplicates quantization code. +// TODO(b/199760123): Remove class because it duplicates quantization code. class FloatPointsTreeEncoder { public: explicit FloatPointsTreeEncoder(PointCloudCompressionMethod method); @@ -91,7 +91,7 @@ bool FloatPointsTreeEncoder::EncodePointCloud(InputIteratorT points_begin, // Collect necessary data for encoding. num_points_ = std::distance(points_begin, points_end); - // TODO(hemmer): Extend quantization tools to make this more automatic. + // TODO(b/199760123): Extend quantization tools to make this more automatic. // Compute range of points for quantization std::vector<Point3ui> qpoints; qpoints.reserve(num_points_); diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h index 94e523cadaf..bc31af58613 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// TODO(hemmer): Make this a wrapper using DynamicIntegerPointsKdTreeDecoder. +// TODO(b/199760123): Make this a wrapper using +// DynamicIntegerPointsKdTreeDecoder. // // See integer_points_kd_tree_encoder.h for documentation. diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h index b8811092ed7..654f14a7866 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// TODO(hemmer): Make this a wrapper using DynamicIntegerPointsKdTreeEncoder. +// TODO(b/199760123): Make this a wrapper using +// DynamicIntegerPointsKdTreeEncoder. #ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_INTEGER_POINTS_KD_TREE_ENCODER_H_ #define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_INTEGER_POINTS_KD_TREE_ENCODER_H_ diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h index 01943ad9e6c..04aa1d95e11 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h +++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h @@ -22,7 +22,7 @@ namespace draco { -// TODO(hemmer): Make this a stable bounding box. +// TODO(b/199760123): Make this a stable bounding box. struct QuantizationInfo { uint32_t quantization_bits; float range; diff --git a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc index 5196edf960c..85f7bc94e33 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc @@ -88,7 +88,9 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options, const uint8_t max_supported_minor_version = header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor : kDracoMeshBitstreamVersionMinor; + // Check for version compatibility. +#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED if (version_major_ < 1 || version_major_ > max_supported_major_version) { return Status(Status::UNKNOWN_VERSION, "Unknown major version."); } @@ -96,6 +98,14 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options, version_minor_ > max_supported_minor_version) { return Status(Status::UNKNOWN_VERSION, "Unknown minor version."); } +#else + if (version_major_ != max_supported_major_version) { + return Status(Status::UNKNOWN_VERSION, "Unsupported major version."); + } + if (version_minor_ != max_supported_minor_version) { + return Status(Status::UNKNOWN_VERSION, "Unsupported minor version."); + } +#endif buffer_->set_bitstream_version( DRACO_BITSTREAM_VERSION(version_major_, version_minor_)); diff --git a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc index b4b0ee94093..a1fda8d5a50 100644 --- a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc +++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc @@ -62,12 +62,14 @@ Status PointCloudEncoder::EncodeHeader() { buffer_->Encode("DRACO", 5); // Version (major, minor). const uint8_t encoder_type = GetGeometryType(); - const uint8_t version_major = encoder_type == POINT_CLOUD - ? kDracoPointCloudBitstreamVersionMajor - : kDracoMeshBitstreamVersionMajor; - const uint8_t version_minor = encoder_type == POINT_CLOUD - ? kDracoPointCloudBitstreamVersionMinor - : kDracoMeshBitstreamVersionMinor; + uint8_t version_major, version_minor; + version_major = encoder_type == POINT_CLOUD + ? kDracoPointCloudBitstreamVersionMajor + : kDracoMeshBitstreamVersionMajor; + version_minor = encoder_type == POINT_CLOUD + ? kDracoPointCloudBitstreamVersionMinor + : kDracoMeshBitstreamVersionMinor; + buffer_->Encode(version_major); buffer_->Encode(version_minor); // Type of the encoder (point cloud, mesh, ...). diff --git a/extern/draco/draco/src/draco/core/bounding_box.cc b/extern/draco/draco/src/draco/core/bounding_box.cc index d95b1e90759..be0d209d857 100644 --- a/extern/draco/draco/src/draco/core/bounding_box.cc +++ b/extern/draco/draco/src/draco/core/bounding_box.cc @@ -16,8 +16,15 @@ namespace draco { -BoundingBox::BoundingBox(const Vector3f &min_point_in, - const Vector3f &max_point_in) - : min_point_(min_point_in), max_point_(max_point_in) {} +BoundingBox::BoundingBox() + : BoundingBox(Vector3f(std::numeric_limits<float>::max(), + std::numeric_limits<float>::max(), + std::numeric_limits<float>::max()), + Vector3f(std::numeric_limits<float>::lowest(), + std::numeric_limits<float>::lowest(), + std::numeric_limits<float>::lowest())) {} + +BoundingBox::BoundingBox(const Vector3f &min_point, const Vector3f &max_point) + : min_point_(min_point), max_point_(max_point) {} } // namespace draco diff --git a/extern/draco/draco/src/draco/core/bounding_box.h b/extern/draco/draco/src/draco/core/bounding_box.h index 1c20fad8bf2..31ba2d68340 100644 --- a/extern/draco/draco/src/draco/core/bounding_box.h +++ b/extern/draco/draco/src/draco/core/bounding_box.h @@ -19,22 +19,27 @@ namespace draco { -// Class for detecting the bounding box of a point_cloud or mesh. -// Use the minimum point and the maximum point to define the bounding box. -// TODO(xiaoxumeng): Change the class of BoundingBox to a template, similar to -// draco/src/draco/core/vector_d.h +// Class for computing the bounding box of points in 3D space. class BoundingBox { public: - // Initialization - BoundingBox(const Vector3f &min_point_in, const Vector3f &max_point_in); + // Creates bounding box object with minimum and maximum points initialized to + // the largest positive and the smallest negative values, respectively. The + // resulting abstract bounding box effectively has no points and can be + // updated by providing any point to Update() method. + BoundingBox(); - inline const Vector3f &min_point() const { return min_point_; } - inline const Vector3f &max_point() const { return max_point_; } + // Creates bounding box object with minimum and maximum points initialized to + // |min_point| and |max_point|, respectively. + BoundingBox(const Vector3f &min_point, const Vector3f &max_point); - // Conditionally updates the bounding box. - // TODO(xiaoxumeng): Change the function to a template function and change the - // argument to an iterator. - inline void update_bounding_box(const Vector3f &new_point) { + // Returns the minimum point of the bounding box. + inline const Vector3f &GetMinPoint() const { return min_point_; } + + // Returns the maximum point of the bounding box. + inline const Vector3f &GetMaxPoint() const { return max_point_; } + + // Conditionally updates the bounding box with a given |new_point|. + void Update(const Vector3f &new_point) { for (int i = 0; i < 3; i++) { if (new_point[i] < min_point_[i]) { min_point_[i] = new_point[i]; @@ -45,6 +50,19 @@ class BoundingBox { } } + // Updates bounding box with minimum and maximum points of the |other| + // bounding box. + void Update(const BoundingBox &other) { + Update(other.GetMinPoint()); + Update(other.GetMaxPoint()); + } + + // Returns the size of the bounding box along each axis. + Vector3f Size() const { return max_point_ - min_point_; } + + // Returns the center of the bounding box. + Vector3f Center() const { return (min_point_ + max_point_) / 2; } + private: Vector3f min_point_; Vector3f max_point_; diff --git a/extern/draco/draco/src/draco/core/cycle_timer.cc b/extern/draco/draco/src/draco/core/cycle_timer.cc index 94b4b28b2f9..58df4df77de 100644 --- a/extern/draco/draco/src/draco/core/cycle_timer.cc +++ b/extern/draco/draco/src/draco/core/cycle_timer.cc @@ -17,31 +17,31 @@ namespace draco { void DracoTimer::Start() { #ifdef _WIN32 - QueryPerformanceCounter(&tv_start); + QueryPerformanceCounter(&tv_start_); #else - gettimeofday(&tv_start, nullptr); + gettimeofday(&tv_start_, nullptr); #endif } void DracoTimer::Stop() { #ifdef _WIN32 - QueryPerformanceCounter(&tv_end); + QueryPerformanceCounter(&tv_end_); #else - gettimeofday(&tv_end, nullptr); + gettimeofday(&tv_end_, nullptr); #endif } int64_t DracoTimer::GetInMs() { #ifdef _WIN32 LARGE_INTEGER elapsed = {0}; - elapsed.QuadPart = tv_end.QuadPart - tv_start.QuadPart; + elapsed.QuadPart = tv_end_.QuadPart - tv_start_.QuadPart; LARGE_INTEGER frequency = {0}; QueryPerformanceFrequency(&frequency); return elapsed.QuadPart * 1000 / frequency.QuadPart; #else - const int64_t seconds = (tv_end.tv_sec - tv_start.tv_sec) * 1000; - const int64_t milliseconds = (tv_end.tv_usec - tv_start.tv_usec) / 1000; + const int64_t seconds = (tv_end_.tv_sec - tv_start_.tv_sec) * 1000; + const int64_t milliseconds = (tv_end_.tv_usec - tv_start_.tv_usec) / 1000; return seconds + milliseconds; #endif } diff --git a/extern/draco/draco/src/draco/core/cycle_timer.h b/extern/draco/draco/src/draco/core/cycle_timer.h index 172f1c2e9b5..f480cc9d389 100644 --- a/extern/draco/draco/src/draco/core/cycle_timer.h +++ b/extern/draco/draco/src/draco/core/cycle_timer.h @@ -20,9 +20,10 @@ #define WIN32_LEAN_AND_MEAN #endif #include <windows.h> -typedef LARGE_INTEGER timeval; +typedef LARGE_INTEGER DracoTimeVal; #else #include <sys/time.h> +typedef timeval DracoTimeVal; #endif #include <cinttypes> @@ -39,8 +40,8 @@ class DracoTimer { int64_t GetInMs(); private: - timeval tv_start; - timeval tv_end; + DracoTimeVal tv_start_; + DracoTimeVal tv_end_; }; typedef DracoTimer CycleTimer; diff --git a/extern/draco/draco/src/draco/core/data_buffer.cc b/extern/draco/draco/src/draco/core/data_buffer.cc index f0b43d67dbd..96a3787987c 100644 --- a/extern/draco/draco/src/draco/core/data_buffer.cc +++ b/extern/draco/draco/src/draco/core/data_buffer.cc @@ -52,7 +52,7 @@ void DataBuffer::Resize(int64_t size) { } void DataBuffer::WriteDataToStream(std::ostream &stream) { - if (data_.size() == 0) { + if (data_.empty()) { return; } stream.write(reinterpret_cast<char *>(data_.data()), data_.size()); diff --git a/extern/draco/draco/src/draco/core/decoder_buffer.h b/extern/draco/draco/src/draco/core/decoder_buffer.h index 0559abbe415..be98e52d60e 100644 --- a/extern/draco/draco/src/draco/core/decoder_buffer.h +++ b/extern/draco/draco/src/draco/core/decoder_buffer.h @@ -54,12 +54,11 @@ class DecoderBuffer { // Decodes up to 32 bits into out_val. Can be called only in between // StartBitDecoding and EndBitDecoding. Otherwise returns false. - bool DecodeLeastSignificantBits32(int nbits, uint32_t *out_value) { + bool DecodeLeastSignificantBits32(uint32_t nbits, uint32_t *out_value) { if (!bit_decoder_active()) { return false; } - bit_decoder_.GetBits(nbits, out_value); - return true; + return bit_decoder_.GetBits(nbits, out_value); } // Decodes an arbitrary data type. @@ -158,9 +157,10 @@ class DecoderBuffer { inline void ConsumeBits(int k) { bit_offset_ += k; } // Returns |nbits| bits in |x|. - inline bool GetBits(int32_t nbits, uint32_t *x) { - DRACO_DCHECK_GE(nbits, 0); - DRACO_DCHECK_LE(nbits, 32); + inline bool GetBits(uint32_t nbits, uint32_t *x) { + if (nbits > 32) { + return false; + } uint32_t value = 0; for (int32_t bit = 0; bit < nbits; ++bit) { value |= GetBit() << bit; diff --git a/extern/draco/draco/src/draco/core/draco_index_type_vector.h b/extern/draco/draco/src/draco/core/draco_index_type_vector.h index d47ab3b04eb..0fefc43b23d 100644 --- a/extern/draco/draco/src/draco/core/draco_index_type_vector.h +++ b/extern/draco/draco/src/draco/core/draco_index_type_vector.h @@ -28,7 +28,6 @@ namespace draco { // draco_index_type.h . // TODO(ostava): Make the interface more complete. It's currently missing // features such as iterators. -// TODO(vytyaz): Add more unit tests for this class. template <class IndexTypeT, class ValueTypeT> class IndexTypeVector { public: @@ -56,7 +55,7 @@ class IndexTypeVector { void push_back(ValueTypeT &&val) { vector_.push_back(std::move(val)); } template <typename... Args> - void emplace_back(Args &&... args) { + void emplace_back(Args &&...args) { vector_.emplace_back(std::forward<Args>(args)...); } diff --git a/extern/draco/draco/src/draco/core/draco_version.h b/extern/draco/draco/src/draco/core/draco_version.h index ffd7948c64d..5f2676ad7e9 100644 --- a/extern/draco/draco/src/draco/core/draco_version.h +++ b/extern/draco/draco/src/draco/core/draco_version.h @@ -18,7 +18,7 @@ namespace draco { // Draco version is comprised of <major>.<minor>.<revision>. -static const char kDracoVersion[] = "1.3.6"; +static const char kDracoVersion[] = "1.5.2"; const char *Version() { return kDracoVersion; } diff --git a/extern/draco/draco/src/draco/core/macros.h b/extern/draco/draco/src/draco/core/macros.h index 89b706e53a5..64647d129d5 100644 --- a/extern/draco/draco/src/draco/core/macros.h +++ b/extern/draco/draco/src/draco/core/macros.h @@ -21,11 +21,13 @@ #ifdef ANDROID_LOGGING #include <android/log.h> #define LOG_TAG "draco" -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) +#define DRACO_LOGI(...) \ + __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +#define DRACO_LOGE(...) \ + __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #else -#define LOGI printf -#define LOGE printf +#define DRACO_LOGI printf +#define DRACO_LOGE printf #endif #include <iostream> @@ -88,6 +90,10 @@ namespace draco { #define DRACO_MACROS_IMPL_CONCAT_INNER_(x, y) x##y #define DRACO_MACROS_IMPL_CONCAT_(x, y) DRACO_MACROS_IMPL_CONCAT_INNER_(x, y) +#define DRACO_MACROS_IMPL_CONCAT_INNER_3_(x, y, z) x##y##z +#define DRACO_MACROS_IMPL_CONCAT_3_(x, y, z) \ + DRACO_MACROS_IMPL_CONCAT_INNER_3_(x, y, z) + // Expand the n-th argument of the macro. Used to select an argument based on // the number of entries in a variadic macro argument. Example usage: // @@ -98,13 +104,20 @@ namespace draco { // #define VARIADIC_MACRO(...) // DRACO_SELECT_NTH_FROM_3(__VA_ARGS__, FUNC_3, FUNC_2, FUNC_1) __VA_ARGS__ // -#define DRACO_SELECT_NTH_FROM_2(_1, _2, NAME) NAME -#define DRACO_SELECT_NTH_FROM_3(_1, _2, _3, NAME) NAME -#define DRACO_SELECT_NTH_FROM_4(_1, _2, _3, _4, NAME) NAME +#define DRACO_SELECT_NTH_FROM_2(_1, _2, NAME, ...) NAME +#define DRACO_SELECT_NTH_FROM_3(_1, _2, _3, NAME, ...) NAME +#define DRACO_SELECT_NTH_FROM_4(_1, _2, _3, _4, NAME, ...) NAME // Macro that converts the Draco bit-stream into one uint16_t number. // Useful mostly when checking version numbers. #define DRACO_BITSTREAM_VERSION(MAJOR, MINOR) \ ((static_cast<uint16_t>(MAJOR) << 8) | MINOR) +// Macro that converts the uint16_t Draco bit-stream number into the major +// and minor components respectively. +#define DRACO_BISTREAM_VERSION_MAJOR(VERSION) \ + (static_cast<uint8_t>(VERSION >> 8)) +#define DRACO_BISTREAM_VERSION_MINOR(VERSION) \ + (static_cast<uint8_t>(VERSION & 0xFF)) + #endif // DRACO_CORE_MACROS_H_ diff --git a/extern/draco/draco/src/draco/core/options.h b/extern/draco/draco/src/draco/core/options.h index 1bc4dc0fb7b..9dc22ce16c2 100644 --- a/extern/draco/draco/src/draco/core/options.h +++ b/extern/draco/draco/src/draco/core/options.h @@ -71,8 +71,6 @@ class Options { private: // All entries are internally stored as strings and converted to the desired // return type based on the used Get* method. - // TODO(ostava): Consider adding type safety mechanism that would prevent - // unsafe operations such as a conversion from vector to int. std::map<std::string, std::string> options_; }; diff --git a/extern/draco/draco/src/draco/core/status.h b/extern/draco/draco/src/draco/core/status.h index 449ad8566de..ee7f43ee59c 100644 --- a/extern/draco/draco/src/draco/core/status.h +++ b/extern/draco/draco/src/draco/core/status.h @@ -15,6 +15,7 @@ #ifndef DRACO_CORE_STATUS_H_ #define DRACO_CORE_STATUS_H_ +#include <ostream> #include <string> namespace draco { @@ -61,6 +62,9 @@ inline std::ostream &operator<<(std::ostream &os, const Status &status) { } inline Status OkStatus() { return Status(Status::OK); } +inline Status ErrorStatus(const std::string &msg) { + return Status(Status::DRACO_ERROR, msg); +} // Evaluates an expression that returns draco::Status. If the status is not OK, // the macro returns the status object. diff --git a/extern/draco/draco/src/draco/core/varint_decoding.h b/extern/draco/draco/src/draco/core/varint_decoding.h index 4e86df732e0..cff47e930b4 100644 --- a/extern/draco/draco/src/draco/core/varint_decoding.h +++ b/extern/draco/draco/src/draco/core/varint_decoding.h @@ -58,6 +58,7 @@ bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) { // Decodes a specified integer as varint. Note that the IntTypeT must be the // same as the one used in the corresponding EncodeVarint() call. +// out_val is undefined if this returns false. template <typename IntTypeT> bool DecodeVarint(IntTypeT *out_val, DecoderBuffer *buffer) { if (std::is_unsigned<IntTypeT>::value) { diff --git a/extern/draco/draco/src/draco/core/vector_d.h b/extern/draco/draco/src/draco/core/vector_d.h index bed97304feb..a0ec2dedf2e 100644 --- a/extern/draco/draco/src/draco/core/vector_d.h +++ b/extern/draco/draco/src/draco/core/vector_d.h @@ -20,6 +20,7 @@ #include <algorithm> #include <array> #include <cmath> +#include <limits> #include "draco/core/macros.h" @@ -33,7 +34,7 @@ class VectorD { typedef ScalarT Scalar; typedef VectorD<Scalar, dimension_t> Self; - // TODO(hemmer): Deprecate. + // TODO(b/199760123): Deprecate. typedef ScalarT CoefficientType; VectorD() { @@ -44,7 +45,7 @@ class VectorD { // The following constructor does not compile in opt mode, which for now led // to the constructors further down, which is not ideal. - // TODO(hemmer): fix constructor below and remove others. + // TODO(b/199760123): Fix constructor below and remove others. // template <typename... Args> // explicit VectorD(Args... args) : v_({args...}) {} @@ -110,7 +111,7 @@ class VectorD { Scalar &operator[](int i) { return v_[i]; } const Scalar &operator[](int i) const { return v_[i]; } - // TODO(hemmer): remove. + // TODO(b/199760123): Remove. // Similar to interface of Eigen library. Scalar &operator()(int i) { return v_[i]; } const Scalar &operator()(int i) const { return v_[i]; } @@ -236,7 +237,12 @@ class VectorD { Scalar AbsSum() const { Scalar result(0); for (int i = 0; i < dimension; ++i) { - result += std::abs(v_[i]); + Scalar next_value = std::abs(v_[i]); + if (result > std::numeric_limits<Scalar>::max() - next_value) { + // Return the max if adding would have caused an overflow. + return std::numeric_limits<Scalar>::max(); + } + result += next_value; } return result; } diff --git a/extern/draco/draco/src/draco/draco_features.h b/extern/draco/draco/src/draco/draco_features.h index 27e3d7f136a..d0a630e5465 100644 --- a/extern/draco/draco/src/draco/draco_features.h +++ b/extern/draco/draco/src/draco/draco_features.h @@ -4,7 +4,5 @@ #define DRACO_MESH_COMPRESSION_SUPPORTED #define DRACO_NORMAL_ENCODING_SUPPORTED #define DRACO_STANDARD_EDGEBREAKER_SUPPORTED -#define DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED -#define DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED #endif // DRACO_FEATURES_H_ diff --git a/extern/draco/draco/src/draco/mesh/corner_table.cc b/extern/draco/draco/src/draco/mesh/corner_table.cc index 6066e58bd8b..3f92f651ab6 100644 --- a/extern/draco/draco/src/draco/mesh/corner_table.cc +++ b/extern/draco/draco/src/draco/mesh/corner_table.cc @@ -66,12 +66,13 @@ bool CornerTable::Reset(int num_faces, int num_vertices) { if (num_faces < 0 || num_vertices < 0) { return false; } - if (static_cast<unsigned int>(num_faces) > + const unsigned int num_faces_unsigned = num_faces; + if (num_faces_unsigned > std::numeric_limits<CornerIndex::ValueType>::max() / 3) { return false; } - corner_to_vertex_map_.assign(num_faces * 3, kInvalidVertexIndex); - opposite_corners_.assign(num_faces * 3, kInvalidCornerIndex); + corner_to_vertex_map_.assign(num_faces_unsigned * 3, kInvalidVertexIndex); + opposite_corners_.assign(num_faces_unsigned * 3, kInvalidCornerIndex); vertex_corners_.reserve(num_vertices); valence_cache_.ClearValenceCache(); valence_cache_.ClearValenceCacheInaccurate(); diff --git a/extern/draco/draco/src/draco/mesh/mesh.h b/extern/draco/draco/src/draco/mesh/mesh.h index f4506da81c9..b1577c03986 100644 --- a/extern/draco/draco/src/draco/mesh/mesh.h +++ b/extern/draco/draco/src/draco/mesh/mesh.h @@ -119,6 +119,10 @@ class Mesh : public PointCloud { const std::vector<PointIndex> &unique_point_ids) override; #endif + // Exposes |faces_|. Use |faces_| at your own risk. DO NOT store the + // reference: the |faces_| object is destroyed with the mesh. + IndexTypeVector<FaceIndex, Face> &faces() { return faces_; } + private: // Mesh specific per-attribute data. std::vector<AttributeData> attribute_data_; diff --git a/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h index 7dad25cf1d2..6f02453d2d4 100644 --- a/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h +++ b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h @@ -130,6 +130,12 @@ class MeshAttributeCornerTable { return false; } + bool IsDegenerated(FaceIndex face) const { + // Introducing seams can't change the degeneracy of the individual faces, + // therefore we can delegate the check to the original |corner_table_|. + return corner_table_->IsDegenerated(face); + } + bool no_interior_seams() const { return no_interior_seams_; } const CornerTable *corner_table() const { return corner_table_; } diff --git a/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc b/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc index 773c1e18fe6..bc44c831c4e 100644 --- a/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc +++ b/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc @@ -14,25 +14,42 @@ // #include "draco/mesh/mesh_cleanup.h" +#include <unordered_set> + +#include "draco/core/hash_utils.h" + namespace draco { -bool MeshCleanup::operator()(Mesh *mesh, const MeshCleanupOptions &options) { - if (!options.remove_degenerated_faces && !options.remove_unused_attributes) { - return true; // Nothing to cleanup. +Status MeshCleanup::Cleanup(Mesh *mesh, const MeshCleanupOptions &options) { + if (!options.remove_degenerated_faces && !options.remove_unused_attributes && + !options.remove_duplicate_faces && !options.make_geometry_manifold) { + return OkStatus(); // Nothing to cleanup. } const PointAttribute *const pos_att = mesh->GetNamedAttribute(GeometryAttribute::POSITION); if (pos_att == nullptr) { - return false; + return Status(Status::DRACO_ERROR, "Missing position attribute."); } - // Array that is going to store whether a corresponding point is used. - std::vector<bool> is_point_used; + + if (options.remove_degenerated_faces) { + RemoveDegeneratedFaces(mesh); + } + + if (options.remove_duplicate_faces) { + RemoveDuplicateFaces(mesh); + } + if (options.remove_unused_attributes) { - is_point_used.resize(mesh->num_points(), false); + RemoveUnusedAttributes(mesh); } + return OkStatus(); +} + +void MeshCleanup::RemoveDegeneratedFaces(Mesh *mesh) { + const PointAttribute *const pos_att = + mesh->GetNamedAttribute(GeometryAttribute::POSITION); FaceIndex::ValueType num_degenerated_faces = 0; - PointIndex::ValueType num_new_points = 0; // Array for storing position indices on a face. std::array<AttributeValueIndex, 3> pos_indices; for (FaceIndex f(0); f < mesh->num_faces(); ++f) { @@ -40,149 +57,195 @@ bool MeshCleanup::operator()(Mesh *mesh, const MeshCleanupOptions &options) { for (int p = 0; p < 3; ++p) { pos_indices[p] = pos_att->mapped_index(face[p]); } - bool is_face_valid = true; - if (options.remove_degenerated_faces) { - if (pos_indices[0] == pos_indices[1] || - pos_indices[0] == pos_indices[2] || - pos_indices[1] == pos_indices[2]) { - ++num_degenerated_faces; - is_face_valid = false; - } else if (num_degenerated_faces > 0) { - // Copy the face to its new location. - mesh->SetFace(f - num_degenerated_faces, face); - } - } - if (options.remove_unused_attributes && is_face_valid) { - for (int p = 0; p < 3; ++p) { - if (!is_point_used[face[p].value()]) { - is_point_used[face[p].value()] = true; - ++num_new_points; - } - } + if (pos_indices[0] == pos_indices[1] || pos_indices[0] == pos_indices[2] || + pos_indices[1] == pos_indices[2]) { + ++num_degenerated_faces; + } else if (num_degenerated_faces > 0) { + // Copy the face to its new location. + mesh->SetFace(f - num_degenerated_faces, face); } } if (num_degenerated_faces > 0) { mesh->SetNumFaces(mesh->num_faces() - num_degenerated_faces); } - if (options.remove_unused_attributes) { - bool points_changed = false; - const PointIndex::ValueType num_original_points = mesh->num_points(); - // Map from old points to the new ones. - IndexTypeVector<PointIndex, PointIndex> point_map(num_original_points); - if (num_new_points < static_cast<int>(mesh->num_points())) { - // Some of the points were removed. We need to remap the old points to the - // new ones. - num_new_points = 0; - for (PointIndex i(0); i < num_original_points; ++i) { - if (is_point_used[i.value()]) { - point_map[i] = num_new_points++; - } else { - point_map[i] = kInvalidPointIndex; - } +} + +void MeshCleanup::RemoveDuplicateFaces(Mesh *mesh) { + const PointAttribute *const pos_att = + mesh->GetNamedAttribute(GeometryAttribute::POSITION); + + typedef std::array<AttributeValueIndex::ValueType, 3> PosTriplet; + PosTriplet pos_indices; + std::unordered_set<PosTriplet, HashArray<PosTriplet>> is_face_used; + + uint32_t num_duplicate_faces = 0; + for (FaceIndex fi(0); fi < mesh->num_faces(); ++fi) { + const auto f = mesh->face(fi); + for (int c = 0; c < 3; ++c) { + pos_indices[c] = pos_att->mapped_index(f[c]).value(); + } + // Shift the position indices until the smallest index is the first one. + while (pos_indices[0] > pos_indices[1] || pos_indices[0] > pos_indices[2]) { + // Shift to the left. + std::swap(pos_indices[0], pos_indices[1]); + std::swap(pos_indices[1], pos_indices[2]); + } + // Check if have encountered the same position triplet on a different face. + if (is_face_used.find(pos_indices) != is_face_used.end()) { + // Duplicate face. Ignore it. + num_duplicate_faces++; + } else { + // Insert new face to the set. + is_face_used.insert(pos_indices); + if (num_duplicate_faces > 0) { + // Copy the face to its new location. + mesh->SetFace(fi - num_duplicate_faces, f); } - // Go over faces and update their points. - for (FaceIndex f(0); f < mesh->num_faces(); ++f) { - Mesh::Face face = mesh->face(f); - for (int p = 0; p < 3; ++p) { - face[p] = point_map[face[p]]; - } - mesh->SetFace(f, face); + } + } + if (num_duplicate_faces > 0) { + mesh->SetNumFaces(mesh->num_faces() - num_duplicate_faces); + } +} + +void MeshCleanup::RemoveUnusedAttributes(Mesh *mesh) { + // Array that is going to store whether a corresponding point is used. + std::vector<bool> is_point_used; + PointIndex::ValueType num_new_points = 0; + is_point_used.resize(mesh->num_points(), false); + for (FaceIndex f(0); f < mesh->num_faces(); ++f) { + const Mesh::Face &face = mesh->face(f); + for (int p = 0; p < 3; ++p) { + if (!is_point_used[face[p].value()]) { + is_point_used[face[p].value()] = true; + ++num_new_points; } - // Set the new number of points. - mesh->set_num_points(num_new_points); - points_changed = true; - } else { - // No points were removed. Initialize identity map between the old and new - // points. - for (PointIndex i(0); i < num_original_points; ++i) { - point_map[i] = i; + } + } + + bool points_changed = false; + const PointIndex::ValueType num_original_points = mesh->num_points(); + // Map from old points to the new ones. + IndexTypeVector<PointIndex, PointIndex> point_map(num_original_points); + if (num_new_points < static_cast<int>(mesh->num_points())) { + // Some of the points were removed. We need to remap the old points to the + // new ones. + num_new_points = 0; + for (PointIndex i(0); i < num_original_points; ++i) { + if (is_point_used[i.value()]) { + point_map[i] = num_new_points++; + } else { + point_map[i] = kInvalidPointIndex; + } + } + // Go over faces and update their points. + for (FaceIndex f(0); f < mesh->num_faces(); ++f) { + Mesh::Face face = mesh->face(f); + for (int p = 0; p < 3; ++p) { + face[p] = point_map[face[p]]; } + mesh->SetFace(f, face); } + // Set the new number of points. + mesh->set_num_points(num_new_points); + points_changed = true; + } else { + // No points were removed. Initialize identity map between the old and new + // points. + for (PointIndex i(0); i < num_original_points; ++i) { + point_map[i] = i; + } + } - // Update index mapping for attributes. - IndexTypeVector<AttributeValueIndex, uint8_t> is_att_index_used; - IndexTypeVector<AttributeValueIndex, AttributeValueIndex> att_index_map; - for (int a = 0; a < mesh->num_attributes(); ++a) { - PointAttribute *const att = mesh->attribute(a); - // First detect which attribute entries are used (included in a point). - is_att_index_used.assign(att->size(), 0); - att_index_map.clear(); - AttributeValueIndex::ValueType num_used_entries = 0; - for (PointIndex i(0); i < num_original_points; ++i) { - if (point_map[i] != kInvalidPointIndex) { - const AttributeValueIndex entry_id = att->mapped_index(i); - if (!is_att_index_used[entry_id]) { - is_att_index_used[entry_id] = 1; - ++num_used_entries; - } + // Update index mapping for attributes. + IndexTypeVector<AttributeValueIndex, uint8_t> is_att_index_used; + IndexTypeVector<AttributeValueIndex, AttributeValueIndex> att_index_map; + for (int a = 0; a < mesh->num_attributes(); ++a) { + PointAttribute *const att = mesh->attribute(a); + // First detect which attribute entries are used (included in a point). + is_att_index_used.assign(att->size(), 0); + att_index_map.clear(); + AttributeValueIndex::ValueType num_used_entries = 0; + for (PointIndex i(0); i < num_original_points; ++i) { + if (point_map[i] != kInvalidPointIndex) { + const AttributeValueIndex entry_id = att->mapped_index(i); + if (!is_att_index_used[entry_id]) { + is_att_index_used[entry_id] = 1; + ++num_used_entries; } } - bool att_indices_changed = false; - // If there are some unused attribute entries, remap the attribute values - // in the attribute buffer. - if (num_used_entries < static_cast<int>(att->size())) { - att_index_map.resize(att->size()); - num_used_entries = 0; - for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size()); - ++i) { - if (is_att_index_used[i]) { - att_index_map[i] = num_used_entries; - if (i > num_used_entries) { - const uint8_t *const src_add = att->GetAddress(i); - att->buffer()->Write( - att->GetBytePos(AttributeValueIndex(num_used_entries)), - src_add, att->byte_stride()); - } - ++num_used_entries; + } + bool att_indices_changed = false; + // If there are some unused attribute entries, remap the attribute values + // in the attribute buffer. + if (num_used_entries < static_cast<int>(att->size())) { + att_index_map.resize(att->size()); + num_used_entries = 0; + for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size()); + ++i) { + if (is_att_index_used[i]) { + att_index_map[i] = num_used_entries; + if (i > num_used_entries) { + const uint8_t *const src_add = att->GetAddress(i); + att->buffer()->Write( + att->GetBytePos(AttributeValueIndex(num_used_entries)), src_add, + att->byte_stride()); } + ++num_used_entries; } - // Update the number of unique entries in the vertex buffer. - att->Resize(num_used_entries); - att_indices_changed = true; } - // If either the points or attribute indices have changed, we need to - // update the attribute index mapping. - if (points_changed || att_indices_changed) { - if (att->is_mapping_identity()) { - // The mapping was identity. It'll remain identity only if the - // number of point and attribute indices is still the same. - if (num_used_entries != static_cast<int>(mesh->num_points())) { - // We need to create an explicit mapping. - // First we need to initialize the explicit map to the original - // number of points to recreate the original identity map. - att->SetExplicitMapping(num_original_points); - // Set the entries of the explicit map to identity. - for (PointIndex::ValueType i = 0; i < num_original_points; ++i) { - att->SetPointMapEntry(PointIndex(i), AttributeValueIndex(i)); - } + // Update the number of unique entries in the vertex buffer. + att->Resize(num_used_entries); + att_indices_changed = true; + } + // If either the points or attribute indices have changed, we need to + // update the attribute index mapping. + if (points_changed || att_indices_changed) { + if (att->is_mapping_identity()) { + // The mapping was identity. It'll remain identity only if the + // number of point and attribute indices is still the same. + if (num_used_entries != static_cast<int>(mesh->num_points())) { + // We need to create an explicit mapping. + // First we need to initialize the explicit map to the original + // number of points to recreate the original identity map. + att->SetExplicitMapping(num_original_points); + // Set the entries of the explicit map to identity. + for (PointIndex::ValueType i = 0; i < num_original_points; ++i) { + att->SetPointMapEntry(PointIndex(i), AttributeValueIndex(i)); } } - if (!att->is_mapping_identity()) { - // Explicit mapping between points and local attribute indices. - for (PointIndex i(0); i < num_original_points; ++i) { - // The new point id that maps to the currently processed attribute - // entry. - const PointIndex new_point_id = point_map[i]; - if (new_point_id == kInvalidPointIndex) { - continue; - } - // Index of the currently processed attribute entry in the original - // mesh. - const AttributeValueIndex original_entry_index = - att->mapped_index(i); - // New index of the same entry after unused entries were removed. - const AttributeValueIndex new_entry_index = - att_index_map[original_entry_index]; - att->SetPointMapEntry(new_point_id, new_entry_index); + } + if (!att->is_mapping_identity()) { + // Explicit mapping between points and local attribute indices. + for (PointIndex i(0); i < num_original_points; ++i) { + // The new point id that maps to the currently processed attribute + // entry. + const PointIndex new_point_id = point_map[i]; + if (new_point_id == kInvalidPointIndex) { + continue; } - // If the number of points changed, we need to set a new explicit map - // size. - att->SetExplicitMapping(mesh->num_points()); + // Index of the currently processed attribute entry in the original + // mesh. + const AttributeValueIndex original_entry_index = att->mapped_index(i); + // New index of the same entry after unused entries were removed. + const AttributeValueIndex new_entry_index = + att_indices_changed ? att_index_map[original_entry_index] + : original_entry_index; + + // Update the mapping. Note that the new point index is always smaller + // than the processed index |i|, making this operation safe. + att->SetPointMapEntry(new_point_id, new_entry_index); } + // If the number of points changed, we need to set a new explicit map + // size. + att->SetExplicitMapping(mesh->num_points()); } } } - return true; +} + +Status MeshCleanup::MakeGeometryManifold(Mesh *mesh) { + return Status(Status::DRACO_ERROR, "Unsupported function."); } } // namespace draco diff --git a/extern/draco/draco/src/draco/mesh/mesh_cleanup.h b/extern/draco/draco/src/draco/mesh/mesh_cleanup.h index b56129dce58..0acdc2ae5b8 100644 --- a/extern/draco/draco/src/draco/mesh/mesh_cleanup.h +++ b/extern/draco/draco/src/draco/mesh/mesh_cleanup.h @@ -15,27 +15,44 @@ #ifndef DRACO_MESH_MESH_CLEANUP_H_ #define DRACO_MESH_MESH_CLEANUP_H_ +#include "draco/core/status.h" #include "draco/mesh/mesh.h" namespace draco { // Options used by the MeshCleanup class. struct MeshCleanupOptions { - MeshCleanupOptions() - : remove_degenerated_faces(true), remove_unused_attributes(true) {} // If true, the cleanup tool removes any face where two or more vertices // share the same position index. - bool remove_degenerated_faces; + bool remove_degenerated_faces = true; + + // If true, the cleanup tool removes all duplicate faces. A pair of faces is + // duplicate if both faces share the same position indices on all vertices + // (that is, position values have to be duduplicated). Note that all + // non-position properties are currently ignored. + bool remove_duplicate_faces = true; + // If true, the cleanup tool removes any unused attribute value or unused // point id. For example, it can be used to remove isolated vertices. - bool remove_unused_attributes; + bool remove_unused_attributes = true; + + // If true, the cleanup tool splits vertices along non-manifold edges and + // vertices. This ensures that the connectivity defined by position indices + // is manifold. + bool make_geometry_manifold = false; }; // Tool that can be used for removing bad or unused data from draco::Meshes. class MeshCleanup { public: // Performs in-place cleanup of the input mesh according to the input options. - bool operator()(Mesh *mesh, const MeshCleanupOptions &options); + static Status Cleanup(Mesh *mesh, const MeshCleanupOptions &options); + + private: + static void RemoveDegeneratedFaces(Mesh *mesh); + static void RemoveDuplicateFaces(Mesh *mesh); + static void RemoveUnusedAttributes(Mesh *mesh); + static Status MakeGeometryManifold(Mesh *mesh); }; } // namespace draco diff --git a/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h index b450bc80cd8..0a3bcf49782 100644 --- a/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h +++ b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h @@ -67,7 +67,6 @@ inline bool IsCornerOppositeToAttributeSeam(CornerIndex ci, // Interpolates an attribute value on a face using given barycentric // coordinates. InterpolatedVectorT should be a VectorD that corresponds to the // values stored in the attribute. -// TODO(ostava): Find a better place for this. template <typename InterpolatedVectorT> InterpolatedVectorT ComputeInterpolatedAttributeValueOnMeshFace( const Mesh &mesh, const PointAttribute &attribute, FaceIndex fi, diff --git a/extern/draco/draco/src/draco/mesh/mesh_stripifier.h b/extern/draco/draco/src/draco/mesh/mesh_stripifier.h index 0c298f48e86..8e8d8d9f21f 100644 --- a/extern/draco/draco/src/draco/mesh/mesh_stripifier.h +++ b/extern/draco/draco/src/draco/mesh/mesh_stripifier.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#ifndef DRACO_SRC_DRACO_MESH_MESH_STRIPIFIER_H_ -#define DRACO_SRC_DRACO_MESH_MESH_STRIPIFIER_H_ +#ifndef DRACO_MESH_MESH_STRIPIFIER_H_ +#define DRACO_MESH_MESH_STRIPIFIER_H_ #include "draco/mesh/mesh_misc_functions.h" @@ -71,8 +71,6 @@ class MeshStripifier { mesh_ = &mesh; num_strips_ = 0; num_encoded_faces_ = 0; - // TODO(ostava): We may be able to avoid computing the corner table if we - // already have it stored somewhere. corner_table_ = CreateCornerTableFromPositionAttribute(mesh_); if (corner_table_ == nullptr) { return false; @@ -257,4 +255,4 @@ bool MeshStripifier::GenerateTriangleStripsWithDegenerateTriangles( } // namespace draco -#endif // DRACO_SRC_DRACO_MESH_MESH_STRIPIFIER_H_ +#endif // DRACO_MESH_MESH_STRIPIFIER_H_ diff --git a/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc index 60b0c50b8d5..cb767f871a9 100644 --- a/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc +++ b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc @@ -41,8 +41,6 @@ void TriangleSoupMeshBuilder::SetAttributeValuesForFace( att->SetAttributeValue(AttributeValueIndex(start_index), corner_value_0); att->SetAttributeValue(AttributeValueIndex(start_index + 1), corner_value_1); att->SetAttributeValue(AttributeValueIndex(start_index + 2), corner_value_2); - // TODO(ostava): The below code should be called only for one attribute. - // It will work OK even for multiple attributes, but it's redundant. mesh_->SetFace(face_id, {{PointIndex(start_index), PointIndex(start_index + 1), PointIndex(start_index + 2)}}); diff --git a/extern/draco/draco/src/draco/metadata/geometry_metadata.cc b/extern/draco/draco/src/draco/metadata/geometry_metadata.cc index b83898140ae..b6a882c0b1b 100644 --- a/extern/draco/draco/src/draco/metadata/geometry_metadata.cc +++ b/extern/draco/draco/src/draco/metadata/geometry_metadata.cc @@ -18,6 +18,19 @@ namespace draco { +AttributeMetadata::AttributeMetadata(const AttributeMetadata &metadata) + : Metadata(metadata) { + att_unique_id_ = metadata.att_unique_id_; +} + +GeometryMetadata::GeometryMetadata(const GeometryMetadata &metadata) + : Metadata(metadata) { + for (size_t i = 0; i < metadata.att_metadatas_.size(); ++i) { + att_metadatas_.push_back(std::unique_ptr<AttributeMetadata>( + new AttributeMetadata(*metadata.att_metadatas_[i]))); + } +} + const AttributeMetadata *GeometryMetadata::GetAttributeMetadataByStringEntry( const std::string &entry_name, const std::string &entry_value) const { for (auto &&att_metadata : att_metadatas_) { @@ -35,7 +48,7 @@ const AttributeMetadata *GeometryMetadata::GetAttributeMetadataByStringEntry( bool GeometryMetadata::AddAttributeMetadata( std::unique_ptr<AttributeMetadata> att_metadata) { - if (!att_metadata.get()) { + if (!att_metadata) { return false; } att_metadatas_.push_back(std::move(att_metadata)); diff --git a/extern/draco/draco/src/draco/metadata/geometry_metadata.h b/extern/draco/draco/src/draco/metadata/geometry_metadata.h index ec7ecb9ee68..531bdef2540 100644 --- a/extern/draco/draco/src/draco/metadata/geometry_metadata.h +++ b/extern/draco/draco/src/draco/metadata/geometry_metadata.h @@ -25,6 +25,7 @@ namespace draco { class AttributeMetadata : public Metadata { public: AttributeMetadata() : att_unique_id_(0) {} + AttributeMetadata(const AttributeMetadata &metadata); explicit AttributeMetadata(const Metadata &metadata) : Metadata(metadata), att_unique_id_(0) {} @@ -57,6 +58,7 @@ struct AttributeMetadataHasher { class GeometryMetadata : public Metadata { public: GeometryMetadata() {} + GeometryMetadata(const GeometryMetadata &metadata); explicit GeometryMetadata(const Metadata &metadata) : Metadata(metadata) {} const AttributeMetadata *GetAttributeMetadataByStringEntry( diff --git a/extern/draco/draco/src/draco/metadata/metadata.cc b/extern/draco/draco/src/draco/metadata/metadata.cc index 9141907ed71..51b4e93a328 100644 --- a/extern/draco/draco/src/draco/metadata/metadata.cc +++ b/extern/draco/draco/src/draco/metadata/metadata.cc @@ -122,6 +122,14 @@ const Metadata *Metadata::GetSubMetadata(const std::string &name) const { return sub_ptr->second.get(); } +Metadata *Metadata::sub_metadata(const std::string &name) { + auto sub_ptr = sub_metadatas_.find(name); + if (sub_ptr == sub_metadatas_.end()) { + return nullptr; + } + return sub_ptr->second.get(); +} + void Metadata::RemoveEntry(const std::string &name) { // Actually just remove "name", no need to check if it exists. auto entry_ptr = entries_.find(name); diff --git a/extern/draco/draco/src/draco/metadata/metadata.h b/extern/draco/draco/src/draco/metadata/metadata.h index 56d05e46a3e..12c1ba97439 100644 --- a/extern/draco/draco/src/draco/metadata/metadata.h +++ b/extern/draco/draco/src/draco/metadata/metadata.h @@ -147,6 +147,7 @@ class Metadata { bool AddSubMetadata(const std::string &name, std::unique_ptr<Metadata> sub_metadata); const Metadata *GetSubMetadata(const std::string &name) const; + Metadata *sub_metadata(const std::string &name); void RemoveEntry(const std::string &name); diff --git a/extern/draco/draco/src/draco/metadata/metadata_decoder.cc b/extern/draco/draco/src/draco/metadata/metadata_decoder.cc index e664e4fa524..a8e66f854cf 100644 --- a/extern/draco/draco/src/draco/metadata/metadata_decoder.cc +++ b/extern/draco/draco/src/draco/metadata/metadata_decoder.cc @@ -78,8 +78,10 @@ bool MetadataDecoder::DecodeMetadata(Metadata *metadata) { std::unique_ptr<Metadata> sub_metadata = std::unique_ptr<Metadata>(new Metadata()); metadata = sub_metadata.get(); - mp.parent_metadata->AddSubMetadata(sub_metadata_name, - std::move(sub_metadata)); + if (!mp.parent_metadata->AddSubMetadata(sub_metadata_name, + std::move(sub_metadata))) { + return false; + } } if (metadata == nullptr) { return false; @@ -98,6 +100,10 @@ bool MetadataDecoder::DecodeMetadata(Metadata *metadata) { if (!DecodeVarint(&num_sub_metadata, buffer_)) { return false; } + if (num_sub_metadata > buffer_->remaining_size()) { + // The decoded number of metadata items is unreasonably high. + return false; + } for (uint32_t i = 0; i < num_sub_metadata; ++i) { metadata_stack.push_back({metadata, nullptr}); } diff --git a/extern/draco/draco/src/draco/point_cloud/point_cloud.cc b/extern/draco/draco/src/draco/point_cloud/point_cloud.cc index 8eb638f80d4..55ad6670da5 100644 --- a/extern/draco/draco/src/draco/point_cloud/point_cloud.cc +++ b/extern/draco/draco/src/draco/point_cloud/point_cloud.cc @@ -241,7 +241,7 @@ void PointCloud::ApplyPointIdDeduplication( bool PointCloud::DeduplicateAttributeValues() { // Go over all attributes and create mapping between duplicate entries. if (num_points() == 0) { - return false; // Unexpected attribute size. + return true; // Nothing to deduplicate. } // Deduplicate all attributes. for (int32_t att_id = 0; att_id < num_attributes(); ++att_id) { @@ -253,17 +253,11 @@ bool PointCloud::DeduplicateAttributeValues() { } #endif -// TODO(xiaoxumeng): Consider to cash the BBox. +// TODO(b/199760503): Consider to cache the BBox. BoundingBox PointCloud::ComputeBoundingBox() const { - BoundingBox bounding_box = - BoundingBox(Vector3f(std::numeric_limits<float>::max(), - std::numeric_limits<float>::max(), - std::numeric_limits<float>::max()), - Vector3f(-std::numeric_limits<float>::max(), - -std::numeric_limits<float>::max(), - -std::numeric_limits<float>::max())); + BoundingBox bounding_box; auto pc_att = GetNamedAttribute(GeometryAttribute::POSITION); - // TODO(xiaoxumeng): Make the BoundingBox a template type, it may not be easy + // TODO(b/199760503): Make the BoundingBox a template type, it may not be easy // because PointCloud is not a template. // Or simply add some preconditioning here to make sure the position attribute // is valid, because the current code works only if the position attribute is @@ -274,7 +268,7 @@ BoundingBox PointCloud::ComputeBoundingBox() const { for (AttributeValueIndex i(0); i < static_cast<uint32_t>(pc_att->size()); ++i) { pc_att->GetValue(i, &p[0]); - bounding_box.update_bounding_box(p); + bounding_box.Update(p); } return bounding_box; } diff --git a/extern/draco/patches/blender.patch b/extern/draco/patches/blender.patch new file mode 100644 index 00000000000..de39260367b --- /dev/null +++ b/extern/draco/patches/blender.patch @@ -0,0 +1,30 @@ +diff --git a/draco/src/draco/attributes/geometry_attribute.h b/draco/src/draco/attributes/geometry_attribute.h +index fd478a4..c1c0148 100644 +--- a/draco/src/draco/attributes/geometry_attribute.h ++++ b/draco/src/draco/attributes/geometry_attribute.h +@@ -285,11 +285,25 @@ class GeometryAttribute { + // Make sure the in_value fits within the range of values that OutT + // is able to represent. Perform the check only for integral types. + if (std::is_integral<T>::value && std::is_integral<OutT>::value) { ++#ifdef _MSC_VER ++# pragma warning(push) ++# pragma warning(disable:4804) ++#endif ++#if defined(__GNUC__) && !defined(__clang__) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wbool-compare" ++#endif + static constexpr OutT kOutMin = + std::is_signed<T>::value ? std::numeric_limits<OutT>::lowest() : 0; + if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) { + return false; + } ++#ifdef __GNUC__ ++# pragma GCC diagnostic pop ++#endif ++#ifdef _MSC_VER ++# pragma warning(pop) ++#endif + } + + out_value[i] = static_cast<OutT>(in_value); diff --git a/extern/draco/src/common.cpp b/extern/draco/src/common.cpp index 6f98d8db7ef..3a11c126ece 100644 --- a/extern/draco/src/common.cpp +++ b/extern/draco/src/common.cpp @@ -54,20 +54,20 @@ size_t getComponentByteLength(size_t componentType) { switch (componentType) { - case ComponentType::Byte: - case ComponentType::UnsignedByte: - return 1; - - case ComponentType::Short: - case ComponentType::UnsignedShort: - return 2; - - case ComponentType::UnsignedInt: - case ComponentType::Float: - return 4; - - default: - return 0; + case ComponentType::Byte: + case ComponentType::UnsignedByte: + return 1; + + case ComponentType::Short: + case ComponentType::UnsignedShort: + return 2; + + case ComponentType::UnsignedInt: + case ComponentType::Float: + return 4; + + default: + return 0; } } diff --git a/extern/draco/src/common.h b/extern/draco/src/common.h index beaf7d91adb..eef50596350 100644 --- a/extern/draco/src/common.h +++ b/extern/draco/src/common.h @@ -33,7 +33,7 @@ #define API(returnType) extern "C" returnType #endif -enum ComponentType: size_t +enum ComponentType : size_t { Byte = 5120, UnsignedByte = 5121, diff --git a/extern/draco/src/decoder.cpp b/extern/draco/src/decoder.cpp index 3f3e03bd9f2..e5ec2b65e6c 100644 --- a/extern/draco/src/decoder.cpp +++ b/extern/draco/src/decoder.cpp @@ -17,7 +17,6 @@ * @date 2020-11-18 */ - #include "decoder.h" #include <memory> @@ -30,7 +29,8 @@ #define LOG_PREFIX "DracoDecoder | " -struct Decoder { +struct Decoder +{ std::unique_ptr<draco::Mesh> mesh; std::vector<uint8_t> indexBuffer; std::map<uint32_t, std::vector<uint8_t>> buffers; @@ -54,20 +54,20 @@ bool decoderDecode(Decoder *decoder, void *data, size_t byteLength) draco::Decoder dracoDecoder; draco::DecoderBuffer dracoDecoderBuffer; dracoDecoderBuffer.Init(reinterpret_cast<char *>(data), byteLength); - + auto decoderStatus = dracoDecoder.DecodeMeshFromBuffer(&dracoDecoderBuffer); if (!decoderStatus.ok()) { printf(LOG_PREFIX "Error during Draco decoding: %s\n", decoderStatus.status().error_msg()); return false; } - + decoder->mesh = std::move(decoderStatus).value(); decoder->vertexCount = decoder->mesh->num_points(); decoder->indexCount = decoder->mesh->num_faces() * 3; - + printf(LOG_PREFIX "Decoded %" PRIu32 " vertices, %" PRIu32 " indices\n", decoder->vertexCount, decoder->indexCount); - + return true; } @@ -83,32 +83,32 @@ uint32_t decoderGetIndexCount(Decoder *decoder) bool decoderAttributeIsNormalized(Decoder *decoder, uint32_t id) { - const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id); + const draco::PointAttribute *attribute = decoder->mesh->GetAttributeByUniqueId(id); return attribute != nullptr && attribute->normalized(); } bool decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType) { - const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id); - + const draco::PointAttribute *attribute = decoder->mesh->GetAttributeByUniqueId(id); + if (attribute == nullptr) { printf(LOG_PREFIX "Attribute with id=%" PRIu32 " does not exist in Draco data\n", id); return false; } - + size_t stride = getAttributeStride(componentType, dataType); - + std::vector<uint8_t> decodedData; decodedData.resize(stride * decoder->vertexCount); - + for (uint32_t i = 0; i < decoder->vertexCount; ++i) { auto index = attribute->mapped_index(draco::PointIndex(i)); uint8_t *value = decodedData.data() + i * stride; - + bool converted = false; - + switch (componentType) { case ComponentType::Byte: @@ -139,7 +139,7 @@ bool decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, c return false; } } - + decoder->buffers[id] = decodedData; return true; } @@ -166,13 +166,13 @@ void decoderCopyAttribute(Decoder *decoder, size_t id, void *output) } } -template<class T> +template <class T> void decodeIndices(Decoder *decoder) { std::vector<uint8_t> decodedIndices; decodedIndices.resize(decoder->indexCount * sizeof(T)); T *typedView = reinterpret_cast<T *>(decodedIndices.data()); - + for (uint32_t faceIndex = 0; faceIndex < decoder->mesh->num_faces(); ++faceIndex) { const draco::Mesh::Face &face = decoder->mesh->face(draco::FaceIndex(faceIndex)); @@ -180,7 +180,7 @@ void decodeIndices(Decoder *decoder) typedView[faceIndex * 3 + 1] = face[1].value(); typedView[faceIndex * 3 + 2] = face[2].value(); } - + decoder->indexBuffer = decodedIndices; } @@ -188,26 +188,26 @@ bool decoderReadIndices(Decoder *decoder, size_t indexComponentType) { switch (indexComponentType) { - case ComponentType::Byte: - decodeIndices<int8_t>(decoder); - break; - case ComponentType::UnsignedByte: - decodeIndices<uint8_t>(decoder); - break; - case ComponentType::Short: - decodeIndices<int16_t>(decoder); - break; - case ComponentType::UnsignedShort: - decodeIndices<uint16_t>(decoder); - break; - case ComponentType::UnsignedInt: - decodeIndices<uint32_t>(decoder); - break; - default: - printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType); - return false; + case ComponentType::Byte: + decodeIndices<int8_t>(decoder); + break; + case ComponentType::UnsignedByte: + decodeIndices<uint8_t>(decoder); + break; + case ComponentType::Short: + decodeIndices<int16_t>(decoder); + break; + case ComponentType::UnsignedShort: + decodeIndices<uint16_t>(decoder); + break; + case ComponentType::UnsignedInt: + decodeIndices<uint32_t>(decoder); + break; + default: + printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType); + return false; } - + return true; } diff --git a/extern/draco/src/decoder.h b/extern/draco/src/decoder.h index 914eb776e8f..c154b426c59 100644 --- a/extern/draco/src/decoder.h +++ b/extern/draco/src/decoder.h @@ -28,26 +28,38 @@ struct Decoder; -API(Decoder *) decoderCreate(); +API(Decoder *) +decoderCreate(); -API(void) decoderRelease(Decoder *decoder); +API(void) +decoderRelease(Decoder *decoder); -API(bool) decoderDecode(Decoder *decoder, void *data, size_t byteLength); +API(bool) +decoderDecode(Decoder *decoder, void *data, size_t byteLength); -API(uint32_t) decoderGetVertexCount(Decoder *decoder); +API(uint32_t) +decoderGetVertexCount(Decoder *decoder); -API(uint32_t) decoderGetIndexCount(Decoder *decoder); +API(uint32_t) +decoderGetIndexCount(Decoder *decoder); -API(bool) decoderAttributeIsNormalized(Decoder *decoder, uint32_t id); +API(bool) +decoderAttributeIsNormalized(Decoder *decoder, uint32_t id); -API(bool) decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType); +API(bool) +decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType); -API(size_t) decoderGetAttributeByteLength(Decoder *decoder, size_t id); +API(size_t) +decoderGetAttributeByteLength(Decoder *decoder, size_t id); -API(void) decoderCopyAttribute(Decoder *decoder, size_t id, void *output); +API(void) +decoderCopyAttribute(Decoder *decoder, size_t id, void *output); -API(bool) decoderReadIndices(Decoder *decoder, size_t indexComponentType); +API(bool) +decoderReadIndices(Decoder *decoder, size_t indexComponentType); -API(size_t) decoderGetIndicesByteLength(Decoder *decoder); +API(size_t) +decoderGetIndicesByteLength(Decoder *decoder); -API(void) decoderCopyIndices(Decoder *decoder, void *output); +API(void) +decoderCopyIndices(Decoder *decoder, void *output); diff --git a/extern/draco/src/encoder.cpp b/extern/draco/src/encoder.cpp index ff7570ecfcd..34282ced8c6 100644 --- a/extern/draco/src/encoder.cpp +++ b/extern/draco/src/encoder.cpp @@ -59,7 +59,8 @@ void encoderRelease(Encoder *encoder) delete encoder; } -void encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel) { +void encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel) +{ encoder->compressionLevel = compressionLevel; } @@ -75,7 +76,7 @@ void encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t no bool encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder) { printf(LOG_PREFIX "Preserve triangle order: %s\n", preserveTriangleOrder ? "yes" : "no"); - + draco::Encoder dracoEncoder; int speed = 10 - static_cast<int>(encoder->compressionLevel); @@ -87,12 +88,12 @@ bool encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder) dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, encoder->quantization.color); dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, encoder->quantization.generic); dracoEncoder.SetTrackEncodedProperties(true); - + if (preserveTriangleOrder) { dracoEncoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING); } - + auto encoderStatus = dracoEncoder.EncodeMeshToBuffer(encoder->mesh, &encoder->encoderBuffer); if (encoderStatus.ok()) { @@ -130,20 +131,19 @@ void encoderCopy(Encoder *encoder, uint8_t *data) memcpy(data, encoder->encoderBuffer.data(), encoder->encoderBuffer.size()); } -template<class T> +template <class T> void encodeIndices(Encoder *encoder, uint32_t indexCount, T *indices) { int face_count = indexCount / 3; encoder->mesh.SetNumFaces(static_cast<size_t>(face_count)); encoder->rawSize += indexCount * sizeof(T); - + for (int i = 0; i < face_count; ++i) { draco::Mesh::Face face = { draco::PointIndex(indices[3 * i + 0]), draco::PointIndex(indices[3 * i + 1]), - draco::PointIndex(indices[3 * i + 2]) - }; + draco::PointIndex(indices[3 * i + 2])}; encoder->mesh.SetFace(draco::FaceIndex(static_cast<uint32_t>(i)), face); } } @@ -152,23 +152,23 @@ void encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t ind { switch (indexComponentType) { - case ComponentType::Byte: - encodeIndices(encoder, indexCount, reinterpret_cast<int8_t *>(indices)); - break; - case ComponentType::UnsignedByte: - encodeIndices(encoder, indexCount, reinterpret_cast<uint8_t *>(indices)); - break; - case ComponentType::Short: - encodeIndices(encoder, indexCount, reinterpret_cast<int16_t *>(indices)); - break; - case ComponentType::UnsignedShort: - encodeIndices(encoder, indexCount, reinterpret_cast<uint16_t *>(indices)); - break; - case ComponentType::UnsignedInt: - encodeIndices(encoder, indexCount, reinterpret_cast<uint32_t *>(indices)); - break; - default: - printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType); + case ComponentType::Byte: + encodeIndices(encoder, indexCount, reinterpret_cast<int8_t *>(indices)); + break; + case ComponentType::UnsignedByte: + encodeIndices(encoder, indexCount, reinterpret_cast<uint8_t *>(indices)); + break; + case ComponentType::Short: + encodeIndices(encoder, indexCount, reinterpret_cast<int16_t *>(indices)); + break; + case ComponentType::UnsignedShort: + encodeIndices(encoder, indexCount, reinterpret_cast<uint16_t *>(indices)); + break; + case ComponentType::UnsignedInt: + encodeIndices(encoder, indexCount, reinterpret_cast<uint32_t *>(indices)); + break; + default: + printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType); } } @@ -190,7 +190,7 @@ draco::GeometryAttribute::Type getAttributeSemantics(char *attribute) { return draco::GeometryAttribute::COLOR; } - + return draco::GeometryAttribute::GENERIC; } @@ -198,37 +198,38 @@ draco::DataType getDataType(size_t componentType) { switch (componentType) { - case ComponentType::Byte: - return draco::DataType::DT_INT8; - - case ComponentType::UnsignedByte: - return draco::DataType::DT_UINT8; - - case ComponentType::Short: - return draco::DataType::DT_INT16; - - case ComponentType::UnsignedShort: - return draco::DataType::DT_UINT16; - - case ComponentType::UnsignedInt: - return draco::DataType::DT_UINT32; - - case ComponentType::Float: - return draco::DataType::DT_FLOAT32; - - default: - return draco::DataType::DT_INVALID; + case ComponentType::Byte: + return draco::DataType::DT_INT8; + + case ComponentType::UnsignedByte: + return draco::DataType::DT_UINT8; + + case ComponentType::Short: + return draco::DataType::DT_INT16; + + case ComponentType::UnsignedShort: + return draco::DataType::DT_UINT16; + + case ComponentType::UnsignedInt: + return draco::DataType::DT_UINT32; + + case ComponentType::Float: + return draco::DataType::DT_FLOAT32; + + default: + return draco::DataType::DT_INVALID; } } -API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data) +API(uint32_t) +encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data) { auto buffer = std::make_unique<draco::DataBuffer>(); uint32_t count = encoder->mesh.num_points(); size_t componentCount = getNumberOfComponents(dataType); size_t stride = getAttributeStride(componentType, dataType); draco::DataType dracoDataType = getDataType(componentType); - + draco::GeometryAttribute::Type semantics = getAttributeSemantics(attributeName); draco::GeometryAttribute attribute; attribute.Init(semantics, &*buffer, componentCount, getDataType(componentType), false, stride, 0); diff --git a/extern/draco/src/encoder.h b/extern/draco/src/encoder.h index 2f7f21a469b..c6fdc30295b 100644 --- a/extern/draco/src/encoder.h +++ b/extern/draco/src/encoder.h @@ -28,24 +28,35 @@ struct Encoder; -API(Encoder *) encoderCreate(uint32_t vertexCount); +API(Encoder *) +encoderCreate(uint32_t vertexCount); -API(void) encoderRelease(Encoder *encoder); +API(void) +encoderRelease(Encoder *encoder); -API(void) encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel); +API(void) +encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel); -API(void) encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic); +API(void) +encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic); -API(bool) encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder); +API(bool) +encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder); -API(uint64_t) encoderGetByteLength(Encoder *encoder); +API(uint64_t) +encoderGetByteLength(Encoder *encoder); -API(void) encoderCopy(Encoder *encoder, uint8_t *data); +API(void) +encoderCopy(Encoder *encoder, uint8_t *data); -API(void) encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices); +API(void) +encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices); -API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data); +API(uint32_t) +encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data); -API(uint32_t) encoderGetEncodedVertexCount(Encoder *encoder); +API(uint32_t) +encoderGetEncodedVertexCount(Encoder *encoder); -API(uint32_t) encoderGetEncodedIndexCount(Encoder *encoder); +API(uint32_t) +encoderGetEncodedIndexCount(Encoder *encoder); diff --git a/intern/cycles/blender/camera.cpp b/intern/cycles/blender/camera.cpp index 402fd7c4ec6..2ab5f02a337 100644 --- a/intern/cycles/blender/camera.cpp +++ b/intern/cycles/blender/camera.cpp @@ -643,7 +643,7 @@ void BlenderSync::sync_camera_motion( /* TODO(sergey): De-duplicate calculation with camera sync. */ float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio); if (fov != cam->get_fov()) { - VLOG(3) << "Camera " << b_ob.name() << " FOV change detected."; + VLOG_WORK << "Camera " << b_ob.name() << " FOV change detected."; if (motion_time == 0.0f) { cam->set_fov(fov); } diff --git a/intern/cycles/blender/curves.cpp b/intern/cycles/blender/curves.cpp index 4e9f4f62087..b01cb85711a 100644 --- a/intern/cycles/blender/curves.cpp +++ b/intern/cycles/blender/curves.cpp @@ -341,7 +341,7 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa /* check allocation */ if ((hair->get_curve_keys().size() != num_keys) || (hair->num_curves() != num_curves)) { - VLOG(1) << "Hair memory allocation failed, clearing data."; + VLOG_WARNING << "Hair memory allocation failed, clearing data."; hair->clear(true); } } @@ -397,7 +397,7 @@ static void export_hair_motion_validate_attribute(Hair *hair, if (num_motion_keys != num_keys || !have_motion) { /* No motion or hair "topology" changed, remove attributes again. */ if (num_motion_keys != num_keys) { - VLOG(1) << "Hair topology changed, removing motion attribute."; + VLOG_WORK << "Hair topology changed, removing motion attribute."; } hair->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); } diff --git a/intern/cycles/blender/display_driver.cpp b/intern/cycles/blender/display_driver.cpp index ee67073a9a4..a1bc064be68 100644 --- a/intern/cycles/blender/display_driver.cpp +++ b/intern/cycles/blender/display_driver.cpp @@ -982,10 +982,8 @@ void BlenderDisplayDriver::draw(const Params ¶ms) gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); - if (VLOG_IS_ON(5)) { - VLOG(5) << "Number of textures: " << GLTexture::num_used; - VLOG(5) << "Number of PBOs: " << GLPixelBufferObject::num_used; - } + VLOG_DEVICE_STATS << "Display driver number of textures: " << GLTexture::num_used; + VLOG_DEVICE_STATS << "Display driver number of PBOs: " << GLPixelBufferObject::num_used; if (use_gl_context_) { gl_context_mutex_.unlock(); diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index e2db52cc5c1..63913b7cd7f 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -1212,17 +1212,17 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) { /* no motion, remove attributes again */ if (b_mesh.vertices.length() != numverts) { - VLOG(1) << "Topology differs, disabling motion blur for object " << ob_name; + VLOG_WARNING << "Topology differs, disabling motion blur for object " << ob_name; } else { - VLOG(1) << "No actual deformation motion for object " << ob_name; + VLOG_DEBUG << "No actual deformation motion for object " << ob_name; } mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mN) mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL); } else if (motion_step > 0) { - VLOG(1) << "Filling deformation motion for object " << ob_name; + VLOG_DEBUG << "Filling deformation motion for object " << ob_name; /* motion, fill up previous steps that we might have skipped because * they had no motion, but we need them anyway now */ float3 *P = &mesh->get_verts()[0]; @@ -1236,8 +1236,8 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, } else { if (b_mesh.vertices.length() != numverts) { - VLOG(1) << "Topology differs, discarding motion blur for object " << ob_name << " at time " - << motion_step; + VLOG_WARNING << "Topology differs, discarding motion blur for object " << ob_name + << " at time " << motion_step; memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts); if (mN != NULL) { memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts); diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp index 9b08b564b25..ca1aa6329d9 100644 --- a/intern/cycles/blender/object.cpp +++ b/intern/cycles/blender/object.cpp @@ -762,7 +762,7 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render, continue; } - VLOG(1) << "Synchronizing motion for the relative time " << relative_time << "."; + VLOG_WORK << "Synchronizing motion for the relative time " << relative_time << "."; /* fixed shutter time to get previous and next frame for motion pass */ float shuttertime = scene->motion_shutter_time(); diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp index 87f051ba50b..6d27b8e7d87 100644 --- a/intern/cycles/blender/session.cpp +++ b/intern/cycles/blender/session.cpp @@ -458,8 +458,8 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) double total_time, render_time; session->progress.get_time(total_time, render_time); - VLOG(1) << "Total render time: " << total_time; - VLOG(1) << "Render time (without synchronization): " << render_time; + VLOG_INFO << "Total render time: " << total_time; + VLOG_INFO << "Render time (without synchronization): " << render_time; } void BlenderSession::render_frame_finish() diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index 1028c940772..63e9e1e0e68 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -285,7 +285,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, free_data_after_sync(b_depsgraph); - VLOG(1) << "Total time spent synchronizing data: " << timer.get_time(); + VLOG_INFO << "Total time spent synchronizing data: " << timer.get_time(); has_updates_ = false; } @@ -390,7 +390,7 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background) } if (scrambling_distance != 1.0f) { - VLOG(3) << "Using scrambling distance: " << scrambling_distance; + VLOG_INFO << "Using scrambling distance: " << scrambling_distance; } integrator->set_scrambling_distance(scrambling_distance); diff --git a/intern/cycles/bvh/build.cpp b/intern/cycles/bvh/build.cpp index 1df3517673e..cf03f05de60 100644 --- a/intern/cycles/bvh/build.cpp +++ b/intern/cycles/bvh/build.cpp @@ -529,7 +529,7 @@ BVHNode *BVHBuild::run() if (progress.get_cancel()) { rootnode->deleteSubtree(); rootnode = NULL; - VLOG(1) << "BVH build cancelled."; + VLOG_WORK << "BVH build cancelled."; } else { /*rotate(rootnode, 4, 5);*/ @@ -537,26 +537,26 @@ BVHNode *BVHBuild::run() rootnode->update_time(); } if (rootnode != NULL) { - VLOG(1) << "BVH build statistics:\n" - << " Build time: " << time_dt() - build_start_time << "\n" - << " Total number of nodes: " - << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT)) - << "\n" - << " Number of inner nodes: " - << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT)) - << "\n" - << " Number of leaf nodes: " - << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT)) - << "\n" - << " Number of unaligned nodes: " - << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_UNALIGNED_COUNT)) - << "\n" - << " Allocation slop factor: " - << ((prim_type.capacity() != 0) ? (float)prim_type.size() / prim_type.capacity() : - 1.0f) - << "\n" - << " Maximum depth: " - << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_DEPTH)) << "\n"; + VLOG_WORK << "BVH build statistics:\n" + << " Build time: " << time_dt() - build_start_time << "\n" + << " Total number of nodes: " + << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT)) + << "\n" + << " Number of inner nodes: " + << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT)) + << "\n" + << " Number of leaf nodes: " + << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT)) + << "\n" + << " Number of unaligned nodes: " + << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_UNALIGNED_COUNT)) + << "\n" + << " Allocation slop factor: " + << ((prim_type.capacity() != 0) ? (float)prim_type.size() / prim_type.capacity() : + 1.0f) + << "\n" + << " Maximum depth: " + << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_DEPTH)) << "\n"; } } diff --git a/intern/cycles/bvh/embree.cpp b/intern/cycles/bvh/embree.cpp index 0fc71f49ce3..eed7ae19965 100644 --- a/intern/cycles/bvh/embree.cpp +++ b/intern/cycles/bvh/embree.cpp @@ -250,7 +250,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) *isect = current_isect; /* Only primitives from volume object. */ uint tri_object = isect->object; - int object_flag = kernel_tex_fetch(__object_flag, tri_object); + int object_flag = kernel_data_fetch(object_flag, tri_object); if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { --ctx->num_hits; } @@ -332,7 +332,7 @@ static bool rtc_memory_monitor_func(void *userPtr, const ssize_t bytes, const bo static void rtc_error_func(void *, enum RTCError, const char *str) { - VLOG(1) << str; + VLOG_WARNING << str; } static double progress_start_time = 0.0; @@ -521,8 +521,8 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i) geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(int) * 3, num_triangles); assert(rtc_indices); if (!rtc_indices) { - VLOG(1) << "Embree could not create new geometry buffer for mesh " << mesh->name.c_str() - << ".\n"; + VLOG_WARNING << "Embree could not create new geometry buffer for mesh " << mesh->name.c_str() + << ".\n"; return; } for (size_t j = 0; j < num_triangles; ++j) { diff --git a/intern/cycles/device/cpu/device_impl.cpp b/intern/cycles/device/cpu/device_impl.cpp index 612c391f7d5..d4f0532aa5e 100644 --- a/intern/cycles/device/cpu/device_impl.cpp +++ b/intern/cycles/device/cpu/device_impl.cpp @@ -51,12 +51,12 @@ CCL_NAMESPACE_BEGIN CPUDevice::CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_) - : Device(info_, stats_, profiler_), texture_info(this, "__texture_info", MEM_GLOBAL) + : Device(info_, stats_, profiler_), texture_info(this, "texture_info", MEM_GLOBAL) { /* Pick any kernel, all of them are supposed to have same level of microarchitecture * optimization. */ - VLOG(1) << "Using " << get_cpu_kernels().integrator_init_from_camera.get_uarch_name() - << " CPU kernels."; + VLOG_INFO << "Using " << get_cpu_kernels().integrator_init_from_camera.get_uarch_name() + << " CPU kernels."; if (info.cpu_threads == 0) { info.cpu_threads = TaskScheduler::max_concurrency(); @@ -111,9 +111,9 @@ void CPUDevice::mem_alloc(device_memory &mem) } else { if (mem.name) { - VLOG(1) << "Buffer allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Buffer allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; } if (mem.type == MEM_DEVICE_ONLY || !mem.host_pointer) { @@ -192,7 +192,7 @@ device_ptr CPUDevice::mem_alloc_sub_ptr(device_memory &mem, size_t offset, size_ void CPUDevice::const_copy_to(const char *name, void *host, size_t size) { #ifdef WITH_EMBREE - if (strcmp(name, "__data") == 0) { + if (strcmp(name, "data") == 0) { assert(size <= sizeof(KernelData)); // Update scene handle (since it is different for each device on multi devices) @@ -205,9 +205,9 @@ void CPUDevice::const_copy_to(const char *name, void *host, size_t size) void CPUDevice::global_alloc(device_memory &mem) { - VLOG(1) << "Global memory allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Global memory allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; kernel_global_memory_copy(&kernel_globals, mem.name, mem.host_pointer, mem.data_size); @@ -227,9 +227,9 @@ void CPUDevice::global_free(device_memory &mem) void CPUDevice::tex_alloc(device_texture &mem) { - VLOG(1) << "Texture allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Texture allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; mem.device_pointer = (device_ptr)mem.host_pointer; mem.device_size = mem.memory_size(); diff --git a/intern/cycles/device/cuda/device.cpp b/intern/cycles/device/cuda/device.cpp index 400490336d6..5a213c45b71 100644 --- a/intern/cycles/device/cuda/device.cpp +++ b/intern/cycles/device/cuda/device.cpp @@ -29,24 +29,25 @@ bool device_cuda_init() initialized = true; int cuew_result = cuewInit(CUEW_INIT_CUDA); if (cuew_result == CUEW_SUCCESS) { - VLOG(1) << "CUEW initialization succeeded"; + VLOG_INFO << "CUEW initialization succeeded"; if (CUDADevice::have_precompiled_kernels()) { - VLOG(1) << "Found precompiled kernels"; + VLOG_INFO << "Found precompiled kernels"; result = true; } else if (cuewCompilerPath() != NULL) { - VLOG(1) << "Found CUDA compiler " << cuewCompilerPath(); + VLOG_INFO << "Found CUDA compiler " << cuewCompilerPath(); result = true; } else { - VLOG(1) << "Neither precompiled kernels nor CUDA compiler was found," - << " unable to use CUDA"; + VLOG_INFO << "Neither precompiled kernels nor CUDA compiler was found," + << " unable to use CUDA"; } } else { - VLOG(1) << "CUEW initialization failed: " - << ((cuew_result == CUEW_ERROR_ATEXIT_FAILED) ? "Error setting up atexit() handler" : - "Error opening the library"); + VLOG_WARNING << "CUEW initialization failed: " + << ((cuew_result == CUEW_ERROR_ATEXIT_FAILED) ? + "Error setting up atexit() handler" : + "Error opening the library"); } return result; @@ -121,7 +122,8 @@ void device_cuda_info(vector<DeviceInfo> &devices) int major; cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, num); if (major < 3) { - VLOG(1) << "Ignoring device \"" << name << "\", this graphics card is no longer supported."; + VLOG_INFO << "Ignoring device \"" << name + << "\", this graphics card is no longer supported."; continue; } @@ -166,21 +168,21 @@ void device_cuda_info(vector<DeviceInfo> &devices) * Windows 10 even when it is, due to an issue in application profiles. * Detect case where we expect it to be available and override. */ if (preempt_attr == 0 && (major >= 6) && system_windows_version_at_least(10, 17134)) { - VLOG(1) << "Assuming device has compute preemption on Windows 10."; + VLOG_INFO << "Assuming device has compute preemption on Windows 10."; preempt_attr = 1; } if (timeout_attr && !preempt_attr) { - VLOG(1) << "Device is recognized as display."; + VLOG_INFO << "Device is recognized as display."; info.description += " (Display)"; info.display_device = true; display_devices.push_back(info); } else { - VLOG(1) << "Device has compute preemption or is not used for display."; + VLOG_INFO << "Device has compute preemption or is not used for display."; devices.push_back(info); } - VLOG(1) << "Added device \"" << name << "\" with id \"" << info.id << "\"."; + VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\"."; } if (!display_devices.empty()) diff --git a/intern/cycles/device/cuda/device_impl.cpp b/intern/cycles/device/cuda/device_impl.cpp index cb7e909a2d5..00851a8e91c 100644 --- a/intern/cycles/device/cuda/device_impl.cpp +++ b/intern/cycles/device/cuda/device_impl.cpp @@ -23,6 +23,8 @@ # include "util/types.h" # include "util/windows.h" +# include "kernel/device/cuda/globals.h" + CCL_NAMESPACE_BEGIN class CUDADevice; @@ -51,7 +53,7 @@ void CUDADevice::set_error(const string &error) } CUDADevice::CUDADevice(const DeviceInfo &info, Stats &stats, Profiler &profiler) - : Device(info, stats, profiler), texture_info(this, "__texture_info", MEM_GLOBAL) + : Device(info, stats, profiler), texture_info(this, "texture_info", MEM_GLOBAL) { first_error = true; @@ -244,9 +246,9 @@ string CUDADevice::compile_kernel(const uint kernel_features, if (!use_adaptive_compilation()) { if (!force_ptx) { const string cubin = path_get(string_printf("lib/%s_sm_%d%d.cubin", name, major, minor)); - VLOG(1) << "Testing for pre-compiled kernel " << cubin << "."; + VLOG_INFO << "Testing for pre-compiled kernel " << cubin << "."; if (path_exists(cubin)) { - VLOG(1) << "Using precompiled kernel."; + VLOG_INFO << "Using precompiled kernel."; return cubin; } } @@ -256,9 +258,9 @@ string CUDADevice::compile_kernel(const uint kernel_features, while (ptx_major >= 3) { const string ptx = path_get( string_printf("lib/%s_compute_%d%d.ptx", name, ptx_major, ptx_minor)); - VLOG(1) << "Testing for pre-compiled kernel " << ptx << "."; + VLOG_INFO << "Testing for pre-compiled kernel " << ptx << "."; if (path_exists(ptx)) { - VLOG(1) << "Using precompiled kernel."; + VLOG_INFO << "Using precompiled kernel."; return ptx; } @@ -287,9 +289,9 @@ string CUDADevice::compile_kernel(const uint kernel_features, const string cubin_file = string_printf( "cycles_%s_%s_%d%d_%s.%s", name, kernel_arch, major, minor, kernel_md5.c_str(), kernel_ext); const string cubin = path_cache_get(path_join("kernels", cubin_file)); - VLOG(1) << "Testing for locally compiled kernel " << cubin << "."; + VLOG_INFO << "Testing for locally compiled kernel " << cubin << "."; if (path_exists(cubin)) { - VLOG(1) << "Using locally compiled kernel."; + VLOG_INFO << "Using locally compiled kernel."; return cubin; } @@ -323,7 +325,7 @@ string CUDADevice::compile_kernel(const uint kernel_features, } const int nvcc_cuda_version = cuewCompilerVersion(); - VLOG(1) << "Found nvcc " << nvcc << ", CUDA version " << nvcc_cuda_version << "."; + VLOG_INFO << "Found nvcc " << nvcc << ", CUDA version " << nvcc_cuda_version << "."; if (nvcc_cuda_version < 101) { printf( "Unsupported CUDA version %d.%d detected, " @@ -399,7 +401,8 @@ bool CUDADevice::load_kernels(const uint kernel_features) */ if (cuModule) { if (use_adaptive_compilation()) { - VLOG(1) << "Skipping CUDA kernel reload for adaptive compilation, not currently supported."; + VLOG_INFO + << "Skipping CUDA kernel reload for adaptive compilation, not currently supported."; } return true; } @@ -481,8 +484,8 @@ void CUDADevice::reserve_local_memory(const uint kernel_features) cuMemGetInfo(&free_after, &total); } - VLOG(1) << "Local memory reserved " << string_human_readable_number(free_before - free_after) - << " bytes. (" << string_human_readable_size(free_before - free_after) << ")"; + VLOG_INFO << "Local memory reserved " << string_human_readable_number(free_before - free_after) + << " bytes. (" << string_human_readable_size(free_before - free_after) << ")"; # if 0 /* For testing mapped host memory, fill up device memory. */ @@ -513,7 +516,7 @@ void CUDADevice::init_host_memory() } } else { - VLOG(1) << "Mapped host memory disabled, failed to get system RAM"; + VLOG_WARNING << "Mapped host memory disabled, failed to get system RAM"; map_host_limit = 0; } @@ -524,8 +527,8 @@ void CUDADevice::init_host_memory() device_working_headroom = 32 * 1024 * 1024LL; // 32MB device_texture_headroom = 128 * 1024 * 1024LL; // 128MB - VLOG(1) << "Mapped host memory limit set to " << string_human_readable_number(map_host_limit) - << " bytes. (" << string_human_readable_size(map_host_limit) << ")"; + VLOG_INFO << "Mapped host memory limit set to " << string_human_readable_number(map_host_limit) + << " bytes. (" << string_human_readable_size(map_host_limit) << ")"; } void CUDADevice::load_texture_info() @@ -593,7 +596,7 @@ void CUDADevice::move_textures_to_host(size_t size, bool for_texture) * multiple CUDA devices could be moving the memory. The * first one will do it, and the rest will adopt the pointer. */ if (max_mem) { - VLOG(1) << "Move memory from device to host: " << max_mem->name; + VLOG_WORK << "Move memory from device to host: " << max_mem->name; static thread_mutex move_mutex; thread_scoped_lock lock(move_mutex); @@ -701,9 +704,9 @@ CUDADevice::CUDAMem *CUDADevice::generic_alloc(device_memory &mem, size_t pitch_ } if (mem.name) { - VLOG(1) << "Buffer allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")" << status; + VLOG_WORK << "Buffer allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")" << status; } mem.device_pointer = (device_ptr)device_pointer; @@ -899,9 +902,19 @@ void CUDADevice::const_copy_to(const char *name, void *host, size_t size) CUdeviceptr mem; size_t bytes; - cuda_assert(cuModuleGetGlobal(&mem, &bytes, cuModule, name)); - // assert(bytes == size); - cuda_assert(cuMemcpyHtoD(mem, host, size)); + cuda_assert(cuModuleGetGlobal(&mem, &bytes, cuModule, "kernel_params")); + assert(bytes == sizeof(KernelParamsCUDA)); + + /* Update data storage pointers in launch parameters. */ +# define KERNEL_DATA_ARRAY(data_type, data_name) \ + if (strcmp(name, #data_name) == 0) { \ + cuda_assert(cuMemcpyHtoD(mem + offsetof(KernelParamsCUDA, data_name), host, size)); \ + return; \ + } + KERNEL_DATA_ARRAY(KernelData, data) + KERNEL_DATA_ARRAY(IntegratorStateGPU, integrator_state) +# include "kernel/data_arrays.h" +# undef KERNEL_DATA_ARRAY } void CUDADevice::global_alloc(device_memory &mem) @@ -925,7 +938,6 @@ void CUDADevice::tex_alloc(device_texture &mem) { CUDAContextScope scope(this); - string bind_name = mem.name; size_t dsize = datatype_size(mem.data_type); size_t size = mem.memory_size(); @@ -1008,9 +1020,9 @@ void CUDADevice::tex_alloc(device_texture &mem) desc.NumChannels = mem.data_elements; desc.Flags = 0; - VLOG(1) << "Array 3D allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Array 3D allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; cuda_assert(cuArray3DCreate(&array_3d, &desc)); diff --git a/intern/cycles/device/cuda/queue.cpp b/intern/cycles/device/cuda/queue.cpp index 38c71866ad0..5912e68a92b 100644 --- a/intern/cycles/device/cuda/queue.cpp +++ b/intern/cycles/device/cuda/queue.cpp @@ -39,12 +39,12 @@ int CUDADeviceQueue::num_concurrent_states(const size_t state_size) const num_states = max((int)(num_states * factor), 1024); } else { - VLOG(3) << "CYCLES_CONCURRENT_STATES_FACTOR evaluated to 0"; + VLOG_DEVICE_STATS << "CYCLES_CONCURRENT_STATES_FACTOR evaluated to 0"; } } - VLOG(3) << "GPU queue concurrent states: " << num_states << ", using up to " - << string_human_readable_size(num_states * state_size); + VLOG_DEVICE_STATS << "GPU queue concurrent states: " << num_states << ", using up to " + << string_human_readable_size(num_states * state_size); return num_states; } diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index ea5b3c6dc8c..82c7881da5f 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -325,8 +325,8 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices, int orig_cpu_threads = (threads) ? threads : TaskScheduler::max_concurrency(); int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), size_t(0)); - VLOG(1) << "CPU render threads reduced from " << orig_cpu_threads << " to " << cpu_threads - << ", to dedicate to GPU."; + VLOG_INFO << "CPU render threads reduced from " << orig_cpu_threads << " to " + << cpu_threads << ", to dedicate to GPU."; if (cpu_threads >= 1) { DeviceInfo cpu_device = device; @@ -338,7 +338,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices, } } else { - VLOG(1) << "CPU render threads disabled for interactive render."; + VLOG_INFO << "CPU render threads disabled for interactive render."; continue; } } diff --git a/intern/cycles/device/hip/device.cpp b/intern/cycles/device/hip/device.cpp index d6a5ed9c419..3c9c73e7db0 100644 --- a/intern/cycles/device/hip/device.cpp +++ b/intern/cycles/device/hip/device.cpp @@ -29,30 +29,31 @@ bool device_hip_init() initialized = true; int hipew_result = hipewInit(HIPEW_INIT_HIP); if (hipew_result == HIPEW_SUCCESS) { - VLOG(1) << "HIPEW initialization succeeded"; + VLOG_INFO << "HIPEW initialization succeeded"; if (HIPDevice::have_precompiled_kernels()) { - VLOG(1) << "Found precompiled kernels"; + VLOG_INFO << "Found precompiled kernels"; result = true; } else if (hipewCompilerPath() != NULL) { - VLOG(1) << "Found HIPCC " << hipewCompilerPath(); + VLOG_INFO << "Found HIPCC " << hipewCompilerPath(); result = true; } else { - VLOG(1) << "Neither precompiled kernels nor HIPCC was found," - << " unable to use HIP"; + VLOG_INFO << "Neither precompiled kernels nor HIPCC was found," + << " unable to use HIP"; } } else { if (hipew_result == HIPEW_ERROR_ATEXIT_FAILED) { - VLOG(1) << "HIPEW initialization failed: Error setting up atexit() handler"; + VLOG_WARNING << "HIPEW initialization failed: Error setting up atexit() handler"; } else if (hipew_result == HIPEW_ERROR_OLD_DRIVER) { - VLOG(1) << "HIPEW initialization failed: Driver version too old, requires AMD Radeon Pro " - "21.Q4 driver or newer"; + VLOG_WARNING + << "HIPEW initialization failed: Driver version too old, requires AMD Radeon Pro " + "21.Q4 driver or newer"; } else { - VLOG(1) << "HIPEW initialization failed: Error opening HIP dynamic library"; + VLOG_WARNING << "HIPEW initialization failed: Error opening HIP dynamic library"; } } @@ -165,16 +166,16 @@ void device_hip_info(vector<DeviceInfo> &devices) hipDeviceGetAttribute(&timeout_attr, hipDeviceAttributeKernelExecTimeout, num); if (timeout_attr && !preempt_attr) { - VLOG(1) << "Device is recognized as display."; + VLOG_INFO << "Device is recognized as display."; info.description += " (Display)"; info.display_device = true; display_devices.push_back(info); } else { - VLOG(1) << "Device has compute preemption or is not used for display."; + VLOG_INFO << "Device has compute preemption or is not used for display."; devices.push_back(info); } - VLOG(1) << "Added device \"" << name << "\" with id \"" << info.id << "\"."; + VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\"."; } if (!display_devices.empty()) diff --git a/intern/cycles/device/hip/device_impl.cpp b/intern/cycles/device/hip/device_impl.cpp index ea68c821166..82db55ea715 100644 --- a/intern/cycles/device/hip/device_impl.cpp +++ b/intern/cycles/device/hip/device_impl.cpp @@ -24,6 +24,8 @@ # include "util/types.h" # include "util/windows.h" +# include "kernel/device/hip/globals.h" + CCL_NAMESPACE_BEGIN class HIPDevice; @@ -52,7 +54,7 @@ void HIPDevice::set_error(const string &error) } HIPDevice::HIPDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler) - : Device(info, stats, profiler), texture_info(this, "__texture_info", MEM_GLOBAL) + : Device(info, stats, profiler), texture_info(this, "texture_info", MEM_GLOBAL) { first_error = true; @@ -233,9 +235,9 @@ string HIPDevice::compile_kernel(const uint kernel_features, const char *name, c /* Attempt to use kernel provided with Blender. */ if (!use_adaptive_compilation()) { const string fatbin = path_get(string_printf("lib/%s_%s.fatbin", name, arch)); - VLOG(1) << "Testing for pre-compiled kernel " << fatbin << "."; + VLOG_INFO << "Testing for pre-compiled kernel " << fatbin << "."; if (path_exists(fatbin)) { - VLOG(1) << "Using precompiled kernel."; + VLOG_INFO << "Using precompiled kernel."; return fatbin; } } @@ -265,9 +267,9 @@ string HIPDevice::compile_kernel(const uint kernel_features, const char *name, c const string include_path = source_path; const string fatbin_file = string_printf("cycles_%s_%s_%s", name, arch, kernel_md5.c_str()); const string fatbin = path_cache_get(path_join("kernels", fatbin_file)); - VLOG(1) << "Testing for locally compiled kernel " << fatbin << "."; + VLOG_INFO << "Testing for locally compiled kernel " << fatbin << "."; if (path_exists(fatbin)) { - VLOG(1) << "Using locally compiled kernel."; + VLOG_INFO << "Using locally compiled kernel."; return fatbin; } @@ -301,7 +303,7 @@ string HIPDevice::compile_kernel(const uint kernel_features, const char *name, c } const int hipcc_hip_version = hipewCompilerVersion(); - VLOG(1) << "Found hipcc " << hipcc << ", HIP version " << hipcc_hip_version << "."; + VLOG_INFO << "Found hipcc " << hipcc << ", HIP version " << hipcc_hip_version << "."; if (hipcc_hip_version < 40) { printf( "Unsupported HIP version %d.%d detected, " @@ -361,7 +363,7 @@ bool HIPDevice::load_kernels(const uint kernel_features) */ if (hipModule) { if (use_adaptive_compilation()) { - VLOG(1) << "Skipping HIP kernel reload for adaptive compilation, not currently supported."; + VLOG_INFO << "Skipping HIP kernel reload for adaptive compilation, not currently supported."; } return true; } @@ -444,8 +446,8 @@ void HIPDevice::reserve_local_memory(const uint kernel_features) hipMemGetInfo(&free_after, &total); } - VLOG(1) << "Local memory reserved " << string_human_readable_number(free_before - free_after) - << " bytes. (" << string_human_readable_size(free_before - free_after) << ")"; + VLOG_INFO << "Local memory reserved " << string_human_readable_number(free_before - free_after) + << " bytes. (" << string_human_readable_size(free_before - free_after) << ")"; # if 0 /* For testing mapped host memory, fill up device memory. */ @@ -476,7 +478,7 @@ void HIPDevice::init_host_memory() } } else { - VLOG(1) << "Mapped host memory disabled, failed to get system RAM"; + VLOG_WARNING << "Mapped host memory disabled, failed to get system RAM"; map_host_limit = 0; } @@ -487,8 +489,8 @@ void HIPDevice::init_host_memory() device_working_headroom = 32 * 1024 * 1024LL; // 32MB device_texture_headroom = 128 * 1024 * 1024LL; // 128MB - VLOG(1) << "Mapped host memory limit set to " << string_human_readable_number(map_host_limit) - << " bytes. (" << string_human_readable_size(map_host_limit) << ")"; + VLOG_INFO << "Mapped host memory limit set to " << string_human_readable_number(map_host_limit) + << " bytes. (" << string_human_readable_size(map_host_limit) << ")"; } void HIPDevice::load_texture_info() @@ -556,7 +558,7 @@ void HIPDevice::move_textures_to_host(size_t size, bool for_texture) * multiple HIP devices could be moving the memory. The * first one will do it, and the rest will adopt the pointer. */ if (max_mem) { - VLOG(1) << "Move memory from device to host: " << max_mem->name; + VLOG_WORK << "Move memory from device to host: " << max_mem->name; static thread_mutex move_mutex; thread_scoped_lock lock(move_mutex); @@ -658,9 +660,9 @@ HIPDevice::HIPMem *HIPDevice::generic_alloc(device_memory &mem, size_t pitch_pad } if (mem.name) { - VLOG(1) << "Buffer allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")" << status; + VLOG_WORK << "Buffer allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")" << status; } mem.device_pointer = (device_ptr)device_pointer; @@ -856,8 +858,19 @@ void HIPDevice::const_copy_to(const char *name, void *host, size_t size) hipDeviceptr_t mem; size_t bytes; - hip_assert(hipModuleGetGlobal(&mem, &bytes, hipModule, name)); - hip_assert(hipMemcpyHtoD(mem, host, size)); + hip_assert(hipModuleGetGlobal(&mem, &bytes, hipModule, "kernel_params")); + assert(bytes == sizeof(KernelParamsHIP)); + + /* Update data storage pointers in launch parameters. */ +# define KERNEL_DATA_ARRAY(data_type, data_name) \ + if (strcmp(name, #data_name) == 0) { \ + hip_assert(hipMemcpyHtoD(mem + offsetof(KernelParamsHIP, data_name), host, size)); \ + return; \ + } + KERNEL_DATA_ARRAY(KernelData, data) + KERNEL_DATA_ARRAY(IntegratorStateGPU, integrator_state) +# include "kernel/data_arrays.h" +# undef KERNEL_DATA_ARRAY } void HIPDevice::global_alloc(device_memory &mem) @@ -881,7 +894,6 @@ void HIPDevice::tex_alloc(device_texture &mem) { HIPContextScope scope(this); - string bind_name = mem.name; size_t dsize = datatype_size(mem.data_type); size_t size = mem.memory_size(); @@ -966,9 +978,9 @@ void HIPDevice::tex_alloc(device_texture &mem) desc.NumChannels = mem.data_elements; desc.Flags = 0; - VLOG(1) << "Array 3D allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Array 3D allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; hip_assert(hipArray3DCreate((hArray *)&array_3d, &desc)); diff --git a/intern/cycles/device/hip/queue.cpp b/intern/cycles/device/hip/queue.cpp index 6c2c2c29624..8b3d963a32f 100644 --- a/intern/cycles/device/hip/queue.cpp +++ b/intern/cycles/device/hip/queue.cpp @@ -39,12 +39,12 @@ int HIPDeviceQueue::num_concurrent_states(const size_t state_size) const num_states = max((int)(num_states * factor), 1024); } else { - VLOG(3) << "CYCLES_CONCURRENT_STATES_FACTOR evaluated to 0"; + VLOG_DEVICE_STATS << "CYCLES_CONCURRENT_STATES_FACTOR evaluated to 0"; } } - VLOG(3) << "GPU queue concurrent states: " << num_states << ", using up to " - << string_human_readable_size(num_states * state_size); + VLOG_DEVICE_STATS << "GPU queue concurrent states: " << num_states << ", using up to " + << string_human_readable_size(num_states * state_size); return num_states; } diff --git a/intern/cycles/device/memory.h b/intern/cycles/device/memory.h index 55d6d39cef8..5f44475077e 100644 --- a/intern/cycles/device/memory.h +++ b/intern/cycles/device/memory.h @@ -350,7 +350,7 @@ template<typename T> class device_only_memory : public device_memory { * * When using memory type MEM_GLOBAL, a pointer to this memory will be * automatically attached to kernel globals, using the provided name - * matching an entry in kernel_textures.h. */ + * matching an entry in kernel/data_arrays.h. */ template<typename T> class device_vector : public device_memory { public: diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 086bf0af979..0a89055af34 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -35,7 +35,7 @@ void MetalDevice::set_error(const string &error) } MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler) - : Device(info, stats, profiler), texture_info(this, "__texture_info", MEM_GLOBAL) + : Device(info, stats, profiler), texture_info(this, "texture_info", MEM_GLOBAL) { mtlDevId = info.num; @@ -411,9 +411,9 @@ MetalDevice::MetalMem *MetalDevice::generic_alloc(device_memory &mem) } if (mem.name) { - VLOG(2) << "Buffer allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Buffer allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; } mem.device_size = metal_buffer.allocatedSize; @@ -625,7 +625,7 @@ device_ptr MetalDevice::mem_alloc_sub_ptr(device_memory &mem, size_t offset, siz void MetalDevice::const_copy_to(const char *name, void *host, size_t size) { - if (strcmp(name, "__data") == 0) { + if (strcmp(name, "data") == 0) { assert(size == sizeof(KernelData)); memcpy((uint8_t *)&launch_params + offsetof(KernelParamsMetal, data), host, size); return; @@ -646,19 +646,19 @@ void MetalDevice::const_copy_to(const char *name, void *host, size_t size) }; /* Update data storage pointers in launch parameters. */ - if (strcmp(name, "__integrator_state") == 0) { + if (strcmp(name, "integrator_state") == 0) { /* IntegratorStateGPU is contiguous pointers */ const size_t pointer_block_size = sizeof(IntegratorStateGPU); update_launch_pointers( - offsetof(KernelParamsMetal, __integrator_state), host, size, pointer_block_size); + offsetof(KernelParamsMetal, integrator_state), host, size, pointer_block_size); } -# define KERNEL_TEX(data_type, tex_name) \ +# define KERNEL_DATA_ARRAY(data_type, tex_name) \ else if (strcmp(name, #tex_name) == 0) \ { \ update_launch_pointers(offsetof(KernelParamsMetal, tex_name), host, size, size); \ } -# include "kernel/textures.h" -# undef KERNEL_TEX +# include "kernel/data_arrays.h" +# undef KERNEL_DATA_ARRAY } void MetalDevice::global_alloc(device_memory &mem) @@ -800,9 +800,9 @@ void MetalDevice::tex_alloc(device_texture &mem) desc.textureType = MTLTextureType3D; desc.depth = mem.data_depth; - VLOG(2) << "Texture 3D allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Texture 3D allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; mtlTexture = [mtlDevice newTextureWithDescriptor:desc]; assert(mtlTexture); @@ -834,9 +834,9 @@ void MetalDevice::tex_alloc(device_texture &mem) desc.storageMode = storage_mode; desc.usage = MTLTextureUsageShaderRead; - VLOG(2) << "Texture 2D allocate: " << mem.name << ", " - << string_human_readable_number(mem.memory_size()) << " bytes. (" - << string_human_readable_size(mem.memory_size()) << ")"; + VLOG_WORK << "Texture 2D allocate: " << mem.name << ", " + << string_human_readable_number(mem.memory_size()) << " bytes. (" + << string_human_readable_size(mem.memory_size()) << ")"; mtlTexture = [mtlDevice newTextureWithDescriptor:desc]; assert(mtlTexture); diff --git a/intern/cycles/device/metal/queue.mm b/intern/cycles/device/metal/queue.mm index 0e260886abb..da5408373bb 100644 --- a/intern/cycles/device/metal/queue.mm +++ b/intern/cycles/device/metal/queue.mm @@ -311,8 +311,8 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel, return false; } - VLOG(3) << "Metal queue launch " << device_kernel_as_string(kernel) << ", work_size " - << work_size; + VLOG_DEVICE_STATS << "Metal queue launch " << device_kernel_as_string(kernel) << ", work_size " + << work_size; id<MTLComputeCommandEncoder> mtlComputeCommandEncoder = get_compute_encoder(kernel); @@ -358,7 +358,7 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel, /* Prepare any non-pointer (i.e. plain-old-data) KernelParamsMetal data */ /* The plain-old-data is contiguous, continuing to the end of KernelParamsMetal */ - size_t plain_old_launch_data_offset = offsetof(KernelParamsMetal, __integrator_state) + + size_t plain_old_launch_data_offset = offsetof(KernelParamsMetal, integrator_state) + sizeof(IntegratorStateGPU); size_t plain_old_launch_data_size = sizeof(KernelParamsMetal) - plain_old_launch_data_offset; memcpy(init_arg_buffer + globals_offsets + plain_old_launch_data_offset, @@ -415,7 +415,7 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel, } /* this relies on IntegratorStateGPU layout being contiguous device_ptrs */ - const size_t pointer_block_end = offsetof(KernelParamsMetal, __integrator_state) + + const size_t pointer_block_end = offsetof(KernelParamsMetal, integrator_state) + sizeof(IntegratorStateGPU); for (size_t offset = 0; offset < pointer_block_end; offset += sizeof(device_ptr)) { int pointer_index = int(offset / sizeof(device_ptr)); diff --git a/intern/cycles/device/optix/device.cpp b/intern/cycles/device/optix/device.cpp index 70810bae10d..68ca21374fd 100644 --- a/intern/cycles/device/optix/device.cpp +++ b/intern/cycles/device/optix/device.cpp @@ -31,12 +31,12 @@ bool device_optix_init() const OptixResult result = optixInit(); if (result == OPTIX_ERROR_UNSUPPORTED_ABI_VERSION) { - VLOG(1) << "OptiX initialization failed because the installed NVIDIA driver is too old. " - "Please update to the latest driver first!"; + VLOG_WARNING << "OptiX initialization failed because the installed NVIDIA driver is too old. " + "Please update to the latest driver first!"; return false; } else if (result != OPTIX_SUCCESS) { - VLOG(1) << "OptiX initialization failed with error code " << (unsigned int)result; + VLOG_WARNING << "OptiX initialization failed with error code " << (unsigned int)result; return false; } diff --git a/intern/cycles/device/optix/device_impl.cpp b/intern/cycles/device/optix/device_impl.cpp index 9ab9bbb59c5..e7dcc29a2da 100644 --- a/intern/cycles/device/optix/device_impl.cpp +++ b/intern/cycles/device/optix/device_impl.cpp @@ -246,7 +246,7 @@ OptiXDevice::Denoiser::Denoiser(OptiXDevice *device) OptiXDevice::OptiXDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler) : CUDADevice(info, stats, profiler), sbt_data(this, "__sbt", MEM_READ_ONLY), - launch_params(this, "__params", false), + launch_params(this, "kernel_params", false), denoiser_(this) { /* Make the CUDA context current. */ @@ -278,7 +278,7 @@ OptiXDevice::OptiXDevice(const DeviceInfo &info, Stats &stats, Profiler &profile }; # endif if (DebugFlags().optix.use_debug) { - VLOG(1) << "Using OptiX debug mode."; + VLOG_INFO << "Using OptiX debug mode."; options.validationMode = OPTIX_DEVICE_CONTEXT_VALIDATION_MODE_ALL; } optix_assert(optixDeviceContextCreate(cuContext, &options, &context)); @@ -421,7 +421,7 @@ bool OptiXDevice::load_kernels(const uint kernel_features) pipeline_options.numPayloadValues = 8; pipeline_options.numAttributeValues = 2; /* u, v */ pipeline_options.exceptionFlags = OPTIX_EXCEPTION_FLAG_NONE; - pipeline_options.pipelineLaunchParamsVariableName = "__params"; /* See globals.h */ + pipeline_options.pipelineLaunchParamsVariableName = "kernel_params"; /* See globals.h */ pipeline_options.usesPrimitiveTypeFlags = OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE; if (kernel_features & KERNEL_FEATURE_HAIR) { @@ -1392,11 +1392,11 @@ bool OptiXDevice::build_optix_bvh(BVHOptiX *bvh, /* The build flags have to match the ones used to query the built-in curve intersection program (see optixBuiltinISModuleGet above) */ build_input.type == OPTIX_BUILD_INPUT_TYPE_CURVES) { - VLOG(2) << "Using fast to trace OptiX BVH"; + VLOG_INFO << "Using fast to trace OptiX BVH"; options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION; } else { - VLOG(2) << "Using fast to update OptiX BVH"; + VLOG_INFO << "Using fast to update OptiX BVH"; options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE; } @@ -2042,7 +2042,7 @@ void OptiXDevice::const_copy_to(const char *name, void *host, size_t size) /* Set constant memory for CUDA module. */ CUDADevice::const_copy_to(name, host, size); - if (strcmp(name, "__data") == 0) { + if (strcmp(name, "data") == 0) { assert(size <= sizeof(KernelData)); /* Update traversable handle (since it is different for each device on multi devices). */ @@ -2054,14 +2054,14 @@ void OptiXDevice::const_copy_to(const char *name, void *host, size_t size) } /* Update data storage pointers in launch parameters. */ -# define KERNEL_TEX(data_type, tex_name) \ - if (strcmp(name, #tex_name) == 0) { \ - update_launch_params(offsetof(KernelParamsOptiX, tex_name), host, size); \ +# define KERNEL_DATA_ARRAY(data_type, data_name) \ + if (strcmp(name, #data_name) == 0) { \ + update_launch_params(offsetof(KernelParamsOptiX, data_name), host, size); \ return; \ } - KERNEL_TEX(IntegratorStateGPU, __integrator_state) -# include "kernel/textures.h" -# undef KERNEL_TEX + KERNEL_DATA_ARRAY(IntegratorStateGPU, integrator_state) +# include "kernel/data_arrays.h" +# undef KERNEL_DATA_ARRAY } void OptiXDevice::update_launch_params(size_t offset, void *data, size_t data_size) diff --git a/intern/cycles/device/queue.cpp b/intern/cycles/device/queue.cpp index de65047ed6a..cc0cf0ccf84 100644 --- a/intern/cycles/device/queue.cpp +++ b/intern/cycles/device/queue.cpp @@ -19,7 +19,7 @@ DeviceQueue::DeviceQueue(Device *device) DeviceQueue::~DeviceQueue() { - if (VLOG_IS_ON(3)) { + if (VLOG_DEVICE_STATS_IS_ON) { /* Print kernel execution times sorted by time. */ vector<pair<DeviceKernelMask, double>> stats_sorted; for (const auto &stat : stats_kernel_time_) { @@ -32,17 +32,18 @@ DeviceQueue::~DeviceQueue() return a.second > b.second; }); - VLOG(3) << "GPU queue stats:"; + VLOG_DEVICE_STATS << "GPU queue stats:"; for (const auto &[mask, time] : stats_sorted) { - VLOG(3) << " " << std::setfill(' ') << std::setw(10) << std::fixed << std::setprecision(5) - << std::right << time << "s: " << device_kernel_mask_as_string(mask); + VLOG_DEVICE_STATS << " " << std::setfill(' ') << std::setw(10) << std::fixed + << std::setprecision(5) << std::right << time + << "s: " << device_kernel_mask_as_string(mask); } } } void DeviceQueue::debug_init_execution() { - if (VLOG_IS_ON(3)) { + if (VLOG_DEVICE_STATS_IS_ON) { last_sync_time_ = time_dt(); } @@ -51,9 +52,9 @@ void DeviceQueue::debug_init_execution() void DeviceQueue::debug_enqueue(DeviceKernel kernel, const int work_size) { - if (VLOG_IS_ON(3)) { - VLOG(4) << "GPU queue launch " << device_kernel_as_string(kernel) << ", work_size " - << work_size; + if (VLOG_DEVICE_STATS_IS_ON) { + VLOG_DEVICE_STATS << "GPU queue launch " << device_kernel_as_string(kernel) << ", work_size " + << work_size; } last_kernels_enqueued_ |= (uint64_t(1) << (uint64_t)kernel); @@ -61,10 +62,10 @@ void DeviceQueue::debug_enqueue(DeviceKernel kernel, const int work_size) void DeviceQueue::debug_synchronize() { - if (VLOG_IS_ON(3)) { + if (VLOG_DEVICE_STATS_IS_ON) { const double new_time = time_dt(); const double elapsed_time = new_time - last_sync_time_; - VLOG(4) << "GPU queue synchronize, elapsed " << std::setw(10) << elapsed_time << "s"; + VLOG_DEVICE_STATS << "GPU queue synchronize, elapsed " << std::setw(10) << elapsed_time << "s"; stats_kernel_time_[last_kernels_enqueued_] += elapsed_time; diff --git a/intern/cycles/integrator/denoiser.cpp b/intern/cycles/integrator/denoiser.cpp index 23ab825a4d2..94991d63e4c 100644 --- a/intern/cycles/integrator/denoiser.cpp +++ b/intern/cycles/integrator/denoiser.cpp @@ -58,8 +58,8 @@ bool Denoiser::load_kernels(Progress *progress) return false; } - VLOG(3) << "Will denoise on " << denoiser_device->info.description << " (" - << denoiser_device->info.id << ")"; + VLOG_WORK << "Will denoise on " << denoiser_device->info.description << " (" + << denoiser_device->info.id << ")"; return true; } diff --git a/intern/cycles/integrator/denoiser_device.cpp b/intern/cycles/integrator/denoiser_device.cpp index 595397312b3..5414f9dfb1a 100644 --- a/intern/cycles/integrator/denoiser_device.cpp +++ b/intern/cycles/integrator/denoiser_device.cpp @@ -48,7 +48,7 @@ bool DeviceDenoiser::denoise_buffer(const BufferParams &buffer_params, task.render_buffers = render_buffers; } else { - VLOG(3) << "Creating temporary buffer on denoiser device."; + VLOG_WORK << "Creating temporary buffer on denoiser device."; DeviceQueue *queue = denoiser_device->get_denoise_queue(); diff --git a/intern/cycles/integrator/denoiser_oidn.cpp b/intern/cycles/integrator/denoiser_oidn.cpp index b074408e229..04e659a15e2 100644 --- a/intern/cycles/integrator/denoiser_oidn.cpp +++ b/intern/cycles/integrator/denoiser_oidn.cpp @@ -284,8 +284,8 @@ class OIDNDenoiseContext { /* Read pass pixels using PassAccessor into a temporary buffer which is owned by the pass.. */ void read_pass_pixels_into_buffer(OIDNPass &oidn_pass) { - VLOG(3) << "Allocating temporary buffer for pass " << oidn_pass.name << " (" - << pass_type_as_string(oidn_pass.type) << ")"; + VLOG_WORK << "Allocating temporary buffer for pass " << oidn_pass.name << " (" + << pass_type_as_string(oidn_pass.type) << ")"; const int64_t width = buffer_params_.width; const int64_t height = buffer_params_.height; diff --git a/intern/cycles/integrator/path_trace.cpp b/intern/cycles/integrator/path_trace.cpp index 36a0326e405..9ad1c465725 100644 --- a/intern/cycles/integrator/path_trace.cpp +++ b/intern/cycles/integrator/path_trace.cpp @@ -348,8 +348,8 @@ void PathTrace::path_trace(RenderWork &render_work) return; } - VLOG(3) << "Will path trace " << render_work.path_trace.num_samples - << " samples at the resolution divider " << render_work.resolution_divider; + VLOG_WORK << "Will path trace " << render_work.path_trace.num_samples + << " samples at the resolution divider " << render_work.resolution_divider; const double start_time = time_dt(); @@ -373,9 +373,9 @@ void PathTrace::path_trace(RenderWork &render_work) work_balance_infos_[i].time_spent += work_time; work_balance_infos_[i].occupancy = statistics.occupancy; - VLOG(3) << "Rendered " << num_samples << " samples in " << work_time << " seconds (" - << work_time / num_samples - << " seconds per sample), occupancy: " << statistics.occupancy; + VLOG_WORK << "Rendered " << num_samples << " samples in " << work_time << " seconds (" + << work_time / num_samples + << " seconds per sample), occupancy: " << statistics.occupancy; }); float occupancy_accum = 0.0f; @@ -398,10 +398,10 @@ void PathTrace::adaptive_sample(RenderWork &render_work) bool did_reschedule_on_idle = false; while (true) { - VLOG(3) << "Will filter adaptive stopping buffer, threshold " - << render_work.adaptive_sampling.threshold; + VLOG_WORK << "Will filter adaptive stopping buffer, threshold " + << render_work.adaptive_sampling.threshold; if (render_work.adaptive_sampling.reset) { - VLOG(3) << "Will re-calculate convergency flag for currently converged pixels."; + VLOG_WORK << "Will re-calculate convergency flag for currently converged pixels."; } const double start_time = time_dt(); @@ -420,11 +420,11 @@ void PathTrace::adaptive_sample(RenderWork &render_work) render_work, time_dt() - start_time, is_cancel_requested()); if (num_active_pixels == 0) { - VLOG(3) << "All pixels converged."; + VLOG_WORK << "All pixels converged."; if (!render_scheduler_.render_work_reschedule_on_converge(render_work)) { break; } - VLOG(3) << "Continuing with lower threshold."; + VLOG_WORK << "Continuing with lower threshold."; } else if (did_reschedule_on_idle) { break; @@ -436,10 +436,10 @@ void PathTrace::adaptive_sample(RenderWork &render_work) * A better heuristic is possible here: for example, use maximum of 128^2 and percentage of * the final resolution. */ if (!render_scheduler_.render_work_reschedule_on_idle(render_work)) { - VLOG(3) << "Rescheduling is not possible: final threshold is reached."; + VLOG_WORK << "Rescheduling is not possible: final threshold is reached."; break; } - VLOG(3) << "Rescheduling lower threshold."; + VLOG_WORK << "Rescheduling lower threshold."; did_reschedule_on_idle = true; } else { @@ -483,7 +483,7 @@ void PathTrace::cryptomatte_postprocess(const RenderWork &render_work) if (!render_work.cryptomatte.postprocess) { return; } - VLOG(3) << "Perform cryptomatte work."; + VLOG_WORK << "Perform cryptomatte work."; parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) { path_trace_work->cryptomatte_postproces(); @@ -501,7 +501,7 @@ void PathTrace::denoise(const RenderWork &render_work) return; } - VLOG(3) << "Perform denoising work."; + VLOG_WORK << "Perform denoising work."; const double start_time = time_dt(); @@ -599,26 +599,26 @@ void PathTrace::update_display(const RenderWork &render_work) } if (!display_ && !output_driver_) { - VLOG(3) << "Ignore display update."; + VLOG_WORK << "Ignore display update."; return; } if (full_params_.width == 0 || full_params_.height == 0) { - VLOG(3) << "Skipping PathTraceDisplay update due to 0 size of the render buffer."; + VLOG_WORK << "Skipping PathTraceDisplay update due to 0 size of the render buffer."; return; } const double start_time = time_dt(); if (output_driver_) { - VLOG(3) << "Invoke buffer update callback."; + VLOG_WORK << "Invoke buffer update callback."; PathTraceTile tile(*this); output_driver_->update_render_tile(tile); } if (display_) { - VLOG(3) << "Perform copy to GPUDisplay work."; + VLOG_WORK << "Perform copy to GPUDisplay work."; const int texture_width = render_state_.effective_big_tile_params.window_width; const int texture_height = render_state_.effective_big_tile_params.window_height; @@ -654,33 +654,33 @@ void PathTrace::rebalance(const RenderWork &render_work) const int num_works = path_trace_works_.size(); if (num_works == 1) { - VLOG(3) << "Ignoring rebalance work due to single device render."; + VLOG_WORK << "Ignoring rebalance work due to single device render."; return; } const double start_time = time_dt(); if (VLOG_IS_ON(3)) { - VLOG(3) << "Perform rebalance work."; - VLOG(3) << "Per-device path tracing time (seconds):"; + VLOG_WORK << "Perform rebalance work."; + VLOG_WORK << "Per-device path tracing time (seconds):"; for (int i = 0; i < num_works; ++i) { - VLOG(3) << path_trace_works_[i]->get_device()->info.description << ": " - << work_balance_infos_[i].time_spent; + VLOG_WORK << path_trace_works_[i]->get_device()->info.description << ": " + << work_balance_infos_[i].time_spent; } } const bool did_rebalance = work_balance_do_rebalance(work_balance_infos_); if (VLOG_IS_ON(3)) { - VLOG(3) << "Calculated per-device weights for works:"; + VLOG_WORK << "Calculated per-device weights for works:"; for (int i = 0; i < num_works; ++i) { - VLOG(3) << path_trace_works_[i]->get_device()->info.description << ": " - << work_balance_infos_[i].weight; + VLOG_WORK << path_trace_works_[i]->get_device()->info.description << ": " + << work_balance_infos_[i].weight; } } if (!did_rebalance) { - VLOG(3) << "Balance in path trace works did not change."; + VLOG_WORK << "Balance in path trace works did not change."; render_scheduler_.report_rebalance_time(render_work, time_dt() - start_time, false); return; } @@ -704,7 +704,7 @@ void PathTrace::write_tile_buffer(const RenderWork &render_work) return; } - VLOG(3) << "Write tile result."; + VLOG_WORK << "Write tile result."; render_state_.tile_written = true; @@ -718,14 +718,14 @@ void PathTrace::write_tile_buffer(const RenderWork &render_work) * * Important thing is: tile should be written to the software via callback only once. */ if (!has_multiple_tiles) { - VLOG(3) << "Write tile result via buffer write callback."; + VLOG_WORK << "Write tile result via buffer write callback."; tile_buffer_write(); } /* Write tile to disk, so that the render work's render buffer can be re-used for the next tile. */ if (has_multiple_tiles) { - VLOG(3) << "Write tile result into ."; + VLOG_WORK << "Write tile result into ."; tile_buffer_write_to_disk(); } } @@ -736,10 +736,10 @@ void PathTrace::finalize_full_buffer_on_disk(const RenderWork &render_work) return; } - VLOG(3) << "Handle full-frame render buffer work."; + VLOG_WORK << "Handle full-frame render buffer work."; if (!tile_manager_.has_written_tiles()) { - VLOG(3) << "No tiles on disk."; + VLOG_WORK << "No tiles on disk."; return; } @@ -935,7 +935,7 @@ static string get_layer_view_name(const RenderBuffers &buffers) void PathTrace::process_full_buffer_from_disk(string_view filename) { - VLOG(3) << "Processing full frame buffer file " << filename; + VLOG_WORK << "Processing full frame buffer file " << filename; progress_set_status("Reading full buffer from disk"); diff --git a/intern/cycles/integrator/path_trace_work_gpu.cpp b/intern/cycles/integrator/path_trace_work_gpu.cpp index ede81705ae8..e262c252ce3 100644 --- a/intern/cycles/integrator/path_trace_work_gpu.cpp +++ b/intern/cycles/integrator/path_trace_work_gpu.cpp @@ -152,7 +152,7 @@ void PathTraceWorkGPU::alloc_integrator_soa() total_soa_size += soa_memory->memory_size(); } - VLOG(3) << "GPU SoA state size: " << string_human_readable_size(total_soa_size); + VLOG_DEVICE_STATS << "GPU SoA state size: " << string_human_readable_size(total_soa_size); } } @@ -239,7 +239,7 @@ void PathTraceWorkGPU::init_execution() /* Copy to device side struct in constant memory. */ device_->const_copy_to( - "__integrator_state", &integrator_state_gpu_, sizeof(integrator_state_gpu_)); + "integrator_state", &integrator_state_gpu_, sizeof(integrator_state_gpu_)); } void PathTraceWorkGPU::render_samples(RenderStatistics &statistics, @@ -820,10 +820,10 @@ bool PathTraceWorkGPU::should_use_graphics_interop() interop_use_ = device->should_use_graphics_interop(); if (interop_use_) { - VLOG(2) << "Using graphics interop GPU display update."; + VLOG_INFO << "Using graphics interop GPU display update."; } else { - VLOG(2) << "Using naive GPU display update."; + VLOG_INFO << "Using naive GPU display update."; } interop_use_checked_ = true; diff --git a/intern/cycles/integrator/render_scheduler.cpp b/intern/cycles/integrator/render_scheduler.cpp index ebc3170393f..e4676bd059c 100644 --- a/intern/cycles/integrator/render_scheduler.cpp +++ b/intern/cycles/integrator/render_scheduler.cpp @@ -225,7 +225,7 @@ bool RenderScheduler::render_work_reschedule_on_idle(RenderWork &render_work) void RenderScheduler::render_work_reschedule_on_cancel(RenderWork &render_work) { - VLOG(3) << "Schedule work for cancel."; + VLOG_WORK << "Schedule work for cancel."; /* Un-schedule samples: they will not be rendered and should not be counted. */ state_.num_rendered_samples -= render_work.path_trace.num_samples; @@ -475,14 +475,14 @@ void RenderScheduler::report_path_trace_time(const RenderWork &render_work, path_trace_time_.add_average(final_time_approx, render_work.path_trace.num_samples); - VLOG(4) << "Average path tracing time: " << path_trace_time_.get_average() << " seconds."; + VLOG_WORK << "Average path tracing time: " << path_trace_time_.get_average() << " seconds."; } void RenderScheduler::report_path_trace_occupancy(const RenderWork &render_work, float occupancy) { state_.occupancy_num_samples = render_work.path_trace.num_samples; state_.occupancy = occupancy; - VLOG(4) << "Measured path tracing occupancy: " << occupancy; + VLOG_WORK << "Measured path tracing occupancy: " << occupancy; } void RenderScheduler::report_adaptive_filter_time(const RenderWork &render_work, @@ -503,8 +503,8 @@ void RenderScheduler::report_adaptive_filter_time(const RenderWork &render_work, adaptive_filter_time_.add_average(final_time_approx, render_work.path_trace.num_samples); - VLOG(4) << "Average adaptive sampling filter time: " << adaptive_filter_time_.get_average() - << " seconds."; + VLOG_WORK << "Average adaptive sampling filter time: " << adaptive_filter_time_.get_average() + << " seconds."; } void RenderScheduler::report_denoise_time(const RenderWork &render_work, double time) @@ -523,7 +523,7 @@ void RenderScheduler::report_denoise_time(const RenderWork &render_work, double denoise_time_.add_average(final_time_approx); - VLOG(4) << "Average denoising time: " << denoise_time_.get_average() << " seconds."; + VLOG_WORK << "Average denoising time: " << denoise_time_.get_average() << " seconds."; } void RenderScheduler::report_display_update_time(const RenderWork &render_work, double time) @@ -542,7 +542,8 @@ void RenderScheduler::report_display_update_time(const RenderWork &render_work, display_update_time_.add_average(final_time_approx); - VLOG(4) << "Average display update time: " << display_update_time_.get_average() << " seconds."; + VLOG_WORK << "Average display update time: " << display_update_time_.get_average() + << " seconds."; /* Move the display update moment further in time, so that logic which checks when last update * did happen have more reliable point in time (without path tracing and denoising parts of the @@ -568,7 +569,7 @@ void RenderScheduler::report_rebalance_time(const RenderWork &render_work, state_.last_rebalance_changed = balance_changed; - VLOG(4) << "Average rebalance time: " << rebalance_time_.get_average() << " seconds."; + VLOG_WORK << "Average rebalance time: " << rebalance_time_.get_average() << " seconds."; } string RenderScheduler::full_report() const @@ -1063,7 +1064,7 @@ void RenderScheduler::update_start_resolution_divider() /* Resolution divider has never been calculated before: use default resolution, so that we have * somewhat good initial behavior, giving a chance to collect real numbers. */ start_resolution_divider_ = default_start_resolution_divider_; - VLOG(3) << "Initial resolution divider is " << start_resolution_divider_; + VLOG_WORK << "Initial resolution divider is " << start_resolution_divider_; return; } @@ -1092,7 +1093,7 @@ void RenderScheduler::update_start_resolution_divider() * simple and compute device is fast). */ start_resolution_divider_ = max(resolution_divider_for_update, pixel_size_); - VLOG(3) << "Calculated resolution divider is " << start_resolution_divider_; + VLOG_WORK << "Calculated resolution divider is " << start_resolution_divider_; } double RenderScheduler::guess_viewport_navigation_update_interval_in_seconds() const diff --git a/intern/cycles/integrator/shader_eval.cpp b/intern/cycles/integrator/shader_eval.cpp index 92b9d1c662d..b1450732f5c 100644 --- a/intern/cycles/integrator/shader_eval.cpp +++ b/intern/cycles/integrator/shader_eval.cpp @@ -31,8 +31,8 @@ bool ShaderEval::eval(const ShaderEvalType type, device_->foreach_device([&](Device *device) { if (!first_device) { - LOG(ERROR) << "Multi-devices are not yet fully implemented, will evaluate shader on a " - "single device."; + VLOG_WORK << "Multi-devices are not yet fully implemented, will evaluate shader on a " + "single device."; return; } first_device = false; diff --git a/intern/cycles/integrator/work_tile_scheduler.cpp b/intern/cycles/integrator/work_tile_scheduler.cpp index 6dc511064c9..4bc8c0c4396 100644 --- a/intern/cycles/integrator/work_tile_scheduler.cpp +++ b/intern/cycles/integrator/work_tile_scheduler.cpp @@ -55,7 +55,7 @@ void WorkTileScheduler::reset_scheduler_state() tile_size_ = tile_calculate_best_size( accelerated_rt_, image_size_px_, samples_num_, max_num_path_states_, scrambling_distance_); - VLOG(3) << "Will schedule tiles of size " << tile_size_; + VLOG_WORK << "Will schedule tiles of size " << tile_size_; if (VLOG_IS_ON(3)) { /* The logging is based on multiple tiles scheduled, ignoring overhead of multi-tile scheduling @@ -63,8 +63,8 @@ void WorkTileScheduler::reset_scheduler_state() const int num_path_states_in_tile = tile_size_.width * tile_size_.height * tile_size_.num_samples; const int num_tiles = max_num_path_states_ / num_path_states_in_tile; - VLOG(3) << "Number of unused path states: " - << max_num_path_states_ - num_tiles * num_path_states_in_tile; + VLOG_WORK << "Number of unused path states: " + << max_num_path_states_ - num_tiles * num_path_states_in_tile; } num_tiles_x_ = divide_up(image_size_px_.x, tile_size_.width); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 473bdb67920..a07d7852211 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -267,8 +267,8 @@ set(SRC_KERNEL_UTIL_HEADERS ) set(SRC_KERNEL_TYPES_HEADERS + data_arrays.h tables.h - textures.h types.h ) diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h index 04ccb7ceff5..a1d0e307170 100644 --- a/intern/cycles/kernel/bvh/bvh.h +++ b/intern/cycles/kernel/bvh/bvh.h @@ -452,7 +452,7 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals kg, # ifdef __EMBREE__ if (kernel_data.bvh.scene) { - const bool has_bvh = !(kernel_tex_fetch(__object_flag, local_object) & + const bool has_bvh = !(kernel_data_fetch(object_flag, local_object) & SD_OBJECT_TRANSFORM_APPLIED); CCLIntersectContext ctx( kg, has_bvh ? CCLIntersectContext::RAY_SSS : CCLIntersectContext::RAY_LOCAL); diff --git a/intern/cycles/kernel/bvh/embree.h b/intern/cycles/kernel/bvh/embree.h index 4f7e6435daf..1c6b9bc1e62 100644 --- a/intern/cycles/kernel/bvh/embree.h +++ b/intern/cycles/kernel/bvh/embree.h @@ -146,14 +146,14 @@ ccl_device_inline void kernel_embree_convert_hit(KernelGlobals kg, const bool is_hair = hit->geomID & 1; if (is_hair) { - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, isect->prim); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, isect->prim); isect->type = segment.type; isect->prim = segment.prim; isect->u = hit->u; isect->v = hit->v; } else { - isect->type = kernel_tex_fetch(__objects, isect->object).primitive_type; + isect->type = kernel_data_fetch(objects, isect->object).primitive_type; isect->u = 1.0f - hit->v - hit->u; isect->v = hit->u; } @@ -170,7 +170,7 @@ ccl_device_inline void kernel_embree_convert_sss_hit( isect->prim = hit->primID + (intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID)); isect->object = object; - isect->type = kernel_tex_fetch(__objects, object).primitive_type; + isect->type = kernel_data_fetch(objects, object).primitive_type; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/bvh/local.h b/intern/cycles/kernel/bvh/local.h index 0d05e09d75f..3b6b30ea93d 100644 --- a/intern/cycles/kernel/bvh/local.h +++ b/intern/cycles/kernel/bvh/local.h @@ -41,7 +41,7 @@ ccl_device_inline /* traversal variables in registers */ int stack_ptr = 0; - int node_addr = kernel_tex_fetch(__object_node, local_object); + int node_addr = kernel_data_fetch(object_node, local_object); /* ray parameters in registers */ float3 P = ray->P; @@ -55,7 +55,7 @@ ccl_device_inline } kernel_assert((local_isect == NULL) == (max_hits == 0)); - const int object_flag = kernel_tex_fetch(__object_flag, local_object); + const int object_flag = kernel_data_fetch(object_flag, local_object); if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { #if BVH_FEATURE(BVH_MOTION) Transform ob_itfm; @@ -73,7 +73,7 @@ ccl_device_inline while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) { int node_addr_child1, traverse_mask; float dist[2]; - float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0); + float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0); traverse_mask = NODE_INTERSECT(kg, P, @@ -117,7 +117,7 @@ ccl_device_inline /* if node is leaf, fetch triangle list */ if (node_addr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1)); + float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1)); int prim_addr = __float_as_int(leaf.x); const int prim_addr2 = __float_as_int(leaf.y); @@ -132,18 +132,18 @@ ccl_device_inline case PRIMITIVE_TRIANGLE: { /* intersect ray against primitive */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); + kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type); /* Only intersect with matching object, for instanced objects we * already know we are only intersecting the right object. */ if (object == OBJECT_NONE) { - if (kernel_tex_fetch(__prim_object, prim_addr) != local_object) { + if (kernel_data_fetch(prim_object, prim_addr) != local_object) { continue; } } /* Skip self intersection. */ - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self_local(ray->self, prim)) { continue; } @@ -167,18 +167,18 @@ ccl_device_inline case PRIMITIVE_MOTION_TRIANGLE: { /* intersect ray against primitive */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); + kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type); /* Only intersect with matching object, for instanced objects we * already know we are only intersecting the right object. */ if (object == OBJECT_NONE) { - if (kernel_tex_fetch(__prim_object, prim_addr) != local_object) { + if (kernel_data_fetch(prim_object, prim_addr) != local_object) { continue; } } /* Skip self intersection. */ - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self_local(ray->self, prim)) { continue; } diff --git a/intern/cycles/kernel/bvh/nodes.h b/intern/cycles/kernel/bvh/nodes.h index fd475dcd5e9..c19dea9223b 100644 --- a/intern/cycles/kernel/bvh/nodes.h +++ b/intern/cycles/kernel/bvh/nodes.h @@ -9,9 +9,9 @@ ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(KernelGlobals kg { Transform space; const int child_addr = node_addr + child * 3; - space.x = kernel_tex_fetch(__bvh_nodes, child_addr + 1); - space.y = kernel_tex_fetch(__bvh_nodes, child_addr + 2); - space.z = kernel_tex_fetch(__bvh_nodes, child_addr + 3); + space.x = kernel_data_fetch(bvh_nodes, child_addr + 1); + space.y = kernel_data_fetch(bvh_nodes, child_addr + 2); + space.z = kernel_data_fetch(bvh_nodes, child_addr + 3); return space; } @@ -26,11 +26,11 @@ ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals kg, /* fetch node data */ #ifdef __VISIBILITY_FLAG__ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0); + float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0); #endif - float4 node0 = kernel_tex_fetch(__bvh_nodes, node_addr + 1); - float4 node1 = kernel_tex_fetch(__bvh_nodes, node_addr + 2); - float4 node2 = kernel_tex_fetch(__bvh_nodes, node_addr + 3); + float4 node0 = kernel_data_fetch(bvh_nodes, node_addr + 1); + float4 node1 = kernel_data_fetch(bvh_nodes, node_addr + 2); + float4 node2 = kernel_data_fetch(bvh_nodes, node_addr + 3); /* intersect ray against child nodes */ float c0lox = (node0.x - P.x) * idir.x; @@ -100,7 +100,7 @@ ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals kg, { int mask = 0; #ifdef __VISIBILITY_FLAG__ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0); + float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0); #endif if (bvh_unaligned_node_intersect_child(kg, P, dir, t, node_addr, 0, &dist[0])) { #ifdef __VISIBILITY_FLAG__ @@ -130,7 +130,7 @@ ccl_device_forceinline int bvh_node_intersect(KernelGlobals kg, const uint visibility, float dist[2]) { - float4 node = kernel_tex_fetch(__bvh_nodes, node_addr); + float4 node = kernel_data_fetch(bvh_nodes, node_addr); if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) { return bvh_unaligned_node_intersect(kg, P, dir, idir, t, node_addr, visibility, dist); } diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h index 2f58929c1e5..e86fe867eac 100644 --- a/intern/cycles/kernel/bvh/shadow_all.h +++ b/intern/cycles/kernel/bvh/shadow_all.h @@ -80,7 +80,7 @@ ccl_device_inline while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) { int node_addr_child1, traverse_mask; float dist[2]; - float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0); + float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0); traverse_mask = NODE_INTERSECT(kg, P, @@ -124,7 +124,7 @@ ccl_device_inline /* if node is leaf, fetch triangle list */ if (node_addr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1)); + float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1)); int prim_addr = __float_as_int(leaf.x); if (prim_addr >= 0) { @@ -137,7 +137,7 @@ ccl_device_inline /* primitive intersection */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == + kernel_assert((kernel_data_fetch(prim_type, prim_addr) & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL)); bool hit; @@ -147,9 +147,9 @@ ccl_device_inline Intersection isect ccl_optional_struct_init; const int prim_object = (object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, prim_addr) : + kernel_data_fetch(prim_object, prim_addr) : object; - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self_shadow(ray->self, prim_object, prim)) { continue; } @@ -181,14 +181,14 @@ ccl_device_inline case PRIMITIVE_CURVE_RIBBON: case PRIMITIVE_MOTION_CURVE_RIBBON: { if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) { - const float2 prim_time = kernel_tex_fetch(__prim_time, prim_addr); + const float2 prim_time = kernel_data_fetch(prim_time, prim_addr); if (ray->time < prim_time.x || ray->time > prim_time.y) { hit = false; break; } } - const int curve_type = kernel_tex_fetch(__prim_type, prim_addr); + const int curve_type = kernel_data_fetch(prim_type, prim_addr); hit = curve_intersect( kg, &isect, P, dir, t_max_current, prim_object, prim, ray->time, curve_type); @@ -199,14 +199,14 @@ ccl_device_inline case PRIMITIVE_POINT: case PRIMITIVE_MOTION_POINT: { if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) { - const float2 prim_time = kernel_tex_fetch(__prim_time, prim_addr); + const float2 prim_time = kernel_data_fetch(prim_time, prim_addr); if (ray->time < prim_time.x || ray->time > prim_time.y) { hit = false; break; } } - const int point_type = kernel_tex_fetch(__prim_type, prim_addr); + const int point_type = kernel_data_fetch(prim_type, prim_addr); hit = point_intersect( kg, &isect, P, dir, t_max_current, prim_object, prim, ray->time, point_type); break; @@ -291,7 +291,7 @@ ccl_device_inline } else { /* instance push */ - object = kernel_tex_fetch(__prim_object, -prim_addr - 1); + object = kernel_data_fetch(prim_object, -prim_addr - 1); #if BVH_FEATURE(BVH_MOTION) t_world_to_instance = bvh_instance_motion_push( @@ -307,7 +307,7 @@ ccl_device_inline kernel_assert(stack_ptr < BVH_STACK_SIZE); traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL; - node_addr = kernel_tex_fetch(__object_node, object); + node_addr = kernel_data_fetch(object_node, object); } } } while (node_addr != ENTRYPOINT_SENTINEL); diff --git a/intern/cycles/kernel/bvh/traversal.h b/intern/cycles/kernel/bvh/traversal.h index 1181d4bfdee..784fbf4fd11 100644 --- a/intern/cycles/kernel/bvh/traversal.h +++ b/intern/cycles/kernel/bvh/traversal.h @@ -62,7 +62,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) { int node_addr_child1, traverse_mask; float dist[2]; - float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0); + float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0); { traverse_mask = NODE_INTERSECT(kg, @@ -108,7 +108,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, /* if node is leaf, fetch triangle list */ if (node_addr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1)); + float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1)); int prim_addr = __float_as_int(leaf.x); if (prim_addr >= 0) { @@ -121,12 +121,12 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, /* primitive intersection */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); + kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type); const int prim_object = (object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, prim_addr) : + kernel_data_fetch(prim_object, prim_addr) : object; - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self_shadow(ray->self, prim_object, prim)) { continue; } @@ -166,13 +166,13 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, case PRIMITIVE_CURVE_RIBBON: case PRIMITIVE_MOTION_CURVE_RIBBON: { if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) { - const float2 prim_time = kernel_tex_fetch(__prim_time, prim_addr); + const float2 prim_time = kernel_data_fetch(prim_time, prim_addr); if (ray->time < prim_time.x || ray->time > prim_time.y) { break; } } - const int curve_type = kernel_tex_fetch(__prim_type, prim_addr); + const int curve_type = kernel_data_fetch(prim_type, prim_addr); const bool hit = curve_intersect( kg, isect, P, dir, isect->t, prim_object, prim, ray->time, curve_type); if (hit) { @@ -187,13 +187,13 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, case PRIMITIVE_POINT: case PRIMITIVE_MOTION_POINT: { if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) { - const float2 prim_time = kernel_tex_fetch(__prim_time, prim_addr); + const float2 prim_time = kernel_data_fetch(prim_time, prim_addr); if (ray->time < prim_time.x || ray->time > prim_time.y) { break; } } - const int point_type = kernel_tex_fetch(__prim_type, prim_addr); + const int point_type = kernel_data_fetch(prim_type, prim_addr); const bool hit = point_intersect( kg, isect, P, dir, isect->t, prim_object, prim, ray->time, point_type); if (hit) { @@ -209,7 +209,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, } else { /* instance push */ - object = kernel_tex_fetch(__prim_object, -prim_addr - 1); + object = kernel_data_fetch(prim_object, -prim_addr - 1); #if BVH_FEATURE(BVH_MOTION) isect->t *= bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &ob_itfm); @@ -221,7 +221,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals kg, kernel_assert(stack_ptr < BVH_STACK_SIZE); traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL; - node_addr = kernel_tex_fetch(__object_node, object); + node_addr = kernel_data_fetch(object_node, object); } } } while (node_addr != ENTRYPOINT_SENTINEL); diff --git a/intern/cycles/kernel/bvh/util.h b/intern/cycles/kernel/bvh/util.h index 71045157372..572e023db25 100644 --- a/intern/cycles/kernel/bvh/util.h +++ b/intern/cycles/kernel/bvh/util.h @@ -53,20 +53,20 @@ ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals kg, int shader = 0; if (type & PRIMITIVE_TRIANGLE) { - shader = kernel_tex_fetch(__tri_shader, prim); + shader = kernel_data_fetch(tri_shader, prim); } #ifdef __POINTCLOUD__ else if (type & PRIMITIVE_POINT) { - shader = kernel_tex_fetch(__points_shader, prim); + shader = kernel_data_fetch(points_shader, prim); } #endif #ifdef __HAIR__ else if (type & PRIMITIVE_CURVE) { - shader = kernel_tex_fetch(__curves, prim).shader_id; + shader = kernel_data_fetch(curves, prim).shader_id; } #endif - return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; + return kernel_data_fetch(shaders, (shader & SHADER_MASK)).flags; } ccl_device_forceinline int intersection_get_shader_from_isect_prim(KernelGlobals kg, @@ -76,16 +76,16 @@ ccl_device_forceinline int intersection_get_shader_from_isect_prim(KernelGlobals int shader = 0; if (isect_type & PRIMITIVE_TRIANGLE) { - shader = kernel_tex_fetch(__tri_shader, prim); + shader = kernel_data_fetch(tri_shader, prim); } #ifdef __POINTCLOUD__ else if (isect_type & PRIMITIVE_POINT) { - shader = kernel_tex_fetch(__points_shader, prim); + shader = kernel_data_fetch(points_shader, prim); } #endif #ifdef __HAIR__ else if (isect_type & PRIMITIVE_CURVE) { - shader = kernel_tex_fetch(__curves, prim).shader_id; + shader = kernel_data_fetch(curves, prim).shader_id; } #endif @@ -101,7 +101,7 @@ ccl_device_forceinline int intersection_get_shader( ccl_device_forceinline int intersection_get_object_flags( KernelGlobals kg, ccl_private const Intersection *ccl_restrict isect) { - return kernel_tex_fetch(__object_flag, isect->object); + return kernel_data_fetch(object_flag, isect->object); } /* TODO: find a better (faster) solution for this. Maybe store offset per object for @@ -110,27 +110,27 @@ ccl_device_inline int intersection_find_attribute(KernelGlobals kg, const int object, const uint id) { - uint attr_offset = kernel_tex_fetch(__objects, object).attribute_map_offset; - uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); + uint attr_offset = kernel_data_fetch(objects, object).attribute_map_offset; + AttributeMap attr_map = kernel_data_fetch(attributes_map, attr_offset); - while (attr_map.x != id) { - if (UNLIKELY(attr_map.x == ATTR_STD_NONE)) { - if (UNLIKELY(attr_map.y == 0)) { + while (attr_map.id != id) { + if (UNLIKELY(attr_map.id == ATTR_STD_NONE)) { + if (UNLIKELY(attr_map.element == 0)) { return (int)ATTR_STD_NOT_FOUND; } else { /* Chain jump to a different part of the table. */ - attr_offset = attr_map.z; + attr_offset = attr_map.offset; } } else { attr_offset += ATTR_PRIM_TYPES; } - attr_map = kernel_tex_fetch(__attributes_map, attr_offset); + attr_map = kernel_data_fetch(attributes_map, attr_offset); } /* return result */ - return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z; + return (attr_map.element == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.offset; } /* Transparent Shadows */ @@ -151,12 +151,12 @@ ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, } /* Interpolate transparency between curve keys. */ - const KernelCurve kcurve = kernel_tex_fetch(__curves, prim); + const KernelCurve kcurve = kernel_data_fetch(curves, prim); const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(kcurve.type); const int k1 = k0 + 1; - const float f0 = kernel_tex_fetch(__attributes_float, offset + k0); - const float f1 = kernel_tex_fetch(__attributes_float, offset + k1); + const float f0 = kernel_data_fetch(attributes_float, offset + k0); + const float f1 = kernel_data_fetch(attributes_float, offset + k1); return (1.0f - u) * f0 + u * f1; } diff --git a/intern/cycles/kernel/bvh/volume.h b/intern/cycles/kernel/bvh/volume.h index d711b3abbf4..9715712a8f2 100644 --- a/intern/cycles/kernel/bvh/volume.h +++ b/intern/cycles/kernel/bvh/volume.h @@ -65,7 +65,7 @@ ccl_device_inline while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) { int node_addr_child1, traverse_mask; float dist[2]; - float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0); + float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0); traverse_mask = NODE_INTERSECT(kg, P, @@ -109,7 +109,7 @@ ccl_device_inline /* if node is leaf, fetch triangle list */ if (node_addr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1)); + float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1)); int prim_addr = __float_as_int(leaf.x); if (prim_addr >= 0) { @@ -125,17 +125,17 @@ ccl_device_inline case PRIMITIVE_TRIANGLE: { /* intersect ray against primitive */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); + kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type); /* only primitives from volume object */ const int prim_object = (object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, prim_addr) : + kernel_data_fetch(prim_object, prim_addr) : object; - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self(ray->self, prim_object, prim)) { continue; } - int object_flag = kernel_tex_fetch(__object_flag, prim_object); + int object_flag = kernel_data_fetch(object_flag, prim_object); if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { continue; } @@ -148,16 +148,16 @@ ccl_device_inline case PRIMITIVE_MOTION_TRIANGLE: { /* intersect ray against primitive */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); + kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type); /* only primitives from volume object */ const int prim_object = (object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, prim_addr) : + kernel_data_fetch(prim_object, prim_addr) : object; - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self(ray->self, prim_object, prim)) { continue; } - int object_flag = kernel_tex_fetch(__object_flag, prim_object); + int object_flag = kernel_data_fetch(object_flag, prim_object); if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { continue; } @@ -182,8 +182,8 @@ ccl_device_inline } else { /* instance push */ - object = kernel_tex_fetch(__prim_object, -prim_addr - 1); - int object_flag = kernel_tex_fetch(__object_flag, object); + object = kernel_data_fetch(prim_object, -prim_addr - 1); + int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_HAS_VOLUME) { #if BVH_FEATURE(BVH_MOTION) isect->t *= bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &ob_itfm); @@ -195,7 +195,7 @@ ccl_device_inline kernel_assert(stack_ptr < BVH_STACK_SIZE); traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL; - node_addr = kernel_tex_fetch(__object_node, object); + node_addr = kernel_data_fetch(object_node, object); } else { /* pop */ diff --git a/intern/cycles/kernel/bvh/volume_all.h b/intern/cycles/kernel/bvh/volume_all.h index a969bae14a1..d06ea8fe557 100644 --- a/intern/cycles/kernel/bvh/volume_all.h +++ b/intern/cycles/kernel/bvh/volume_all.h @@ -67,7 +67,7 @@ ccl_device_inline while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) { int node_addr_child1, traverse_mask; float dist[2]; - float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0); + float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0); traverse_mask = NODE_INTERSECT(kg, P, @@ -111,7 +111,7 @@ ccl_device_inline /* if node is leaf, fetch triangle list */ if (node_addr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1)); + float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1)); int prim_addr = __float_as_int(leaf.x); if (prim_addr >= 0) { @@ -128,16 +128,16 @@ ccl_device_inline case PRIMITIVE_TRIANGLE: { /* intersect ray against primitive */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); + kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type); /* only primitives from volume object */ const int prim_object = (object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, prim_addr) : + kernel_data_fetch(prim_object, prim_addr) : object; - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self(ray->self, prim_object, prim)) { continue; } - int object_flag = kernel_tex_fetch(__object_flag, prim_object); + int object_flag = kernel_data_fetch(object_flag, prim_object); if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { continue; } @@ -172,16 +172,16 @@ ccl_device_inline case PRIMITIVE_MOTION_TRIANGLE: { /* intersect ray against primitive */ for (; prim_addr < prim_addr2; prim_addr++) { - kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); + kernel_assert(kernel_data_fetch(prim_type, prim_addr) == type); /* only primitives from volume object */ const int prim_object = (object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, prim_addr) : + kernel_data_fetch(prim_object, prim_addr) : object; - const int prim = kernel_tex_fetch(__prim_index, prim_addr); + const int prim = kernel_data_fetch(prim_index, prim_addr); if (intersection_skip_self(ray->self, prim_object, prim)) { continue; } - int object_flag = kernel_tex_fetch(__object_flag, prim_object); + int object_flag = kernel_data_fetch(object_flag, prim_object); if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { continue; } @@ -228,8 +228,8 @@ ccl_device_inline } else { /* instance push */ - object = kernel_tex_fetch(__prim_object, -prim_addr - 1); - int object_flag = kernel_tex_fetch(__object_flag, object); + object = kernel_data_fetch(prim_object, -prim_addr - 1); + int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_HAS_VOLUME) { #if BVH_FEATURE(BVH_MOTION) isect_t *= bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &ob_itfm); @@ -244,7 +244,7 @@ ccl_device_inline kernel_assert(stack_ptr < BVH_STACK_SIZE); traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL; - node_addr = kernel_tex_fetch(__object_node, object); + node_addr = kernel_data_fetch(object_node, object); } else { /* pop */ diff --git a/intern/cycles/kernel/camera/camera.h b/intern/cycles/kernel/camera/camera.h index aad68e527ac..25960a94ddb 100644 --- a/intern/cycles/kernel/camera/camera.h +++ b/intern/cycles/kernel/camera/camera.h @@ -90,7 +90,7 @@ ccl_device void camera_sample_perspective(KernelGlobals kg, #ifdef __CAMERA_MOTION__ if (kernel_data.cam.num_motion_steps) { transform_motion_array_interpolate(&cameratoworld, - kernel_tex_array(__camera_motion), + kernel_data_array(camera_motion), kernel_data.cam.num_motion_steps, ray->time); } @@ -210,7 +210,7 @@ ccl_device void camera_sample_orthographic(KernelGlobals kg, #ifdef __CAMERA_MOTION__ if (kernel_data.cam.num_motion_steps) { transform_motion_array_interpolate(&cameratoworld, - kernel_tex_array(__camera_motion), + kernel_data_array(camera_motion), kernel_data.cam.num_motion_steps, ray->time); } @@ -421,7 +421,7 @@ ccl_device_inline void camera_sample(KernelGlobals kg, } else { #ifdef __CAMERA_MOTION__ - ccl_global const DecomposedTransform *cam_motion = kernel_tex_array(__camera_motion); + ccl_global const DecomposedTransform *cam_motion = kernel_data_array(camera_motion); camera_sample_panorama(&kernel_data.cam, cam_motion, raster_x, raster_y, lens_u, lens_v, ray); #else camera_sample_panorama(&kernel_data.cam, raster_x, raster_y, lens_u, lens_v, ray); diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 011155cdf5f..6f3c2092c64 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -434,7 +434,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg, else { /* Shadow terminator offset. */ const float frequency_multiplier = - kernel_tex_fetch(__objects, sd->object).shadow_terminator_shading_offset; + kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset; if (frequency_multiplier > 1.0f) { *eval *= shift_cos_in(dot(*omega_in, sc->N), frequency_multiplier); } @@ -556,7 +556,7 @@ ccl_device_inline } /* Shadow terminator offset. */ const float frequency_multiplier = - kernel_tex_fetch(__objects, sd->object).shadow_terminator_shading_offset; + kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset; if (frequency_multiplier > 1.0f) { eval *= shift_cos_in(dot(omega_in, sc->N), frequency_multiplier); } diff --git a/intern/cycles/kernel/data_arrays.h b/intern/cycles/kernel/data_arrays.h new file mode 100644 index 00000000000..7205f728088 --- /dev/null +++ b/intern/cycles/kernel/data_arrays.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#ifndef KERNEL_DATA_ARRAY +# define KERNEL_DATA_ARRAY(type, name) +#endif + +/* BVH2, not used for OptiX or Embree. */ +KERNEL_DATA_ARRAY(float4, bvh_nodes) +KERNEL_DATA_ARRAY(float4, bvh_leaf_nodes) +KERNEL_DATA_ARRAY(uint, prim_type) +KERNEL_DATA_ARRAY(uint, prim_visibility) +KERNEL_DATA_ARRAY(uint, prim_index) +KERNEL_DATA_ARRAY(uint, prim_object) +KERNEL_DATA_ARRAY(uint, object_node) +KERNEL_DATA_ARRAY(float2, prim_time) + +/* objects */ +KERNEL_DATA_ARRAY(KernelObject, objects) +KERNEL_DATA_ARRAY(Transform, object_motion_pass) +KERNEL_DATA_ARRAY(DecomposedTransform, object_motion) +KERNEL_DATA_ARRAY(uint, object_flag) +KERNEL_DATA_ARRAY(float, object_volume_step) +KERNEL_DATA_ARRAY(uint, object_prim_offset) + +/* cameras */ +KERNEL_DATA_ARRAY(DecomposedTransform, camera_motion) + +/* triangles */ +KERNEL_DATA_ARRAY(uint, tri_shader) +KERNEL_DATA_ARRAY(packed_float3, tri_vnormal) +KERNEL_DATA_ARRAY(uint4, tri_vindex) +KERNEL_DATA_ARRAY(uint, tri_patch) +KERNEL_DATA_ARRAY(float2, tri_patch_uv) +KERNEL_DATA_ARRAY(packed_float3, tri_verts) + +/* curves */ +KERNEL_DATA_ARRAY(KernelCurve, curves) +KERNEL_DATA_ARRAY(float4, curve_keys) +KERNEL_DATA_ARRAY(KernelCurveSegment, curve_segments) + +/* patches */ +KERNEL_DATA_ARRAY(uint, patches) + +/* pointclouds */ +KERNEL_DATA_ARRAY(float4, points) +KERNEL_DATA_ARRAY(uint, points_shader) + +/* attributes */ +KERNEL_DATA_ARRAY(AttributeMap, attributes_map) +KERNEL_DATA_ARRAY(float, attributes_float) +KERNEL_DATA_ARRAY(float2, attributes_float2) +KERNEL_DATA_ARRAY(packed_float3, attributes_float3) +KERNEL_DATA_ARRAY(float4, attributes_float4) +KERNEL_DATA_ARRAY(uchar4, attributes_uchar4) + +/* lights */ +KERNEL_DATA_ARRAY(KernelLightDistribution, light_distribution) +KERNEL_DATA_ARRAY(KernelLight, lights) +KERNEL_DATA_ARRAY(float2, light_background_marginal_cdf) +KERNEL_DATA_ARRAY(float2, light_background_conditional_cdf) + +/* particles */ +KERNEL_DATA_ARRAY(KernelParticle, particles) + +/* shaders */ +KERNEL_DATA_ARRAY(uint4, svm_nodes) +KERNEL_DATA_ARRAY(KernelShader, shaders) + +/* lookup tables */ +KERNEL_DATA_ARRAY(float, lookup_table) + +/* sobol */ +KERNEL_DATA_ARRAY(float, sample_pattern_lut) + +/* image textures */ +KERNEL_DATA_ARRAY(TextureInfo, texture_info) + +/* ies lights */ +KERNEL_DATA_ARRAY(float, ies) + +#undef KERNEL_DATA_ARRAY diff --git a/intern/cycles/kernel/device/cpu/compat.h b/intern/cycles/kernel/device/cpu/compat.h index e1c20169582..3bfc37e98ee 100644 --- a/intern/cycles/kernel/device/cpu/compat.h +++ b/intern/cycles/kernel/device/cpu/compat.h @@ -35,20 +35,6 @@ CCL_NAMESPACE_BEGIN #define kernel_assert(cond) assert(cond) -/* Texture types to be compatible with CUDA textures. These are really just - * simple arrays and after inlining fetch hopefully revert to being a simple - * pointer lookup. */ -template<typename T> struct texture { - ccl_always_inline const T &fetch(int index) const - { - kernel_assert(index >= 0 && index < width); - return data[index]; - } - - T *data; - int width; -}; - /* Macros to handle different memory storage on different devices */ #ifdef __KERNEL_SSE2__ diff --git a/intern/cycles/kernel/device/cpu/globals.h b/intern/cycles/kernel/device/cpu/globals.h index 7e080d428ea..309afae412e 100644 --- a/intern/cycles/kernel/device/cpu/globals.h +++ b/intern/cycles/kernel/device/cpu/globals.h @@ -12,7 +12,7 @@ CCL_NAMESPACE_BEGIN /* On the CPU, we pass along the struct KernelGlobals to nearly everywhere in - * the kernel, to access constant data. These are all stored as "textures", but + * the kernel, to access constant data. These are all stored as flat arrays. * these are really just standard arrays. We can't use actually globals because * multiple renders may be running inside the same process. */ @@ -22,11 +22,23 @@ struct OSLThreadData; struct OSLShadingSystem; #endif +/* Array for kernel data, with size to be able to assert on invalid data access. */ +template<typename T> struct kernel_array { + ccl_always_inline const T &fetch(int index) const + { + kernel_assert(index >= 0 && index < width); + return data[index]; + } + + T *data; + int width; +}; + typedef struct KernelGlobalsCPU { -#define KERNEL_TEX(type, name) texture<type> name; -#include "kernel/textures.h" +#define KERNEL_DATA_ARRAY(type, name) kernel_array<type> name; +#include "kernel/data_arrays.h" - KernelData __data; + KernelData data; #ifdef __OSL__ /* On the CPU, we also have the OSL globals here. Most data structures are shared @@ -44,8 +56,8 @@ typedef struct KernelGlobalsCPU { typedef const KernelGlobalsCPU *ccl_restrict KernelGlobals; /* Abstraction macros */ -#define kernel_tex_fetch(tex, index) (kg->tex.fetch(index)) -#define kernel_tex_array(tex) (kg->tex.data) -#define kernel_data (kg->__data) +#define kernel_data_fetch(name, index) (kg->name.fetch(index)) +#define kernel_data_array(name) (kg->name.data) +#define kernel_data (kg->data) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/device/cpu/image.h b/intern/cycles/kernel/device/cpu/image.h index 7809ec5f4a7..320e6309128 100644 --- a/intern/cycles/kernel/device/cpu/image.h +++ b/intern/cycles/kernel/device/cpu/image.h @@ -733,7 +733,7 @@ template<typename TexT, typename OutT = float4> struct NanoVDBInterpolator { ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, float y) { - const TextureInfo &info = kernel_tex_fetch(__texture_info, id); + const TextureInfo &info = kernel_data_fetch(texture_info, id); if (UNLIKELY(!info.data)) { return zero_float4(); @@ -776,7 +776,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg, float3 P, InterpolationType interp) { - const TextureInfo &info = kernel_tex_fetch(__texture_info, id); + const TextureInfo &info = kernel_data_fetch(texture_info, id); if (UNLIKELY(!info.data)) { return zero_float4(); diff --git a/intern/cycles/kernel/device/cpu/kernel.cpp b/intern/cycles/kernel/device/cpu/kernel.cpp index b12e3089378..01087c96dd6 100644 --- a/intern/cycles/kernel/device/cpu/kernel.cpp +++ b/intern/cycles/kernel/device/cpu/kernel.cpp @@ -53,8 +53,8 @@ CCL_NAMESPACE_BEGIN void kernel_const_copy(KernelGlobalsCPU *kg, const char *name, void *host, size_t) { - if (strcmp(name, "__data") == 0) { - kg->__data = *(KernelData *)host; + if (strcmp(name, "data") == 0) { + kg->data = *(KernelData *)host; } else { assert(0); @@ -66,13 +66,13 @@ void kernel_global_memory_copy(KernelGlobalsCPU *kg, const char *name, void *mem if (0) { } -#define KERNEL_TEX(type, tname) \ +#define KERNEL_DATA_ARRAY(type, tname) \ else if (strcmp(name, #tname) == 0) \ { \ kg->tname.data = (type *)mem; \ kg->tname.width = size; \ } -#include "kernel/textures.h" +#include "kernel/data_arrays.h" else { assert(0); } diff --git a/intern/cycles/kernel/device/cuda/globals.h b/intern/cycles/kernel/device/cuda/globals.h index e77fcd2b424..f5f7bcf58ee 100644 --- a/intern/cycles/kernel/device/cuda/globals.h +++ b/intern/cycles/kernel/device/cuda/globals.h @@ -20,18 +20,24 @@ struct KernelGlobalsGPU { }; typedef ccl_global const KernelGlobalsGPU *ccl_restrict KernelGlobals; -/* Global scene data and textures */ -__constant__ KernelData __data; -#define KERNEL_TEX(type, name) const __constant__ __device__ type *name; -#include "kernel/textures.h" +struct KernelParamsCUDA { + /* Global scene data and textures */ + KernelData data; +#define KERNEL_DATA_ARRAY(type, name) const type *name; +#include "kernel/data_arrays.h" + + /* Integrator state */ + IntegratorStateGPU integrator_state; +}; -/* Integrator state */ -__constant__ IntegratorStateGPU __integrator_state; +#ifdef __KERNEL_GPU__ +__constant__ KernelParamsCUDA kernel_params; +#endif /* Abstraction macros */ -#define kernel_data __data -#define kernel_tex_fetch(t, index) t[(index)] -#define kernel_tex_array(t) (t) -#define kernel_integrator_state __integrator_state +#define kernel_data kernel_params.data +#define kernel_data_fetch(name, index) kernel_params.name[(index)] +#define kernel_data_array(name) (kernel_params.name) +#define kernel_integrator_state kernel_params.integrator_state CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h index 29d851ae478..a8c72645569 100644 --- a/intern/cycles/kernel/device/gpu/image.h +++ b/intern/cycles/kernel/device/gpu/image.h @@ -181,7 +181,7 @@ ccl_device_noinline typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_in ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, float y) { - ccl_global const TextureInfo &info = kernel_tex_fetch(__texture_info, id); + ccl_global const TextureInfo &info = kernel_data_fetch(texture_info, id); /* float4, byte4, ushort4 and half4 */ const int texture_type = info.data_type; @@ -216,7 +216,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg, float3 P, InterpolationType interp) { - ccl_global const TextureInfo &info = kernel_tex_fetch(__texture_info, id); + ccl_global const TextureInfo &info = kernel_data_fetch(texture_info, id); if (info.use_transform_3d) { P = transform_point(&info.transform_3d, P); diff --git a/intern/cycles/kernel/device/hip/globals.h b/intern/cycles/kernel/device/hip/globals.h index 50f117038a2..3a334b21a9e 100644 --- a/intern/cycles/kernel/device/hip/globals.h +++ b/intern/cycles/kernel/device/hip/globals.h @@ -20,18 +20,24 @@ struct KernelGlobalsGPU { }; typedef ccl_global const KernelGlobalsGPU *ccl_restrict KernelGlobals; -/* Global scene data and textures */ -__constant__ KernelData __data; -#define KERNEL_TEX(type, name) __attribute__((used)) const __constant__ __device__ type *name; -#include "kernel/textures.h" +struct KernelParamsHIP { + /* Global scene data and textures */ + KernelData data; +#define KERNEL_DATA_ARRAY(type, name) const type *name; +#include "kernel/data_arrays.h" + + /* Integrator state */ + IntegratorStateGPU integrator_state; +}; -/* Integrator state */ -__constant__ IntegratorStateGPU __integrator_state; +#ifdef __KERNEL_GPU__ +__constant__ KernelParamsHIP kernel_params; +#endif /* Abstraction macros */ -#define kernel_data __data -#define kernel_tex_fetch(t, index) t[(index)] -#define kernel_tex_array(t) (t) -#define kernel_integrator_state __integrator_state +#define kernel_data kernel_params.data +#define kernel_data_fetch(name, index) kernel_params.name[(index)] +#define kernel_data_array(name) (kernel_params.name) +#define kernel_integrator_state kernel_params.integrator_state CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/device/metal/context_end.h b/intern/cycles/kernel/device/metal/context_end.h index b4c8661c401..44ac0478266 100644 --- a/intern/cycles/kernel/device/metal/context_end.h +++ b/intern/cycles/kernel/device/metal/context_end.h @@ -7,4 +7,4 @@ /* NOTE: These macros will need maintaining as entry-points change. */ #undef kernel_integrator_state -#define kernel_integrator_state context.launch_params_metal.__integrator_state +#define kernel_integrator_state context.launch_params_metal.integrator_state diff --git a/intern/cycles/kernel/device/metal/globals.h b/intern/cycles/kernel/device/metal/globals.h index 1c3e775dbae..a336c096440 100644 --- a/intern/cycles/kernel/device/metal/globals.h +++ b/intern/cycles/kernel/device/metal/globals.h @@ -12,11 +12,11 @@ CCL_NAMESPACE_BEGIN typedef struct KernelParamsMetal { -#define KERNEL_TEX(type, name) ccl_global const type *name; -#include "kernel/textures.h" -#undef KERNEL_TEX +#define KERNEL_DATA_ARRAY(type, name) ccl_global const type *name; +#include "kernel/data_arrays.h" +#undef KERNEL_DATA_ARRAY - const IntegratorStateGPU __integrator_state; + const IntegratorStateGPU integrator_state; const KernelData data; } KernelParamsMetal; @@ -27,12 +27,10 @@ typedef struct KernelGlobalsGPU { typedef ccl_global const KernelGlobalsGPU *ccl_restrict KernelGlobals; +/* Abstraction macros */ #define kernel_data launch_params_metal.data -#define kernel_integrator_state launch_params_metal.__integrator_state - -/* data lookup defines */ - -#define kernel_tex_fetch(tex, index) launch_params_metal.tex[index] -#define kernel_tex_array(tex) launch_params_metal.tex +#define kernel_data_fetch(name, index) launch_params_metal.name[index] +#define kernel_data_array(name) launch_params_metal.name +#define kernel_integrator_state launch_params_metal.integrator_state CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/device/metal/kernel.metal b/intern/cycles/kernel/device/metal/kernel.metal index a7252570e64..3c31dc3354c 100644 --- a/intern/cycles/kernel/device/metal/kernel.metal +++ b/intern/cycles/kernel/device/metal/kernel.metal @@ -59,7 +59,7 @@ TReturn metalrt_local_hit(constant KernelParamsMetal &launch_params_metal, TReturn result; #ifdef __BVH_LOCAL__ - uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); + uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); if ((object != payload.local_object) || intersection_skip_self_local(payload.self, prim)) { /* Only intersect with matching object and skip self-intersecton. */ @@ -113,16 +113,16 @@ TReturn metalrt_local_hit(constant KernelParamsMetal &launch_params_metal, isect->t = ray_tmax; isect->prim = prim; isect->object = object; - isect->type = kernel_tex_fetch(__objects, object).primitive_type; + isect->type = kernel_data_fetch(objects, object).primitive_type; isect->u = 1.0f - barycentrics.y - barycentrics.x; isect->v = barycentrics.x; /* Record geometric normal */ - const uint tri_vindex = kernel_tex_fetch(__tri_vindex, isect->prim).w; - const float3 tri_a = float3(kernel_tex_fetch(__tri_verts, tri_vindex + 0)); - const float3 tri_b = float3(kernel_tex_fetch(__tri_verts, tri_vindex + 1)); - const float3 tri_c = float3(kernel_tex_fetch(__tri_verts, tri_vindex + 2)); + const uint tri_vindex = kernel_data_fetch(tri_vindex, isect->prim).w; + const float3 tri_a = float3(kernel_data_fetch(tri_verts, tri_vindex + 0)); + const float3 tri_b = float3(kernel_data_fetch(tri_verts, tri_vindex + 1)); + const float3 tri_c = float3(kernel_data_fetch(tri_verts, tri_vindex + 2)); payload.local_isect.Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a)); /* Continue tracing (without this the trace call would return after the first hit) */ @@ -168,7 +168,7 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal, #ifdef __SHADOW_RECORD_ALL__ # ifdef __VISIBILITY_FLAG__ const uint visibility = payload.visibility; - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { /* continue search */ return true; } @@ -184,14 +184,14 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal, if (intersection_type == METALRT_HIT_TRIANGLE) { u = 1.0f - barycentrics.y - barycentrics.x; v = barycentrics.x; - type = kernel_tex_fetch(__objects, object).primitive_type; + type = kernel_data_fetch(objects, object).primitive_type; } # ifdef __HAIR__ else { u = barycentrics.x; v = barycentrics.y; - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, prim); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim); type = segment.type; prim = segment.prim; @@ -294,7 +294,7 @@ __anyhit__cycles_metalrt_shadow_all_hit_tri(constant KernelParamsMetal &launch_p float2 barycentrics [[barycentric_coord]], float ray_tmax [[distance]]) { - uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); + uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); TriangleIntersectionResult result; result.continue_search = metalrt_shadow_all_hit<METALRT_HIT_TRIANGLE>( @@ -337,7 +337,7 @@ inline TReturnType metalrt_visibility_test(constant KernelParamsMetal &launch_pa uint visibility = payload.visibility; # ifdef __VISIBILITY_FLAG__ - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { result.accept = false; result.continue_search = true; return result; @@ -377,12 +377,12 @@ __anyhit__cycles_metalrt_visibility_test_tri(constant KernelParamsMetal &launch_ unsigned int object [[user_instance_id]], unsigned int primitive_id [[primitive_id]]) { - uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); + uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); TriangleIntersectionResult result = metalrt_visibility_test<TriangleIntersectionResult, METALRT_HIT_TRIANGLE>( launch_params_metal, payload, object, prim, 0.0f); if (result.accept) { payload.prim = prim; - payload.type = kernel_tex_fetch(__objects, object).primitive_type; + payload.type = kernel_data_fetch(objects, object).primitive_type; } return result; } @@ -414,7 +414,7 @@ void metalrt_intersection_curve(constant KernelParamsMetal &launch_params_metal, { # ifdef __VISIBILITY_FLAG__ const uint visibility = payload.visibility; - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { return; } # endif @@ -495,8 +495,8 @@ __intersection__curve_ribbon(constant KernelParamsMetal &launch_params_metal [[b const float3 ray_direction [[direction]], const float ray_tmax [[max_distance]]) { - uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, prim); + uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim); BoundingBoxIntersectionResult result; result.accept = false; @@ -526,8 +526,8 @@ __intersection__curve_ribbon_shadow(constant KernelParamsMetal &launch_params_me const float3 ray_direction [[direction]], const float ray_tmax [[max_distance]]) { - uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, prim); + uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim); BoundingBoxIntersectionResult result; result.accept = false; @@ -557,8 +557,8 @@ __intersection__curve_all(constant KernelParamsMetal &launch_params_metal [[buff const float3 ray_direction [[direction]], const float ray_tmax [[max_distance]]) { - uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, prim); + uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim); BoundingBoxIntersectionResult result; result.accept = false; @@ -585,8 +585,8 @@ __intersection__curve_all_shadow(constant KernelParamsMetal &launch_params_metal const float3 ray_direction [[direction]], const float ray_tmax [[max_distance]]) { - uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, prim); + uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim); BoundingBoxIntersectionResult result; result.accept = false; @@ -620,7 +620,7 @@ void metalrt_intersection_point(constant KernelParamsMetal &launch_params_metal, { # ifdef __VISIBILITY_FLAG__ const uint visibility = payload.visibility; - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { return; } # endif @@ -701,8 +701,8 @@ __intersection__point(constant KernelParamsMetal &launch_params_metal [[buffer(1 const float3 ray_direction [[direction]], const float ray_tmax [[max_distance]]) { - const uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); - const int type = kernel_tex_fetch(__objects, object).primitive_type; + const uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); + const int type = kernel_data_fetch(objects, object).primitive_type; BoundingBoxIntersectionResult result; result.accept = false; @@ -730,8 +730,8 @@ __intersection__point_shadow(constant KernelParamsMetal &launch_params_metal [[b const float3 ray_direction [[direction]], const float ray_tmax [[max_distance]]) { - const uint prim = primitive_id + kernel_tex_fetch(__object_prim_offset, object); - const int type = kernel_tex_fetch(__objects, object).primitive_type; + const uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object); + const int type = kernel_data_fetch(objects, object).primitive_type; BoundingBoxIntersectionResult result; result.accept = false; diff --git a/intern/cycles/kernel/device/optix/globals.h b/intern/cycles/kernel/device/optix/globals.h index bb752c531f0..7af2e421378 100644 --- a/intern/cycles/kernel/device/optix/globals.h +++ b/intern/cycles/kernel/device/optix/globals.h @@ -28,21 +28,21 @@ struct KernelParamsOptiX { /* Global scene data and textures */ KernelData data; -#define KERNEL_TEX(type, name) const type *name; -#include "kernel/textures.h" +#define KERNEL_DATA_ARRAY(type, name) const type *name; +#include "kernel/data_arrays.h" /* Integrator state */ - IntegratorStateGPU __integrator_state; + IntegratorStateGPU integrator_state; }; #ifdef __NVCC__ -extern "C" static __constant__ KernelParamsOptiX __params; +extern "C" static __constant__ KernelParamsOptiX kernel_params; #endif /* Abstraction macros */ -#define kernel_data __params.data -#define kernel_tex_array(t) __params.t -#define kernel_tex_fetch(t, index) __params.t[(index)] -#define kernel_integrator_state __params.__integrator_state +#define kernel_data kernel_params.data +#define kernel_data_array(name) kernel_params.name +#define kernel_data_fetch(name, index) kernel_params.name[(index)] +#define kernel_integrator_state kernel_params.integrator_state CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/device/optix/kernel.cu b/intern/cycles/kernel/device/optix/kernel.cu index 9843b2e99be..949bf41d171 100644 --- a/intern/cycles/kernel/device/optix/kernel.cu +++ b/intern/cycles/kernel/device/optix/kernel.cu @@ -51,15 +51,15 @@ ccl_device_forceinline int get_object_id() extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_closest() { const int global_index = optixGetLaunchIndex().x; - const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] : + const int path_index = (kernel_params.path_index_array) ? kernel_params.path_index_array[global_index] : global_index; - integrator_intersect_closest(nullptr, path_index, __params.render_buffer); + integrator_intersect_closest(nullptr, path_index, kernel_params.render_buffer); } extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_shadow() { const int global_index = optixGetLaunchIndex().x; - const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] : + const int path_index = (kernel_params.path_index_array) ? kernel_params.path_index_array[global_index] : global_index; integrator_intersect_shadow(nullptr, path_index); } @@ -67,7 +67,7 @@ extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_shadow() extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_subsurface() { const int global_index = optixGetLaunchIndex().x; - const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] : + const int path_index = (kernel_params.path_index_array) ? kernel_params.path_index_array[global_index] : global_index; integrator_intersect_subsurface(nullptr, path_index); } @@ -75,7 +75,7 @@ extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_subsurfac extern "C" __global__ void __raygen__kernel_optix_integrator_intersect_volume_stack() { const int global_index = optixGetLaunchIndex().x; - const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] : + const int path_index = (kernel_params.path_index_array) ? kernel_params.path_index_array[global_index] : global_index; integrator_intersect_volume_stack(nullptr, path_index); } @@ -151,17 +151,17 @@ extern "C" __global__ void __anyhit__kernel_optix_local_hit() isect->t = optixGetRayTmax(); isect->prim = prim; isect->object = get_object_id(); - isect->type = kernel_tex_fetch(__objects, isect->object).primitive_type; + isect->type = kernel_data_fetch(objects, isect->object).primitive_type; const float2 barycentrics = optixGetTriangleBarycentrics(); isect->u = 1.0f - barycentrics.y - barycentrics.x; isect->v = barycentrics.x; /* Record geometric normal. */ - const uint tri_vindex = kernel_tex_fetch(__tri_vindex, prim).w; - const float3 tri_a = kernel_tex_fetch(__tri_verts, tri_vindex + 0); - const float3 tri_b = kernel_tex_fetch(__tri_verts, tri_vindex + 1); - const float3 tri_c = kernel_tex_fetch(__tri_verts, tri_vindex + 2); + const uint tri_vindex = kernel_data_fetch(tri_vindex, prim).w; + const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex + 0); + const float3 tri_b = kernel_data_fetch(tri_verts, tri_vindex + 1); + const float3 tri_c = kernel_data_fetch(tri_verts, tri_vindex + 2); local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a)); /* Continue tracing (without this the trace call would return after the first hit). */ @@ -176,7 +176,7 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit() const uint object = get_object_id(); # ifdef __VISIBILITY_FLAG__ const uint visibility = optixGetPayload_4(); - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { return optixIgnoreIntersection(); } # endif @@ -192,14 +192,14 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit() const float2 barycentrics = optixGetTriangleBarycentrics(); u = 1.0f - barycentrics.y - barycentrics.x; v = barycentrics.x; - type = kernel_tex_fetch(__objects, object).primitive_type; + type = kernel_data_fetch(objects, object).primitive_type; } # ifdef __HAIR__ else if ((optixGetHitKind() & (~PRIMITIVE_MOTION)) != PRIMITIVE_POINT) { u = __uint_as_float(optixGetAttribute_0()); v = __uint_as_float(optixGetAttribute_1()); - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, prim); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim); type = segment.type; prim = segment.prim; @@ -212,7 +212,7 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit() } # endif else { - type = kernel_tex_fetch(__objects, object).primitive_type; + type = kernel_data_fetch(objects, object).primitive_type; u = 0.0f; v = 0.0f; } @@ -307,12 +307,12 @@ extern "C" __global__ void __anyhit__kernel_optix_volume_test() const uint object = get_object_id(); #ifdef __VISIBILITY_FLAG__ const uint visibility = optixGetPayload_4(); - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { return optixIgnoreIntersection(); } #endif - if ((kernel_tex_fetch(__object_flag, object) & SD_OBJECT_HAS_VOLUME) == 0) { + if ((kernel_data_fetch(object_flag, object) & SD_OBJECT_HAS_VOLUME) == 0) { return optixIgnoreIntersection(); } @@ -340,7 +340,7 @@ extern "C" __global__ void __anyhit__kernel_optix_visibility_test() const uint object = get_object_id(); const uint visibility = optixGetPayload_4(); #ifdef __VISIBILITY_FLAG__ - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { return optixIgnoreIntersection(); } #endif @@ -377,10 +377,10 @@ extern "C" __global__ void __closesthit__kernel_optix_hit() optixSetPayload_1(__float_as_uint(1.0f - barycentrics.y - barycentrics.x)); optixSetPayload_2(__float_as_uint(barycentrics.x)); optixSetPayload_3(prim); - optixSetPayload_5(kernel_tex_fetch(__objects, object).primitive_type); + optixSetPayload_5(kernel_data_fetch(objects, object).primitive_type); } else if ((optixGetHitKind() & (~PRIMITIVE_MOTION)) != PRIMITIVE_POINT) { - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, prim); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim); optixSetPayload_1(optixGetAttribute_0()); /* Same as 'optixGetCurveParameter()' */ optixSetPayload_2(optixGetAttribute_1()); optixSetPayload_3(segment.prim); @@ -390,7 +390,7 @@ extern "C" __global__ void __closesthit__kernel_optix_hit() optixSetPayload_1(0); optixSetPayload_2(0); optixSetPayload_3(prim); - optixSetPayload_5(kernel_tex_fetch(__objects, object).primitive_type); + optixSetPayload_5(kernel_data_fetch(objects, object).primitive_type); } } @@ -401,7 +401,7 @@ ccl_device_inline void optix_intersection_curve(const int prim, const int type) # ifdef __VISIBILITY_FLAG__ const uint visibility = optixGetPayload_4(); - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { return; } # endif @@ -436,7 +436,7 @@ ccl_device_inline void optix_intersection_curve(const int prim, const int type) extern "C" __global__ void __intersection__curve_ribbon() { - const KernelCurveSegment segment = kernel_tex_fetch(__curve_segments, optixGetPrimitiveIndex()); + const KernelCurveSegment segment = kernel_data_fetch(curve_segments, optixGetPrimitiveIndex()); const int prim = segment.prim; const int type = segment.type; if (type & PRIMITIVE_CURVE_RIBBON) { @@ -451,11 +451,11 @@ extern "C" __global__ void __intersection__point() { const int prim = optixGetPrimitiveIndex(); const int object = get_object_id(); - const int type = kernel_tex_fetch(__objects, object).primitive_type; + const int type = kernel_data_fetch(objects, object).primitive_type; # ifdef __VISIBILITY_FLAG__ const uint visibility = optixGetPayload_4(); - if ((kernel_tex_fetch(__objects, object).visibility & visibility) == 0) { + if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) { return; } # endif diff --git a/intern/cycles/kernel/device/optix/kernel_shader_raytrace.cu b/intern/cycles/kernel/device/optix/kernel_shader_raytrace.cu index 3bd57bc0f1a..41e6224f6da 100644 --- a/intern/cycles/kernel/device/optix/kernel_shader_raytrace.cu +++ b/intern/cycles/kernel/device/optix/kernel_shader_raytrace.cu @@ -11,15 +11,15 @@ extern "C" __global__ void __raygen__kernel_optix_integrator_shade_surface_raytrace() { const int global_index = optixGetLaunchIndex().x; - const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] : + const int path_index = (kernel_params.path_index_array) ? kernel_params.path_index_array[global_index] : global_index; - integrator_shade_surface_raytrace(nullptr, path_index, __params.render_buffer); + integrator_shade_surface_raytrace(nullptr, path_index, kernel_params.render_buffer); } extern "C" __global__ void __raygen__kernel_optix_integrator_shade_surface_mnee() { const int global_index = optixGetLaunchIndex().x; - const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] : + const int path_index = (kernel_params.path_index_array) ? kernel_params.path_index_array[global_index] : global_index; - integrator_shade_surface_mnee(nullptr, path_index, __params.render_buffer); + integrator_shade_surface_mnee(nullptr, path_index, kernel_params.render_buffer); } diff --git a/intern/cycles/kernel/geom/attribute.h b/intern/cycles/kernel/geom/attribute.h index da620f69e2d..31a9e39d528 100644 --- a/intern/cycles/kernel/geom/attribute.h +++ b/intern/cycles/kernel/geom/attribute.h @@ -18,7 +18,7 @@ CCL_NAMESPACE_BEGIN ccl_device_inline uint subd_triangle_patch(KernelGlobals kg, ccl_private const ShaderData *sd) { - return (sd->prim != PRIM_NONE) ? kernel_tex_fetch(__tri_patch, sd->prim) : ~0; + return (sd->prim != PRIM_NONE) ? kernel_data_fetch(tri_patch, sd->prim) : ~0; } ccl_device_inline uint attribute_primitive_type(KernelGlobals kg, ccl_private const ShaderData *sd) @@ -42,7 +42,7 @@ ccl_device_inline AttributeDescriptor attribute_not_found() ccl_device_inline uint object_attribute_map_offset(KernelGlobals kg, int object) { - return kernel_tex_fetch(__objects, object).attribute_map_offset; + return kernel_data_fetch(objects, object).attribute_map_offset; } ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, @@ -56,26 +56,26 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, /* for SVM, find attribute by unique id */ uint attr_offset = object_attribute_map_offset(kg, sd->object); attr_offset += attribute_primitive_type(kg, sd); - uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); + AttributeMap attr_map = kernel_data_fetch(attributes_map, attr_offset); - while (attr_map.x != id) { - if (UNLIKELY(attr_map.x == ATTR_STD_NONE)) { - if (UNLIKELY(attr_map.y == 0)) { + while (attr_map.id != id) { + if (UNLIKELY(attr_map.id == ATTR_STD_NONE)) { + if (UNLIKELY(attr_map.element == 0)) { return attribute_not_found(); } else { /* Chain jump to a different part of the table. */ - attr_offset = attr_map.z; + attr_offset = attr_map.offset; } } else { attr_offset += ATTR_PRIM_TYPES; } - attr_map = kernel_tex_fetch(__attributes_map, attr_offset); + attr_map = kernel_data_fetch(attributes_map, attr_offset); } AttributeDescriptor desc; - desc.element = (AttributeElement)attr_map.y; + desc.element = (AttributeElement)attr_map.element; if (sd->prim == PRIM_NONE && desc.element != ATTR_ELEMENT_MESH && desc.element != ATTR_ELEMENT_VOXEL && desc.element != ATTR_ELEMENT_OBJECT) { @@ -83,9 +83,10 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, } /* return result */ - desc.offset = (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z; - desc.type = (NodeAttributeType)(attr_map.w & 0xff); - desc.flags = (AttributeFlag)(attr_map.w >> 8); + desc.offset = (attr_map.element == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : + (int)attr_map.offset; + desc.type = (NodeAttributeType)attr_map.type; + desc.flags = (AttributeFlag)attr_map.flags; return desc; } @@ -98,9 +99,9 @@ ccl_device Transform primitive_attribute_matrix(KernelGlobals kg, { Transform tfm; - tfm.x = kernel_tex_fetch(__attributes_float4, desc.offset + 0); - tfm.y = kernel_tex_fetch(__attributes_float4, desc.offset + 1); - tfm.z = kernel_tex_fetch(__attributes_float4, desc.offset + 2); + tfm.x = kernel_data_fetch(attributes_float4, desc.offset + 0); + tfm.y = kernel_data_fetch(attributes_float4, desc.offset + 1); + tfm.z = kernel_data_fetch(attributes_float4, desc.offset + 2); return tfm; } diff --git a/intern/cycles/kernel/geom/curve.h b/intern/cycles/kernel/geom/curve.h index 4dbc6d4f6db..e243adfde21 100644 --- a/intern/cycles/kernel/geom/curve.h +++ b/intern/cycles/kernel/geom/curve.h @@ -23,12 +23,12 @@ ccl_device float curve_attribute_float(KernelGlobals kg, ccl_private float *dy) { if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { - KernelCurve curve = kernel_tex_fetch(__curves, sd->prim); + KernelCurve curve = kernel_data_fetch(curves, sd->prim); int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; - float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0); - float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1); + float f0 = kernel_data_fetch(attributes_float, desc.offset + k0); + float f1 = kernel_data_fetch(attributes_float, desc.offset + k1); # ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -50,7 +50,7 @@ ccl_device float curve_attribute_float(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float, offset); + return kernel_data_fetch(attributes_float, offset); } else { return 0.0f; @@ -65,12 +65,12 @@ ccl_device float2 curve_attribute_float2(KernelGlobals kg, ccl_private float2 *dy) { if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { - KernelCurve curve = kernel_tex_fetch(__curves, sd->prim); + KernelCurve curve = kernel_data_fetch(curves, sd->prim); int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; - float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + k0); - float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + k1); + float2 f0 = kernel_data_fetch(attributes_float2, desc.offset + k0); + float2 f1 = kernel_data_fetch(attributes_float2, desc.offset + k1); # ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -96,7 +96,7 @@ ccl_device float2 curve_attribute_float2(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float2, offset); + return kernel_data_fetch(attributes_float2, offset); } else { return make_float2(0.0f, 0.0f); @@ -111,12 +111,12 @@ ccl_device float3 curve_attribute_float3(KernelGlobals kg, ccl_private float3 *dy) { if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { - KernelCurve curve = kernel_tex_fetch(__curves, sd->prim); + KernelCurve curve = kernel_data_fetch(curves, sd->prim); int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; - float3 f0 = kernel_tex_fetch(__attributes_float3, desc.offset + k0); - float3 f1 = kernel_tex_fetch(__attributes_float3, desc.offset + k1); + float3 f0 = kernel_data_fetch(attributes_float3, desc.offset + k0); + float3 f1 = kernel_data_fetch(attributes_float3, desc.offset + k1); # ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -138,7 +138,7 @@ ccl_device float3 curve_attribute_float3(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float3, offset); + return kernel_data_fetch(attributes_float3, offset); } else { return make_float3(0.0f, 0.0f, 0.0f); @@ -153,12 +153,12 @@ ccl_device float4 curve_attribute_float4(KernelGlobals kg, ccl_private float4 *dy) { if (desc.element & (ATTR_ELEMENT_CURVE_KEY | ATTR_ELEMENT_CURVE_KEY_MOTION)) { - KernelCurve curve = kernel_tex_fetch(__curves, sd->prim); + KernelCurve curve = kernel_data_fetch(curves, sd->prim); int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; - float4 f0 = kernel_tex_fetch(__attributes_float4, desc.offset + k0); - float4 f1 = kernel_tex_fetch(__attributes_float4, desc.offset + k1); + float4 f0 = kernel_data_fetch(attributes_float4, desc.offset + k0); + float4 f1 = kernel_data_fetch(attributes_float4, desc.offset + k1); # ifdef __RAY_DIFFERENTIALS__ if (dx) @@ -180,7 +180,7 @@ ccl_device float4 curve_attribute_float4(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_CURVE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float4, offset); + return kernel_data_fetch(attributes_float4, offset); } else { return zero_float4(); @@ -195,15 +195,15 @@ ccl_device float curve_thickness(KernelGlobals kg, ccl_private const ShaderData float r = 0.0f; if (sd->type & PRIMITIVE_CURVE) { - KernelCurve curve = kernel_tex_fetch(__curves, sd->prim); + KernelCurve curve = kernel_data_fetch(curves, sd->prim); int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; float4 P_curve[2]; if (!(sd->type & PRIMITIVE_MOTION)) { - P_curve[0] = kernel_tex_fetch(__curve_keys, k0); - P_curve[1] = kernel_tex_fetch(__curve_keys, k1); + P_curve[0] = kernel_data_fetch(curve_keys, k0); + P_curve[1] = kernel_data_fetch(curve_keys, k1); } else { motion_curve_keys_linear(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve); @@ -232,14 +232,14 @@ ccl_device float curve_random(KernelGlobals kg, ccl_private const ShaderData *sd ccl_device float3 curve_motion_center_location(KernelGlobals kg, ccl_private const ShaderData *sd) { - KernelCurve curve = kernel_tex_fetch(__curves, sd->prim); + KernelCurve curve = kernel_data_fetch(curves, sd->prim); int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; float4 P_curve[2]; - P_curve[0] = kernel_tex_fetch(__curve_keys, k0); - P_curve[1] = kernel_tex_fetch(__curve_keys, k1); + P_curve[0] = kernel_data_fetch(curve_keys, k0); + P_curve[1] = kernel_data_fetch(curve_keys, k1); return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u); } diff --git a/intern/cycles/kernel/geom/curve_intersect.h b/intern/cycles/kernel/geom/curve_intersect.h index e1a1f9c02c5..11ec42a0598 100644 --- a/intern/cycles/kernel/geom/curve_intersect.h +++ b/intern/cycles/kernel/geom/curve_intersect.h @@ -624,7 +624,7 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals kg, { const bool is_motion = (type & PRIMITIVE_MOTION); - KernelCurve kcurve = kernel_tex_fetch(__curves, prim); + KernelCurve kcurve = kernel_data_fetch(curves, prim); int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type); int k1 = k0 + 1; @@ -633,10 +633,10 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals kg, float4 curve[4]; if (!is_motion) { - curve[0] = kernel_tex_fetch(__curve_keys, ka); - curve[1] = kernel_tex_fetch(__curve_keys, k0); - curve[2] = kernel_tex_fetch(__curve_keys, k1); - curve[3] = kernel_tex_fetch(__curve_keys, kb); + curve[0] = kernel_data_fetch(curve_keys, ka); + curve[1] = kernel_data_fetch(curve_keys, k0); + curve[2] = kernel_data_fetch(curve_keys, k1); + curve[3] = kernel_data_fetch(curve_keys, kb); } else { motion_curve_keys(kg, object, prim, time, ka, k0, k1, kb, curve); @@ -682,7 +682,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg, D = safe_normalize_len(D, &t); } - KernelCurve kcurve = kernel_tex_fetch(__curves, isect_prim); + KernelCurve kcurve = kernel_data_fetch(curves, isect_prim); int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; @@ -692,10 +692,10 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg, float4 P_curve[4]; if (!(sd->type & PRIMITIVE_MOTION)) { - P_curve[0] = kernel_tex_fetch(__curve_keys, ka); - P_curve[1] = kernel_tex_fetch(__curve_keys, k0); - P_curve[2] = kernel_tex_fetch(__curve_keys, k1); - P_curve[3] = kernel_tex_fetch(__curve_keys, kb); + P_curve[0] = kernel_data_fetch(curve_keys, ka); + P_curve[1] = kernel_data_fetch(curve_keys, k0); + P_curve[2] = kernel_data_fetch(curve_keys, k1); + P_curve[3] = kernel_data_fetch(curve_keys, kb); } else { motion_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve); @@ -750,7 +750,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg, sd->P = P; sd->Ng = (sd->type & PRIMITIVE_CURVE_RIBBON) ? sd->I : sd->N; sd->dPdv = cross(sd->dPdu, sd->Ng); - sd->shader = kernel_tex_fetch(__curves, sd->prim).shader_id; + sd->shader = kernel_data_fetch(curves, sd->prim).shader_id; } #endif diff --git a/intern/cycles/kernel/geom/motion_curve.h b/intern/cycles/kernel/geom/motion_curve.h index b5289b6dda1..448e4b95e0b 100644 --- a/intern/cycles/kernel/geom/motion_curve.h +++ b/intern/cycles/kernel/geom/motion_curve.h @@ -27,8 +27,8 @@ ccl_device_inline void motion_curve_keys_for_step_linear(KernelGlobals kg, { if (step == numsteps) { /* center step: regular key location */ - keys[0] = kernel_tex_fetch(__curve_keys, k0); - keys[1] = kernel_tex_fetch(__curve_keys, k1); + keys[0] = kernel_data_fetch(curve_keys, k0); + keys[1] = kernel_data_fetch(curve_keys, k1); } else { /* center step is not stored in this array */ @@ -37,8 +37,8 @@ ccl_device_inline void motion_curve_keys_for_step_linear(KernelGlobals kg, offset += step * numkeys; - keys[0] = kernel_tex_fetch(__attributes_float4, offset + k0); - keys[1] = kernel_tex_fetch(__attributes_float4, offset + k1); + keys[0] = kernel_data_fetch(attributes_float4, offset + k0); + keys[1] = kernel_data_fetch(attributes_float4, offset + k1); } } @@ -83,10 +83,10 @@ ccl_device_inline void motion_curve_keys_for_step(KernelGlobals kg, { if (step == numsteps) { /* center step: regular key location */ - keys[0] = kernel_tex_fetch(__curve_keys, k0); - keys[1] = kernel_tex_fetch(__curve_keys, k1); - keys[2] = kernel_tex_fetch(__curve_keys, k2); - keys[3] = kernel_tex_fetch(__curve_keys, k3); + keys[0] = kernel_data_fetch(curve_keys, k0); + keys[1] = kernel_data_fetch(curve_keys, k1); + keys[2] = kernel_data_fetch(curve_keys, k2); + keys[3] = kernel_data_fetch(curve_keys, k3); } else { /* center step is not stored in this array */ @@ -95,10 +95,10 @@ ccl_device_inline void motion_curve_keys_for_step(KernelGlobals kg, offset += step * numkeys; - keys[0] = kernel_tex_fetch(__attributes_float4, offset + k0); - keys[1] = kernel_tex_fetch(__attributes_float4, offset + k1); - keys[2] = kernel_tex_fetch(__attributes_float4, offset + k2); - keys[3] = kernel_tex_fetch(__attributes_float4, offset + k3); + keys[0] = kernel_data_fetch(attributes_float4, offset + k0); + keys[1] = kernel_data_fetch(attributes_float4, offset + k1); + keys[2] = kernel_data_fetch(attributes_float4, offset + k2); + keys[3] = kernel_data_fetch(attributes_float4, offset + k3); } } diff --git a/intern/cycles/kernel/geom/motion_point.h b/intern/cycles/kernel/geom/motion_point.h index c1952ab090a..4916ae702ff 100644 --- a/intern/cycles/kernel/geom/motion_point.h +++ b/intern/cycles/kernel/geom/motion_point.h @@ -19,7 +19,7 @@ motion_point_for_step(KernelGlobals kg, int offset, int numkeys, int numsteps, i { if (step == numsteps) { /* center step: regular key location */ - return kernel_tex_fetch(__points, prim); + return kernel_data_fetch(points, prim); } else { /* center step is not stored in this array */ @@ -28,7 +28,7 @@ motion_point_for_step(KernelGlobals kg, int offset, int numkeys, int numsteps, i offset += step * numkeys; - return kernel_tex_fetch(__attributes_float4, offset + prim); + return kernel_data_fetch(attributes_float4, offset + prim); } } diff --git a/intern/cycles/kernel/geom/motion_triangle.h b/intern/cycles/kernel/geom/motion_triangle.h index a87eb11f4f4..06308071700 100644 --- a/intern/cycles/kernel/geom/motion_triangle.h +++ b/intern/cycles/kernel/geom/motion_triangle.h @@ -30,9 +30,9 @@ ccl_device_inline void motion_triangle_verts_for_step(KernelGlobals kg, { if (step == numsteps) { /* center step: regular vertex location */ - verts[0] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0); - verts[1] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1); - verts[2] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2); + verts[0] = kernel_data_fetch(tri_verts, tri_vindex.w + 0); + verts[1] = kernel_data_fetch(tri_verts, tri_vindex.w + 1); + verts[2] = kernel_data_fetch(tri_verts, tri_vindex.w + 2); } else { /* center step not store in this array */ @@ -41,9 +41,9 @@ ccl_device_inline void motion_triangle_verts_for_step(KernelGlobals kg, offset += step * numverts; - verts[0] = kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x); - verts[1] = kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y); - verts[2] = kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z); + verts[0] = kernel_data_fetch(attributes_float3, offset + tri_vindex.x); + verts[1] = kernel_data_fetch(attributes_float3, offset + tri_vindex.y); + verts[2] = kernel_data_fetch(attributes_float3, offset + tri_vindex.z); } } @@ -57,9 +57,9 @@ ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals kg, { if (step == numsteps) { /* center step: regular vertex location */ - normals[0] = kernel_tex_fetch(__tri_vnormal, tri_vindex.x); - normals[1] = kernel_tex_fetch(__tri_vnormal, tri_vindex.y); - normals[2] = kernel_tex_fetch(__tri_vnormal, tri_vindex.z); + normals[0] = kernel_data_fetch(tri_vnormal, tri_vindex.x); + normals[1] = kernel_data_fetch(tri_vnormal, tri_vindex.y); + normals[2] = kernel_data_fetch(tri_vnormal, tri_vindex.z); } else { /* center step is not stored in this array */ @@ -68,9 +68,9 @@ ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals kg, offset += step * numverts; - normals[0] = kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x); - normals[1] = kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y); - normals[2] = kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z); + normals[0] = kernel_data_fetch(attributes_float3, offset + tri_vindex.x); + normals[1] = kernel_data_fetch(attributes_float3, offset + tri_vindex.y); + normals[2] = kernel_data_fetch(attributes_float3, offset + tri_vindex.z); } } @@ -92,7 +92,7 @@ ccl_device_inline void motion_triangle_vertices( /* fetch vertex coordinates */ float3 next_verts[3]; - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); + uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts); @@ -121,7 +121,7 @@ ccl_device_inline void motion_triangle_vertices_and_normals( /* Fetch vertex coordinates. */ float3 next_verts[3]; - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); + uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts); @@ -167,7 +167,7 @@ ccl_device_inline float3 motion_triangle_smooth_normal( /* fetch normals */ float3 normals[3], next_normals[3]; - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); + uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals); motion_triangle_normals_for_step( diff --git a/intern/cycles/kernel/geom/motion_triangle_intersect.h b/intern/cycles/kernel/geom/motion_triangle_intersect.h index fb951fa151d..6eea5096567 100644 --- a/intern/cycles/kernel/geom/motion_triangle_intersect.h +++ b/intern/cycles/kernel/geom/motion_triangle_intersect.h @@ -63,7 +63,7 @@ ccl_device_inline bool motion_triangle_intersect(KernelGlobals kg, /* Visibility flag test. we do it here under the assumption * that most triangles are culled by node flags. */ - if (kernel_tex_fetch(__prim_visibility, prim_addr) & visibility) + if (kernel_data_fetch(prim_visibility, prim_addr) & visibility) #endif { isect->t = t; diff --git a/intern/cycles/kernel/geom/motion_triangle_shader.h b/intern/cycles/kernel/geom/motion_triangle_shader.h index 2b2bb858816..236e737b785 100644 --- a/intern/cycles/kernel/geom/motion_triangle_shader.h +++ b/intern/cycles/kernel/geom/motion_triangle_shader.h @@ -31,7 +31,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg, bool is_local) { /* Get shader. */ - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); + sd->shader = kernel_data_fetch(tri_shader, sd->prim); /* Get motion info. */ /* TODO(sergey): This logic is really similar to motion_triangle_vertices(), * can we de-duplicate something here? @@ -47,7 +47,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg, kernel_assert(offset != ATTR_STD_NOT_FOUND); /* Fetch vertex coordinates. */ float3 verts[3], next_verts[3]; - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + uint4 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts); motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts); /* Interpolate between steps. */ diff --git a/intern/cycles/kernel/geom/object.h b/intern/cycles/kernel/geom/object.h index 3faab7fa905..b15f6b5dda5 100644 --- a/intern/cycles/kernel/geom/object.h +++ b/intern/cycles/kernel/geom/object.h @@ -31,10 +31,10 @@ ccl_device_inline Transform object_fetch_transform(KernelGlobals kg, enum ObjectTransform type) { if (type == OBJECT_INVERSE_TRANSFORM) { - return kernel_tex_fetch(__objects, object).itfm; + return kernel_data_fetch(objects, object).itfm; } else { - return kernel_tex_fetch(__objects, object).tfm; + return kernel_data_fetch(objects, object).tfm; } } @@ -43,10 +43,10 @@ ccl_device_inline Transform object_fetch_transform(KernelGlobals kg, ccl_device_inline Transform lamp_fetch_transform(KernelGlobals kg, int lamp, bool inverse) { if (inverse) { - return kernel_tex_fetch(__lights, lamp).itfm; + return kernel_data_fetch(lights, lamp).itfm; } else { - return kernel_tex_fetch(__lights, lamp).tfm; + return kernel_data_fetch(lights, lamp).tfm; } } @@ -57,7 +57,7 @@ ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals kg, enum ObjectVectorTransform type) { int offset = object * OBJECT_MOTION_PASS_SIZE + (int)type; - return kernel_tex_fetch(__object_motion_pass, offset); + return kernel_data_fetch(object_motion_pass, offset); } /* Motion blurred object transformations */ @@ -65,9 +65,9 @@ ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals kg, #ifdef __OBJECT_MOTION__ ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals kg, int object, float time) { - const uint motion_offset = kernel_tex_fetch(__objects, object).motion_offset; - ccl_global const DecomposedTransform *motion = &kernel_tex_fetch(__object_motion, motion_offset); - const uint num_steps = kernel_tex_fetch(__objects, object).numsteps * 2 + 1; + const uint motion_offset = kernel_data_fetch(objects, object).motion_offset; + ccl_global const DecomposedTransform *motion = &kernel_data_fetch(object_motion, motion_offset); + const uint num_steps = kernel_data_fetch(objects, object).numsteps * 2 + 1; Transform tfm; transform_motion_array_interpolate(&tfm, motion, num_steps, time); @@ -80,7 +80,7 @@ ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals kg, float time, ccl_private Transform *itfm) { - int object_flag = kernel_tex_fetch(__object_flag, object); + int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_MOTION) { /* if we do motion blur */ Transform tfm = object_fetch_transform_motion(kg, object, time); @@ -259,7 +259,7 @@ ccl_device_inline float3 object_color(KernelGlobals kg, int object) if (object == OBJECT_NONE) return make_float3(0.0f, 0.0f, 0.0f); - ccl_global const KernelObject *kobject = &kernel_tex_fetch(__objects, object); + ccl_global const KernelObject *kobject = &kernel_data_fetch(objects, object); return make_float3(kobject->color[0], kobject->color[1], kobject->color[2]); } @@ -270,7 +270,7 @@ ccl_device_inline float object_alpha(KernelGlobals kg, int object) if (object == OBJECT_NONE) return 0.0f; - return kernel_tex_fetch(__objects, object).alpha; + return kernel_data_fetch(objects, object).alpha; } /* Pass ID number of object */ @@ -280,7 +280,7 @@ ccl_device_inline float object_pass_id(KernelGlobals kg, int object) if (object == OBJECT_NONE) return 0.0f; - return kernel_tex_fetch(__objects, object).pass_id; + return kernel_data_fetch(objects, object).pass_id; } /* Lightgroup of lamp */ @@ -290,7 +290,7 @@ ccl_device_inline int lamp_lightgroup(KernelGlobals kg, int lamp) if (lamp == LAMP_NONE) return LIGHTGROUP_NONE; - return kernel_tex_fetch(__lights, lamp).lightgroup; + return kernel_data_fetch(lights, lamp).lightgroup; } /* Lightgroup of object */ @@ -300,7 +300,7 @@ ccl_device_inline int object_lightgroup(KernelGlobals kg, int object) if (object == OBJECT_NONE) return LIGHTGROUP_NONE; - return kernel_tex_fetch(__objects, object).lightgroup; + return kernel_data_fetch(objects, object).lightgroup; } /* Per lamp random number for shader variation */ @@ -310,7 +310,7 @@ ccl_device_inline float lamp_random_number(KernelGlobals kg, int lamp) if (lamp == LAMP_NONE) return 0.0f; - return kernel_tex_fetch(__lights, lamp).random; + return kernel_data_fetch(lights, lamp).random; } /* Per object random number for shader variation */ @@ -320,7 +320,7 @@ ccl_device_inline float object_random_number(KernelGlobals kg, int object) if (object == OBJECT_NONE) return 0.0f; - return kernel_tex_fetch(__objects, object).random_number; + return kernel_data_fetch(objects, object).random_number; } /* Particle ID from which this object was generated */ @@ -330,7 +330,7 @@ ccl_device_inline int object_particle_id(KernelGlobals kg, int object) if (object == OBJECT_NONE) return 0; - return kernel_tex_fetch(__objects, object).particle_index; + return kernel_data_fetch(objects, object).particle_index; } /* Generated texture coordinate on surface from where object was instanced */ @@ -340,7 +340,7 @@ ccl_device_inline float3 object_dupli_generated(KernelGlobals kg, int object) if (object == OBJECT_NONE) return make_float3(0.0f, 0.0f, 0.0f); - ccl_global const KernelObject *kobject = &kernel_tex_fetch(__objects, object); + ccl_global const KernelObject *kobject = &kernel_data_fetch(objects, object); return make_float3( kobject->dupli_generated[0], kobject->dupli_generated[1], kobject->dupli_generated[2]); } @@ -352,7 +352,7 @@ ccl_device_inline float3 object_dupli_uv(KernelGlobals kg, int object) if (object == OBJECT_NONE) return make_float3(0.0f, 0.0f, 0.0f); - ccl_global const KernelObject *kobject = &kernel_tex_fetch(__objects, object); + ccl_global const KernelObject *kobject = &kernel_data_fetch(objects, object); return make_float3(kobject->dupli_uv[0], kobject->dupli_uv[1], 0.0f); } @@ -365,13 +365,13 @@ ccl_device_inline void object_motion_info(KernelGlobals kg, ccl_private int *numkeys) { if (numkeys) { - *numkeys = kernel_tex_fetch(__objects, object).numkeys; + *numkeys = kernel_data_fetch(objects, object).numkeys; } if (numsteps) - *numsteps = kernel_tex_fetch(__objects, object).numsteps; + *numsteps = kernel_data_fetch(objects, object).numsteps; if (numverts) - *numverts = kernel_tex_fetch(__objects, object).numverts; + *numverts = kernel_data_fetch(objects, object).numverts; } /* Offset to an objects patch map */ @@ -381,7 +381,7 @@ ccl_device_inline uint object_patch_map_offset(KernelGlobals kg, int object) if (object == OBJECT_NONE) return 0; - return kernel_tex_fetch(__objects, object).patch_map_offset; + return kernel_data_fetch(objects, object).patch_map_offset; } /* Volume step size */ @@ -392,7 +392,7 @@ ccl_device_inline float object_volume_density(KernelGlobals kg, int object) return 1.0f; } - return kernel_tex_fetch(__objects, object).volume_density; + return kernel_data_fetch(objects, object).volume_density; } ccl_device_inline float object_volume_step_size(KernelGlobals kg, int object) @@ -401,14 +401,14 @@ ccl_device_inline float object_volume_step_size(KernelGlobals kg, int object) return kernel_data.background.volume_step_size; } - return kernel_tex_fetch(__object_volume_step, object); + return kernel_data_fetch(object_volume_step, object); } /* Pass ID for shader */ ccl_device int shader_pass_id(KernelGlobals kg, ccl_private const ShaderData *sd) { - return kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).pass_id; + return kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).pass_id; } /* Cryptomatte ID */ @@ -418,7 +418,7 @@ ccl_device_inline float object_cryptomatte_id(KernelGlobals kg, int object) if (object == OBJECT_NONE) return 0.0f; - return kernel_tex_fetch(__objects, object).cryptomatte_object; + return kernel_data_fetch(objects, object).cryptomatte_object; } ccl_device_inline float object_cryptomatte_asset_id(KernelGlobals kg, int object) @@ -426,49 +426,49 @@ ccl_device_inline float object_cryptomatte_asset_id(KernelGlobals kg, int object if (object == OBJECT_NONE) return 0; - return kernel_tex_fetch(__objects, object).cryptomatte_asset; + return kernel_data_fetch(objects, object).cryptomatte_asset; } /* Particle data from which object was instanced */ ccl_device_inline uint particle_index(KernelGlobals kg, int particle) { - return kernel_tex_fetch(__particles, particle).index; + return kernel_data_fetch(particles, particle).index; } ccl_device float particle_age(KernelGlobals kg, int particle) { - return kernel_tex_fetch(__particles, particle).age; + return kernel_data_fetch(particles, particle).age; } ccl_device float particle_lifetime(KernelGlobals kg, int particle) { - return kernel_tex_fetch(__particles, particle).lifetime; + return kernel_data_fetch(particles, particle).lifetime; } ccl_device float particle_size(KernelGlobals kg, int particle) { - return kernel_tex_fetch(__particles, particle).size; + return kernel_data_fetch(particles, particle).size; } ccl_device float4 particle_rotation(KernelGlobals kg, int particle) { - return kernel_tex_fetch(__particles, particle).rotation; + return kernel_data_fetch(particles, particle).rotation; } ccl_device float3 particle_location(KernelGlobals kg, int particle) { - return float4_to_float3(kernel_tex_fetch(__particles, particle).location); + return float4_to_float3(kernel_data_fetch(particles, particle).location); } ccl_device float3 particle_velocity(KernelGlobals kg, int particle) { - return float4_to_float3(kernel_tex_fetch(__particles, particle).velocity); + return float4_to_float3(kernel_data_fetch(particles, particle).velocity); } ccl_device float3 particle_angular_velocity(KernelGlobals kg, int particle) { - return float4_to_float3(kernel_tex_fetch(__particles, particle).angular_velocity); + return float4_to_float3(kernel_data_fetch(particles, particle).angular_velocity); } /* Object intersection in BVH */ diff --git a/intern/cycles/kernel/geom/patch.h b/intern/cycles/kernel/geom/patch.h index 1c63a00e30d..ec98ddf51f0 100644 --- a/intern/cycles/kernel/geom/patch.h +++ b/intern/cycles/kernel/geom/patch.h @@ -62,7 +62,7 @@ patch_map_find_patch(KernelGlobals kg, int object, int patch, float u, float v) int quadrant = patch_map_resolve_quadrant(median, &u, &v); kernel_assert(quadrant >= 0); - uint child = kernel_tex_fetch(__patches, node + quadrant); + uint child = kernel_data_fetch(patches, node + quadrant); /* is the quadrant a hole? */ if (!(child & PATCH_MAP_NODE_IS_SET)) { @@ -73,9 +73,9 @@ patch_map_find_patch(KernelGlobals kg, int object, int patch, float u, float v) uint index = child & PATCH_MAP_NODE_INDEX_MASK; if (child & PATCH_MAP_NODE_IS_LEAF) { - handle.array_index = kernel_tex_fetch(__patches, index + 0); - handle.patch_index = kernel_tex_fetch(__patches, index + 1); - handle.vert_index = kernel_tex_fetch(__patches, index + 2); + handle.array_index = kernel_data_fetch(patches, index + 0); + handle.patch_index = kernel_data_fetch(patches, index + 1); + handle.vert_index = kernel_data_fetch(patches, index + 2); return handle; } @@ -189,11 +189,11 @@ ccl_device_inline int patch_eval_indices(KernelGlobals kg, int channel, int indices[PATCH_MAX_CONTROL_VERTS]) { - int index_base = kernel_tex_fetch(__patches, handle->array_index + 2) + handle->vert_index; + int index_base = kernel_data_fetch(patches, handle->array_index + 2) + handle->vert_index; /* XXX: regular patches only */ for (int i = 0; i < 16; i++) { - indices[i] = kernel_tex_fetch(__patches, index_base + i); + indices[i] = kernel_data_fetch(patches, index_base + i); } return 16; @@ -209,7 +209,7 @@ ccl_device_inline void patch_eval_basis(KernelGlobals kg, float weights_du[PATCH_MAX_CONTROL_VERTS], float weights_dv[PATCH_MAX_CONTROL_VERTS]) { - uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); /* read patch param */ + uint patch_bits = kernel_data_fetch(patches, handle->patch_index + 1); /* read patch param */ float d_scale = 1 << patch_eval_depth(patch_bits); bool non_quad_root = (patch_bits >> 4) & 0x1; @@ -287,7 +287,7 @@ ccl_device float patch_eval_float(KernelGlobals kg, *dv = 0.0f; for (int i = 0; i < num_control; i++) { - float v = kernel_tex_fetch(__attributes_float, offset + indices[i]); + float v = kernel_data_fetch(attributes_float, offset + indices[i]); val += v * weights[i]; if (du) @@ -324,7 +324,7 @@ ccl_device float2 patch_eval_float2(KernelGlobals kg, *dv = make_float2(0.0f, 0.0f); for (int i = 0; i < num_control; i++) { - float2 v = kernel_tex_fetch(__attributes_float2, offset + indices[i]); + float2 v = kernel_data_fetch(attributes_float2, offset + indices[i]); val += v * weights[i]; if (du) @@ -361,7 +361,7 @@ ccl_device float3 patch_eval_float3(KernelGlobals kg, *dv = make_float3(0.0f, 0.0f, 0.0f); for (int i = 0; i < num_control; i++) { - float3 v = kernel_tex_fetch(__attributes_float3, offset + indices[i]); + float3 v = kernel_data_fetch(attributes_float3, offset + indices[i]); val += v * weights[i]; if (du) @@ -398,7 +398,7 @@ ccl_device float4 patch_eval_float4(KernelGlobals kg, *dv = zero_float4(); for (int i = 0; i < num_control; i++) { - float4 v = kernel_tex_fetch(__attributes_float4, offset + indices[i]); + float4 v = kernel_data_fetch(attributes_float4, offset + indices[i]); val += v * weights[i]; if (du) @@ -436,7 +436,7 @@ ccl_device float4 patch_eval_uchar4(KernelGlobals kg, for (int i = 0; i < num_control; i++) { float4 v = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, offset + indices[i]))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, offset + indices[i]))); val += v * weights[i]; if (du) diff --git a/intern/cycles/kernel/geom/point.h b/intern/cycles/kernel/geom/point.h index ee7eca9e0c6..726d829c329 100644 --- a/intern/cycles/kernel/geom/point.h +++ b/intern/cycles/kernel/geom/point.h @@ -26,7 +26,7 @@ ccl_device float point_attribute_float(KernelGlobals kg, # endif if (desc.element == ATTR_ELEMENT_VERTEX) { - return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim); + return kernel_data_fetch(attributes_float, desc.offset + sd->prim); } else { return 0.0f; @@ -47,7 +47,7 @@ ccl_device float2 point_attribute_float2(KernelGlobals kg, # endif if (desc.element == ATTR_ELEMENT_VERTEX) { - return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim); + return kernel_data_fetch(attributes_float2, desc.offset + sd->prim); } else { return make_float2(0.0f, 0.0f); @@ -68,7 +68,7 @@ ccl_device float3 point_attribute_float3(KernelGlobals kg, # endif if (desc.element == ATTR_ELEMENT_VERTEX) { - return kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim); + return kernel_data_fetch(attributes_float3, desc.offset + sd->prim); } else { return make_float3(0.0f, 0.0f, 0.0f); @@ -89,7 +89,7 @@ ccl_device float4 point_attribute_float4(KernelGlobals kg, # endif if (desc.element == ATTR_ELEMENT_VERTEX) { - return kernel_tex_fetch(__attributes_float4, desc.offset + sd->prim); + return kernel_data_fetch(attributes_float4, desc.offset + sd->prim); } else { return zero_float4(); @@ -104,7 +104,7 @@ ccl_device float3 point_position(KernelGlobals kg, ccl_private const ShaderData /* World space center. */ float3 P = (sd->type & PRIMITIVE_MOTION) ? float4_to_float3(motion_point(kg, sd->object, sd->prim, sd->time)) : - float4_to_float3(kernel_tex_fetch(__points, sd->prim)); + float4_to_float3(kernel_data_fetch(points, sd->prim)); if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { object_position_transform(kg, sd, &P); @@ -122,7 +122,7 @@ ccl_device float point_radius(KernelGlobals kg, ccl_private const ShaderData *sd { if (sd->type & PRIMITIVE_POINT) { /* World space radius. */ - const float r = kernel_tex_fetch(__points, sd->prim).w; + const float r = kernel_data_fetch(points, sd->prim).w; if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) { return r; @@ -155,7 +155,7 @@ ccl_device float point_random(KernelGlobals kg, ccl_private const ShaderData *sd ccl_device float3 point_motion_center_location(KernelGlobals kg, ccl_private const ShaderData *sd) { - return float4_to_float3(kernel_tex_fetch(__points, sd->prim)); + return float4_to_float3(kernel_data_fetch(points, sd->prim)); } #endif /* __POINTCLOUD__ */ diff --git a/intern/cycles/kernel/geom/point_intersect.h b/intern/cycles/kernel/geom/point_intersect.h index c7ae72bb488..dfd9d9a015b 100644 --- a/intern/cycles/kernel/geom/point_intersect.h +++ b/intern/cycles/kernel/geom/point_intersect.h @@ -63,7 +63,7 @@ ccl_device_forceinline bool point_intersect(KernelGlobals kg, const int type) { const float4 point = (type & PRIMITIVE_MOTION) ? motion_point(kg, object, prim, time) : - kernel_tex_fetch(__points, prim); + kernel_data_fetch(points, prim); if (!point_intersect_test(point, P, dir, tmax, &isect->t)) { return false; @@ -82,7 +82,7 @@ ccl_device_inline void point_shader_setup(KernelGlobals kg, ccl_private const Intersection *isect, ccl_private const Ray *ray) { - sd->shader = kernel_tex_fetch(__points_shader, isect->prim); + sd->shader = kernel_data_fetch(points_shader, isect->prim); sd->P = ray->P + ray->D * isect->t; /* Texture coordinates, zero for now. */ @@ -94,7 +94,7 @@ ccl_device_inline void point_shader_setup(KernelGlobals kg, /* Compute point center for normal. */ float3 center = float4_to_float3((isect->type & PRIMITIVE_MOTION) ? motion_point(kg, sd->object, sd->prim, sd->time) : - kernel_tex_fetch(__points, sd->prim)); + kernel_data_fetch(points, sd->prim)); if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { object_position_transform_auto(kg, sd, ¢er); } diff --git a/intern/cycles/kernel/geom/shader_data.h b/intern/cycles/kernel/geom/shader_data.h index 7a439da427a..e5dbeac5e66 100644 --- a/intern/cycles/kernel/geom/shader_data.h +++ b/intern/cycles/kernel/geom/shader_data.h @@ -40,7 +40,7 @@ ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, sd->ray_length = isect->t; sd->type = isect->type; sd->object = isect->object; - sd->object_flag = kernel_tex_fetch(__object_flag, sd->object); + sd->object_flag = kernel_data_fetch(object_flag, sd->object); sd->prim = isect->prim; sd->lamp = LAMP_NONE; sd->flag = 0; @@ -73,7 +73,7 @@ ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, if (sd->type == PRIMITIVE_TRIANGLE) { /* static triangle */ float3 Ng = triangle_normal(kg, sd); - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); + sd->shader = kernel_data_fetch(tri_shader, sd->prim); /* vectors */ sd->P = triangle_point_from_uv(kg, sd, isect->object, isect->prim, isect->u, isect->v); @@ -106,7 +106,7 @@ ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, } } - sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; + sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags; /* backfacing test */ bool backfacing = (dot(sd->Ng, sd->I) < 0.0f); @@ -169,10 +169,10 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals kg, sd->time = time; sd->ray_length = t; - sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; + sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags; sd->object_flag = 0; if (sd->object != OBJECT_NONE) { - sd->object_flag |= kernel_tex_fetch(__object_flag, sd->object); + sd->object_flag |= kernel_data_fetch(object_flag, sd->object); #ifdef __OBJECT_MOTION__ shader_setup_object_transforms(kg, sd, time); @@ -264,21 +264,20 @@ ccl_device void shader_setup_from_displace(KernelGlobals kg, /* force smooth shading for displacement */ shader |= SHADER_SMOOTH_NORMAL; - shader_setup_from_sample( - kg, - sd, - P, - Ng, - I, - shader, - object, - prim, - u, - v, - 0.0f, - 0.5f, - !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED), - LAMP_NONE); + shader_setup_from_sample(kg, + sd, + P, + Ng, + I, + shader, + object, + prim, + u, + v, + 0.0f, + 0.5f, + !(kernel_data_fetch(object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED), + LAMP_NONE); } /* ShaderData setup for point on curve. */ @@ -300,18 +299,18 @@ ccl_device void shader_setup_from_curve(KernelGlobals kg, sd->ray_length = 0.0f; /* Shader */ - sd->shader = kernel_tex_fetch(__curves, prim).shader_id; - sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; + sd->shader = kernel_data_fetch(curves, prim).shader_id; + sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags; /* Object */ sd->object = object; - sd->object_flag = kernel_tex_fetch(__object_flag, sd->object); + sd->object_flag = kernel_data_fetch(object_flag, sd->object); #ifdef __OBJECT_MOTION__ shader_setup_object_transforms(kg, sd, sd->time); #endif /* Get control points. */ - KernelCurve kcurve = kernel_tex_fetch(__curves, prim); + KernelCurve kcurve = kernel_data_fetch(curves, prim); int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type); int k1 = k0 + 1; @@ -320,10 +319,10 @@ ccl_device void shader_setup_from_curve(KernelGlobals kg, float4 P_curve[4]; - P_curve[0] = kernel_tex_fetch(__curve_keys, ka); - P_curve[1] = kernel_tex_fetch(__curve_keys, k0); - P_curve[2] = kernel_tex_fetch(__curve_keys, k1); - P_curve[3] = kernel_tex_fetch(__curve_keys, kb); + P_curve[0] = kernel_data_fetch(curve_keys, ka); + P_curve[1] = kernel_data_fetch(curve_keys, k0); + P_curve[2] = kernel_data_fetch(curve_keys, k1); + P_curve[3] = kernel_data_fetch(curve_keys, kb); /* Interpolate position and tangent. */ sd->P = float4_to_float3(catmull_rom_basis_derivative(P_curve, sd->u)); @@ -373,7 +372,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals kg, sd->Ng = -ray_D; sd->I = -ray_D; sd->shader = kernel_data.background.surface_shader; - sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; + sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags; sd->object_flag = 0; sd->time = ray_time; sd->ray_length = 0.0f; diff --git a/intern/cycles/kernel/geom/subd_triangle.h b/intern/cycles/kernel/geom/subd_triangle.h index 24e1e454b8c..8b73b342e16 100644 --- a/intern/cycles/kernel/geom/subd_triangle.h +++ b/intern/cycles/kernel/geom/subd_triangle.h @@ -13,11 +13,11 @@ ccl_device_inline void subd_triangle_patch_uv(KernelGlobals kg, ccl_private const ShaderData *sd, float2 uv[3]) { - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + uint4 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); - uv[0] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.x); - uv[1] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.y); - uv[2] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.z); + uv[0] = kernel_data_fetch(tri_patch_uv, tri_vindex.x); + uv[1] = kernel_data_fetch(tri_patch_uv, tri_vindex.y); + uv[2] = kernel_data_fetch(tri_patch_uv, tri_vindex.z); } /* Vertex indices of patch */ @@ -26,10 +26,10 @@ ccl_device_inline uint4 subd_triangle_patch_indices(KernelGlobals kg, int patch) { uint4 indices; - indices.x = kernel_tex_fetch(__patches, patch + 0); - indices.y = kernel_tex_fetch(__patches, patch + 1); - indices.z = kernel_tex_fetch(__patches, patch + 2); - indices.w = kernel_tex_fetch(__patches, patch + 3); + indices.x = kernel_data_fetch(patches, patch + 0); + indices.y = kernel_data_fetch(patches, patch + 1); + indices.z = kernel_data_fetch(patches, patch + 2); + indices.w = kernel_data_fetch(patches, patch + 3); return indices; } @@ -38,14 +38,14 @@ ccl_device_inline uint4 subd_triangle_patch_indices(KernelGlobals kg, int patch) ccl_device_inline uint subd_triangle_patch_face(KernelGlobals kg, int patch) { - return kernel_tex_fetch(__patches, patch + 4); + return kernel_data_fetch(patches, patch + 4); } /* Number of corners on originating face */ ccl_device_inline uint subd_triangle_patch_num_corners(KernelGlobals kg, int patch) { - return kernel_tex_fetch(__patches, patch + 5) & 0xffff; + return kernel_data_fetch(patches, patch + 5) & 0xffff; } /* Indices of the four corners that are used by the patch */ @@ -54,10 +54,10 @@ ccl_device_inline void subd_triangle_patch_corners(KernelGlobals kg, int patch, { uint4 data; - data.x = kernel_tex_fetch(__patches, patch + 4); - data.y = kernel_tex_fetch(__patches, patch + 5); - data.z = kernel_tex_fetch(__patches, patch + 6); - data.w = kernel_tex_fetch(__patches, patch + 7); + data.x = kernel_data_fetch(patches, patch + 4); + data.y = kernel_data_fetch(patches, patch + 5); + data.z = kernel_data_fetch(patches, patch + 6); + data.w = kernel_data_fetch(patches, patch + 7); int num_corners = data.y & 0xffff; @@ -141,7 +141,7 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals kg, if (dy) *dy = 0.0f; - return kernel_tex_fetch(__attributes_float, desc.offset + subd_triangle_patch_face(kg, patch)); + return kernel_data_fetch(attributes_float, desc.offset + subd_triangle_patch_face(kg, patch)); } else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { float2 uv[3]; @@ -149,10 +149,10 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals kg, uint4 v = subd_triangle_patch_indices(kg, patch); - float f0 = kernel_tex_fetch(__attributes_float, desc.offset + v.x); - float f1 = kernel_tex_fetch(__attributes_float, desc.offset + v.y); - float f2 = kernel_tex_fetch(__attributes_float, desc.offset + v.z); - float f3 = kernel_tex_fetch(__attributes_float, desc.offset + v.w); + float f0 = kernel_data_fetch(attributes_float, desc.offset + v.x); + float f1 = kernel_data_fetch(attributes_float, desc.offset + v.y); + float f2 = kernel_data_fetch(attributes_float, desc.offset + v.z); + float f3 = kernel_data_fetch(attributes_float, desc.offset + v.w); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -179,10 +179,10 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals kg, int corners[4]; subd_triangle_patch_corners(kg, patch, corners); - float f0 = kernel_tex_fetch(__attributes_float, corners[0] + desc.offset); - float f1 = kernel_tex_fetch(__attributes_float, corners[1] + desc.offset); - float f2 = kernel_tex_fetch(__attributes_float, corners[2] + desc.offset); - float f3 = kernel_tex_fetch(__attributes_float, corners[3] + desc.offset); + float f0 = kernel_data_fetch(attributes_float, corners[0] + desc.offset); + float f1 = kernel_data_fetch(attributes_float, corners[1] + desc.offset); + float f2 = kernel_data_fetch(attributes_float, corners[2] + desc.offset); + float f3 = kernel_data_fetch(attributes_float, corners[3] + desc.offset); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -208,7 +208,7 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals kg, if (dy) *dy = 0.0f; - return kernel_tex_fetch(__attributes_float, desc.offset); + return kernel_data_fetch(attributes_float, desc.offset); } else { if (dx) @@ -281,8 +281,7 @@ ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals kg, if (dy) *dy = make_float2(0.0f, 0.0f); - return kernel_tex_fetch(__attributes_float2, - desc.offset + subd_triangle_patch_face(kg, patch)); + return kernel_data_fetch(attributes_float2, desc.offset + subd_triangle_patch_face(kg, patch)); } else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { float2 uv[3]; @@ -290,10 +289,10 @@ ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals kg, uint4 v = subd_triangle_patch_indices(kg, patch); - float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + v.x); - float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + v.y); - float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + v.z); - float2 f3 = kernel_tex_fetch(__attributes_float2, desc.offset + v.w); + float2 f0 = kernel_data_fetch(attributes_float2, desc.offset + v.x); + float2 f1 = kernel_data_fetch(attributes_float2, desc.offset + v.y); + float2 f2 = kernel_data_fetch(attributes_float2, desc.offset + v.z); + float2 f3 = kernel_data_fetch(attributes_float2, desc.offset + v.w); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -322,10 +321,10 @@ ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals kg, float2 f0, f1, f2, f3; - f0 = kernel_tex_fetch(__attributes_float2, corners[0] + desc.offset); - f1 = kernel_tex_fetch(__attributes_float2, corners[1] + desc.offset); - f2 = kernel_tex_fetch(__attributes_float2, corners[2] + desc.offset); - f3 = kernel_tex_fetch(__attributes_float2, corners[3] + desc.offset); + f0 = kernel_data_fetch(attributes_float2, corners[0] + desc.offset); + f1 = kernel_data_fetch(attributes_float2, corners[1] + desc.offset); + f2 = kernel_data_fetch(attributes_float2, corners[2] + desc.offset); + f3 = kernel_data_fetch(attributes_float2, corners[3] + desc.offset); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -351,7 +350,7 @@ ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals kg, if (dy) *dy = make_float2(0.0f, 0.0f); - return kernel_tex_fetch(__attributes_float2, desc.offset); + return kernel_data_fetch(attributes_float2, desc.offset); } else { if (dx) @@ -423,8 +422,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals kg, if (dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - return kernel_tex_fetch(__attributes_float3, - desc.offset + subd_triangle_patch_face(kg, patch)); + return kernel_data_fetch(attributes_float3, desc.offset + subd_triangle_patch_face(kg, patch)); } else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { float2 uv[3]; @@ -432,10 +430,10 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals kg, uint4 v = subd_triangle_patch_indices(kg, patch); - float3 f0 = kernel_tex_fetch(__attributes_float3, desc.offset + v.x); - float3 f1 = kernel_tex_fetch(__attributes_float3, desc.offset + v.y); - float3 f2 = kernel_tex_fetch(__attributes_float3, desc.offset + v.z); - float3 f3 = kernel_tex_fetch(__attributes_float3, desc.offset + v.w); + float3 f0 = kernel_data_fetch(attributes_float3, desc.offset + v.x); + float3 f1 = kernel_data_fetch(attributes_float3, desc.offset + v.y); + float3 f2 = kernel_data_fetch(attributes_float3, desc.offset + v.z); + float3 f3 = kernel_data_fetch(attributes_float3, desc.offset + v.w); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -464,10 +462,10 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals kg, float3 f0, f1, f2, f3; - f0 = kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset); - f1 = kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset); - f2 = kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset); - f3 = kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset); + f0 = kernel_data_fetch(attributes_float3, corners[0] + desc.offset); + f1 = kernel_data_fetch(attributes_float3, corners[1] + desc.offset); + f2 = kernel_data_fetch(attributes_float3, corners[2] + desc.offset); + f3 = kernel_data_fetch(attributes_float3, corners[3] + desc.offset); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -493,7 +491,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals kg, if (dy) *dy = make_float3(0.0f, 0.0f, 0.0f); - return kernel_tex_fetch(__attributes_float3, desc.offset); + return kernel_data_fetch(attributes_float3, desc.offset); } else { if (dx) @@ -570,8 +568,7 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg, if (dy) *dy = zero_float4(); - return kernel_tex_fetch(__attributes_float4, - desc.offset + subd_triangle_patch_face(kg, patch)); + return kernel_data_fetch(attributes_float4, desc.offset + subd_triangle_patch_face(kg, patch)); } else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { float2 uv[3]; @@ -579,10 +576,10 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg, uint4 v = subd_triangle_patch_indices(kg, patch); - float4 f0 = kernel_tex_fetch(__attributes_float4, desc.offset + v.x); - float4 f1 = kernel_tex_fetch(__attributes_float4, desc.offset + v.y); - float4 f2 = kernel_tex_fetch(__attributes_float4, desc.offset + v.z); - float4 f3 = kernel_tex_fetch(__attributes_float4, desc.offset + v.w); + float4 f0 = kernel_data_fetch(attributes_float4, desc.offset + v.x); + float4 f1 = kernel_data_fetch(attributes_float4, desc.offset + v.y); + float4 f2 = kernel_data_fetch(attributes_float4, desc.offset + v.z); + float4 f3 = kernel_data_fetch(attributes_float4, desc.offset + v.w); if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -613,19 +610,19 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg, if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { f0 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, corners[0] + desc.offset))); f1 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, corners[1] + desc.offset))); f2 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, corners[2] + desc.offset))); f3 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, corners[3] + desc.offset))); } else { - f0 = kernel_tex_fetch(__attributes_float4, corners[0] + desc.offset); - f1 = kernel_tex_fetch(__attributes_float4, corners[1] + desc.offset); - f2 = kernel_tex_fetch(__attributes_float4, corners[2] + desc.offset); - f3 = kernel_tex_fetch(__attributes_float4, corners[3] + desc.offset); + f0 = kernel_data_fetch(attributes_float4, corners[0] + desc.offset); + f1 = kernel_data_fetch(attributes_float4, corners[1] + desc.offset); + f2 = kernel_data_fetch(attributes_float4, corners[2] + desc.offset); + f3 = kernel_data_fetch(attributes_float4, corners[3] + desc.offset); } if (subd_triangle_patch_num_corners(kg, patch) != 4) { @@ -652,7 +649,7 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg, if (dy) *dy = zero_float4(); - return kernel_tex_fetch(__attributes_float4, desc.offset); + return kernel_data_fetch(attributes_float4, desc.offset); } else { if (dx) diff --git a/intern/cycles/kernel/geom/triangle.h b/intern/cycles/kernel/geom/triangle.h index 8ac7e67ff05..788bfaca7cf 100644 --- a/intern/cycles/kernel/geom/triangle.h +++ b/intern/cycles/kernel/geom/triangle.h @@ -15,10 +15,10 @@ CCL_NAMESPACE_BEGIN ccl_device_inline float3 triangle_normal(KernelGlobals kg, ccl_private ShaderData *sd) { /* load triangle vertices */ - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - const float3 v0 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0); - const float3 v1 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1); - const float3 v2 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); + const float3 v0 = kernel_data_fetch(tri_verts, tri_vindex.w + 0); + const float3 v1 = kernel_data_fetch(tri_verts, tri_vindex.w + 1); + const float3 v2 = kernel_data_fetch(tri_verts, tri_vindex.w + 2); /* return normal */ if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) { @@ -40,15 +40,15 @@ ccl_device_inline void triangle_point_normal(KernelGlobals kg, ccl_private int *shader) { /* load triangle vertices */ - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); - float3 v0 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0); - float3 v1 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1); - float3 v2 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); + float3 v0 = kernel_data_fetch(tri_verts, tri_vindex.w + 0); + float3 v1 = kernel_data_fetch(tri_verts, tri_vindex.w + 1); + float3 v2 = kernel_data_fetch(tri_verts, tri_vindex.w + 2); /* compute point */ float t = 1.0f - u - v; *P = (u * v0 + v * v1 + t * v2); /* get object flags */ - int object_flag = kernel_tex_fetch(__object_flag, object); + int object_flag = kernel_data_fetch(object_flag, object); /* compute normal */ if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) { *Ng = normalize(cross(v2 - v0, v1 - v0)); @@ -57,17 +57,17 @@ ccl_device_inline void triangle_point_normal(KernelGlobals kg, *Ng = normalize(cross(v1 - v0, v2 - v0)); } /* shader`*/ - *shader = kernel_tex_fetch(__tri_shader, prim); + *shader = kernel_data_fetch(tri_shader, prim); } /* Triangle vertex locations */ ccl_device_inline void triangle_vertices(KernelGlobals kg, int prim, float3 P[3]) { - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); - P[0] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0); - P[1] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1); - P[2] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); + P[0] = kernel_data_fetch(tri_verts, tri_vindex.w + 0); + P[1] = kernel_data_fetch(tri_verts, tri_vindex.w + 1); + P[2] = kernel_data_fetch(tri_verts, tri_vindex.w + 2); } /* Triangle vertex locations and vertex normals */ @@ -77,13 +77,13 @@ ccl_device_inline void triangle_vertices_and_normals(KernelGlobals kg, float3 P[3], float3 N[3]) { - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); - P[0] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0); - P[1] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1); - P[2] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2); - N[0] = kernel_tex_fetch(__tri_vnormal, tri_vindex.x); - N[1] = kernel_tex_fetch(__tri_vnormal, tri_vindex.y); - N[2] = kernel_tex_fetch(__tri_vnormal, tri_vindex.z); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); + P[0] = kernel_data_fetch(tri_verts, tri_vindex.w + 0); + P[1] = kernel_data_fetch(tri_verts, tri_vindex.w + 1); + P[2] = kernel_data_fetch(tri_verts, tri_vindex.w + 2); + N[0] = kernel_data_fetch(tri_vnormal, tri_vindex.x); + N[1] = kernel_data_fetch(tri_vnormal, tri_vindex.y); + N[2] = kernel_data_fetch(tri_vnormal, tri_vindex.z); } /* Interpolate smooth vertex normal from vertices */ @@ -92,10 +92,10 @@ ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, float3 Ng, int prim, float u, float v) { /* load triangle vertices */ - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); - float3 n0 = kernel_tex_fetch(__tri_vnormal, tri_vindex.x); - float3 n1 = kernel_tex_fetch(__tri_vnormal, tri_vindex.y); - float3 n2 = kernel_tex_fetch(__tri_vnormal, tri_vindex.z); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); + float3 n0 = kernel_data_fetch(tri_vnormal, tri_vindex.x); + float3 n1 = kernel_data_fetch(tri_vnormal, tri_vindex.y); + float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z); float3 N = safe_normalize((1.0f - u - v) * n2 + u * n0 + v * n1); @@ -106,10 +106,10 @@ ccl_device_inline float3 triangle_smooth_normal_unnormalized( KernelGlobals kg, ccl_private const ShaderData *sd, float3 Ng, int prim, float u, float v) { /* load triangle vertices */ - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); - float3 n0 = kernel_tex_fetch(__tri_vnormal, tri_vindex.x); - float3 n1 = kernel_tex_fetch(__tri_vnormal, tri_vindex.y); - float3 n2 = kernel_tex_fetch(__tri_vnormal, tri_vindex.z); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); + float3 n0 = kernel_data_fetch(tri_vnormal, tri_vindex.x); + float3 n1 = kernel_data_fetch(tri_vnormal, tri_vindex.y); + float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z); /* ensure that the normals are in object space */ if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) { @@ -131,10 +131,10 @@ ccl_device_inline void triangle_dPdudv(KernelGlobals kg, ccl_private float3 *dPdv) { /* fetch triangle vertex coordinates */ - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); - const float3 p0 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0); - const float3 p1 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1); - const float3 p2 = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, prim); + const float3 p0 = kernel_data_fetch(tri_verts, tri_vindex.w + 0); + const float3 p1 = kernel_data_fetch(tri_verts, tri_vindex.w + 1); + const float3 p2 = kernel_data_fetch(tri_verts, tri_vindex.w + 2); /* compute derivatives of P w.r.t. uv */ *dPdu = (p0 - p2); @@ -153,16 +153,16 @@ ccl_device float triangle_attribute_float(KernelGlobals kg, float f0, f1, f2; if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x); - f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y); - f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); + f0 = kernel_data_fetch(attributes_float, desc.offset + tri_vindex.x); + f1 = kernel_data_fetch(attributes_float, desc.offset + tri_vindex.y); + f2 = kernel_data_fetch(attributes_float, desc.offset + tri_vindex.z); } else { const int tri = desc.offset + sd->prim * 3; - f0 = kernel_tex_fetch(__attributes_float, tri + 0); - f1 = kernel_tex_fetch(__attributes_float, tri + 1); - f2 = kernel_tex_fetch(__attributes_float, tri + 2); + f0 = kernel_data_fetch(attributes_float, tri + 0); + f1 = kernel_data_fetch(attributes_float, tri + 1); + f2 = kernel_data_fetch(attributes_float, tri + 2); } #ifdef __RAY_DIFFERENTIALS__ @@ -185,7 +185,7 @@ ccl_device float triangle_attribute_float(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float, offset); + return kernel_data_fetch(attributes_float, offset); } else { return 0.0f; @@ -203,16 +203,16 @@ ccl_device float2 triangle_attribute_float2(KernelGlobals kg, float2 f0, f1, f2; if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x); - f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y); - f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); + f0 = kernel_data_fetch(attributes_float2, desc.offset + tri_vindex.x); + f1 = kernel_data_fetch(attributes_float2, desc.offset + tri_vindex.y); + f2 = kernel_data_fetch(attributes_float2, desc.offset + tri_vindex.z); } else { const int tri = desc.offset + sd->prim * 3; - f0 = kernel_tex_fetch(__attributes_float2, tri + 0); - f1 = kernel_tex_fetch(__attributes_float2, tri + 1); - f2 = kernel_tex_fetch(__attributes_float2, tri + 2); + f0 = kernel_data_fetch(attributes_float2, tri + 0); + f1 = kernel_data_fetch(attributes_float2, tri + 1); + f2 = kernel_data_fetch(attributes_float2, tri + 2); } #ifdef __RAY_DIFFERENTIALS__ @@ -235,7 +235,7 @@ ccl_device float2 triangle_attribute_float2(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float2, offset); + return kernel_data_fetch(attributes_float2, offset); } else { return make_float2(0.0f, 0.0f); @@ -253,16 +253,16 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals kg, float3 f0, f1, f2; if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - f0 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x); - f1 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y); - f2 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); + f0 = kernel_data_fetch(attributes_float3, desc.offset + tri_vindex.x); + f1 = kernel_data_fetch(attributes_float3, desc.offset + tri_vindex.y); + f2 = kernel_data_fetch(attributes_float3, desc.offset + tri_vindex.z); } else { const int tri = desc.offset + sd->prim * 3; - f0 = kernel_tex_fetch(__attributes_float3, tri + 0); - f1 = kernel_tex_fetch(__attributes_float3, tri + 1); - f2 = kernel_tex_fetch(__attributes_float3, tri + 2); + f0 = kernel_data_fetch(attributes_float3, tri + 0); + f1 = kernel_data_fetch(attributes_float3, tri + 1); + f2 = kernel_data_fetch(attributes_float3, tri + 2); } #ifdef __RAY_DIFFERENTIALS__ @@ -285,7 +285,7 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float3, offset); + return kernel_data_fetch(attributes_float3, offset); } else { return make_float3(0.0f, 0.0f, 0.0f); @@ -304,25 +304,25 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals kg, float4 f0, f1, f2; if (desc.element & (ATTR_ELEMENT_VERTEX | ATTR_ELEMENT_VERTEX_MOTION)) { - const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - f0 = kernel_tex_fetch(__attributes_float4, desc.offset + tri_vindex.x); - f1 = kernel_tex_fetch(__attributes_float4, desc.offset + tri_vindex.y); - f2 = kernel_tex_fetch(__attributes_float4, desc.offset + tri_vindex.z); + const uint4 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim); + f0 = kernel_data_fetch(attributes_float4, desc.offset + tri_vindex.x); + f1 = kernel_data_fetch(attributes_float4, desc.offset + tri_vindex.y); + f2 = kernel_data_fetch(attributes_float4, desc.offset + tri_vindex.z); } else { const int tri = desc.offset + sd->prim * 3; if (desc.element == ATTR_ELEMENT_CORNER) { - f0 = kernel_tex_fetch(__attributes_float4, tri + 0); - f1 = kernel_tex_fetch(__attributes_float4, tri + 1); - f2 = kernel_tex_fetch(__attributes_float4, tri + 2); + f0 = kernel_data_fetch(attributes_float4, tri + 0); + f1 = kernel_data_fetch(attributes_float4, tri + 1); + f2 = kernel_data_fetch(attributes_float4, tri + 2); } else { f0 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, tri + 0))); f1 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, tri + 1))); f2 = color_srgb_to_linear_v4( - color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2))); + color_uchar4_to_float4(kernel_data_fetch(attributes_uchar4, tri + 2))); } } @@ -346,7 +346,7 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals kg, if (desc.element & (ATTR_ELEMENT_FACE | ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { const int offset = (desc.element == ATTR_ELEMENT_FACE) ? desc.offset + sd->prim : desc.offset; - return kernel_tex_fetch(__attributes_float4, offset); + return kernel_data_fetch(attributes_float4, offset); } else { return zero_float4(); diff --git a/intern/cycles/kernel/geom/triangle_intersect.h b/intern/cycles/kernel/geom/triangle_intersect.h index fe531e6868a..0c76de9ccc7 100644 --- a/intern/cycles/kernel/geom/triangle_intersect.h +++ b/intern/cycles/kernel/geom/triangle_intersect.h @@ -23,17 +23,17 @@ ccl_device_inline bool triangle_intersect(KernelGlobals kg, int prim, int prim_addr) { - const uint tri_vindex = kernel_tex_fetch(__tri_vindex, prim).w; - const float3 tri_a = kernel_tex_fetch(__tri_verts, tri_vindex + 0), - tri_b = kernel_tex_fetch(__tri_verts, tri_vindex + 1), - tri_c = kernel_tex_fetch(__tri_verts, tri_vindex + 2); + const uint tri_vindex = kernel_data_fetch(tri_vindex, prim).w; + const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex + 0), + tri_b = kernel_data_fetch(tri_verts, tri_vindex + 1), + tri_c = kernel_data_fetch(tri_verts, tri_vindex + 2); float t, u, v; if (ray_triangle_intersect(P, dir, tmax, tri_a, tri_b, tri_c, &u, &v, &t)) { #ifdef __VISIBILITY_FLAG__ /* Visibility flag test. we do it here under the assumption * that most triangles are culled by node flags. */ - if (kernel_tex_fetch(__prim_visibility, prim_addr) & visibility) + if (kernel_data_fetch(prim_visibility, prim_addr) & visibility) #endif { isect->object = object; @@ -66,10 +66,10 @@ ccl_device_inline bool triangle_intersect_local(KernelGlobals kg, ccl_private uint *lcg_state, int max_hits) { - const uint tri_vindex = kernel_tex_fetch(__tri_vindex, prim).w; - const float3 tri_a = kernel_tex_fetch(__tri_verts, tri_vindex + 0), - tri_b = kernel_tex_fetch(__tri_verts, tri_vindex + 1), - tri_c = kernel_tex_fetch(__tri_verts, tri_vindex + 2); + const uint tri_vindex = kernel_data_fetch(tri_vindex, prim).w; + const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex + 0), + tri_b = kernel_data_fetch(tri_verts, tri_vindex + 1), + tri_c = kernel_data_fetch(tri_verts, tri_vindex + 2); float t, u, v; if (!ray_triangle_intersect(P, dir, tmax, tri_a, tri_b, tri_c, &u, &v, &t)) { return false; @@ -139,10 +139,10 @@ ccl_device_inline float3 triangle_point_from_uv(KernelGlobals kg, const float u, const float v) { - const uint tri_vindex = kernel_tex_fetch(__tri_vindex, isect_prim).w; - const packed_float3 tri_a = kernel_tex_fetch(__tri_verts, tri_vindex + 0), - tri_b = kernel_tex_fetch(__tri_verts, tri_vindex + 1), - tri_c = kernel_tex_fetch(__tri_verts, tri_vindex + 2); + const uint tri_vindex = kernel_data_fetch(tri_vindex, isect_prim).w; + const packed_float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex + 0), + tri_b = kernel_data_fetch(tri_verts, tri_vindex + 1), + tri_c = kernel_data_fetch(tri_verts, tri_vindex + 2); float w = 1.0f - u - v; float3 P = u * tri_a + v * tri_b + w * tri_c; diff --git a/intern/cycles/kernel/geom/volume.h b/intern/cycles/kernel/geom/volume.h index 22715dee5bf..3510a905def 100644 --- a/intern/cycles/kernel/geom/volume.h +++ b/intern/cycles/kernel/geom/volume.h @@ -62,7 +62,7 @@ ccl_device float4 volume_attribute_float4(KernelGlobals kg, const AttributeDescriptor desc) { if (desc.element & (ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) { - return kernel_tex_fetch(__attributes_float4, desc.offset); + return kernel_data_fetch(attributes_float4, desc.offset); } else if (desc.element == ATTR_ELEMENT_VOXEL) { /* todo: optimize this so we don't have to transform both here and in diff --git a/intern/cycles/kernel/integrator/init_from_bake.h b/intern/cycles/kernel/integrator/init_from_bake.h index 0db4241b6e3..7d53bf479bf 100644 --- a/intern/cycles/kernel/integrator/init_from_bake.h +++ b/intern/cycles/kernel/integrator/init_from_bake.h @@ -160,7 +160,7 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg, int shader; triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader); - const int object_flag = kernel_tex_fetch(__object_flag, object); + const int object_flag = kernel_data_fetch(object_flag, object); if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); P = transform_point_auto(&tfm, P); @@ -193,7 +193,7 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg, } const int shader_index = shader & SHADER_MASK; - const int shader_flags = kernel_tex_fetch(__shaders, shader_index).flags; + const int shader_flags = kernel_data_fetch(shaders, shader_index).flags; /* Fast path for position and normal passes not affected by shaders. */ if (kernel_data.film.pass_position != PASS_UNUSED) { diff --git a/intern/cycles/kernel/integrator/intersect_closest.h b/intern/cycles/kernel/integrator/intersect_closest.h index 2dfac44b414..621aa05f46b 100644 --- a/intern/cycles/kernel/integrator/intersect_closest.h +++ b/intern/cycles/kernel/integrator/intersect_closest.h @@ -122,7 +122,7 @@ ccl_device_forceinline void integrator_split_shadow_catcher( /* Continue with shading shadow catcher surface. */ const int shader = intersection_get_shader(kg, isect); - const int flags = kernel_tex_fetch(__shaders, shader).flags; + const int flags = kernel_data_fetch(shaders, shader).flags; const bool use_caustics = kernel_data.integrator.use_caustics && (object_flags & SD_OBJECT_CAUSTICS); const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); @@ -149,7 +149,7 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catche integrator_state_read_isect(kg, state, &isect); const int shader = intersection_get_shader(kg, &isect); - const int flags = kernel_tex_fetch(__shaders, shader).flags; + const int flags = kernel_data_fetch(shaders, shader).flags; const int object_flags = intersection_get_object_flags(kg, &isect); const bool use_caustics = kernel_data.integrator.use_caustics && (object_flags & SD_OBJECT_CAUSTICS); @@ -203,7 +203,7 @@ ccl_device_forceinline void integrator_intersect_next_kernel( if (!integrator_state_volume_stack_is_empty(kg, state)) { const bool hit_surface = hit && !(isect->type & PRIMITIVE_LAMP); const int shader = (hit_surface) ? intersection_get_shader(kg, isect) : SHADER_NONE; - const int flags = (hit_surface) ? kernel_tex_fetch(__shaders, shader).flags : 0; + const int flags = (hit_surface) ? kernel_data_fetch(shaders, shader).flags : 0; if (!integrator_intersect_terminate(kg, state, flags)) { INTEGRATOR_PATH_NEXT(current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME); @@ -223,7 +223,7 @@ ccl_device_forceinline void integrator_intersect_next_kernel( else { /* Hit a surface, continue with surface kernel unless terminated. */ const int shader = intersection_get_shader(kg, isect); - const int flags = kernel_tex_fetch(__shaders, shader).flags; + const int flags = kernel_data_fetch(shaders, shader).flags; if (!integrator_intersect_terminate(kg, state, flags)) { const int object_flags = intersection_get_object_flags(kg, isect); @@ -279,7 +279,7 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_volume( else { /* Hit a surface, continue with surface kernel unless terminated. */ const int shader = intersection_get_shader(kg, isect); - const int flags = kernel_tex_fetch(__shaders, shader).flags; + const int flags = kernel_data_fetch(shaders, shader).flags; const int object_flags = intersection_get_object_flags(kg, isect); const bool use_caustics = kernel_data.integrator.use_caustics && (object_flags & SD_OBJECT_CAUSTICS); @@ -332,7 +332,7 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg, ray.t = kernel_data.integrator.ao_bounces_distance; if (last_isect_object != OBJECT_NONE) { - const float object_ao_distance = kernel_tex_fetch(__objects, last_isect_object).ao_distance; + const float object_ao_distance = kernel_data_fetch(objects, last_isect_object).ao_distance; if (object_ao_distance != 0.0f) { ray.t = object_ao_distance; } @@ -366,7 +366,7 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg, bool from_caustic_caster = false; bool from_caustic_receiver = false; if (!(path_flag & PATH_RAY_CAMERA) && last_isect_object != OBJECT_NONE) { - const int object_flags = kernel_tex_fetch(__object_flag, last_isect_object); + const int object_flags = kernel_data_fetch(object_flag, last_isect_object); from_caustic_receiver = (object_flags & SD_OBJECT_CAUSTICS_RECEIVER); from_caustic_caster = (object_flags & SD_OBJECT_CAUSTICS_CASTER); } diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h index ad83f82d091..75d30a0aeff 100644 --- a/intern/cycles/kernel/integrator/mnee.h +++ b/intern/cycles/kernel/integrator/mnee.h @@ -115,7 +115,7 @@ ccl_device_forceinline void mnee_update_light_sample(KernelGlobals kg, { /* correct light sample position/direction and pdf * NOTE: preserve pdf in area measure */ - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, ls->lamp); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ls->lamp); if (ls->type == LIGHT_POINT || ls->type == LIGHT_SPOT) { ls->D = normalize_len(ls->P - P, &ls->t); @@ -154,12 +154,12 @@ ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg, ccl_private const Intersection *isect, ccl_private ShaderData *sd_vtx) { - sd_vtx->object = (isect->object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, isect->prim) : + sd_vtx->object = (isect->object == OBJECT_NONE) ? kernel_data_fetch(prim_object, isect->prim) : isect->object; sd_vtx->type = isect->type; sd_vtx->flag = 0; - sd_vtx->object_flag = kernel_tex_fetch(__object_flag, sd_vtx->object); + sd_vtx->object_flag = kernel_data_fetch(object_flag, sd_vtx->object); /* Matrices and time. */ shader_setup_object_transforms(kg, sd_vtx, ray->time); @@ -171,7 +171,7 @@ ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg, sd_vtx->u = isect->u; sd_vtx->v = isect->v; - sd_vtx->shader = kernel_tex_fetch(__tri_shader, sd_vtx->prim); + sd_vtx->shader = kernel_data_fetch(tri_shader, sd_vtx->prim); float3 verts[3]; float3 normals[3]; @@ -509,7 +509,7 @@ ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg, break; int hit_object = (projection_isect.object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, projection_isect.prim) : + kernel_data_fetch(prim_object, projection_isect.prim) : projection_isect.object; if (hit_object == mv.object) { @@ -870,7 +870,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, probe_ray.D = normalize_len(v.p - probe_ray.P, &probe_ray.t); if (scene_intersect(kg, &probe_ray, PATH_RAY_TRANSMIT, &probe_isect)) { int hit_object = (probe_isect.object == OBJECT_NONE) ? - kernel_tex_fetch(__prim_object, probe_isect.prim) : + kernel_data_fetch(prim_object, probe_isect.prim) : probe_isect.object; /* Test whether the ray hit the appropriate object at its intended location. */ if (hit_object != v.object || fabsf(probe_ray.t - probe_isect.t) > MNEE_MIN_DISTANCE) diff --git a/intern/cycles/kernel/integrator/shade_background.h b/intern/cycles/kernel/integrator/shade_background.h index 72ecf67e8a0..4791a963ae6 100644 --- a/intern/cycles/kernel/integrator/shade_background.h +++ b/intern/cycles/kernel/integrator/shade_background.h @@ -107,7 +107,7 @@ ccl_device_inline void integrate_background(KernelGlobals kg, for (int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) { /* This path should have been resolved with mnee, it will * generate a firefly for small lights since it is improbable. */ - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp); if (klight->type == LIGHT_BACKGROUND && klight->use_caustics) { eval_background = false; break; @@ -160,7 +160,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg, if (INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) { /* This path should have been resolved with mnee, it will * generate a firefly for small lights since it is improbable. */ - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp); if (klight->use_caustics) return; } diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index ce1398859b7..e0a7f998a3f 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -141,7 +141,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, { if (ls.lamp != LAMP_NONE) { /* Is this a caustic light? */ - const bool use_caustics = kernel_tex_fetch(__lights, ls.lamp).use_caustics; + const bool use_caustics = kernel_data_fetch(lights, ls.lamp).use_caustics; if (use_caustics) { /* Are we on a caustic caster? */ if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER)) diff --git a/intern/cycles/kernel/integrator/shader_eval.h b/intern/cycles/kernel/integrator/shader_eval.h index 4da92929366..ed4d973e864 100644 --- a/intern/cycles/kernel/integrator/shader_eval.h +++ b/intern/cycles/kernel/integrator/shader_eval.h @@ -528,12 +528,12 @@ ccl_device bool shader_constant_emission_eval(KernelGlobals kg, ccl_private float3 *eval) { int shader_index = shader & SHADER_MASK; - int shader_flag = kernel_tex_fetch(__shaders, shader_index).flags; + int shader_flag = kernel_data_fetch(shaders, shader_index).flags; if (shader_flag & SD_HAS_CONSTANT_EMISSION) { - *eval = make_float3(kernel_tex_fetch(__shaders, shader_index).constant_emission[0], - kernel_tex_fetch(__shaders, shader_index).constant_emission[1], - kernel_tex_fetch(__shaders, shader_index).constant_emission[2]); + *eval = make_float3(kernel_data_fetch(shaders, shader_index).constant_emission[0], + kernel_data_fetch(shaders, shader_index).constant_emission[1], + kernel_data_fetch(shaders, shader_index).constant_emission[2]); return true; } @@ -821,11 +821,11 @@ ccl_device_inline void shader_eval_volume(KernelGlobals kg, sd->shader = entry.shader; sd->flag &= ~SD_SHADER_FLAGS; - sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; + sd->flag |= kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags; sd->object_flag &= ~SD_OBJECT_FLAGS; if (sd->object != OBJECT_NONE) { - sd->object_flag |= kernel_tex_fetch(__object_flag, sd->object); + sd->object_flag |= kernel_data_fetch(object_flag, sd->object); # ifdef __OBJECT_MOTION__ /* todo: this is inefficient for motion blur, we should be @@ -837,7 +837,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals kg, kernel_assert(v_desc.offset != ATTR_STD_NOT_FOUND); const float3 P = sd->P; - const float velocity_scale = kernel_tex_fetch(__objects, sd->object).velocity_scale; + const float velocity_scale = kernel_data_fetch(objects, sd->object).velocity_scale; const float time_offset = kernel_data.cam.motion_position == MOTION_POSITION_CENTER ? 0.5f : 0.0f; @@ -946,7 +946,7 @@ ccl_device void shader_eval_displacement(KernelGlobals kg, ccl_device float shader_cryptomatte_id(KernelGlobals kg, int shader) { - return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).cryptomatte_id; + return kernel_data_fetch(shaders, (shader & SHADER_MASK)).cryptomatte_id; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index b449f807290..1e6fcf4aff0 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -147,7 +147,7 @@ ccl_device_inline bool subsurface_scatter(KernelGlobals kg, IntegratorState stat /* Update volume stack if needed. */ if (kernel_data.integrator.use_volumes) { const int object = ss_isect.hits[0].object; - const int object_flag = kernel_tex_fetch(__object_flag, object); + const int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_INTERSECTS_VOLUME) { float3 P = INTEGRATOR_STATE(state, ray, P); @@ -170,7 +170,7 @@ ccl_device_inline bool subsurface_scatter(KernelGlobals kg, IntegratorState stat INTEGRATOR_STATE_WRITE(state, path, rng_offset) += PRNG_BOUNCE_NUM; const int shader = intersection_get_shader(kg, &ss_isect.hits[0]); - const int shader_flags = kernel_tex_fetch(__shaders, shader).flags; + const int shader_flags = kernel_data_fetch(shaders, shader).flags; const int object_flags = intersection_get_object_flags(kg, &ss_isect.hits[0]); const bool use_caustics = kernel_data.integrator.use_caustics && (object_flags & SD_OBJECT_CAUSTICS); diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h index 34330671748..ae857c50493 100644 --- a/intern/cycles/kernel/integrator/subsurface_disk.h +++ b/intern/cycles/kernel/integrator/subsurface_disk.h @@ -113,7 +113,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, for (int hit = 0; hit < num_eval_hits; hit++) { /* Get geometric normal. */ const int object = ss_isect.hits[hit].object; - const int object_flag = kernel_tex_fetch(__object_flag, object); + const int object_flag = kernel_data_fetch(object_flag, object); float3 hit_Ng = ss_isect.Ng[hit]; if (path_flag & PATH_RAY_SUBSURFACE_BACKFACING) { hit_Ng = -hit_Ng; diff --git a/intern/cycles/kernel/integrator/volume_stack.h b/intern/cycles/kernel/integrator/volume_stack.h index 5256349a0cc..97a0f0f386c 100644 --- a/intern/cycles/kernel/integrator/volume_stack.h +++ b/intern/cycles/kernel/integrator/volume_stack.h @@ -133,7 +133,7 @@ ccl_device float volume_stack_step_size(KernelGlobals kg, StackReadOp stack_read break; } - int shader_flag = kernel_tex_fetch(__shaders, (entry.shader & SHADER_MASK)).flags; + int shader_flag = kernel_data_fetch(shaders, (entry.shader & SHADER_MASK)).flags; bool heterogeneous = false; @@ -146,7 +146,7 @@ ccl_device float volume_stack_step_size(KernelGlobals kg, StackReadOp stack_read * heterogeneous volume objects may be using the same shader. */ int object = entry.object; if (object != OBJECT_NONE) { - int object_flag = kernel_tex_fetch(__object_flag, object); + int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_HAS_VOLUME_ATTRIBUTES) { heterogeneous = true; } @@ -180,7 +180,7 @@ ccl_device VolumeSampleMethod volume_stack_sample_method(KernelGlobals kg, Integ break; } - int shader_flag = kernel_tex_fetch(__shaders, (entry.shader & SHADER_MASK)).flags; + int shader_flag = kernel_data_fetch(shaders, (entry.shader & SHADER_MASK)).flags; if (shader_flag & SD_VOLUME_MIS) { /* Multiple importance sampling. */ diff --git a/intern/cycles/kernel/light/background.h b/intern/cycles/kernel/light/background.h index 0cbf7fb76fe..2a97d43c9ce 100644 --- a/intern/cycles/kernel/light/background.h +++ b/intern/cycles/kernel/light/background.h @@ -31,7 +31,7 @@ ccl_device float3 background_map_sample(KernelGlobals kg, int step = count >> 1; int middle = first + step; - if (kernel_tex_fetch(__light_background_marginal_cdf, middle).y < randv) { + if (kernel_data_fetch(light_background_marginal_cdf, middle).y < randv) { first = middle + 1; count -= step + 1; } @@ -42,9 +42,9 @@ ccl_device float3 background_map_sample(KernelGlobals kg, int index_v = max(0, first - 1); kernel_assert(index_v >= 0 && index_v < res_y); - float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v); - float2 cdf_next_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v + 1); - float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y); + float2 cdf_v = kernel_data_fetch(light_background_marginal_cdf, index_v); + float2 cdf_next_v = kernel_data_fetch(light_background_marginal_cdf, index_v + 1); + float2 cdf_last_v = kernel_data_fetch(light_background_marginal_cdf, res_y); /* importance-sampled V direction */ float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv); @@ -57,7 +57,7 @@ ccl_device float3 background_map_sample(KernelGlobals kg, int step = count >> 1; int middle = first + step; - if (kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + middle).y < + if (kernel_data_fetch(light_background_conditional_cdf, index_v * cdf_width + middle).y < randu) { first = middle + 1; count -= step + 1; @@ -69,12 +69,12 @@ ccl_device float3 background_map_sample(KernelGlobals kg, int index_u = max(0, first - 1); kernel_assert(index_u >= 0 && index_u < res_x); - float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, - index_v * cdf_width + index_u); - float2 cdf_next_u = kernel_tex_fetch(__light_background_conditional_cdf, - index_v * cdf_width + index_u + 1); - float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, - index_v * cdf_width + res_x); + float2 cdf_u = kernel_data_fetch(light_background_conditional_cdf, + index_v * cdf_width + index_u); + float2 cdf_next_u = kernel_data_fetch(light_background_conditional_cdf, + index_v * cdf_width + index_u + 1); + float2 cdf_last_u = kernel_data_fetch(light_background_conditional_cdf, + index_v * cdf_width + res_x); /* importance-sampled U direction */ float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu); @@ -112,9 +112,9 @@ ccl_device float background_map_pdf(KernelGlobals kg, float3 direction) int index_v = clamp(float_to_int(uv.y * res_y), 0, res_y - 1); /* pdfs in V direction */ - float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, - index_v * cdf_width + res_x); - float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y); + float2 cdf_last_u = kernel_data_fetch(light_background_conditional_cdf, + index_v * cdf_width + res_x); + float2 cdf_last_v = kernel_data_fetch(light_background_marginal_cdf, res_y); float denom = (M_2PI_F * M_PI_F * sin_theta) * cdf_last_u.x * cdf_last_v.x; @@ -122,9 +122,9 @@ ccl_device float background_map_pdf(KernelGlobals kg, float3 direction) return 0.0f; /* pdfs in U direction */ - float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, - index_v * cdf_width + index_u); - float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v); + float2 cdf_u = kernel_data_fetch(light_background_conditional_cdf, + index_v * cdf_width + index_u); + float2 cdf_v = kernel_data_fetch(light_background_marginal_cdf, index_v); return (cdf_u.x * cdf_v.x) / denom; } @@ -133,7 +133,7 @@ ccl_device_inline bool background_portal_data_fetch_and_check_side( KernelGlobals kg, float3 P, int index, ccl_private float3 *lightpos, ccl_private float3 *dir) { int portal = kernel_data.background.portal_offset + index; - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, portal); *lightpos = make_float3(klight->co[0], klight->co[1], klight->co[2]); *dir = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]); @@ -166,7 +166,7 @@ ccl_device_inline float background_portal_pdf( num_possible++; int portal = kernel_data.background.portal_offset + p; - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, portal); float3 axisu = make_float3( klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); float3 axisv = make_float3( @@ -242,7 +242,7 @@ ccl_device float3 background_portal_sample(KernelGlobals kg, if (portal == 0) { /* p is the portal to be sampled. */ int portal = kernel_data.background.portal_offset + p; - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, portal); float3 axisu = make_float3( klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); float3 axisv = make_float3( diff --git a/intern/cycles/kernel/light/light.h b/intern/cycles/kernel/light/light.h index 1df1615ed99..1e7a333d013 100644 --- a/intern/cycles/kernel/light/light.h +++ b/intern/cycles/kernel/light/light.h @@ -38,7 +38,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg, const uint32_t path_flag, ccl_private LightSample *ls) { - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp); if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) { if (klight->shader_id & SHADER_EXCLUDE_SHADOW_CATCHER) { return false; @@ -237,7 +237,7 @@ ccl_device bool lights_intersect(KernelGlobals kg, const uint32_t path_flag) { for (int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) { - const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + const ccl_global KernelLight *klight = &kernel_data_fetch(lights, lamp); if (path_flag & PATH_RAY_CAMERA) { if (klight->shader_id & SHADER_EXCLUDE_CAMERA) { @@ -358,7 +358,7 @@ ccl_device bool light_sample_from_distant_ray(KernelGlobals kg, const int lamp, ccl_private LightSample *ccl_restrict ls) { - ccl_global const KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + ccl_global const KernelLight *klight = &kernel_data_fetch(lights, lamp); const int shader = klight->shader_id; const float radius = klight->distant.radius; const LightType type = (LightType)klight->type; @@ -433,7 +433,7 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg, ccl_private LightSample *ccl_restrict ls) { const int lamp = isect->prim; - ccl_global const KernelLight *klight = &kernel_tex_fetch(__lights, lamp); + ccl_global const KernelLight *klight = &kernel_data_fetch(lights, lamp); LightType type = (LightType)klight->type; ls->type = type; ls->shader = klight->shader_id; @@ -562,7 +562,7 @@ ccl_device_inline bool triangle_world_space_vertices( KernelGlobals kg, int object, int prim, float time, float3 V[3]) { bool has_motion = false; - const int object_flag = kernel_tex_fetch(__object_flag, object); + const int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) { motion_triangle_vertices(kg, object, prim, time, V); @@ -699,12 +699,12 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals kg, float area = 0.5f * Nl; /* flip normal if necessary */ - const int object_flag = kernel_tex_fetch(__object_flag, object); + const int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) { ls->Ng = -ls->Ng; } ls->eval_fac = 1.0f; - ls->shader = kernel_tex_fetch(__tri_shader, prim); + ls->shader = kernel_data_fetch(tri_shader, prim); ls->object = object; ls->prim = prim; ls->lamp = LAMP_NONE; @@ -845,7 +845,7 @@ ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *ra int half_len = len >> 1; int middle = first + half_len; - if (r < kernel_tex_fetch(__light_distribution, middle).totarea) { + if (r < kernel_data_fetch(light_distribution, middle).totarea) { len = half_len; } else { @@ -860,8 +860,8 @@ ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *ra /* Rescale to reuse random number. this helps the 2D samples within * each area light be stratified as well. */ - float distr_min = kernel_tex_fetch(__light_distribution, index).totarea; - float distr_max = kernel_tex_fetch(__light_distribution, index + 1).totarea; + float distr_min = kernel_data_fetch(light_distribution, index).totarea; + float distr_max = kernel_data_fetch(light_distribution, index + 1).totarea; *randu = (r - distr_min) / (distr_max - distr_min); return index; @@ -871,7 +871,7 @@ ccl_device int light_distribution_sample(KernelGlobals kg, ccl_private float *ra ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals kg, int index, int bounce) { - return (bounce > kernel_tex_fetch(__lights, index).max_bounces); + return (bounce > kernel_data_fetch(lights, index).max_bounces); } template<bool in_volume_segment> @@ -886,8 +886,8 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg, { /* Sample light index from distribution. */ const int index = light_distribution_sample(kg, &randu); - ccl_global const KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution, - index); + ccl_global const KernelLightDistribution *kdistribution = &kernel_data_fetch(light_distribution, + index); const int prim = kdistribution->prim; if (prim >= 0) { @@ -896,7 +896,7 @@ ccl_device_noinline bool light_distribution_sample(KernelGlobals kg, /* Exclude synthetic meshes from shadow catcher pass. */ if ((path_flag & PATH_RAY_SHADOW_CATCHER_PASS) && - !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) { + !(kernel_data_fetch(object_flag, object) & SD_OBJECT_SHADOW_CATCHER)) { return false; } diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h index 9bbbd5b0d10..ea7b9950268 100644 --- a/intern/cycles/kernel/light/sample.h +++ b/intern/cycles/kernel/light/sample.h @@ -81,7 +81,7 @@ light_sample_shader_eval(KernelGlobals kg, eval *= ls->eval_fac; if (ls->lamp != LAMP_NONE) { - ccl_global const KernelLight *klight = &kernel_tex_fetch(__lights, ls->lamp); + ccl_global const KernelLight *klight = &kernel_data_fetch(lights, ls->lamp); eval *= make_float3(klight->strength[0], klight->strength[1], klight->strength[2]); } @@ -187,7 +187,7 @@ ccl_device_inline float3 shadow_ray_offset(KernelGlobals kg, if ((sd->type & PRIMITIVE_TRIANGLE) && (sd->shader & SHADER_SMOOTH_NORMAL)) { const float offset_cutoff = - kernel_tex_fetch(__objects, sd->object).shadow_terminator_geometry_offset; + kernel_data_fetch(objects, sd->object).shadow_terminator_geometry_offset; /* Do ray offset (heavy stuff) only for close to be terminated triangles: * offset_cutoff = 0.1f means that 10-20% of rays will be affected. Also * make a smooth transition near the threshold. */ diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp index e2e10b5b83f..6e75ae54f33 100644 --- a/intern/cycles/kernel/osl/services.cpp +++ b/intern/cycles/kernel/osl/services.cpp @@ -132,7 +132,7 @@ OSLRenderServices::OSLRenderServices(OSL::TextureSystem *texture_system) OSLRenderServices::~OSLRenderServices() { if (texture_system) { - VLOG(2) << "OSL texture system stats:\n" << texture_system->getstats(); + VLOG_INFO << "OSL texture system stats:\n" << texture_system->getstats(); } } diff --git a/intern/cycles/kernel/sample/jitter.h b/intern/cycles/kernel/sample/jitter.h index b8da94248a4..b5cfa624406 100644 --- a/intern/cycles/kernel/sample/jitter.h +++ b/intern/cycles/kernel/sample/jitter.h @@ -97,7 +97,7 @@ ccl_device float pmj_sample_1D(KernelGlobals kg, uint sample, uint rng_hash, uin * the x part is used for even dims and the y for odd. */ int index = 2 * ((dim >> 1) * NUM_PMJ_SAMPLES + (s % NUM_PMJ_SAMPLES)) + (dim & 1); - float fx = kernel_tex_fetch(__sample_pattern_lut, index); + float fx = kernel_data_fetch(sample_pattern_lut, index); #ifndef _NO_CRANLEY_PATTERSON_ROTATION_ /* Use Cranley-Patterson rotation to displace the sample pattern. */ @@ -154,8 +154,8 @@ ccl_device void pmj_sample_2D(KernelGlobals kg, uint dim = d % NUM_PMJ_PATTERNS; int index = 2 * (dim * NUM_PMJ_SAMPLES + (s % NUM_PMJ_SAMPLES)); - float fx = kernel_tex_fetch(__sample_pattern_lut, index); - float fy = kernel_tex_fetch(__sample_pattern_lut, index + 1); + float fx = kernel_data_fetch(sample_pattern_lut, index); + float fy = kernel_data_fetch(sample_pattern_lut, index + 1); #ifndef _NO_CRANLEY_PATTERSON_ROTATION_ /* Use Cranley-Patterson rotation to displace the sample pattern. */ diff --git a/intern/cycles/kernel/sample/pattern.h b/intern/cycles/kernel/sample/pattern.h index 1e66f39ede2..89500d51872 100644 --- a/intern/cycles/kernel/sample/pattern.h +++ b/intern/cycles/kernel/sample/pattern.h @@ -32,7 +32,7 @@ ccl_device uint sobol_dimension(KernelGlobals kg, int index, int dimension) uint i = index + SOBOL_SKIP; for (int j = 0, x; (x = find_first_set(i)); i >>= x) { j += x; - result ^= __float_as_uint(kernel_tex_fetch(__sample_pattern_lut, 32 * dimension + j - 1)); + result ^= __float_as_uint(kernel_data_fetch(sample_pattern_lut, 32 * dimension + j - 1)); } return result; } diff --git a/intern/cycles/kernel/svm/bevel.h b/intern/cycles/kernel/svm/bevel.h index 5abffe1c771..f79bcae5cd2 100644 --- a/intern/cycles/kernel/svm/bevel.h +++ b/intern/cycles/kernel/svm/bevel.h @@ -222,7 +222,7 @@ ccl_device float3 svm_bevel( /* Get geometric normal. */ float3 hit_Ng = isect.Ng[hit]; int object = isect.hits[hit].object; - int object_flag = kernel_tex_fetch(__object_flag, object); + int object_flag = kernel_data_fetch(object_flag, object); if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) { hit_Ng = -hit_Ng; } @@ -230,7 +230,7 @@ ccl_device float3 svm_bevel( /* Compute smooth normal. */ float3 N = hit_Ng; int prim = isect.hits[hit].prim; - int shader = kernel_tex_fetch(__tri_shader, prim); + int shader = kernel_data_fetch(tri_shader, prim); if (shader & SHADER_SMOOTH_NORMAL) { float u = isect.hits[hit].u; diff --git a/intern/cycles/kernel/svm/ies.h b/intern/cycles/kernel/svm/ies.h index 201d88101cd..3648cb580d5 100644 --- a/intern/cycles/kernel/svm/ies.h +++ b/intern/cycles/kernel/svm/ies.h @@ -17,7 +17,7 @@ ccl_device_inline float interpolate_ies_vertical( * Therefore, the assumption is made that the light is going to be symmetrical, which means that * we can just take the corresponding value at the current horizontal coordinate. */ -#define IES_LOOKUP(v) kernel_tex_fetch(__ies, ofs + h * v_num + (v)) +#define IES_LOOKUP(v) kernel_data_fetch(ies, ofs + h * v_num + (v)) /* If v is zero, assume symmetry and read at v=1 instead of v=-1. */ float a = IES_LOOKUP((v == 0) ? 1 : v - 1); float b = IES_LOOKUP(v); @@ -31,16 +31,16 @@ ccl_device_inline float interpolate_ies_vertical( ccl_device_inline float kernel_ies_interp(KernelGlobals kg, int slot, float h_angle, float v_angle) { /* Find offset of the IES data in the table. */ - int ofs = __float_as_int(kernel_tex_fetch(__ies, slot)); + int ofs = __float_as_int(kernel_data_fetch(ies, slot)); if (ofs == -1) { return 100.0f; } - int h_num = __float_as_int(kernel_tex_fetch(__ies, ofs++)); - int v_num = __float_as_int(kernel_tex_fetch(__ies, ofs++)); + int h_num = __float_as_int(kernel_data_fetch(ies, ofs++)); + int v_num = __float_as_int(kernel_data_fetch(ies, ofs++)); -#define IES_LOOKUP_ANGLE_H(h) kernel_tex_fetch(__ies, ofs + (h)) -#define IES_LOOKUP_ANGLE_V(v) kernel_tex_fetch(__ies, ofs + h_num + (v)) +#define IES_LOOKUP_ANGLE_H(h) kernel_data_fetch(ies, ofs + (h)) +#define IES_LOOKUP_ANGLE_V(v) kernel_data_fetch(ies, ofs + h_num + (v)) /* Check whether the angle is within the bounds of the IES texture. */ if (v_angle >= IES_LOOKUP_ANGLE_V(v_num - 1)) { diff --git a/intern/cycles/kernel/svm/ramp.h b/intern/cycles/kernel/svm/ramp.h index 342b15da9ed..0df9268bd9c 100644 --- a/intern/cycles/kernel/svm/ramp.h +++ b/intern/cycles/kernel/svm/ramp.h @@ -9,7 +9,7 @@ CCL_NAMESPACE_BEGIN ccl_device_inline float fetch_float(KernelGlobals kg, int offset) { - uint4 node = kernel_tex_fetch(__svm_nodes, offset); + uint4 node = kernel_data_fetch(svm_nodes, offset); return __uint_as_float(node.x); } diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 5def943c87f..624ef810e85 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -95,14 +95,14 @@ ccl_device_inline bool stack_valid(uint a) ccl_device_inline uint4 read_node(KernelGlobals kg, ccl_private int *offset) { - uint4 node = kernel_tex_fetch(__svm_nodes, *offset); + uint4 node = kernel_data_fetch(svm_nodes, *offset); (*offset)++; return node; } ccl_device_inline float4 read_node_float(KernelGlobals kg, ccl_private int *offset) { - uint4 node = kernel_tex_fetch(__svm_nodes, *offset); + uint4 node = kernel_data_fetch(svm_nodes, *offset); float4 f = make_float4(__uint_as_float(node.x), __uint_as_float(node.y), __uint_as_float(node.z), @@ -113,7 +113,7 @@ ccl_device_inline float4 read_node_float(KernelGlobals kg, ccl_private int *offs ccl_device_inline float4 fetch_node_float(KernelGlobals kg, int offset) { - uint4 node = kernel_tex_fetch(__svm_nodes, offset); + uint4 node = kernel_data_fetch(svm_nodes, offset); return make_float4(__uint_as_float(node.x), __uint_as_float(node.y), __uint_as_float(node.z), diff --git a/intern/cycles/kernel/textures.h b/intern/cycles/kernel/textures.h deleted file mode 100644 index 7deb589a0a9..00000000000 --- a/intern/cycles/kernel/textures.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 - * Copyright 2011-2022 Blender Foundation */ - -#ifndef KERNEL_TEX -# define KERNEL_TEX(type, name) -#endif - -/* BVH2, not used for OptiX or Embree. */ -KERNEL_TEX(float4, __bvh_nodes) -KERNEL_TEX(float4, __bvh_leaf_nodes) -KERNEL_TEX(uint, __prim_type) -KERNEL_TEX(uint, __prim_visibility) -KERNEL_TEX(uint, __prim_index) -KERNEL_TEX(uint, __prim_object) -KERNEL_TEX(uint, __object_node) -KERNEL_TEX(float2, __prim_time) - -/* objects */ -KERNEL_TEX(KernelObject, __objects) -KERNEL_TEX(Transform, __object_motion_pass) -KERNEL_TEX(DecomposedTransform, __object_motion) -KERNEL_TEX(uint, __object_flag) -KERNEL_TEX(float, __object_volume_step) -KERNEL_TEX(uint, __object_prim_offset) - -/* cameras */ -KERNEL_TEX(DecomposedTransform, __camera_motion) - -/* triangles */ -KERNEL_TEX(uint, __tri_shader) -KERNEL_TEX(packed_float3, __tri_vnormal) -KERNEL_TEX(uint4, __tri_vindex) -KERNEL_TEX(uint, __tri_patch) -KERNEL_TEX(float2, __tri_patch_uv) -KERNEL_TEX(packed_float3, __tri_verts) - -/* curves */ -KERNEL_TEX(KernelCurve, __curves) -KERNEL_TEX(float4, __curve_keys) -KERNEL_TEX(KernelCurveSegment, __curve_segments) - -/* patches */ -KERNEL_TEX(uint, __patches) - -/* pointclouds */ -KERNEL_TEX(float4, __points) -KERNEL_TEX(uint, __points_shader) - -/* attributes */ -KERNEL_TEX(uint4, __attributes_map) -KERNEL_TEX(float, __attributes_float) -KERNEL_TEX(float2, __attributes_float2) -KERNEL_TEX(packed_float3, __attributes_float3) -KERNEL_TEX(float4, __attributes_float4) -KERNEL_TEX(uchar4, __attributes_uchar4) - -/* lights */ -KERNEL_TEX(KernelLightDistribution, __light_distribution) -KERNEL_TEX(KernelLight, __lights) -KERNEL_TEX(float2, __light_background_marginal_cdf) -KERNEL_TEX(float2, __light_background_conditional_cdf) - -/* particles */ -KERNEL_TEX(KernelParticle, __particles) - -/* shaders */ -KERNEL_TEX(uint4, __svm_nodes) -KERNEL_TEX(KernelShader, __shaders) - -/* lookup tables */ -KERNEL_TEX(float, __lookup_table) - -/* sobol */ -KERNEL_TEX(float, __sample_pattern_lut) - -/* image textures */ -KERNEL_TEX(TextureInfo, __texture_info) - -/* ies lights */ -KERNEL_TEX(float, __ies) - -#undef KERNEL_TEX diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index b1ca379bab8..ad022716207 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -670,6 +670,16 @@ typedef struct AttributeDescriptor { int offset; } AttributeDescriptor; +/* For looking up attributes on objects and geometry. */ +typedef struct AttributeMap { + uint id; /* Global unique identifier. */ + uint element; /* AttributeElement. */ + int offset; /* Offset into __attributes global arrays. */ + uint8_t type; /* NodeAttributeType. */ + uint8_t flags; /* AttributeFlag. */ + uint8_t pad[2]; +} AttributeMap; + /* Closure data */ #ifndef __MAX_CLOSURE__ diff --git a/intern/cycles/kernel/util/lookup_table.h b/intern/cycles/kernel/util/lookup_table.h index e19e2ce5bd1..4db4dadab0e 100644 --- a/intern/cycles/kernel/util/lookup_table.h +++ b/intern/cycles/kernel/util/lookup_table.h @@ -15,11 +15,11 @@ ccl_device float lookup_table_read(KernelGlobals kg, float x, int offset, int si int nindex = min(index + 1, size - 1); float t = x - index; - float data0 = kernel_tex_fetch(__lookup_table, index + offset); + float data0 = kernel_data_fetch(lookup_table, index + offset); if (t == 0.0f) return data0; - float data1 = kernel_tex_fetch(__lookup_table, nindex + offset); + float data1 = kernel_data_fetch(lookup_table, nindex + offset); return (1.0f - t) * data0 + t * data1; } diff --git a/intern/cycles/scene/alembic.cpp b/intern/cycles/scene/alembic.cpp index c1e2d306fcc..e6f39bf8625 100644 --- a/intern/cycles/scene/alembic.cpp +++ b/intern/cycles/scene/alembic.cpp @@ -1514,7 +1514,7 @@ void AlembicProcedural::build_caches(Progress &progress) } } - VLOG(1) << "AlembicProcedural memory usage : " << string_human_readable_size(memory_used); + VLOG_WORK << "AlembicProcedural memory usage : " << string_human_readable_size(memory_used); } CCL_NAMESPACE_END diff --git a/intern/cycles/scene/camera.cpp b/intern/cycles/scene/camera.cpp index 710f1c5ee90..eec269ab542 100644 --- a/intern/cycles/scene/camera.cpp +++ b/intern/cycles/scene/camera.cpp @@ -530,7 +530,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen if (object->get_geometry()->has_volume && viewplane_boundbox.intersects(object->bounds)) { /* TODO(sergey): Consider adding more grained check. */ - VLOG(1) << "Detected camera inside volume."; + VLOG_INFO << "Detected camera inside volume."; kcam->is_inside_volume = 1; parallel_for_cancel(); break; @@ -539,7 +539,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen }); if (!kcam->is_inside_volume) { - VLOG(1) << "Camera is outside of the volume."; + VLOG_INFO << "Camera is outside of the volume."; } } diff --git a/intern/cycles/scene/colorspace.cpp b/intern/cycles/scene/colorspace.cpp index f87b4c62ab2..189e3bc752d 100644 --- a/intern/cycles/scene/colorspace.cpp +++ b/intern/cycles/scene/colorspace.cpp @@ -55,8 +55,8 @@ ColorSpaceProcessor *ColorSpaceManager::get_processor(ustring colorspace) } catch (OCIO::Exception &exception) { cached_processors[colorspace] = OCIO::ConstProcessorRcPtr(); - VLOG(1) << "Colorspace " << colorspace.c_str() - << " can't be converted to scene_linear: " << exception.what(); + VLOG_WARNING << "Colorspace " << colorspace.c_str() + << " can't be converted to scene_linear: " << exception.what(); } } @@ -132,12 +132,12 @@ ustring ColorSpaceManager::detect_known_colorspace(ustring colorspace, thread_scoped_lock cache_lock(cache_colorspaces_mutex); if (is_scene_linear) { - VLOG(1) << "Colorspace " << colorspace.string() << " is no-op"; + VLOG_INFO << "Colorspace " << colorspace.string() << " is no-op"; cached_colorspaces[colorspace] = u_colorspace_raw; return u_colorspace_raw; } else if (is_srgb) { - VLOG(1) << "Colorspace " << colorspace.string() << " is sRGB"; + VLOG_INFO << "Colorspace " << colorspace.string() << " is sRGB"; cached_colorspaces[colorspace] = u_colorspace_srgb; return u_colorspace_srgb; } @@ -146,22 +146,23 @@ ustring ColorSpaceManager::detect_known_colorspace(ustring colorspace, if (!get_processor(colorspace)) { OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig(); if (!config || !config->getColorSpace(colorspace.c_str())) { - VLOG(1) << "Colorspace " << colorspace.c_str() << " not found, using raw instead"; + VLOG_WARNING << "Colorspace " << colorspace.c_str() << " not found, using raw instead"; } else { - VLOG(1) << "Colorspace " << colorspace.c_str() - << " can't be converted to scene_linear, using raw instead"; + VLOG_WARNING << "Colorspace " << colorspace.c_str() + << " can't be converted to scene_linear, using raw instead"; } cached_colorspaces[colorspace] = u_colorspace_raw; return u_colorspace_raw; } /* Convert to/from colorspace with OpenColorIO. */ - VLOG(1) << "Colorspace " << colorspace.string() << " handled through OpenColorIO"; + VLOG_INFO << "Colorspace " << colorspace.string() << " handled through OpenColorIO"; cached_colorspaces[colorspace] = colorspace; return colorspace; #else - VLOG(1) << "Colorspace " << colorspace.c_str() << " not available, built without OpenColorIO"; + VLOG_WARNING << "Colorspace " << colorspace.c_str() + << " not available, built without OpenColorIO"; return u_colorspace_raw; #endif } diff --git a/intern/cycles/scene/constant_fold.cpp b/intern/cycles/scene/constant_fold.cpp index 46ffbe9043a..4bce5661f9b 100644 --- a/intern/cycles/scene/constant_fold.cpp +++ b/intern/cycles/scene/constant_fold.cpp @@ -30,8 +30,8 @@ bool ConstantFolder::all_inputs_constant() const void ConstantFolder::make_constant(float value) const { - VLOG(3) << "Folding " << node->name << "::" << output->name() << " to constant (" << value - << ")."; + VLOG_DEBUG << "Folding " << node->name << "::" << output->name() << " to constant (" << value + << ")."; foreach (ShaderInput *sock, output->links) { sock->set(value); @@ -43,7 +43,8 @@ void ConstantFolder::make_constant(float value) const void ConstantFolder::make_constant(float3 value) const { - VLOG(3) << "Folding " << node->name << "::" << output->name() << " to constant " << value << "."; + VLOG_DEBUG << "Folding " << node->name << "::" << output->name() << " to constant " << value + << "."; foreach (ShaderInput *sock, output->links) { sock->set(value); @@ -99,8 +100,8 @@ void ConstantFolder::bypass(ShaderOutput *new_output) const { assert(new_output); - VLOG(3) << "Folding " << node->name << "::" << output->name() << " to socket " - << new_output->parent->name << "::" << new_output->name() << "."; + VLOG_DEBUG << "Folding " << node->name << "::" << output->name() << " to socket " + << new_output->parent->name << "::" << new_output->name() << "."; /* Remove all outgoing links from socket and connect them to new_output instead. * The graph->relink method affects node inputs, so it's not safe to use in constant @@ -118,7 +119,7 @@ void ConstantFolder::discard() const { assert(output->type() == SocketType::CLOSURE); - VLOG(3) << "Discarding closure " << node->name << "."; + VLOG_DEBUG << "Discarding closure " << node->name << "."; graph->disconnect(output); } diff --git a/intern/cycles/scene/film.cpp b/intern/cycles/scene/film.cpp index 7f69df7b321..8239ee84b82 100644 --- a/intern/cycles/scene/film.cpp +++ b/intern/cycles/scene/film.cpp @@ -152,7 +152,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) KernelFilm *kfilm = &dscene->data.film; - /* update __data */ + /* update data */ kfilm->exposure = exposure; kfilm->pass_alpha_threshold = pass_alpha_threshold; kfilm->pass_flag = 0; @@ -580,10 +580,10 @@ void Film::update_passes(Scene *scene, bool add_sample_count_pass) tag_modified(); /* Debug logging. */ - if (VLOG_IS_ON(2)) { - VLOG(2) << "Effective scene passes:"; + if (VLOG_INFO_IS_ON) { + VLOG_INFO << "Effective scene passes:"; for (const Pass *pass : scene->passes) { - VLOG(2) << "- " << *pass; + VLOG_INFO << "- " << *pass; } } } diff --git a/intern/cycles/scene/geometry.cpp b/intern/cycles/scene/geometry.cpp index 9152abacbdb..bdc8839e277 100644 --- a/intern/cycles/scene/geometry.cpp +++ b/intern/cycles/scene/geometry.cpp @@ -407,43 +407,47 @@ void GeometryManager::update_osl_attributes(Device *device, /* Generate a normal attribute map entry from an attribute descriptor. */ static void emit_attribute_map_entry( - uint4 *attr_map, int index, uint id, TypeDesc type, const AttributeDescriptor &desc) + AttributeMap *attr_map, int index, uint id, TypeDesc type, const AttributeDescriptor &desc) { - attr_map[index].x = id; - attr_map[index].y = desc.element; - attr_map[index].z = as_uint(desc.offset); + attr_map[index].id = id; + attr_map[index].element = desc.element; + attr_map[index].offset = as_uint(desc.offset); if (type == TypeDesc::TypeFloat) - attr_map[index].w = NODE_ATTR_FLOAT; + attr_map[index].type = NODE_ATTR_FLOAT; else if (type == TypeDesc::TypeMatrix) - attr_map[index].w = NODE_ATTR_MATRIX; + attr_map[index].type = NODE_ATTR_MATRIX; else if (type == TypeFloat2) - attr_map[index].w = NODE_ATTR_FLOAT2; + attr_map[index].type = NODE_ATTR_FLOAT2; else if (type == TypeFloat4) - attr_map[index].w = NODE_ATTR_FLOAT4; + attr_map[index].type = NODE_ATTR_FLOAT4; else if (type == TypeRGBA) - attr_map[index].w = NODE_ATTR_RGBA; + attr_map[index].type = NODE_ATTR_RGBA; else - attr_map[index].w = NODE_ATTR_FLOAT3; + attr_map[index].type = NODE_ATTR_FLOAT3; - attr_map[index].w |= desc.flags << 8; + attr_map[index].flags = desc.flags; } /* Generate an attribute map end marker, optionally including a link to another map. * Links are used to connect object attribute maps to mesh attribute maps. */ -static void emit_attribute_map_terminator(uint4 *attr_map, int index, bool chain, uint chain_link) +static void emit_attribute_map_terminator(AttributeMap *attr_map, + int index, + bool chain, + uint chain_link) { for (int j = 0; j < ATTR_PRIM_TYPES; j++) { - attr_map[index + j].x = ATTR_STD_NONE; - attr_map[index + j].y = chain; /* link is valid flag */ - attr_map[index + j].z = chain ? chain_link + j : 0; /* link to the correct sub-entry */ - attr_map[index + j].w = 0; + attr_map[index + j].id = ATTR_STD_NONE; + attr_map[index + j].element = chain; /* link is valid flag */ + attr_map[index + j].offset = chain ? chain_link + j : 0; /* link to the correct sub-entry */ + attr_map[index + j].type = 0; + attr_map[index + j].flags = 0; } } /* Generate all necessary attribute map entries from the attribute request. */ static void emit_attribute_mapping( - uint4 *attr_map, int index, Scene *scene, AttributeRequest &req, Geometry *geom) + AttributeMap *attr_map, int index, Scene *scene, AttributeRequest &req, Geometry *geom) { uint id; @@ -501,8 +505,8 @@ void GeometryManager::update_svm_attributes(Device *, } /* create attribute map */ - uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size); - memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint)); + AttributeMap *attr_map = dscene->attributes_map.alloc(attr_map_size); + memset(attr_map, 0, dscene->attributes_map.size() * sizeof(*attr_map)); for (size_t i = 0; i < scene->geometry.size(); i++) { Geometry *geom = scene->geometry[i]; @@ -1288,7 +1292,7 @@ void GeometryManager::device_update_bvh(Device *device, bparams.bvh_type = scene->params.bvh_type; bparams.curve_subdivisions = scene->params.curve_subdivisions(); - VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; + VLOG_INFO << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; const bool can_refit = scene->bvh != nullptr && (bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX || @@ -1799,7 +1803,7 @@ void GeometryManager::device_update(Device *device, if (!need_update()) return; - VLOG(1) << "Total " << scene->geometry.size() << " meshes."; + VLOG_INFO << "Total " << scene->geometry.size() << " meshes."; bool true_displacement_used = false; bool curve_shadow_transparency_used = false; @@ -1953,7 +1957,7 @@ void GeometryManager::device_update(Device *device, { /* Copy constant data needed by shader evaluation. */ - device->const_copy_to("__data", &dscene->data, sizeof(dscene->data)); + device->const_copy_to("data", &dscene->data, sizeof(dscene->data)); scoped_callback_timer timer([scene](double time) { if (scene->update_stats) { @@ -2038,7 +2042,7 @@ void GeometryManager::device_update(Device *device, TaskPool::Summary summary; pool.wait_work(&summary); - VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report(); + VLOG_WORK << "Objects BVH build pool statistics:\n" << summary.full_report(); } foreach (Shader *shader, scene->shaders) { diff --git a/intern/cycles/scene/image.cpp b/intern/cycles/scene/image.cpp index 1b44162351a..0352ed3e66c 100644 --- a/intern/cycles/scene/image.cpp +++ b/intern/cycles/scene/image.cpp @@ -653,8 +653,8 @@ bool ImageManager::file_load_image(Image *img, int texture_limit) while (max_size * scale_factor > texture_limit) { scale_factor *= 0.5f; } - VLOG(1) << "Scaling image " << img->loader->name() << " by a factor of " << scale_factor - << "."; + VLOG_WORK << "Scaling image " << img->loader->name() << " by a factor of " << scale_factor + << "."; vector<StorageType> scaled_pixels; size_t scaled_width, scaled_height, scaled_depth; util_image_resize_pixels(pixels_storage, @@ -697,7 +697,7 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro ImageDataType type = img->metadata.type; /* Name for debugging. */ - img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type), slot); + img->mem_name = string_printf("tex_image_%s_%03d", name_from_type(type), slot); /* Free previous texture in slot. */ if (img->mem) { diff --git a/intern/cycles/scene/image_oiio.cpp b/intern/cycles/scene/image_oiio.cpp index 09676455308..500e53ed763 100644 --- a/intern/cycles/scene/image_oiio.cpp +++ b/intern/cycles/scene/image_oiio.cpp @@ -22,11 +22,11 @@ bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures & /*features*/, { /* Perform preliminary checks, with meaningful logging. */ if (!path_exists(filepath.string())) { - VLOG(1) << "File '" << filepath.string() << "' does not exist."; + VLOG_WARNING << "File '" << filepath.string() << "' does not exist."; return false; } if (path_is_directory(filepath.string())) { - VLOG(1) << "File '" << filepath.string() << "' is a directory, can't use as image."; + VLOG_WARNING << "File '" << filepath.string() << "' is a directory, can't use as image."; return false; } diff --git a/intern/cycles/scene/image_vdb.cpp b/intern/cycles/scene/image_vdb.cpp index 2209be60a97..059eb09fef4 100644 --- a/intern/cycles/scene/image_vdb.cpp +++ b/intern/cycles/scene/image_vdb.cpp @@ -70,7 +70,7 @@ struct ToNanoOp { nanogrid = nanovdb::openToNanoVDB(floatgrid); } catch (const std::exception &e) { - VLOG(1) << "Error converting OpenVDB to NanoVDB grid: " << e.what(); + VLOG_WARNING << "Error converting OpenVDB to NanoVDB grid: " << e.what(); } return true; } diff --git a/intern/cycles/scene/integrator.cpp b/intern/cycles/scene/integrator.cpp index fda6ecc8d14..aa11004fb48 100644 --- a/intern/cycles/scene/integrator.cpp +++ b/intern/cycles/scene/integrator.cpp @@ -338,7 +338,7 @@ AdaptiveSampling Integrator::get_adaptive_sampling() const if (aa_samples > 0 && adaptive_threshold == 0.0f) { adaptive_sampling.threshold = max(0.001f, 1.0f / (float)aa_samples); - VLOG(1) << "Cycles adaptive sampling: automatic threshold = " << adaptive_sampling.threshold; + VLOG_INFO << "Cycles adaptive sampling: automatic threshold = " << adaptive_sampling.threshold; } else { adaptive_sampling.threshold = adaptive_threshold; @@ -350,8 +350,8 @@ AdaptiveSampling Integrator::get_adaptive_sampling() const * in various test scenes. */ const int min_samples = (int)ceilf(16.0f / powf(adaptive_sampling.threshold, 0.3f)); adaptive_sampling.min_samples = max(4, min_samples); - VLOG(1) << "Cycles adaptive sampling: automatic min samples = " - << adaptive_sampling.min_samples; + VLOG_INFO << "Cycles adaptive sampling: automatic min samples = " + << adaptive_sampling.min_samples; } else { adaptive_sampling.min_samples = max(4, adaptive_min_samples); diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp index 5e311d3051f..ea1f45793fa 100644 --- a/intern/cycles/scene/light.cpp +++ b/intern/cycles/scene/light.cpp @@ -34,7 +34,7 @@ static void shade_background_pixels(Device *device, Progress &progress) { /* Needs to be up to data for attribute access. */ - device->const_copy_to("__data", &dscene->data, sizeof(dscene->data)); + device->const_copy_to("data", &dscene->data, sizeof(dscene->data)); const int size = width * height; const int num_channels = 3; @@ -215,7 +215,9 @@ void LightManager::test_enabled_lights(Scene *scene) */ Shader *shader = scene->background->get_shader(scene); const bool disable_mis = !(has_portal || shader->has_surface_spatial_varying); - VLOG_IF(1, disable_mis) << "Background MIS has been disabled.\n"; + if (disable_mis) { + VLOG_INFO << "Background MIS has been disabled.\n"; + } foreach (Light *light, scene->lights) { if (light->light_type == LIGHT_BACKGROUND) { light->is_enabled = !disable_mis; @@ -309,7 +311,7 @@ void LightManager::device_update_distribution(Device *, } size_t num_distribution = num_triangles + num_lights; - VLOG(1) << "Total " << num_distribution << " of light distribution primitives."; + VLOG_INFO << "Total " << num_distribution << " of light distribution primitives."; /* emission area */ KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1); @@ -655,13 +657,14 @@ void LightManager::device_update_background(Device *device, if (res.x == 0) { res = environment_res; if (res.x > 0 && res.y > 0) { - VLOG(2) << "Automatically set World MIS resolution to " << res.x << " by " << res.y << "\n"; + VLOG_INFO << "Automatically set World MIS resolution to " << res.x << " by " << res.y + << "\n"; } } /* If it's still unknown, just use the default. */ if (res.x == 0 || res.y == 0) { res = make_int2(1024, 512); - VLOG(2) << "Setting World MIS resolution to default\n"; + VLOG_INFO << "Setting World MIS resolution to default\n"; } kbackground->map_res_x = res.x; kbackground->map_res_y = res.y; @@ -704,7 +707,7 @@ void LightManager::device_update_background(Device *device, marg_cdf[res.y].y = 1.0f; - VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n"; + VLOG_WORK << "Background MIS build time " << time_dt() - time_start << "\n"; /* update device */ dscene->light_background_marginal_cdf.copy_to_device(); @@ -725,7 +728,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc KernelLight *klights = dscene->lights.alloc(num_lights); if (num_lights == 0) { - VLOG(1) << "No effective light, ignoring points update."; + VLOG_WORK << "No effective light, ignoring points update."; return; } @@ -955,9 +958,9 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc light_index++; } - VLOG(1) << "Number of lights sent to the device: " << light_index; + VLOG_INFO << "Number of lights sent to the device: " << light_index; - VLOG(1) << "Number of lights without contribution: " << num_scene_lights - light_index; + VLOG_INFO << "Number of lights without contribution: " << num_scene_lights - light_index; dscene->lights.copy_to_device(); } @@ -976,7 +979,7 @@ void LightManager::device_update(Device *device, } }); - VLOG(1) << "Total " << scene->lights.size() << " lights."; + VLOG_INFO << "Total " << scene->lights.size() << " lights."; /* Detect which lights are enabled, also determines if we need to update the background. */ test_enabled_lights(scene); diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp index ddd89a16640..3a1c177fe3b 100644 --- a/intern/cycles/scene/object.cpp +++ b/intern/cycles/scene/object.cpp @@ -688,7 +688,7 @@ void ObjectManager::device_update(Device *device, dscene->objects.tag_modified(); } - VLOG(1) << "Total " << scene->objects.size() << " objects."; + VLOG_INFO << "Total " << scene->objects.size() << " objects."; device_free(device, dscene, false); diff --git a/intern/cycles/scene/osl.cpp b/intern/cycles/scene/osl.cpp index 6698e6e2cce..f5ee0c0f1d3 100644 --- a/intern/cycles/scene/osl.cpp +++ b/intern/cycles/scene/osl.cpp @@ -92,7 +92,7 @@ void OSLShaderManager::device_update_specific(Device *device, } }); - VLOG(1) << "Total " << scene->shaders.size() << " shaders."; + VLOG_INFO << "Total " << scene->shaders.size() << " shaders."; device_free(device, dscene, scene); @@ -240,7 +240,7 @@ void OSLShaderManager::shading_system_init() ss_shared->attribute("searchpath:shader", shader_path); ss_shared->attribute("greedyjit", 1); - VLOG(1) << "Using shader search path: " << shader_path; + VLOG_INFO << "Using shader search path: " << shader_path; /* our own ray types */ static const char *raytypes[] = { diff --git a/intern/cycles/scene/particles.cpp b/intern/cycles/scene/particles.cpp index a05acf17ccf..b527dd0ebe8 100644 --- a/intern/cycles/scene/particles.cpp +++ b/intern/cycles/scene/particles.cpp @@ -105,7 +105,7 @@ void ParticleSystemManager::device_update(Device *device, } }); - VLOG(1) << "Total " << scene->particle_systems.size() << " particle systems."; + VLOG_INFO << "Total " << scene->particle_systems.size() << " particle systems."; device_free(device, dscene); diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp index 8b5604eba72..1fcc3331337 100644 --- a/intern/cycles/scene/scene.cpp +++ b/intern/cycles/scene/scene.cpp @@ -34,49 +34,49 @@ CCL_NAMESPACE_BEGIN DeviceScene::DeviceScene(Device *device) - : bvh_nodes(device, "__bvh_nodes", MEM_GLOBAL), - bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_GLOBAL), - object_node(device, "__object_node", MEM_GLOBAL), - prim_type(device, "__prim_type", MEM_GLOBAL), - prim_visibility(device, "__prim_visibility", MEM_GLOBAL), - prim_index(device, "__prim_index", MEM_GLOBAL), - prim_object(device, "__prim_object", MEM_GLOBAL), - prim_time(device, "__prim_time", MEM_GLOBAL), - tri_verts(device, "__tri_verts", MEM_GLOBAL), - tri_shader(device, "__tri_shader", MEM_GLOBAL), - tri_vnormal(device, "__tri_vnormal", MEM_GLOBAL), - tri_vindex(device, "__tri_vindex", MEM_GLOBAL), - tri_patch(device, "__tri_patch", MEM_GLOBAL), - tri_patch_uv(device, "__tri_patch_uv", MEM_GLOBAL), - curves(device, "__curves", MEM_GLOBAL), - curve_keys(device, "__curve_keys", MEM_GLOBAL), - curve_segments(device, "__curve_segments", MEM_GLOBAL), - patches(device, "__patches", MEM_GLOBAL), - points(device, "__points", MEM_GLOBAL), - points_shader(device, "__points_shader", MEM_GLOBAL), - objects(device, "__objects", MEM_GLOBAL), - object_motion_pass(device, "__object_motion_pass", MEM_GLOBAL), - object_motion(device, "__object_motion", MEM_GLOBAL), - object_flag(device, "__object_flag", MEM_GLOBAL), - object_volume_step(device, "__object_volume_step", MEM_GLOBAL), - object_prim_offset(device, "__object_prim_offset", MEM_GLOBAL), - camera_motion(device, "__camera_motion", MEM_GLOBAL), - attributes_map(device, "__attributes_map", MEM_GLOBAL), - attributes_float(device, "__attributes_float", MEM_GLOBAL), - attributes_float2(device, "__attributes_float2", MEM_GLOBAL), - attributes_float3(device, "__attributes_float3", MEM_GLOBAL), - attributes_float4(device, "__attributes_float4", MEM_GLOBAL), - attributes_uchar4(device, "__attributes_uchar4", MEM_GLOBAL), - light_distribution(device, "__light_distribution", MEM_GLOBAL), - lights(device, "__lights", MEM_GLOBAL), - light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_GLOBAL), - light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_GLOBAL), - particles(device, "__particles", MEM_GLOBAL), - svm_nodes(device, "__svm_nodes", MEM_GLOBAL), - shaders(device, "__shaders", MEM_GLOBAL), - lookup_table(device, "__lookup_table", MEM_GLOBAL), - sample_pattern_lut(device, "__sample_pattern_lut", MEM_GLOBAL), - ies_lights(device, "__ies", MEM_GLOBAL) + : bvh_nodes(device, "bvh_nodes", MEM_GLOBAL), + bvh_leaf_nodes(device, "bvh_leaf_nodes", MEM_GLOBAL), + object_node(device, "object_node", MEM_GLOBAL), + prim_type(device, "prim_type", MEM_GLOBAL), + prim_visibility(device, "prim_visibility", MEM_GLOBAL), + prim_index(device, "prim_index", MEM_GLOBAL), + prim_object(device, "prim_object", MEM_GLOBAL), + prim_time(device, "prim_time", MEM_GLOBAL), + tri_verts(device, "tri_verts", MEM_GLOBAL), + tri_shader(device, "tri_shader", MEM_GLOBAL), + tri_vnormal(device, "tri_vnormal", MEM_GLOBAL), + tri_vindex(device, "tri_vindex", MEM_GLOBAL), + tri_patch(device, "tri_patch", MEM_GLOBAL), + tri_patch_uv(device, "tri_patch_uv", MEM_GLOBAL), + curves(device, "curves", MEM_GLOBAL), + curve_keys(device, "curve_keys", MEM_GLOBAL), + curve_segments(device, "curve_segments", MEM_GLOBAL), + patches(device, "patches", MEM_GLOBAL), + points(device, "points", MEM_GLOBAL), + points_shader(device, "points_shader", MEM_GLOBAL), + objects(device, "objects", MEM_GLOBAL), + object_motion_pass(device, "object_motion_pass", MEM_GLOBAL), + object_motion(device, "object_motion", MEM_GLOBAL), + object_flag(device, "object_flag", MEM_GLOBAL), + object_volume_step(device, "object_volume_step", MEM_GLOBAL), + object_prim_offset(device, "object_prim_offset", MEM_GLOBAL), + camera_motion(device, "camera_motion", MEM_GLOBAL), + attributes_map(device, "attributes_map", MEM_GLOBAL), + attributes_float(device, "attributes_float", MEM_GLOBAL), + attributes_float2(device, "attributes_float2", MEM_GLOBAL), + attributes_float3(device, "attributes_float3", MEM_GLOBAL), + attributes_float4(device, "attributes_float4", MEM_GLOBAL), + attributes_uchar4(device, "attributes_uchar4", MEM_GLOBAL), + light_distribution(device, "light_distribution", MEM_GLOBAL), + lights(device, "lights", MEM_GLOBAL), + light_background_marginal_cdf(device, "light_background_marginal_cdf", MEM_GLOBAL), + light_background_conditional_cdf(device, "light_background_conditional_cdf", MEM_GLOBAL), + particles(device, "particles", MEM_GLOBAL), + svm_nodes(device, "svm_nodes", MEM_GLOBAL), + shaders(device, "shaders", MEM_GLOBAL), + lookup_table(device, "lookup_table", MEM_GLOBAL), + sample_pattern_lut(device, "sample_pattern_lut", MEM_GLOBAL), + ies_lights(device, "ies", MEM_GLOBAL) { memset((void *)&data, 0, sizeof(data)); } @@ -366,18 +366,18 @@ void Scene::device_update(Device *device_, Progress &progress) dscene.data.volume_stack_size = get_volume_stack_size(); progress.set_status("Updating Device", "Writing constant memory"); - device->const_copy_to("__data", &dscene.data, sizeof(dscene.data)); + device->const_copy_to("data", &dscene.data, sizeof(dscene.data)); } if (print_stats) { size_t mem_used = util_guarded_get_mem_used(); size_t mem_peak = util_guarded_get_mem_peak(); - VLOG(1) << "System memory statistics after full device sync:\n" - << " Usage: " << string_human_readable_number(mem_used) << " (" - << string_human_readable_size(mem_used) << ")\n" - << " Peak: " << string_human_readable_number(mem_peak) << " (" - << string_human_readable_size(mem_peak) << ")"; + VLOG_INFO << "System memory statistics after full device sync:\n" + << " Usage: " << string_human_readable_number(mem_used) << " (" + << string_human_readable_size(mem_used) << ")\n" + << " Peak: " << string_human_readable_number(mem_peak) << " (" + << string_human_readable_size(mem_peak) << ")"; } } @@ -586,35 +586,38 @@ bool Scene::update(Progress &progress) static void log_kernel_features(const uint features) { - VLOG(2) << "Requested features:\n"; - VLOG(2) << "Use BSDF " << string_from_bool(features & KERNEL_FEATURE_NODE_BSDF) << "\n"; - VLOG(2) << "Use Principled BSDF " << string_from_bool(features & KERNEL_FEATURE_PRINCIPLED) - << "\n"; - VLOG(2) << "Use Emission " << string_from_bool(features & KERNEL_FEATURE_NODE_EMISSION) << "\n"; - VLOG(2) << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_NODE_VOLUME) << "\n"; - VLOG(2) << "Use Bump " << string_from_bool(features & KERNEL_FEATURE_NODE_BUMP) << "\n"; - VLOG(2) << "Use Voronoi " << string_from_bool(features & KERNEL_FEATURE_NODE_VORONOI_EXTRA) - << "\n"; - VLOG(2) << "Use Shader Raytrace " << string_from_bool(features & KERNEL_FEATURE_NODE_RAYTRACE) - << "\n"; - VLOG(2) << "Use MNEE" << string_from_bool(features & KERNEL_FEATURE_MNEE) << "\n"; - VLOG(2) << "Use Transparent " << string_from_bool(features & KERNEL_FEATURE_TRANSPARENT) << "\n"; - VLOG(2) << "Use Denoising " << string_from_bool(features & KERNEL_FEATURE_DENOISING) << "\n"; - VLOG(2) << "Use Path Tracing " << string_from_bool(features & KERNEL_FEATURE_PATH_TRACING) - << "\n"; - VLOG(2) << "Use Hair " << string_from_bool(features & KERNEL_FEATURE_HAIR) << "\n"; - VLOG(2) << "Use Pointclouds " << string_from_bool(features & KERNEL_FEATURE_POINTCLOUD) << "\n"; - VLOG(2) << "Use Object Motion " << string_from_bool(features & KERNEL_FEATURE_OBJECT_MOTION) - << "\n"; - VLOG(2) << "Use Camera Motion " << string_from_bool(features & KERNEL_FEATURE_CAMERA_MOTION) - << "\n"; - VLOG(2) << "Use Baking " << string_from_bool(features & KERNEL_FEATURE_BAKING) << "\n"; - VLOG(2) << "Use Subsurface " << string_from_bool(features & KERNEL_FEATURE_SUBSURFACE) << "\n"; - VLOG(2) << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_VOLUME) << "\n"; - VLOG(2) << "Use Patch Evaluation " - << string_from_bool(features & KERNEL_FEATURE_PATCH_EVALUATION) << "\n"; - VLOG(2) << "Use Shadow Catcher " << string_from_bool(features & KERNEL_FEATURE_SHADOW_CATCHER) - << "\n"; + VLOG_INFO << "Requested features:\n"; + VLOG_INFO << "Use BSDF " << string_from_bool(features & KERNEL_FEATURE_NODE_BSDF) << "\n"; + VLOG_INFO << "Use Principled BSDF " << string_from_bool(features & KERNEL_FEATURE_PRINCIPLED) + << "\n"; + VLOG_INFO << "Use Emission " << string_from_bool(features & KERNEL_FEATURE_NODE_EMISSION) + << "\n"; + VLOG_INFO << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_NODE_VOLUME) << "\n"; + VLOG_INFO << "Use Bump " << string_from_bool(features & KERNEL_FEATURE_NODE_BUMP) << "\n"; + VLOG_INFO << "Use Voronoi " << string_from_bool(features & KERNEL_FEATURE_NODE_VORONOI_EXTRA) + << "\n"; + VLOG_INFO << "Use Shader Raytrace " << string_from_bool(features & KERNEL_FEATURE_NODE_RAYTRACE) + << "\n"; + VLOG_INFO << "Use MNEE" << string_from_bool(features & KERNEL_FEATURE_MNEE) << "\n"; + VLOG_INFO << "Use Transparent " << string_from_bool(features & KERNEL_FEATURE_TRANSPARENT) + << "\n"; + VLOG_INFO << "Use Denoising " << string_from_bool(features & KERNEL_FEATURE_DENOISING) << "\n"; + VLOG_INFO << "Use Path Tracing " << string_from_bool(features & KERNEL_FEATURE_PATH_TRACING) + << "\n"; + VLOG_INFO << "Use Hair " << string_from_bool(features & KERNEL_FEATURE_HAIR) << "\n"; + VLOG_INFO << "Use Pointclouds " << string_from_bool(features & KERNEL_FEATURE_POINTCLOUD) + << "\n"; + VLOG_INFO << "Use Object Motion " << string_from_bool(features & KERNEL_FEATURE_OBJECT_MOTION) + << "\n"; + VLOG_INFO << "Use Camera Motion " << string_from_bool(features & KERNEL_FEATURE_CAMERA_MOTION) + << "\n"; + VLOG_INFO << "Use Baking " << string_from_bool(features & KERNEL_FEATURE_BAKING) << "\n"; + VLOG_INFO << "Use Subsurface " << string_from_bool(features & KERNEL_FEATURE_SUBSURFACE) << "\n"; + VLOG_INFO << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_VOLUME) << "\n"; + VLOG_INFO << "Use Patch Evaluation " + << string_from_bool(features & KERNEL_FEATURE_PATCH_EVALUATION) << "\n"; + VLOG_INFO << "Use Shadow Catcher " << string_from_bool(features & KERNEL_FEATURE_SHADOW_CATCHER) + << "\n"; } bool Scene::load_kernels(Progress &progress, bool lock_scene) @@ -675,8 +678,8 @@ int Scene::get_max_closure_count() * closures discarded due to mixing or low weights. We need to limit * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it * avoids excessive memory usage for split kernels. */ - VLOG(2) << "Maximum number of closures exceeded: " << max_closure_global << " > " - << MAX_CLOSURE; + VLOG_WARNING << "Maximum number of closures exceeded: " << max_closure_global << " > " + << MAX_CLOSURE; max_closure_global = MAX_CLOSURE; } @@ -723,7 +726,7 @@ int Scene::get_volume_stack_size() const volume_stack_size = min(volume_stack_size, MAX_VOLUME_STACK_SIZE); - VLOG(3) << "Detected required volume stack size " << volume_stack_size; + VLOG_WORK << "Detected required volume stack size " << volume_stack_size; return volume_stack_size; } diff --git a/intern/cycles/scene/scene.h b/intern/cycles/scene/scene.h index a0d2f4a6c06..d04c6a27f11 100644 --- a/intern/cycles/scene/scene.h +++ b/intern/cycles/scene/scene.h @@ -98,7 +98,7 @@ class DeviceScene { device_vector<DecomposedTransform> camera_motion; /* attributes */ - device_vector<uint4> attributes_map; + device_vector<AttributeMap> attributes_map; device_vector<float> attributes_float; device_vector<float2> attributes_float2; device_vector<packed_float3> attributes_float3; diff --git a/intern/cycles/scene/shader_graph.cpp b/intern/cycles/scene/shader_graph.cpp index f25d0b7c7b9..ef3f142ed4e 100644 --- a/intern/cycles/scene/shader_graph.cpp +++ b/intern/cycles/scene/shader_graph.cpp @@ -659,7 +659,7 @@ void ShaderGraph::deduplicate_nodes() } if (num_deduplicated > 0) { - VLOG(1) << "Deduplicated " << num_deduplicated << " nodes."; + VLOG_DEBUG << "Deduplicated " << num_deduplicated << " nodes."; } } @@ -700,7 +700,7 @@ void ShaderGraph::verify_volume_output() } } if (!has_valid_volume) { - VLOG(1) << "Disconnect meaningless volume output."; + VLOG_DEBUG << "Disconnect meaningless volume output."; disconnect(volume_in->link); } } diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 3b58556f601..f93a1a5231a 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -2391,7 +2391,7 @@ void GlossyBsdfNode::simplify_settings(Scene *scene) * NOTE: Keep the epsilon in sync with kernel! */ if (!roughness_input->link && roughness <= 1e-4f) { - VLOG(3) << "Using sharp glossy BSDF."; + VLOG_DEBUG << "Using sharp glossy BSDF."; distribution = CLOSURE_BSDF_REFLECTION_ID; } } @@ -2400,7 +2400,7 @@ void GlossyBsdfNode::simplify_settings(Scene *scene) * benefit from closure blur to remove unwanted noise. */ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFLECTION_ID) { - VLOG(3) << "Using GGX glossy with filter glossy."; + VLOG_DEBUG << "Using GGX glossy with filter glossy."; distribution = CLOSURE_BSDF_MICROFACET_GGX_ID; roughness = 0.0f; } @@ -2484,7 +2484,7 @@ void GlassBsdfNode::simplify_settings(Scene *scene) * NOTE: Keep the epsilon in sync with kernel! */ if (!roughness_input->link && roughness <= 1e-4f) { - VLOG(3) << "Using sharp glass BSDF."; + VLOG_DEBUG << "Using sharp glass BSDF."; distribution = CLOSURE_BSDF_SHARP_GLASS_ID; } } @@ -2493,7 +2493,7 @@ void GlassBsdfNode::simplify_settings(Scene *scene) * benefit from closure blur to remove unwanted noise. */ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_SHARP_GLASS_ID) { - VLOG(3) << "Using GGX glass with filter glossy."; + VLOG_DEBUG << "Using GGX glass with filter glossy."; distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID; roughness = 0.0f; } @@ -2577,7 +2577,7 @@ void RefractionBsdfNode::simplify_settings(Scene *scene) * NOTE: Keep the epsilon in sync with kernel! */ if (!roughness_input->link && roughness <= 1e-4f) { - VLOG(3) << "Using sharp refraction BSDF."; + VLOG_DEBUG << "Using sharp refraction BSDF."; distribution = CLOSURE_BSDF_REFRACTION_ID; } } @@ -2586,7 +2586,7 @@ void RefractionBsdfNode::simplify_settings(Scene *scene) * benefit from closure blur to remove unwanted noise. */ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFRACTION_ID) { - VLOG(3) << "Using GGX refraction with filter glossy."; + VLOG_DEBUG << "Using GGX refraction with filter glossy."; distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; roughness = 0.0f; } diff --git a/intern/cycles/scene/svm.cpp b/intern/cycles/scene/svm.cpp index 484a7d6de72..4bc5a1b9cc2 100644 --- a/intern/cycles/scene/svm.cpp +++ b/intern/cycles/scene/svm.cpp @@ -51,9 +51,9 @@ void SVMShaderManager::device_update_shader(Scene *scene, compiler.background = (shader == scene->background->get_shader(scene)); compiler.compile(shader, *svm_nodes, 0, &summary); - VLOG(3) << "Compilation summary:\n" - << "Shader name: " << shader->name << "\n" - << summary.full_report(); + VLOG_WORK << "Compilation summary:\n" + << "Shader name: " << shader->name << "\n" + << summary.full_report(); } void SVMShaderManager::device_update_specific(Device *device, @@ -72,7 +72,7 @@ void SVMShaderManager::device_update_specific(Device *device, const int num_shaders = scene->shaders.size(); - VLOG(1) << "Total " << num_shaders << " shaders."; + VLOG_INFO << "Total " << num_shaders << " shaders."; double start_time = time_dt(); @@ -148,8 +148,8 @@ void SVMShaderManager::device_update_specific(Device *device, update_flags = UPDATE_NONE; - VLOG(1) << "Shader manager updated " << num_shaders << " shaders in " << time_dt() - start_time - << " seconds."; + VLOG_INFO << "Shader manager updated " << num_shaders << " shaders in " << time_dt() - start_time + << " seconds."; } void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene) diff --git a/intern/cycles/scene/tables.cpp b/intern/cycles/scene/tables.cpp index bb35880d37e..3e57b535f35 100644 --- a/intern/cycles/scene/tables.cpp +++ b/intern/cycles/scene/tables.cpp @@ -34,7 +34,7 @@ void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene) } }); - VLOG(1) << "Total " << lookup_tables.size() << " lookup tables."; + VLOG_INFO << "Total " << lookup_tables.size() << " lookup tables."; if (lookup_tables.size() > 0) dscene->lookup_table.copy_to_device(); diff --git a/intern/cycles/scene/volume.cpp b/intern/cycles/scene/volume.cpp index 39e9b0bbbf4..77955350305 100644 --- a/intern/cycles/scene/volume.cpp +++ b/intern/cycles/scene/volume.cpp @@ -754,11 +754,11 @@ void GeometryManager::create_volume_mesh(const Scene *scene, Volume *volume, Pro } /* Print stats. */ - VLOG(1) << "Memory usage volume mesh: " - << ((vertices.size() + face_normals.size()) * sizeof(float3) + - indices.size() * sizeof(int)) / - (1024.0 * 1024.0) - << "Mb."; + VLOG_WORK << "Memory usage volume mesh: " + << ((vertices.size() + face_normals.size()) * sizeof(float3) + + indices.size() * sizeof(int)) / + (1024.0 * 1024.0) + << "Mb."; } CCL_NAMESPACE_END diff --git a/intern/cycles/session/session.cpp b/intern/cycles/session/session.cpp index ef177636046..ba30be817cf 100644 --- a/intern/cycles/session/session.cpp +++ b/intern/cycles/session/session.cpp @@ -146,11 +146,11 @@ void Session::run_main_render_loop() RenderWork render_work = run_update_for_next_iteration(); if (!render_work) { - if (VLOG_IS_ON(2)) { + if (VLOG_WORK_IS_ON) { double total_time, render_time; progress.get_time(total_time, render_time); - VLOG(2) << "Rendering in main loop is done in " << render_time << " seconds."; - VLOG(2) << path_trace_->full_report(); + VLOG_WORK << "Rendering in main loop is done in " << render_time << " seconds."; + VLOG_WORK << path_trace_->full_report(); } if (params.background) { diff --git a/intern/cycles/session/tile.cpp b/intern/cycles/session/tile.cpp index 82272a7dbf5..f4930cbb945 100644 --- a/intern/cycles/session/tile.cpp +++ b/intern/cycles/session/tile.cpp @@ -335,7 +335,7 @@ int TileManager::compute_render_tile_size(const int suggested_tile_size) const void TileManager::reset_scheduling(const BufferParams ¶ms, int2 tile_size) { - VLOG(3) << "Using tile size of " << tile_size; + VLOG_WORK << "Using tile size of " << tile_size; close_tile_output(); @@ -466,7 +466,7 @@ bool TileManager::open_tile_output() write_state_.num_tiles_written = 0; - VLOG(3) << "Opened tile file " << write_state_.filename; + VLOG_WORK << "Opened tile file " << write_state_.filename; return true; } @@ -485,7 +485,7 @@ bool TileManager::close_tile_output() return false; } - VLOG(3) << "Tile output is closed."; + VLOG_WORK << "Tile output is closed."; return true; } @@ -536,7 +536,7 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers) pixels = pixel_storage.data(); } - VLOG(3) << "Write tile at " << tile_x << ", " << tile_y; + VLOG_WORK << "Write tile at " << tile_x << ", " << tile_y; /* The image tile sizes in the OpenEXR file are different from the size of our big tiles. The * write_tiles() method expects a contiguous image region that will be split into tiles @@ -567,7 +567,7 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers) ++write_state_.num_tiles_written; - VLOG(3) << "Tile written in " << time_dt() - time_start << " seconds."; + VLOG_WORK << "Tile written in " << time_dt() - time_start << " seconds."; return true; } @@ -591,7 +591,7 @@ void TileManager::finish_write_tiles() const int tile_x = tile.x + tile.window_x; const int tile_y = tile.y + tile.window_y; - VLOG(3) << "Write dummy tile at " << tile_x << ", " << tile_y; + VLOG_WORK << "Write dummy tile at " << tile_x << ", " << tile_y; write_state_.tile_out->write_tiles(tile_x, tile_x + tile.window_width, @@ -610,8 +610,8 @@ void TileManager::finish_write_tiles() full_buffer_written_cb(write_state_.filename); } - VLOG(3) << "Tile file size is " - << string_human_readable_number(path_file_size(write_state_.filename)) << " bytes."; + VLOG_WORK << "Tile file size is " + << string_human_readable_number(path_file_size(write_state_.filename)) << " bytes."; /* Advance the counter upon explicit finish of the file. * Makes it possible to re-use tile manager for another scene, and avoids unnecessary increments diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp index dac36ab0135..2dc13f0eccb 100644 --- a/intern/cycles/test/render_graph_finalize_test.cpp +++ b/intern/cycles/test/render_graph_finalize_test.cpp @@ -166,7 +166,7 @@ class RenderGraph : public testing::Test { virtual void SetUp() { util_logging_start(); - util_logging_verbosity_set(3); + util_logging_verbosity_set(5); device_cpu = Device::create(device_info, stats, profiler); scene = new Scene(scene_params, device_cpu); diff --git a/intern/cycles/util/debug.cpp b/intern/cycles/util/debug.cpp index 65d108bb9d1..faa54a92c24 100644 --- a/intern/cycles/util/debug.cpp +++ b/intern/cycles/util/debug.cpp @@ -25,7 +25,7 @@ void DebugFlags::CPU::reset() do { \ flag = (getenv(env) == NULL); \ if (!flag) { \ - VLOG(1) << "Disabling " << STRINGIFY(flag) << " instruction set."; \ + VLOG_INFO << "Disabling " << STRINGIFY(flag) << " instruction set."; \ } \ } while (0) diff --git a/intern/cycles/util/log.h b/intern/cycles/util/log.h index b33c826d6f5..3780d03c0d1 100644 --- a/intern/cycles/util/log.h +++ b/intern/cycles/util/log.h @@ -69,9 +69,22 @@ class LogMessageVoidify { # define LOG_ASSERT(expression) LOG_SUPPRESS() #endif -#define VLOG_ONCE(level, flag) \ - if (!flag) \ - flag = true, VLOG(level) +/* Verbose logging categories. */ + +/* Warnings. */ +#define VLOG_WARNING VLOG(1) +/* Info about devices, scene contents and features used. */ +#define VLOG_INFO VLOG(2) +#define VLOG_INFO_IS_ON VLOG_IS_ON(2) +/* Work being performed and timing/memory stats about that work. */ +#define VLOG_WORK VLOG(3) +#define VLOG_WORK_IS_ON VLOG_IS_ON(3) +/* Detailed device timing stats. */ +#define VLOG_DEVICE_STATS VLOG(4) +#define VLOG_DEVICE_STATS_IS_ON VLOG_IS_ON(4) +/* Verbose debug messages. */ +#define VLOG_DEBUG VLOG(5) +#define VLOG_DEBUG_IS_ON VLOG_IS_ON(5) struct int2; struct float3; diff --git a/intern/cycles/util/task.cpp b/intern/cycles/util/task.cpp index 2edc82eb7c3..12f661f752d 100644 --- a/intern/cycles/util/task.cpp +++ b/intern/cycles/util/task.cpp @@ -70,7 +70,7 @@ void TaskScheduler::init(int num_threads) } if (num_threads > 0) { /* Automatic number of threads. */ - VLOG(1) << "Overriding number of TBB threads to " << num_threads << "."; + VLOG_INFO << "Overriding number of TBB threads to " << num_threads << "."; global_control = new tbb::global_control(tbb::global_control::max_allowed_parallelism, num_threads); active_num_threads = num_threads; diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 5b06b5d98e6..945b3261562 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -303,59 +303,63 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) message(FATAL_ERROR "path to wayland-protocols not found") endif() + set(INC_DST ${CMAKE_CURRENT_BINARY_DIR}/libwayland) + # Generate protocols bindings. - macro(generate_protocol_bindings NAME PROT_DEF) + macro(generate_protocol_bindings PROT_DEF) + # File name without directory or extension (use for header name). + get_filename_component(_name ${PROT_DEF} NAME_WLE) add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h - COMMAND ${WAYLAND_SCANNER} client-header ${PROT_DEF} ${NAME}-client-protocol.h + OUTPUT ${INC_DST}/${_name}-client-protocol.h + COMMAND ${CMAKE_COMMAND} -E make_directory ${INC_DST} + COMMAND ${WAYLAND_SCANNER} client-header ${PROT_DEF} ${INC_DST}/${_name}-client-protocol.h ) add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c - COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${NAME}-client-protocol.c - DEPENDS ${NAME}-client-protocol.h + OUTPUT ${INC_DST}/${_name}-client-protocol.c + COMMAND ${CMAKE_COMMAND} -E make_directory ${INC_DST} + COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${INC_DST}/${_name}-client-protocol.c + DEPENDS ${INC_DST}/${_name}-client-protocol.h ) list(APPEND SRC - ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c - ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h + ${INC_DST}/${_name}-client-protocol.c + ${INC_DST}/${_name}-client-protocol.h ) + unset(_name) endmacro() + list(APPEND INC_SYS - ${CMAKE_CURRENT_BINARY_DIR} + ${INC_DST} ) # `xdg-shell`. generate_protocol_bindings( - xdg-shell "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml" ) # `xdg-decoration`. generate_protocol_bindings( - xdg-decoration "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" ) # `xdg-output`. generate_protocol_bindings( - xdg-output "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-output/xdg-output-unstable-v1.xml" ) # Pointer-constraints. generate_protocol_bindings( - pointer-constraints "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" ) # Relative-pointer. generate_protocol_bindings( - relative-pointer "${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml" ) # Tablet. generate_protocol_bindings( - tablet "${WAYLAND_PROTOCOLS_DIR}/unstable/tablet/tablet-unstable-v2.xml" ) add_definitions(-DWITH_GHOST_WAYLAND) + + unset(INC_DST) endif() if(WITH_INPUT_NDOF) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index c92e6ba78c1..5ace0fcc9d2 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -20,7 +20,7 @@ extern "C" { * \param event: The event received. * \param userdata: The callback's user data, supplied to #GHOST_CreateSystem. */ -typedef int (*GHOST_EventCallbackProcPtr)(GHOST_EventHandle event, GHOST_TUserDataPtr userdata); +typedef bool (*GHOST_EventCallbackProcPtr)(GHOST_EventHandle event, GHOST_TUserDataPtr userdata); /** * Creates the one and only system. @@ -206,7 +206,7 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl */ extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata); -extern int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle); +extern bool GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle); /** * Dispose a window. @@ -223,7 +223,7 @@ extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, * \param windowhandle: Handle to the window to be checked. * \return Indication of validity. */ -extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle); +extern bool GHOST_ValidWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle); /** * Begins full screen mode. @@ -235,7 +235,7 @@ extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle */ extern GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle, GHOST_DisplaySetting *setting, - const int stereoVisual); + const bool stereoVisual); /** * Ends full screen mode. @@ -249,7 +249,7 @@ extern GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle); * \param systemhandle: The handle to the system. * \return The current status. */ -extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle); +extern bool GHOST_GetFullScreen(GHOST_SystemHandle systemhandle); /** * Get the Window under the cursor. @@ -364,12 +364,15 @@ extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle int hotY, bool canInvertColor); +extern GHOST_TSuccess GHOST_GetCursorBitmap(GHOST_WindowHandle windowhandle, + GHOST_CursorBitmapRef *bitmap); + /** * Returns the visibility state of the cursor. * \param windowhandle: The handle to the window. * \return The visibility state of the cursor. */ -extern int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle); +extern bool GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle); /** * Shows or hides the cursor. @@ -377,7 +380,7 @@ extern int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle); * \param visible: The new visibility state of the cursor. * \return Indication of success. */ -extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, int visible); +extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, bool visible); /** * Returns the current location of the cursor (location in screen coordinates) @@ -404,8 +407,9 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, void GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle, GHOST_TGrabCursorMode *r_mode, - GHOST_TAxisFlag *r_wrap_axis, - int r_bounds[4]); + GHOST_TAxisFlag *r_axis_flag, + int r_bounds[4], + bool *r_use_software_cursor); /** * Grabs the cursor for a modal operation, to keep receiving @@ -436,7 +440,7 @@ extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, */ extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, GHOST_TModifierKeyMask mask, - int *isDown); + bool *r_is_down); /** * Returns the state of a mouse button (outside the message queue). @@ -447,7 +451,7 @@ extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, */ extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, GHOST_TButtonMask mask, - int *isDown); + bool *r_is_down); #ifdef WITH_INPUT_NDOF /*************************************************************************************** @@ -468,7 +472,7 @@ extern void GHOST_setNDOFDeadZone(float deadzone); /** * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop */ -extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool canAccept); +extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool can_accept); /** * Returns the event type. @@ -534,7 +538,7 @@ extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, * \param windowhandle: The handle to the window. * \return The validity of the window. */ -extern int GHOST_GetValid(GHOST_WindowHandle windowhandle); +extern bool GHOST_GetValid(GHOST_WindowHandle windowhandle); /** * Returns the type of drawing context used in this window. @@ -894,22 +898,22 @@ extern void GHOST_putClipboard(const char *buffer, bool selection); * \param action: console state * \return current status (1 -visible, 0 - hidden) */ -extern int setConsoleWindowState(GHOST_TConsoleWindowState action); +extern bool GHOST_setConsoleWindowState(GHOST_TConsoleWindowState action); /** * Use native pixel size (MacBook pro 'retina'), if supported. */ -extern int GHOST_UseNativePixels(void); +extern bool GHOST_UseNativePixels(void); /** * Warp the cursor, if supported. */ -extern int GHOST_SupportsCursorWarp(void); +extern bool GHOST_SupportsCursorWarp(void); /** * Support positioning windows (when false `wmWindow.x,y` are meaningless). */ -extern int GHOST_SupportsWindowPosition(void); +extern bool GHOST_SupportsWindowPosition(void); /** * Assign the callback which generates a back-trace (may be NULL). @@ -919,7 +923,7 @@ extern void GHOST_SetBacktraceHandler(GHOST_TBacktraceFn backtrace_fn); /** * Focus window after opening, or put them in the background. */ -extern void GHOST_UseWindowFocus(int use_focus); +extern void GHOST_UseWindowFocus(bool use_focus); /** * If window was opened using native pixel size, it returns scaling factor. diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 7927190de04..f712d9bd9f0 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -258,7 +258,10 @@ class GHOST_IWindow { virtual void getCursorGrabState(GHOST_TGrabCursorMode &mode, GHOST_TAxisFlag &axis_flag, - GHOST_Rect &bounds) = 0; + GHOST_Rect &bounds, + bool &use_software_cursor) = 0; + + virtual bool getCursorGrabUseSoftwareDisplay() = 0; /** * Test if the standard cursor shape is supported by current platform. @@ -282,6 +285,8 @@ class GHOST_IWindow { int hotY, bool canInvertColor) = 0; + virtual GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap) = 0; + /** * Returns the visibility state of the cursor. * \return The visibility state of the cursor. diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index 0a5561b7d68..1cbc75fe60b 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -101,6 +101,12 @@ class GHOST_Rect { * \param y: The y-coordinate of the point. */ virtual inline void wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAxisFlag axis); + /** + * Confine x & y within the rectangle (inclusive). + * \param x: The x-coordinate of the point. + * \param y: The y-coordinate of the point. + */ + virtual inline void clampPoint(int32_t &x, int32_t &y); /** * Returns whether the point is inside this rectangle. @@ -190,26 +196,34 @@ inline bool GHOST_Rect::isValid() const inline void GHOST_Rect::unionRect(const GHOST_Rect &r) { - if (r.m_l < m_l) + if (r.m_l < m_l) { m_l = r.m_l; - if (r.m_r > m_r) + } + if (r.m_r > m_r) { m_r = r.m_r; - if (r.m_t < m_t) + } + if (r.m_t < m_t) { m_t = r.m_t; - if (r.m_b > m_b) + } + if (r.m_b > m_b) { m_b = r.m_b; + } } inline void GHOST_Rect::unionPoint(int32_t x, int32_t y) { - if (x < m_l) + if (x < m_l) { m_l = x; - if (x > m_r) + } + if (x > m_r) { m_r = x; - if (y < m_t) + } + if (y < m_t) { m_t = y; - if (y > m_b) + } + if (y > m_b) { m_b = y; + } } inline void GHOST_Rect::wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAxisFlag axis) @@ -223,16 +237,37 @@ inline void GHOST_Rect::wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAx } if (axis & GHOST_kAxisX) { - while (x - ofs < m_l) + while (x - ofs < m_l) { x += w - (ofs * 2); - while (x + ofs > m_r) + } + while (x + ofs > m_r) { x -= w - (ofs * 2); + } } if (axis & GHOST_kGrabAxisY) { - while (y - ofs < m_t) + while (y - ofs < m_t) { y += h - (ofs * 2); - while (y + ofs > m_b) + } + while (y + ofs > m_b) { y -= h - (ofs * 2); + } + } +} + +inline void GHOST_Rect::clampPoint(int32_t &x, int32_t &y) +{ + if (x < m_l) { + x = m_l; + } + else if (x > m_r) { + x = m_r; + } + + if (y < m_t) { + y = m_t; + } + else if (y > m_b) { + y = m_b; } } diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 78f2b24ea78..35bde3d4413 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -44,6 +44,16 @@ GHOST_DECLARE_HANDLE(GHOST_XrContextHandle); typedef void (*GHOST_TBacktraceFn)(void *file_handle); +/** + * A reference to cursor bitmap data. + */ +typedef struct { + /** `RGBA` bytes. */ + const uint8_t *data; + int data_size[2]; + int hot_spot[2]; +} GHOST_CursorBitmapRef; + typedef struct { int flags; } GHOST_GLSettings; diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index b1a15fdf4d7..2b5414cd47b 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -177,11 +177,11 @@ void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr window->setUserData(userdata); } -int GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle) +bool GHOST_IsDialogWindow(GHOST_WindowHandle windowhandle) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - return (int)window->isDialog(); + return window->isDialog(); } GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, @@ -193,17 +193,17 @@ GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle, return system->disposeWindow(window); } -int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle) +bool GHOST_ValidWindow(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - return (int)system->validWindow(window); + return system->validWindow(window); } GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle, GHOST_DisplaySetting *setting, - const int stereoVisual) + const bool stereoVisual) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; GHOST_IWindow *window = nullptr; @@ -228,11 +228,11 @@ GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle) return system->endFullScreen(); } -int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle) +bool GHOST_GetFullScreen(GHOST_SystemHandle systemhandle) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; - return (int)system->getFullScreen(); + return system->getFullScreen(); } GHOST_WindowHandle GHOST_GetWindowUnderCursor(GHOST_SystemHandle systemhandle, @@ -326,18 +326,26 @@ GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle, return window->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor); } -int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle) +GHOST_TSuccess GHOST_GetCursorBitmap(GHOST_WindowHandle windowhandle, + GHOST_CursorBitmapRef *bitmap) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - return (int)window->getCursorVisibility(); + return window->getCursorBitmap(bitmap); } -GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, int visible) +bool GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - return window->setCursorVisibility(visible ? true : false); + return window->getCursorVisibility(); +} + +GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle, bool visible) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + + return window->setCursorVisibility(visible); } GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle, int32_t *x, int32_t *y) @@ -379,41 +387,44 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, void GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle, GHOST_TGrabCursorMode *r_mode, GHOST_TAxisFlag *r_axis_flag, - int r_bounds[4]) + int r_bounds[4], + bool *r_use_software_cursor) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; GHOST_Rect bounds_rect; - window->getCursorGrabState(*r_mode, *r_axis_flag, bounds_rect); + bool use_software_cursor; + window->getCursorGrabState(*r_mode, *r_axis_flag, bounds_rect, use_software_cursor); r_bounds[0] = bounds_rect.m_l; r_bounds[1] = bounds_rect.m_t; r_bounds[2] = bounds_rect.m_r; r_bounds[3] = bounds_rect.m_b; + *r_use_software_cursor = use_software_cursor; } GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, GHOST_TModifierKeyMask mask, - int *isDown) + bool *r_is_down) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; GHOST_TSuccess result; - bool isdown = false; + bool is_down = false; - result = system->getModifierKeyState(mask, isdown); - *isDown = (int)isdown; + result = system->getModifierKeyState(mask, is_down); + *r_is_down = is_down; return result; } GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle, GHOST_TButtonMask mask, - int *isDown) + bool *r_is_down) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; GHOST_TSuccess result; - bool isdown = false; + bool is_down = false; - result = system->getButtonState(mask, isdown); - *isDown = (int)isdown; + result = system->getButtonState(mask, is_down); + *r_is_down = is_down; return result; } @@ -426,11 +437,11 @@ void GHOST_setNDOFDeadZone(float deadzone) } #endif -void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool canAccept) +void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, bool can_accept) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - window->setAcceptDragOperation(canAccept); + window->setAcceptDragOperation(can_accept); } GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle) @@ -489,11 +500,11 @@ void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, GHOST_TUs timertask->setUserData(userdata); } -int GHOST_GetValid(GHOST_WindowHandle windowhandle) +bool GHOST_GetValid(GHOST_WindowHandle windowhandle) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - return (int)window->getValid(); + return window->getValid(); } GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle) @@ -817,25 +828,26 @@ void GHOST_putClipboard(const char *buffer, bool selection) system->putClipboard(buffer, selection); } -int setConsoleWindowState(GHOST_TConsoleWindowState action) +bool GHOST_setConsoleWindowState(GHOST_TConsoleWindowState action) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); - return system->setConsoleWindowState(action); + /* FIXME: use `bool` instead of int for this value. */ + return (bool)system->setConsoleWindowState(action); } -int GHOST_UseNativePixels(void) +bool GHOST_UseNativePixels(void) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); return system->useNativePixel(); } -int GHOST_SupportsCursorWarp(void) +bool GHOST_SupportsCursorWarp(void) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); return system->supportsCursorWarp(); } -int GHOST_SupportsWindowPosition(void) +bool GHOST_SupportsWindowPosition(void) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); return system->supportsWindowPosition(); @@ -846,7 +858,7 @@ void GHOST_SetBacktraceHandler(GHOST_TBacktraceFn backtrace_fn) GHOST_ISystem::setBacktraceFn(backtrace_fn); } -void GHOST_UseWindowFocus(int use_focus) +void GHOST_UseWindowFocus(bool use_focus) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); return system->useWindowFocus(use_focus); diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp index 72aeebdc876..9f14d56cd9a 100644 --- a/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp @@ -22,5 +22,5 @@ GHOST_CallbackEventConsumer::GHOST_CallbackEventConsumer(GHOST_EventCallbackProc bool GHOST_CallbackEventConsumer::processEvent(GHOST_IEvent *event) { - return m_eventCallback((GHOST_EventHandle)event, m_userData) != 0; + return m_eventCallback((GHOST_EventHandle)event, m_userData); } diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp index baabdc6c521..b4a076e4598 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.cpp +++ b/intern/ghost/intern/GHOST_ContextGLX.cpp @@ -105,7 +105,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store); /* -------------------------------------------------------------------- */ - /* Begin Inline Glew */ + /* Begin Inline GLEW. */ #ifdef USE_GLXEW_INIT_WORKAROUND const GLubyte *extStart = (GLubyte *)""; @@ -142,11 +142,11 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() "GLX_EXT_create_context_es2_profile", extStart, extEnd); # endif /* WITH_GLEW_ES */ - /* End Inline Glew */ + /* End Inline GLEW. */ /* -------------------------------------------------------------------- */ #else - /* important to initialize only glxew (_not_ glew), - * since this breaks w/ Mesa's `swrast`, see: T46431 */ + /* Important to initialize only glxew (_not_ GLEW), + * since this breaks w/ Mesa's `swrast`, see: T46431. */ glxewInit(); #endif /* USE_GLXEW_INIT_WORKAROUND */ @@ -395,7 +395,7 @@ int GHOST_X11_GL_GetAttributes( return i; } -/* excuse inlining part of glew */ +/* Excuse inlining part of GLEW. */ #ifdef USE_GLXEW_INIT_WORKAROUND static GLuint _glewStrLen(const GLubyte *s) { diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp index 70c2eb8c29e..900e46c3732 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.cpp +++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp @@ -31,7 +31,7 @@ int GHOST_DropTargetX11::m_refCounter = 0; #define dndTypePlainText m_dndTypes[dndTypePlainTextID] #define dndTypeOctetStream m_dndTypes[dndTypeOctetStreamID] -void GHOST_DropTargetX11::Initialize(void) +void GHOST_DropTargetX11::Initialize() { Display *display = m_system->getXDisplay(); int dndTypesCount = sizeof(m_dndMimeTypes) / sizeof(char *); @@ -60,7 +60,7 @@ void GHOST_DropTargetX11::Initialize(void) m_dndActions[counter++] = 0; } -void GHOST_DropTargetX11::Uninitialize(void) +void GHOST_DropTargetX11::Uninitialize() { xdnd_shut(&m_dndClass); @@ -98,12 +98,12 @@ GHOST_DropTargetX11::~GHOST_DropTargetX11() /* Based on: https://stackoverflow.com/a/2766963/432509 */ -typedef enum DecodeState_e { +using DecodeState_e = enum DecodeState_e { /** Searching for an ampersand to convert. */ STATE_SEARCH = 0, /** Convert the two proceeding characters from hex. */ STATE_CONVERTING -} DecodeState_e; +}; void GHOST_DropTargetX11::UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn) { @@ -122,7 +122,7 @@ void GHOST_DropTargetX11::UrlDecode(char *decodedOut, int bufferSize, const char case STATE_SEARCH: if (encodedIn[i] != '%') { strncat(decodedOut, &encodedIn[i], 1); - assert(strlen(decodedOut) < bufferSize); + assert((int)strlen(decodedOut) < bufferSize); break; } @@ -145,18 +145,19 @@ void GHOST_DropTargetX11::UrlDecode(char *decodedOut, int bufferSize, const char /* Ensure both characters are hexadecimal */ for (j = 0; j < 2; ++j) { - if (!isxdigit(tempNumBuf[j])) + if (!isxdigit(tempNumBuf[j])) { bothDigits = false; + } } - if (!bothDigits) + if (!bothDigits) { break; - + } /* Convert two hexadecimal characters into one character */ sscanf(tempNumBuf, "%x", &asciiCharacter); /* Ensure we aren't going to overflow */ - assert(strlen(decodedOut) < bufferSize); + assert((int)strlen(decodedOut) < bufferSize); /* Concatenate this character onto the output */ strncat(decodedOut, (char *)&asciiCharacter, 1); diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp index 758938e879e..2620bcc075d 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.cpp +++ b/intern/ghost/intern/GHOST_EventPrinter.cpp @@ -12,7 +12,7 @@ #include "GHOST_EventKey.h" #include <iostream> -#include <stdio.h> +#include <cstdio> bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event) { @@ -20,9 +20,9 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event) GHOST_ASSERT(event, "event==0"); - if (event->getType() == GHOST_kEventWindowUpdate) + if (event->getType() == GHOST_kEventWindowUpdate) { return false; - + } std::cout << "GHOST_EventPrinter::processEvent, time: " << (int32_t)event->getTime() << ", type: "; switch (event->getType()) { @@ -106,8 +106,9 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event) std::cout << " type : GHOST_kDragnDropTypeFilenames,"; std::cout << "\n Received " << strArray->count << " filename" << (strArray->count > 1 ? "s:" : ":"); - for (i = 0; i < strArray->count; i++) + for (i = 0; i < strArray->count; i++) { std::cout << "\n File[" << i << "] : " << strArray->strings[i]; + } } break; default: break; @@ -117,10 +118,12 @@ bool GHOST_EventPrinter::processEvent(GHOST_IEvent *event) case GHOST_kEventOpenMainFile: { GHOST_TEventDataPtr eventData = ((GHOST_IEvent *)event)->getData(); - if (eventData) + if (eventData) { std::cout << "GHOST_kEventOpenMainFile for path : " << (char *)eventData; - else + } + else { std::cout << "GHOST_kEventOpenMainFile with no path specified!!"; + } } break; case GHOST_kEventQuitRequest: @@ -167,7 +170,7 @@ void GHOST_EventPrinter::getKeyString(GHOST_TKey key, char str[32]) const sprintf(str, "F%d", key - GHOST_kKeyF1 + 1); } else { - const char *tstr = NULL; + const char *tstr = nullptr; switch (key) { case GHOST_kKeyBackSpace: tstr = "BackSpace"; diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 7f6b5f53316..2298ba86521 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -6,10 +6,10 @@ #include "GHOST_EventNDOF.h" #include "GHOST_WindowManager.h" -#include <limits.h> -#include <math.h> -#include <stdio.h> /* For error/info reporting. */ -#include <string.h> /* For memory functions. */ +#include <climits> +#include <cmath> +#include <cstdio> /* For error/info reporting. */ +#include <cstring> /* For memory functions. */ #ifdef DEBUG_NDOF_MOTION /* Printable version of each GHOST_TProgress value. */ @@ -255,8 +255,9 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); } - if (m_buttonMask == 0) + if (m_buttonMask == 0) { m_buttonMask = (int)~(UINT_MAX << m_buttonCount); + } #ifdef DEBUG_NDOF_BUTTONS printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp index 7e53ce45f70..7770f5f39ce 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp @@ -32,10 +32,11 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) char line[MAX_LINE_LENGTH] = {0}; while (fgets(line, MAX_LINE_LENGTH, command_output)) { unsigned short vendor_id = 0, product_id = 0; - if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) + if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) { if (setDevice(vendor_id, product_id)) { break; /* stop looking once the first 3D mouse is found */ } + } } pclose(command_output); } @@ -44,8 +45,9 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) GHOST_NDOFManagerUnix::~GHOST_NDOFManagerUnix() { - if (m_available) + if (m_available) { spnav_close(); + } } bool GHOST_NDOFManagerUnix::available() diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index c8308b3586b..cc8d0915c5a 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -158,7 +158,7 @@ GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting &settin return success; } -GHOST_TSuccess GHOST_System::endFullScreen(void) +GHOST_TSuccess GHOST_System::endFullScreen() { GHOST_TSuccess success = GHOST_kFailure; GHOST_ASSERT(m_windowManager, "GHOST_System::endFullScreen(): invalid window manager"); @@ -177,7 +177,7 @@ GHOST_TSuccess GHOST_System::endFullScreen(void) return success; } -bool GHOST_System::getFullScreen(void) +bool GHOST_System::getFullScreen() { bool fullScreen; if (m_windowManager) { @@ -289,7 +289,7 @@ void GHOST_System::setTabletAPI(GHOST_TTabletAPI api) m_tabletAPI = api; } -GHOST_TTabletAPI GHOST_System::getTabletAPI(void) +GHOST_TTabletAPI GHOST_System::getTabletAPI() { return m_tabletAPI; } @@ -319,9 +319,7 @@ GHOST_TSuccess GHOST_System::init() if (m_timerManager && m_windowManager && m_eventManager) { return GHOST_kSuccess; } - else { - return GHOST_kFailure; - } + return GHOST_kFailure; } GHOST_TSuccess GHOST_System::exit() @@ -357,10 +355,12 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, { GHOST_GLSettings glSettings = {0}; - if (stereoVisual) + if (stereoVisual) { glSettings.flags |= GHOST_glStereoVisual; - if (alphaBackground) + } + if (alphaBackground) { glSettings.flags |= GHOST_glAlphaBackground; + } /* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may * be zoomed in and the desktop may be bigger than the viewport. */ diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index d8fbe875f67..33afb5f3155 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -26,15 +26,18 @@ #include <unordered_map> #include <unordered_set> -#include "GHOST_WaylandCursorSettings.h" -#include <pointer-constraints-client-protocol.h> -#include <relative-pointer-client-protocol.h> -#include <tablet-client-protocol.h> #include <wayland-cursor.h> -#include <xdg-output-client-protocol.h> + +#include "GHOST_WaylandCursorSettings.h" #include <xkbcommon/xkbcommon.h> +/* Generated by `wayland-scanner`. */ +#include <pointer-constraints-unstable-v1-client-protocol.h> +#include <relative-pointer-unstable-v1-client-protocol.h> +#include <tablet-unstable-v2-client-protocol.h> +#include <xdg-output-unstable-v1-client-protocol.h> + #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> @@ -44,6 +47,24 @@ static GHOST_WindowWayland *window_from_surface(struct wl_surface *surface); +/** + * GNOME (mutter 42.2 had a bug with confine not respecting scale - Hi-DPI), See: T98793. + * Even though this has been fixed, at time of writing it's not yet in a release. + * Workaround the problem by implementing confine with a software cursor. + * While this isn't ideal, it's not adding a lot of overhead as software + * cursors are already used for warping (which WAYLAND doesn't support). + */ +#define USE_GNOME_CONFINE_HACK +/** + * Always use software confine (not just in GNOME). + * Useful for developing with compositors that don't need this workaround. + */ +// #define USE_GNOME_CONFINE_HACK_ALWAYS_ON + +#ifdef USE_GNOME_CONFINE_HACK +static bool use_gnome_confine_hack = false; +#endif + /* -------------------------------------------------------------------- */ /** \name Private Types & Defines * \{ */ @@ -78,6 +99,14 @@ struct buffer_t { struct cursor_t { bool visible = false; + /** + * When false, hide the hardware cursor, while the cursor is still considered to be `visible`, + * since the grab-mode determines the state of the software cursor, + * this may change - removing the need for a software cursor and in this case it's important + * the hardware cursor is used. + */ + bool is_hardware = true; + bool is_custom = false; struct wl_surface *wl_surface = nullptr; struct wl_buffer *wl_buffer = nullptr; struct wl_cursor_image wl_image = {0}; @@ -87,7 +116,9 @@ struct cursor_t { std::string theme_name; /** Outputs on which the cursor is visible. */ std::unordered_set<const output_t *> outputs; - int scale = 1; + + int theme_scale = 1; + int custom_scale = 1; }; /** @@ -125,6 +156,12 @@ struct key_repeat_payload_t { GHOST_TEventKeyData key_data = {GHOST_kKeyUnknown}; }; +/** Internal variables used to track grab-state. */ +struct input_grab_state_t { + bool use_lock = false; + bool use_confine = false; +}; + struct input_t { GHOST_SystemWayland *system = nullptr; @@ -153,9 +190,14 @@ struct input_t { * wl_fixed_to_int(scale * input->xy[0]), * wl_fixed_to_int(scale * input->xy[1]), * }; - * \endocde + * \endcode */ wl_fixed_t xy[2] = {0, 0}; + +#ifdef USE_GNOME_CONFINE_HACK + bool xy_software_confine = false; +#endif + GHOST_Buttons buttons = GHOST_Buttons(); struct cursor_t cursor; @@ -496,7 +538,7 @@ static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_ta static const int default_cursor_size = 24; -static const std::unordered_map<GHOST_TStandardCursor, std::string> cursors = { +static const std::unordered_map<GHOST_TStandardCursor, const char *> cursors = { {GHOST_kStandardCursorDefault, "left_ptr"}, {GHOST_kStandardCursorRightArrow, "right_ptr"}, {GHOST_kStandardCursorLeftArrow, "left_ptr"}, @@ -590,6 +632,21 @@ static void relative_pointer_handle_relative_motion( input->xy[0] += dx / scale; input->xy[1] += dy / scale; +#ifdef USE_GNOME_CONFINE_HACK + if (input->xy_software_confine) { + GHOST_Rect bounds; + win->getClientBounds(bounds); + /* Needed or the cursor is considered outside the window and doesn't restore the location. */ + bounds.m_r -= 1; + bounds.m_b -= 1; + + bounds.m_l = wl_fixed_from_int(bounds.m_l) / scale; + bounds.m_t = wl_fixed_from_int(bounds.m_t) / scale; + bounds.m_r = wl_fixed_from_int(bounds.m_r) / scale; + bounds.m_b = wl_fixed_from_int(bounds.m_b) / scale; + bounds.clampPoint(input->xy[0], input->xy[1]); + } +#endif input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), GHOST_kEventCursorMove, win, @@ -1039,9 +1096,11 @@ static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm) } } - if (scale > 0 && cursor.scale != scale) { - cursor.scale = scale; - wl_surface_set_buffer_scale(cursor.wl_surface, scale); + if (scale > 0 && cursor.theme_scale != scale) { + cursor.theme_scale = scale; + if (!cursor.is_custom) { + wl_surface_set_buffer_scale(cursor.wl_surface, scale); + } wl_cursor_theme_destroy(cursor.wl_theme); cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm); return true; @@ -1123,12 +1182,13 @@ static void pointer_handle_leave(void *data, uint32_t /*serial*/, struct wl_surface *surface) { + /* First clear the `focus_pointer`, since the window won't exist when closing the window. */ + static_cast<input_t *>(data)->focus_pointer = nullptr; + GHOST_IWindow *win = window_from_surface(surface); if (!win) { return; } - - static_cast<input_t *>(data)->focus_pointer = nullptr; static_cast<GHOST_WindowWayland *>(win)->deactivate(); } @@ -1860,16 +1920,21 @@ static void xdg_output_handle_logical_size(void *data, if (output->size_logical[0] != 0 && output->size_logical[1] != 0) { /* Original comment from SDL. */ - /* FIXME: GNOME has a bug where the logical size does not account for + /* FIXME(@flibit): GNOME has a bug where the logical size does not account for * scale, resulting in bogus viewport sizes. * * Until this is fixed, validate that _some_ kind of scaling is being * done (we can't match exactly because fractional scaling can't be - * detected otherwise), then override if necessary. - * -flibit - */ + * detected otherwise), then override if necessary. */ if ((output->size_logical[0] == width) && (output->scale_fractional == wl_fixed_from_int(1))) { GHOST_PRINT("xdg_output scale did not match, overriding with wl_output scale"); + +#ifdef USE_GNOME_CONFINE_HACK + /* Use a bug in GNOME to check GNOME is in use. If the bug is fixed this won't cause an issue + * as T98793 has been fixed up-stream too, but not in a release at time of writing. */ + use_gnome_confine_hack = true; +#endif + return; } } @@ -1968,7 +2033,7 @@ static void output_handle_done(void *data, struct wl_output * /*wl_output*/) int32_t size_native[2]; if (output->transform & WL_OUTPUT_TRANSFORM_90) { size_native[0] = output->size_native[1]; - size_native[1] = output->size_native[1]; + size_native[1] = output->size_native[0]; } else { size_native[0] = output->size_native[0]; @@ -2317,16 +2382,33 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(int32_t /*x*/, int32_t /*y void GHOST_SystemWayland::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { - if (getNumDisplays() > 0) { - /* We assume first output as main. */ - width = uint32_t(d->outputs[0]->size_native[0]) / d->outputs[0]->scale; - height = uint32_t(d->outputs[0]->size_native[1]) / d->outputs[0]->scale; + if (getNumDisplays() == 0) { + return; } + /* We assume first output as main. */ + width = uint32_t(d->outputs[0]->size_native[0]); + height = uint32_t(d->outputs[0]->size_native[1]); } void GHOST_SystemWayland::getAllDisplayDimensions(uint32_t &width, uint32_t &height) const { - getMainDisplayDimensions(width, height); + int32_t xy_min[2] = {INT32_MAX, INT32_MAX}; + int32_t xy_max[2] = {INT32_MIN, INT32_MIN}; + + for (const output_t *output : d->outputs) { + int32_t xy[2] = {0, 0}; + if (output->has_position_logical) { + xy[0] = output->position_logical[0]; + xy[1] = output->position_logical[1]; + } + xy_min[0] = std::min(xy_min[0], xy[0]); + xy_min[1] = std::min(xy_min[1], xy[1]); + xy_max[0] = std::max(xy_max[0], xy[0] + output->size_native[0]); + xy_max[1] = std::max(xy_max[1], xy[1] + output->size_native[1]); + } + + width = xy_max[0] - xy_min[0]; + height = xy_max[1] - xy_min[1]; } GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*glSettings*/) @@ -2466,47 +2548,152 @@ void GHOST_SystemWayland::setSelection(const std::string &selection) this->selection = selection; } -static void set_cursor_buffer(input_t *input, wl_buffer *buffer) +/** + * Show the buffer defined by #cursor_buffer_set without changing anything else, + * so #cursor_buffer_hide can be used to display it again. + * + * The caller is responsible for setting `input->cursor.visible`. + */ +static void cursor_buffer_show(const input_t *input) +{ + const cursor_t *c = &input->cursor; + const int scale = c->is_custom ? c->custom_scale : c->theme_scale; + const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + wl_pointer_set_cursor( + input->wl_pointer, input->pointer_serial, c->wl_surface, hotspot_x, hotspot_y); + for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { + tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>( + zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); + zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, + input->tablet_serial, + tool_input->cursor_surface, + hotspot_x, + hotspot_y); + } +} + +/** + * Hide the buffer defined by #cursor_buffer_set without changing anything else, + * so #cursor_buffer_show can be used to display it again. + * + * The caller is responsible for setting `input->cursor.visible`. + */ +static void cursor_buffer_hide(const input_t *input) +{ + wl_pointer_set_cursor(input->wl_pointer, input->pointer_serial, nullptr, 0, 0); + for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { + zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, input->tablet_serial, nullptr, 0, 0); + } +} + +static void cursor_buffer_set(const input_t *input, wl_buffer *buffer) { - cursor_t *c = &input->cursor; + const cursor_t *c = &input->cursor; + const int scale = c->is_custom ? c->custom_scale : c->theme_scale; - c->visible = (buffer != nullptr); + const bool visible = (c->visible && c->is_hardware); const int32_t image_size_x = int32_t(c->wl_image.width); const int32_t image_size_y = int32_t(c->wl_image.height); - const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / c->scale; - const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / c->scale; + /* This is a requirement of WAYLAND, when this isn't the case, + * it causes Blender's window to close intermittently. */ + GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0, + "The size must be a multiple of the scale!"); + const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + + wl_surface_set_buffer_scale(c->wl_surface, scale); wl_surface_attach(c->wl_surface, buffer, 0, 0); wl_surface_damage(c->wl_surface, 0, 0, image_size_x, image_size_y); + wl_surface_commit(c->wl_surface); wl_pointer_set_cursor(input->wl_pointer, input->pointer_serial, - c->visible ? c->wl_surface : nullptr, + visible ? c->wl_surface : nullptr, hotspot_x, hotspot_y); - wl_surface_commit(c->wl_surface); - /* Set the cursor for all tablet tools as well. */ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>( zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); + /* FIXME: for some reason cursor scale is applied twice (when the scale isn't 1x), * this happens both in gnome-shell & KDE. Setting the surface scale here doesn't help. */ - // wl_surface_set_buffer_scale(tool_input->cursor_surface, 1); + wl_surface_set_buffer_scale(tool_input->cursor_surface, scale); wl_surface_attach(tool_input->cursor_surface, buffer, 0, 0); wl_surface_damage(tool_input->cursor_surface, 0, 0, image_size_x, image_size_y); + wl_surface_commit(tool_input->cursor_surface); zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, input->tablet_serial, - c->visible ? tool_input->cursor_surface : nullptr, + visible ? tool_input->cursor_surface : nullptr, hotspot_x, hotspot_y); + } +} - wl_surface_commit(tool_input->cursor_surface); +enum eCursorSetMode { + CURSOR_VISIBLE_ALWAYS_SET = 1, + CURSOR_VISIBLE_ONLY_HIDE, + CURSOR_VISIBLE_ONLY_SHOW, +}; + +static void cursor_visible_set(input_t *input, + const bool visible, + const bool is_hardware, + const enum eCursorSetMode set_mode) +{ + cursor_t *cursor = &input->cursor; + const bool was_visible = cursor->is_hardware && cursor->visible; + const bool use_visible = is_hardware && visible; + + if (set_mode == CURSOR_VISIBLE_ALWAYS_SET) { + /* Pass. */ + } + else if ((set_mode == CURSOR_VISIBLE_ONLY_SHOW)) { + if (!use_visible) { + return; + } + } + else if ((set_mode == CURSOR_VISIBLE_ONLY_HIDE)) { + if (use_visible) { + return; + } + } + + if (use_visible) { + if (!was_visible) { + cursor_buffer_show(input); + } + } + else { + if (was_visible) { + cursor_buffer_hide(input); + } + } + cursor->visible = visible; + cursor->is_hardware = is_hardware; +} + +static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_software_confine) +{ + if (mode == GHOST_kGrabWrap) { + return true; + } +#ifdef USE_GNOME_CONFINE_HACK + if (mode == GHOST_kGrabNormal) { + if (use_software_confine) { + return true; + } } +#else + (void)use_software_confine; +#endif + return false; } GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) @@ -2514,8 +2701,10 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) if (d->inputs.empty()) { return GHOST_kFailure; } - const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) : - cursors.at(GHOST_kStandardCursorDefault); + auto cursor_find = cursors.find(shape); + const char *cursor_name = (cursor_find == cursors.end()) ? + cursors.at(GHOST_kStandardCursorDefault) : + (*cursor_find).second; input_t *input = d->inputs[0]; cursor_t *c = &input->cursor; @@ -2526,7 +2715,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) c->theme_name.c_str(), c->size, d->inputs[0]->system->shm()); } - wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name.c_str()); + wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name); if (!cursor) { GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl); @@ -2539,17 +2728,27 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) return GHOST_kFailure; } + c->visible = true; + c->is_custom = false; c->wl_buffer = buffer; c->wl_image = *image; - set_cursor_buffer(input, buffer); + cursor_buffer_set(input, buffer); return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(GHOST_TStandardCursor cursorShape) { - return GHOST_TSuccess(cursors.count(cursorShape) && !cursors.at(cursorShape).empty()); + auto cursor_find = cursors.find(cursorShape); + if (cursor_find == cursors.end()) { + return GHOST_kFailure; + } + const char *value = (*cursor_find).second; + if (*value == '\0') { + return GHOST_kFailure; + } + return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, @@ -2602,6 +2801,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (cursor->file_buffer->data == MAP_FAILED) { + cursor->file_buffer->data = nullptr; close(fd); return GHOST_kFailure; } @@ -2646,37 +2846,49 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, } } + cursor->visible = true; + cursor->is_custom = true; + cursor->custom_scale = 1; /* TODO: support Hi-DPI custom cursors. */ cursor->wl_buffer = buffer; cursor->wl_image.width = uint32_t(sizex); cursor->wl_image.height = uint32_t(sizey); cursor->wl_image.hotspot_x = uint32_t(hotX); cursor->wl_image.hotspot_y = uint32_t(hotY); - set_cursor_buffer(d->inputs[0], buffer); + cursor_buffer_set(d->inputs[0], buffer); return GHOST_kSuccess; } -GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) +GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap) { - if (d->inputs.empty()) { + cursor_t *cursor = &d->inputs[0]->cursor; + if (cursor->file_buffer->data == nullptr) { + return GHOST_kFailure; + } + if (!cursor->is_custom) { return GHOST_kFailure; } - input_t *input = d->inputs[0]; + bitmap->data_size[0] = cursor->wl_image.width; + bitmap->data_size[1] = cursor->wl_image.height; - cursor_t *cursor = &input->cursor; - if (visible) { - if (!cursor->visible) { - set_cursor_buffer(input, cursor->wl_buffer); - } - } - else { - if (cursor->visible) { - set_cursor_buffer(input, nullptr); - } + bitmap->hot_spot[0] = cursor->wl_image.hotspot_x; + bitmap->hot_spot[1] = cursor->wl_image.hotspot_y; + + bitmap->data = (uint8_t *)static_cast<void *>(cursor->file_buffer->data); + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; } + input_t *input = d->inputs[0]; + cursor_visible_set(input, visible, input->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET); return GHOST_kSuccess; } @@ -2693,6 +2905,60 @@ bool GHOST_SystemWayland::supportsWindowPosition() return false; } +bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode) +{ + if (d->inputs.empty()) { + return false; + } + +#ifdef USE_GNOME_CONFINE_HACK + input_t *input = d->inputs[0]; + const bool use_software_confine = input->xy_software_confine; +#else + const bool use_software_confine = false; +#endif + + return cursor_is_software(mode, use_software_confine); +} + +#ifdef USE_GNOME_CONFINE_HACK +static bool setCursorGrab_use_software_confine(const GHOST_TGrabCursorMode mode, + wl_surface *surface) +{ +# ifndef USE_GNOME_CONFINE_HACK_ALWAYS_ON + if (use_gnome_confine_hack == false) { + return false; + } +# endif + if (mode != GHOST_kGrabNormal) { + return false; + } + GHOST_WindowWayland *win = window_from_surface(surface); + if (!win) { + return false; + } + +# ifndef USE_GNOME_CONFINE_HACK_ALWAYS_ON + if (win->scale() <= 1) { + return false; + } +# endif + return true; +} +#endif + +static input_grab_state_t input_grab_state_from_mode(const GHOST_TGrabCursorMode mode, + const bool use_software_confine) +{ + /* Initialize all members. */ + const struct input_grab_state_t grab_state = { + /* Warping happens to require software cursor which also hides. */ + .use_lock = (mode == GHOST_kGrabWrap || mode == GHOST_kGrabHide) || use_software_confine, + .use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false), + }; + return grab_state; +} + GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode, const GHOST_TGrabCursorMode mode_current, wl_surface *surface) @@ -2705,7 +2971,6 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo if (d->inputs.empty()) { return GHOST_kFailure; } - /* No change, success. */ if (mode == mode_current) { return GHOST_kSuccess; @@ -2713,32 +2978,33 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo input_t *input = d->inputs[0]; -#define MODE_NEEDS_LOCK(m) ((m) == GHOST_kGrabWrap || (m) == GHOST_kGrabHide) -#define MODE_NEEDS_HIDE(m) ((m) == GHOST_kGrabHide) -#define MODE_NEEDS_CONFINE(m) ((m) == GHOST_kGrabNormal) +#ifdef USE_GNOME_CONFINE_HACK + const bool was_software_confine = input->xy_software_confine; + const bool use_software_confine = setCursorGrab_use_software_confine(mode, surface); +#else + const bool was_software_confine = false; + const bool use_software_confine = false; +#endif - const bool was_lock = MODE_NEEDS_LOCK(mode_current); - const bool use_lock = MODE_NEEDS_LOCK(mode); + const struct input_grab_state_t grab_state_prev = input_grab_state_from_mode( + mode_current, was_software_confine); + const struct input_grab_state_t grab_state_next = input_grab_state_from_mode( + mode, use_software_confine); /* Check for wrap as #supportsCursorWarp isn't supported. */ - const bool was_hide = MODE_NEEDS_HIDE(mode_current) || (mode_current == GHOST_kGrabWrap); - const bool use_hide = MODE_NEEDS_HIDE(mode) || (mode == GHOST_kGrabWrap); + const bool use_visible = !(((mode == GHOST_kGrabHide) || (mode == GHOST_kGrabWrap)) || + use_software_confine); - const bool was_confine = MODE_NEEDS_CONFINE(mode_current); - const bool use_confine = MODE_NEEDS_CONFINE(mode); + const bool is_hardware_cursor = !cursor_is_software(mode, use_software_confine); -#undef MODE_NEEDS_LOCK -#undef MODE_NEEDS_HIDE -#undef MODE_NEEDS_CONFINE - - if (!use_hide) { - setCursorVisibility(true); - } + /* Only hide so the cursor is not made visible before it's location is restored. + * This function is called again at the end of this function which only shows. */ + cursor_visible_set(input, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_HIDE); /* Switching from one grab mode to another, * in this case disable the current locks as it makes logic confusing, * postpone changing the cursor to avoid flickering. */ - if (!use_lock) { + if (!grab_state_next.use_lock) { if (input->relative_pointer) { zwp_relative_pointer_v1_destroy(input->relative_pointer); input->relative_pointer = nullptr; @@ -2786,13 +3052,22 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo wl_surface_commit(surface); } } +#ifdef USE_GNOME_CONFINE_HACK + else if (mode_current == GHOST_kGrabNormal) { + if (was_software_confine) { + zwp_locked_pointer_v1_set_cursor_position_hint( + input->locked_pointer, input->xy[0], input->xy[1]); + wl_surface_commit(surface); + } + } +#endif zwp_locked_pointer_v1_destroy(input->locked_pointer); input->locked_pointer = nullptr; } } - if (!use_confine) { + if (!grab_state_next.use_confine) { if (input->confined_pointer) { zwp_confined_pointer_v1_destroy(input->confined_pointer); input->confined_pointer = nullptr; @@ -2800,8 +3075,8 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo } if (mode != GHOST_kGrabDisable) { - if (use_lock) { - if (!was_lock) { + if (grab_state_next.use_lock) { + if (!grab_state_prev.use_lock) { /* TODO(@campbellbarton): As WAYLAND does not support warping the pointer it may not be * possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates. * An alternative could be to draw the cursor in software (and hide the real cursor), @@ -2818,8 +3093,8 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); } } - else if (use_confine) { - if (!was_confine) { + else if (grab_state_next.use_confine) { + if (!grab_state_prev.use_confine) { input->confined_pointer = zwp_pointer_constraints_v1_confine_pointer( d->pointer_constraints, surface, @@ -2828,12 +3103,15 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); } } - - if (use_hide && !was_hide) { - setCursorVisibility(false); - } } + /* Only show so the cursor is made visible as the last step. */ + cursor_visible_set(input, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_SHOW); + +#ifdef USE_GNOME_CONFINE_HACK + input->xy_software_confine = use_software_confine; +#endif + return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 762ceb80e38..4b953dccac6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -12,7 +12,9 @@ #include "GHOST_WindowWayland.h" #include <wayland-client.h> -#include <xdg-decoration-client-protocol.h> + +/* Generated by `wayland-scanner`. */ +#include <xdg-decoration-unstable-v1-client-protocol.h> #include <xdg-shell-client-protocol.h> #include <string> @@ -32,6 +34,7 @@ struct output_t { int32_t size_logical[2] = {0, 0}; bool has_size_logical = false; + /** Monitor position in pixels. */ int32_t position_logical[2] = {0, 0}; bool has_position_logical = false; @@ -122,11 +125,15 @@ class GHOST_SystemWayland : public GHOST_System { int hotY, bool canInvertColor); + GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap); + GHOST_TSuccess setCursorVisibility(bool visible); bool supportsCursorWarp(); bool supportsWindowPosition(); + bool getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode); + GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode, const GHOST_TGrabCursorMode mode_current, wl_surface *surface); diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index e93a56cc8d4..bed9cd6c784 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -506,8 +506,9 @@ static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/) { GHOST_PRINT("XIM server died\n"); - if (ptr) + if (ptr) { *(XIM *)ptr = nullptr; + } } bool GHOST_SystemX11::openX11_IM() @@ -519,8 +520,9 @@ bool GHOST_SystemX11::openX11_IM() XSetLocaleModifiers(""); m_xim = XOpenIM(m_display, nullptr, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS); - if (!m_xim) + if (!m_xim) { return false; + } XIMCallback destroy; destroy.callback = (XIMProc)destroyIMCallback; @@ -641,10 +643,11 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent) SleepTillEvent(m_display, -1); } else { - int64_t maxSleep = next - getMilliSeconds(); + const int64_t maxSleep = next - getMilliSeconds(); - if (maxSleep >= 0) + if (maxSleep >= 0) { SleepTillEvent(m_display, next - getMilliSeconds()); + } } } @@ -692,8 +695,9 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent) } else if (xevent.type == KeyPress) { if ((xevent.xkey.keycode == m_last_release_keycode) && - ((xevent.xkey.time <= m_last_release_time))) + ((xevent.xkey.time <= m_last_release_time))) { continue; + } } processEvent(&xevent); @@ -733,7 +737,7 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent) XK_Super_R, }; - for (int i = 0; i < (sizeof(modifiers) / sizeof(*modifiers)); i++) { + for (int i = 0; i < (int)(sizeof(modifiers) / sizeof(*modifiers)); i++) { KeyCode kc = XKeysymToKeycode(m_display, modifiers[i]); if (kc != 0 && ((xevent.xkeymap.key_vector[kc >> 3] >> (kc & 7)) & 1) != 0) { pushEvent(new GHOST_EventKey(getMilliSeconds(), @@ -1233,36 +1237,46 @@ void GHOST_SystemX11::processEvent(XEvent *xe) /* process wheel mouse events and break, only pass on press events */ if (xbe.button == Button4) { - if (xbe.type == ButtonPress) + if (xbe.type == ButtonPress) { g_event = new GHOST_EventWheel(getMilliSeconds(), window, 1); + } break; } - else if (xbe.button == Button5) { - if (xbe.type == ButtonPress) + if (xbe.button == Button5) { + if (xbe.type == ButtonPress) { g_event = new GHOST_EventWheel(getMilliSeconds(), window, -1); + } break; } /* process rest of normal mouse buttons */ - if (xbe.button == Button1) + if (xbe.button == Button1) { gbmask = GHOST_kButtonMaskLeft; - else if (xbe.button == Button2) + } + else if (xbe.button == Button2) { gbmask = GHOST_kButtonMaskMiddle; - else if (xbe.button == Button3) + } + else if (xbe.button == Button3) { gbmask = GHOST_kButtonMaskRight; - /* It seems events 6 and 7 are for horizontal scrolling. - * you can re-order button mapping like this... (swaps 6,7 with 8,9) - * `xmodmap -e "pointer = 1 2 3 4 5 8 9 6 7"` */ - else if (xbe.button == 6) + /* It seems events 6 and 7 are for horizontal scrolling. + * you can re-order button mapping like this... (swaps 6,7 with 8,9) + * `xmodmap -e "pointer = 1 2 3 4 5 8 9 6 7"` */ + } + else if (xbe.button == 6) { gbmask = GHOST_kButtonMaskButton6; - else if (xbe.button == 7) + } + else if (xbe.button == 7) { gbmask = GHOST_kButtonMaskButton7; - else if (xbe.button == 8) + } + else if (xbe.button == 8) { gbmask = GHOST_kButtonMaskButton4; - else if (xbe.button == 9) + } + else if (xbe.button == 9) { gbmask = GHOST_kButtonMaskButton5; - else + } + else { break; + } g_event = new GHOST_EventButton( getMilliSeconds(), type, window, gbmask, window->GetTabletData()); @@ -1326,8 +1340,9 @@ void GHOST_SystemX11::processEvent(XEvent *xe) if (XGetWindowAttributes(m_display, xcme.window, &attr) == True) { if (XGetInputFocus(m_display, &fwin, &revert_to) == True) { if (attr.map_state == IsViewable) { - if (fwin != xcme.window) + if (fwin != xcme.window) { XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]); + } } } } @@ -1376,10 +1391,12 @@ void GHOST_SystemX11::processEvent(XEvent *xe) // printf("X: %s window %d\n", // xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window); - if (xce.type == EnterNotify) + if (xce.type == EnterNotify) { m_windowManager->setActiveWindow(window); - else + } + else { m_windowManager->setWindowInactive(window); + } break; } @@ -1645,10 +1662,10 @@ static GHOST_TSuccess getCursorPosition_impl(Display *display, &mask_return) == False) { return GHOST_kFailure; } - else { - x = rx; - y = ry; - } + + x = rx; + y = ry; + return GHOST_kSuccess; } @@ -1955,18 +1972,19 @@ void GHOST_SystemX11::getClipboard_xcout(const XEvent *evt, return; case XCLIB_XCOUT_SENTCONVSEL: - if (evt->type != SelectionNotify) + if (evt->type != SelectionNotify) { return; + } if (target == m_atom.UTF8_STRING && evt->xselection.property == None) { *context = XCLIB_XCOUT_FALLBACK_UTF8; return; } - else if (target == m_atom.COMPOUND_TEXT && evt->xselection.property == None) { + if (target == m_atom.COMPOUND_TEXT && evt->xselection.property == None) { *context = XCLIB_XCOUT_FALLBACK_COMP; return; } - else if (target == m_atom.TEXT && evt->xselection.property == None) { + if (target == m_atom.TEXT && evt->xselection.property == None) { *context = XCLIB_XCOUT_FALLBACK_TEXT; return; } @@ -2042,12 +2060,14 @@ void GHOST_SystemX11::getClipboard_xcout(const XEvent *evt, * then read it, delete it, etc. */ /* make sure that the event is relevant */ - if (evt->type != PropertyNotify) + if (evt->type != PropertyNotify) { return; + } /* skip unless the property has a new value */ - if (evt->xproperty.state != PropertyNewValue) + if (evt->xproperty.state != PropertyNewValue) { return; + } /* check size and format of the property */ XGetWindowProperty(m_display, @@ -2121,7 +2141,6 @@ void GHOST_SystemX11::getClipboard_xcout(const XEvent *evt, XFlush(m_display); return; } - return; } char *GHOST_SystemX11::getClipboard(bool selection) const @@ -2136,10 +2155,12 @@ char *GHOST_SystemX11::getClipboard(bool selection) const XEvent evt; unsigned int context = XCLIB_XCOUT_NONE; - if (selection == True) + if (selection == True) { sseln = m_atom.PRIMARY; - else + } + else { sseln = m_atom.CLIPBOARD; + } const vector<GHOST_IWindow *> &win_vec = m_windowManager->getWindows(); vector<GHOST_IWindow *>::const_iterator win_it = win_vec.begin(); @@ -2154,20 +2175,18 @@ char *GHOST_SystemX11::getClipboard(bool selection) const strcpy(sel_buf, txt_cut_buffer); return sel_buf; } - else { - sel_buf = (char *)malloc(strlen(txt_select_buffer) + 1); - strcpy(sel_buf, txt_select_buffer); - return sel_buf; - } + sel_buf = (char *)malloc(strlen(txt_select_buffer) + 1); + strcpy(sel_buf, txt_select_buffer); + return sel_buf; } - else if (owner == None) { + if (owner == None) { return nullptr; } /* Restore events so copy doesn't swallow other event types (keyboard/mouse). */ vector<XEvent> restore_events; - while (1) { + while (true) { /* only get an event if xcout() is doing something */ bool restore_this_event = false; if (context != XCLIB_XCOUT_NONE) { @@ -2188,26 +2207,27 @@ char *GHOST_SystemX11::getClipboard(bool selection) const target = m_atom.STRING; continue; } - else if (context == XCLIB_XCOUT_FALLBACK_UTF8) { + if (context == XCLIB_XCOUT_FALLBACK_UTF8) { /* utf8 fail, move to compound text. */ context = XCLIB_XCOUT_NONE; target = m_atom.COMPOUND_TEXT; continue; } - else if (context == XCLIB_XCOUT_FALLBACK_COMP) { + if (context == XCLIB_XCOUT_FALLBACK_COMP) { /* Compound text fail, move to text. */ context = XCLIB_XCOUT_NONE; target = m_atom.TEXT; continue; } - else if (context == XCLIB_XCOUT_FALLBACK_TEXT) { + if (context == XCLIB_XCOUT_FALLBACK_TEXT) { /* Text fail, nothing else to try, break. */ context = XCLIB_XCOUT_NONE; } /* Only continue if #xcout() is doing something. */ - if (context == XCLIB_XCOUT_NONE) + if (context == XCLIB_XCOUT_NONE) { break; + } } while (!restore_events.empty()) { @@ -2221,10 +2241,12 @@ char *GHOST_SystemX11::getClipboard(bool selection) const memcpy(tmp_data, (char *)sel_buf, sel_len); tmp_data[sel_len] = '\0'; - if (sseln == m_atom.STRING) + if (sseln == m_atom.STRING) { XFree(sel_buf); - else + } + else { free(sel_buf); + } return tmp_data; } @@ -2244,8 +2266,9 @@ void GHOST_SystemX11::putClipboard(const char *buffer, bool selection) const if (selection == False) { XSetSelectionOwner(m_display, m_atom.CLIPBOARD, m_window, CurrentTime); owner = XGetSelectionOwner(m_display, m_atom.CLIPBOARD); - if (txt_cut_buffer) + if (txt_cut_buffer) { free((void *)txt_cut_buffer); + } txt_cut_buffer = (char *)malloc(strlen(buffer) + 1); strcpy(txt_cut_buffer, buffer); @@ -2253,15 +2276,17 @@ void GHOST_SystemX11::putClipboard(const char *buffer, bool selection) const else { XSetSelectionOwner(m_display, m_atom.PRIMARY, m_window, CurrentTime); owner = XGetSelectionOwner(m_display, m_atom.PRIMARY); - if (txt_select_buffer) + if (txt_select_buffer) { free((void *)txt_select_buffer); + } txt_select_buffer = (char *)malloc(strlen(buffer) + 1); strcpy(txt_select_buffer, buffer); } - if (owner != m_window) + if (owner != m_window) { fprintf(stderr, "failed to own primary\n"); + } } } @@ -2374,7 +2399,7 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title, const char *help_label, const char *continue_label, const char *link, - GHOST_DialogOptions) const + GHOST_DialogOptions /*dialog_options*/) const { char **text_splitted = nullptr; int textLines = 0; @@ -2557,18 +2582,23 @@ static bool match_token(const char *haystack, const char *needle) { const char *h, *n; for (h = haystack; *h;) { - while (*h && is_filler_char(*h)) + while (*h && is_filler_char(*h)) { h++; - if (!*h) + } + if (!*h) { break; + } - for (n = needle; *n && *h && tolower(*h) == tolower(*n); n++) + for (n = needle; *n && *h && tolower(*h) == tolower(*n); n++) { h++; - if (!*n && (is_filler_char(*h) || !*h)) + } + if (!*n && (is_filler_char(*h) || !*h)) { return true; + } - while (*h && !is_filler_char(*h)) + while (*h && !is_filler_char(*h)) { h++; + } } return false; } diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index de7c5422d3f..3f093840d0c 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -164,7 +164,8 @@ GHOST_TSuccess GHOST_Window::getCursorGrabBounds(GHOST_Rect &bounds) void GHOST_Window::getCursorGrabState(GHOST_TGrabCursorMode &mode, GHOST_TAxisFlag &wrap_axis, - GHOST_Rect &bounds) + GHOST_Rect &bounds, + bool &use_software_cursor) { mode = m_cursorGrab; if (m_cursorGrab == GHOST_kGrabWrap) { @@ -178,6 +179,14 @@ void GHOST_Window::getCursorGrabState(GHOST_TGrabCursorMode &mode, bounds.m_b = -1; wrap_axis = GHOST_kGrabAxisNone; } + use_software_cursor = (m_cursorGrab != GHOST_kGrabDisable) ? getCursorGrabUseSoftwareDisplay() : + false; +} + +bool GHOST_Window::getCursorGrabUseSoftwareDisplay() +{ + /* Sub-classes may override, by default don't use software cursor. */ + return false; } GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape) @@ -199,6 +208,12 @@ GHOST_TSuccess GHOST_Window::setCustomCursorShape( return GHOST_kFailure; } +GHOST_TSuccess GHOST_Window::getCursorBitmap(GHOST_CursorBitmapRef * /*bitmap*/) +{ + /* Sub-classes may override. */ + return GHOST_kFailure; +} + void GHOST_Window::setAcceptDragOperation(bool canAccept) { m_canAcceptDragOperation = canAccept; diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index adbc29eb84e..5ff91c05b16 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -117,6 +117,8 @@ class GHOST_Window : public GHOST_IWindow { int hotY, bool canInvertColor); + GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap); + /** * Returns the visibility state of the cursor. * \return The visibility state of the cursor. @@ -154,7 +156,12 @@ class GHOST_Window : public GHOST_IWindow { void getCursorGrabState(GHOST_TGrabCursorMode &mode, GHOST_TAxisFlag &axis_flag, - GHOST_Rect &bounds); + GHOST_Rect &bounds, + bool &use_software_cursor); + /** + * Return true when a software cursor should be used. + */ + bool getCursorGrabUseSoftwareDisplay(); /** * Sets the progress bar value displayed in the window/application icon diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 21e3793d3b1..941e08ff035 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -492,12 +492,22 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor s return ok; } +bool GHOST_WindowWayland::getCursorGrabUseSoftwareDisplay() +{ + return m_system->getCursorGrabUseSoftwareDisplay(m_cursorGrab); +} + GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape( uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) { return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor); } +GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap) +{ + return m_system->getCursorBitmap(bitmap); +} + void GHOST_WindowWayland::setTitle(const char *title) { xdg_toplevel_set_title(w->xdg_toplevel, title); diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index b6d9fa04079..89354c54c0f 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -10,7 +10,6 @@ #include "GHOST_Window.h" -#include <unordered_set> #include <vector> class GHOST_SystemWayland; @@ -52,6 +51,9 @@ class GHOST_WindowWayland : public GHOST_Window { int hotX, int hotY, bool canInvertColor) override; + bool getCursorGrabUseSoftwareDisplay() override; + + GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap) override; void setTitle(const char *title) override; diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp index 587b1124848..0e725bf4075 100644 --- a/intern/ghost/intern/GHOST_XrAction.cpp +++ b/intern/ghost/intern/GHOST_XrAction.cpp @@ -332,23 +332,26 @@ void GHOST_XrAction::updateState(XrSession session, break; } case GHOST_kXrActionTypePoseInput: { - XrActionStatePose state{XR_TYPE_ACTION_STATE_POSE}; - CHECK_XR( - xrGetActionStatePose(session, &state_info, &state), - (std::string("Failed to get state for pose action \"") + action_name + "\".").data()); - if (state.isActive) { - XrSpace pose_space = ((subaction != nullptr) && (subaction->space != nullptr)) ? - subaction->space->getSpace() : - XR_NULL_HANDLE; - if (pose_space != XR_NULL_HANDLE) { - XrSpaceLocation space_location{XR_TYPE_SPACE_LOCATION}; - CHECK_XR( - xrLocateSpace( - pose_space, reference_space, predicted_display_time, &space_location), - (std::string("Failed to query pose space for action \"") + action_name + "\".") - .data()); - copy_openxr_pose_to_ghost_pose(space_location.pose, - ((GHOST_XrPose *)m_states)[subaction_idx]); + /* Check for valid display time to avoid an error in #xrLocateSpace(). */ + if (predicted_display_time > 0) { + XrActionStatePose state{XR_TYPE_ACTION_STATE_POSE}; + CHECK_XR(xrGetActionStatePose(session, &state_info, &state), + (std::string("Failed to get state for pose action \"") + action_name + "\".") + .data()); + if (state.isActive) { + XrSpace pose_space = ((subaction != nullptr) && (subaction->space != nullptr)) ? + subaction->space->getSpace() : + XR_NULL_HANDLE; + if (pose_space != XR_NULL_HANDLE) { + XrSpaceLocation space_location{XR_TYPE_SPACE_LOCATION}; + CHECK_XR( + xrLocateSpace( + pose_space, reference_space, predicted_display_time, &space_location), + (std::string("Failed to query pose space for action \"") + action_name + "\".") + .data()); + copy_openxr_pose_to_ghost_pose(space_location.pose, + ((GHOST_XrPose *)m_states)[subaction_idx]); + } } } break; diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c index 71f3a6f43b4..46c8fda0665 100644 --- a/intern/ghost/test/gears/GHOST_C-Test.c +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -31,7 +31,7 @@ #endif /* defined(WIN32) || defined(__APPLE__) */ static void gearsTimerProc(GHOST_TimerTaskHandle task, uint64_t time); -int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData); +bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData); static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; static GLfloat fAngle = 0.0; @@ -269,9 +269,9 @@ static void setViewPortGL(GHOST_WindowHandle hWindow) GHOST_DisposeRectangle(hRect); } -int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData) +bool processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData) { - int handled = 1; + bool handled = true; int cursor; int visibility; GHOST_TEventKeyData *keyData = NULL; @@ -389,10 +389,10 @@ int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData) } break; case GHOST_kEventWindowActivate: - handled = 0; + handled = false; break; case GHOST_kEventWindowDeactivate: - handled = 0; + handled = false; break; case GHOST_kEventWindowUpdate: { GHOST_WindowHandle window2 = GHOST_GetEventWindow(hEvent); @@ -404,7 +404,7 @@ int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData) } break; default: - handled = 0; + handled = false; break; } return handled; diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index 35b1de65171..157e4f1b0f2 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -812,7 +812,7 @@ struct _MultiTestApp { int exit; }; -static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr data) +static bool multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr data) { MultiTestApp *app = data; GHOST_WindowHandle win; @@ -820,7 +820,7 @@ static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr dat win = GHOST_GetEventWindow(evt); if (win && !GHOST_ValidWindow(app->sys, win)) { loggerwindow_log(app->logger, "WARNING: bad event, non-valid window\n"); - return 1; + return true; } if (win) { @@ -845,7 +845,7 @@ static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr dat } } - return 1; + return true; } /**/ diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 915744ad8e255d1723d77671a6c6b074773c219 +Subproject 9a85b13795157560b319235c63f5a13b0107ba4 diff --git a/release/scripts/addons b/release/scripts/addons -Subproject c51e0bb1793c44c7a1b7435593dd5022cf7c8ee +Subproject bdf75cb276dfd3b5266c909de4c099c00c68a65 diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py index 9896bd3e281..cfce84f84e3 100644 --- a/release/scripts/modules/rna_manual_reference.py +++ b/release/scripts/modules/rna_manual_reference.py @@ -189,6 +189,7 @@ url_manual_mapping = ( ("bpy.types.rendersettings_simplify_gpencil_view_fill*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-view-fill"), ("bpy.types.sequencertoolsettings.snap_to_hold_offset*", "video_editing/edit/montage/editing.html#bpy-types-sequencertoolsettings-snap-to-hold-offset"), ("bpy.types.toolsettings.use_mesh_automerge_and_split*", "modeling/meshes/tools/tool_settings.html#bpy-types-toolsettings-use-mesh-automerge-and-split"), + ("bpy.ops.scene.view_layer_remove_unused_lightgroups*", "render/layers/passes.html#bpy-ops-scene-view-layer-remove-unused-lightgroups"), ("bpy.types.animvizmotionpaths.show_keyframe_numbers*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-show-keyframe-numbers"), ("bpy.types.brush.cloth_constraint_softbody_strength*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-constraint-softbody-strength"), ("bpy.types.brush.elastic_deform_volume_preservation*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-volume-preservation"), @@ -302,11 +303,13 @@ url_manual_mapping = ( ("bpy.types.rigidbodyconstraint.breaking_threshold*", "physics/rigid_body/constraints/introduction.html#bpy-types-rigidbodyconstraint-breaking-threshold"), ("bpy.types.spaceclipeditor.use_manual_calibration*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-use-manual-calibration"), ("bpy.types.spacedopesheeteditor.show_pose_markers*", "animation/markers.html#bpy-types-spacedopesheeteditor-show-pose-markers"), + ("bpy.types.spaceimageoverlay.show_grid_background*", "editors/uv/overlays.html#bpy-types-spaceimageoverlay-show-grid-background"), + ("bpy.types.spacenodeoverlay.show_named_attributes*", "modeling/geometry_nodes/inspection.html#bpy-types-spacenodeoverlay-show-named-attributes"), ("bpy.types.spaceoutliner.use_filter_object_camera*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-object-camera"), ("bpy.types.spaceoutliner.use_filter_object_others*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-object-others"), ("bpy.types.spacesequenceeditor.overlay_frame_type*", "editors/video_sequencer/preview/sidebar.html#bpy-types-spacesequenceeditor-overlay-frame-type"), ("bpy.types.spacesequenceeditor.show_strip_overlay*", "editors/video_sequencer/sequencer/display.html#bpy-types-spacesequenceeditor-show-strip-overlay"), - ("bpy.types.spaceuveditor.custom_grid_subdivisions*", "editors/uv/sidebar.html#bpy-types-spaceuveditor-custom-grid-subdivisions"), + ("bpy.types.spaceuveditor.custom_grid_subdivisions*", "editors/uv/overlays.html#bpy-types-spaceuveditor-custom-grid-subdivisions"), ("bpy.types.toolsettings.proportional_edit_falloff*", "editors/3dview/controls/proportional_editing.html#bpy-types-toolsettings-proportional-edit-falloff"), ("bpy.types.toolsettings.use_edge_path_live_unwrap*", "modeling/meshes/tools/tool_settings.html#bpy-types-toolsettings-use-edge-path-live-unwrap"), ("bpy.types.toolsettings.use_gpencil_draw_additive*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-draw-additive"), @@ -388,6 +391,7 @@ url_manual_mapping = ( ("bpy.types.geometrynodecurvehandletypeselection*", "modeling/geometry_nodes/curve/handle_type_selection.html#bpy-types-geometrynodecurvehandletypeselection"), ("bpy.types.geometrynodeinputmeshvertexneighbors*", "modeling/geometry_nodes/mesh/vertex_neighbors.html#bpy-types-geometrynodeinputmeshvertexneighbors"), ("bpy.types.greasepencil.curve_edit_corner_angle*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-corner-angle"), + ("bpy.types.imageformatsettings.color_management*", "render/output/properties/output.html#bpy-types-imageformatsettings-color-management"), ("bpy.types.lineartgpencilmodifier.source_camera*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-source-camera"), ("bpy.types.lineartgpencilmodifier.use_face_mark*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-face-mark"), ("bpy.types.linestylegeometrymodifier_tipremover*", "render/freestyle/view_layer/line_style/modifiers/geometry/tip_remover.html#bpy-types-linestylegeometrymodifier-tipremover"), @@ -404,6 +408,7 @@ url_manual_mapping = ( ("bpy.types.viewlayer.use_pass_cryptomatte_asset*", "render/layers/passes.html#bpy-types-viewlayer-use-pass-cryptomatte-asset"), ("bpy.ops.outliner.collection_indirect_only_set*", "render/layers/introduction.html#bpy-ops-outliner-collection-indirect-only-set"), ("bpy.ops.scene.freestyle_geometry_modifier_add*", "render/freestyle/view_layer/line_style/geometry.html#bpy-ops-scene-freestyle-geometry-modifier-add"), + ("bpy.ops.scene.view_layer_add_used_lightgroups*", "render/layers/passes.html#bpy-ops-scene-view-layer-add-used-lightgroups"), ("bpy.ops.sequencer.deinterlace_selected_movies*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-deinterlace-selected-movies"), ("bpy.types.bakesettings.use_selected_to_active*", "render/cycles/baking.html#bpy-types-bakesettings-use-selected-to-active"), ("bpy.types.brush.surface_smooth_current_vertex*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-current-vertex"), @@ -420,6 +425,7 @@ url_manual_mapping = ( ("bpy.types.cyclesworldsettings.sampling_method*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings-sampling-method"), ("bpy.types.cyclesworldsettings.volume_sampling*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings-volume-sampling"), ("bpy.types.editbone.bbone_handle_use_scale_end*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-handle-use-scale-end"), + ("bpy.types.ffmpegsettings.constant_rate_factor*", "render/output/properties/output.html#bpy-types-ffmpegsettings-constant-rate-factor"), ("bpy.types.fluiddomainsettings.adapt_threshold*", "physics/fluid/type/domain/gas/adaptive_domain.html#bpy-types-fluiddomainsettings-adapt-threshold"), ("bpy.types.fluiddomainsettings.cache_directory*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-cache-directory"), ("bpy.types.fluiddomainsettings.cache_frame_end*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-cache-frame-end"), @@ -510,12 +516,14 @@ url_manual_mapping = ( ("bpy.types.spaceclipeditor.show_green_channel*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-green-channel"), ("bpy.types.spacenodeoverlay.show_context_path*", "interface/controls/nodes/introduction.html#bpy-types-spacenodeoverlay-show-context-path"), ("bpy.types.spaceoutliner.show_restrict_column*", "editors/outliner/interface.html#bpy-types-spaceoutliner-show-restrict-column"), + ("bpy.types.spacesequenceeditor.use_clamp_view*", "editors/video_sequencer/sequencer/navigating.html#bpy-types-spacesequenceeditor-use-clamp-view"), ("bpy.types.spacespreadsheet.object_eval_state*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-object-eval-state"), ("bpy.types.spaceuveditor.display_stretch_type*", "editors/uv/overlays.html#bpy-types-spaceuveditor-display-stretch-type"), ("bpy.types.toolsettings.transform_pivot_point*", "editors/3dview/controls/pivot_point/index.html#bpy-types-toolsettings-transform-pivot-point"), ("bpy.types.toolsettings.use_proportional_edit*", "editors/3dview/controls/proportional_editing.html#bpy-types-toolsettings-use-proportional-edit"), ("bpy.types.toolsettings.uv_sticky_select_mode*", "editors/uv/selecting.html#bpy-types-toolsettings-uv-sticky-select-mode"), ("bpy.types.volumedisplay.interpolation_method*", "modeling/volumes/properties.html#bpy-types-volumedisplay-interpolation-method"), + ("bpy.ops.geometry.color_attribute_render_set*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-render-set"), ("bpy.types.brushgpencilsettings.angle_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-angle-factor"), ("bpy.types.brushgpencilsettings.pen_strength*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-pen-strength"), ("bpy.types.clothsettings.use_pressure_volume*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-use-pressure-volume"), @@ -538,6 +546,7 @@ url_manual_mapping = ( ("bpy.types.freestylelinestyle.use_length_max*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-max"), ("bpy.types.freestylelinestyle.use_length_min*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-min"), ("bpy.types.geometrynodeinputmeshedgevertices*", "modeling/geometry_nodes/mesh/edge_vertices.html#bpy-types-geometrynodeinputmeshedgevertices"), + ("bpy.types.geometrynodeinputmeshfaceisplanar*", "modeling/geometry_nodes/mesh/face_is_planar.html#bpy-types-geometrynodeinputmeshfaceisplanar"), ("bpy.types.geometrynodeinputsplineresolution*", "modeling/geometry_nodes/curve/spline_resolution.html#bpy-types-geometrynodeinputsplineresolution"), ("bpy.types.greasepencil.curve_edit_threshold*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-threshold"), ("bpy.types.materialgpencilstyle.stroke_style*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-stroke-style"), @@ -561,11 +570,14 @@ url_manual_mapping = ( ("bpy.types.toolsettings.use_snap_peel_object*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-peel-object"), ("bpy.types.view3doverlay.fade_inactive_alpha*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-fade-inactive-alpha"), ("bpy.types.view3doverlay.wireframe_threshold*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-wireframe-threshold"), + ("bpy.types.viewlayer.active_lightgroup_index*", "render/layers/passes.html#bpy-types-viewlayer-active-lightgroup-index"), + ("bpy.ops.ed.lib_id_override_editable_toggle*", "editors/outliner/interface.html#bpy-ops-ed-lib-id-override-editable-toggle"), ("bpy.ops.object.constraint_add_with_targets*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraint-add-with-targets"), ("bpy.ops.object.material_slot_remove_unused*", "scene_layout/object/editing/cleanup.html#bpy-ops-object-material-slot-remove-unused"), ("bpy.ops.outliner.collection_disable_render*", "editors/outliner/editing.html#bpy-ops-outliner-collection-disable-render"), ("bpy.ops.scene.freestyle_alpha_modifier_add*", "render/freestyle/view_layer/line_style/alpha.html#bpy-ops-scene-freestyle-alpha-modifier-add"), ("bpy.ops.scene.freestyle_color_modifier_add*", "render/freestyle/view_layer/line_style/color.html#bpy-ops-scene-freestyle-color-modifier-add"), + ("bpy.ops.scene.view_layer_remove_lightgroup*", "render/layers/passes.html#bpy-ops-scene-view-layer-remove-lightgroup"), ("bpy.types.brush.cloth_simulation_area_type*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-simulation-area-type"), ("bpy.types.brushgpencilsettings.eraser_mode*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-eraser-mode"), ("bpy.types.brushgpencilsettings.fill_factor*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-factor"), @@ -599,6 +611,7 @@ url_manual_mapping = ( ("bpy.types.freestylesettings.use_smoothness*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-smoothness"), ("bpy.types.geometrynodecurveprimitivecircle*", "modeling/geometry_nodes/curve_primitives/curve_circle.html#bpy-types-geometrynodecurveprimitivecircle"), ("bpy.types.geometrynodecurvequadraticbezier*", "modeling/geometry_nodes/curve_primitives/quadratic_bezier.html#bpy-types-geometrynodecurvequadraticbezier"), + ("bpy.types.geometrynoderemovenamedattribute*", "modeling/geometry_nodes/attribute/remove_named_attribute.html#bpy-types-geometrynoderemovenamedattribute"), ("bpy.types.gpencillayer.use_viewlayer_masks*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-viewlayer-masks"), ("bpy.types.greasepencil.onion_keyframe_type*", "grease_pencil/properties/onion_skinning.html#bpy-types-greasepencil-onion-keyframe-type"), ("bpy.types.lineartgpencilmodifier.use_cache*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-cache"), @@ -642,6 +655,7 @@ url_manual_mapping = ( ("bpy.types.cyclesrendersettings.time_limit*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-time-limit"), ("bpy.types.cyclesvisibilitysettings.camera*", "render/cycles/world_settings.html#bpy-types-cyclesvisibilitysettings-camera"), ("bpy.types.cyclesworldsettings.max_bounces*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings-max-bounces"), + ("bpy.types.ffmpegsettings.use_max_b_frames*", "render/output/properties/output.html#bpy-types-ffmpegsettings-use-max-b-frames"), ("bpy.types.fluiddomainsettings.domain_type*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-domain-type"), ("bpy.types.fluiddomainsettings.flame_smoke*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-flame-smoke"), ("bpy.types.fluiddomainsettings.fluid_group*", "physics/fluid/type/domain/collections.html#bpy-types-fluiddomainsettings-fluid-group"), @@ -657,6 +671,7 @@ url_manual_mapping = ( ("bpy.types.freestylesettings.sphere_radius*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-sphere-radius"), ("bpy.types.geometrynodeattributedomainsize*", "modeling/geometry_nodes/attribute/domain_size.html#bpy-types-geometrynodeattributedomainsize"), ("bpy.types.geometrynodesetsplineresolution*", "modeling/geometry_nodes/curve/set_spline_resolution.html#bpy-types-geometrynodesetsplineresolution"), + ("bpy.types.geometrynodestorenamedattribute*", "modeling/geometry_nodes/attribute/store_named_attribute.html#bpy-types-geometrynodestorenamedattribute"), ("bpy.types.gpencillayer.annotation_opacity*", "interface/annotate_tool.html#bpy-types-gpencillayer-annotation-opacity"), ("bpy.types.gpencillayer.use_onion_skinning*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-onion-skinning"), ("bpy.types.gpencilsculptguide.use_snapping*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-use-snapping"), @@ -747,6 +762,8 @@ url_manual_mapping = ( ("bpy.types.linestyle*modifier_alongstroke*", "render/freestyle/view_layer/line_style/modifiers/color/along_stroke.html#bpy-types-linestyle-modifier-alongstroke"), ("bpy.types.linestyle*modifier_creaseangle*", "render/freestyle/view_layer/line_style/modifiers/color/crease_angle.html#bpy-types-linestyle-modifier-creaseangle"), ("bpy.types.linestylecolormodifier_tangent*", "render/freestyle/view_layer/line_style/modifiers/color/tangent.html#bpy-types-linestylecolormodifier-tangent"), + ("bpy.types.material.show_transparent_back*", "render/eevee/materials/settings.html#bpy-types-material-show-transparent-back"), + ("bpy.types.material.use_screen_refraction*", "render/eevee/materials/settings.html#bpy-types-material-use-screen-refraction"), ("bpy.types.materialgpencilstyle.mix_color*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-mix-color"), ("bpy.types.materialgpencilstyle.show_fill*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-show-fill"), ("bpy.types.mesh.use_customdata_edge_bevel*", "modeling/meshes/properties/custom_data.html#bpy-types-mesh-use-customdata-edge-bevel"), @@ -774,6 +791,7 @@ url_manual_mapping = ( ("bpy.types.volumedisplay.wireframe_detail*", "modeling/volumes/properties.html#bpy-types-volumedisplay-wireframe-detail"), ("bpy.types.windowmanager.asset_path_dummy*", "editors/asset_browser.html#bpy-types-windowmanager-asset-path-dummy"), ("bpy.ops.armature.rigify_add_bone_groups*", "addons/rigging/rigify/metarigs.html#bpy-ops-armature-rigify-add-bone-groups"), + ("bpy.ops.geometry.color_attribute_remove*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-remove"), ("bpy.ops.object.assign_property_defaults*", "animation/armatures/posing/editing/apply.html#bpy-ops-object-assign-property-defaults"), ("bpy.ops.object.vertex_group_limit_total*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-limit-total"), ("bpy.ops.object.vertex_group_remove_from*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-remove-from"), @@ -783,6 +801,7 @@ url_manual_mapping = ( ("bpy.ops.outliner.collection_show_inside*", "editors/outliner/editing.html#bpy-ops-outliner-collection-show-inside"), ("bpy.ops.poselib.restore_previous_action*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-restore-previous-action"), ("bpy.ops.preferences.reset_default_theme*", "editors/preferences/themes.html#bpy-ops-preferences-reset-default-theme"), + ("bpy.ops.scene.view_layer_add_lightgroup*", "render/layers/passes.html#bpy-ops-scene-view-layer-add-lightgroup"), ("bpy.ops.sequencer.strip_transform_clear*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-strip-transform-clear"), ("bpy.ops.spreadsheet.add_row_filter_rule*", "editors/spreadsheet.html#bpy-ops-spreadsheet-add-row-filter-rule"), ("bpy.types.animdata.action_extrapolation*", "editors/nla/sidebar.html#bpy-types-animdata-action-extrapolation"), @@ -800,6 +819,7 @@ url_manual_mapping = ( ("bpy.types.cyclesrendersettings.caustics*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-caustics"), ("bpy.types.cyclesrendersettings.denoiser*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-denoiser"), ("bpy.types.editbone.use_inherit_rotation*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-use-inherit-rotation"), + ("bpy.types.ffmpegsettings.audio_channels*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-channels"), ("bpy.types.fileselectparams.display_size*", "editors/file_browser.html#bpy-types-fileselectparams-display-size"), ("bpy.types.fileselectparams.display_type*", "editors/file_browser.html#bpy-types-fileselectparams-display-type"), ("bpy.types.fluiddomainsettings.use_guide*", "physics/fluid/type/domain/guides.html#bpy-types-fluiddomainsettings-use-guide"), @@ -818,12 +838,14 @@ url_manual_mapping = ( ("bpy.types.freestylelinestyle.split_dash*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-split-dash"), ("bpy.types.freestylesettings.use_culling*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-culling"), ("bpy.types.geometrynodeattributetransfer*", "modeling/geometry_nodes/attribute/transfer_attribute.html#bpy-types-geometrynodeattributetransfer"), + ("bpy.types.geometrynodeduplicateelements*", "modeling/geometry_nodes/geometry/duplicate_elements.html#bpy-types-geometrynodeduplicateelements"), ("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/face_area.html#bpy-types-geometrynodeinputmeshfacearea"), ("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"), ("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"), ("bpy.types.gpencillayer.viewlayer_render*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-viewlayer-render"), ("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"), ("bpy.types.layercollection.indirect_only*", "editors/outliner/interface.html#bpy-types-layercollection-indirect-only"), + ("bpy.types.material.use_backface_culling*", "render/eevee/materials/settings.html#bpy-types-material-use-backface-culling"), ("bpy.types.material.use_sss_translucency*", "render/eevee/materials/settings.html#bpy-types-material-use-sss-translucency"), ("bpy.types.materiallineart.mat_occlusion*", "render/materials/line_art.html#bpy-types-materiallineart-mat-occlusion"), ("bpy.types.movietrackingcamera.principal*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-principal"), @@ -841,7 +863,8 @@ url_manual_mapping = ( ("bpy.types.spacetexteditor.margin_column*", "editors/text_editor.html#bpy-types-spacetexteditor-margin-column"), ("bpy.types.spacetexteditor.use_find_wrap*", "editors/text_editor.html#bpy-types-spacetexteditor-use-find-wrap"), ("bpy.types.spaceuveditor.pixel_snap_mode*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-pixel-snap-mode"), - ("bpy.types.spaceuveditor.use_custom_grid*", "editors/uv/sidebar.html#bpy-types-spaceuveditor-use-custom-grid"), + ("bpy.types.spaceuveditor.tile_grid_shape*", "editors/uv/overlays.html#bpy-types-spaceuveditor-tile-grid-shape"), + ("bpy.types.spaceuveditor.use_custom_grid*", "editors/uv/overlays.html#bpy-types-spaceuveditor-use-custom-grid"), ("bpy.types.spaceuveditor.use_live_unwrap*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-use-live-unwrap"), ("bpy.types.toolsettings.double_threshold*", "modeling/meshes/tools/tool_settings.html#bpy-types-toolsettings-double-threshold"), ("bpy.types.toolsettings.lock_object_mode*", "interface/window_system/topbar.html#bpy-types-toolsettings-lock-object-mode"), @@ -870,6 +893,11 @@ url_manual_mapping = ( ("bpy.types.compositornodedoubleedgemask*", "compositing/types/matte/double_edge_mask.html#bpy-types-compositornodedoubleedgemask"), ("bpy.types.cyclesrendersettings.samples*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-samples"), ("bpy.types.dopesheet.show_only_selected*", "editors/dope_sheet/introduction.html#bpy-types-dopesheet-show-only-selected"), + ("bpy.types.ffmpegsettings.audio_bitrate*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-bitrate"), + ("bpy.types.ffmpegsettings.audio_mixrate*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-mixrate"), + ("bpy.types.ffmpegsettings.ffmpeg_preset*", "render/output/properties/output.html#bpy-types-ffmpegsettings-ffmpeg-preset"), + ("bpy.types.ffmpegsettings.use_autosplit*", "render/output/properties/output.html#bpy-types-ffmpegsettings-use-autosplit"), + ("bpy.types.ffmpegsettings.video_bitrate*", "render/output/properties/output.html#bpy-types-ffmpegsettings-video-bitrate"), ("bpy.types.fileselectparams.show_hidden*", "editors/file_browser.html#bpy-types-fileselectparams-show-hidden"), ("bpy.types.fileselectparams.sort_method*", "editors/file_browser.html#bpy-types-fileselectparams-sort-method"), ("bpy.types.fluiddomainsettings.clipping*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-clipping"), @@ -898,10 +926,14 @@ url_manual_mapping = ( ("bpy.types.rendersettings.use_sequencer*", "render/output/properties/post_processing.html#bpy-types-rendersettings-use-sequencer"), ("bpy.types.sceneeevee.volumetric_shadow*", "render/eevee/render_settings/volumetrics.html#bpy-types-sceneeevee-volumetric-shadow"), ("bpy.types.sequenceeditor.overlay_frame*", "editors/video_sequencer/preview/sidebar.html#bpy-types-sequenceeditor-overlay-frame"), + ("bpy.types.sequencetimelinechannel.lock*", "editors/video_sequencer/sequencer/channels.html#bpy-types-sequencetimelinechannel-lock"), + ("bpy.types.sequencetimelinechannel.mute*", "editors/video_sequencer/sequencer/channels.html#bpy-types-sequencetimelinechannel-mute"), + ("bpy.types.sequencetimelinechannel.name*", "editors/video_sequencer/sequencer/channels.html#bpy-types-sequencetimelinechannel-name"), ("bpy.types.shadernodebsdfhairprincipled*", "render/shader_nodes/shader/hair_principled.html#bpy-types-shadernodebsdfhairprincipled"), ("bpy.types.shadernodevectordisplacement*", "render/shader_nodes/vector/vector_displacement.html#bpy-types-shadernodevectordisplacement"), ("bpy.types.spacegrapheditor.show_cursor*", "editors/graph_editor/introduction.html#bpy-types-spacegrapheditor-show-cursor"), ("bpy.types.spaceimageeditor.show_repeat*", "editors/image/sidebar.html#bpy-types-spaceimageeditor-show-repeat"), + ("bpy.types.spacenodeoverlay.show_timing*", "modeling/geometry_nodes/inspection.html#bpy-types-spacenodeoverlay-show-timing"), ("bpy.types.spaceoutliner.use_sort_alpha*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-sort-alpha"), ("bpy.types.spacepreferences.filter_text*", "editors/preferences/keymap.html#bpy-types-spacepreferences-filter-text"), ("bpy.types.spacepreferences.filter_type*", "editors/preferences/keymap.html#bpy-types-spacepreferences-filter-type"), @@ -934,6 +966,7 @@ url_manual_mapping = ( ("bpy.types.bakesettings.cage_extrusion*", "render/cycles/baking.html#bpy-types-bakesettings-cage-extrusion"), ("bpy.types.bakesettings.use_pass_color*", "render/cycles/baking.html#bpy-types-bakesettings-use-pass-color"), ("bpy.types.brush.boundary_falloff_type*", "sculpt_paint/sculpting/tools/boundary.html#bpy-types-brush-boundary-falloff-type"), + ("bpy.types.brush.cursor_color_subtract*", "sculpt_paint/brush/cursor.html#bpy-types-brush-cursor-color-subtract"), ("bpy.types.brush.texture_overlay_alpha*", "sculpt_paint/brush/cursor.html#bpy-types-brush-texture-overlay-alpha"), ("bpy.types.brushgpencilsettings.aspect*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-aspect"), ("bpy.types.brushgpencilsettings.dilate*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-dilate"), @@ -947,6 +980,8 @@ url_manual_mapping = ( ("bpy.types.compositornodesetalpha.mode*", "compositing/types/converter/set_alpha.html#bpy-types-compositornodesetalpha-mode"), ("bpy.types.dopesheet.use_filter_invert*", "editors/graph_editor/channels.html#bpy-types-dopesheet-use-filter-invert"), ("bpy.types.editbone.use_local_location*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-use-local-location"), + ("bpy.types.ffmpegsettings.audio_volume*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-volume"), + ("bpy.types.ffmpegsettings.max_b_frames*", "render/output/properties/output.html#bpy-types-ffmpegsettings-max-b-frames"), ("bpy.types.fileselectparams.use_filter*", "editors/file_browser.html#bpy-types-fileselectparams-use-filter"), ("bpy.types.fluiddomainsettings.gravity*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-gravity"), ("bpy.types.fluidflowsettings.flow_type*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-flow-type"), @@ -1001,6 +1036,7 @@ url_manual_mapping = ( ("bpy.ops.anim.channels_fcurves_enable*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-fcurves-enable"), ("bpy.ops.anim.channels_setting_toggle*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-setting-toggle"), ("bpy.ops.clip.set_viewport_background*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-set-viewport-background"), + ("bpy.ops.geometry.color_attribute_add*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-add"), ("bpy.ops.gpencil.interpolate_sequence*", "grease_pencil/animation/tools.html#bpy-ops-gpencil-interpolate-sequence"), ("bpy.ops.mesh.normals_make_consistent*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-mesh-normals-make-consistent"), ("bpy.ops.mesh.offset_edge_loops_slide*", "modeling/meshes/editing/edge/offset_edge_slide.html#bpy-ops-mesh-offset-edge-loops-slide"), @@ -1031,6 +1067,7 @@ url_manual_mapping = ( ("bpy.types.compositornodecolorbalance*", "compositing/types/color/color_balance.html#bpy-types-compositornodecolorbalance"), ("bpy.types.compositornodekeyingscreen*", "compositing/types/matte/keying_screen.html#bpy-types-compositornodekeyingscreen"), ("bpy.types.dynamicpaintcanvassettings*", "physics/dynamic_paint/canvas.html#bpy-types-dynamicpaintcanvassettings"), + ("bpy.types.ffmpegsettings.audio_codec*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-codec"), ("bpy.types.fileselectparams.directory*", "editors/file_browser.html#bpy-types-fileselectparams-directory"), ("bpy.types.fluidflowsettings.use_flow*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-flow"), ("bpy.types.fmodifierfunctiongenerator*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierfunctiongenerator"), @@ -1038,6 +1075,7 @@ url_manual_mapping = ( ("bpy.types.geometrynodedeletegeometry*", "modeling/geometry_nodes/geometry/delete_geometry.html#bpy-types-geometrynodedeletegeometry"), ("bpy.types.geometrynodeinputcurvetilt*", "modeling/geometry_nodes/curve/curve_tilt.html#bpy-types-geometrynodeinputcurvetilt"), ("bpy.types.geometrynodeinputscenetime*", "modeling/geometry_nodes/input/scene_time.html#bpy-types-geometrynodeinputscenetime"), + ("bpy.types.geometrynodenamedattribute*", "modeling/geometry_nodes/input/named_attribute.html#bpy-types-geometrynodenamedattribute"), ("bpy.types.geometrynodepointstovolume*", "modeling/geometry_nodes/point/points_to_volume.html#bpy-types-geometrynodepointstovolume"), ("bpy.types.geometrynodescaleinstances*", "modeling/geometry_nodes/instances/scale_instances.html#bpy-types-geometrynodescaleinstances"), ("bpy.types.geometrynodesetcurveradius*", "modeling/geometry_nodes/curve/set_curve_radius.html#bpy-types-geometrynodesetcurveradius"), @@ -1067,6 +1105,7 @@ url_manual_mapping = ( ("bpy.types.spaceuveditor.show_stretch*", "editors/uv/overlays.html#bpy-types-spaceuveditor-show-stretch"), ("bpy.types.toolsettings.keyframe_type*", "editors/timeline.html#bpy-types-toolsettings-keyframe-type"), ("bpy.types.toolsettings.snap_elements*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-snap-elements"), + ("bpy.types.toolsettings.use_snap_node*", "interface/controls/nodes/arranging.html#bpy-types-toolsettings-use-snap-node"), ("bpy.types.toolsettings.use_snap_self*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-self"), ("bpy.types.viewlayer.active_aov_index*", "render/layers/passes.html#bpy-types-viewlayer-active-aov-index"), ("bpy.ops.anim.channels_enable_toggle*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-enable-toggle"), @@ -1086,6 +1125,7 @@ url_manual_mapping = ( ("bpy.ops.object.material_slot_assign*", "render/materials/assignment.html#bpy-ops-object-material-slot-assign"), ("bpy.ops.object.material_slot_select*", "render/materials/assignment.html#bpy-ops-object-material-slot-select"), ("bpy.ops.object.multires_unsubdivide*", "modeling/modifiers/generate/multiresolution.html#bpy-ops-object-multires-unsubdivide"), + ("bpy.ops.object.parent_inverse_apply*", "scene_layout/object/editing/apply.html#bpy-ops-object-parent-inverse-apply"), ("bpy.ops.object.paths_update_visible*", "animation/motion_paths.html#bpy-ops-object-paths-update-visible"), ("bpy.ops.object.transforms_to_deltas*", "scene_layout/object/editing/apply.html#bpy-ops-object-transforms-to-deltas"), ("bpy.ops.outliner.collection_disable*", "editors/outliner/editing.html#bpy-ops-outliner-collection-disable"), @@ -1116,6 +1156,8 @@ url_manual_mapping = ( ("bpy.types.cyclesrendersettings.seed*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-seed"), ("bpy.types.dynamicpaintbrushsettings*", "physics/dynamic_paint/brush.html#bpy-types-dynamicpaintbrushsettings"), ("bpy.types.editbone.use_scale_easing*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-use-scale-easing"), + ("bpy.types.ffmpegsettings.buffersize*", "render/output/properties/output.html#bpy-types-ffmpegsettings-buffersize"), + ("bpy.types.ffmpegsettings.packetsize*", "render/output/properties/output.html#bpy-types-ffmpegsettings-packetsize"), ("bpy.types.fileselectparams.filename*", "editors/file_browser.html#bpy-types-fileselectparams-filename"), ("bpy.types.fluiddomainsettings.alpha*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-alpha"), ("bpy.types.fluidflowsettings.density*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-density"), @@ -1135,6 +1177,7 @@ url_manual_mapping = ( ("bpy.types.greasepencil.pixel_factor*", "grease_pencil/properties/strokes.html#bpy-types-greasepencil-pixel-factor"), ("bpy.types.keyframe.handle_left_type*", "editors/graph_editor/fcurves/properties.html#bpy-types-keyframe-handle-left-type"), ("bpy.types.light.use_custom_distance*", "render/eevee/lighting.html#bpy-types-light-use-custom-distance"), + ("bpy.types.material.refraction_depth*", "render/eevee/materials/settings.html#bpy-types-material-refraction-depth"), ("bpy.types.materialgpencilstyle.flip*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-flip"), ("bpy.types.materialgpencilstyle.mode*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-mode"), ("bpy.types.meshsequencecachemodifier*", "modeling/modifiers/modify/mesh_sequence_cache.html#bpy-types-meshsequencecachemodifier"), @@ -1197,6 +1240,7 @@ url_manual_mapping = ( ("bpy.ops.sequencer.export_subtitles*", "editors/video_sequencer/preview/header.html#bpy-ops-sequencer-export-subtitles"), ("bpy.ops.transform.edge_bevelweight*", "modeling/meshes/editing/edge/edge_data.html#bpy-ops-transform-edge-bevelweight"), ("bpy.ops.wm.previews_batch_generate*", "files/blend/previews.html#bpy-ops-wm-previews-batch-generate"), + ("bpy.types.animvizmotionpaths.range*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-range"), ("bpy.types.assetmetadata.active_tag*", "editors/asset_browser.html#bpy-types-assetmetadata-active-tag"), ("bpy.types.bakesettings.cage_object*", "render/cycles/baking.html#bpy-types-bakesettings-cage-object"), ("bpy.types.bakesettings.margin_type*", "render/cycles/baking.html#bpy-types-bakesettings-margin-type"), @@ -1243,6 +1287,7 @@ url_manual_mapping = ( ("bpy.types.imagepaint.interpolation*", "sculpt_paint/texture_paint/tool_settings/texture_slots.html#bpy-types-imagepaint-interpolation"), ("bpy.types.linestyle*modifier_noise*", "render/freestyle/view_layer/line_style/modifiers/color/noise.html#bpy-types-linestyle-modifier-noise"), ("bpy.types.maintainvolumeconstraint*", "animation/constraints/transform/maintain_volume.html#bpy-types-maintainvolumeconstraint"), + ("bpy.types.material.alpha_threshold*", "render/eevee/materials/settings.html#bpy-types-material-alpha-threshold"), ("bpy.types.mesh.use_mirror_topology*", "modeling/meshes/tools/tool_settings.html#bpy-types-mesh-use-mirror-topology"), ("bpy.types.movieclip.display_aspect*", "editors/clip/display/clip_display.html#bpy-types-movieclip-display-aspect"), ("bpy.types.nodesocketinterface.name*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-name"), @@ -1251,6 +1296,7 @@ url_manual_mapping = ( ("bpy.types.rendersettings.hair_type*", "render/eevee/render_settings/hair.html#bpy-types-rendersettings-hair-type"), ("bpy.types.rendersettings.tile_size*", "render/cycles/render_settings/performance.html#bpy-types-rendersettings-tile-size"), ("bpy.types.sequencertimelineoverlay*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay"), + ("bpy.types.sequencetransform.filter*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequencetransform-filter"), ("bpy.types.sequencetransform.offset*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequencetransform-offset"), ("bpy.types.shadernodebrightcontrast*", "render/shader_nodes/color/bright_contrast.html#bpy-types-shadernodebrightcontrast"), ("bpy.types.shadernodebsdfprincipled*", "render/shader_nodes/shader/principled.html#bpy-types-shadernodebsdfprincipled"), @@ -1368,6 +1414,7 @@ url_manual_mapping = ( ("bpy.types.rigidbodyobject.enabled*", "physics/rigid_body/properties/settings.html#bpy-types-rigidbodyobject-enabled"), ("bpy.types.sceneeevee.use_overscan*", "render/eevee/render_settings/film.html#bpy-types-sceneeevee-use-overscan"), ("bpy.types.sequencerpreviewoverlay*", "editors/video_sequencer/preview/display/overlays.html#bpy-types-sequencerpreviewoverlay"), + ("bpy.types.sequencetimelinechannel*", "editors/video_sequencer/sequencer/channels.html#bpy-types-sequencetimelinechannel"), ("bpy.types.sequencetransform.scale*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequencetransform-scale"), ("bpy.types.shadernodeeeveespecular*", "render/shader_nodes/shader/specular_bsdf.html#bpy-types-shadernodeeeveespecular"), ("bpy.types.shadernodehuesaturation*", "render/shader_nodes/color/hue_saturation.html#bpy-types-shadernodehuesaturation"), @@ -1453,6 +1500,10 @@ url_manual_mapping = ( ("bpy.types.editbone.bbone_rollout*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-rollout"), ("bpy.types.editbone.bbone_scalein*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-scalein"), ("bpy.types.editbone.inherit_scale*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-inherit-scale"), + ("bpy.types.ffmpegsettings.gopsize*", "render/output/properties/output.html#bpy-types-ffmpegsettings-gopsize"), + ("bpy.types.ffmpegsettings.maxrate*", "render/output/properties/output.html#bpy-types-ffmpegsettings-maxrate"), + ("bpy.types.ffmpegsettings.minrate*", "render/output/properties/output.html#bpy-types-ffmpegsettings-minrate"), + ("bpy.types.ffmpegsettings.muxrate*", "render/output/properties/output.html#bpy-types-ffmpegsettings-muxrate"), ("bpy.types.freestylelinestyle.gap*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-gap"), ("bpy.types.freestylesettings.mode*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-mode"), ("bpy.types.functionnodefloattoint*", "modeling/geometry_nodes/utilities/float_to_integer.html#bpy-types-functionnodefloattoint"), @@ -1472,7 +1523,9 @@ url_manual_mapping = ( ("bpy.types.keyframe.interpolation*", "editors/graph_editor/fcurves/properties.html#bpy-types-keyframe-interpolation"), ("bpy.types.latticegpencilmodifier*", "grease_pencil/modifiers/deform/lattice.html#bpy-types-latticegpencilmodifier"), ("bpy.types.lineartgpencilmodifier*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier"), + ("bpy.types.material.diffuse_color*", "render/materials/settings.html#bpy-types-material-diffuse-color"), ("bpy.types.material.line_priority*", "render/freestyle/material.html#bpy-types-material-line-priority"), + ("bpy.types.material.shadow_method*", "render/eevee/materials/settings.html#bpy-types-material-shadow-method"), ("bpy.types.mesh.auto_smooth_angle*", "modeling/meshes/structure.html#bpy-types-mesh-auto-smooth-angle"), ("bpy.types.modifier.show_viewport*", "modeling/modifiers/introduction.html#bpy-types-modifier-show-viewport"), ("bpy.types.motionpath.frame_start*", "animation/motion_paths.html#bpy-types-motionpath-frame-start"), @@ -1516,6 +1569,7 @@ url_manual_mapping = ( ("bpy.ops.graph.snap_cursor_value*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-snap-cursor-value"), ("bpy.ops.image.save_all_modified*", "editors/image/editing.html#bpy-ops-image-save-all-modified"), ("bpy.ops.marker.make_links_scene*", "animation/markers.html#bpy-ops-marker-make-links-scene"), + ("bpy.ops.marker.select_leftright*", "animation/markers.html#bpy-ops-marker-select-leftright"), ("bpy.ops.mesh.extrude_edges_move*", "modeling/meshes/editing/edge/extrude_edges.html#bpy-ops-mesh-extrude-edges-move"), ("bpy.ops.mesh.extrude_faces_move*", "modeling/meshes/editing/face/extrude_individual_faces.html#bpy-ops-mesh-extrude-faces-move"), ("bpy.ops.mesh.faces_shade_smooth*", "modeling/meshes/editing/face/shading.html#bpy-ops-mesh-faces-shade-smooth"), @@ -1551,6 +1605,7 @@ url_manual_mapping = ( ("bpy.ops.transform.rotate_normal*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-transform-rotate-normal"), ("bpy.ops.transform.shrink_fatten*", "modeling/meshes/editing/mesh/transform/shrink-fatten.html#bpy-ops-transform-shrink-fatten"), ("bpy.ops.transform.vertex_random*", "modeling/meshes/editing/mesh/transform/randomize.html#bpy-ops-transform-vertex-random"), + ("bpy.ops.ui.reset_default_button*", "interface/controls/buttons/menus.html#bpy-ops-ui-reset-default-button"), ("bpy.ops.uv.shortest_path_select*", "editors/uv/selecting.html#bpy-ops-uv-shortest-path-select"), ("bpy.ops.wm.operator_cheat_sheet*", "advanced/operators.html#bpy-ops-wm-operator-cheat-sheet"), ("bpy.ops.wm.previews_batch_clear*", "files/blend/previews.html#bpy-ops-wm-previews-batch-clear"), @@ -1583,6 +1638,7 @@ url_manual_mapping = ( ("bpy.types.editbone.bbone_easein*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-easein"), ("bpy.types.editbone.bbone_rollin*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-rollin"), ("bpy.types.fcurve.auto_smoothing*", "editors/graph_editor/fcurves/properties.html#bpy-types-fcurve-auto-smoothing"), + ("bpy.types.ffmpegsettings.format*", "render/output/properties/output.html#bpy-types-ffmpegsettings-format"), ("bpy.types.fluideffectorsettings*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings"), ("bpy.types.followtrackconstraint*", "animation/constraints/motion_tracking/follow_track.html#bpy-types-followtrackconstraint"), ("bpy.types.functionnodeinputbool*", "modeling/geometry_nodes/input/boolean.html#bpy-types-functionnodeinputbool"), @@ -1639,6 +1695,7 @@ url_manual_mapping = ( ("bpy.ops.geometry.attribute_add*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-geometry-attribute-add"), ("bpy.ops.gpencil.duplicate_move*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-duplicate-move"), ("bpy.ops.gpencil.stroke_arrange*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-arrange"), + ("bpy.ops.graph.blend_to_default*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-blend-to-default"), ("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"), ("bpy.ops.mesh.bridge-edge-loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"), ("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"), @@ -1683,7 +1740,7 @@ url_manual_mapping = ( ("bpy.types.datatransfermodifier*", "modeling/modifiers/modify/data_transfer.html#bpy-types-datatransfermodifier"), ("bpy.types.dynamicpaintmodifier*", "physics/dynamic_paint/index.html#bpy-types-dynamicpaintmodifier"), ("bpy.types.editbone.use_connect*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-use-connect"), - ("bpy.types.ffmpegsettings.audio*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio"), + ("bpy.types.ffmpegsettings.codec*", "render/output/properties/output.html#bpy-types-ffmpegsettings-codec"), ("bpy.types.followpathconstraint*", "animation/constraints/relationship/follow_path.html#bpy-types-followpathconstraint"), ("bpy.types.functionnodeinputint*", "modeling/geometry_nodes/input/integer.html#bpy-types-functionnodeinputint"), ("bpy.types.gaussianblursequence*", "video_editing/edit/montage/strips/effects/blur.html#bpy-types-gaussianblursequence"), @@ -1823,6 +1880,7 @@ url_manual_mapping = ( ("bpy.types.imageformatsettings*", "files/media/image_formats.html#bpy-types-imageformatsettings"), ("bpy.types.kinematicconstraint*", "animation/constraints/tracking/ik_solver.html#bpy-types-kinematicconstraint"), ("bpy.types.material.line_color*", "render/freestyle/material.html#bpy-types-material-line-color"), + ("bpy.types.material.pass_index*", "render/materials/settings.html#bpy-types-material-pass-index"), ("bpy.types.mesh.use_paint_mask*", "sculpt_paint/brush/introduction.html#bpy-types-mesh-use-paint-mask"), ("bpy.types.movietrackingcamera*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera"), ("bpy.types.object.display_type*", "scene_layout/object/properties/display.html#bpy-types-object-display-type"), @@ -1916,6 +1974,7 @@ url_manual_mapping = ( ("bpy.ops.transform.edge_slide*", "modeling/meshes/editing/edge/edge_slide.html#bpy-ops-transform-edge-slide"), ("bpy.ops.transform.vert_slide*", "modeling/meshes/editing/vertex/slide_vertices.html#bpy-ops-transform-vert-slide"), ("bpy.ops.uv.project_from_view*", "modeling/meshes/editing/uv.html#bpy-ops-uv-project-from-view"), + ("bpy.ops.view3d.view_selected*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-view-selected"), ("bpy.ops.wm.memory_statistics*", "advanced/operators.html#bpy-ops-wm-memory-statistics"), ("bpy.ops.wm.recover_auto_save*", "files/blend/open_save.html#bpy-ops-wm-recover-auto-save"), ("bpy.types.adjustmentsequence*", "video_editing/edit/montage/strips/adjustment.html#bpy-types-adjustmentsequence"), @@ -1924,7 +1983,7 @@ url_manual_mapping = ( ("bpy.types.armature.show_axes*", "animation/armatures/properties/display.html#bpy-types-armature-show-axes"), ("bpy.types.armatureconstraint*", "animation/constraints/relationship/armature.html#bpy-types-armatureconstraint"), ("bpy.types.compositornodeblur*", "compositing/types/filter/blur_node.html#bpy-types-compositornodeblur"), - ("bpy.types.compositornodecomb*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodecomb"), + ("bpy.types.compositornodecomb*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodecomb"), ("bpy.types.compositornodecrop*", "compositing/types/distort/crop.html#bpy-types-compositornodecrop"), ("bpy.types.compositornodeflip*", "compositing/types/distort/flip.html#bpy-types-compositornodeflip"), ("bpy.types.compositornodemask*", "compositing/types/input/mask.html#bpy-types-compositornodemask"), @@ -1949,6 +2008,7 @@ url_manual_mapping = ( ("bpy.types.huecorrectmodifier*", "editors/video_sequencer/sequencer/sidebar/modifiers.html#bpy-types-huecorrectmodifier"), ("bpy.types.image.is_multiview*", "editors/image/image_settings.html#bpy-types-image-is-multiview"), ("bpy.types.imagepaint.stencil*", "sculpt_paint/texture_paint/tool_settings/mask.html#bpy-types-imagepaint-stencil"), + ("bpy.types.material.roughness*", "render/materials/settings.html#bpy-types-material-roughness"), ("bpy.types.meshdeformmodifier*", "modeling/modifiers/deform/mesh_deform.html#bpy-types-meshdeformmodifier"), ("bpy.types.movietrackingtrack*", "movie_clip/tracking/clip/sidebar/track/index.html#bpy-types-movietrackingtrack"), ("bpy.types.nodeoutputfileslot*", "compositing/types/output/file.html#bpy-types-nodeoutputfileslot"), @@ -2056,7 +2116,7 @@ url_manual_mapping = ( ("bpy.types.collisionmodifier*", "physics/collision.html#bpy-types-collisionmodifier"), ("bpy.types.collisionsettings*", "physics/collision.html#bpy-types-collisionsettings"), ("bpy.types.compositornodergb*", "compositing/types/input/rgb.html#bpy-types-compositornodergb"), - ("bpy.types.compositornodesep*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodesep"), + ("bpy.types.compositornodesep*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodesep"), ("bpy.types.curve.bevel_depth*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-depth"), ("bpy.types.curve.use_stretch*", "modeling/curves/properties/shape.html#bpy-types-curve-use-stretch"), ("bpy.types.edgesplitmodifier*", "modeling/modifiers/generate/edge_split.html#bpy-types-edgesplitmodifier"), @@ -2069,6 +2129,7 @@ url_manual_mapping = ( ("bpy.types.gpencillayer.hide*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-hide"), ("bpy.types.gpencillayer.lock*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-lock"), ("bpy.types.imagepaint.dither*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-imagepaint-dither"), + ("bpy.types.material.metallic*", "render/materials/settings.html#bpy-types-material-metallic"), ("bpy.types.materialslot.link*", "render/materials/assignment.html#bpy-types-materialslot-link"), ("bpy.types.mesh.texture_mesh*", "modeling/meshes/uv/uv_texture_spaces.html#bpy-types-mesh-texture-mesh"), ("bpy.types.mesh.use_mirror_x*", "modeling/meshes/tools/tool_settings.html#bpy-types-mesh-use-mirror-x"), @@ -2078,6 +2139,7 @@ url_manual_mapping = ( ("bpy.types.movieclipsequence*", "video_editing/edit/montage/strips/clip.html#bpy-types-movieclipsequence"), ("bpy.types.object.dimensions*", "scene_layout/object/properties/transforms.html#bpy-types-object-dimensions"), ("bpy.types.object.is_holdout*", "scene_layout/object/properties/visibility.html#bpy-types-object-is-holdout"), + ("bpy.types.object.lightgroup*", "render/cycles/object_settings/object_data.html#bpy-types-object-lightgroup"), ("bpy.types.object.pass_index*", "scene_layout/object/properties/relations.html#bpy-types-object-pass-index"), ("bpy.types.object.track_axis*", "scene_layout/object/properties/relations.html#bpy-types-object-track-axis"), ("bpy.types.pose.use_mirror_x*", "animation/armatures/posing/tool_settings.html#bpy-types-pose-use-mirror-x"), @@ -2151,12 +2213,13 @@ url_manual_mapping = ( ("bpy.ops.sculpt.mask_filter*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-mask-filter"), ("bpy.ops.transform.tosphere*", "modeling/meshes/editing/mesh/transform/to_sphere.html#bpy-ops-transform-tosphere"), ("bpy.ops.view3d.clip_border*", "editors/3dview/navigate/regions.html#bpy-ops-view3d-clip-border"), + ("bpy.ops.view3d.zoom_border*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-zoom-border"), ("bpy.ops.wm.previews_ensure*", "files/blend/previews.html#bpy-ops-wm-previews-ensure"), ("bpy.ops.wm.properties_edit*", "files/data_blocks.html#bpy-ops-wm-properties-edit"), ("bpy.ops.wm.search_operator*", "interface/controls/templates/operator_search.html#bpy-ops-wm-search-operator"), ("bpy.types.actionconstraint*", "animation/constraints/relationship/action.html#bpy-types-actionconstraint"), ("bpy.types.addonpreferences*", "editors/preferences/addons.html#bpy-types-addonpreferences"), - ("bpy.types.arealight.spread*", "render/lights/light_object.html#bpy-types-arealight-spread"), + ("bpy.types.arealight.spread*", "render/cycles/light_settings.html#bpy-types-arealight-spread"), ("bpy.types.armaturemodifier*", "modeling/modifiers/deform/armature.html#bpy-types-armaturemodifier"), ("bpy.types.bone.head_radius*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-head-radius"), ("bpy.types.bone.tail_radius*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-tail-radius"), @@ -2220,7 +2283,7 @@ url_manual_mapping = ( ("bpy.types.texturenodegroup*", "editors/texture_node/types/groups.html#bpy-types-texturenodegroup"), ("bpy.types.texturenodeimage*", "editors/texture_node/types/input/image.html#bpy-types-texturenodeimage"), ("bpy.types.texturenodescale*", "editors/texture_node/types/distort/scale.html#bpy-types-texturenodescale"), - ("bpy.types.viewlayer.use_ao*", "render/layers/introduction.html#bpy-types-viewlayer-use-ao"), + ("bpy.types.world.lightgroup*", "render/cycles/world_settings.html#bpy-types-world-lightgroup"), ("bpy.ops.armature.dissolve*", "animation/armatures/bones/editing/delete.html#bpy-ops-armature-dissolve"), ("bpy.ops.armature.separate*", "animation/armatures/bones/editing/separate_bones.html#bpy-ops-armature-separate"), ("bpy.ops.clip.clean_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-clean-tracks"), @@ -2237,6 +2300,7 @@ url_manual_mapping = ( ("bpy.ops.gpencil.reproject*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-reproject"), ("bpy.ops.graph.easing_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-easing-type"), ("bpy.ops.graph.handle_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-handle-type"), + ("bpy.ops.marker.select_all*", "animation/markers.html#bpy-ops-marker-select-all"), ("bpy.ops.mask.parent_clear*", "movie_clip/masking/editing.html#bpy-ops-mask-parent-clear"), ("bpy.ops.mask.select_lasso*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-lasso"), ("bpy.ops.mesh.bevel.vertex*", "modeling/meshes/editing/vertex/bevel_vertices.html#bpy-ops-mesh-bevel-vertex"), @@ -2296,6 +2360,7 @@ url_manual_mapping = ( ("bpy.types.preferencesview*", "editors/preferences/interface.html#bpy-types-preferencesview"), ("bpy.types.rigidbodyobject*", "physics/rigid_body/index.html#bpy-types-rigidbodyobject"), ("bpy.types.scene.frame_end*", "render/output/properties/frame_range.html#bpy-types-scene-frame-end"), + ("bpy.types.scene.sync_mode*", "editors/timeline.html#bpy-types-scene-sync-mode"), ("bpy.types.sceneeevee.gtao*", "render/eevee/render_settings/ambient_occlusion.html#bpy-types-sceneeevee-gtao"), ("bpy.types.screen.use_play*", "editors/timeline.html#bpy-types-screen-use-play"), ("bpy.types.shadernodebevel*", "render/shader_nodes/input/bevel.html#bpy-types-shadernodebevel"), @@ -2351,6 +2416,7 @@ url_manual_mapping = ( ("bpy.ops.uv.snap_selected*", "modeling/meshes/uv/editing.html#bpy-ops-uv-snap-selected"), ("bpy.ops.view3d.localview*", "editors/3dview/navigate/local_view.html#bpy-ops-view3d-localview"), ("bpy.ops.view3d.view_axis*", "editors/3dview/navigate/viewpoint.html#bpy-ops-view3d-view-axis"), + ("bpy.ops.view3d.view_roll*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-view-roll"), ("bpy.ops.wm.open_mainfile*", "files/blend/open_save.html#bpy-ops-wm-open-mainfile"), ("bpy.ops.wm.owner_disable*", "interface/window_system/workspaces.html#bpy-ops-wm-owner-disable"), ("bpy.ops.wm.save_mainfile*", "files/blend/open_save.html#bpy-ops-wm-save-mainfile"), @@ -2430,6 +2496,7 @@ url_manual_mapping = ( ("bpy.ops.uv.cube_project*", "modeling/meshes/editing/uv.html#bpy-ops-uv-cube-project"), ("bpy.ops.uv.pack_islands*", "modeling/meshes/uv/editing.html#bpy-ops-uv-pack-islands"), ("bpy.ops.uv.select_split*", "modeling/meshes/uv/editing.html#bpy-ops-uv-select-split"), + ("bpy.ops.view3d.view_all*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-view-all"), ("bpy.ops.view3d.view_pan*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-view-pan"), ("bpy.ops.wm.app_template*", "advanced/app_templates.html#bpy-ops-wm-app-template"), ("bpy.ops.wm.batch_rename*", "files/blend/rename.html#bpy-ops-wm-batch-rename"), @@ -2523,6 +2590,7 @@ url_manual_mapping = ( ("bpy.ops.sequencer.swap*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-swap"), ("bpy.ops.transform.bend*", "modeling/meshes/editing/mesh/transform/bend.html#bpy-ops-transform-bend"), ("bpy.ops.transform.tilt*", "modeling/curves/editing/control_points.html#bpy-ops-transform-tilt"), + ("bpy.ops.uv.select_mode*", "editors/uv/selecting.html#bpy-ops-uv-select-mode"), ("bpy.ops.uv.snap_cursor*", "modeling/meshes/uv/editing.html#bpy-ops-uv-snap-cursor"), ("bpy.ops.wm.search_menu*", "interface/controls/templates/operator_search.html#bpy-ops-wm-search-menu"), ("bpy.types.bakesettings*", "render/cycles/baking.html#bpy-types-bakesettings"), @@ -2575,7 +2643,6 @@ url_manual_mapping = ( ("bpy.ops.image.replace*", "editors/image/editing.html#bpy-ops-image-replace"), ("bpy.ops.image.save_as*", "editors/image/editing.html#bpy-ops-image-save-as"), ("bpy.ops.marker.delete*", "animation/markers.html#bpy-ops-marker-delete"), - ("bpy.ops.marker.rename*", "animation/markers.html#bpy-ops-marker-rename"), ("bpy.ops.marker.select*", "animation/markers.html#bpy-ops-marker-select"), ("bpy.ops.material.copy*", "render/materials/assignment.html#bpy-ops-material-copy"), ("bpy.ops.mesh.decimate*", "modeling/meshes/editing/mesh/cleanup.html#bpy-ops-mesh-decimate"), @@ -2594,6 +2661,7 @@ url_manual_mapping = ( ("bpy.ops.view3d.select*", "editors/3dview/selecting.html#bpy-ops-view3d-select"), ("bpy.ops.wm.debug_menu*", "advanced/operators.html#bpy-ops-wm-debug-menu"), ("bpy.ops.wm.obj_export*", "files/import_export/obj.html#bpy-ops-wm-obj-export"), + ("bpy.ops.wm.obj_import*", "files/import_export/obj.html#bpy-ops-wm-obj-import"), ("bpy.ops.wm.properties*", "files/data_blocks.html#bpy-ops-wm-properties"), ("bpy.ops.wm.usd_export*", "files/import_export/usd.html#bpy-ops-wm-usd-export"), ("bpy.types.addsequence*", "video_editing/edit/montage/strips/effects/add.html#bpy-types-addsequence"), @@ -2642,6 +2710,7 @@ url_manual_mapping = ( ("bpy.ops.object.quick*", "physics/introduction.html#bpy-ops-object-quick"), ("bpy.ops.text.replace*", "editors/text_editor.html#bpy-ops-text-replace"), ("bpy.ops.uv.mark_seam*", "modeling/meshes/uv/unwrapping/seams.html#bpy-ops-uv-mark-seam"), + ("bpy.ops.view3d.dolly*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-dolly"), ("bpy.ops.view3d.ruler*", "editors/3dview/toolbar/measure.html#bpy-ops-view3d-ruler"), ("bpy.types.areaspaces*", "interface/window_system/areas.html#bpy-types-areaspaces"), ("bpy.types.bonegroups*", "animation/armatures/properties/bone_groups.html#bpy-types-bonegroups"), @@ -2738,6 +2807,7 @@ url_manual_mapping = ( ("bpy.types.facemaps*", "modeling/meshes/properties/object_data.html#bpy-types-facemaps"), ("bpy.types.keyframe*", "animation/keyframes/index.html#bpy-types-keyframe"), ("bpy.types.linesets*", "render/freestyle/view_layer/line_set.html#bpy-types-linesets"), + ("bpy.types.material*", "render/materials/index.html#bpy-types-material"), ("bpy.types.metaball*", "modeling/metas/index.html#bpy-types-metaball"), ("bpy.types.modifier*", "modeling/modifiers/index.html#bpy-types-modifier"), ("bpy.types.nlastrip*", "editors/nla/strips.html#bpy-types-nlastrip"), @@ -2751,6 +2821,7 @@ url_manual_mapping = ( ("bpy.types.spacenla*", "editors/nla/index.html#bpy-types-spacenla"), ("bpy.types.sunlight*", "render/lights/light_object.html#bpy-types-sunlight"), ("bpy.ops.clip.open*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-open"), + ("bpy.ops.curve.pen*", "modeling/curves/tools/pen.html#bpy-ops-curve-pen"), ("bpy.ops.file.next*", "editors/file_browser.html#bpy-ops-file-next"), ("bpy.ops.image.new*", "editors/image/editing.html#bpy-ops-image-new"), ("bpy.ops.mesh.fill*", "modeling/meshes/editing/face/fill.html#bpy-ops-mesh-fill"), @@ -2776,7 +2847,7 @@ url_manual_mapping = ( ("bpy.ops.armature*", "animation/armatures/index.html#bpy-ops-armature"), ("bpy.ops.geometry*", "modeling/index.html#bpy-ops-geometry"), ("bpy.ops.material*", "render/materials/index.html#bpy-ops-material"), - ("bpy.ops.nla.bake*", "animation/actions.html#bpy-ops-nla-bake"), + ("bpy.ops.nla.bake*", "editors/nla/editing.html#bpy-ops-nla-bake"), ("bpy.ops.nla.snap*", "editors/nla/editing.html#bpy-ops-nla-snap"), ("bpy.ops.nla.swap*", "editors/nla/editing.html#bpy-ops-nla-swap"), ("bpy.ops.outliner*", "editors/outliner/index.html#bpy-ops-outliner"), diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 7d0929ef28f..1239f49473c 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -1265,6 +1265,7 @@ def km_uv_editor(params): {"properties": [("deselect", True)]}), ("uv.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("uv.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), + ("uv.select_similar", {"type": 'G', "value": 'PRESS', "shift": True}, None), *_template_items_select_actions(params, "uv.select_all"), *_template_items_hide_reveal_actions("uv.hide", "uv.reveal"), ("uv.select_pinned", {"type": 'P', "value": 'PRESS', "shift": True}, None), diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 0eaada7249b..50fc6bad720 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1352,7 +1352,7 @@ class WM_OT_properties_edit(Operator): items=rna_custom_property_type_items, ) is_overridable_library: BoolProperty( - name="Is Library Overridable", + name="Library Overridable", description="Allow the property to be overridden when the data-block is linked", default=False, ) @@ -1363,7 +1363,7 @@ class WM_OT_properties_edit(Operator): # Shared for integer and string properties. use_soft_limits: BoolProperty( - name="Use Soft Limits", + name="Soft Limits", description=( "Limits the Property Value slider to a range, " "values outside the range must be inputted numerically" diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 8e5050be07e..8c43186313f 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -234,6 +234,11 @@ class GPENCIL_MT_move_to_layer(Menu): layout = self.layout gpd = context.gpencil_data if gpd: + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("gpencil.move_to_layer", text="New Layer", icon='ADD').layer = -1 + + layout.separator() + gpl_active = context.active_gpencil_layer tot_layers = len(gpd.layers) i = tot_layers - 1 @@ -246,11 +251,6 @@ class GPENCIL_MT_move_to_layer(Menu): layout.operator("gpencil.move_to_layer", text=gpl.info, icon=icon, translate=False).layer = i i -= 1 - layout.separator() - - layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("gpencil.move_to_layer", text="New Layer", icon='ADD').layer = -1 - class GPENCIL_MT_layer_active(Menu): bl_label = "Change Active Layer" @@ -261,6 +261,10 @@ class GPENCIL_MT_layer_active(Menu): gpd = context.gpencil_data if gpd: + layout.operator("gpencil.layer_add", text="New Layer", icon='ADD') + + layout.separator() + gpl_active = context.active_gpencil_layer tot_layers = len(gpd.layers) i = tot_layers - 1 @@ -273,10 +277,6 @@ class GPENCIL_MT_layer_active(Menu): layout.operator("gpencil.layer_active", text=gpl.info, icon=icon).layer = i i -= 1 - layout.separator() - - layout.operator("gpencil.layer_add", text="New Layer", icon='ADD') - class GPENCIL_MT_material_active(Menu): bl_label = "Change Active Material" diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index 3131833454b..47a25db20b1 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -239,6 +239,9 @@ class MASK_PT_display: sub = row.row() sub.active = space_data.show_mask_overlay sub.prop(space_data, "mask_overlay_mode", text="") + row = layout.row() + row.active = (space_data.mask_overlay_mode in ['COMBINED'] and space_data.show_mask_overlay) + row.prop(space_data, "blend_factor", text="Blending Factor") class MASK_PT_transforms: diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 1f02e0f64d4..5d25d02d98e 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -159,6 +159,7 @@ class IMAGE_MT_select(Menu): layout.operator("uv.select_pinned") layout.menu("IMAGE_MT_select_linked") + layout.operator("uv.select_similar") layout.separator() diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index fec3447ca6c..a8184b1d84b 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -714,6 +714,7 @@ geometry_node_categories = [ NodeItem("ShaderNodeVectorRotate"), ]), GeometryNodeCategory("GEO_VOLUME", "Volume", items=[ + NodeItem("GeometryNodeVolumeCube"), NodeItem("GeometryNodeVolumeToMesh"), ]), GeometryNodeCategory("GEO_GROUP", "Group", items=node_group_items), diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index e5e2b1711b1..78c8612f7f5 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -14,6 +14,15 @@ extern "C" { #endif +/* Name of subfolder inside BLENDER_DATAFILES that contains font files. */ +#define BLF_DATAFILES_FONTS_DIR "fonts" + +/* File name of the default variable-width font. */ +#define BLF_DEFAULT_PROPORTIONAL_FONT "droidsans.ttf" + +/* File name of the default fixed-pitch font. */ +#define BLF_DEFAULT_MONOSPACED_FONT "bmonofont-i18n.ttf" + /* enable this only if needed (unused circa 2016) */ #define BLF_BLUR_ENABLE 0 @@ -37,12 +46,14 @@ void BLF_cache_flush_set_fn(void (*cache_flush_fn)(void)); */ int BLF_load(const char *name) ATTR_NONNULL(); int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL(); +bool BLF_is_loaded(const char *name) ATTR_NONNULL(); int BLF_load_unique(const char *name) ATTR_NONNULL(); int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL(); void BLF_unload(const char *name) ATTR_NONNULL(); void BLF_unload_id(int fontid); +void BLF_unload_all(void); char *BLF_display_name_from_file(const char *filepath); @@ -312,6 +323,7 @@ int BLF_set_default(void); int BLF_load_default(bool unique); int BLF_load_mono_default(bool unique); +void BLF_load_font_stack(void); #ifdef DEBUG void BLF_state_print(int fontid); @@ -331,6 +343,9 @@ void BLF_state_print(int fontid); #define BLF_HINTING_FULL (1 << 10) #define BLF_BOLD (1 << 11) #define BLF_ITALIC (1 << 12) +#define BLF_MONOSPACED (1 << 13) /* Intended USE is monospaced, regardless of font type. */ +#define BLF_DEFAULT (1 << 14) /* A font within the default stack of fonts. */ +#define BLF_LAST_RESORT (1 << 15) /* Must only be used as last font in the stack. */ #define BLF_DRAW_STR_DUMMY_MAX 1024 diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index a944ab332bd..a1fcc17ca3f 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -34,13 +34,6 @@ #include "blf_internal.h" #include "blf_internal_types.h" -/* Max number of font in memory. - * Take care that now every font have a glyph cache per size/dpi, - * so we don't need load the same font with different size, just - * load one and call BLF_size. - */ -#define BLF_MAX_FONT 16 - #define BLF_RESULT_CHECK_INIT(r_info) \ if (r_info) { \ memset(r_info, 0, sizeof(*(r_info))); \ @@ -48,7 +41,7 @@ ((void)0) /* Font array. */ -static FontBLF *global_font[BLF_MAX_FONT] = {NULL}; +FontBLF *global_font[BLF_MAX_FONT] = {NULL}; /* XXX: should these be made into global_font_'s too? */ @@ -134,6 +127,11 @@ bool BLF_has_glyph(int fontid, unsigned int unicode) return false; } +bool BLF_is_loaded(const char *name) +{ + return blf_search(name) >= 0; +} + int BLF_load(const char *name) { /* check if we already load this font. */ @@ -255,6 +253,20 @@ void BLF_unload_id(int fontid) } } +void BLF_unload_all(void) +{ + for (int i = 0; i < BLF_MAX_FONT; i++) { + FontBLF *font = global_font[i]; + if (font) { + blf_font_free(font); + global_font[i] = NULL; + } + } + blf_mono_font = -1; + blf_mono_font_render = -1; + BLF_default_set(-1); +} + void BLF_enable(int fontid, int option) { FontBLF *font = blf_get(fontid); diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index a170f27d247..26a72fcb95a 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -18,6 +18,7 @@ #include FT_FREETYPE_H #include FT_GLYPH_H +#include FT_TRUETYPE_TABLES_H /* For TT_OS2 */ #include "MEM_guardedalloc.h" @@ -1288,6 +1289,25 @@ FontBLF *blf_font_new(const char *name, const char *filepath) font->filepath = BLI_strdup(filepath); blf_font_fill(font); + /* Save TrueType table with bits to quickly test most unicode block coverage. */ + TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(font->face, FT_SFNT_OS2); + if (os2_table) { + font->UnicodeRanges[0] = (uint)os2_table->ulUnicodeRange1; + font->UnicodeRanges[1] = (uint)os2_table->ulUnicodeRange2; + font->UnicodeRanges[2] = (uint)os2_table->ulUnicodeRange3; + font->UnicodeRanges[3] = (uint)os2_table->ulUnicodeRange4; + } + + /* Detect "Last resort" fonts. They have everything. Usually except last 5 bits. */ + if (font->UnicodeRanges[0] == 0xffffffffU && font->UnicodeRanges[1] == 0xffffffffU && + font->UnicodeRanges[2] == 0xffffffffU && font->UnicodeRanges[3] >= 0x7FFFFFFU) { + font->flags |= BLF_LAST_RESORT; + } + + if (FT_IS_FIXED_WIDTH(font->face)) { + font->flags |= BLF_MONOSPACED; + } + if (FT_HAS_KERNING(font->face)) { /* Create kerning cache table and fill with value indicating "unset". */ font->kerning_cache = MEM_mallocN(sizeof(KerningCacheBLF), __func__); diff --git a/source/blender/blenfont/intern/blf_font_default.c b/source/blender/blenfont/intern/blf_font_default.c index 3a68423e64e..1bde25b5776 100644 --- a/source/blender/blenfont/intern/blf_font_default.c +++ b/source/blender/blenfont/intern/blf_font_default.c @@ -11,13 +11,14 @@ #include "BLF_api.h" +#include "BLI_fileops.h" #include "BLI_path_util.h" #include "BKE_appdir.h" static int blf_load_font_default(const char *filename, const bool unique) { - const char *dir = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts"); + const char *dir = BKE_appdir_folder_id(BLENDER_DATAFILES, BLF_DATAFILES_FONTS_DIR); if (dir == NULL) { fprintf(stderr, "%s: 'fonts' data path not found for '%s', will not be able to display text\n", @@ -34,10 +35,46 @@ static int blf_load_font_default(const char *filename, const bool unique) int BLF_load_default(const bool unique) { - return blf_load_font_default("droidsans.ttf", unique); + int font_id = blf_load_font_default(BLF_DEFAULT_PROPORTIONAL_FONT, unique); + BLF_enable(font_id, BLF_DEFAULT); + return font_id; } int BLF_load_mono_default(const bool unique) { - return blf_load_font_default("bmonofont-i18n.ttf", unique); + int font_id = blf_load_font_default(BLF_DEFAULT_MONOSPACED_FONT, unique); + BLF_enable(font_id, BLF_MONOSPACED | BLF_DEFAULT); + return font_id; +} + +void BLF_load_font_stack() +{ + /* Load these if not already, might have been replaced by user custom. */ + BLF_load_default(false); + BLF_load_mono_default(false); + + const char *path = BKE_appdir_folder_id(BLENDER_DATAFILES, BLF_DATAFILES_FONTS_DIR SEP_STR); + if (path && BLI_exists(path)) { + struct direntry *dir; + uint num_files = BLI_filelist_dir_contents(path, &dir); + for (int f = 0; f < num_files; f++) { + if (!FILENAME_IS_CURRPAR(dir[f].relname) && !BLI_is_dir(dir[f].path)) { + if (!BLF_is_loaded(dir[f].path)) { + int font_id = BLF_load(dir[f].path); + if (font_id == -1) { + fprintf(stderr, "Unable to load font: %s\n", dir[f].path); + } + else { + BLF_enable(font_id, BLF_DEFAULT); + /* TODO: FontBLF will later load FT_Face on demand. When this is in + * place we can drop this face now since we have all needed data. */ + } + } + } + } + BLI_filelist_free(dir, num_files); + } + else { + fprintf(stderr, "Fonts not found at %s\n", path); + } } diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 2694b179a11..ed30cca4da2 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -39,6 +39,7 @@ #include "BLI_math_vector.h" #include "BLI_strict_flags.h" +#include "BLI_string_utf8.h" /* -------------------------------------------------------------------- */ /** \name Internal Utilities @@ -222,6 +223,335 @@ static GlyphBLF *blf_glyph_cache_add_glyph( return g; } +/* This table can be used to find a coverage bit based on a charcode. later we can get default + * language and script from codepoint. */ + +typedef struct eUnicodeBlock { + unsigned int first; + unsigned int last; + int coverage_bit; /* 0-122. -1 is N/A. */ + /* Later we add primary script and language for Harfbuzz, data from + * https://en.wikipedia.org/wiki/Unicode_block */ +} eUnicodeBlock; + +static eUnicodeBlock unicode_blocks[] = { + /* Must be in ascending order by start of range. */ + {0x0, 0x7F, 0}, /* Basic Latin. */ + {0x80, 0xFF, 1}, /* Latin-1 Supplement. */ + {0x100, 0x17F, 2}, /* Latin Extended-A. */ + {0x180, 0x24F, 3}, /* Latin Extended-B. */ + {0x250, 0x2AF, 4}, /* IPA Extensions. */ + {0x2B0, 0x2FF, 5}, /* Spacing Modifier Letters. */ + {0x300, 0x36F, 6}, /* Combining Diacritical Marks. */ + {0x370, 0x3FF, 7}, /* Greek. */ + {0x400, 0x52F, 9}, /* Cyrillic. */ + {0x530, 0x58F, 10}, /* Armenian. */ + {0x590, 0x5FF, 11}, /* Hebrew. */ + {0x600, 0x6FF, 13}, /* Arabic. */ + {0x700, 0x74F, 71}, /* Syriac. */ + {0x750, 0x77F, 13}, /* Arabic Supplement. */ + {0x780, 0x7BF, 72}, /* Thaana. */ + {0x7C0, 0x7FF, 14}, /* NKo. */ + {0x800, 0x83F, -1}, /* Samaritan. */ + {0x840, 0x85F, -1}, /* Mandaic. */ + {0x900, 0x97F, 15}, /* Devanagari. */ + {0x980, 0x9FF, 16}, /* Bengali. */ + {0xA00, 0xA7F, 17}, /* Gurmukhi. */ + {0xA80, 0xAFF, 18}, /* Gujarati. */ + {0xB00, 0xB7F, 19}, /* Oriya. */ + {0xB80, 0xBFF, 20}, /* Tamil. */ + {0xC00, 0xC7F, 21}, /* Telugu. */ + {0xC80, 0xCFF, 22}, /* Kannada. */ + {0xD00, 0xD7F, 23}, /* Malayalam. */ + {0xD80, 0xDFF, 73}, /* Sinhala. */ + {0xE00, 0xE7F, 24}, /* Thai. */ + {0xE80, 0xEFF, 25}, /* Lao. */ + {0xF00, 0xFFF, 70}, /* Tibetan. */ + {0x1000, 0x109F, 74}, /* Myanmar. */ + {0x10A0, 0x10FF, 26}, /* Georgian. */ + {0x1100, 0x11FF, 28}, /* Hangul Jamo. */ + {0x1200, 0x139F, 75}, /* Ethiopic. */ + {0x13A0, 0x13FF, 76}, /* Cherokee. */ + {0x1400, 0x167F, 77}, /* Canadian Aboriginal. */ + {0x1680, 0x169F, 78}, /* Ogham. */ + {0x16A0, 0x16FF, 79}, /* unic. */ + {0x1700, 0x171F, 84}, /* Tagalog. */ + {0x1720, 0x173F, 84}, /* Hanunoo. */ + {0x1740, 0x175F, 84}, /* Buhid. */ + {0x1760, 0x177F, 84}, /* Tagbanwa. */ + {0x1780, 0x17FF, 80}, /* Khmer. */ + {0x1800, 0x18AF, 81}, /* Mongolian. */ + {0x1900, 0x194F, 93}, /* Limbu. */ + {0x1950, 0x197F, 94}, /* Tai Le. */ + {0x1980, 0x19DF, 95}, /* New Tai Lue". */ + {0x19E0, 0x19FF, 80}, /* Khmer. */ + {0x1A00, 0x1A1F, 96}, /* Buginese. */ + {0x1A20, 0x1AAF, -1}, /* Tai Tham. */ + {0x1B00, 0x1B7F, 27}, /* Balinese. */ + {0x1B80, 0x1BBF, 112}, /* Sundanese. */ + {0x1BC0, 0x1BFF, -1}, /* Batak. */ + {0x1C00, 0x1C4F, 113}, /* Lepcha. */ + {0x1C50, 0x1C7F, 114}, /* Ol Chiki. */ + {0x1D00, 0x1DBF, 4}, /* IPA Extensions. */ + {0x1DC0, 0x1DFF, 6}, /* Combining Diacritical Marks. */ + {0x1E00, 0x1EFF, 29}, /* Latin Extended Additional. */ + {0x1F00, 0x1FFF, 30}, /* Greek Extended. */ + {0x2000, 0x206F, 31}, /* General Punctuation. */ + {0x2070, 0x209F, 32}, /* Superscripts And Subscripts. */ + {0x20A0, 0x20CF, 33}, /* Currency Symbols. */ + {0x20D0, 0x20FF, 34}, /* Combining Diacritical Marks For Symbols. */ + {0x2100, 0x214F, 35}, /* Letterlike Symbols. */ + {0x2150, 0x218F, 36}, /* Number Forms. */ + {0x2190, 0x21FF, 37}, /* Arrows. */ + {0x2200, 0x22FF, 38}, /* Mathematical Operators. */ + {0x2300, 0x23FF, 39}, /* Miscellaneous Technical. */ + {0x2400, 0x243F, 40}, /* Control Pictures. */ + {0x2440, 0x245F, 41}, /* Optical Character Recognition. */ + {0x2460, 0x24FF, 42}, /* Enclosed Alphanumerics. */ + {0x2500, 0x257F, 43}, /* Box Drawing. */ + {0x2580, 0x259F, 44}, /* Block Elements. */ + {0x25A0, 0x25FF, 45}, /* Geometric Shapes. */ + {0x2600, 0x26FF, 46}, /* Miscellaneous Symbols. */ + {0x2700, 0x27BF, 47}, /* Dingbats. */ + {0x27C0, 0x27EF, 38}, /* Mathematical Operators. */ + {0x27F0, 0x27FF, 37}, /* Arrows. */ + {0x2800, 0x28FF, 82}, /* Braille. */ + {0x2900, 0x297F, 37}, /* Arrows. */ + {0x2980, 0x2AFF, 38}, /* Mathematical Operators. */ + {0x2B00, 0x2BFF, 37}, /* Arrows. */ + {0x2C00, 0x2C5F, 97}, /* Glagolitic. */ + {0x2C60, 0x2C7F, 29}, /* Latin Extended Additional. */ + {0x2C80, 0x2CFF, 8}, /* Coptic. */ + {0x2D00, 0x2D2F, 26}, /* Georgian. */ + {0x2D30, 0x2D7F, 98}, /* Tifinagh. */ + {0x2D80, 0x2DDF, 75}, /* Ethiopic. */ + {0x2DE0, 0x2DFF, 9}, /* Cyrillic. */ + {0x2E00, 0x2E7F, 31}, /* General Punctuation. */ + {0x2E80, 0x2FFF, 59}, /* CJK Unified Ideographs. */ + {0x3000, 0x303F, 48}, /* CJK Symbols And Punctuation. */ + {0x3040, 0x309F, 49}, /* Hiragana. */ + {0x30A0, 0x30FF, 50}, /* Katakana. */ + {0x3100, 0x312F, 51}, /* Bopomofo. */ + {0x3130, 0x318F, 52}, /* Hangul Compatibility Jamo. */ + {0x3190, 0x319F, 59}, /* CJK Unified Ideographs. */ + {0x31A0, 0x31BF, 51}, /* Bopomofo. */ + {0x31C0, 0x31EF, 59}, /* CJK Unified Ideographs. */ + {0x31F0, 0x31FF, 50}, /* Katakana. */ + {0x3200, 0x32FF, 54}, /* Enclosed CJK Letters And Months. */ + {0x3300, 0x33FF, 55}, /* CJK Compatibility. */ + {0x3400, 0x4DBF, 59}, /* CJK Unified Ideographs. */ + {0x4DC0, 0x4DFF, 99}, /* Yijing. */ + {0x4E00, 0x9FFF, 59}, /* CJK Unified Ideographs. */ + {0xA000, 0xA4CF, 83}, /* Yi. */ + {0xA4D0, 0xA4FF, -1}, /* Lisu. */ + {0xA500, 0xA63F, 12}, /* Vai. */ + {0xA640, 0xA69F, 9}, /* Cyrillic. */ + {0xA6A0, 0xA6FF, -1}, /* Bamum. */ + {0xA700, 0xA71F, 5}, /* Spacing Modifier Letters. */ + {0xA720, 0xA7FF, 29}, /* Latin Extended Additional. */ + {0xA800, 0xA82F, 100}, /* Syloti Nagri. */ + {0xA840, 0xA87F, 53}, /* Phags-pa. */ + {0xA880, 0xA8DF, 115}, /* Saurashtra. */ + {0xA900, 0xA92F, 116}, /* Kayah Li. */ + {0xA930, 0xA95F, 117}, /* Rejang. */ + {0xA960, 0xA97F, 56}, /* Hangul Syllables. */ + {0xA980, 0xA9DF, -1}, /* Javanese. */ + {0xA9E0, 0xA9FF, 74}, /* Myanmar. */ + {0xAA00, 0xAA5F, 118}, /* Cham. */ + {0xAA60, 0xAA7F, 74}, /* Myanmar. */ + {0xAA80, 0xAADF, -1}, /* Tai Viet. */ + {0xAAE0, 0xAAFF, -1}, /* Meetei Mayek. */ + {0xAB00, 0xAB2F, 75}, /* Ethiopic. */ + {0xAB70, 0xABBF, 76}, /* Cherokee. */ + {0xABC0, 0xABFF, -1}, /* Meetei Mayek. */ + {0xAC00, 0xD7AF, 56}, /* Hangul Syllables. */ + {0xD800, 0xDFFF, 57}, /* Non-Plane 0. */ + {0xE000, 0xF6FF, 60}, /* Private Use Area. */ + {0xE700, 0xEFFF, -1}, /* MS Wingdings. */ + {0xF000, 0xF8FF, -1}, /* MS Symbols. */ + {0xF900, 0xFAFF, 61}, /* CJK Compatibility Ideographs. */ + {0xFB00, 0xFB4F, 62}, /* Alphabetic Presentation Forms. */ + {0xFB50, 0xFDFF, 63}, /* Arabic Presentation Forms-A. */ + {0xFE00, 0xFE0F, 91}, /* Variation Selectors. */ + {0xFE10, 0xFE1F, 65}, /* CJK Compatibility Forms. */ + {0xFE20, 0xFE2F, 64}, /* Combining Half Marks. */ + {0xFE30, 0xFE4F, 65}, /* CJK Compatibility Forms. */ + {0xFE50, 0xFE6F, 66}, /* Small Form Variants. */ + {0xFE70, 0xFEFF, 67}, /* Arabic Presentation Forms-B. */ + {0xFF00, 0xFFEF, 68}, /* Halfwidth And Fullwidth Forms. */ + {0xFFF0, 0xFFFF, 69}, /* Specials. */ + {0x10000, 0x1013F, 101}, /* Linear B. */ + {0x10140, 0x1018F, 102}, /* Ancient Greek Numbers. */ + {0x10190, 0x101CF, 119}, /* Ancient Symbols. */ + {0x101D0, 0x101FF, 120}, /* Phaistos Disc. */ + {0x10280, 0x1029F, 121}, /* Lycian. */ + {0x102A0, 0x102DF, 121}, /* Carian. */ + {0x10300, 0x1032F, 85}, /* Old Italic. */ + {0x10330, 0x1034F, 86}, /* Gothic. */ + {0x10350, 0x1037F, -1}, /* Old Permic. */ + {0x10380, 0x1039F, 103}, /* Ugaritic. */ + {0x103A0, 0x103DF, 104}, /* Old Persian. */ + {0x10400, 0x1044F, 87}, /* Deseret. */ + {0x10450, 0x1047F, 105}, /* Shavian. */ + {0x10480, 0x104AF, 106}, /* Osmanya. */ + {0x104B0, 0x104FF, -1}, /* Osage. */ + {0x10500, 0x1052F, -1}, /* Elbasan. */ + {0x10530, 0x1056F, -1}, /* Caucasian Albanian. */ + {0x10570, 0x105BF, -1}, /* Vithkuqi. */ + {0x10600, 0x1077F, -1}, /* Linear A. */ + {0x10780, 0x107BF, 3}, /* Latin Extended-B. */ + {0x10800, 0x1083F, 107}, /* Cypriot Syllabary. */ + {0x10840, 0x1085F, -1}, /* Imperial Aramaic. */ + {0x10860, 0x1087F, -1}, /* Palmyrene. */ + {0x10880, 0x108AF, -1}, /* Nabataean. */ + {0x108E0, 0x108FF, -1}, /* Hatran. */ + {0x10900, 0x1091F, 58}, /* Phoenician. */ + {0x10920, 0x1093F, 121}, /* Lydian. */ + {0x10980, 0x1099F, -1}, /* Meroitic Hieroglyphs. */ + {0x109A0, 0x109FF, -1}, /* Meroitic Cursive. */ + {0x10A00, 0x10A5F, 108}, /* Kharoshthi. */ + {0x10A60, 0x10A7F, -1}, /* Old South Arabian. */ + {0x10A80, 0x10A9F, -1}, /* Old North Arabian. */ + {0x10AC0, 0x10AFF, -1}, /* Manichaean. */ + {0x10B00, 0x10B3F, -1}, /* Avestan. */ + {0x10B40, 0x10B5F, -1}, /* Inscriptional Parthian. */ + {0x10B60, 0x10B7F, -1}, /* Inscriptional Pahlavi. */ + {0x10B80, 0x10BAF, -1}, /* Psalter Pahlavi. */ + {0x10C00, 0x10C4F, -1}, /* Old Turkic. */ + {0x10C80, 0x10CFF, -1}, /* Old Hungarian. */ + {0x10D00, 0x10D3F, -1}, /* Hanifi Rohingya. */ + {0x108E0, 0x10E7F, -1}, /* Rumi Numeral Symbols. */ + {0x10E80, 0x10EBF, -1}, /* Yezidi. */ + {0x10F00, 0x10F2F, -1}, /* Old Sogdian. */ + {0x10F30, 0x10F6F, -1}, /* Sogdian. */ + {0x10F70, 0x10FAF, -1}, /* Old Uyghur. */ + {0x10FB0, 0x10FDF, -1}, /* Chorasmian. */ + {0x10FE0, 0x10FFF, -1}, /* Elymaic. */ + {0x11000, 0x1107F, -1}, /* Brahmi. */ + {0x11080, 0x110CF, -1}, /* Kaithi. */ + {0x110D0, 0x110FF, -1}, /* Sora Sompeng. */ + {0x11100, 0x1114F, -1}, /* Chakma. */ + {0x11150, 0x1117F, -1}, /* Mahajani. */ + {0x11180, 0x111DF, -1}, /* Sharada. */ + {0x111E0, 0x111FF, -1}, /* Sinhala Archaic Numbers. */ + {0x11200, 0x1124F, -1}, /* Khojki. */ + {0x11280, 0x112AF, -1}, /* Multani. */ + {0x112B0, 0x112FF, -1}, /* Khudawadi. */ + {0x11300, 0x1137F, -1}, /* Grantha. */ + {0x11400, 0x1147F, -1}, /* Newa. */ + {0x11480, 0x114DF, -1}, /* Tirhuta. */ + {0x11580, 0x115FF, -1}, /* Siddham. */ + {0x11600, 0x1165F, -1}, /* Modi. */ + {0x11660, 0x1167F, 81}, /* Mongolian. */ + {0x11680, 0x116CF, -1}, /* Takri. */ + {0x11700, 0x1174F, -1}, /* Ahom. */ + {0x11800, 0x1184F, -1}, /* Dogra. */ + {0x118A0, 0x118FF, -1}, /* Warang Citi. */ + {0x11900, 0x1195F, -1}, /* Dives Akuru. */ + {0x119A0, 0x119FF, -1}, /* Nandinagari. */ + {0x11A00, 0x11A4F, -1}, /* Zanabazar Square. */ + {0x11A50, 0x11AAF, -1}, /* Soyombo. */ + {0x11AB0, 0x11ABF, 77}, /* Canadian Aboriginal Syllabics. */ + {0x11AC0, 0x11AFF, -1}, /* Pau Cin Hau. */ + {0x11C00, 0x11C6F, -1}, /* Bhaiksuki. */ + {0x11C70, 0x11CBF, -1}, /* Marchen. */ + {0x11D00, 0x11D5F, -1}, /* Masaram Gondi. */ + {0x11D60, 0x11DAF, -1}, /* Gunjala Gondi. */ + {0x11EE0, 0x11EFF, -1}, /* Makasar. */ + {0x11FB0, 0x11FBF, -1}, /* Lisu. */ + {0x11FC0, 0x11FFF, 20}, /* Tamil. */ + {0x12000, 0x1254F, 110}, /* Cuneiform. */ + {0x12F90, 0x12FFF, -1}, /* Cypro-Minoan. */ + {0x13000, 0x1343F, -1}, /* Egyptian Hieroglyphs. */ + {0x14400, 0x1467F, -1}, /* Anatolian Hieroglyphs. */ + {0x16800, 0x16A3F, -1}, /* Bamum. */ + {0x16A40, 0x16A6F, -1}, /* Mro. */ + {0x16A70, 0x16ACF, -1}, /* Tangsa. */ + {0x16AD0, 0x16AFF, -1}, /* Bassa Vah. */ + {0x16B00, 0x16B8F, -1}, /* Pahawh Hmong. */ + {0x16E40, 0x16E9F, -1}, /* Medefaidrin. */ + {0x16F00, 0x16F9F, -1}, /* Miao. */ + {0x16FE0, 0x16FFF, -1}, /* Ideographic Symbols. */ + {0x17000, 0x18AFF, -1}, /* Tangut. */ + {0x1B170, 0x1B2FF, -1}, /* Nushu. */ + {0x1BC00, 0x1BC9F, -1}, /* Duployan. */ + {0x1D000, 0x1D24F, 88}, /* Musical Symbols. */ + {0x1D2E0, 0x1D2FF, -1}, /* Mayan Numerals. */ + {0x1D300, 0x1D35F, 109}, /* Tai Xuan Jing. */ + {0x1D360, 0x1D37F, 111}, /* Counting Rod Numerals. */ + {0x1D400, 0x1D7FF, 89}, /* Mathematical Alphanumeric Symbols. */ + {0x1E2C0, 0x1E2FF, -1}, /* Wancho. */ + {0x1E800, 0x1E8DF, -1}, /* Mende Kikakui. */ + {0x1E900, 0x1E95F, -1}, /* Adlam. */ + {0x1EC70, 0x1ECBF, -1}, /* Indic Siyaq Numbers. */ + {0x1F000, 0x1F02F, 122}, /* Mahjong Tiles. */ + {0x1F030, 0x1F09F, 122}, /* Domino Tiles. */ + {0x1F600, 0x1F64F, -1}, /* Emoticons. */ + {0x20000, 0x2A6DF, 59}, /* CJK Unified Ideographs. */ + {0x2F800, 0x2FA1F, 61}, /* CJK Compatibility Ideographs. */ + {0xE0000, 0xE007F, 92}, /* Tags. */ + {0xE0100, 0xE01EF, 91}, /* Variation Selectors. */ + {0xF0000, 0x10FFFD, 90}}; /* Private Use Supplementary. */ + +/* Find a unicode block that a charcode belongs to. */ +static eUnicodeBlock *blf_charcode_to_unicode_block(uint charcode) +{ + if (charcode < 0x80) { + /* Shortcut to Basic Latin. */ + return &unicode_blocks[0]; + } + + /* Binary search for other blocks. */ + + int min = 0; + int max = ARRAY_SIZE(unicode_blocks) - 1; + int mid; + + if (charcode < unicode_blocks[0].first || charcode > unicode_blocks[max].last) { + return NULL; + } + + while (max >= min) { + mid = (min + max) / 2; + if (charcode > unicode_blocks[mid].last) { + min = mid + 1; + } + else if (charcode < unicode_blocks[mid].first) { + max = mid - 1; + } + else { + return &unicode_blocks[mid]; + } + } + + return NULL; +} + +static int blf_charcode_to_coverage_bit(uint charcode) +{ + int coverage_bit = -1; + eUnicodeBlock *block = blf_charcode_to_unicode_block(charcode); + if (block) { + coverage_bit = block->coverage_bit; + } + + if (coverage_bit < 0 && charcode > 0xFFFF) { + /* No coverage bit, but OpenType specs v.1.3+ says bit 57 implies that there + * are codepoints supported beyond the BMP, so only check fonts with this set. */ + coverage_bit = 57; + } + + return coverage_bit; +} + +static bool blf_font_has_coverage_bit(FontBLF *font, int coverage_bit) +{ + if (coverage_bit < 0) { + return false; + } + return (font->UnicodeRanges[(uint)coverage_bit >> 5] & (1u << ((uint)coverage_bit % 32))); +} + /** * Return a glyph index from `charcode`. Not found returns zero, which is a valid * printable character (`.notdef` or `tofu`). Font is allowed to change here. @@ -229,8 +559,42 @@ static GlyphBLF *blf_glyph_cache_add_glyph( static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode) { FT_UInt glyph_index = FT_Get_Char_Index((*font)->face, charcode); - /* TODO: If not found in this font, check others, update font pointer. */ - return glyph_index; + if (glyph_index) { + return glyph_index; + } + + /* Not found in main font, so look in the others. */ + FontBLF *last_resort = NULL; + int coverage_bit = blf_charcode_to_coverage_bit(charcode); + for (int i = 0; i < BLF_MAX_FONT; i++) { + FontBLF *f = global_font[i]; + if (!f || f == *font || !(f->flags & BLF_DEFAULT)) { + continue; + } + + if (f->flags & BLF_LAST_RESORT) { + last_resort = f; + continue; + } + if (coverage_bit < 0 || blf_font_has_coverage_bit(f, coverage_bit)) { + glyph_index = FT_Get_Char_Index(f->face, charcode); + if (glyph_index) { + *font = f; + return glyph_index; + } + } + } + + /* Not found in the stack, return from Last Resort if there is one. */ + if (last_resort) { + glyph_index = FT_Get_Char_Index(last_resort->face, charcode); + if (glyph_index) { + *font = last_resort; + return glyph_index; + } + } + + return 0; } /** @@ -377,24 +741,24 @@ static bool UNUSED_FUNCTION(blf_glyph_transform_width)(FT_GlyphSlot glyph, float /** * Transform glyph to fit nicely within a fixed column width. */ -static bool UNUSED_FUNCTION(blf_glyph_transform_monospace)(FT_GlyphSlot glyph, int width) +static bool blf_glyph_transform_monospace(FT_GlyphSlot glyph, int width) { if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - int gwidth = (int)(glyph->linearHoriAdvance >> 16); - if (gwidth > width) { - float scale = (float)width / (float)gwidth; + FT_Fixed current = glyph->linearHoriAdvance; + FT_Fixed target = width << 16; /* Do math in 16.16 values. */ + if (target < current) { + const FT_Pos embolden = (FT_Pos)((current - target) >> 13); + /* Horizontally widen strokes to counteract narrowing. */ + FT_Outline_EmboldenXY(&glyph->outline, embolden, 0); + const float scale = (float)(target - (embolden << 9)) / (float)current; FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16dot16(1)}; - /* Narrowing all points also thins vertical strokes. */ FT_Outline_Transform(&glyph->outline, &matrix); - const FT_Pos extra_x = (int)((float)(gwidth - width) * 5.65f); - /* Horizontally widen strokes to counteract narrowing. */ - FT_Outline_EmboldenXY(&glyph->outline, extra_x, 0); } - else if (gwidth < width) { - /* Narrow glyphs only need to be centered. */ - int nudge = (width - gwidth) / 2; - FT_Outline_Translate(&glyph->outline, (FT_Pos)nudge * 64, 0); + else if (target > current) { + /* Center narrow glyphs. */ + FT_Outline_Translate(&glyph->outline, (FT_Pos)((target - current) >> 11), 0); } + glyph->advance.x = width << 6; return true; } return false; @@ -411,7 +775,9 @@ static bool UNUSED_FUNCTION(blf_glyph_transform_monospace)(FT_GlyphSlot glyph, i */ static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font, FontBLF *glyph_font, - FT_UInt glyph_index) + FT_UInt glyph_index, + uint charcode, + int fixed_width) { if (glyph_font != settings_font) { FT_Set_Char_Size(glyph_font->face, @@ -428,6 +794,10 @@ static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font, return NULL; } + if ((settings_font->flags & BLF_MONOSPACED) && (settings_font != glyph_font)) { + blf_glyph_transform_monospace(glyph, BLI_wcwidth((char32_t)charcode) * fixed_width); + } + if ((settings_font->flags & BLF_ITALIC) != 0) { /* 37.5% of maximum rightward slant results in 6 degree slope, matching italic * version (`DejaVuSans-Oblique.ttf`) of our current font. But a nice median when @@ -466,7 +836,8 @@ GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode) * renderer uses a shared buffer internally. */ BLI_spin_lock(font_with_glyph->ft_lib_mutex); - FT_GlyphSlot glyph = blf_glyph_render(font, font_with_glyph, glyph_index); + FT_GlyphSlot glyph = blf_glyph_render( + font, font_with_glyph, glyph_index, charcode, gc->fixed_width); if (glyph) { /* Save this glyph in the initial font's cache. */ diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 7754f960043..84037ff4bd0 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -14,6 +14,12 @@ struct ResultBLF; struct rctf; struct rcti; +/* Max number of fonts in memory. Take care that every font has a glyph cache per size/dpi, + * so we don't need load the same font with different size, just load one and call BLF_size. */ +#define BLF_MAX_FONT 32 + +extern struct FontBLF *global_font[BLF_MAX_FONT]; + void blf_batch_draw_begin(struct FontBLF *font); void blf_batch_draw(void); diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 9dfcb1a4ad6..998093dae70 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -226,6 +226,11 @@ typedef struct FontBLF { /** File-path or NULL. */ char *filepath; + /* Copied from the SFNT OS/2 table. Bit flags for unicode blocks and ranges + * considered "functional". Cached here because face might not always exist. + * See: https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur */ + uint UnicodeRanges[4]; + /* aspect ratio or scale. */ float aspect[3]; diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 2cd753da9d3..20eb33c5d15 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 1 +#define BLENDER_FILE_SUBVERSION 2 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 59b22f7759b..2c444f42c46 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -77,8 +77,16 @@ typedef struct MainIDRelationsEntry { typedef enum eMainIDRelationsEntryTags { /* Generic tag marking the entry as to be processed. */ MAINIDRELATIONS_ENTRY_TAGS_DOIT = 1 << 0, + + /* Generic tag marking the entry as processed in the `to` direction (i.e. we processed the IDs + * used by this item). */ + MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO = 1 << 1, + /* Generic tag marking the entry as processed in the `from` direction (i.e. we processed the IDs + * using by this item). */ + MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_FROM = 1 << 2, /* Generic tag marking the entry as processed. */ - MAINIDRELATIONS_ENTRY_TAGS_PROCESSED = 1 << 1, + MAINIDRELATIONS_ENTRY_TAGS_PROCESSED = MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO | + MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_FROM, } eMainIDRelationsEntryTags; typedef struct MainIDRelations { diff --git a/source/blender/blenkernel/BKE_mesh_boolean_convert.hh b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh index abaf2ab0178..441783d46a1 100644 --- a/source/blender/blenkernel/BKE_mesh_boolean_convert.hh +++ b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh @@ -23,6 +23,8 @@ namespace blender::meshintersect { * \param material_remaps: An array of maps from material slot numbers in the corresponding mesh * to the material slot in the first mesh. It is OK for material_remaps or any of its constituent * arrays to be empty. + * \param r_intersecting_edges: Array to store indices of edges on the resulting mesh in. These + * 'new' edges are the result of the intersections. */ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, Span<const float4x4 *> transforms, @@ -30,6 +32,7 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, Span<Array<short>> material_remaps, bool use_self, bool hole_tolerant, - int boolean_mode); + int boolean_mode, + Vector<int> *r_intersecting_edges); } // namespace blender::meshintersect diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index e2b16a7681d..ee0179c7a77 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -42,7 +42,7 @@ void BKE_mesh_remap_free(MeshPairRemap *map); void BKE_mesh_remap_item_define_invalid(MeshPairRemap *map, int index); /* TODO: - * Add other 'from/to' mapping sources, like e.g. using an UVMap, etc. + * Add other 'from/to' mapping sources, like e.g. using a UVMap, etc. * https://blenderartists.org/t/619105 * * We could also use similar topology mappings inside a same mesh diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh index 37c2ad7d3cb..cbbd0249f4f 100644 --- a/source/blender/blenkernel/BKE_mesh_sample.hh +++ b/source/blender/blenkernel/BKE_mesh_sample.hh @@ -6,12 +6,20 @@ * \ingroup bke */ +#include "BLI_function_ref.hh" #include "BLI_generic_virtual_array.hh" #include "BLI_math_vec_types.hh" +#include "DNA_meshdata_types.h" + #include "BKE_attribute.h" struct Mesh; +struct BVHTreeFromMesh; + +namespace blender { +class RandomNumberGenerator; +} namespace blender::bke { struct ReadAttributeLookup; @@ -82,4 +90,55 @@ class MeshAttributeInterpolator { Span<float3> ensure_nearest_weights(); }; +/** + * Find randomly distributed points on the surface of a mesh within a 3D sphere. This does not + * sample an exact number of points because it comes with extra overhead to avoid bias that is only + * required in some cases. If an exact number of points is required, that has to be implemented at + * a higher level. + * + * \param approximate_density: Roughly the number of points per unit of area. + * \return The number of added points. + */ +int sample_surface_points_spherical(RandomNumberGenerator &rng, + const Mesh &mesh, + Span<int> looptri_indices_to_sample, + const float3 &sample_pos, + float sample_radius, + float approximate_density, + Vector<float3> &r_bary_coords, + Vector<int> &r_looptri_indices, + Vector<float3> &r_positions); + +/** + * Find randomly distributed points on the surface of a mesh within a circle that is projected on + * the mesh. This does not result in an exact number of points because that would come with extra + * overhead and is not always possible. If an exact number of points is required, that has to be + * implemented at a higher level. + * + * \param region_position_to_ray: Function that converts a 2D position into a 3D ray that is used + * to find positions on the mesh. + * \param mesh_bvhtree: BVH tree of the triangles in the mesh. Passed in so that it does not have + * to be retrieved again. + * \param tries_num: Number of 2d positions that are sampled. The maximum + * number of new samples. + * \return The number of added points. + */ +int sample_surface_points_projected( + RandomNumberGenerator &rng, + const Mesh &mesh, + BVHTreeFromMesh &mesh_bvhtree, + const float2 &sample_pos_re, + float sample_radius_re, + FunctionRef<void(const float2 &pos_re, float3 &r_start, float3 &r_end)> region_position_to_ray, + bool front_face_only, + int tries_num, + int max_points, + Vector<float3> &r_bary_coords, + Vector<int> &r_looptri_indices, + Vector<float3> &r_positions); + +float3 compute_bary_coord_in_triangle(const Mesh &mesh, + const MLoopTri &looptri, + const float3 &position); + } // namespace blender::bke::mesh_surface_sample diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 7ec8000b6f9..59a1599e7ae 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1495,6 +1495,7 @@ struct TexResult; #define GEO_NODE_REMOVE_ATTRIBUTE 1158 #define GEO_NODE_INPUT_INSTANCE_ROTATION 1159 #define GEO_NODE_INPUT_INSTANCE_SCALE 1160 +#define GEO_NODE_VOLUME_CUBE 1161 /** \} */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 6ffb3299869..aa09541c043 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -949,30 +949,9 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph), } \ (void)0 -static void custom_space_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) +static bool is_custom_space_needed(bConstraint *con) { - func(con, (ID **)&con->space_object, false, userdata); -} - -static int get_space_tar(bConstraint *con, ListBase *list) -{ - if (!con || !list || - (con->ownspace != CONSTRAINT_SPACE_CUSTOM && con->tarspace != CONSTRAINT_SPACE_CUSTOM)) { - return 0; - } - bConstraintTarget *ct; - SINGLETARGET_GET_TARS(con, con->space_object, con->space_subtarget, ct, list); - return 1; -} - -static void flush_space_tar(bConstraint *con, ListBase *list, bool no_copy) -{ - if (!con || !list || - (con->ownspace != CONSTRAINT_SPACE_CUSTOM && con->tarspace != CONSTRAINT_SPACE_CUSTOM)) { - return; - } - bConstraintTarget *ct = (bConstraintTarget *)list->last; - SINGLETARGET_FLUSH_TARS(con, con->space_object, con->space_subtarget, ct, list, no_copy); + return con->ownspace == CONSTRAINT_SPACE_CUSTOM || con->tarspace == CONSTRAINT_SPACE_CUSTOM; } /* --------- ChildOf Constraint ------------ */ @@ -1161,8 +1140,6 @@ static void trackto_id_looper(bConstraint *con, ConstraintIDFunc func, void *use /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int trackto_get_tars(bConstraint *con, ListBase *list) @@ -1174,7 +1151,7 @@ static int trackto_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -1188,7 +1165,6 @@ static void trackto_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -1661,11 +1637,11 @@ static bConstraintTypeInfo CTI_LOCLIMIT = { "Limit Location", /* name */ "bLocLimitConstraint", /* struct name */ NULL, /* free data */ - custom_space_id_looper, /* id looper */ + NULL, /* id looper */ NULL, /* copy data */ NULL, /* new data */ - get_space_tar, /* get constraint targets */ - flush_space_tar, /* flush constraint targets */ + NULL, /* get constraint targets */ + NULL, /* flush constraint targets */ NULL, /* get target matrix */ loclimit_evaluate, /* evaluate */ }; @@ -1742,11 +1718,11 @@ static bConstraintTypeInfo CTI_ROTLIMIT = { "Limit Rotation", /* name */ "bRotLimitConstraint", /* struct name */ NULL, /* free data */ - custom_space_id_looper, /* id looper */ + NULL, /* id looper */ NULL, /* copy data */ NULL, /* new data */ - get_space_tar, /* get constraint targets */ - flush_space_tar, /* flush constraint targets */ + NULL, /* get constraint targets */ + NULL, /* flush constraint targets */ NULL, /* get target matrix */ rotlimit_evaluate, /* evaluate */ }; @@ -1809,11 +1785,11 @@ static bConstraintTypeInfo CTI_SIZELIMIT = { "Limit Scale", /* name */ "bSizeLimitConstraint", /* struct name */ NULL, /* free data */ - custom_space_id_looper, /* id looper */ + NULL, /* id looper */ NULL, /* copy data */ NULL, /* new data */ - get_space_tar, /* get constraint targets */ - flush_space_tar, /* flush constraint targets */ + NULL, /* get constraint targets */ + NULL, /* flush constraint targets */ NULL, /* get target matrix */ sizelimit_evaluate, /* evaluate */ }; @@ -1833,8 +1809,6 @@ static void loclike_id_looper(bConstraint *con, ConstraintIDFunc func, void *use /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int loclike_get_tars(bConstraint *con, ListBase *list) @@ -1846,7 +1820,7 @@ static int loclike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -1860,7 +1834,6 @@ static void loclike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -1933,8 +1906,6 @@ static void rotlike_id_looper(bConstraint *con, ConstraintIDFunc func, void *use /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int rotlike_get_tars(bConstraint *con, ListBase *list) @@ -1946,7 +1917,7 @@ static int rotlike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -1960,7 +1931,6 @@ static void rotlike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -2114,8 +2084,6 @@ static void sizelike_id_looper(bConstraint *con, ConstraintIDFunc func, void *us /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int sizelike_get_tars(bConstraint *con, ListBase *list) @@ -2127,7 +2095,7 @@ static int sizelike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -2141,7 +2109,6 @@ static void sizelike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -2239,8 +2206,6 @@ static void translike_id_looper(bConstraint *con, ConstraintIDFunc func, void *u /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int translike_get_tars(bConstraint *con, ListBase *list) @@ -2252,7 +2217,7 @@ static int translike_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -2266,7 +2231,6 @@ static void translike_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -2400,11 +2364,11 @@ static bConstraintTypeInfo CTI_SAMEVOL = { "Maintain Volume", /* name */ "bSameVolumeConstraint", /* struct name */ NULL, /* free data */ - custom_space_id_looper, /* id looper */ + NULL, /* id looper */ NULL, /* copy data */ samevolume_new_data, /* new data */ - get_space_tar, /* get constraint targets */ - flush_space_tar, /* flush constraint targets */ + NULL, /* get constraint targets */ + NULL, /* flush constraint targets */ NULL, /* get target matrix */ samevolume_evaluate, /* evaluate */ }; @@ -2810,8 +2774,6 @@ static void actcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *user /* action */ func(con, (ID **)&data->act, true, userdata); - - custom_space_id_looper(con, func, userdata); } static int actcon_get_tars(bConstraint *con, ListBase *list) @@ -2823,7 +2785,7 @@ static int actcon_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -2837,7 +2799,6 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -3338,8 +3299,6 @@ static void distlimit_id_looper(bConstraint *con, ConstraintIDFunc func, void *u /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int distlimit_get_tars(bConstraint *con, ListBase *list) @@ -3351,7 +3310,7 @@ static int distlimit_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -3365,7 +3324,6 @@ static void distlimit_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -3694,8 +3652,6 @@ static void minmax_id_looper(bConstraint *con, ConstraintIDFunc func, void *user /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int minmax_get_tars(bConstraint *con, ListBase *list) @@ -3707,7 +3663,7 @@ static int minmax_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -3721,7 +3677,6 @@ static void minmax_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -4019,8 +3974,6 @@ static void transform_id_looper(bConstraint *con, ConstraintIDFunc func, void *u /* target only */ func(con, (ID **)&data->tar, false, userdata); - - custom_space_id_looper(con, func, userdata); } static int transform_get_tars(bConstraint *con, ListBase *list) @@ -4032,7 +3985,7 @@ static int transform_get_tars(bConstraint *con, ListBase *list) /* standard target-getting macro for single-target constraints */ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list); - return 1 + get_space_tar(con, list); + return 1; } return 0; @@ -4046,7 +3999,6 @@ static void transform_flush_tars(bConstraint *con, ListBase *list, bool no_copy) /* the following macro is used for all standard single-target constraints */ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, no_copy); - flush_space_tar(con, list, no_copy); } } @@ -5582,6 +5534,19 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), } } +/** Helper function to invoke the id_looper callback, including custom space. */ +static void con_invoke_id_looper(const bConstraintTypeInfo *cti, + bConstraint *con, + ConstraintIDFunc func, + void *userdata) +{ + if (cti->id_looper) { + cti->id_looper(con, func, userdata); + } + + func(con, (ID **)&con->space_object, false, userdata); +} + void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user) { if (con->data) { @@ -5594,8 +5559,8 @@ void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user) } /* unlink the referenced resources it uses */ - if (do_id_user && cti->id_looper) { - cti->id_looper(con, con_unlink_refs_cb, NULL); + if (do_id_user) { + con_invoke_id_looper(cti, con, con_unlink_refs_cb, NULL); } } @@ -5913,9 +5878,7 @@ void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *use const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti) { - if (cti->id_looper) { - cti->id_looper(con, func, userdata); - } + con_invoke_id_looper(cti, con, func, userdata); } } } @@ -5967,16 +5930,14 @@ static void constraint_copy_data_ex(bConstraint *dst, } /* Fix usercounts for all referenced data that need it. */ - if (cti->id_looper && (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { - cti->id_looper(dst, con_fix_copied_refs_cb, NULL); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + con_invoke_id_looper(cti, dst, con_fix_copied_refs_cb, NULL); } /* for proxies we don't want to make extern */ if (do_extern) { /* go over used ID-links for this constraint to ensure that they are valid for proxies */ - if (cti->id_looper) { - cti->id_looper(dst, con_extern_cb, NULL); - } + con_invoke_id_looper(cti, dst, con_extern_cb, NULL); } } } @@ -6208,6 +6169,15 @@ int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targe count = cti->get_constraint_targets(con, r_targets); } + /* Add the custom target. */ + if (is_custom_space_needed(con)) { + bConstraintTarget *ct; + SINGLETARGET_GET_TARS(con, con->space_object, con->space_subtarget, ct, r_targets); + ct->space = CONSTRAINT_SPACE_WORLD; + ct->flag |= CONSTRAINT_TAR_CUSTOM_SPACE; + count++; + } + return count; } @@ -6219,6 +6189,20 @@ void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targ return; } + /* Remove the custom target. */ + bConstraintTarget *ct = (bConstraintTarget *)targets->last; + + if (ct && (ct->flag & CONSTRAINT_TAR_CUSTOM_SPACE)) { + BLI_assert(is_custom_space_needed(con)); + + if (!no_copy) { + con->space_object = ct->tar; + BLI_strncpy(con->space_subtarget, ct->subtarget, sizeof(con->space_subtarget)); + } + + BLI_freelinkN(targets, ct); + } + /* Release the constraint-specific targets. */ if (cti->flush_constraint_targets) { cti->flush_constraint_targets(con, targets, no_copy); diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 1c3715aaf69..b58781ce806 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -1370,6 +1370,7 @@ void CurvesGeometry::remove_curves(const IndexMask curves_to_delete) } if (curves_to_delete.size() == this->curves_num()) { *this = {}; + return; } *this = copy_with_removed_curves(*this, curves_to_delete); } diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index f2915a97746..7722c2fa004 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -868,8 +868,6 @@ static void do_texture_effector(EffectorCache *eff, return; } - result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL; - strength = eff->pd->f_strength * efd->falloff; copy_v3_v3(tex_co, point->loc); diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 06d32d5bfd4..5cd5a699dec 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -1942,7 +1942,6 @@ static void sample_mesh(FluidFlowSettings *ffs, tex_co[1] = tex_co[1] * 2.0f - 1.0f; tex_co[2] = ffs->texture_offset; } - texres.nor = NULL; BKE_texture_get_value(NULL, ffs->noise_texture, tex_co, &texres, false); emission_strength *= texres.tin; } diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 5ef4d231807..0bf5418ea8f 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -678,7 +678,7 @@ static void copy_frame_to_eval_cb(bGPDlayer *gpl, static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *scene, Object *ob) { - /* Remap layers'active frame with time modifiers applied. */ + /* Remap layers active frame with time modifiers applied. */ bGPdata *gpd_eval = ob->data; LISTBASE_FOREACH (bGPDlayer *, gpl_eval, &gpd_eval->layers) { bGPDframe *gpf_eval = gpl_eval->actframe; diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index b9bb536d173..0c1f01c3796 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -1730,7 +1730,7 @@ static void stampdata_from_template(StampData *stamp_data, stamp_data->file[0] = '\0'; } if (scene->r.stamp & R_STAMP_NOTE) { - SNPRINTF(stamp_data->note, "%s", stamp_data_template->note); + STRNCPY(stamp_data->note, stamp_data_template->note); } else { stamp_data->note[0] = '\0'; diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc index 22012662180..0b91a1e2866 100644 --- a/source/blender/blenkernel/intern/lib_override.cc +++ b/source/blender/blenkernel/intern/lib_override.cc @@ -687,6 +687,51 @@ static void lib_override_group_tag_data_clear(LibOverrideGroupTagData *data) memset(data, 0, sizeof(*data)); } +static void lib_override_hierarchy_dependencies_recursive_tag_from(LibOverrideGroupTagData *data) +{ + Main *bmain = data->bmain; + ID *id = data->id_root; + const bool is_override = data->is_override; + + if ((*(uint *)&id->tag & data->tag) == 0) { + /* This ID is not tagged, no reason to proceed further to its parents. */ + return; + } + + MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>( + BLI_ghash_lookup(bmain->relations->relations_from_pointers, id)); + BLI_assert(entry != nullptr); + + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_FROM) { + /* This ID has already been processed. */ + return; + } + /* This way we won't process again that ID, should we encounter it again through another + * relationship hierarchy. */ + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_FROM; + + for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != nullptr; + from_id_entry = from_id_entry->next) { + if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) { + /* Never consider non-overridable relationships ('from', 'parents', 'owner' etc. pointers) + * as actual dependencies. */ + continue; + } + /* We only consider IDs from the same library. */ + ID *from_id = from_id_entry->id_pointer.from; + if (from_id == nullptr || from_id->lib != id->lib || + (is_override && !ID_IS_OVERRIDE_LIBRARY(from_id))) { + /* IDs from different libraries, or non-override IDs in case we are processing overrides, + * are both barriers of dependency. */ + continue; + } + from_id->tag |= data->tag; + LibOverrideGroupTagData sub_data = *data; + sub_data.id_root = from_id; + lib_override_hierarchy_dependencies_recursive_tag_from(&sub_data); + } +} + /* Tag all IDs in dependency relationships within an override hierarchy/group. * * Requires existing `Main.relations`. @@ -703,13 +748,13 @@ static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTa BLI_ghash_lookup(bmain->relations->relations_from_pointers, id)); BLI_assert(entry != nullptr); - if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO) { /* This ID has already been processed. */ return (*(uint *)&id->tag & data->tag) != 0; } /* This way we won't process again that ID, should we encounter it again through another * relationship hierarchy. */ - entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO; for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr; to_id_entry = to_id_entry->next) { @@ -733,6 +778,15 @@ static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTa } } + /* If the current ID is/has been tagged for override above, then check its reversed dependencies + * (i.e. IDs that depend on the current one). + * + * This will cover e.g. the case where user override an armature, and would expect the mesh + * object deformed by that armature to also be overridden. */ + if ((*(uint *)&id->tag & data->tag) != 0) { + lib_override_hierarchy_dependencies_recursive_tag_from(data); + } + return (*(uint *)&id->tag & data->tag) != 0; } diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index 14bd6aa5b2f..a1ef2d2e6b5 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -791,7 +791,8 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, Span<Array<short>> material_remaps, const bool use_self, const bool hole_tolerant, - const int boolean_mode) + const int boolean_mode, + Vector<int> *r_intersecting_edges) { #ifdef WITH_GMP BLI_assert(meshes.size() == transforms.size()); @@ -828,7 +829,23 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, write_obj_mesh(m_out, "m_out"); } - return imesh_to_mesh(&m_out, mim); + Mesh *result = imesh_to_mesh(&m_out, mim); + + /* Store intersecting edge indices. */ + if (r_intersecting_edges != nullptr) { + for (int fi : m_out.face_index_range()) { + const Face &face = *m_out.face(fi); + const MPoly &poly = result->mpoly[fi]; + for (int corner_i : face.index_range()) { + if (face.is_intersect[corner_i]) { + int e_index = result->mloop[poly.loopstart + corner_i].e; + r_intersecting_edges->append(e_index); + } + } + } + } + + return result; #else // WITH_GMP UNUSED_VARS(meshes, transforms, @@ -836,7 +853,8 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, target_transform, use_self, hole_tolerant, - boolean_mode); + boolean_mode, + r_intersecting_edges); return nullptr; #endif // WITH_GMP } diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 7595c08a208..106c4c610ba 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -2,12 +2,15 @@ #include "BKE_attribute_access.hh" #include "BKE_attribute_math.hh" +#include "BKE_bvhutils.h" #include "BKE_mesh_runtime.h" #include "BKE_mesh_sample.hh" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "BLI_rand.hh" + namespace blender::bke::mesh_surface_sample { template<typename T> @@ -259,4 +262,173 @@ void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_ } } +int sample_surface_points_spherical(RandomNumberGenerator &rng, + const Mesh &mesh, + const Span<int> looptri_indices_to_sample, + const float3 &sample_pos, + const float sample_radius, + const float approximate_density, + Vector<float3> &r_bary_coords, + Vector<int> &r_looptri_indices, + Vector<float3> &r_positions) +{ + const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), + BKE_mesh_runtime_looptri_len(&mesh)}; + + const float sample_radius_sq = pow2f(sample_radius); + const float sample_plane_area = M_PI * sample_radius_sq; + /* Used for switching between two triangle sampling strategies. */ + const float area_threshold = sample_plane_area; + + const int old_num = r_bary_coords.size(); + + for (const int looptri_index : looptri_indices_to_sample) { + const MLoopTri &looptri = looptris[looptri_index]; + + const float3 &v0 = mesh.mvert[mesh.mloop[looptri.tri[0]].v].co; + const float3 &v1 = mesh.mvert[mesh.mloop[looptri.tri[1]].v].co; + const float3 &v2 = mesh.mvert[mesh.mloop[looptri.tri[2]].v].co; + + const float looptri_area = area_tri_v3(v0, v1, v2); + + if (looptri_area < area_threshold) { + /* The triangle is small compared to the sample radius. Sample by generating random + * barycentric coordinates. */ + const int amount = rng.round_probabilistic(approximate_density * looptri_area); + for ([[maybe_unused]] const int i : IndexRange(amount)) { + const float3 bary_coord = rng.get_barycentric_coordinates(); + const float3 point_pos = attribute_math::mix3(bary_coord, v0, v1, v2); + const float dist_to_sample_sq = math::distance_squared(point_pos, sample_pos); + if (dist_to_sample_sq > sample_radius_sq) { + continue; + } + + r_bary_coords.append(bary_coord); + r_looptri_indices.append(looptri_index); + r_positions.append(point_pos); + } + } + else { + /* The triangle is large compared to the sample radius. Sample by generating random points + * on the triangle plane within the sample radius. */ + float3 normal; + normal_tri_v3(normal, v0, v1, v2); + + float3 sample_pos_proj = sample_pos; + project_v3_plane(sample_pos_proj, normal, v0); + + const float proj_distance_sq = math::distance_squared(sample_pos_proj, sample_pos); + const float sample_radius_factor_sq = 1.0f - + std::min(1.0f, proj_distance_sq / sample_radius_sq); + const float radius_proj_sq = sample_radius_sq * sample_radius_factor_sq; + const float radius_proj = std::sqrt(radius_proj_sq); + const float circle_area = M_PI * radius_proj; + + const int amount = rng.round_probabilistic(approximate_density * circle_area); + + const float3 axis_1 = math::normalize(v1 - v0) * radius_proj; + const float3 axis_2 = math::normalize(math::cross(axis_1, math::cross(axis_1, v2 - v0))) * + radius_proj; + + for ([[maybe_unused]] const int i : IndexRange(amount)) { + const float r = std::sqrt(rng.get_float()); + const float angle = rng.get_float() * 2.0f * M_PI; + const float x = r * std::cos(angle); + const float y = r * std::sin(angle); + const float3 point_pos = sample_pos_proj + axis_1 * x + axis_2 * y; + if (!isect_point_tri_prism_v3(point_pos, v0, v1, v2)) { + /* Sampled point is not in the triangle. */ + continue; + } + + float3 bary_coord; + interp_weights_tri_v3(bary_coord, v0, v1, v2, point_pos); + + r_bary_coords.append(bary_coord); + r_looptri_indices.append(looptri_index); + r_positions.append(point_pos); + } + } + } + return r_bary_coords.size() - old_num; +} + +int sample_surface_points_projected( + RandomNumberGenerator &rng, + const Mesh &mesh, + BVHTreeFromMesh &mesh_bvhtree, + const float2 &sample_pos_re, + const float sample_radius_re, + const FunctionRef<void(const float2 &pos_re, float3 &r_start, float3 &r_end)> + region_position_to_ray, + const bool front_face_only, + const int tries_num, + const int max_points, + Vector<float3> &r_bary_coords, + Vector<int> &r_looptri_indices, + Vector<float3> &r_positions) +{ + const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh), + BKE_mesh_runtime_looptri_len(&mesh)}; + + int point_count = 0; + for ([[maybe_unused]] const int _ : IndexRange(tries_num)) { + if (point_count == max_points) { + break; + } + + const float r = sample_radius_re * std::sqrt(rng.get_float()); + const float angle = rng.get_float() * 2.0f * M_PI; + float3 ray_start, ray_end; + const float2 pos_re = sample_pos_re + r * float2(std::cos(angle), std::sin(angle)); + region_position_to_ray(pos_re, ray_start, ray_end); + const float3 ray_direction = math::normalize(ray_end - ray_start); + + BVHTreeRayHit ray_hit; + ray_hit.dist = FLT_MAX; + ray_hit.index = -1; + BLI_bvhtree_ray_cast(mesh_bvhtree.tree, + ray_start, + ray_direction, + 0.0f, + &ray_hit, + mesh_bvhtree.raycast_callback, + &mesh_bvhtree); + + if (ray_hit.index == -1) { + continue; + } + + if (front_face_only) { + const float3 normal = ray_hit.no; + if (math::dot(ray_direction, normal) >= 0.0f) { + continue; + } + } + + const int looptri_index = ray_hit.index; + const float3 pos = ray_hit.co; + + const float3 bary_coords = compute_bary_coord_in_triangle(mesh, looptris[looptri_index], pos); + + r_positions.append(pos); + r_bary_coords.append(bary_coords); + r_looptri_indices.append(looptri_index); + point_count++; + } + return point_count; +} + +float3 compute_bary_coord_in_triangle(const Mesh &mesh, + const MLoopTri &looptri, + const float3 &position) +{ + const float3 &v0 = mesh.mvert[mesh.mloop[looptri.tri[0]].v].co; + const float3 &v1 = mesh.mvert[mesh.mloop[looptri.tri[1]].v].co; + const float3 &v2 = mesh.mvert[mesh.mloop[looptri.tri[2]].v].co; + float3 bary_coords; + interp_weights_tri_v3(bary_coords, v0, v1, v2, position); + return bary_coords; +} + } // namespace blender::bke::mesh_surface_sample diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c index c0b2b33c47c..a677a0d6ebb 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.c +++ b/source/blender/blenkernel/intern/mesh_tangent.c @@ -167,7 +167,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, if (!loopuvs) { BKE_reportf(reports, RPT_ERROR, - "Tangent space computation needs an UVMap, \"%s\" not found, aborting", + "Tangent space computation needs a UV Map, \"%s\" not found, aborting", uvmap); return; } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 8f54d71108a..10abb8f20df 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -252,12 +252,15 @@ static NlaStrip *find_active_strip_from_listbase(const NlaStrip *active_strip, const ListBase /* NlaStrip */ *strips_source, const ListBase /* NlaStrip */ *strips_dest) { + BLI_assert_msg(BLI_listbase_count(strips_source) == BLI_listbase_count(strips_dest), + "Expecting the same number of source and destination strips"); + NlaStrip *strip_dest = strips_dest->first; LISTBASE_FOREACH (const NlaStrip *, strip_source, strips_source) { if (strip_dest == NULL) { - /* The tracks are assumed to have an equal number of strips, but this is not the case when - * dragging multiple strips. The transform system merges the selected strips into one - * meta-strip, reducing the number of strips in `track_dest`. */ + /* The tracks are assumed to have an equal number of strips, but this is + * not the case. Not sure when this might happen, but it's better to not + * crash. */ break; } if (strip_source == active_strip) { @@ -282,7 +285,9 @@ static NlaStrip *find_active_strip_from_listbase(const NlaStrip *active_strip, return NULL; } -/* Set adt_dest->actstrip to the strip with the same index as adt_source->actstrip. */ +/* Set adt_dest->actstrip to the strip with the same index as + * adt_source->actstrip. Note that this always sets `adt_dest->actstrip`; sets + * to NULL when `adt_source->actstrip` cannot be found. */ static void update_active_strip(AnimData *adt_dest, NlaTrack *track_dest, const AnimData *adt_source, @@ -298,6 +303,12 @@ static void update_active_strip(AnimData *adt_dest, /* Set adt_dest->act_track to the track with the same index as adt_source->act_track. */ static void update_active_track(AnimData *adt_dest, const AnimData *adt_source) { + adt_dest->act_track = NULL; + adt_dest->actstrip = NULL; + if (adt_source->act_track == NULL && adt_source->actstrip == NULL) { + return; + } + BLI_assert(BLI_listbase_count(&adt_source->nla_tracks) == BLI_listbase_count(&adt_dest->nla_tracks)); @@ -306,7 +317,11 @@ static void update_active_track(AnimData *adt_dest, const AnimData *adt_source) if (track_source == adt_source->act_track) { adt_dest->act_track = track_dest; } - update_active_strip(adt_dest, track_dest, adt_source, track_source); + + /* Only search for the active strip if it hasn't been found yet. */ + if (adt_dest->actstrip == NULL && adt_source->actstrip != NULL) { + update_active_strip(adt_dest, track_dest, adt_source, track_source); + } track_dest = track_dest->next; } diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 1ffc4a56a0e..e02d3b6486c 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -4836,6 +4836,7 @@ static void registerGeometryNodes() register_node_type_geo_translate_instances(); register_node_type_geo_triangulate(); register_node_type_geo_viewer(); + register_node_type_geo_volume_cube(); register_node_type_geo_volume_to_mesh(); } diff --git a/source/blender/blenlib/BLI_generic_virtual_array.hh b/source/blender/blenlib/BLI_generic_virtual_array.hh index 3fce2947d0d..985d914f4a4 100644 --- a/source/blender/blenlib/BLI_generic_virtual_array.hh +++ b/source/blender/blenlib/BLI_generic_virtual_array.hh @@ -934,15 +934,15 @@ template<typename T> inline GVArray::GVArray(const VArray<T> &varray) if (varray.try_assign_GVArray(*this)) { return; } - /* Need to check this before the span/single special cases, because otherwise we might loose - * ownership to the referenced data when #varray goes out of scope. */ - if (varray.may_have_ownership()) { - *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray); - } - else if (varray.is_single()) { + if (varray.is_single()) { T value = varray.get_internal_single(); *this = GVArray::ForSingle(CPPType::get<T>(), varray.size(), &value); } + /* Need to check this before the span special case, because otherwise we might loose + * ownership to the referenced data when #varray goes out of scope. */ + else if (varray.may_have_ownership()) { + *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray); + } else if (varray.is_span()) { Span<T> data = varray.get_internal_span(); *this = GVArray::ForSpan(data); @@ -962,14 +962,14 @@ template<typename T> inline VArray<T> GVArray::typed() const if (this->try_assign_VArray(varray)) { return varray; } - if (this->may_have_ownership()) { - return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this); - } if (this->is_single()) { T value; this->get_internal_single(&value); return VArray<T>::ForSingle(value, this->size()); } + if (this->may_have_ownership()) { + return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this); + } if (this->is_span()) { const Span<T> span = this->get_internal_span().typed<T>(); return VArray<T>::ForSpan(span); diff --git a/source/blender/blenlib/BLI_math_base.hh b/source/blender/blenlib/BLI_math_base.hh index 3057e30dc03..b15179f75b6 100644 --- a/source/blender/blenlib/BLI_math_base.hh +++ b/source/blender/blenlib/BLI_math_base.hh @@ -44,6 +44,16 @@ template<typename T> inline T max(const T &a, const T &b) return std::max(a, b); } +template<typename T> inline void max_inplace(T &a, const T &b) +{ + a = math::max(a, b); +} + +template<typename T> inline void min_inplace(T &a, const T &b) +{ + a = math::min(a, b); +} + template<typename T> inline T clamp(const T &a, const T &min, const T &max) { return std::clamp(a, min, max); diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 109230ebfa7..95b4987596e 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -445,6 +445,7 @@ if(WITH_GTESTS) tests/BLI_index_range_test.cc tests/BLI_inplace_priority_queue_test.cc tests/BLI_kdopbvh_test.cc + tests/BLI_kdtree_test.cc tests/BLI_length_parameterize_test.cc tests/BLI_linear_allocator_test.cc tests/BLI_linklist_lockfree_test.cc diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h index d9ae826093c..6614f1bf964 100644 --- a/source/blender/blenlib/intern/kdtree_impl.h +++ b/source/blender/blenlib/intern/kdtree_impl.h @@ -927,6 +927,14 @@ int BLI_kdtree_nd_(calc_duplicates_fast)(const KDTree *tree, /** \name BLI_kdtree_3d_deduplicate * \{ */ +static int kdtree_cmp_bool(const bool a, const bool b) +{ + if (a == b) { + return 0; + } + return b ? -1 : 1; +} + static int kdtree_node_cmp_deduplicate(const void *n0_p, const void *n1_p) { const KDTreeNode *n0 = n0_p; @@ -939,17 +947,16 @@ static int kdtree_node_cmp_deduplicate(const void *n0_p, const void *n1_p) return 1; } } - /* Sort by pointer so the first added will be used. - * assignment below ignores const correctness, - * however the values aren't used for sorting and are to be discarded. */ - if (n0 < n1) { - ((KDTreeNode *)n1)->d = KD_DIMS; /* tag invalid */ - return -1; - } - else { - ((KDTreeNode *)n0)->d = KD_DIMS; /* tag invalid */ - return 1; + + if (n0->d != KD_DIMS && n1->d != KD_DIMS) { + /* Two nodes share identical `co` + * Both are still valid. + * Cast away `const` and tag one of them as invalid. */ + ((KDTreeNode *)n1)->d = KD_DIMS; } + + /* Keep sorting until each unique value has one and only one valid node. */ + return kdtree_cmp_bool(n0->d == KD_DIMS, n1->d == KD_DIMS); } /** diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 94efb0dd9e7..0cbf62cce03 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -363,6 +363,10 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, int BLI_wcwidth(char32_t ucs) { + /* Treat private use areas (icon fonts), symbols, and emoticons as double-width. */ + if (ucs >= 0xf0000 || (ucs >= 0xe000 && ucs < 0xf8ff) || (ucs >= 0x1f300 && ucs < 0x1fbff)) { + return 2; + } return mk_wcwidth(ucs); } diff --git a/source/blender/blenlib/tests/BLI_kdtree_test.cc b/source/blender/blenlib/tests/BLI_kdtree_test.cc new file mode 100644 index 00000000000..f8675ef332d --- /dev/null +++ b/source/blender/blenlib/tests/BLI_kdtree_test.cc @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "testing/testing.h" + +#include "BLI_kdtree.h" + +#include <math.h> + +/* -------------------------------------------------------------------- */ +/* Tests */ + +static void standard_test() +{ + for (int tree_size = 30; tree_size < 500; tree_size++) { + int tree_index = 0; + KDTree_1d *tree = BLI_kdtree_1d_new(tree_size); + int mask = tree_size & 31; + bool occupied[32] = {false}; + + for (int i = 0; i < tree_size; i++) { + int index = i & mask; + occupied[index] = true; + float value = fmodf(index * 7.121f, 0.6037f); /* Co-prime. */ + float key[1] = {value}; + BLI_kdtree_1d_insert(tree, tree_index++, key); + } + int expected = 0; + for (int j = 0; j < 32; j++) { + if (occupied[j]) { + expected++; + } + } + + int dedup_count = BLI_kdtree_1d_deduplicate(tree); + EXPECT_EQ(dedup_count, expected); + BLI_kdtree_1d_free(tree); + } +} + +static void deduplicate_test() +{ + for (int tree_size = 1; tree_size < 40; tree_size++) { + int tree_index = 0; + KDTree_1d *tree = BLI_kdtree_1d_new(tree_size); + for (int i = 0; i < tree_size; i++) { + float key[1] = {1.0f}; + BLI_kdtree_1d_insert(tree, tree_index++, key); + } + int dedup_count = BLI_kdtree_1d_deduplicate(tree); + EXPECT_EQ(dedup_count, 1); + BLI_kdtree_1d_free(tree); + } +} + +TEST(kdtree, Standard) +{ + standard_test(); +} + +TEST(kdtree, Deduplicate) +{ + deduplicate_test(); +} diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index eafb27f9758..e542bc46a28 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -4102,7 +4102,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) LISTBASE_FOREACH (Object *, ob, &bmain->objects) { LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { if (md->type == eModifierType_DataTransfer) { - /* Now datatransfer's mix factor is multiplied with weights when any, + /* Now data-transfer's mix factor is multiplied with weights when any, * instead of being ignored, * we need to take care of that to keep 'old' files compatible. */ DataTransferModifierData *dtmd = (DataTransferModifierData *)md; diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 97b414d4b4a..5af42f9f1f6 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -3084,6 +3084,18 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; } + if (!MAIN_VERSION_ATLEAST(bmain, 303, 2)) { + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_CLIP) { + ((SpaceClip *)sl)->mask_info.blend_factor = 1.0; + } + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f65976ee55f..91b2f509a7f 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -184,6 +184,7 @@ static void blo_update_defaults_screen(bScreen *screen, else if (area->spacetype == SPACE_CLIP) { SpaceClip *sclip = area->spacedata.first; sclip->around = V3D_AROUND_CENTER_MEDIAN; + sclip->mask_info.blend_factor = 0.7f; } } diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index d12ce7213f9..4528027a9ea 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -125,7 +125,8 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, struct GPUShader *sh, DRWPass **pass, bool upsample, - bool resolve) + bool resolve, + bool resolve_add_base) { struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); @@ -141,7 +142,7 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, } if (resolve) { DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1); - DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", true); + DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", resolve_add_base); } return grp; @@ -193,18 +194,21 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved EEVEE_shaders_bloom_downsample_get(use_antiflicker), &psl->bloom_downsample_first, false, + false, false); eevee_create_bloom_pass("Bloom Downsample", effects, EEVEE_shaders_bloom_downsample_get(false), &psl->bloom_downsample, false, + false, false); eevee_create_bloom_pass("Bloom Upsample", effects, EEVEE_shaders_bloom_upsample_get(use_highres), &psl->bloom_upsample, true, + false, false); grp = eevee_create_bloom_pass("Bloom Blit", @@ -212,6 +216,7 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved EEVEE_shaders_bloom_blit_get(use_antiflicker), &psl->bloom_blit, false, + false, false); DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1); DRW_shgroup_uniform_float(grp, "clampIntensity", &effects->bloom_clamp, 1); @@ -221,6 +226,7 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved EEVEE_shaders_bloom_resolve_get(use_highres), &psl->bloom_resolve, true, + true, true); } } @@ -304,13 +310,13 @@ void EEVEE_bloom_output_init(EEVEE_ViewLayerData *UNUSED(sldata), {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->bloom_accum)}); /* Create Pass and shgroup. */ - DRWShadingGroup *grp = eevee_create_bloom_pass("Bloom Accumulate", - effects, - EEVEE_shaders_bloom_resolve_get(use_highres), - &psl->bloom_accum_ps, - true, - true); - DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", false); + eevee_create_bloom_pass("Bloom Accumulate", + effects, + EEVEE_shaders_bloom_resolve_get(use_highres), + &psl->bloom_accum_ps, + true, + true, + false); } void EEVEE_bloom_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index 6fd5d97089d..5709621fc05 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -718,7 +718,7 @@ GPUShader *EEVEE_shaders_cryptomatte_sh_get(bool is_hair) if (e_data.cryptomatte_sh[index] == NULL) { DynStr *ds = BLI_dynstr_new(); BLI_dynstr_append(ds, SHADER_DEFINES); - BLI_dynstr_append(ds, "#define attrib_load(a) \n"); + BLI_dynstr_append(ds, "#define attrib_load() \n"); if (is_hair) { BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); } diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl index 0f5290a7c07..ffca97b6b8f 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl @@ -181,6 +181,8 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection) /* Glue with the old system. */ CLOSURE_VARS_DECLARE_2(Diffuse, Glossy); + /* WORKAROUND: This is to avoid regression in 3.2 and avoid messing with EEVEE-Next. */ + in_common.occlusion = (diffuse.sss_radius.g == -1.0) ? diffuse.sss_radius.r : 1.0; in_Diffuse_0.N = diffuse.N; in_Diffuse_0.albedo = diffuse.color; in_Glossy_1.N = reflection.N; @@ -207,6 +209,8 @@ Closure closure_eval(ClosureDiffuse diffuse, /* Glue with the old system. */ CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy); + /* WORKAROUND: This is to avoid regression in 3.2 and avoid messing with EEVEE-Next. */ + in_common.occlusion = (diffuse.sss_radius.g == -1.0) ? diffuse.sss_radius.r : 1.0; in_Diffuse_0.N = diffuse.N; in_Diffuse_0.albedo = diffuse.color; in_Glossy_1.N = reflection.N; diff --git a/source/blender/draw/intern/draw_attributes.cc b/source/blender/draw/intern/draw_attributes.cc index 8fb4210901f..3f187aef8e6 100644 --- a/source/blender/draw/intern/draw_attributes.cc +++ b/source/blender/draw/intern/draw_attributes.cc @@ -65,9 +65,10 @@ bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b) } DRW_AttributeRequest *drw_attributes_add_request(DRW_Attributes *attrs, - eCustomDataType type, - int layer, - eAttrDomain domain) + const char *name, + const eCustomDataType type, + const int layer_index, + const eAttrDomain domain) { if (attrs->num_requests >= GPU_MAX_ATTR) { return nullptr; @@ -75,7 +76,8 @@ DRW_AttributeRequest *drw_attributes_add_request(DRW_Attributes *attrs, DRW_AttributeRequest *req = &attrs->requests[attrs->num_requests]; req->cd_type = type; - req->layer_index = layer; + BLI_strncpy(req->attribute_name, name, sizeof(req->attribute_name)); + req->layer_index = layer_index; req->domain = domain; attrs->num_requests += 1; return req; diff --git a/source/blender/draw/intern/draw_attributes.h b/source/blender/draw/intern/draw_attributes.h index 4f82f3b94e9..b577c6c4162 100644 --- a/source/blender/draw/intern/draw_attributes.h +++ b/source/blender/draw/intern/draw_attributes.h @@ -46,8 +46,9 @@ void drw_attributes_merge(DRW_Attributes *dst, bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b); DRW_AttributeRequest *drw_attributes_add_request(DRW_Attributes *attrs, - eCustomDataType type, - int layer, + const char *name, + eCustomDataType data_type, + int layer_index, eAttrDomain domain); bool drw_custom_data_match_attribute(const CustomData *custom_data, diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 00005fd7b4c..380736ef656 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -155,7 +155,7 @@ struct ExtractTaskData { bool use_threading = false; ExtractTaskData(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, ExtractorRunDatas *extractors, MeshBufferList *mbuflist, const bool use_threading) @@ -193,7 +193,7 @@ static void extract_task_data_free(void *data) * \{ */ BLI_INLINE void extract_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, ExtractorRunDatas &extractors, MeshBufferList *mbuflist, void *data_stack) @@ -209,7 +209,7 @@ BLI_INLINE void extract_init(const MeshRenderData *mr, } BLI_INLINE void extract_finish(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, const ExtractorRunDatas &extractors, void *data_stack) { diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 0755d5967d5..4fa5813d476 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -156,11 +156,15 @@ struct GPUBatch *DRW_lattice_batch_cache_get_edit_verts(struct Lattice *lt); /** \} */ /* -------------------------------------------------------------------- */ -/** \name Hair +/** \name Curves * \{ */ int DRW_curves_material_count_get(struct Curves *curves); +struct GPUBatch *DRW_curves_batch_cache_get_edit_points(struct Curves *curves); + +void DRW_curves_batch_cache_create_requested(struct Object *ob); + /** \} */ /* -------------------------------------------------------------------- */ @@ -352,16 +356,6 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *ob /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Curves - * \{ */ - -struct GPUBatch *DRW_curves_batch_cache_get_edit_points(struct Curves *curves); - -void DRW_curves_batch_cache_create_requested(const struct Object *ob); - -/** \} */ - #ifdef __cplusplus } #endif diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc index 992ffe16a14..ee81f74ca26 100644 --- a/source/blender/draw/intern/draw_cache_impl_curves.cc +++ b/source/blender/draw/intern/draw_cache_impl_curves.cc @@ -87,13 +87,13 @@ static void curves_batch_cache_init(Curves &curves) static void curves_discard_attributes(CurvesEvalCache &curves_cache) { - for (int i = 0; i < GPU_MAX_ATTR; i++) { + for (const int i : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_attributes_buf[i]); DRW_TEXTURE_FREE_SAFE(curves_cache.proc_attributes_tex[i]); } - for (int i = 0; i < MAX_HAIR_SUBDIV; i++) { - for (int j = 0; j < GPU_MAX_ATTR; j++) { + for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { + for (const int j : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].attributes_buf[j]); DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].attributes_tex[j]); } @@ -115,10 +115,10 @@ static void curves_batch_cache_clear_data(CurvesEvalCache &curves_cache) DRW_TEXTURE_FREE_SAFE(curves_cache.strand_tex); DRW_TEXTURE_FREE_SAFE(curves_cache.strand_seg_tex); - for (int i = 0; i < MAX_HAIR_SUBDIV; i++) { + for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].proc_buf); DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].proc_tex); - for (int j = 0; j < MAX_THICKRES; j++) { + for (const int j : IndexRange(MAX_THICKRES)) { GPU_BATCH_DISCARD_SAFE(curves_cache.final[i].proc_hairs[j]); } } @@ -184,7 +184,7 @@ void DRW_curves_batch_cache_free_old(Curves *curves, int ctime) bool do_discard = false; - for (int i = 0; i < MAX_HAIR_SUBDIV; i++) { + for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { CurvesEvalFinalCache &final_cache = cache->curves_cache.final[i]; if (drw_attributes_overlap(&final_cache.attr_used_over_time, &final_cache.attr_used)) { @@ -515,48 +515,28 @@ static bool curves_ensure_attributes(const Curves &curves, ListBase gpu_attrs = GPU_material_attributes(gpu_material); LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) { const char *name = gpu_attr->name; - eCustomDataType type = static_cast<eCustomDataType>(gpu_attr->type); - int layer = -1; - eAttrDomain domain; - if (drw_custom_data_match_attribute(cd_curve, name, &layer, &type)) { + int layer_index; + eCustomDataType type; + eAttrDomain domain; + if (drw_custom_data_match_attribute(cd_curve, name, &layer_index, &type)) { domain = ATTR_DOMAIN_CURVE; } - else if (drw_custom_data_match_attribute(cd_point, name, &layer, &type)) { + else if (drw_custom_data_match_attribute(cd_point, name, &layer_index, &type)) { domain = ATTR_DOMAIN_POINT; } else { continue; } - switch (type) { - case CD_PROP_BOOL: - case CD_PROP_INT8: - case CD_PROP_INT32: - case CD_PROP_FLOAT: - case CD_PROP_FLOAT2: - case CD_PROP_FLOAT3: - case CD_PROP_COLOR: { - if (layer != -1) { - DRW_AttributeRequest *req = drw_attributes_add_request( - &attrs_needed, (eCustomDataType)type, layer, domain); - if (req) { - BLI_strncpy(req->attribute_name, name, sizeof(req->attribute_name)); - } - } - break; - } - default: - break; - } + drw_attributes_add_request(&attrs_needed, name, type, layer_index, domain); } CurvesEvalFinalCache &final_cache = cache.curves_cache.final[subdiv]; - const bool attr_overlap = drw_attributes_overlap(&final_cache.attr_used, &attrs_needed); - if (attr_overlap == false) { + if (!drw_attributes_overlap(&final_cache.attr_used, &attrs_needed)) { /* Some new attributes have been added, free all and start over. */ - for (int i = 0; i < GPU_MAX_ATTR; i++) { + for (const int i : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(cache.curves_cache.proc_attributes_buf[i]); DRW_TEXTURE_FREE_SAFE(cache.curves_cache.proc_attributes_tex[i]); } @@ -566,7 +546,7 @@ static bool curves_ensure_attributes(const Curves &curves, bool need_tf_update = false; - for (int i = 0; i < final_cache.attr_used.num_requests; i++) { + for (const int i : IndexRange(final_cache.attr_used.num_requests)) { const DRW_AttributeRequest &request = final_cache.attr_used.requests[i]; if (cache.curves_cache.proc_attributes_buf[i] != nullptr) { @@ -638,7 +618,7 @@ GPUBatch *DRW_curves_batch_cache_get_edit_points(Curves *curves) return DRW_batch_request(&cache.edit_points); } -void DRW_curves_batch_cache_create_requested(const Object *ob) +void DRW_curves_batch_cache_create_requested(Object *ob) { Curves *curves = static_cast<Curves *>(ob->data); CurvesBatchCache &cache = curves_batch_cache_get(*curves); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index 7c02ee2c033..e93b1a66b66 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -574,7 +574,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, } if (layer != -1 && domain.has_value()) { - drw_attributes_add_request(attributes, type, layer, *domain); + drw_attributes_add_request(attributes, name, type, layer, *domain); } break; } @@ -585,7 +585,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, case CD_PROP_FLOAT: case CD_PROP_FLOAT2: { if (layer != -1 && domain.has_value()) { - drw_attributes_add_request(attributes, type, layer, *domain); + drw_attributes_add_request(attributes, name, type, layer, *domain); } break; } diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index b37a420b555..afec92a894d 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -1204,8 +1204,8 @@ struct DRWSubdivUboStorage { * of out of bond accesses as compute dispatch are of fixed size. */ uint total_dispatch_size; - int _pad0; - int _pad2; + int is_edit_mode; + int use_hide; int _pad3; }; @@ -1236,6 +1236,8 @@ static void draw_subdiv_init_ubo_storage(const DRWSubdivCache *cache, ubo->coarse_face_hidden_mask = SUBDIV_COARSE_FACE_FLAG_HIDDEN_MASK; ubo->coarse_face_loopstart_mask = SUBDIV_COARSE_FACE_LOOP_START_MASK; ubo->total_dispatch_size = total_dispatch_size; + ubo->is_edit_mode = cache->is_edit_mode; + ubo->use_hide = cache->use_hide; } static void draw_subdiv_ubo_update_and_bind(const DRWSubdivCache *cache, @@ -2004,7 +2006,7 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache *cache, static bool draw_subdiv_create_requested_buffers(Object *ob, Mesh *mesh, - struct MeshBatchCache *batch_cache, + MeshBatchCache *batch_cache, MeshBufferCache *mbc, const bool is_editmode, const bool is_paint_mode, @@ -2083,6 +2085,12 @@ static bool draw_subdiv_create_requested_buffers(Object *ob, MeshRenderData *mr = mesh_render_data_create( ob, mesh, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts); mr->use_hide = use_hide; + draw_cache->use_hide = use_hide; + + /* Used for setting loop normals flags. Mapped extraction is only used during edit mode. + * See comments in #extract_lnor_iter_poly_mesh. + */ + draw_cache->is_edit_mode = mr->edit_bmesh != nullptr; draw_subdiv_cache_update_extra_coarse_face_data(draw_cache, mesh_eval, mr); @@ -2195,7 +2203,7 @@ static OpenSubdiv_EvaluatorCache *g_evaluator_cache = nullptr; void DRW_create_subdivision(Object *ob, Mesh *mesh, - struct MeshBatchCache *batch_cache, + MeshBatchCache *batch_cache, MeshBufferCache *mbc, const bool is_editmode, const bool is_paint_mode, diff --git a/source/blender/draw/intern/draw_subdivision.h b/source/blender/draw/intern/draw_subdivision.h index 2d9f4713feb..ef580fc116a 100644 --- a/source/blender/draw/intern/draw_subdivision.h +++ b/source/blender/draw/intern/draw_subdivision.h @@ -177,6 +177,10 @@ typedef struct DRWSubdivCache { /* UBO to store settings for the various compute shaders. */ struct GPUUniformBuf *ubo; + + /* Extra flags, passed to the UBO. */ + bool is_edit_mode; + bool use_hide; } DRWSubdivCache; /* Only frees the data of the cache, caller is responsible to free the cache itself if necessary. diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc index 9824602b129..2ff093d0bd8 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc @@ -22,7 +22,7 @@ struct MeshExtract_EditUvElem_Data { }; static void extract_edituv_tris_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { @@ -69,7 +69,7 @@ static void extract_edituv_tris_iter_looptri_mesh(const MeshRenderData *mr, } static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -142,7 +142,7 @@ static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache *UNUSED(su static void extract_edituv_tris_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -176,7 +176,7 @@ constexpr MeshExtract create_extractor_edituv_tris() * \{ */ static void extract_edituv_lines_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { @@ -236,7 +236,7 @@ static void extract_edituv_lines_iter_poly_mesh(const MeshRenderData *mr, } static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -307,7 +307,7 @@ static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_c static void extract_edituv_lines_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -341,7 +341,7 @@ constexpr MeshExtract create_extractor_edituv_lines() * \{ */ static void extract_edituv_points_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { @@ -394,7 +394,7 @@ static void extract_edituv_points_iter_poly_mesh(const MeshRenderData *mr, } static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -459,7 +459,7 @@ static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_ static void extract_edituv_points_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -493,7 +493,7 @@ constexpr MeshExtract create_extractor_edituv_points() * \{ */ static void extract_edituv_fdots_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { @@ -557,7 +557,7 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr, } static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc index 4eebea1b79f..cc0b383f12b 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc @@ -15,7 +15,7 @@ namespace blender::draw { * \{ */ static void extract_fdots_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *tls_data) { @@ -68,7 +68,7 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr, } static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_userdata) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc index 4e89b34c0a0..51d98d1ff26 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc @@ -18,7 +18,7 @@ namespace blender::draw { * \{ */ static void extract_lines_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *tls_data) { @@ -132,7 +132,7 @@ static void extract_lines_task_reduce(void *_userdata_to, void *_userdata_from) } static void extract_lines_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *data) { @@ -143,7 +143,7 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr), static void extract_lines_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buffer, void *UNUSED(data)) { @@ -229,7 +229,7 @@ constexpr MeshExtract create_extractor_lines() /** \name Extract Lines and Loose Edges Sub Buffer * \{ */ -static void extract_lines_loose_subbuffer(const MeshRenderData *mr, struct MeshBatchCache *cache) +static void extract_lines_loose_subbuffer(const MeshRenderData *mr, MeshBatchCache *cache) { BLI_assert(cache->final.buff.ibo.lines); /* Multiply by 2 because these are edges indices. */ @@ -241,7 +241,7 @@ static void extract_lines_loose_subbuffer(const MeshRenderData *mr, struct MeshB } static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *data) { @@ -253,7 +253,7 @@ static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, static void extract_lines_with_lines_loose_finish_subdiv(const struct DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *UNUSED(buf), void *UNUSED(_data)) { @@ -292,7 +292,7 @@ constexpr MeshExtract create_extractor_lines_with_lines_loose() * \{ */ static void extract_lines_loose_only_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *UNUSED(tls_data)) { @@ -303,7 +303,7 @@ static void extract_lines_loose_only_init(const MeshRenderData *mr, static void extract_lines_loose_only_init_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc index 9ba9453dada..c2cfb66ec28 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc @@ -42,7 +42,7 @@ static void line_adjacency_data_init(MeshExtract_LineAdjacency_Data *data, } static void extract_lines_adjacency_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *tls_data) { @@ -132,7 +132,7 @@ static void extract_lines_adjacency_iter_looptri_mesh(const MeshRenderData *mr, } static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *_data) { @@ -166,7 +166,7 @@ static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr), static void extract_lines_adjacency_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *_data) { @@ -222,7 +222,7 @@ static void extract_lines_adjacency_iter_subdiv_mesh(const DRWSubdivCache *subdi static void extract_lines_adjacency_finish_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc index 713a533492f..11c71d61775 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc @@ -26,7 +26,7 @@ struct MeshExtract_LinePaintMask_Data { }; static void extract_lines_paint_mask_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { @@ -78,7 +78,7 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, } static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -126,7 +126,8 @@ static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subd if (!((mr->use_hide && (me->flag & ME_HIDE)) || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) && (mr->e_origindex[coarse_edge_index] == ORIGINDEX_NONE)))) { - const uint ml_index_other = (loop_idx == end_loop_idx) ? start_loop_idx : loop_idx + 1; + const uint ml_index_other = (loop_idx == (end_loop_idx - 1)) ? start_loop_idx : + loop_idx + 1; if (coarse_quad->flag & ME_FACE_SEL) { if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, coarse_edge_index)) { /* Hide edge as it has more than 2 selected loop. */ @@ -154,7 +155,7 @@ static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subd static void extract_lines_paint_mask_finish_subdiv( const struct DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc index e746b37fd30..f7c5505422b 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc @@ -19,7 +19,7 @@ namespace blender::draw { * \{ */ static void extract_points_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *tls_data) { @@ -131,7 +131,7 @@ static void extract_points_task_reduce(void *_userdata_to, void *_userdata_from) } static void extract_points_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_userdata) { @@ -142,7 +142,7 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), static void extract_points_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buffer), void *data) { @@ -285,7 +285,7 @@ static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, static void extract_points_finish_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache), const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_userdata) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc index 4c8d1d0002a..9fc18620d11 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc @@ -25,7 +25,7 @@ static void extract_tris_mat_task_reduce(void *_userdata_to, void *_userdata_fro * \{ */ static void extract_tris_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { @@ -81,7 +81,7 @@ static void extract_tris_iter_poly_mesh(const MeshRenderData *mr, } static void extract_tris_finish(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *_data) { @@ -111,7 +111,7 @@ static void extract_tris_finish(const MeshRenderData *mr, static void extract_tris_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { @@ -157,7 +157,7 @@ constexpr MeshExtract create_extractor_tris() * \{ */ static void extract_tris_single_mat_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(ibo), void *tls_data) { @@ -199,7 +199,7 @@ static void extract_tris_single_mat_iter_looptri_mesh(const MeshRenderData *mr, } static void extract_tris_single_mat_finish(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index fb6b5e1904b..ff86bc768a3 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -120,8 +120,7 @@ static GPUVertCompType get_comp_type_for_type(eCustomDataType type) } } -static void init_vbo_for_attribute(const MeshRenderData *mr, - GPUVertBuf *vbo, +static void init_vbo_for_attribute(GPUVertBuf *vbo, const DRW_AttributeRequest &request, bool build_on_device, uint32_t len) @@ -132,11 +131,8 @@ static void init_vbo_for_attribute(const MeshRenderData *mr, /* We should not be here if the attribute type is not supported. */ BLI_assert(comp_size != 0); - const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain); char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name( - custom_data, request.cd_type, request.layer_index); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + GPU_vertformat_safe_attr_name(request.attribute_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); /* Attributes use auto-name. */ BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); @@ -258,18 +254,15 @@ static void extract_attr_generic(const MeshRenderData *mr, } } -static void extract_attr_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, - void *buf, - void *UNUSED(tls_data), - int index) +static void extract_attr_init( + const MeshRenderData *mr, MeshBatchCache *cache, void *buf, void *UNUSED(tls_data), int index) { const DRW_Attributes *attrs_used = &cache->attr_used; const DRW_AttributeRequest &request = attrs_used->requests[index]; GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); - init_vbo_for_attribute(mr, vbo, request, false, static_cast<uint32_t>(mr->loop_len)); + init_vbo_for_attribute(vbo, request, false, static_cast<uint32_t>(mr->loop_len)); /* TODO(@kevindietrich): float3 is used for scalar attributes as the implicit conversion done by * OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following the @@ -350,7 +343,7 @@ static void extract_attr_init_subdiv(const DRWSubdivCache *subdiv_cache, } GPUVertBuf *dst_buffer = static_cast<GPUVertBuf *>(buffer); - init_vbo_for_attribute(mr, dst_buffer, request, true, subdiv_cache->num_subdiv_loops); + init_vbo_for_attribute(dst_buffer, request, true, subdiv_cache->num_subdiv_loops); /* Ensure data is uploaded properly. */ GPU_vertbuf_tag_dirty(src_data); @@ -364,13 +357,13 @@ static void extract_attr_init_subdiv(const DRWSubdivCache *subdiv_cache, * extract. The overall API does not allow us to pass this in a convenient way. */ #define EXTRACT_INIT_WRAPPER(index) \ static void extract_attr_init##index( \ - const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf, void *tls_data) \ + const MeshRenderData *mr, MeshBatchCache *cache, void *buf, void *tls_data) \ { \ extract_attr_init(mr, cache, buf, tls_data, index); \ } \ static void extract_attr_init_subdiv##index(const DRWSubdivCache *subdiv_cache, \ const MeshRenderData *mr, \ - struct MeshBatchCache *cache, \ + MeshBatchCache *cache, \ void *buf, \ void *tls_data) \ { \ diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc index a11f740239a..eb6e800023a 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc @@ -43,7 +43,7 @@ static float loop_edge_factor_get(const float f_no[3], } static void extract_edge_fac_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { @@ -167,7 +167,7 @@ static void extract_edge_fac_iter_ledge_mesh(const MeshRenderData *mr, } static void extract_edge_fac_finish(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *_data) { @@ -218,7 +218,7 @@ static GPUVertFormat *get_subdiv_edge_fac_format() static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc index 3bb706e82cd..27fd6546b8c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc @@ -112,7 +112,7 @@ static GPUVertFormat *get_edit_data_format() } static void extract_edit_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc index 6d54fce2a0d..0b9043e3289 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc @@ -43,7 +43,7 @@ static void extract_edituv_data_init_common(const MeshRenderData *mr, } static void extract_edituv_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc index 5d6dd14b57a..969ff9f6f09 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc @@ -74,7 +74,7 @@ static void edituv_get_edituv_stretch_angle(float auv[2][2], } static void extract_edituv_stretch_angle_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { @@ -212,7 +212,7 @@ static GPUVertFormat *get_edituv_stretch_angle_format_subdiv() static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(tls_data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc index 70dcc24f946..2bb786303c4 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc @@ -20,7 +20,7 @@ namespace blender::draw { * \{ */ static void extract_edituv_stretch_area_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(tls_data)) { @@ -89,7 +89,7 @@ static void compute_area_ratio(const MeshRenderData *mr, } static void extract_edituv_stretch_area_finish(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *UNUSED(data)) { @@ -131,7 +131,7 @@ static void extract_edituv_stretch_area_finish(const MeshRenderData *mr, static void extract_edituv_stretch_area_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc index 64bec0adad4..27d1975d67b 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_edituv_data.cc @@ -21,7 +21,7 @@ struct MeshExtract_EditUVFdotData_Data { }; static void extract_fdots_edituv_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc index 8d189db9f12..c2af7f2c9bd 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc @@ -19,7 +19,7 @@ namespace blender::draw { #define NOR_AND_FLAG_HIDDEN -2 static void extract_fdots_nor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(tls_data)) { @@ -34,7 +34,7 @@ static void extract_fdots_nor_init(const MeshRenderData *mr, } static void extract_fdots_nor_finish(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(data)) { @@ -101,7 +101,7 @@ constexpr MeshExtract create_extractor_fdots_nor() * \{ */ static void extract_fdots_nor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(tls_data)) { @@ -116,7 +116,7 @@ static void extract_fdots_nor_hq_init(const MeshRenderData *mr, } static void extract_fdots_nor_hq_finish(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc index 822b5928c49..c391cb6ca5a 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc @@ -36,7 +36,7 @@ static GPUVertFormat *get_fdots_nor_format_subdiv() } static void extract_fdots_pos_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { @@ -101,7 +101,7 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, static void extract_fdots_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc index de21c63e5fd..b0403cf7c4c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_uv.cc @@ -22,7 +22,7 @@ struct MeshExtract_FdotUV_Data { }; static void extract_fdots_uv_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc index 42a9a58bbe4..ac517269e7d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc @@ -16,7 +16,7 @@ namespace blender::draw { * \{ */ static void extract_lnor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { @@ -105,7 +105,7 @@ static GPUVertFormat *get_subdiv_lnor_format() static void extract_lnor_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { @@ -141,7 +141,7 @@ struct gpuHQNor { }; static void extract_lnor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc index b57e2f6b807..951990466d0 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc @@ -23,7 +23,7 @@ namespace blender::draw { * \{ */ static void extract_mesh_analysis_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(tls_data)) { @@ -587,7 +587,7 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) } static void extract_analysis_iter_finish_mesh(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc index 68d838e9e62..4fcbdb1fc7c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc @@ -19,7 +19,7 @@ struct MeshExtract_Orco_Data { }; static void extract_orco_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc index 313744bdd27..9788beabeb5 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc @@ -28,7 +28,7 @@ struct MeshExtract_PosNor_Data { }; static void extract_pos_nor_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { @@ -171,7 +171,7 @@ static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, } static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *_data) { @@ -201,7 +201,7 @@ static GPUVertFormat *get_custom_normals_format() static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { @@ -372,7 +372,7 @@ struct MeshExtract_PosNorHQ_Data { }; static void extract_pos_nor_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { @@ -521,7 +521,7 @@ static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr, } static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *UNUSED(buf), void *_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc index 0d959e324f8..492721b4853 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc @@ -31,7 +31,7 @@ static GPUVertFormat *get_sculpt_data_format() } static void extract_sculpt_data_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(tls_data)) { @@ -113,7 +113,7 @@ static void extract_sculpt_data_init(const MeshRenderData *mr, static void extract_sculpt_data_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buffer, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc index 6230e1974be..9e0d171c9e4 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc @@ -30,7 +30,7 @@ static void extract_select_idx_init_impl(const MeshRenderData *UNUSED(mr), } static void extract_select_idx_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { @@ -366,7 +366,7 @@ constexpr MeshExtract create_extractor_vert_idx() } static void extract_fdot_idx_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *tls_data) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc index a275f247cad..f7655658bdd 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc @@ -19,7 +19,7 @@ struct SkinRootData { }; static void extract_skin_roots_init(const MeshRenderData *mr, - struct MeshBatchCache *UNUSED(cache), + MeshBatchCache *UNUSED(cache), void *buf, void *UNUSED(tls_data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc index 83453d6ef38..049fa416523 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc @@ -25,7 +25,7 @@ namespace blender::draw { * \{ */ static void extract_tan_init_common(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, GPUVertFormat *format, GPUVertCompType comp_type, GPUVertFetchMode fetch_mode, @@ -161,7 +161,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, } static void extract_tan_ex_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, GPUVertBuf *vbo, const bool do_hq) { @@ -235,7 +235,7 @@ static void extract_tan_ex_init(const MeshRenderData *mr, } static void extract_tan_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *UNUSED(tls_data)) { @@ -254,7 +254,7 @@ static GPUVertFormat *get_coarse_tan_format() static void extract_tan_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { @@ -344,7 +344,7 @@ constexpr MeshExtract create_extractor_tan() * \{ */ static void extract_tan_hq_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *UNUSED(tls_data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc index ddb8ed9b25b..6606912850d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc @@ -19,7 +19,7 @@ namespace blender::draw { /* Initialize the vertex format to be used for UVs. Return true if any UV layer is * found, false otherwise. */ static bool mesh_extract_uv_format_init(GPUVertFormat *format, - struct MeshBatchCache *cache, + MeshBatchCache *cache, CustomData *cd_ldata, eMRExtractType extract_type, uint32_t &r_uv_layers) @@ -72,7 +72,7 @@ static bool mesh_extract_uv_format_init(GPUVertFormat *format, } static void extract_uv_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *UNUSED(tls_data)) { @@ -120,7 +120,7 @@ static void extract_uv_init(const MeshRenderData *mr, static void extract_uv_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc index 84ab20f8f90..419cbb0267f 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc @@ -123,7 +123,7 @@ struct gpuMeshVcol { }; static void extract_vcol_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *UNUSED(tls_data)) { @@ -234,7 +234,7 @@ static void extract_vcol_init(const MeshRenderData *mr, static void extract_vcol_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *UNUSED(data)) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc index c64cca4dff5..ba194a4b167 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc @@ -79,7 +79,7 @@ static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeig } static void extract_weights_init(const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buf, void *tls_data) { @@ -154,7 +154,7 @@ static void extract_weights_iter_poly_mesh(const MeshRenderData *mr, static void extract_weights_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *mr, - struct MeshBatchCache *cache, + MeshBatchCache *cache, void *buffer, void *_data) { diff --git a/source/blender/draw/intern/shaders/common_subdiv_ibo_lines_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_ibo_lines_comp.glsl index 3244b7960d8..eacdf8e6333 100644 --- a/source/blender/draw/intern/shaders/common_subdiv_ibo_lines_comp.glsl +++ b/source/blender/draw/intern/shaders/common_subdiv_ibo_lines_comp.glsl @@ -35,7 +35,7 @@ void emit_line(uint line_offset, uint quad_index, uint start_loop_index, uint co uint coarse_quad_index = coarse_polygon_index_from_subdiv_quad_index(quad_index, coarse_poly_count); - if (is_face_hidden(coarse_quad_index) || + if (use_hide && is_face_hidden(coarse_quad_index) || (input_origindex[vertex_index] == ORIGINDEX_NONE && optimal_display)) { output_lines[line_offset + 0] = 0xffffffff; output_lines[line_offset + 1] = 0xffffffff; diff --git a/source/blender/draw/intern/shaders/common_subdiv_ibo_tris_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_ibo_tris_comp.glsl index ce3c8478d3f..a46d69eca88 100644 --- a/source/blender/draw/intern/shaders/common_subdiv_ibo_tris_comp.glsl +++ b/source/blender/draw/intern/shaders/common_subdiv_ibo_tris_comp.glsl @@ -45,7 +45,7 @@ void main() int triangle_loop_index = (int(quad_index) + mat_offset) * 6; #endif - if (is_face_hidden(coarse_quad_index)) { + if (use_hide && is_face_hidden(coarse_quad_index)) { output_tris[triangle_loop_index + 0] = 0xffffffff; output_tris[triangle_loop_index + 1] = 0xffffffff; output_tris[triangle_loop_index + 2] = 0xffffffff; diff --git a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl index d76a7369f79..4183b4a1cd3 100644 --- a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl +++ b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl @@ -36,6 +36,10 @@ layout(std140) uniform shader_data /* Total number of elements to process. */ uint total_dispatch_size; + + bool is_edit_mode; + + bool use_hide; }; uint get_global_invocation_index() diff --git a/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl index e146ccb343a..81e346863c2 100644 --- a/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl +++ b/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl @@ -427,7 +427,7 @@ void main() output_nors[coarse_quad_index] = fnor; # endif - if (is_face_hidden(coarse_quad_index)) { + if (use_hide && is_face_hidden(coarse_quad_index)) { output_indices[coarse_quad_index] = 0xffffffff; } else { diff --git a/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl index f5c4c7895aa..97c07704c06 100644 --- a/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl +++ b/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl @@ -26,6 +26,23 @@ bool is_face_selected(uint coarse_quad_index) return (extra_coarse_face_data[coarse_quad_index] & coarse_face_select_mask) != 0; } +bool is_face_hidden(uint coarse_quad_index) +{ + return (extra_coarse_face_data[coarse_quad_index] & coarse_face_hidden_mask) != 0; +} + +/* Flag for paint mode overlay and normals drawing in edit-mode. */ +float get_loop_flag(uint coarse_quad_index, int vert_origindex) +{ + if (is_face_hidden(coarse_quad_index) || (is_edit_mode && vert_origindex == -1)) { + return -1.0; + } + if (is_face_selected(coarse_quad_index)) { + return 1.0; + } + return 0.0; +} + void main() { /* We execute for each quad. */ @@ -44,7 +61,11 @@ void main() /* Face is smooth, use vertex normals. */ for (int i = 0; i < 4; i++) { PosNorLoop pos_nor_loop = pos_nor[start_loop_index + i]; - output_lnor[start_loop_index + i] = get_normal_and_flag(pos_nor_loop); + int origindex = input_vert_origindex[start_loop_index + i]; + LoopNormal loop_normal = get_normal_and_flag(pos_nor_loop); + loop_normal.flag = get_loop_flag(coarse_quad_index, origindex); + + output_lnor[start_loop_index + i] = loop_normal; } } else { @@ -68,11 +89,7 @@ void main() for (int i = 0; i < 4; i++) { int origindex = input_vert_origindex[start_loop_index + i]; - float flag = 0.0; - if (origindex == -1) { - flag = -1.0; - } - loop_normal.flag = flag; + loop_normal.flag = get_loop_flag(coarse_quad_index, origindex); output_lnor[start_loop_index + i] = loop_normal; } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index fc5b3838900..7b659511aaa 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -388,6 +388,17 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, /* Create new layer */ /* TODO: have some way of specifying that we don't want this? */ + { + /* "New Layer" entry */ + item_tmp.identifier = "__CREATE__"; + item_tmp.name = "New Layer"; + item_tmp.value = -1; + item_tmp.icon = ICON_ADD; + RNA_enum_item_add(&item, &totitem, &item_tmp); + + /* separator */ + RNA_enum_item_add_separator(&item, &totitem); + } const int tot = BLI_listbase_count(&gpd->layers); /* Existing layers */ @@ -405,17 +416,6 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, RNA_enum_item_add(&item, &totitem, &item_tmp); } - { - /* separator */ - RNA_enum_item_add_separator(&item, &totitem); - - /* "New Layer" entry */ - item_tmp.identifier = "__CREATE__"; - item_tmp.name = "New Layer"; - item_tmp.value = -1; - item_tmp.icon = ICON_ADD; - RNA_enum_item_add(&item, &totitem, &item_tmp); - } RNA_enum_item_end(&item, &totitem); *r_free = true; diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index c5a45f8b73e..74735018814 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -22,13 +22,36 @@ struct bScreen; /* ** clip_editor.c ** */ -/* common poll functions */ +/* Returns true when the following conditions are met: + * - Current space is Space Clip. + * - There is a movie clip opened in it. */ bool ED_space_clip_poll(struct bContext *C); +/* Returns true when the following conditions are met: + * - Current space is Space Clip. + * - It is set to Clip view. + * + * It is not required to have movie clip opened for editing. */ bool ED_space_clip_view_clip_poll(struct bContext *C); +/* Returns true when the following conditions are met: + * - Current space is Space Clip. + * - It is set to Tracking mode. + * + * It is not required to have movie clip opened for editing. */ bool ED_space_clip_tracking_poll(struct bContext *C); + +/* Returns true when the following conditions are met: + * - Current space is Space Clip. + * - It is set to Mask mode. + * + * It is not required to have mask opened for editing. */ bool ED_space_clip_maskedit_poll(struct bContext *C); + +/* Returns true when the following conditions are met: + * - Current space is Space Clip. + * - It is set to Mask mode. + * - The space has mask opened. */ bool ED_space_clip_maskedit_mask_poll(struct bContext *C); void ED_space_clip_get_size(struct SpaceClip *sc, int *width, int *height); diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index b16844c01ea..3e5d4c3adf4 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -137,8 +137,22 @@ bool ED_space_image_paint_curve(const struct bContext *C); * Matches clip function. */ bool ED_space_image_check_show_maskedit(struct SpaceImage *sima, struct Object *obedit); + +/* Returns true when the following conditions are met: + * - Current space is Image Editor. + * - The image editor is not a UV Editor. + * - It is set to Mask mode. + * + * It is not required to have mask opened for editing. */ bool ED_space_image_maskedit_poll(struct bContext *C); + +/* Returns true when the following conditions are met: + * - Current space is Image Editor. + * - The image editor is not a UV Editor. + * - It is set to Mask mode. + * - The space has mask opened. */ bool ED_space_image_maskedit_mask_poll(struct bContext *C); + bool ED_space_image_cursor_poll(struct bContext *C); /** diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 7039d6d9fc7..6d4d4fcff48 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -22,6 +22,19 @@ struct wmKeyConfig; /* mask_edit.c */ +/* Returns true when the following conditions are met: + * - Current space supports mask editing. + * - The space is configured to interact with mask. + * + * It is not required to have mask opened for editing. */ +bool ED_maskedit_poll(struct bContext *C); + +/* Returns true when the following conditions are met: + * - Current space supports mask editing. + * - The space is configured to interact with mask. + * - The space has mask open for editing. */ +bool ED_maskedit_mask_poll(struct bContext *C); + void ED_mask_deselect_all(const struct bContext *C); void ED_operatortypes_mask(void); @@ -73,6 +86,7 @@ void ED_mask_draw_region(struct Depsgraph *depsgraph, char draw_flag, char draw_type, eMaskOverlayMode overlay_mode, + float blend_factor, int width_i, int height_i, float aspx, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index aa62a6209e4..a24c8625a63 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -595,7 +595,6 @@ bool ED_operator_object_active_local_editable_posemode_exclusive(struct bContext bool ED_operator_posemode_context(struct bContext *C); bool ED_operator_posemode(struct bContext *C); bool ED_operator_posemode_local(struct bContext *C); -bool ED_operator_mask(struct bContext *C); bool ED_operator_camera_poll(struct bContext *C); /* screen_user_menu.c */ diff --git a/source/blender/editors/include/ED_select_utils.h b/source/blender/editors/include/ED_select_utils.h index fa02ebe18f6..8c856794ec8 100644 --- a/source/blender/editors/include/ED_select_utils.h +++ b/source/blender/editors/include/ED_select_utils.h @@ -40,11 +40,11 @@ typedef enum { } eSelectOp; /* Select Similar */ -enum { +typedef enum { SIM_CMP_EQ = 0, SIM_CMP_GT, SIM_CMP_LT, -}; +} eSimilarCmp; #define SEL_OP_USE_OUTSIDE(sel_op) (ELEM(sel_op, SEL_OP_AND)) #define SEL_OP_USE_PRE_DESELECT(sel_op) (ELEM(sel_op, SEL_OP_SET)) @@ -63,11 +63,11 @@ int ED_select_op_action(eSelectOp sel_op, bool is_select, bool is_inside); */ int ED_select_op_action_deselected(eSelectOp sel_op, bool is_select, bool is_inside); -int ED_select_similar_compare_float(float delta, float thresh, int compare); +bool ED_select_similar_compare_float(float delta, float thresh, eSimilarCmp compare); bool ED_select_similar_compare_float_tree(const struct KDTree_1d *tree, float length, float thresh, - int compare); + eSimilarCmp compare); /** * Utility to use for selection operations that run multiple times (circle select). diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 341d5e78872..7c00c4f1875 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4818,8 +4818,7 @@ static int ui_do_but_GRIDTILE(bContext *C, uiHandleButtonData *data, const wmEvent *event) { - uiButGridTile *grid_tile_but = (uiButGridTile *)but; - BLI_assert(grid_tile_but->but.type == UI_BTYPE_GRID_TILE); + BLI_assert(but->type == UI_BTYPE_GRID_TILE); if (data->state == BUTTON_STATE_HIGHLIGHT) { if (event->type == LEFTMOUSE) { @@ -4840,7 +4839,8 @@ static int ui_do_but_GRIDTILE(bContext *C, case KM_DBL_CLICK: data->cancel = true; - // UI_tree_view_item_begin_rename(grid_tile_but->tree_item); + // uiButGridTile *grid_tile_but = (uiButGridTile *)but; + // UI_tree_view_item_begin_rename(grid_tile_but->tree_item); ED_region_tag_redraw(CTX_wm_region(C)); return WM_UI_HANDLER_BREAK; } diff --git a/source/blender/editors/interface/interface_region_search.cc b/source/blender/editors/interface/interface_region_search.cc index 64de31dfe6a..81c0c29d09a 100644 --- a/source/blender/editors/interface/interface_region_search.cc +++ b/source/blender/editors/interface/interface_region_search.cc @@ -451,15 +451,16 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re /* reset vars */ data->items.totitem = 0; data->items.more = 0; - if (reset == false) { + if (!reset) { data->items.offset_i = data->items.offset; } else { data->items.offset_i = data->items.offset = 0; data->active = -1; - /* handle active */ - if (search_but->items_update_fn && search_but->item_active) { + /* On init, find and center active item. */ + const bool is_first_search = !search_but->but.changed; + if (is_first_search && search_but->items_update_fn && search_but->item_active) { data->items.active = search_but->item_active; ui_searchbox_update_fn(C, search_but, but->editstr, &data->items); data->items.active = nullptr; diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index c7ebecb178b..82d4405e1b5 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -800,7 +800,7 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C, .style = UI_TIP_STYLE_HEADER, .color_id = UI_TIP_LC_NORMAL, }); - field->text = BLI_sprintfN("%s", but_label.strinfo); + field->text = BLI_strdup(but_label.strinfo); } /* Tip */ diff --git a/source/blender/editors/interface/interface_style.cc b/source/blender/editors/interface/interface_style.cc index 291ede05730..904765f6dc4 100644 --- a/source/blender/editors/interface/interface_style.cc +++ b/source/blender/editors/interface/interface_style.cc @@ -382,19 +382,8 @@ void uiStyleInit(void) } CLAMP(U.dpi, 48, 144); - LISTBASE_FOREACH (uiFont *, font, &U.uifonts) { - BLF_unload_id(font->blf_id); - } - - if (blf_mono_font != -1) { - BLF_unload_id(blf_mono_font); - blf_mono_font = -1; - } - - if (blf_mono_font_render != -1) { - BLF_unload_id(blf_mono_font_render); - blf_mono_font_render = -1; - } + /* Needed so that custom fonts are always first. */ + BLF_unload_all(); uiFont *font_first = static_cast<uiFont *>(U.uifonts.first); @@ -498,6 +487,9 @@ void uiStyleInit(void) const bool unique = true; blf_mono_font_render = BLF_load_mono_default(unique); } + + /* Load the fallback fonts last. */ + BLF_load_font_stack(); } void UI_fontstyle_set(const uiFontStyle *fs) diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c index 4819ae09785..53fa4788d0e 100644 --- a/source/blender/editors/io/io_obj.c +++ b/source/blender/editors/io/io_obj.c @@ -392,6 +392,7 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op) import_params.clamp_size = RNA_float_get(op->ptr, "clamp_size"); import_params.forward_axis = RNA_enum_get(op->ptr, "forward_axis"); import_params.up_axis = RNA_enum_get(op->ptr, "up_axis"); + import_params.import_vertex_groups = RNA_boolean_get(op->ptr, "import_vertex_groups"); import_params.validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes"); OBJ_import(C, &import_params); @@ -422,6 +423,7 @@ static void ui_obj_import_settings(uiLayout *layout, PointerRNA *imfptr) box = uiLayoutBox(layout); uiItemL(box, IFACE_("Options"), ICON_EXPORT); col = uiLayoutColumn(box, false); + uiItemR(col, imfptr, "import_vertex_groups", 0, NULL, ICON_NONE); uiItemR(col, imfptr, "validate_meshes", 0, NULL, ICON_NONE); } @@ -468,6 +470,11 @@ void WM_OT_obj_import(struct wmOperatorType *ot) ot->srna, "forward_axis", io_transform_axis, IO_AXIS_NEGATIVE_Z, "Forward Axis", ""); RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", ""); RNA_def_boolean(ot->srna, + "import_vertex_groups", + false, + "Vertex Groups", + "Import OBJ groups as vertex groups"); + RNA_def_boolean(ot->srna, "validate_meshes", false, "Validate Meshes", diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 194170b1677..42f3acaa6bc 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -583,7 +583,7 @@ void MASK_OT_add_vertex(wmOperatorType *ot) /* api callbacks */ ot->exec = add_vertex_exec; ot->invoke = add_vertex_invoke; - ot->poll = ED_operator_mask; + ot->poll = ED_maskedit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -862,7 +862,7 @@ void MASK_OT_primitive_circle_add(wmOperatorType *ot) /* api callbacks */ ot->exec = primitive_circle_add_exec; ot->invoke = primitive_add_invoke; - ot->poll = ED_operator_mask; + ot->poll = ED_maskedit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -897,7 +897,7 @@ void MASK_OT_primitive_square_add(wmOperatorType *ot) /* api callbacks */ ot->exec = primitive_square_add_exec; ot->invoke = primitive_add_invoke; - ot->poll = ED_operator_mask; + ot->poll = ED_maskedit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index aab4007854f..1bd224fe763 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -663,6 +663,7 @@ void ED_mask_draw_region( const char draw_flag, const char draw_type, const eMaskOverlayMode overlay_mode, + const float blend_factor, /* convert directly into aspect corrected vars */ const int width_i, const int height_i, @@ -721,12 +722,14 @@ void ED_mask_draw_region( } if (draw_flag & MASK_DRAWFLAG_OVERLAY) { - const float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; + float buf_col[4] = {1.0f, 0.0f, 0.0f, 0.0f}; float *buffer = mask_rasterize(mask_eval, width, height); if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { /* More blending types could be supported in the future. */ - GPU_blend(GPU_BLEND_MULTIPLY); + GPU_blend(GPU_BLEND_ALPHA); + buf_col[0] = -1.0f; + buf_col[3] = 1.0f; } GPU_matrix_push(); @@ -737,10 +740,18 @@ void ED_mask_draw_region( } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); - immDrawPixelsTexTiled( - &state, 0.0f, 0.0f, width, height, GPU_R16F, false, buffer, 1.0f, 1.0f, NULL); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, buf_col); + if (overlay_mode == MASK_OVERLAY_COMBINED) { + const float blend_col[4] = {0.0f, 0.0f, 0.0f, blend_factor}; + + immDrawPixelsTexTiled( + &state, 0.0f, 0.0f, width, height, GPU_R16F, false, buffer, 1.0f, 1.0f, blend_col); + } + else { + immDrawPixelsTexTiled( + &state, 0.0f, 0.0f, width, height, GPU_R16F, false, buffer, 1.0f, 1.0f, NULL); + } GPU_matrix_pop(); if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index c620d781c7f..2e99b45f215 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -86,9 +86,6 @@ void ED_mask_select_flush_all(struct Mask *mask); /* mask_editor.c */ -bool ED_maskedit_poll(struct bContext *C); -bool ED_maskedit_mask_poll(struct bContext *C); - /* Generalized solution for preserving editor viewport when making changes while lock-to-selection * is enabled. * Any mask operator can use this API, without worrying that some editors do not have an idea of diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 3c0e7ee399c..3ca9f4d06e2 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -113,7 +113,7 @@ void MASK_OT_new(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_new_exec; - ot->poll = ED_operator_mask; + ot->poll = ED_maskedit_poll; /* properties */ RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Name of new mask"); @@ -146,7 +146,7 @@ void MASK_OT_layer_new(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_layer_new_exec; - ot->poll = ED_maskedit_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -181,7 +181,7 @@ void MASK_OT_layer_remove(wmOperatorType *ot) /* api callbacks */ ot->exec = mask_layer_remove_exec; - ot->poll = ED_maskedit_poll; + ot->poll = ED_maskedit_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -907,7 +907,7 @@ void MASK_OT_slide_point(wmOperatorType *ot) /* api callbacks */ ot->invoke = slide_point_invoke; ot->modal = slide_point_modal; - ot->poll = ED_operator_mask; + ot->poll = ED_maskedit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1297,7 +1297,7 @@ void MASK_OT_slide_spline_curvature(wmOperatorType *ot) /* api callbacks */ ot->invoke = slide_spline_curvature_invoke; ot->modal = slide_spline_curvature_modal; - ot->poll = ED_operator_mask; + ot->poll = ED_maskedit_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 9d8b84de66b..afeb1500267 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -21,6 +21,7 @@ #include "WM_types.h" #include "ED_clip.h" /* frame remapping functions */ +#include "ED_mask.h" #include "ED_screen.h" #include "mask_intern.h" /* own include */ diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 969d5b5912c..e7891450bd6 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -669,7 +669,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) short etype = event->type; short eval = event->val; - /* When activated from toolbar, need to convert leftmouse release to confirm */ + /* When activated from toolbar, need to convert left-mouse release to confirm. */ if (ELEM(etype, LEFTMOUSE, opdata->launch_event) && (eval == KM_RELEASE) && RNA_boolean_get(op->ptr, "release_confirm")) { etype = EVT_MODAL_MAP; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 369ca553a8c..f58baa0e25c 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -3458,9 +3458,9 @@ ScrArea *ED_area_find_under_cursor(const bContext *C, int spacetype, const int x if (!area) { /* Check all windows except the active one. */ int scr_pos[2]; - wmWindow *r_win = WM_window_find_under_cursor(win, xy, scr_pos); - if (r_win && r_win != win) { - win = r_win; + wmWindow *win_other = WM_window_find_under_cursor(win, xy, scr_pos); + if (win_other && win_other != win) { + win = win_other; screen = WM_window_get_active_screen(win); area = BKE_screen_find_area_xy(screen, spacetype, scr_pos); } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 55721e6380d..212fb846b43 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -659,32 +659,6 @@ bool ED_operator_editmball(bContext *C) return false; } -bool ED_operator_mask(bContext *C) -{ - ScrArea *area = CTX_wm_area(C); - if (area && area->spacedata.first) { - switch (area->spacetype) { - case SPACE_CLIP: { - SpaceClip *space_clip = area->spacedata.first; - return ED_space_clip_check_show_maskedit(space_clip); - } - case SPACE_SEQ: { - SpaceSeq *sseq = area->spacedata.first; - Scene *scene = CTX_data_scene(C); - return ED_space_sequencer_check_show_maskedit(sseq, scene); - } - case SPACE_IMAGE: { - SpaceImage *sima = area->spacedata.first; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); - return ED_space_image_check_show_maskedit(sima, obedit); - } - } - } - - return false; -} - bool ED_operator_camera_poll(bContext *C) { struct Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index b1b52d16c6d..8879161d2af 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -52,7 +52,7 @@ set(SRC paint_stroke.c paint_utils.c paint_vertex.cc - paint_vertex_color_ops.c + paint_vertex_color_ops.cc paint_vertex_color_utils.c paint_vertex_proj.c paint_vertex_weight_ops.c diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index f013fa05f4c..bac03de77e7 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -22,9 +22,9 @@ #include "BKE_geometry_set.hh" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" +#include "BKE_mesh_sample.hh" #include "BKE_paint.h" #include "BKE_report.h" -#include "BKE_spline.hh" #include "DNA_brush_enums.h" #include "DNA_brush_types.h" @@ -38,10 +38,12 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "GEO_add_curves_on_mesh.hh" + #include "WM_api.h" /** - * The code below uses a prefix naming convention to indicate the coordinate space: + * The code below uses a suffix naming convention to indicate the coordinate space: * cu: Local space of the curves object that is being edited. * su: Local space of the surface object. * wo: World space. @@ -70,16 +72,6 @@ class AddOperation : public CurvesSculptStrokeOperation { void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override; }; -static void initialize_straight_curve_positions(const float3 &p1, - const float3 &p2, - MutableSpan<float3> r_positions) -{ - const float step = 1.0f / (float)(r_positions.size() - 1); - for (const int i : r_positions.index_range()) { - r_positions[i] = math::interpolate(p1, p2, i * step); - } -} - /** * Utility class that actually executes the update when the stroke is updated. That's useful * because it avoids passing a very large number of parameters between functions. @@ -95,54 +87,26 @@ struct AddOperationExecutor { Object *surface_ob_ = nullptr; Mesh *surface_ = nullptr; Span<MLoopTri> surface_looptris_; - Span<float3> corner_normals_su_; - VArray_Span<float2> surface_uv_map_; const CurvesSculpt *curves_sculpt_ = nullptr; const Brush *brush_ = nullptr; const BrushCurvesSculptSettings *brush_settings_ = nullptr; + int add_amount_; + bool use_front_face_; float brush_radius_re_; float2 brush_pos_re_; - bool use_front_face_; - bool interpolate_length_; - bool interpolate_shape_; - bool interpolate_point_count_; - bool use_interpolation_; - float new_curve_length_; - int add_amount_; - int constant_points_per_curve_; - - /** Various matrices to convert between coordinate spaces. */ - float4x4 curves_to_world_mat_; - float4x4 curves_to_surface_mat_; - float4x4 world_to_curves_mat_; - float4x4 world_to_surface_mat_; - float4x4 surface_to_world_mat_; - float4x4 surface_to_curves_mat_; - float4x4 surface_to_curves_normal_mat_; + CurvesSculptTransforms transforms_; BVHTreeFromMesh surface_bvh_; - int tot_old_curves_; - int tot_old_points_; - struct AddedPoints { Vector<float3> positions_cu; Vector<float3> bary_coords; Vector<int> looptri_indices; }; - struct NeighborInfo { - /* Curve index of the neighbor. */ - int index; - /* The weights of all neighbors of a new curve add up to 1. */ - float weight; - }; - static constexpr int max_neighbors = 5; - using NeighborsVector = Vector<NeighborInfo, max_neighbors>; - AddOperationExecutor(const bContext &C) : ctx_(C) { } @@ -159,23 +123,10 @@ struct AddOperationExecutor { return; } - curves_to_world_mat_ = object_->obmat; - world_to_curves_mat_ = curves_to_world_mat_.inverted(); + transforms_ = CurvesSculptTransforms(*object_, curves_id_->surface); surface_ob_ = curves_id_->surface; surface_ = static_cast<Mesh *>(surface_ob_->data); - surface_to_world_mat_ = surface_ob_->obmat; - world_to_surface_mat_ = surface_to_world_mat_.inverted(); - surface_to_curves_mat_ = world_to_curves_mat_ * surface_to_world_mat_; - surface_to_curves_normal_mat_ = surface_to_curves_mat_.inverted().transposed(); - curves_to_surface_mat_ = world_to_surface_mat_ * curves_to_world_mat_; - - if (!CustomData_has_layer(&surface_->ldata, CD_NORMAL)) { - BKE_mesh_calc_normals_split(surface_); - } - corner_normals_su_ = { - reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_->ldata, CD_NORMAL)), - surface_->totloop}; curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt; brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint); @@ -187,16 +138,6 @@ struct AddOperationExecutor { const eBrushFalloffShape falloff_shape = static_cast<eBrushFalloffShape>( brush_->falloff_shape); add_amount_ = std::max(0, brush_settings_->add_amount); - constant_points_per_curve_ = std::max(2, brush_settings_->points_per_curve); - interpolate_length_ = brush_settings_->flag & BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_LENGTH; - interpolate_shape_ = brush_settings_->flag & BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_SHAPE; - interpolate_point_count_ = brush_settings_->flag & - BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_POINT_COUNT; - use_interpolation_ = interpolate_length_ || interpolate_shape_ || interpolate_point_count_; - new_curve_length_ = brush_settings_->curve_length; - - tot_old_curves_ = curves_->curves_num(); - tot_old_points_ = curves_->points_num(); if (add_amount_ == 0) { return; @@ -212,15 +153,6 @@ struct AddOperationExecutor { surface_looptris_ = {BKE_mesh_runtime_looptri_ensure(surface_), BKE_mesh_runtime_looptri_len(surface_)}; - if (curves_id_->surface_uv_map != nullptr) { - MeshComponent surface_component; - surface_component.replace(surface_, GeometryOwnershipType::ReadOnly); - surface_uv_map_ = surface_component - .attribute_try_get_for_read(curves_id_->surface_uv_map, - ATTR_DOMAIN_CORNER) - .typed<float2>(); - } - /* Sample points on the surface using one of multiple strategies. */ AddedPoints added_points; if (add_amount_ == 1) { @@ -241,28 +173,52 @@ struct AddOperationExecutor { return; } - Array<NeighborsVector> neighbors_per_curve; - if (use_interpolation_) { - this->ensure_curve_roots_kdtree(); - neighbors_per_curve = this->find_curve_neighbors(added_points); + /* Find UV map. */ + VArray_Span<float2> surface_uv_map; + if (curves_id_->surface_uv_map != nullptr) { + MeshComponent surface_component; + surface_component.replace(surface_, GeometryOwnershipType::ReadOnly); + surface_uv_map = surface_component + .attribute_try_get_for_read(curves_id_->surface_uv_map, + ATTR_DOMAIN_CORNER) + .typed<float2>(); } - /* Resize to add the new curves, building the offsets in the array owned by the curves. */ - const int tot_added_curves = added_points.bary_coords.size(); - curves_->resize(curves_->points_num(), curves_->curves_num() + tot_added_curves); - if (interpolate_point_count_) { - this->initialize_curve_offsets_with_interpolation(neighbors_per_curve); - } - else { - this->initialize_curve_offsets_without_interpolation(constant_points_per_curve_); + /* Find normals. */ + if (!CustomData_has_layer(&surface_->ldata, CD_NORMAL)) { + BKE_mesh_calc_normals_split(surface_); } + const Span<float3> corner_normals_su = { + reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_->ldata, CD_NORMAL)), + surface_->totloop}; - /* Resize to add the correct point count calculated as part of building the offsets. */ - curves_->resize(curves_->offsets().last(), curves_->curves_num()); - - this->initialize_attributes(added_points, neighbors_per_curve); + geometry::AddCurvesOnMeshInputs add_inputs; + add_inputs.root_positions_cu = added_points.positions_cu; + add_inputs.bary_coords = added_points.bary_coords; + add_inputs.looptri_indices = added_points.looptri_indices; + add_inputs.interpolate_length = brush_settings_->flag & + BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_LENGTH; + add_inputs.interpolate_shape = brush_settings_->flag & + BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_SHAPE; + add_inputs.interpolate_point_count = brush_settings_->flag & + BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_POINT_COUNT; + add_inputs.fallback_curve_length = brush_settings_->curve_length; + add_inputs.fallback_point_count = std::max(2, brush_settings_->points_per_curve); + add_inputs.surface = surface_; + add_inputs.surface_bvh = &surface_bvh_; + add_inputs.surface_looptris = surface_looptris_; + add_inputs.surface_uv_map = surface_uv_map; + add_inputs.corner_normals_su = corner_normals_su; + add_inputs.curves_to_surface_mat = transforms_.curves_to_surface; + add_inputs.surface_to_curves_normal_mat = transforms_.surface_to_curves_normal; + + if (add_inputs.interpolate_length || add_inputs.interpolate_shape || + add_inputs.interpolate_point_count) { + this->ensure_curve_roots_kdtree(); + add_inputs.old_roots_kdtree = self_->curve_roots_kdtree_; + } - curves_->update_curve_types(); + geometry::add_curves_on_mesh(*curves_, add_inputs); DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id); @@ -277,14 +233,14 @@ struct AddOperationExecutor { float3 ray_start_wo, ray_end_wo; ED_view3d_win_to_segment_clipped( ctx_.depsgraph, ctx_.region, ctx_.v3d, brush_pos_re_, ray_start_wo, ray_end_wo, true); - const float3 ray_start_cu = world_to_curves_mat_ * ray_start_wo; - const float3 ray_end_cu = world_to_curves_mat_ * ray_end_wo; + const float3 ray_start_cu = transforms_.world_to_curves * ray_start_wo; + const float3 ray_end_cu = transforms_.world_to_curves * ray_end_wo; const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_->symmetry)); for (const float4x4 &brush_transform : symmetry_brush_transforms) { - const float4x4 transform = curves_to_surface_mat_ * brush_transform; + const float4x4 transform = transforms_.curves_to_surface * brush_transform; this->sample_in_center(r_added_points, transform * ray_start_cu, transform * ray_end_cu); } } @@ -312,10 +268,10 @@ struct AddOperationExecutor { const int looptri_index = ray_hit.index; const float3 brush_pos_su = ray_hit.co; - const float3 bary_coords = compute_bary_coord_in_triangle( + const float3 bary_coords = bke::mesh_surface_sample::compute_bary_coord_in_triangle( *surface_, surface_looptris_[looptri_index], brush_pos_su); - const float3 brush_pos_cu = surface_to_curves_mat_ * brush_pos_su; + const float3 brush_pos_cu = transforms_.surface_to_curves * brush_pos_su; r_added_points.positions_cu.append(brush_pos_cu); r_added_points.bary_coords.append(bary_coords); @@ -339,60 +295,37 @@ struct AddOperationExecutor { const float4x4 &brush_transform) { const int old_amount = r_added_points.bary_coords.size(); - const int max_iterations = std::max(100'000, add_amount_ * 10); + const int max_iterations = 100; int current_iteration = 0; while (r_added_points.bary_coords.size() < old_amount + add_amount_) { if (current_iteration++ >= max_iterations) { break; } - - const float r = brush_radius_re_ * std::sqrt(rng.get_float()); - const float angle = rng.get_float() * 2.0f * M_PI; - const float2 pos_re = brush_pos_re_ + r * float2(std::cos(angle), std::sin(angle)); - - float3 ray_start_wo, ray_end_wo; - ED_view3d_win_to_segment_clipped( - ctx_.depsgraph, ctx_.region, ctx_.v3d, pos_re, ray_start_wo, ray_end_wo, true); - const float3 ray_start_cu = brush_transform * (world_to_curves_mat_ * ray_start_wo); - const float3 ray_end_cu = brush_transform * (world_to_curves_mat_ * ray_end_wo); - - const float3 ray_start_su = curves_to_surface_mat_ * ray_start_cu; - const float3 ray_end_su = curves_to_surface_mat_ * ray_end_cu; - const float3 ray_direction_su = math::normalize(ray_end_su - ray_start_su); - - BVHTreeRayHit ray_hit; - ray_hit.dist = FLT_MAX; - ray_hit.index = -1; - BLI_bvhtree_ray_cast(surface_bvh_.tree, - ray_start_su, - ray_direction_su, - 0.0f, - &ray_hit, - surface_bvh_.raycast_callback, - &surface_bvh_); - - if (ray_hit.index == -1) { - continue; - } - - if (use_front_face_) { - const float3 normal_su = ray_hit.no; - if (math::dot(ray_direction_su, normal_su) >= 0.0f) { - continue; - } + const int missing_amount = add_amount_ + old_amount - r_added_points.bary_coords.size(); + const int new_points = bke::mesh_surface_sample::sample_surface_points_projected( + rng, + *surface_, + surface_bvh_, + brush_pos_re_, + brush_radius_re_, + [&](const float2 &pos_re, float3 &r_start_su, float3 &r_end_su) { + float3 start_wo, end_wo; + ED_view3d_win_to_segment_clipped( + ctx_.depsgraph, ctx_.region, ctx_.v3d, pos_re, start_wo, end_wo, true); + const float3 start_cu = brush_transform * (transforms_.world_to_curves * start_wo); + const float3 end_cu = brush_transform * (transforms_.world_to_curves * end_wo); + r_start_su = transforms_.curves_to_surface * start_cu; + r_end_su = transforms_.curves_to_surface * end_cu; + }, + use_front_face_, + add_amount_, + missing_amount, + r_added_points.bary_coords, + r_added_points.looptri_indices, + r_added_points.positions_cu); + for (float3 &pos : r_added_points.positions_cu.as_mutable_span().take_back(new_points)) { + pos = transforms_.surface_to_curves * pos; } - - const int looptri_index = ray_hit.index; - const float3 pos_su = ray_hit.co; - - const float3 bary_coords = compute_bary_coord_in_triangle( - *surface_, surface_looptris_[looptri_index], pos_su); - - const float3 pos_cu = surface_to_curves_mat_ * pos_su; - - r_added_points.positions_cu.append(pos_cu); - r_added_points.bary_coords.append(bary_coords); - r_added_points.looptri_indices.append(looptri_index); } } @@ -401,72 +334,47 @@ struct AddOperationExecutor { */ void sample_spherical_with_symmetry(RandomNumberGenerator &rng, AddedPoints &r_added_points) { - /* Find ray that starts in the center of the brush. */ - float3 brush_ray_start_wo, brush_ray_end_wo; - ED_view3d_win_to_segment_clipped(ctx_.depsgraph, - ctx_.region, - ctx_.v3d, - brush_pos_re_, - brush_ray_start_wo, - brush_ray_end_wo, - true); - const float3 brush_ray_start_cu = world_to_curves_mat_ * brush_ray_start_wo; - const float3 brush_ray_end_cu = world_to_curves_mat_ * brush_ray_end_wo; + const std::optional<CurvesBrush3D> brush_3d = sample_curves_surface_3d_brush(*ctx_.depsgraph, + *ctx_.region, + *ctx_.v3d, + transforms_, + surface_bvh_, + brush_pos_re_, + brush_radius_re_); + if (!brush_3d.has_value()) { + return; + } - /* Find ray that starts on the boundary of the brush. That is used to compute the brush radius - * in 3D. */ - float3 brush_radius_ray_start_wo, brush_radius_ray_end_wo; + float3 view_ray_start_wo, view_ray_end_wo; ED_view3d_win_to_segment_clipped(ctx_.depsgraph, ctx_.region, ctx_.v3d, - brush_pos_re_ + float2(brush_radius_re_, 0), - brush_radius_ray_start_wo, - brush_radius_ray_end_wo, + brush_pos_re_, + view_ray_start_wo, + view_ray_end_wo, true); - const float3 brush_radius_ray_start_cu = world_to_curves_mat_ * brush_radius_ray_start_wo; - const float3 brush_radius_ray_end_cu = world_to_curves_mat_ * brush_radius_ray_end_wo; + const float3 view_direction_su = math::normalize( + transforms_.world_to_surface * view_ray_end_wo - + transforms_.world_to_surface * view_ray_start_wo); const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_->symmetry)); for (const float4x4 &brush_transform : symmetry_brush_transforms) { - const float4x4 transform = curves_to_surface_mat_ * brush_transform; - this->sample_spherical(rng, - r_added_points, - transform * brush_ray_start_cu, - transform * brush_ray_end_cu, - transform * brush_radius_ray_start_cu, - transform * brush_radius_ray_end_cu); + const float4x4 transform = transforms_.curves_to_surface * brush_transform; + const float3 brush_pos_su = transform * brush_3d->position_cu; + const float brush_radius_su = transform_brush_radius( + transform, brush_3d->position_cu, brush_3d->radius_cu); + this->sample_spherical( + rng, r_added_points, brush_pos_su, brush_radius_su, view_direction_su); } } void sample_spherical(RandomNumberGenerator &rng, AddedPoints &r_added_points, - const float3 &brush_ray_start_su, - const float3 &brush_ray_end_su, - const float3 &brush_radius_ray_start_su, - const float3 &brush_radius_ray_end_su) + const float3 &brush_pos_su, + const float brush_radius_su, + const float3 &view_direction_su) { - const float3 brush_ray_direction_su = math::normalize(brush_ray_end_su - brush_ray_start_su); - - BVHTreeRayHit ray_hit; - ray_hit.dist = FLT_MAX; - ray_hit.index = -1; - BLI_bvhtree_ray_cast(surface_bvh_.tree, - brush_ray_start_su, - brush_ray_direction_su, - 0.0f, - &ray_hit, - surface_bvh_.raycast_callback, - &surface_bvh_); - - if (ray_hit.index == -1) { - return; - } - - /* Compute brush radius. */ - const float3 brush_pos_su = ray_hit.co; - const float brush_radius_su = dist_to_line_v3( - brush_pos_su, brush_radius_ray_start_su, brush_radius_ray_end_su); const float brush_radius_sq_su = pow2f(brush_radius_su); /* Find surface triangles within brush radius. */ @@ -483,7 +391,7 @@ struct AddOperationExecutor { const float3 v2_su = surface_->mvert[surface_->mloop[looptri.tri[2]].v].co; float3 normal_su; normal_tri_v3(normal_su, v0_su, v1_su, v2_su); - if (math::dot(normal_su, brush_ray_direction_su) >= 0.0f) { + if (math::dot(normal_su, view_direction_su) >= 0.0f) { return; } looptri_indices.append(index); @@ -505,9 +413,6 @@ struct AddOperationExecutor { const float brush_plane_area_su = M_PI * brush_radius_sq_su; const float approximate_density_su = add_amount_ / brush_plane_area_su; - /* Used for switching between two triangle sampling strategies. */ - const float area_threshold = brush_plane_area_su; - /* Usually one or two iterations should be enough. */ const int max_iterations = 5; int current_iteration = 0; @@ -517,78 +422,18 @@ struct AddOperationExecutor { if (current_iteration++ >= max_iterations) { break; } - - for (const int looptri_index : looptri_indices) { - const MLoopTri &looptri = surface_looptris_[looptri_index]; - - const float3 v0_su = surface_->mvert[surface_->mloop[looptri.tri[0]].v].co; - const float3 v1_su = surface_->mvert[surface_->mloop[looptri.tri[1]].v].co; - const float3 v2_su = surface_->mvert[surface_->mloop[looptri.tri[2]].v].co; - - const float looptri_area_su = area_tri_v3(v0_su, v1_su, v2_su); - - if (looptri_area_su < area_threshold) { - /* The triangle is small compared to the brush radius. Sample by generating random - * barycentric coordinates. */ - const int amount = rng.round_probabilistic(approximate_density_su * looptri_area_su); - for ([[maybe_unused]] const int i : IndexRange(amount)) { - const float3 bary_coord = rng.get_barycentric_coordinates(); - const float3 point_pos_su = attribute_math::mix3(bary_coord, v0_su, v1_su, v2_su); - const float distance_to_brush_sq_su = math::distance_squared(point_pos_su, - brush_pos_su); - if (distance_to_brush_sq_su > brush_radius_sq_su) { - continue; - } - - r_added_points.bary_coords.append(bary_coord); - r_added_points.looptri_indices.append(looptri_index); - r_added_points.positions_cu.append(surface_to_curves_mat_ * point_pos_su); - } - } - else { - /* The triangle is large compared to the brush radius. Sample by generating random points - * on the triangle plane within the brush radius. */ - float3 normal_su; - normal_tri_v3(normal_su, v0_su, v1_su, v2_su); - - float3 brush_pos_proj_su = brush_pos_su; - project_v3_plane(brush_pos_proj_su, normal_su, v0_su); - - const float proj_distance_sq_su = math::distance_squared(brush_pos_proj_su, - brush_pos_su); - const float brush_radius_factor_sq = 1.0f - - std::min(1.0f, - proj_distance_sq_su / brush_radius_sq_su); - const float radius_proj_sq_su = brush_radius_sq_su * brush_radius_factor_sq; - const float radius_proj_su = std::sqrt(radius_proj_sq_su); - const float circle_area_su = M_PI * radius_proj_su; - - const int amount = rng.round_probabilistic(approximate_density_su * circle_area_su); - - const float3 axis_1_su = math::normalize(v1_su - v0_su) * radius_proj_su; - const float3 axis_2_su = math::normalize(math::cross( - axis_1_su, math::cross(axis_1_su, v2_su - v0_su))) * - radius_proj_su; - - for ([[maybe_unused]] const int i : IndexRange(amount)) { - const float r = std::sqrt(rng.get_float()); - const float angle = rng.get_float() * 2.0f * M_PI; - const float x = r * std::cos(angle); - const float y = r * std::sin(angle); - const float3 point_pos_su = brush_pos_proj_su + axis_1_su * x + axis_2_su * y; - if (!isect_point_tri_prism_v3(point_pos_su, v0_su, v1_su, v2_su)) { - /* Sampled point is not in the triangle. */ - continue; - } - - float3 bary_coord; - interp_weights_tri_v3(bary_coord, v0_su, v1_su, v2_su, point_pos_su); - - r_added_points.bary_coords.append(bary_coord); - r_added_points.looptri_indices.append(looptri_index); - r_added_points.positions_cu.append(surface_to_curves_mat_ * point_pos_su); - } - } + const int new_points = bke::mesh_surface_sample::sample_surface_points_spherical( + rng, + *surface_, + looptri_indices, + brush_pos_su, + brush_radius_su, + approximate_density_su, + r_added_points.bary_coords, + r_added_points.looptri_indices, + r_added_points.positions_cu); + for (float3 &pos : r_added_points.positions_cu.as_mutable_span().take_back(new_points)) { + pos = transforms_.surface_to_curves * pos; } } @@ -613,312 +458,6 @@ struct AddOperationExecutor { BLI_kdtree_3d_balance(self_->curve_roots_kdtree_); } } - - void initialize_curve_offsets_with_interpolation(const Span<NeighborsVector> neighbors_per_curve) - { - MutableSpan<int> new_offsets = curves_->offsets_for_write().drop_front(tot_old_curves_); - - attribute_math::DefaultMixer<int> mixer{new_offsets}; - threading::parallel_for(neighbors_per_curve.index_range(), 1024, [&](IndexRange curves_range) { - for (const int i : curves_range) { - if (neighbors_per_curve[i].is_empty()) { - mixer.mix_in(i, constant_points_per_curve_, 1.0f); - } - else { - for (const NeighborInfo &neighbor : neighbors_per_curve[i]) { - const int neighbor_points_num = curves_->points_for_curve(neighbor.index).size(); - mixer.mix_in(i, neighbor_points_num, neighbor.weight); - } - } - } - }); - mixer.finalize(); - - bke::curves::accumulate_counts_to_offsets(new_offsets, tot_old_points_); - } - - void initialize_curve_offsets_without_interpolation(const int points_per_curve) - { - MutableSpan<int> new_offsets = curves_->offsets_for_write().drop_front(tot_old_curves_); - int offset = tot_old_points_; - for (const int i : new_offsets.index_range()) { - new_offsets[i] = offset; - offset += points_per_curve; - } - } - - void initialize_attributes(const AddedPoints &added_points, - const Span<NeighborsVector> neighbors_per_curve) - { - Array<float> new_lengths_cu(added_points.bary_coords.size()); - if (interpolate_length_) { - this->interpolate_lengths(neighbors_per_curve, new_lengths_cu); - } - else { - new_lengths_cu.fill(new_curve_length_); - } - - Array<float3> new_normals_su = this->compute_normals_for_added_curves_su(added_points); - if (!surface_uv_map_.is_empty()) { - this->initialize_surface_attachment(added_points); - } - - this->fill_new_selection(); - - if (interpolate_shape_) { - this->initialize_position_with_interpolation( - added_points, neighbors_per_curve, new_normals_su, new_lengths_cu); - } - else { - this->initialize_position_without_interpolation( - added_points, new_lengths_cu, new_normals_su); - } - } - - /** - * Select newly created points or curves in new curves if necessary. - */ - void fill_new_selection() - { - switch (curves_id_->selection_domain) { - case ATTR_DOMAIN_CURVE: { - const VArray<float> selection = curves_->selection_curve_float(); - if (selection.is_single() && selection.get_internal_single() >= 1.0f) { - return; - } - curves_->selection_curve_float_for_write().drop_front(tot_old_curves_).fill(1.0f); - break; - } - case ATTR_DOMAIN_POINT: { - const VArray<float> selection = curves_->selection_point_float(); - if (selection.is_single() && selection.get_internal_single() >= 1.0f) { - return; - } - curves_->selection_point_float_for_write().drop_front(tot_old_points_).fill(1.0f); - break; - } - default: - BLI_assert_unreachable(); - } - } - - Array<NeighborsVector> find_curve_neighbors(const AddedPoints &added_points) - { - const int tot_added_curves = added_points.bary_coords.size(); - Array<NeighborsVector> neighbors_per_curve(tot_added_curves); - threading::parallel_for(IndexRange(tot_added_curves), 128, [&](const IndexRange range) { - for (const int i : range) { - const float3 root_cu = added_points.positions_cu[i]; - std::array<KDTreeNearest_3d, max_neighbors> nearest_n; - const int found_neighbors = BLI_kdtree_3d_find_nearest_n( - self_->curve_roots_kdtree_, root_cu, nearest_n.data(), max_neighbors); - float tot_weight = 0.0f; - for (const int neighbor_i : IndexRange(found_neighbors)) { - KDTreeNearest_3d &nearest = nearest_n[neighbor_i]; - const float weight = 1.0f / std::max(nearest.dist, 0.00001f); - tot_weight += weight; - neighbors_per_curve[i].append({nearest.index, weight}); - } - /* Normalize weights. */ - for (NeighborInfo &neighbor : neighbors_per_curve[i]) { - neighbor.weight /= tot_weight; - } - } - }); - return neighbors_per_curve; - } - - void interpolate_lengths(const Span<NeighborsVector> neighbors_per_curve, - MutableSpan<float> r_lengths) - { - const Span<float3> positions_cu = curves_->positions(); - - threading::parallel_for(r_lengths.index_range(), 128, [&](const IndexRange range) { - for (const int added_curve_i : range) { - const Span<NeighborInfo> neighbors = neighbors_per_curve[added_curve_i]; - float length_sum = 0.0f; - for (const NeighborInfo &neighbor : neighbors) { - const IndexRange neighbor_points = curves_->points_for_curve(neighbor.index); - float neighbor_length = 0.0f; - for (const int segment_i : neighbor_points.drop_back(1)) { - const float3 &p1 = positions_cu[segment_i]; - const float3 &p2 = positions_cu[segment_i + 1]; - neighbor_length += math::distance(p1, p2); - } - length_sum += neighbor.weight * neighbor_length; - } - const float length = neighbors.is_empty() ? new_curve_length_ : length_sum; - r_lengths[added_curve_i] = length; - } - }); - } - - float3 compute_point_normal_su(const int looptri_index, const float3 &bary_coord) - { - const MLoopTri &looptri = surface_looptris_[looptri_index]; - const int l0 = looptri.tri[0]; - const int l1 = looptri.tri[1]; - const int l2 = looptri.tri[2]; - - const float3 &l0_normal_su = corner_normals_su_[l0]; - const float3 &l1_normal_su = corner_normals_su_[l1]; - const float3 &l2_normal_su = corner_normals_su_[l2]; - - const float3 normal_su = math::normalize( - attribute_math::mix3(bary_coord, l0_normal_su, l1_normal_su, l2_normal_su)); - return normal_su; - } - - Array<float3> compute_normals_for_added_curves_su(const AddedPoints &added_points) - { - Array<float3> normals_su(added_points.bary_coords.size()); - threading::parallel_for(normals_su.index_range(), 256, [&](const IndexRange range) { - for (const int i : range) { - const int looptri_index = added_points.looptri_indices[i]; - const float3 &bary_coord = added_points.bary_coords[i]; - normals_su[i] = compute_surface_point_normal( - surface_looptris_[looptri_index], bary_coord, corner_normals_su_); - } - }); - return normals_su; - } - - void initialize_surface_attachment(const AddedPoints &added_points) - { - MutableSpan<float2> surface_uv_coords = curves_->surface_uv_coords_for_write(); - threading::parallel_for( - added_points.bary_coords.index_range(), 1024, [&](const IndexRange range) { - for (const int i : range) { - const int curve_i = tot_old_curves_ + i; - const MLoopTri &looptri = surface_looptris_[added_points.looptri_indices[i]]; - const float2 &uv0 = surface_uv_map_[looptri.tri[0]]; - const float2 &uv1 = surface_uv_map_[looptri.tri[1]]; - const float2 &uv2 = surface_uv_map_[looptri.tri[2]]; - const float3 &bary_coords = added_points.bary_coords[i]; - const float2 uv = attribute_math::mix3(bary_coords, uv0, uv1, uv2); - surface_uv_coords[curve_i] = uv; - } - }); - } - - /** - * Initialize new curves so that they are just a straight line in the normal direction. - */ - void initialize_position_without_interpolation(const AddedPoints &added_points, - const Span<float> lengths_cu, - const MutableSpan<float3> normals_su) - { - MutableSpan<float3> positions_cu = curves_->positions_for_write(); - - threading::parallel_for( - added_points.bary_coords.index_range(), 256, [&](const IndexRange range) { - for (const int i : range) { - const IndexRange points = curves_->points_for_curve(tot_old_curves_ + i); - const float3 &root_cu = added_points.positions_cu[i]; - const float length = lengths_cu[i]; - const float3 &normal_su = normals_su[i]; - const float3 normal_cu = math::normalize(surface_to_curves_normal_mat_ * normal_su); - const float3 tip_cu = root_cu + length * normal_cu; - - initialize_straight_curve_positions(root_cu, tip_cu, positions_cu.slice(points)); - } - }); - } - - /** - * Use neighboring curves to determine the shape. - */ - void initialize_position_with_interpolation(const AddedPoints &added_points, - const Span<NeighborsVector> neighbors_per_curve, - const Span<float3> new_normals_su, - const Span<float> new_lengths_cu) - { - MutableSpan<float3> positions_cu = curves_->positions_for_write(); - - threading::parallel_for( - added_points.bary_coords.index_range(), 256, [&](const IndexRange range) { - for (const int i : range) { - const Span<NeighborInfo> neighbors = neighbors_per_curve[i]; - const IndexRange points = curves_->points_for_curve(tot_old_curves_ + i); - - const float length_cu = new_lengths_cu[i]; - const float3 &normal_su = new_normals_su[i]; - const float3 normal_cu = math::normalize(surface_to_curves_normal_mat_ * normal_su); - - const float3 &root_cu = added_points.positions_cu[i]; - - if (neighbors.is_empty()) { - /* If there are no neighbors, just make a straight line. */ - const float3 tip_cu = root_cu + length_cu * normal_cu; - initialize_straight_curve_positions(root_cu, tip_cu, positions_cu.slice(points)); - continue; - } - - positions_cu.slice(points).fill(root_cu); - - for (const NeighborInfo &neighbor : neighbors) { - const int neighbor_curve_i = neighbor.index; - const float3 &neighbor_first_pos_cu = - positions_cu[curves_->offsets()[neighbor_curve_i]]; - const float3 neighbor_first_pos_su = curves_to_surface_mat_ * neighbor_first_pos_cu; - - BVHTreeNearest nearest; - nearest.dist_sq = FLT_MAX; - BLI_bvhtree_find_nearest(surface_bvh_.tree, - neighbor_first_pos_su, - &nearest, - surface_bvh_.nearest_callback, - &surface_bvh_); - const int neighbor_looptri_index = nearest.index; - const MLoopTri &neighbor_looptri = surface_looptris_[neighbor_looptri_index]; - - const float3 neighbor_bary_coord = compute_bary_coord_in_triangle( - *surface_, neighbor_looptri, nearest.co); - - const float3 neighbor_normal_su = compute_surface_point_normal( - surface_looptris_[neighbor_looptri_index], - neighbor_bary_coord, - corner_normals_su_); - const float3 neighbor_normal_cu = math::normalize(surface_to_curves_normal_mat_ * - neighbor_normal_su); - - /* The rotation matrix used to transform relative coordinates of the neighbor curve - * to the new curve. */ - float normal_rotation_cu[3][3]; - rotation_between_vecs_to_mat3(normal_rotation_cu, neighbor_normal_cu, normal_cu); - - const IndexRange neighbor_points = curves_->points_for_curve(neighbor_curve_i); - const float3 &neighbor_root_cu = positions_cu[neighbor_points[0]]; - - /* Use a temporary #PolySpline, because that's the easiest way to resample an - * existing curve right now. Resampling is necessary if the length of the new curve - * does not match the length of the neighbors or the number of handle points is - * different. */ - PolySpline neighbor_spline; - neighbor_spline.resize(neighbor_points.size()); - neighbor_spline.positions().copy_from(positions_cu.slice(neighbor_points)); - neighbor_spline.mark_cache_invalid(); - - const float neighbor_length_cu = neighbor_spline.length(); - const float length_factor = std::min(1.0f, length_cu / neighbor_length_cu); - - const float resample_factor = (1.0f / (points.size() - 1.0f)) * length_factor; - for (const int j : IndexRange(points.size())) { - const Spline::LookupResult lookup = neighbor_spline.lookup_evaluated_factor( - j * resample_factor); - const float index_factor = lookup.evaluated_index + lookup.factor; - float3 p; - neighbor_spline.sample_with_index_factors<float3>( - neighbor_spline.positions(), {&index_factor, 1}, {&p, 1}); - const float3 relative_coord = p - neighbor_root_cu; - float3 rotated_relative_coord = relative_coord; - mul_m3_v3(normal_rotation_cu, rotated_relative_coord); - positions_cu[points[j]] += neighbor.weight * rotated_relative_coord; - } - } - } - }); - } }; void AddOperation::on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc index 7e583773512..8c6ef34ef26 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc @@ -256,6 +256,55 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph, return brush_3d; } +std::optional<CurvesBrush3D> sample_curves_surface_3d_brush( + const Depsgraph &depsgraph, + const ARegion ®ion, + const View3D &v3d, + const CurvesSculptTransforms &transforms, + const BVHTreeFromMesh &surface_bvh, + const float2 &brush_pos_re, + const float brush_radius_re) +{ + float3 brush_ray_start_wo, brush_ray_end_wo; + ED_view3d_win_to_segment_clipped( + &depsgraph, ®ion, &v3d, brush_pos_re, brush_ray_start_wo, brush_ray_end_wo, true); + const float3 brush_ray_start_su = transforms.world_to_surface * brush_ray_start_wo; + const float3 brush_ray_end_su = transforms.world_to_surface * brush_ray_end_wo; + + const float3 brush_ray_direction_su = math::normalize(brush_ray_end_su - brush_ray_start_su); + + BVHTreeRayHit ray_hit; + ray_hit.dist = FLT_MAX; + ray_hit.index = -1; + BLI_bvhtree_ray_cast(surface_bvh.tree, + brush_ray_start_su, + brush_ray_direction_su, + 0.0f, + &ray_hit, + surface_bvh.raycast_callback, + const_cast<void *>(static_cast<const void *>(&surface_bvh))); + if (ray_hit.index == -1) { + return std::nullopt; + } + + float3 brush_radius_ray_start_wo, brush_radius_ray_end_wo; + ED_view3d_win_to_segment_clipped(&depsgraph, + ®ion, + &v3d, + brush_pos_re + float2(brush_radius_re, 0), + brush_radius_ray_start_wo, + brush_radius_ray_end_wo, + true); + const float3 brush_radius_ray_start_cu = transforms.world_to_curves * brush_radius_ray_start_wo; + const float3 brush_radius_ray_end_cu = transforms.world_to_curves * brush_radius_ray_end_wo; + + const float3 brush_pos_su = ray_hit.co; + const float3 brush_pos_cu = transforms.surface_to_curves * brush_pos_su; + const float brush_radius_cu = dist_to_line_v3( + brush_pos_cu, brush_radius_ray_start_cu, brush_radius_ray_end_cu); + return CurvesBrush3D{brush_pos_cu, brush_radius_cu}; +} + Vector<float4x4> get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry) { Vector<float4x4> matrices; @@ -284,6 +333,16 @@ Vector<float4x4> get_symmetry_brush_transforms(const eCurvesSymmetryType symmetr return matrices; } +float transform_brush_radius(const float4x4 &transform, + const float3 &brush_position, + const float old_radius) +{ + const float3 offset_position = brush_position + float3(old_radius, 0.0f, 0.0f); + const float3 new_position = transform * brush_position; + const float3 new_offset_position = transform * offset_position; + return math::distance(new_position, new_offset_position); +} + void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position) { /* Find the accumulated length of each point in the original curve, @@ -324,33 +383,18 @@ CurvesSculptCommonContext::CurvesSculptCommonContext(const bContext &C) this->rv3d = CTX_wm_region_view3d(&C); } -float3 compute_surface_point_normal(const MLoopTri &looptri, - const float3 &bary_coord, - const Span<float3> corner_normals) -{ - const int l0 = looptri.tri[0]; - const int l1 = looptri.tri[1]; - const int l2 = looptri.tri[2]; - - const float3 &l0_normal = corner_normals[l0]; - const float3 &l1_normal = corner_normals[l1]; - const float3 &l2_normal = corner_normals[l2]; - - const float3 normal = math::normalize( - attribute_math::mix3(bary_coord, l0_normal, l1_normal, l2_normal)); - return normal; -} - -float3 compute_bary_coord_in_triangle(const Mesh &mesh, - const MLoopTri &looptri, - const float3 &position) +CurvesSculptTransforms::CurvesSculptTransforms(const Object &curves_ob, const Object *surface_ob) { - const float3 &v0 = mesh.mvert[mesh.mloop[looptri.tri[0]].v].co; - const float3 &v1 = mesh.mvert[mesh.mloop[looptri.tri[1]].v].co; - const float3 &v2 = mesh.mvert[mesh.mloop[looptri.tri[2]].v].co; - float3 bary_coords; - interp_weights_tri_v3(bary_coords, v0, v1, v2, position); - return bary_coords; + this->curves_to_world = curves_ob.obmat; + this->world_to_curves = this->curves_to_world.inverted(); + + if (surface_ob != nullptr) { + this->surface_to_world = surface_ob->obmat; + this->world_to_surface = this->surface_to_world.inverted(); + this->surface_to_curves = this->world_to_curves * this->surface_to_world; + this->curves_to_surface = this->world_to_surface * this->curves_to_world; + this->surface_to_curves_normal = this->surface_to_curves.inverted().transposed(); + } } } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc index ae0a512c5ee..541bf9d8253 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc @@ -100,8 +100,7 @@ struct CombOperationExecutor { float2 brush_pos_re_; float2 brush_pos_diff_re_; - float4x4 curves_to_world_mat_; - float4x4 world_to_curves_mat_; + CurvesSculptTransforms transforms_; CombOperationExecutor(const bContext &C) : ctx_(C) { @@ -121,9 +120,6 @@ struct CombOperationExecutor { brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension); brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension); - curves_to_world_mat_ = object_->obmat; - world_to_curves_mat_ = curves_to_world_mat_.inverted(); - falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape); curves_id_ = static_cast<Curves *>(object_->data); @@ -132,6 +128,8 @@ struct CombOperationExecutor { return; } + transforms_ = CurvesSculptTransforms(*object_, curves_id_->surface); + point_factors_ = get_point_selection(*curves_id_); curve_selection_ = retrieve_selected_curves(*curves_id_, selected_curve_indices_); @@ -225,11 +223,11 @@ struct CombOperationExecutor { float3 new_position_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * old_pos_cu, + transforms_.curves_to_world * old_pos_cu, new_position_re, new_position_wo); const float3 new_position_cu = brush_transform * - (world_to_curves_mat_ * new_position_wo); + (transforms_.world_to_curves * new_position_wo); positions_cu[point_i] = new_position_cu; curve_changed = true; @@ -252,16 +250,16 @@ struct CombOperationExecutor { float3 brush_start_wo, brush_end_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_prev_re_, brush_start_wo); ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_re_, brush_end_wo); - const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo; - const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo; + const float3 brush_start_cu = transforms_.world_to_curves * brush_start_wo; + const float3 brush_end_cu = transforms_.world_to_curves * brush_end_wo; const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc b/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc index 6f12d539aa2..eab7dabcd22 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc @@ -76,8 +76,7 @@ struct DeleteOperationExecutor { float2 brush_pos_re_; - float4x4 curves_to_world_mat_; - float4x4 world_to_curves_mat_; + CurvesSculptTransforms transforms_; DeleteOperationExecutor(const bContext &C) : ctx_(C) { @@ -101,8 +100,7 @@ struct DeleteOperationExecutor { brush_pos_re_ = stroke_extension.mouse_position; - curves_to_world_mat_ = object_->obmat; - world_to_curves_mat_ = curves_to_world_mat_.inverted(); + transforms_ = CurvesSculptTransforms(*object_, curves_id_->surface); const eBrushFalloffShape falloff_shape = static_cast<eBrushFalloffShape>( brush_->falloff_shape); @@ -199,10 +197,10 @@ struct DeleteOperationExecutor { float3 brush_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_re_, brush_wo); - const float3 brush_cu = world_to_curves_mat_ * brush_wo; + const float3 brush_cu = transforms_.world_to_curves * brush_wo; const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_->symmetry)); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc index 3420659520b..cf893f09fc6 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc @@ -247,8 +247,7 @@ struct CurvesEffectOperationExecutor { eBrushFalloffShape falloff_shape_; - float4x4 curves_to_world_mat_; - float4x4 world_to_curves_mat_; + CurvesSculptTransforms transforms_; float2 brush_pos_start_re_; float2 brush_pos_end_re_; @@ -290,8 +289,7 @@ struct CurvesEffectOperationExecutor { falloff_shape_ = eBrushFalloffShape(brush_->falloff_shape); - curves_to_world_mat_ = object_->obmat; - world_to_curves_mat_ = curves_to_world_mat_.inverted(); + transforms_ = CurvesSculptTransforms(*object_, curves_id_->surface); brush_pos_start_re_ = self.last_mouse_position_; brush_pos_end_re_ = stroke_extension.mouse_position; @@ -398,16 +396,16 @@ struct CurvesEffectOperationExecutor { float3 brush_start_pos_wo, brush_end_pos_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * closest_on_segment_cu, + transforms_.curves_to_world * closest_on_segment_cu, brush_pos_start_re_, brush_start_pos_wo); ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * closest_on_segment_cu, + transforms_.curves_to_world * closest_on_segment_cu, brush_pos_end_re_, brush_end_pos_wo); - const float3 brush_start_pos_cu = world_to_curves_mat_ * brush_start_pos_wo; - const float3 brush_end_pos_cu = world_to_curves_mat_ * brush_end_pos_wo; + const float3 brush_start_pos_cu = transforms_.world_to_curves * brush_start_pos_wo; + const float3 brush_end_pos_cu = transforms_.world_to_curves * brush_end_pos_wo; const float move_distance_cu = weight * math::distance(brush_start_pos_cu, brush_end_pos_cu); @@ -430,16 +428,16 @@ struct CurvesEffectOperationExecutor { float3 brush_pos_start_wo, brush_pos_end_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_start_re_, brush_pos_start_wo); ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_end_re_, brush_pos_end_wo); - const float3 brush_pos_start_cu = world_to_curves_mat_ * brush_pos_start_wo; - const float3 brush_pos_end_cu = world_to_curves_mat_ * brush_pos_end_wo; + const float3 brush_pos_start_cu = transforms_.world_to_curves * brush_pos_start_wo; + const float3 brush_pos_end_cu = transforms_.world_to_curves * brush_pos_end_wo; const float3 brush_pos_diff_cu = brush_pos_end_cu - brush_pos_start_cu; const float brush_pos_diff_length_cu = math::length(brush_pos_diff_cu); const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh index 5c926b1a740..ad3871bee45 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh @@ -21,6 +21,7 @@ struct View3D; struct Object; struct Brush; struct Scene; +struct BVHTreeFromMesh; namespace blender::ed::sculpt_paint { @@ -60,6 +61,13 @@ std::unique_ptr<CurvesSculptStrokeOperation> new_grow_shrink_operation( const BrushStrokeMode brush_mode, const bContext &C); std::unique_ptr<CurvesSculptStrokeOperation> new_selection_paint_operation( const BrushStrokeMode brush_mode, const bContext &C); +std::unique_ptr<CurvesSculptStrokeOperation> new_pinch_operation(const BrushStrokeMode brush_mode, + const bContext &C); +std::unique_ptr<CurvesSculptStrokeOperation> new_smooth_operation(); +std::unique_ptr<CurvesSculptStrokeOperation> new_puff_operation(); +std::unique_ptr<CurvesSculptStrokeOperation> new_density_operation( + const BrushStrokeMode brush_mode, const bContext &C); +std::unique_ptr<CurvesSculptStrokeOperation> new_slide_operation(); struct CurvesBrush3D { float3 position_cu; @@ -97,14 +105,6 @@ IndexMask retrieve_selected_curves(const Curves &curves_id, Vector<int64_t> &r_i void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position); -float3 compute_surface_point_normal(const MLoopTri &looptri, - const float3 &bary_coord, - const Span<float3> corner_normals); - -float3 compute_bary_coord_in_triangle(const Mesh &mesh, - const MLoopTri &looptri, - const float3 &position); - class CurvesSculptCommonContext { public: const Depsgraph *depsgraph = nullptr; @@ -116,4 +116,30 @@ class CurvesSculptCommonContext { CurvesSculptCommonContext(const bContext &C); }; +struct CurvesSculptTransforms { + float4x4 curves_to_world; + float4x4 curves_to_surface; + float4x4 world_to_curves; + float4x4 world_to_surface; + float4x4 surface_to_world; + float4x4 surface_to_curves; + float4x4 surface_to_curves_normal; + + CurvesSculptTransforms() = default; + CurvesSculptTransforms(const Object &curves_ob, const Object *surface_ob); +}; + +std::optional<CurvesBrush3D> sample_curves_surface_3d_brush( + const Depsgraph &depsgraph, + const ARegion ®ion, + const View3D &v3d, + const CurvesSculptTransforms &transforms, + const BVHTreeFromMesh &surface_bvh, + const float2 &brush_pos_re, + const float brush_radius_re); + +float transform_brush_radius(const float4x4 &transform, + const float3 &brush_position, + const float old_radius); + } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_selection_paint.cc b/source/blender/editors/sculpt_paint/curves_sculpt_selection_paint.cc index 69615a3bfb4..b40aebcaaf1 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_selection_paint.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_selection_paint.cc @@ -66,8 +66,7 @@ struct SelectionPaintOperationExecutor { float2 brush_pos_re_; - float4x4 curves_to_world_mat_; - float4x4 world_to_curves_mat_; + CurvesSculptTransforms transforms_; SelectionPaintOperationExecutor(const bContext &C) : ctx_(C) { @@ -105,8 +104,7 @@ struct SelectionPaintOperationExecutor { } } - curves_to_world_mat_ = object_->obmat; - world_to_curves_mat_ = curves_to_world_mat_.inverted(); + transforms_ = CurvesSculptTransforms(*object_, curves_id_->surface); const eBrushFalloffShape falloff_shape = static_cast<eBrushFalloffShape>( brush_->falloff_shape); @@ -201,10 +199,10 @@ struct SelectionPaintOperationExecutor { float3 brush_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_re_, brush_wo); - const float3 brush_cu = world_to_curves_mat_ * brush_wo; + const float3 brush_cu = transforms_.world_to_curves * brush_wo; const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_->symmetry)); @@ -309,10 +307,10 @@ struct SelectionPaintOperationExecutor { float3 brush_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_re_, brush_wo); - const float3 brush_cu = world_to_curves_mat_ * brush_wo; + const float3 brush_cu = transforms_.world_to_curves * brush_wo; const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_->symmetry)); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc index e1aecabdcc7..b63e5a7756b 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc @@ -89,8 +89,7 @@ struct SnakeHookOperatorExecutor { Vector<int64_t> selected_curve_indices_; IndexMask curve_selection_; - float4x4 curves_to_world_mat_; - float4x4 world_to_curves_mat_; + CurvesSculptTransforms transforms_; float2 brush_pos_prev_re_; float2 brush_pos_re_; @@ -118,15 +117,14 @@ struct SnakeHookOperatorExecutor { falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape); - curves_to_world_mat_ = object_->obmat; - world_to_curves_mat_ = curves_to_world_mat_.inverted(); - curves_id_ = static_cast<Curves *>(object_->data); curves_ = &CurvesGeometry::wrap(curves_id_->geometry); if (curves_->curves_num() == 0) { return; } + transforms_ = CurvesSculptTransforms(*object_, curves_id_->surface); + curve_factors_ = get_curves_selection(*curves_id_); curve_selection_ = retrieve_selected_curves(*curves_id_, selected_curve_indices_); @@ -210,10 +208,11 @@ struct SnakeHookOperatorExecutor { float3 new_position_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * old_pos_cu, + transforms_.curves_to_world * old_pos_cu, new_position_re, new_position_wo); - const float3 new_position_cu = brush_transform * (world_to_curves_mat_ * new_position_wo); + const float3 new_position_cu = brush_transform * + (transforms_.world_to_curves * new_position_wo); move_last_point_and_resample(positions_cu.slice(points), new_position_cu); } @@ -228,16 +227,16 @@ struct SnakeHookOperatorExecutor { float3 brush_start_wo, brush_end_wo; ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_prev_re_, brush_start_wo); ED_view3d_win_to_3d(ctx_.v3d, ctx_.region, - curves_to_world_mat_ * self_->brush_3d_.position_cu, + transforms_.curves_to_world * self_->brush_3d_.position_cu, brush_pos_re_, brush_end_wo); - const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo; - const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo; + const float3 brush_start_cu = transforms_.world_to_curves * brush_start_wo; + const float3 brush_end_cu = transforms_.world_to_curves * brush_end_wo; const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_; diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc index a2e1adff50a..6a47aceb2b0 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc @@ -11,6 +11,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BLI_array.hh" #include "BLI_math_base.h" #include "BLI_math_color.h" @@ -30,6 +31,8 @@ #include "paint_intern.h" /* own include */ +using blender::Array; + /* -------------------------------------------------------------------- */ /** \name Internal Utility Functions * \{ */ @@ -45,7 +48,7 @@ static bool vertex_weight_paint_mode_poll(bContext *C) static void tag_object_after_update(Object *object) { BLI_assert(object->type == OB_MESH); - Mesh *mesh = object->data; + Mesh *mesh = static_cast<Mesh *>(object->data); DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE); /* NOTE: Original mesh is used for display, so tag it directly here. */ BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL); @@ -63,7 +66,8 @@ static bool vertex_paint_from_weight(Object *ob) const MPoly *mp; int vgroup_active; - if (((me = BKE_mesh_from_object(ob)) == NULL || (ED_mesh_color_ensure(me, NULL)) == false)) { + if (((me = BKE_mesh_from_object(ob)) == nullptr || + (ED_mesh_color_ensure(me, nullptr)) == false)) { return false; } @@ -128,14 +132,13 @@ static void vertex_color_smooth_looptag(Mesh *me, const bool *mlooptag) { const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; const MPoly *mp; - int(*scol)[4]; bool has_shared = false; - if (me->mloopcol == NULL || me->totvert == 0 || me->totpoly == 0) { + if (me->mloopcol == nullptr || me->totvert == 0 || me->totpoly == 0) { return; } - scol = MEM_callocN(sizeof(int) * me->totvert * 5, "scol"); + int(*scol)[4] = static_cast<int(*)[4]>(MEM_callocN(sizeof(int) * me->totvert * 5, "scol")); int i; for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) { @@ -185,16 +188,15 @@ static bool vertex_color_smooth(Object *ob) const MPoly *mp; int i, j; - bool *mlooptag; - - if (((me = BKE_mesh_from_object(ob)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) { + if (((me = BKE_mesh_from_object(ob)) == nullptr) || + (ED_mesh_color_ensure(me, nullptr) == false)) { return false; } const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - mlooptag = MEM_callocN(sizeof(bool) * me->totloop, "VPaintData mlooptag"); + Array<bool> loop_tag(me->totloop, false); /* simply tag loops of selected faces */ mp = me->mpoly; @@ -208,7 +210,7 @@ static bool vertex_color_smooth(Object *ob) j = 0; do { if (!(use_vert_sel && !(me->mvert[ml->v].flag & SELECT))) { - mlooptag[mp->loopstart + j] = true; + loop_tag[mp->loopstart + j] = true; } ml++; j++; @@ -218,9 +220,7 @@ static bool vertex_color_smooth(Object *ob) /* remove stale me->mcol, will be added later */ BKE_mesh_tessface_clear(me); - vertex_color_smooth_looptag(me, mlooptag); - - MEM_freeN(mlooptag); + vertex_color_smooth_looptag(me, loop_tag.data()); tag_object_after_update(ob); @@ -268,7 +268,8 @@ static void vpaint_tx_brightness_contrast(const float col[3], const void *user_data, float r_col[3]) { - const struct VPaintTx_BrightContrastData *data = user_data; + const VPaintTx_BrightContrastData *data = static_cast<const VPaintTx_BrightContrastData *>( + user_data); for (int i = 0; i < 3; i++) { r_col[i] = data->gain * col[i] + data->offset; @@ -302,10 +303,9 @@ static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op) } } - const struct VPaintTx_BrightContrastData user_data = { - .gain = gain, - .offset = offset, - }; + VPaintTx_BrightContrastData user_data{}; + user_data.gain = gain; + user_data.offset = offset; if (ED_vpaint_color_transform(obact, vpaint_tx_brightness_contrast, &user_data)) { WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact); @@ -345,7 +345,7 @@ struct VPaintTx_HueSatData { static void vpaint_tx_hsv(const float col[3], const void *user_data, float r_col[3]) { - const struct VPaintTx_HueSatData *data = user_data; + const VPaintTx_HueSatData *data = static_cast<const VPaintTx_HueSatData *>(user_data); float hsv[3]; rgb_to_hsv_v(col, hsv); @@ -366,11 +366,10 @@ static int vertex_color_hsv_exec(bContext *C, wmOperator *op) { Object *obact = CTX_data_active_object(C); - const struct VPaintTx_HueSatData user_data = { - .hue = RNA_float_get(op->ptr, "h"), - .sat = RNA_float_get(op->ptr, "s"), - .val = RNA_float_get(op->ptr, "v"), - }; + VPaintTx_HueSatData user_data{}; + user_data.hue = RNA_float_get(op->ptr, "h"); + user_data.sat = RNA_float_get(op->ptr, "s"); + user_data.val = RNA_float_get(op->ptr, "v"); if (ED_vpaint_color_transform(obact, vpaint_tx_hsv, &user_data)) { WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact); @@ -410,7 +409,7 @@ static int vertex_color_invert_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obact = CTX_data_active_object(C); - if (ED_vpaint_color_transform(obact, vpaint_tx_invert, NULL)) { + if (ED_vpaint_color_transform(obact, vpaint_tx_invert, nullptr)) { WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact); return OPERATOR_FINISHED; } @@ -439,7 +438,7 @@ struct VPaintTx_LevelsData { static void vpaint_tx_levels(const float col[3], const void *user_data, float r_col[3]) { - const struct VPaintTx_LevelsData *data = user_data; + const VPaintTx_LevelsData *data = static_cast<const VPaintTx_LevelsData *>(user_data); for (int i = 0; i < 3; i++) { r_col[i] = data->gain * (col[i] + data->offset); } @@ -449,10 +448,9 @@ static int vertex_color_levels_exec(bContext *C, wmOperator *op) { Object *obact = CTX_data_active_object(C); - const struct VPaintTx_LevelsData user_data = { - .gain = RNA_float_get(op->ptr, "gain"), - .offset = RNA_float_get(op->ptr, "offset"), - }; + VPaintTx_LevelsData user_data{}; + user_data.gain = RNA_float_get(op->ptr, "gain"); + user_data.offset = RNA_float_get(op->ptr, "offset"); if (ED_vpaint_color_transform(obact, vpaint_tx_levels, &user_data)) { WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 5f52e1a3071..a73883e7624 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -860,6 +860,7 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) sc->mask_info.draw_flag, sc->mask_info.draw_type, sc->mask_info.overlay_mode, + sc->mask_info.blend_factor, mask_width, mask_height, aspx, diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index fa49e996c2a..537132ac428 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -964,7 +964,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) static bool image_view_selected_poll(bContext *C) { - return (space_image_main_region_poll(C) && (ED_operator_uvedit(C) || ED_operator_mask(C))); + return (space_image_main_region_poll(C) && (ED_operator_uvedit(C) || ED_maskedit_poll(C))); } void IMAGE_OT_view_selected(wmOperatorType *ot) diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index ab8143c5bf5..785a5419e04 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -694,6 +694,7 @@ static void image_main_region_draw(const bContext *C, ARegion *region) sima->mask_info.draw_flag & ~MASK_DRAWFLAG_OVERLAY, sima->mask_info.draw_type, sima->mask_info.overlay_mode, + sima->mask_info.blend_factor, width, height, aspx, diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 6c631f46069..bb9e201d94a 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -621,7 +621,6 @@ static void nla_draw_strip(SpaceNla *snla, static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, - int index, View2D *v2d, float xminc, float xmaxc, @@ -636,7 +635,7 @@ static void nla_draw_strip_text(AnimData *adt, /* just print the name and the range */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index); + str_len = BLI_snprintf_rlen(str, sizeof(str), "Temp-Meta"); } else { str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str)); @@ -702,6 +701,89 @@ static void nla_draw_strip_frames_text( /* ---------------------- */ +/** + * Gets the first and last visible NLA strips on a track. + * Note that this also includes tracks that might only be + * visible because of their extendmode. + */ +static ListBase get_visible_nla_strips(NlaTrack *nlt, View2D *v2d) +{ + if (BLI_listbase_is_empty(&nlt->strips)) { + ListBase empty = {NULL, NULL}; + return empty; + } + + NlaStrip *first = NULL; + NlaStrip *last = NULL; + + /* Find the first strip that is within the bounds of the view. */ + LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) { + if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { + first = last = strip; + break; + } + } + + const bool has_strips_within_bounds = first != NULL; + + if (has_strips_within_bounds) { + /* Find the last visible strip. */ + for (NlaStrip *strip = first->next; strip; strip = strip->next) { + if (!BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { + break; + } + last = strip; + } + /* Check if the first strip is adjacent to a strip outside the view to the left + * that has an extendmode region that should be drawn. + * If so, adjust the first strip to include drawing that strip as well. + */ + NlaStrip *prev = first->prev; + if (prev && prev->extendmode != NLASTRIP_EXTEND_NOTHING) { + first = prev; + } + } + else { + /* No immediately visible strips. + * Figure out where our view is relative to the strips, then determine + * if the view is adjacent to a strip that should have its extendmode + * rendered. + */ + NlaStrip *first_strip = nlt->strips.first; + NlaStrip *last_strip = nlt->strips.last; + if (first_strip && v2d->cur.xmax < first_strip->start && + first_strip->extendmode == NLASTRIP_EXTEND_HOLD) { + /* The view is to the left of all strips and the first strip has an + * extendmode that should be drawn. + */ + first = last = first_strip; + } + else if (last_strip && v2d->cur.xmin > last_strip->end && + last_strip->extendmode != NLASTRIP_EXTEND_NOTHING) { + /* The view is to the right of all strips and the last strip has an + * extendmode that should be drawn. + */ + first = last = last_strip; + } + else { + /* The view is in the middle of two strips. */ + LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) { + /* Find the strip to the left by finding the strip to the right and getting its prev. */ + if (v2d->cur.xmax < strip->start) { + /* If the strip to the left has an extendmode, set that as the only visible strip. */ + if (strip->prev && strip->prev->extendmode != NLASTRIP_EXTEND_NOTHING) { + first = last = strip->prev; + } + break; + } + } + } + } + + ListBase visible_strips = {first, last}; + return visible_strips; +} + void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) { View2D *v2d = ®ion->v2d; @@ -737,29 +819,26 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *region) case ANIMTYPE_NLATRACK: { AnimData *adt = ale->adt; NlaTrack *nlt = (NlaTrack *)ale->data; - NlaStrip *strip; - int index; - - /* draw each strip in the track (if visible) */ - for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) { - if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { - const float xminc = strip->start + text_margin_x; - const float xmaxc = strip->end - text_margin_x; - - /* draw the visualization of the strip */ - nla_draw_strip(snla, adt, nlt, strip, v2d, ymin, ymax); - - /* add the text for this strip to the cache */ - if (xminc < xmaxc) { - nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, ymin, ymax); - } - - /* if transforming strips (only real reason for temp-metas currently), - * add to the cache the frame numbers of the strip's extents - */ - if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - nla_draw_strip_frames_text(nlt, strip, v2d, ymin, ymax); - } + ListBase visible_nla_strips = get_visible_nla_strips(nlt, v2d); + + /* Draw each visible strip in the track. */ + LISTBASE_FOREACH (NlaStrip *, strip, &visible_nla_strips) { + const float xminc = strip->start + text_margin_x; + const float xmaxc = strip->end - text_margin_x; + + /* draw the visualization of the strip */ + nla_draw_strip(snla, adt, nlt, strip, v2d, ymin, ymax); + + /* add the text for this strip to the cache */ + if (xminc < xmaxc) { + nla_draw_strip_text(adt, nlt, strip, v2d, xminc, xmaxc, ymin, ymax); + } + + /* if transforming strips (only real reason for temp-metas currently), + * add to the cache the frame numbers of the strip's extents + */ + if (strip->flag & NLASTRIP_FLAG_TEMP_META) { + nla_draw_strip_frames_text(nlt, strip, v2d, ymin, ymax); } } break; diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c index 263ef06718f..660afa4c3d7 100644 --- a/source/blender/editors/util/select_utils.c +++ b/source/blender/editors/util/select_utils.c @@ -66,15 +66,18 @@ eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first) return sel_op; } -int ED_select_similar_compare_float(const float delta, const float thresh, const int compare) +bool ED_select_similar_compare_float(const float delta, + const float thresh, + const eSimilarCmp compare) { + BLI_assert(thresh >= 0.0f); switch (compare) { case SIM_CMP_EQ: return (fabsf(delta) <= thresh); case SIM_CMP_GT: - return ((delta + thresh) >= 0.0); + return ((delta + thresh) >= 0.0f); case SIM_CMP_LT: - return ((delta - thresh) <= 0.0); + return ((delta - thresh) <= 0.0f); default: BLI_assert_unreachable(); return 0; @@ -84,8 +87,10 @@ int ED_select_similar_compare_float(const float delta, const float thresh, const bool ED_select_similar_compare_float_tree(const KDTree_1d *tree, const float length, const float thresh, - const int compare) + const eSimilarCmp compare) { + BLI_assert(compare == SIM_CMP_EQ || length >= 0.0f); /* See precision note below. */ + /* Length of the edge we want to compare against. */ float nearest_edge_length; @@ -112,6 +117,7 @@ bool ED_select_similar_compare_float_tree(const KDTree_1d *tree, KDTreeNearest_1d nearest; if (BLI_kdtree_1d_find_nearest(tree, &nearest_edge_length, &nearest) != -1) { + BLI_assert(compare == SIM_CMP_EQ || nearest.co[0] >= 0.0f); /* See precision note above. */ float delta = length - nearest.co[0]; return ED_select_similar_compare_float(delta, thresh, compare); } diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 181982f0b2c..04128cf378c 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -182,5 +182,6 @@ void UV_OT_select_circle(struct wmOperatorType *ot); void UV_OT_select_more(struct wmOperatorType *ot); void UV_OT_select_less(struct wmOperatorType *ot); void UV_OT_select_overlap(struct wmOperatorType *ot); +void UV_OT_select_similar(struct wmOperatorType *ot); /* Used only when UV sync select is disabled. */ void UV_OT_select_mode(struct wmOperatorType *ot); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index fe6f9f0d513..0b5d6592426 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2044,6 +2044,7 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_select_pinned); WM_operatortype_append(UV_OT_select_box); WM_operatortype_append(UV_OT_select_lasso); + WM_operatortype_append(UV_OT_select_similar); WM_operatortype_append(UV_OT_select_circle); WM_operatortype_append(UV_OT_select_more); WM_operatortype_append(UV_OT_select_less); diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index cea2bb05547..8dcf2ceb679 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -12,6 +12,7 @@ #include "MEM_guardedalloc.h" #include "DNA_image_types.h" +#include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -22,6 +23,7 @@ #include "BLI_blenlib.h" #include "BLI_hash.h" #include "BLI_kdopbvh.h" +#include "BLI_kdtree.h" #include "BLI_lasso_2d.h" #include "BLI_math.h" #include "BLI_polyfill_2d.h" @@ -31,6 +33,7 @@ #include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_layer.h" +#include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_report.h" @@ -75,6 +78,16 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph, const ToolSettings *ts, Object *obedit); +typedef enum { + UV_SSIM_AREA_UV = 1000, + UV_SSIM_AREA_3D, + UV_SSIM_LENGTH_UV, + UV_SSIM_LENGTH_3D, + UV_SSIM_SIDES, + UV_SSIM_PIN, + UV_SSIM_MATERIAL, +} eUVSelectSimilar; + /* -------------------------------------------------------------------- */ /** \name Active Selection Tracking * @@ -586,12 +599,25 @@ bool uvedit_uv_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_lo if (ts->selectmode & SCE_SELECT_FACE) { return BM_elem_flag_test_bool(l->f, BM_ELEM_SELECT); } + if (ts->selectmode & SCE_SELECT_EDGE) { + /* Are you looking for `uvedit_edge_select_test(...)` instead? */ + } return BM_elem_flag_test_bool(l->v, BM_ELEM_SELECT); } MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (ts->selectmode & SCE_SELECT_FACE) { + /* Are you looking for `uvedit_face_select_test(...)` instead? */ + } + + if (ts->selectmode & SCE_SELECT_EDGE) { + /* Are you looking for `uvedit_edge_select_test(...)` instead? */ + } + return (luv->flag & MLOOPUV_VERTSEL) != 0; } + bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) { return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); @@ -699,6 +725,10 @@ void uvedit_uv_select_enable(const Scene *scene, { const ToolSettings *ts = scene->toolsettings; + if (ts->selectmode & SCE_SELECT_EDGE) { + /* Are you looking for `uvedit_edge_select_set(...)` instead? */ + } + if (ts->uv_flag & UV_SYNC_SELECTION) { if (ts->selectmode & SCE_SELECT_FACE) { BM_face_select_set(em->bm, l->f, true); @@ -4412,6 +4442,550 @@ void UV_OT_select_overlap(wmOperatorType *ot) } /** \} */ +/** \name Select Similar Operator + * \{ */ + +static float get_uv_vert_needle(const eUVSelectSimilar type, + BMVert *vert, + const float ob_m3[3][3], + MLoopUV *luv, + const int cd_loop_uv_offset) +{ + float result = 0.0f; + switch (type) { + case UV_SSIM_AREA_UV: { + BMFace *f; + BMIter iter; + BM_ITER_ELEM (f, &iter, vert, BM_FACES_OF_VERT) { + result += BM_face_calc_area_uv(f, cd_loop_uv_offset); + } + } break; + case UV_SSIM_AREA_3D: { + BMFace *f; + BMIter iter; + BM_ITER_ELEM (f, &iter, vert, BM_FACES_OF_VERT) { + result += BM_face_calc_area_with_mat3(f, ob_m3); + } + } break; + case UV_SSIM_SIDES: { + BMEdge *e; + BMIter iter; + BM_ITER_ELEM (e, &iter, vert, BM_EDGES_OF_VERT) { + result += 1.0f; + } + } break; + case UV_SSIM_PIN: + return (luv->flag & MLOOPUV_PINNED) ? 1.0f : 0.0f; + default: + BLI_assert_unreachable(); + return false; + } + + return result; +} + +static float get_uv_edge_needle(const eUVSelectSimilar type, + BMEdge *edge, + const float ob_m3[3][3], + MLoopUV *luv_a, + MLoopUV *luv_b, + const int cd_loop_uv_offset) +{ + float result = 0.0f; + switch (type) { + case UV_SSIM_AREA_UV: { + BMFace *f; + BMIter iter; + BM_ITER_ELEM (f, &iter, edge, BM_FACES_OF_EDGE) { + result += BM_face_calc_area_uv(f, cd_loop_uv_offset); + } + } break; + case UV_SSIM_AREA_3D: { + BMFace *f; + BMIter iter; + BM_ITER_ELEM (f, &iter, edge, BM_FACES_OF_EDGE) { + result += BM_face_calc_area_with_mat3(f, ob_m3); + } + } break; + case UV_SSIM_LENGTH_UV: + return len_v2v2(luv_a->uv, luv_b->uv); + case UV_SSIM_LENGTH_3D: + return len_v3v3(edge->v1->co, edge->v2->co); + case UV_SSIM_SIDES: { + BMEdge *e; + BMIter iter; + BM_ITER_ELEM (e, &iter, edge, BM_FACES_OF_EDGE) { + result += 1.0f; + } + } break; + case UV_SSIM_PIN: + if (luv_a->flag & MLOOPUV_PINNED) { + result += 1.0f; + } + if (luv_b->flag & MLOOPUV_PINNED) { + result += 1.0f; + } + break; + default: + BLI_assert_unreachable(); + return false; + } + + return result; +} + +static float get_uv_face_needle(const eUVSelectSimilar type, + BMFace *face, + const float ob_m3[3][3], + const int cd_loop_uv_offset) +{ + float result = 0.0f; + switch (type) { + case UV_SSIM_AREA_UV: + return BM_face_calc_area_uv(face, cd_loop_uv_offset); + case UV_SSIM_AREA_3D: + return BM_face_calc_area_with_mat3(face, ob_m3); + case UV_SSIM_SIDES: + return face->len; + case UV_SSIM_PIN: { + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, face, BM_LOOPS_OF_FACE) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (luv->flag & MLOOPUV_PINNED) { + result += 1.0f; + } + } + } break; + case UV_SSIM_MATERIAL: + return face->mat_nr; + default: + BLI_assert_unreachable(); + return false; + } + return result; +} + +static int uv_select_similar_vert_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + const eUVSelectSimilar type = RNA_enum_get(op->ptr, "type"); + const float threshold = RNA_float_get(op->ptr, "threshold"); + const eSimilarCmp compare = RNA_enum_get(op->ptr, "compare"); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + int max_verts_selected_all = 0; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + max_verts_selected_all += face->len; + } + /* TODO: Get a tighter bounds */ + } + + int tree_index = 0; + KDTree_1d *tree_1d = BLI_kdtree_1d_new(max_verts_selected_all); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em->bm; + if (bm->totvertsel == 0) { + continue; + } + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + float ob_m3[3][3]; + copy_m3_m4(ob_m3, ob->obmat); + + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, face, BM_LOOPS_OF_FACE) { + if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + continue; + } + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + float needle = get_uv_vert_needle(type, l->v, ob_m3, luv, cd_loop_uv_offset); + BLI_kdtree_1d_insert(tree_1d, tree_index++, &needle); + } + } + } + + if (tree_1d != NULL) { + BLI_kdtree_1d_deduplicate(tree_1d); + BLI_kdtree_1d_balance(tree_1d); + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em->bm; + if (bm->totvertsel == 0) { + continue; + } + + bool changed = false; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + float ob_m3[3][3]; + copy_m3_m4(ob_m3, ob->obmat); + + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, face, BM_LOOPS_OF_FACE) { + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + continue; /* Already selected. */ + } + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const float needle = get_uv_vert_needle(type, l->v, ob_m3, luv, cd_loop_uv_offset); + bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare); + if (select) { + uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + changed = true; + } + } + if (changed) { + uv_select_tag_update_for_object(depsgraph, ts, ob); + } + } + } + + MEM_SAFE_FREE(objects); + BLI_kdtree_1d_free(tree_1d); + return OPERATOR_FINISHED; +} + +static int uv_select_similar_edge_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + const eUVSelectSimilar type = RNA_enum_get(op->ptr, "type"); + const float threshold = RNA_float_get(op->ptr, "threshold"); + const eSimilarCmp compare = RNA_enum_get(op->ptr, "compare"); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + int max_edges_selected_all = 0; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + max_edges_selected_all += face->len; + } + /* TODO: Get a tighter bounds. */ + } + + int tree_index = 0; + KDTree_1d *tree_1d = BLI_kdtree_1d_new(max_edges_selected_all); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em->bm; + if (bm->totvertsel == 0) { + continue; + } + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + float ob_m3[3][3]; + copy_m3_m4(ob_m3, ob->obmat); + + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, face, BM_LOOPS_OF_FACE) { + if (!uvedit_edge_select_test(scene, l, cd_loop_uv_offset)) { + continue; + } + + MLoopUV *luv_a = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + MLoopUV *luv_b = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + float needle = get_uv_edge_needle(type, l->e, ob_m3, luv_a, luv_b, cd_loop_uv_offset); + if (tree_1d) { + BLI_kdtree_1d_insert(tree_1d, tree_index++, &needle); + } + } + } + } + + if (tree_1d != NULL) { + BLI_kdtree_1d_deduplicate(tree_1d); + BLI_kdtree_1d_balance(tree_1d); + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em->bm; + if (bm->totvertsel == 0) { + continue; + } + + bool changed = false; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + float ob_m3[3][3]; + copy_m3_m4(ob_m3, ob->obmat); + + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, face, BM_LOOPS_OF_FACE) { + if (uvedit_edge_select_test(scene, l, cd_loop_uv_offset)) { + continue; /* Already selected. */ + } + + MLoopUV *luv_a = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + MLoopUV *luv_b = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + float needle = get_uv_edge_needle(type, l->e, ob_m3, luv_a, luv_b, cd_loop_uv_offset); + bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare); + if (select) { + uvedit_edge_select_set(scene, em, l, select, false, cd_loop_uv_offset); + changed = true; + } + } + if (changed) { + uv_select_tag_update_for_object(depsgraph, ts, ob); + } + } + } + + MEM_SAFE_FREE(objects); + BLI_kdtree_1d_free(tree_1d); + return OPERATOR_FINISHED; +} + +static int uv_select_similar_face_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + const eUVSelectSimilar type = RNA_enum_get(op->ptr, "type"); + const float threshold = RNA_float_get(op->ptr, "threshold"); + const eSimilarCmp compare = RNA_enum_get(op->ptr, "compare"); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + int max_faces_selected_all = 0; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(ob); + max_faces_selected_all += em->bm->totfacesel; + /* TODO: Get a tighter bounds */ + } + + int tree_index = 0; + KDTree_1d *tree_1d = BLI_kdtree_1d_new(max_faces_selected_all); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em->bm; + + float ob_m3[3][3]; + copy_m3_m4(ob_m3, ob->obmat); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + if (!uvedit_face_select_test(scene, face, cd_loop_uv_offset)) { + continue; + } + + float needle = get_uv_face_needle(type, face, ob_m3, cd_loop_uv_offset); + if (tree_1d) { + BLI_kdtree_1d_insert(tree_1d, tree_index++, &needle); + } + } + } + + if (tree_1d != NULL) { + BLI_kdtree_1d_deduplicate(tree_1d); + BLI_kdtree_1d_balance(tree_1d); + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em->bm; + bool changed = false; + bool do_history = false; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + + float ob_m3[3][3]; + copy_m3_m4(ob_m3, ob->obmat); + + BMFace *face; + BMIter iter; + BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, face)) { + continue; + } + if (uvedit_face_select_test(scene, face, cd_loop_uv_offset)) { + continue; + } + + float needle = get_uv_face_needle(type, face, ob_m3, cd_loop_uv_offset); + + bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare); + if (select) { + uvedit_face_select_set(scene, em, face, select, do_history, cd_loop_uv_offset); + changed = true; + } + } + if (changed) { + uv_select_tag_update_for_object(depsgraph, ts, ob); + } + } + + MEM_SAFE_FREE(objects); + BLI_kdtree_1d_free(tree_1d); + return OPERATOR_FINISHED; +} + +/* Select similar UV faces/edges/verts based on current selection. */ +static int uv_select_similar_exec(bContext *C, wmOperator *op) +{ + ToolSettings *ts = CTX_data_tool_settings(C); + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "threshold"); + + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_float_set(op->ptr, prop, ts->select_thresh); + } + else { + ts->select_thresh = RNA_property_float_get(op->ptr, prop); + } + + int selectmode = (ts->uv_flag & UV_SYNC_SELECTION) ? ts->selectmode : ts->uv_selectmode; + if (selectmode & UV_SELECT_EDGE) { + return uv_select_similar_edge_exec(C, op); + } + else if (selectmode & UV_SELECT_FACE) { + return uv_select_similar_face_exec(C, op); + } + if (selectmode & UV_SELECT_ISLAND) { + // return uv_select_similar_island_exec(C, op); + } + + return uv_select_similar_vert_exec(C, op); +} + +static EnumPropertyItem prop_vert_similar_types[] = {{UV_SSIM_PIN, "PIN", 0, "Pinned", ""}, {0}}; + +static EnumPropertyItem prop_edge_similar_types[] = { + {UV_SSIM_LENGTH_UV, "LENGTH", 0, "Length", ""}, + {UV_SSIM_LENGTH_3D, "LENGTH_3D", 0, "Length 3D", ""}, + {UV_SSIM_PIN, "PIN", 0, "Pinned", ""}, + {0}}; + +static EnumPropertyItem prop_face_similar_types[] = { + {UV_SSIM_AREA_UV, "AREA", 0, "Area", ""}, + {UV_SSIM_AREA_3D, "AREA_3D", 0, "Area 3D", ""}, + {UV_SSIM_SIDES, "SIDES", 0, "Polygon Sides", ""}, + {UV_SSIM_MATERIAL, "MATERIAL", 0, "Material", ""}, + {0}}; + +static EnumPropertyItem prop_similar_compare_types[] = {{SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, + {SIM_CMP_GT, "GREATER", 0, "Greater", ""}, + {SIM_CMP_LT, "LESS", 0, "Less", ""}, + {0}}; + +static const EnumPropertyItem *uv_select_similar_type_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *UNUSED(r_free)) +{ + const ToolSettings *ts = CTX_data_tool_settings(C); + if (ts) { + int selectmode = (ts->uv_flag & UV_SYNC_SELECTION) ? ts->selectmode : ts->uv_selectmode; + if (selectmode & UV_SELECT_EDGE) { + return prop_edge_similar_types; + } + if (selectmode & UV_SELECT_FACE) { + return prop_face_similar_types; + } + } + + return prop_vert_similar_types; +} +void UV_OT_select_similar(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Similar"; + ot->description = "Select similar UVs by property types"; + ot->idname = "UV_OT_select_similar"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = uv_select_similar_exec; + ot->poll = ED_operator_uvedit_space_image; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop = ot->prop = RNA_def_enum( + ot->srna, "type", prop_vert_similar_types, SIMVERT_NORMAL, "Type", ""); + RNA_def_enum_funcs(prop, uv_select_similar_type_itemf); + RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", ""); + RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f); +} + +/** \} */ /* -------------------------------------------------------------------- */ /** \name Selected Elements as Arrays (Vertex, Edge & Faces) diff --git a/source/blender/functions/FN_multi_function_procedure.hh b/source/blender/functions/FN_multi_function_procedure.hh index 75a54992a48..da269b08155 100644 --- a/source/blender/functions/FN_multi_function_procedure.hh +++ b/source/blender/functions/FN_multi_function_procedure.hh @@ -87,7 +87,7 @@ class MFVariable : NonCopyable, NonMovable { MFDataType data_type_; Vector<MFInstruction *> users_; std::string name_; - int id_; + int index_in_graph_; friend MFProcedure; friend MFCallInstruction; @@ -101,7 +101,7 @@ class MFVariable : NonCopyable, NonMovable { StringRefNull name() const; void set_name(std::string name); - int id() const; + int index_in_procedure() const; }; /** Base class for all instruction types. */ @@ -376,9 +376,9 @@ inline StringRefNull MFVariable::name() const return name_; } -inline int MFVariable::id() const +inline int MFVariable::index_in_procedure() const { - return id_; + return index_in_graph_; } /** \} */ diff --git a/source/blender/functions/intern/multi_function_procedure.cc b/source/blender/functions/intern/multi_function_procedure.cc index bc045bfd44b..7ad324a9574 100644 --- a/source/blender/functions/intern/multi_function_procedure.cc +++ b/source/blender/functions/intern/multi_function_procedure.cc @@ -173,7 +173,7 @@ MFVariable &MFProcedure::new_variable(MFDataType data_type, std::string name) MFVariable &variable = *allocator_.construct<MFVariable>().release(); variable.name_ = std::move(name); variable.data_type_ = data_type; - variable.id_ = variables_.size(); + variable.index_in_graph_ = variables_.size(); variables_.append(&variable); return variable; } @@ -753,7 +753,7 @@ class MFProcedureDotExport { ss << "null"; } else { - ss << "$" << variable->id(); + ss << "$" << variable->index_in_procedure(); if (!variable->name().is_empty()) { ss << "(" << variable->name() << ")"; } diff --git a/source/blender/functions/intern/multi_function_procedure_executor.cc b/source/blender/functions/intern/multi_function_procedure_executor.cc index d852fe19924..a45240dad55 100644 --- a/source/blender/functions/intern/multi_function_procedure_executor.cc +++ b/source/blender/functions/intern/multi_function_procedure_executor.cc @@ -157,10 +157,6 @@ class ValueAllocator : NonCopyable, NonMovable { { } - template<typename... Args> VariableState *obtain_variable_state(Args &&...args); - - void release_variable_state(VariableState *state); - VariableValue_GVArray *obtain_GVArray(const GVArray &varray) { return this->obtain<VariableValue_GVArray>(varray); @@ -294,32 +290,27 @@ class ValueAllocator : NonCopyable, NonMovable { * This class keeps track of a single variable during evaluation. */ class VariableState : NonCopyable, NonMovable { - private: + public: /** The current value of the variable. The storage format may change over time. */ - VariableValue *value_; + VariableValue *value_ = nullptr; /** Number of indices that are currently initialized in this variable. */ - int tot_initialized_; + int tot_initialized_ = 0; /* This a non-owning pointer to either span buffer or #GVectorArray or null. */ void *caller_provided_storage_ = nullptr; - public: - VariableState(VariableValue &value, int tot_initialized, void *caller_provided_storage = nullptr) - : value_(&value), - tot_initialized_(tot_initialized), - caller_provided_storage_(caller_provided_storage) - { - } - - void destruct_self(ValueAllocator &value_allocator, const MFDataType &data_type) + void destruct_value(ValueAllocator &value_allocator, const MFDataType &data_type) { value_allocator.release_value(value_, data_type); - value_allocator.release_variable_state(this); + value_ = nullptr; } /* True if this contains only one value for all indices, i.e. the value for all indices is * the same. */ bool is_one() const { + if (value_ == nullptr) { + return true; + } switch (value_->type) { case ValueType::GVArray: return this->value_as<VariableValue_GVArray>()->data.is_single(); @@ -353,6 +344,7 @@ class VariableState : NonCopyable, NonMovable { { /* Sanity check to make sure that enough values are initialized. */ BLI_assert(mask.size() <= tot_initialized_); + BLI_assert(value_ != nullptr); switch (value_->type) { case ValueType::GVArray: { @@ -391,7 +383,7 @@ class VariableState : NonCopyable, NonMovable { const MFDataType &data_type, ValueAllocator &value_allocator) { - if (ELEM(value_->type, ValueType::Span, ValueType::GVectorArray)) { + if (value_ != nullptr && ELEM(value_->type, ValueType::Span, ValueType::GVectorArray)) { return; } @@ -408,22 +400,24 @@ class VariableState : NonCopyable, NonMovable { /* Reuse the storage provided caller when possible. */ new_value = value_allocator.obtain_Span_not_owned(caller_provided_storage_); } - if (value_->type == ValueType::GVArray) { - /* Fill new buffer with data from virtual array. */ - this->value_as<VariableValue_GVArray>()->data.materialize_to_uninitialized( - full_mask, new_value->data); - } - else if (value_->type == ValueType::OneSingle) { - auto *old_value_typed_ = this->value_as<VariableValue_OneSingle>(); - if (old_value_typed_->is_initialized) { - /* Fill the buffer with a single value. */ - type.fill_construct_indices(old_value_typed_->data, new_value->data, full_mask); + if (value_ != nullptr) { + if (value_->type == ValueType::GVArray) { + /* Fill new buffer with data from virtual array. */ + this->value_as<VariableValue_GVArray>()->data.materialize_to_uninitialized( + full_mask, new_value->data); } + else if (value_->type == ValueType::OneSingle) { + auto *old_value_typed_ = this->value_as<VariableValue_OneSingle>(); + if (old_value_typed_->is_initialized) { + /* Fill the buffer with a single value. */ + type.fill_construct_indices(old_value_typed_->data, new_value->data, full_mask); + } + } + else { + BLI_assert_unreachable(); + } + value_allocator.release_value(value_, data_type); } - else { - BLI_assert_unreachable(); - } - value_allocator.release_value(value_, data_type); value_ = new_value; break; } @@ -437,19 +431,21 @@ class VariableState : NonCopyable, NonMovable { new_value = value_allocator.obtain_GVectorArray_not_owned( *(GVectorArray *)caller_provided_storage_); } - if (value_->type == ValueType::GVVectorArray) { - /* Fill new vector array with data from virtual vector array. */ - new_value->data.extend(full_mask, this->value_as<VariableValue_GVVectorArray>()->data); - } - else if (value_->type == ValueType::OneVector) { - /* Fill all indices with the same value. */ - const GSpan vector = this->value_as<VariableValue_OneVector>()->data[0]; - new_value->data.extend(full_mask, GVVectorArray_For_SingleGSpan{vector, array_size}); - } - else { - BLI_assert_unreachable(); + if (value_ != nullptr) { + if (value_->type == ValueType::GVVectorArray) { + /* Fill new vector array with data from virtual vector array. */ + new_value->data.extend(full_mask, this->value_as<VariableValue_GVVectorArray>()->data); + } + else if (value_->type == ValueType::OneVector) { + /* Fill all indices with the same value. */ + const GSpan vector = this->value_as<VariableValue_OneVector>()->data[0]; + new_value->data.extend(full_mask, GVVectorArray_For_SingleGSpan{vector, array_size}); + } + else { + BLI_assert_unreachable(); + } + value_allocator.release_value(value_, data_type); } - value_allocator.release_value(value_, data_type); value_ = new_value; break; } @@ -466,6 +462,7 @@ class VariableState : NonCopyable, NonMovable { BLI_assert(mask.size() <= tot_initialized_); this->ensure_is_mutable(full_mask, data_type, value_allocator); + BLI_assert(value_ != nullptr); switch (value_->type) { case ValueType::Span: { @@ -497,6 +494,7 @@ class VariableState : NonCopyable, NonMovable { /* Sanity check to make sure that enough values are not initialized. */ BLI_assert(mask.size() <= full_mask.size() - tot_initialized_); this->ensure_is_mutable(full_mask, data_type, value_allocator); + BLI_assert(value_ != nullptr); switch (value_->type) { case ValueType::Span: { @@ -524,6 +522,7 @@ class VariableState : NonCopyable, NonMovable { void add_as_input__one(MFParamsBuilder ¶ms, const MFDataType &data_type) const { BLI_assert(this->is_one()); + BLI_assert(value_ != nullptr); switch (value_->type) { case ValueType::GVArray: { @@ -556,7 +555,7 @@ class VariableState : NonCopyable, NonMovable { void ensure_is_mutable__one(const MFDataType &data_type, ValueAllocator &value_allocator) { BLI_assert(this->is_one()); - if (ELEM(value_->type, ValueType::OneSingle, ValueType::OneVector)) { + if (value_ != nullptr && ELEM(value_->type, ValueType::OneSingle, ValueType::OneVector)) { return; } @@ -564,38 +563,42 @@ class VariableState : NonCopyable, NonMovable { case MFDataType::Single: { const CPPType &type = data_type.single_type(); VariableValue_OneSingle *new_value = value_allocator.obtain_OneSingle(type); - if (value_->type == ValueType::GVArray) { - this->value_as<VariableValue_GVArray>()->data.get_internal_single_to_uninitialized( - new_value->data); - new_value->is_initialized = true; - } - else if (value_->type == ValueType::Span) { - BLI_assert(tot_initialized_ == 0); - /* Nothing to do, the single value is uninitialized already. */ - } - else { - BLI_assert_unreachable(); + if (value_ != nullptr) { + if (value_->type == ValueType::GVArray) { + this->value_as<VariableValue_GVArray>()->data.get_internal_single_to_uninitialized( + new_value->data); + new_value->is_initialized = true; + } + else if (value_->type == ValueType::Span) { + BLI_assert(tot_initialized_ == 0); + /* Nothing to do, the single value is uninitialized already. */ + } + else { + BLI_assert_unreachable(); + } + value_allocator.release_value(value_, data_type); } - value_allocator.release_value(value_, data_type); value_ = new_value; break; } case MFDataType::Vector: { const CPPType &type = data_type.vector_base_type(); VariableValue_OneVector *new_value = value_allocator.obtain_OneVector(type); - if (value_->type == ValueType::GVVectorArray) { - const GVVectorArray &old_vector_array = - this->value_as<VariableValue_GVVectorArray>()->data; - new_value->data.extend(IndexRange(1), old_vector_array); - } - else if (value_->type == ValueType::GVectorArray) { - BLI_assert(tot_initialized_ == 0); - /* Nothing to do. */ - } - else { - BLI_assert_unreachable(); + if (value_ != nullptr) { + if (value_->type == ValueType::GVVectorArray) { + const GVVectorArray &old_vector_array = + this->value_as<VariableValue_GVVectorArray>()->data; + new_value->data.extend(IndexRange(1), old_vector_array); + } + else if (value_->type == ValueType::GVectorArray) { + BLI_assert(tot_initialized_ == 0); + /* Nothing to do. */ + } + else { + BLI_assert_unreachable(); + } + value_allocator.release_value(value_, data_type); } - value_allocator.release_value(value_, data_type); value_ = new_value; break; } @@ -608,6 +611,7 @@ class VariableState : NonCopyable, NonMovable { { BLI_assert(this->is_one()); this->ensure_is_mutable__one(data_type, value_allocator); + BLI_assert(value_ != nullptr); switch (value_->type) { case ValueType::OneSingle: { @@ -637,6 +641,7 @@ class VariableState : NonCopyable, NonMovable { { BLI_assert(this->is_one()); this->ensure_is_mutable__one(data_type, value_allocator); + BLI_assert(value_ != nullptr); switch (value_->type) { case ValueType::OneSingle: { @@ -676,6 +681,7 @@ class VariableState : NonCopyable, NonMovable { const MFDataType &data_type, ValueAllocator &value_allocator) { + BLI_assert(value_ != nullptr); int new_tot_initialized = tot_initialized_ - mask.size(); /* Sanity check to make sure that enough indices can be destructed. */ @@ -743,6 +749,7 @@ class VariableState : NonCopyable, NonMovable { void indices_split(IndexMask mask, IndicesSplitVectors &r_indices) { BLI_assert(mask.size() <= tot_initialized_); + BLI_assert(value_ != nullptr); switch (value_->type) { case ValueType::GVArray: { @@ -778,51 +785,47 @@ class VariableState : NonCopyable, NonMovable { template<typename T> T *value_as() { + BLI_assert(value_ != nullptr); BLI_assert(value_->type == T::static_type); return static_cast<T *>(value_); } template<typename T> const T *value_as() const { + BLI_assert(value_ != nullptr); BLI_assert(value_->type == T::static_type); return static_cast<T *>(value_); } }; -template<typename... Args> VariableState *ValueAllocator::obtain_variable_state(Args &&...args) -{ - if (variable_state_free_list_.is_empty()) { - void *buffer = linear_allocator_.allocate(sizeof(VariableState), alignof(VariableState)); - return new (buffer) VariableState(std::forward<Args>(args)...); - } - return new (variable_state_free_list_.pop()) VariableState(std::forward<Args>(args)...); -} - -void ValueAllocator::release_variable_state(VariableState *state) -{ - state->~VariableState(); - variable_state_free_list_.push(state); -} - /** Keeps track of the states of all variables during evaluation. */ class VariableStates { private: ValueAllocator value_allocator_; - Map<const MFVariable *, VariableState *> variable_states_; + const MFProcedure &procedure_; + /** The state of every variable, indexed by #MFVariable::index_in_procedure(). */ + Array<VariableState> variable_states_; IndexMask full_mask_; public: - VariableStates(LinearAllocator<> &linear_allocator, IndexMask full_mask) - : value_allocator_(linear_allocator), full_mask_(full_mask) + VariableStates(LinearAllocator<> &linear_allocator, + const MFProcedure &procedure, + IndexMask full_mask) + : value_allocator_(linear_allocator), + procedure_(procedure), + variable_states_(procedure.variables().size()), + full_mask_(full_mask) { } ~VariableStates() { - for (auto &&item : variable_states_.items()) { - const MFVariable *variable = item.key; - VariableState *state = item.value; - state->destruct_self(value_allocator_, variable->data_type()); + for (const int variable_i : procedure_.variables().index_range()) { + VariableState &state = variable_states_[variable_i]; + if (state.value_ != nullptr) { + const MFVariable *variable = procedure_.variables()[variable_i]; + state.destruct_value(value_allocator_, variable->data_type()); + } } } @@ -848,9 +851,12 @@ class VariableStates { bool input_is_initialized, void *caller_provided_storage = nullptr) { const int tot_initialized = input_is_initialized ? full_mask_.size() : 0; - variable_states_.add_new(variable, - value_allocator_.obtain_variable_state( - *value, tot_initialized, caller_provided_storage)); + const int variable_i = variable->index_in_procedure(); + VariableState &variable_state = variable_states_[variable_i]; + BLI_assert(variable_state.value_ == nullptr); + variable_state.value_ = value; + variable_state.tot_initialized_ = tot_initialized; + variable_state.caller_provided_storage_ = caller_provided_storage; }; switch (param_type.category()) { @@ -936,32 +942,15 @@ class VariableStates { { VariableState &variable_state = this->get_variable_state(variable); if (variable_state.destruct(mask, full_mask_, variable.data_type(), value_allocator_)) { - variable_state.destruct_self(value_allocator_, variable.data_type()); - variable_states_.remove_contained(&variable); + variable_state.destruct_value(value_allocator_, variable.data_type()); } } VariableState &get_variable_state(const MFVariable &variable) { - return *variable_states_.lookup_or_add_cb( - &variable, [&]() { return this->create_new_state_for_variable(variable); }); - } - - VariableState *create_new_state_for_variable(const MFVariable &variable) - { - MFDataType data_type = variable.data_type(); - switch (data_type.category()) { - case MFDataType::Single: { - const CPPType &type = data_type.single_type(); - return value_allocator_.obtain_variable_state(*value_allocator_.obtain_OneSingle(type), 0); - } - case MFDataType::Vector: { - const CPPType &type = data_type.vector_base_type(); - return value_allocator_.obtain_variable_state(*value_allocator_.obtain_OneVector(type), 0); - } - } - BLI_assert_unreachable(); - return nullptr; + const int variable_i = variable.index_in_procedure(); + VariableState &variable_state = variable_states_[variable_i]; + return variable_state; } }; @@ -977,49 +966,82 @@ static bool evaluate_as_one(const MultiFunction &fn, return false; } for (VariableState *state : param_variable_states) { - if (state != nullptr && !state->is_one()) { + if (state != nullptr && state->value_ != nullptr && !state->is_one()) { return false; } } return true; } -static void execute_call_instruction(const MFCallInstruction &instruction, - IndexMask mask, - VariableStates &variable_states, - const MFContext &context) +static void gather_parameter_variable_states(const MultiFunction &fn, + const MFCallInstruction &instruction, + VariableStates &variable_states, + MutableSpan<VariableState *> r_param_variable_states) { - const MultiFunction &fn = instruction.fn(); - - Vector<VariableState *> param_variable_states; - param_variable_states.resize(fn.param_amount()); - for (const int param_index : fn.param_indices()) { const MFVariable *variable = instruction.params()[param_index]; if (variable == nullptr) { - param_variable_states[param_index] = nullptr; + r_param_variable_states[param_index] = nullptr; } else { VariableState &variable_state = variable_states.get_variable_state(*variable); - param_variable_states[param_index] = &variable_state; + r_param_variable_states[param_index] = &variable_state; + } + } +} + +static void fill_params__one(const MultiFunction &fn, + const IndexMask mask, + MFParamsBuilder ¶ms, + VariableStates &variable_states, + const Span<VariableState *> param_variable_states) +{ + for (const int param_index : fn.param_indices()) { + const MFParamType param_type = fn.param_type(param_index); + VariableState *variable_state = param_variable_states[param_index]; + if (variable_state == nullptr) { + params.add_ignored_single_output(); + } + else { + variable_states.add_as_param__one(*variable_state, params, param_type, mask); } } +} + +static void fill_params(const MultiFunction &fn, + const IndexMask mask, + MFParamsBuilder ¶ms, + VariableStates &variable_states, + const Span<VariableState *> param_variable_states) +{ + for (const int param_index : fn.param_indices()) { + const MFParamType param_type = fn.param_type(param_index); + VariableState *variable_state = param_variable_states[param_index]; + if (variable_state == nullptr) { + params.add_ignored_single_output(); + } + else { + variable_states.add_as_param(*variable_state, params, param_type, mask); + } + } +} + +static void execute_call_instruction(const MFCallInstruction &instruction, + const IndexMask mask, + VariableStates &variable_states, + const MFContext &context) +{ + const MultiFunction &fn = instruction.fn(); + + Vector<VariableState *> param_variable_states; + param_variable_states.resize(fn.param_amount()); + gather_parameter_variable_states(fn, instruction, variable_states, param_variable_states); /* If all inputs to the function are constant, it's enough to call the function only once instead * of for every index. */ if (evaluate_as_one(fn, param_variable_states, mask, variable_states.full_mask())) { MFParamsBuilder params(fn, 1); - - for (const int param_index : fn.param_indices()) { - const MFParamType param_type = fn.param_type(param_index); - VariableState *variable_state = param_variable_states[param_index]; - if (variable_state == nullptr) { - params.add_ignored_single_output(); - } - else { - variable_states.add_as_param__one(*variable_state, params, param_type, mask); - } - } + fill_params__one(fn, mask, params, variable_states, param_variable_states); try { fn.call(IndexRange(1), params, context); @@ -1031,17 +1053,7 @@ static void execute_call_instruction(const MFCallInstruction &instruction, } else { MFParamsBuilder params(fn, &mask); - - for (const int param_index : fn.param_indices()) { - const MFParamType param_type = fn.param_type(param_index); - VariableState *variable_state = param_variable_states[param_index]; - if (variable_state == nullptr) { - params.add_ignored_single_output(); - } - else { - variable_states.add_as_param(*variable_state, params, param_type, mask); - } - } + fill_params(fn, mask, params, variable_states, param_variable_states); try { fn.call_auto(mask, params, context); @@ -1090,7 +1102,7 @@ struct NextInstructionInfo { */ class InstructionScheduler { private: - Map<const MFInstruction *, Vector<InstructionIndices>> indices_by_instruction_; + Stack<NextInstructionInfo> next_instructions_; public: InstructionScheduler() = default; @@ -1103,7 +1115,7 @@ class InstructionScheduler { InstructionIndices new_indices; new_indices.is_owned = false; new_indices.referenced_indices = mask; - indices_by_instruction_.lookup_or_add_default(&instruction).append(std::move(new_indices)); + next_instructions_.push({&instruction, std::move(new_indices)}); } void add_owned_indices(const MFInstruction &instruction, Vector<int64_t> indices) @@ -1116,43 +1128,28 @@ class InstructionScheduler { InstructionIndices new_indices; new_indices.is_owned = true; new_indices.owned_indices = std::move(indices); - indices_by_instruction_.lookup_or_add_default(&instruction).append(std::move(new_indices)); + next_instructions_.push({&instruction, std::move(new_indices)}); } - void add_previous_instruction_indices(const MFInstruction &instruction, - NextInstructionInfo &instr_info) + bool is_done() const { - indices_by_instruction_.lookup_or_add_default(&instruction) - .append(std::move(instr_info.indices)); + return next_instructions_.is_empty(); } - NextInstructionInfo pop_next() + const NextInstructionInfo &peek() const { - if (indices_by_instruction_.is_empty()) { - return {}; - } - /* TODO: Implement better mechanism to determine next instruction. */ - const MFInstruction *instruction = *indices_by_instruction_.keys().begin(); + BLI_assert(!this->is_done()); + return next_instructions_.peek(); + } - NextInstructionInfo next_instruction_info; - next_instruction_info.instruction = instruction; - next_instruction_info.indices = this->pop_indices_array(instruction); - return next_instruction_info; + void update_instruction_pointer(const MFInstruction &instruction) + { + next_instructions_.peek().instruction = &instruction; } - private: - InstructionIndices pop_indices_array(const MFInstruction *instruction) + NextInstructionInfo pop() { - Vector<InstructionIndices> *indices = indices_by_instruction_.lookup_ptr(instruction); - if (indices == nullptr) { - return {}; - } - InstructionIndices r_indices = (*indices).pop_last(); - BLI_assert(!r_indices.mask().is_empty()); - if (indices->is_empty()) { - indices_by_instruction_.remove_contained(instruction); - } - return r_indices; + return next_instructions_.pop(); } }; @@ -1160,23 +1157,26 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c { BLI_assert(procedure_.validate()); + AlignedBuffer<512, 64> local_buffer; LinearAllocator<> linear_allocator; + linear_allocator.provide_buffer(local_buffer); - VariableStates variable_states{linear_allocator, full_mask}; + VariableStates variable_states{linear_allocator, procedure_, full_mask}; variable_states.add_initial_variable_states(*this, procedure_, params); InstructionScheduler scheduler; scheduler.add_referenced_indices(*procedure_.entry(), full_mask); /* Loop until all indices got to a return instruction. */ - while (NextInstructionInfo instr_info = scheduler.pop_next()) { + while (!scheduler.is_done()) { + const NextInstructionInfo &instr_info = scheduler.peek(); const MFInstruction &instruction = *instr_info.instruction; switch (instruction.type()) { case MFInstructionType::Call: { const MFCallInstruction &call_instruction = static_cast<const MFCallInstruction &>( instruction); execute_call_instruction(call_instruction, instr_info.mask(), variable_states, context); - scheduler.add_previous_instruction_indices(*call_instruction.next(), instr_info); + scheduler.update_instruction_pointer(*call_instruction.next()); break; } case MFInstructionType::Branch: { @@ -1187,6 +1187,7 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c IndicesSplitVectors new_indices; variable_state.indices_split(instr_info.mask(), new_indices); + scheduler.pop(); scheduler.add_owned_indices(*branch_instruction.branch_false(), new_indices[false]); scheduler.add_owned_indices(*branch_instruction.branch_true(), new_indices[true]); break; @@ -1196,17 +1197,18 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c static_cast<const MFDestructInstruction &>(instruction); const MFVariable *variable = destruct_instruction.variable(); variable_states.destruct(*variable, instr_info.mask()); - scheduler.add_previous_instruction_indices(*destruct_instruction.next(), instr_info); + scheduler.update_instruction_pointer(*destruct_instruction.next()); break; } case MFInstructionType::Dummy: { const MFDummyInstruction &dummy_instruction = static_cast<const MFDummyInstruction &>( instruction); - scheduler.add_previous_instruction_indices(*dummy_instruction.next(), instr_info); + scheduler.update_instruction_pointer(*dummy_instruction.next()); break; } case MFInstructionType::Return: { /* Don't insert the indices back into the scheduler. */ + scheduler.pop(); break; } } diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index 1916c5f91f3..531487a45e2 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -15,6 +15,7 @@ set(INC ) set(SRC + intern/add_curves_on_mesh.cc intern/mesh_merge_by_distance.cc intern/mesh_primitive_cuboid.cc intern/mesh_to_curve_convert.cc @@ -24,6 +25,7 @@ set(SRC intern/reverse_uv_sampler.cc intern/uv_parametrizer.c + GEO_add_curves_on_mesh.hh GEO_mesh_merge_by_distance.hh GEO_mesh_primitive_cuboid.hh GEO_mesh_to_curve.hh diff --git a/source/blender/geometry/GEO_add_curves_on_mesh.hh b/source/blender/geometry/GEO_add_curves_on_mesh.hh new file mode 100644 index 00000000000..cf60a8e8ace --- /dev/null +++ b/source/blender/geometry/GEO_add_curves_on_mesh.hh @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BLI_float4x4.hh" +#include "BLI_kdtree.h" +#include "BLI_math_vector.hh" +#include "BLI_span.hh" + +#include "BKE_bvhutils.h" +#include "BKE_curves.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +namespace blender::geometry { + +struct AddCurvesOnMeshInputs { + /** Information about the root points where new curves should be generated. */ + Span<float3> root_positions_cu; + Span<float3> bary_coords; + Span<int> looptri_indices; + + /** Determines shape of new curves. */ + bool interpolate_length = false; + bool interpolate_shape = false; + bool interpolate_point_count = false; + float fallback_curve_length = 0.0f; + int fallback_point_count = 0; + + /** Information about the surface that the new curves are attached to. */ + const Mesh *surface = nullptr; + BVHTreeFromMesh *surface_bvh = nullptr; + Span<MLoopTri> surface_looptris; + Span<float2> surface_uv_map; + Span<float3> corner_normals_su; + + /** Transformation matrices. */ + float4x4 curves_to_surface_mat; + float4x4 surface_to_curves_normal_mat; + + /** + * KD-Tree that contains the root points of existing curves. This is only necessary when + * interpolation is used. + */ + KDTree_3d *old_roots_kdtree = nullptr; +}; + +/** + * Generate new curves on a mesh surface with the given inputs. Existing curves stay intact. + */ +void add_curves_on_mesh(bke::CurvesGeometry &curves, const AddCurvesOnMeshInputs &inputs); + +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/add_curves_on_mesh.cc b/source/blender/geometry/intern/add_curves_on_mesh.cc new file mode 100644 index 00000000000..34551bd474f --- /dev/null +++ b/source/blender/geometry/intern/add_curves_on_mesh.cc @@ -0,0 +1,354 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_mesh_sample.hh" +#include "BKE_spline.hh" + +#include "GEO_add_curves_on_mesh.hh" + +/** + * The code below uses a suffix naming convention to indicate the coordinate space: + * cu: Local space of the curves object that is being edited. + * su: Local space of the surface object. + */ + +namespace blender::geometry { + +using bke::CurvesGeometry; + +struct NeighborCurve { + /* Curve index of the neighbor. */ + int index; + /* The weights of all neighbors of a new curve add up to 1. */ + float weight; +}; + +static constexpr int max_neighbors = 5; +using NeighborCurves = Vector<NeighborCurve, max_neighbors>; + +static float3 compute_surface_point_normal(const MLoopTri &looptri, + const float3 &bary_coord, + const Span<float3> corner_normals) +{ + const int l0 = looptri.tri[0]; + const int l1 = looptri.tri[1]; + const int l2 = looptri.tri[2]; + + const float3 &l0_normal = corner_normals[l0]; + const float3 &l1_normal = corner_normals[l1]; + const float3 &l2_normal = corner_normals[l2]; + + const float3 normal = math::normalize( + attribute_math::mix3(bary_coord, l0_normal, l1_normal, l2_normal)); + return normal; +} + +static void initialize_straight_curve_positions(const float3 &p1, + const float3 &p2, + MutableSpan<float3> r_positions) +{ + const float step = 1.0f / (float)(r_positions.size() - 1); + for (const int i : r_positions.index_range()) { + r_positions[i] = math::interpolate(p1, p2, i * step); + } +} + +static Array<NeighborCurves> find_curve_neighbors(const Span<float3> root_positions, + const KDTree_3d &old_roots_kdtree) +{ + const int tot_added_curves = root_positions.size(); + Array<NeighborCurves> neighbors_per_curve(tot_added_curves); + threading::parallel_for(IndexRange(tot_added_curves), 128, [&](const IndexRange range) { + for (const int i : range) { + const float3 root = root_positions[i]; + std::array<KDTreeNearest_3d, max_neighbors> nearest_n; + const int found_neighbors = BLI_kdtree_3d_find_nearest_n( + &old_roots_kdtree, root, nearest_n.data(), max_neighbors); + float tot_weight = 0.0f; + for (const int neighbor_i : IndexRange(found_neighbors)) { + KDTreeNearest_3d &nearest = nearest_n[neighbor_i]; + const float weight = 1.0f / std::max(nearest.dist, 0.00001f); + tot_weight += weight; + neighbors_per_curve[i].append({nearest.index, weight}); + } + /* Normalize weights. */ + for (NeighborCurve &neighbor : neighbors_per_curve[i]) { + neighbor.weight /= tot_weight; + } + } + }); + return neighbors_per_curve; +} + +template<typename T, typename GetValueF> +void interpolate_from_neighbors(const Span<NeighborCurves> neighbors_per_curve, + const T &fallback, + const GetValueF &get_value_from_neighbor, + MutableSpan<T> r_interpolated_values) +{ + attribute_math::DefaultMixer<T> mixer{r_interpolated_values}; + threading::parallel_for(r_interpolated_values.index_range(), 512, [&](const IndexRange range) { + for (const int i : range) { + const NeighborCurves &neighbors = neighbors_per_curve[i]; + if (neighbors.is_empty()) { + mixer.mix_in(i, fallback, 1.0f); + } + else { + for (const NeighborCurve &neighbor : neighbors) { + const T neighbor_value = get_value_from_neighbor(neighbor.index); + mixer.mix_in(i, neighbor_value, neighbor.weight); + } + } + } + }); + mixer.finalize(); +} + +static void interpolate_position_without_interpolation( + CurvesGeometry &curves, + const int old_curves_num, + const Span<float3> root_positions_cu, + const Span<float> new_lengths_cu, + const Span<float3> new_normals_su, + const float4x4 &surface_to_curves_normal_mat) +{ + const int added_curves_num = root_positions_cu.size(); + MutableSpan<float3> positions_cu = curves.positions_for_write(); + threading::parallel_for(IndexRange(added_curves_num), 256, [&](const IndexRange range) { + for (const int i : range) { + const int curve_i = old_curves_num + i; + const IndexRange points = curves.points_for_curve(curve_i); + const float3 &root_cu = root_positions_cu[i]; + const float length = new_lengths_cu[i]; + const float3 &normal_su = new_normals_su[i]; + const float3 normal_cu = math::normalize(surface_to_curves_normal_mat * normal_su); + const float3 tip_cu = root_cu + length * normal_cu; + + initialize_straight_curve_positions(root_cu, tip_cu, positions_cu.slice(points)); + } + }); +} + +static void interpolate_position_with_interpolation(CurvesGeometry &curves, + const Span<float3> root_positions_cu, + const Span<NeighborCurves> neighbors_per_curve, + const int old_curves_num, + const Span<float> new_lengths_cu, + const Span<float3> new_normals_su, + const float4x4 &surface_to_curves_normal_mat, + const float4x4 &curves_to_surface_mat, + const BVHTreeFromMesh &surface_bvh, + const Span<MLoopTri> surface_looptris, + const Mesh &surface, + const Span<float3> corner_normals_su) +{ + MutableSpan<float3> positions_cu = curves.positions_for_write(); + const int added_curves_num = root_positions_cu.size(); + + threading::parallel_for(IndexRange(added_curves_num), 256, [&](const IndexRange range) { + for (const int i : range) { + const NeighborCurves &neighbors = neighbors_per_curve[i]; + const int curve_i = old_curves_num + i; + const IndexRange points = curves.points_for_curve(curve_i); + + const float length_cu = new_lengths_cu[i]; + const float3 &normal_su = new_normals_su[i]; + const float3 normal_cu = math::normalize(surface_to_curves_normal_mat * normal_su); + + const float3 &root_cu = root_positions_cu[i]; + + if (neighbors.is_empty()) { + /* If there are no neighbors, just make a straight line. */ + const float3 tip_cu = root_cu + length_cu * normal_cu; + initialize_straight_curve_positions(root_cu, tip_cu, positions_cu.slice(points)); + continue; + } + + positions_cu.slice(points).fill(root_cu); + + for (const NeighborCurve &neighbor : neighbors) { + const int neighbor_curve_i = neighbor.index; + const float3 &neighbor_first_pos_cu = positions_cu[curves.offsets()[neighbor_curve_i]]; + const float3 neighbor_first_pos_su = curves_to_surface_mat * neighbor_first_pos_cu; + + BVHTreeNearest nearest; + nearest.dist_sq = FLT_MAX; + BLI_bvhtree_find_nearest(surface_bvh.tree, + neighbor_first_pos_su, + &nearest, + surface_bvh.nearest_callback, + const_cast<BVHTreeFromMesh *>(&surface_bvh)); + const int neighbor_looptri_index = nearest.index; + const MLoopTri &neighbor_looptri = surface_looptris[neighbor_looptri_index]; + + const float3 neighbor_bary_coord = + bke::mesh_surface_sample::compute_bary_coord_in_triangle( + surface, neighbor_looptri, nearest.co); + + const float3 neighbor_normal_su = compute_surface_point_normal( + surface_looptris[neighbor_looptri_index], neighbor_bary_coord, corner_normals_su); + const float3 neighbor_normal_cu = math::normalize(surface_to_curves_normal_mat * + neighbor_normal_su); + + /* The rotation matrix used to transform relative coordinates of the neighbor curve + * to the new curve. */ + float normal_rotation_cu[3][3]; + rotation_between_vecs_to_mat3(normal_rotation_cu, neighbor_normal_cu, normal_cu); + + const IndexRange neighbor_points = curves.points_for_curve(neighbor_curve_i); + const float3 &neighbor_root_cu = positions_cu[neighbor_points[0]]; + + /* Use a temporary #PolySpline, because that's the easiest way to resample an + * existing curve right now. Resampling is necessary if the length of the new curve + * does not match the length of the neighbors or the number of handle points is + * different. */ + PolySpline neighbor_spline; + neighbor_spline.resize(neighbor_points.size()); + neighbor_spline.positions().copy_from(positions_cu.slice(neighbor_points)); + neighbor_spline.mark_cache_invalid(); + + const float neighbor_length_cu = neighbor_spline.length(); + const float length_factor = std::min(1.0f, length_cu / neighbor_length_cu); + + const float resample_factor = (1.0f / (points.size() - 1.0f)) * length_factor; + for (const int j : IndexRange(points.size())) { + const Spline::LookupResult lookup = neighbor_spline.lookup_evaluated_factor( + j * resample_factor); + const float index_factor = lookup.evaluated_index + lookup.factor; + float3 p; + neighbor_spline.sample_with_index_factors<float3>( + neighbor_spline.positions(), {&index_factor, 1}, {&p, 1}); + const float3 relative_coord = p - neighbor_root_cu; + float3 rotated_relative_coord = relative_coord; + mul_m3_v3(normal_rotation_cu, rotated_relative_coord); + positions_cu[points[j]] += neighbor.weight * rotated_relative_coord; + } + } + } + }); +} + +void add_curves_on_mesh(CurvesGeometry &curves, const AddCurvesOnMeshInputs &inputs) +{ + const bool use_interpolation = inputs.interpolate_length || inputs.interpolate_point_count || + inputs.interpolate_shape; + + Array<NeighborCurves> neighbors_per_curve; + if (use_interpolation) { + BLI_assert(inputs.old_roots_kdtree != nullptr); + neighbors_per_curve = find_curve_neighbors(inputs.root_positions_cu, *inputs.old_roots_kdtree); + } + + const int added_curves_num = inputs.root_positions_cu.size(); + const int old_points_num = curves.points_num(); + const int old_curves_num = curves.curves_num(); + const int new_curves_num = old_curves_num + added_curves_num; + + /* Grow number of curves first, so that the offsets array can be filled. */ + curves.resize(old_points_num, new_curves_num); + + /* Compute new curve offsets. */ + MutableSpan<int> curve_offsets = curves.offsets_for_write(); + MutableSpan<int> new_point_counts_per_curve = curve_offsets.take_back(added_curves_num); + if (inputs.interpolate_point_count) { + interpolate_from_neighbors<int>( + neighbors_per_curve, + inputs.fallback_point_count, + [&](const int curve_i) { return curves.points_for_curve(curve_i).size(); }, + new_point_counts_per_curve); + } + else { + new_point_counts_per_curve.fill(inputs.fallback_point_count); + } + for (const int i : IndexRange(added_curves_num)) { + curve_offsets[old_curves_num + i + 1] += curve_offsets[old_curves_num + i]; + } + + const int new_points_num = curves.offsets().last(); + curves.resize(new_points_num, new_curves_num); + MutableSpan<float3> positions_cu = curves.positions_for_write(); + + /* Determine length of new curves. */ + Array<float> new_lengths_cu(added_curves_num); + if (inputs.interpolate_length) { + interpolate_from_neighbors<float>( + neighbors_per_curve, + inputs.fallback_curve_length, + [&](const int curve_i) { + const IndexRange points = curves.points_for_curve(curve_i); + float length = 0.0f; + for (const int segment_i : points.drop_back(1)) { + const float3 &p1 = positions_cu[segment_i]; + const float3 &p2 = positions_cu[segment_i + 1]; + length += math::distance(p1, p2); + } + return length; + }, + new_lengths_cu); + } + else { + new_lengths_cu.fill(inputs.fallback_curve_length); + } + + /* Find surface normal at root points. */ + Array<float3> new_normals_su(added_curves_num); + threading::parallel_for(IndexRange(added_curves_num), 256, [&](const IndexRange range) { + for (const int i : range) { + const int looptri_index = inputs.looptri_indices[i]; + const float3 &bary_coord = inputs.bary_coords[i]; + new_normals_su[i] = compute_surface_point_normal( + inputs.surface_looptris[looptri_index], bary_coord, inputs.corner_normals_su); + } + }); + + /* Propagate attachment information. */ + if (!inputs.surface_uv_map.is_empty()) { + MutableSpan<float2> surface_uv_coords = curves.surface_uv_coords_for_write(); + bke::mesh_surface_sample::sample_corner_attribute( + *inputs.surface, + inputs.looptri_indices, + inputs.bary_coords, + GVArray::ForSpan(inputs.surface_uv_map), + IndexRange(added_curves_num), + surface_uv_coords.take_back(added_curves_num)); + } + + /* Update selection arrays when available. */ + const VArray<float> points_selection = curves.selection_point_float(); + if (points_selection.is_span()) { + MutableSpan<float> points_selection_span = curves.selection_point_float_for_write(); + points_selection_span.drop_front(old_points_num).fill(1.0f); + } + const VArray<float> curves_selection = curves.selection_curve_float(); + if (curves_selection.is_span()) { + MutableSpan<float> curves_selection_span = curves.selection_curve_float_for_write(); + curves_selection_span.drop_front(old_curves_num).fill(1.0f); + } + + /* Initialize position attribute. */ + if (inputs.interpolate_shape) { + interpolate_position_with_interpolation(curves, + inputs.root_positions_cu, + neighbors_per_curve, + old_curves_num, + new_lengths_cu, + new_normals_su, + inputs.surface_to_curves_normal_mat, + inputs.curves_to_surface_mat, + *inputs.surface_bvh, + inputs.surface_looptris, + *inputs.surface, + inputs.corner_normals_su); + } + else { + interpolate_position_without_interpolation(curves, + old_curves_num, + inputs.root_positions_cu, + new_lengths_cu, + new_normals_su, + inputs.surface_to_curves_normal_mat); + } + + curves.update_curve_types(); +} + +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 4db4256ec8f..bd4099d37f9 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -134,6 +134,12 @@ struct RealizeCurveInfo { * doesn't exist on some (but not all) of the input curves data-blocks. */ Span<float> radius; + + /** + * The resolution attribute must be filled with the default value if it does not exist on some + * curves. + */ + VArray<int> resolution; }; /** Start indices in the final output curves data-block. */ @@ -185,6 +191,7 @@ struct AllCurvesInfo { bool create_id_attribute = false; bool create_handle_postion_attributes = false; bool create_radius_attribute = false; + bool create_resolution_attribute = false; }; /** Collects all tasks that need to be executed to realize all instances. */ @@ -1037,6 +1044,7 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate( src_component_types, GEO_COMPONENT_TYPE_CURVE, true, attributes_to_propagate); attributes_to_propagate.remove("position"); attributes_to_propagate.remove("radius"); + attributes_to_propagate.remove("resolution"); attributes_to_propagate.remove("handle_right"); attributes_to_propagate.remove("handle_left"); r_create_id = attributes_to_propagate.pop_try("id").has_value(); @@ -1075,12 +1083,13 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set, info.realize_info.reinitialize(info.order.size()); for (const int curve_index : info.realize_info.index_range()) { RealizeCurveInfo &curve_info = info.realize_info[curve_index]; - const Curves *curves = info.order[curve_index]; - curve_info.curves = curves; + const Curves *curves_id = info.order[curve_index]; + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry); + curve_info.curves = curves_id; /* Access attributes. */ CurveComponent component; - component.replace(const_cast<Curves *>(curves), GeometryOwnershipType::ReadOnly); + component.replace(const_cast<Curves *>(curves_id), GeometryOwnershipType::ReadOnly); curve_info.attributes.reinitialize(info.attributes.size()); for (const int attribute_index : info.attributes.index_range()) { const eAttrDomain domain = info.attributes.kinds[attribute_index].domain; @@ -1106,6 +1115,12 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set, info.create_radius_attribute = true; } + /* Retrieve the resolution attribute, if it exists. */ + curve_info.resolution = curves.resolution(); + if (component.attribute_exists("resolution")) { + info.create_resolution_attribute = true; + } + /* Retrieve handle position attributes, if they exist. */ if (component.attribute_exists("handle_right")) { curve_info.handle_left = component @@ -1131,7 +1146,8 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options, MutableSpan<int> all_dst_ids, MutableSpan<float3> all_handle_left, MutableSpan<float3> all_handle_right, - MutableSpan<float> all_radii) + MutableSpan<float> all_radii, + MutableSpan<int> all_resolutions) { const RealizeCurveInfo &curves_info = *task.curve_info; const Curves &curves_id = *curves_info.curves; @@ -1171,6 +1187,10 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options, } } + if (all_curves_info.create_resolution_attribute) { + curves_info.resolution.materialize(all_resolutions.slice(dst_curve_range)); + } + /* Copy curve offsets. */ const Span<int> src_offsets = curves.offsets(); const MutableSpan<int> dst_offsets = dst_curves.offsets_for_write().slice(dst_curve_range); @@ -1268,6 +1288,15 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, radius_span = radius.as_span(); } + /* Prepare resolution attribute if necessary. */ + OutputAttribute_Typed<int> resolution; + MutableSpan<int> resolution_span; + if (all_curves_info.create_resolution_attribute) { + resolution = dst_component.attribute_try_get_for_output_only<int>("resolution", + ATTR_DOMAIN_CURVE); + resolution_span = resolution.as_span(); + } + /* Actually execute all tasks. */ threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) { for (const int task_index : task_range) { @@ -1281,7 +1310,8 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, point_ids_span, handle_left_span, handle_right_span, - radius_span); + radius_span, + resolution_span); } }); @@ -1295,6 +1325,9 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options, if (radius) { radius.save(); } + if (resolution) { + resolution.save(); + } if (all_curves_info.create_handle_postion_attributes) { handle_left.save(); handle_right.save(); diff --git a/source/blender/geometry/intern/uv_parametrizer.c b/source/blender/geometry/intern/uv_parametrizer.c index 46ebe6cfdce..8863b9192ca 100644 --- a/source/blender/geometry/intern/uv_parametrizer.c +++ b/source/blender/geometry/intern/uv_parametrizer.c @@ -4,27 +4,18 @@ * \ingroup eduv */ +#include "GEO_uv_parametrizer.h" + #include "MEM_guardedalloc.h" #include "BLI_boxpack_2d.h" #include "BLI_convexhull_2d.h" #include "BLI_ghash.h" #include "BLI_heap.h" -#include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_polyfill_2d.h" #include "BLI_polyfill_2d_beautify.h" #include "BLI_rand.h" -#include "BLI_utildefines.h" - -#include "GEO_uv_parametrizer.h" - -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "BLI_sys_types.h" /* for intptr_t support */ #include "eigen_capi.h" @@ -52,11 +43,6 @@ typedef struct PHash { int size, cursize, cursize_id; } PHash; -struct PChart; -struct PEdge; -struct PFace; -struct PVert; - /* Simplices */ typedef struct PVert { @@ -318,54 +304,14 @@ static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link) /* Geometry */ -static float p_vec_angle_cos(const float v1[3], const float v2[3], const float v3[3]) -{ - float d1[3], d2[3]; - - d1[0] = v1[0] - v2[0]; - d1[1] = v1[1] - v2[1]; - d1[2] = v1[2] - v2[2]; - - d2[0] = v3[0] - v2[0]; - d2[1] = v3[1] - v2[1]; - d2[2] = v3[2] - v2[2]; - - normalize_v3(d1); - normalize_v3(d2); - - return d1[0] * d2[0] + d1[1] * d2[1] + d1[2] * d2[2]; -} - static float p_vec_angle(const float v1[3], const float v2[3], const float v3[3]) { - float dot = p_vec_angle_cos(v1, v2, v3); - - if (dot <= -1.0f) { - return (float)M_PI; - } - if (dot >= 1.0f) { - return 0.0f; - } - return acosf(dot); + return angle_v3v3v3(v1, v2, v3); } - static float p_vec2_angle(const float v1[2], const float v2[2], const float v3[2]) { - float u1[3], u2[3], u3[3]; - - u1[0] = v1[0]; - u1[1] = v1[1]; - u1[2] = 0.0f; - u2[0] = v2[0]; - u2[1] = v2[1]; - u2[2] = 0.0f; - u3[0] = v3[0]; - u3[1] = v3[1]; - u3[2] = 0.0f; - - return p_vec_angle(u1, u2, u3); + return angle_v2v2v2(v1, v2, v3); } - static void p_triangle_angles( const float v1[3], const float v2[3], const float v3[3], float *r_a1, float *r_a2, float *r_a3) { @@ -406,25 +352,12 @@ static float p_face_uv_area_signed(PFace *f) static float p_edge_length(PEdge *e) { - PVert *v1 = e->vert, *v2 = e->next->vert; - float d[3]; - - d[0] = v2->co[0] - v1->co[0]; - d[1] = v2->co[1] - v1->co[1]; - d[2] = v2->co[2] - v1->co[2]; - - return sqrtf(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + return len_v3v3(e->vert->co, e->next->vert->co); } static float p_edge_uv_length(PEdge *e) { - PVert *v1 = e->vert, *v2 = e->next->vert; - float d[3]; - - d[0] = v2->uv[0] - v1->uv[0]; - d[1] = v2->uv[1] - v1->uv[1]; - - return sqrtf(d[0] * d[0] + d[1] * d[1]); + return len_v2v2(e->vert->uv, e->next->vert->uv); } static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2]) @@ -498,16 +431,6 @@ static void p_chart_uv_to_array(PChart *chart, float (*points)[2]) } } -static void UNUSED_FUNCTION(p_chart_uv_from_array)(PChart *chart, float (*points)[2]) -{ - PVert *v; - uint i = 0; - - for (v = chart->verts; v; v = v->nextlink) { - copy_v2_v2(v->uv, points[i++]); - } -} - static bool p_intersect_line_2d_dir(const float v1[2], const float dir1[2], const float v2[2], diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c index f179713e8cb..8d77fb50c71 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillineart.c @@ -324,6 +324,10 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemPointerR( row, ptr, "target_material", &obj_data_ptr, "materials", NULL, ICON_SHADING_TEXTURE); + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "thickness", UI_ITEM_R_SLIDER, IFACE_("Line Thickness"), ICON_NONE); + uiItemR(col, ptr, "opacity", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + gpencil_modifier_panel_end(layout, ptr); } @@ -398,21 +402,6 @@ static void options_panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(col, ptr, "use_back_face_culling", 0, IFACE_("Force Backface Culling"), ICON_NONE); } -static void style_panel_draw(const bContext *UNUSED(C), Panel *panel) -{ - uiLayout *layout = panel->layout; - PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); - - const bool is_baked = RNA_boolean_get(ptr, "is_baked"); - - uiLayoutSetPropSep(layout, true); - uiLayoutSetEnabled(layout, !is_baked); - - uiItemR(layout, ptr, "thickness", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - - uiItemR(layout, ptr, "opacity", UI_ITEM_R_SLIDER, NULL, ICON_NONE); -} - static void occlusion_panel_draw(const bContext *UNUSED(C), Panel *panel) { uiLayout *layout = panel->layout; @@ -708,8 +697,6 @@ static void panelRegister(ARegionType *region_type) region_type, "edge_types", "Edge Types", NULL, edge_types_panel_draw, panel_type); gpencil_modifier_subpanel_register( region_type, "geometry", "Geometry Processing", NULL, options_panel_draw, panel_type); - gpencil_modifier_subpanel_register( - region_type, "style", "Style", NULL, style_panel_draw, panel_type); PanelType *occlusion_panel = gpencil_modifier_subpanel_register( region_type, "occlusion", "Occlusion", NULL, occlusion_panel_draw, panel_type); gpencil_modifier_subpanel_register(region_type, diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index c6eaf7defdc..b7dad589395 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -177,7 +177,7 @@ void GPU_render_step() /** \name Backend selection * \{ */ -static GPUBackend *g_backend; +static GPUBackend *g_backend = nullptr; bool GPU_backend_supported(eGPUBackendType type) { diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 808a8ccd955..5d6651c3e3a 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -669,7 +669,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUNodeGraph.used_libraries"); mat->refcount = 1; #ifndef NDEBUG - BLI_snprintf(mat->name, sizeof(mat->name), "%s", name); + STRNCPY(mat->name, name); #else UNUSED_VARS(name); #endif diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index d78dc845074..c300c0da3b2 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -702,7 +702,11 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *r_size) void GPU_samplers_update() { - GPUBackend::get()->samplers_update(); + /* Backend may not exist when we are updating preferences from background mode. */ + GPUBackend *backend = GPUBackend::get(); + if (backend) { + backend->samplers_update(); + } } /** \} */ diff --git a/source/blender/gpu/metal/mtl_texture.hh b/source/blender/gpu/metal/mtl_texture.hh index b820256ec36..b4b1e91c496 100644 --- a/source/blender/gpu/metal/mtl_texture.hh +++ b/source/blender/gpu/metal/mtl_texture.hh @@ -349,7 +349,7 @@ class MTLTexture : public Texture { * - Per-component size matches (e.g. GPU_DATA_UBYTE) * OR GPU_DATA_10_11_11_REV && GPU_R11G11B10 (equiv) * OR D24S8 and GPU_DATA_UINT_24_8 - * We can Use BLIT ENCODER. + * We can use BLIT ENCODER. * * OTHERWISE TRIGGER COMPUTE: * - Compute sizes will vary. Threads per grid WILL match 'extent'. diff --git a/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh index 6840dfe25de..396ee64454c 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh @@ -37,7 +37,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color) GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_clipped) .do_static_compilation(true) - /* TODO(fclem): Put in an UBO to fit the 128byte requirement. */ + /* TODO(fclem): Put in a UBO to fit the 128byte requirement. */ .push_constant(Type::MAT4, "ModelMatrix") .push_constant(Type::VEC4, "ClipPlane") .define("CLIP") diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl index 530907859e9..c95a41c58fc 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl @@ -34,6 +34,13 @@ void node_eevee_specular(vec4 diffuse, diffuse_data.N = N; diffuse_data.sss_id = 0u; + /* WORKAROUND: Nasty workaround to the current interface with the closure evaluation. + * Ideally the occlusion input should be move to the output node or removed all-together. + * This is temporary to avoid a regression in 3.2 and should be removed after EEVEE-Next rewrite. + */ + diffuse_data.sss_radius.r = occlusion; + diffuse_data.sss_radius.g = -1.0; /* Flag */ + ClosureReflection reflection_data; reflection_data.weight = alpha; if (true) { @@ -41,7 +48,7 @@ void node_eevee_specular(vec4 diffuse, vec2 split_sum = brdf_lut(NV, roughness); vec3 brdf = F_brdf_single_scatter(specular.rgb, vec3(1.0), split_sum); - reflection_data.color = specular.rgb * brdf; + reflection_data.color = brdf; reflection_data.N = N; reflection_data.roughness = roughness; } diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c index 52756891f21..2a0baaf6172 100644 --- a/source/blender/imbuf/intern/stereoimbuf.c +++ b/source/blender/imbuf/intern/stereoimbuf.c @@ -702,21 +702,21 @@ int *IMB_stereo3d_from_rect(const ImageFormatData *im_format, int *rect_left, int *rect_right) { - int *r_rect; + int *rect_result; Stereo3DData s3d_data = {{NULL}}; size_t width, height; const bool is_float = im_format->depth > 8; IMB_stereo3d_write_dimensions( im_format->stereo3d_format.display_mode, false, x, y, &width, &height); - r_rect = MEM_mallocN(channels * sizeof(int) * width * height, __func__); + rect_result = MEM_mallocN(channels * sizeof(int) * width * height, __func__); imb_stereo3d_data_init( - &s3d_data, is_float, x, y, channels, rect_left, rect_right, r_rect, NULL, NULL, NULL); + &s3d_data, is_float, x, y, channels, rect_left, rect_right, rect_result, NULL, NULL, NULL); imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); - imb_stereo3d_squeeze_rect(r_rect, &im_format->stereo3d_format, x, y, channels); + imb_stereo3d_squeeze_rect(rect_result, &im_format->stereo3d_format, x, y, channels); - return r_rect; + return rect_result; } float *IMB_stereo3d_from_rectf(const ImageFormatData *im_format, @@ -726,21 +726,30 @@ float *IMB_stereo3d_from_rectf(const ImageFormatData *im_format, float *rectf_left, float *rectf_right) { - float *r_rectf; + float *rectf_result; Stereo3DData s3d_data = {{NULL}}; size_t width, height; const bool is_float = im_format->depth > 8; IMB_stereo3d_write_dimensions( im_format->stereo3d_format.display_mode, false, x, y, &width, &height); - r_rectf = MEM_mallocN(channels * sizeof(float) * width * height, __func__); + rectf_result = MEM_mallocN(channels * sizeof(float) * width * height, __func__); - imb_stereo3d_data_init( - &s3d_data, is_float, x, y, channels, NULL, NULL, NULL, rectf_left, rectf_right, r_rectf); + imb_stereo3d_data_init(&s3d_data, + is_float, + x, + y, + channels, + NULL, + NULL, + NULL, + rectf_left, + rectf_right, + rectf_result); imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); - imb_stereo3d_squeeze_rectf(r_rectf, &im_format->stereo3d_format, x, y, channels); + imb_stereo3d_squeeze_rectf(rectf_result, &im_format->stereo3d_format, x, y, channels); - return r_rectf; + return rectf_result; } ImBuf *IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right) diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index 0d4e1d04db0..1fb535a57f2 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -573,12 +573,10 @@ static void import_endjob(void *user_data) ImportJobData *data = static_cast<ImportJobData *>(user_data); - std::vector<AbcObjectReader *>::iterator iter; - /* Delete objects on cancellation. */ if (data->was_cancelled) { - for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { - Object *ob = (*iter)->object(); + for (AbcObjectReader *reader : data->readers) { + Object *ob = reader->object(); /* It's possible that cancellation occurred between the creation of * the reader and the creation of the Blender object. */ @@ -590,7 +588,6 @@ static void import_endjob(void *user_data) } } else { - /* Add object to scene. */ Base *base; LayerCollection *lc; ViewLayer *view_layer = data->view_layer; @@ -599,11 +596,17 @@ static void import_endjob(void *user_data) lc = BKE_layer_collection_get_active(view_layer); - for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { - Object *ob = (*iter)->object(); - + /* Add all objects to the collection (don't do sync for each object). */ + BKE_layer_collection_resync_forbid(); + for (AbcObjectReader *reader : data->readers) { + Object *ob = reader->object(); BKE_collection_object_add(data->bmain, lc->collection, ob); - + } + /* Sync the collection, and do view layer operations. */ + BKE_layer_collection_resync_allow(); + BKE_main_collection_sync(data->bmain); + for (AbcObjectReader *reader : data->readers) { + Object *ob = reader->object(); base = BKE_view_layer_base_find(view_layer, ob); /* TODO: is setting active needed? */ BKE_view_layer_base_select_and_set_active(view_layer, base); @@ -625,8 +628,7 @@ static void import_endjob(void *user_data) } } - for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { - AbcObjectReader *reader = *iter; + for (AbcObjectReader *reader : data->readers) { reader->decref(); if (reader->refcount() == 0) { diff --git a/source/blender/io/stl/importer/stl_import_mesh.cc b/source/blender/io/stl/importer/stl_import_mesh.cc index 7de8239b233..b9ed441f0d9 100644 --- a/source/blender/io/stl/importer/stl_import_mesh.cc +++ b/source/blender/io/stl/importer/stl_import_mesh.cc @@ -63,11 +63,11 @@ void STLMeshHelper::add_triangle(const float3 &a, Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name) { if (degenerate_tris_num_ > 0) { - std::cout << "STL Importer: " << degenerate_tris_num_ << "degenerate triangles were removed" + std::cout << "STL Importer: " << degenerate_tris_num_ << " degenerate triangles were removed" << std::endl; } if (duplicate_tris_num_ > 0) { - std::cout << "STL Importer: " << duplicate_tris_num_ << "duplicate triangles were removed" + std::cout << "STL Importer: " << duplicate_tris_num_ << " duplicate triangles were removed" << std::endl; } diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc index 29b256125f0..4118205d87f 100644 --- a/source/blender/io/usd/intern/usd_capi_import.cc +++ b/source/blender/io/usd/intern/usd_capi_import.cc @@ -277,7 +277,6 @@ static void import_endjob(void *customdata) } } else if (data->archive) { - /* Add object to scene. */ Base *base; LayerCollection *lc; ViewLayer *view_layer = data->view_layer; @@ -286,20 +285,30 @@ static void import_endjob(void *customdata) lc = BKE_layer_collection_get_active(view_layer); + /* Add all objects to the collection (don't do sync for each object). */ + BKE_layer_collection_resync_forbid(); for (USDPrimReader *reader : data->archive->readers()) { - if (!reader) { continue; } - Object *ob = reader->object(); - if (!ob) { continue; } - BKE_collection_object_add(data->bmain, lc->collection, ob); + } + /* Sync the collection, and do view layer operations. */ + BKE_layer_collection_resync_allow(); + BKE_main_collection_sync(data->bmain); + for (USDPrimReader *reader : data->archive->readers()) { + if (!reader) { + continue; + } + Object *ob = reader->object(); + if (!ob) { + continue; + } base = BKE_view_layer_base_find(view_layer, ob); /* TODO: is setting active needed? */ BKE_view_layer_base_select_and_set_active(view_layer, base); diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 368d0e1bab9..36e1a40953c 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -111,6 +111,7 @@ static void assign_materials(Main *bmain, const std::map<pxr::SdfPath, int> &mat_index_map, const USDImportParams ¶ms, pxr::UsdStageRefPtr stage, + std::map<std::string, Material *> &mat_name_to_mat, std::map<std::string, std::string> &usd_path_to_mat_name) { if (!(stage && bmain && ob)) { @@ -132,16 +133,12 @@ static void assign_materials(Main *bmain, return; } - /* TODO(kevin): use global map? */ - std::map<std::string, Material *> mat_map; - build_mat_map(bmain, &mat_map); - blender::io::usd::USDMaterialReader mat_reader(params, bmain); for (it = mat_index_map.begin(); it != mat_index_map.end(); ++it) { Material *assigned_mat = find_existing_material( - it->first, params, mat_map, usd_path_to_mat_name); + it->first, params, mat_name_to_mat, usd_path_to_mat_name); if (!assigned_mat) { /* Blender material doesn't exist, so create it now. */ @@ -165,7 +162,7 @@ static void assign_materials(Main *bmain, } const std::string mat_name = pxr::TfMakeValidIdentifier(assigned_mat->id.name + 2); - mat_map[mat_name] = assigned_mat; + mat_name_to_mat[mat_name] = assigned_mat; if (params.mtl_name_collision_mode == USD_MTL_NAME_COLLISION_MAKE_UNIQUE) { /* Record the name of the Blender material we created for the USD material @@ -805,11 +802,16 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot std::map<pxr::SdfPath, int> mat_map; assign_facesets_to_mpoly(motionSampleTime, mesh->mpoly, mesh->totpoly, &mat_map); + /* Build material name map if it's not built yet. */ + if (this->settings_->mat_name_to_mat.empty()) { + utils::build_mat_map(bmain, &this->settings_->mat_name_to_mat); + } utils::assign_materials(bmain, object_, mat_map, this->import_params_, this->prim_.GetStage(), + this->settings_->mat_name_to_mat, this->settings_->usd_path_to_mat_name); } diff --git a/source/blender/io/usd/intern/usd_reader_prim.h b/source/blender/io/usd/intern/usd_reader_prim.h index f2df00accf6..c44c4a14ad7 100644 --- a/source/blender/io/usd/intern/usd_reader_prim.h +++ b/source/blender/io/usd/intern/usd_reader_prim.h @@ -11,6 +11,7 @@ #include <string> struct Main; +struct Material; struct Object; namespace blender::io::usd { @@ -42,6 +43,10 @@ struct ImportSettings { * of what the importer is doing. This is necessary even * when all the other import settings are to remain const. */ mutable std::map<std::string, std::string> usd_path_to_mat_name; + /* Map a material name to Blender material. + * This map is updated by readers during stage traversal, + * and is mutable similar to the map above. */ + mutable std::map<std::string, Material *> mat_name_to_mat; ImportSettings() : do_convert_mat(false), diff --git a/source/blender/io/wavefront_obj/IO_wavefront_obj.h b/source/blender/io/wavefront_obj/IO_wavefront_obj.h index a719dff2126..b4a00deb99c 100644 --- a/source/blender/io/wavefront_obj/IO_wavefront_obj.h +++ b/source/blender/io/wavefront_obj/IO_wavefront_obj.h @@ -72,6 +72,7 @@ struct OBJImportParams { float clamp_size; eIOAxis forward_axis; eIOAxis up_axis; + bool import_vertex_groups; bool validate_meshes; }; diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc index 9cfce5c2257..3cc17e7d8e6 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc @@ -6,6 +6,7 @@ #include "BLI_map.hh" #include "BLI_math_color.h" +#include "BLI_math_vector.h" #include "BLI_string_ref.hh" #include "BLI_vector.hh" @@ -78,7 +79,7 @@ static void geom_add_vertex(Geometry *geom, p = parse_floats(p, end, 0.0f, vert, 3); r_global_vertices.vertices.append(vert); geom->vertex_count_++; - /* OBJ extension: "xyzrgb" vertex colors, when the vertex position + /* OBJ extension: `xyzrgb` vertex colors, when the vertex position * is followed by 3 more RGB color components. See * http://paulbourke.net/dataformats/obj/colour.html */ if (p < end) { @@ -129,6 +130,10 @@ static void geom_add_vertex_normal(Geometry *geom, { float3 normal; parse_floats(p, end, 0.0f, normal, 3); + /* Normals can be printed with only several digits in the file, + * making them ever-so-slightly non unit length. Make sure they are + * normalized. */ + normalize_v3(normal); r_global_vertices.vertex_normals.append(normal); geom->has_vertex_normals_ = true; } @@ -170,7 +175,7 @@ static void geom_add_polygon(Geometry *geom, curr_face.material_index = material_index; if (group_index >= 0) { curr_face.vertex_group_index = group_index; - geom->use_vertex_groups_ = true; + geom->has_vertex_groups_ = true; } const int orig_corners_size = geom->face_corners_.size(); diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index acc35ad46e1..51318331c76 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -10,6 +10,7 @@ #include "BKE_attribute.h" #include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_node_tree_update.h" @@ -47,7 +48,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain, obj->data = BKE_object_obdata_add_from_type(bmain, OB_MESH, ob_name.c_str()); create_vertices(mesh); - create_polys_loops(obj, mesh); + create_polys_loops(obj, mesh, import_params.import_vertex_groups); create_edges(mesh); create_uv_verts(mesh); create_normals(mesh); @@ -69,6 +70,9 @@ Object *MeshFromGeometry::create_mesh(Main *bmain, BKE_mesh_nomain_to_mesh(mesh, dst, obj, &CD_MASK_EVERYTHING, true); dst->flag |= autosmooth; + /* Note: vertex groups have to be created after final mesh is assigned to the object. */ + create_vertex_groups(obj); + return obj; } @@ -163,19 +167,13 @@ void MeshFromGeometry::create_vertices(Mesh *mesh) } } -void MeshFromGeometry::create_polys_loops(Object *obj, Mesh *mesh) +void MeshFromGeometry::create_polys_loops(Object *obj, Mesh *mesh, bool use_vertex_groups) { - /* Will not be used if vertex groups are not imported. */ mesh->dvert = nullptr; - float weight = 0.0f; const int64_t total_verts = mesh_geometry_.vertex_count_; - if (total_verts && mesh_geometry_.use_vertex_groups_) { + if (use_vertex_groups && total_verts && mesh_geometry_.has_vertex_groups_) { mesh->dvert = static_cast<MDeformVert *>( CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, nullptr, total_verts)); - weight = 1.0f / total_verts; - } - else { - UNUSED_VARS(weight); } const int64_t tot_face_elems{mesh->totpoly}; @@ -208,28 +206,23 @@ void MeshFromGeometry::create_polys_loops(Object *obj, Mesh *mesh) tot_loop_idx++; mloop.v = curr_corner.vert_index; + /* Setup vertex group data, if needed. */ if (!mesh->dvert) { continue; } - /* Iterating over mloop results in finding the same vertex multiple times. - * Another way is to allocate memory for dvert while creating vertices and fill them here. - */ - MDeformVert &def_vert = mesh->dvert[mloop.v]; - if (!def_vert.dw) { - def_vert.dw = static_cast<MDeformWeight *>( - MEM_callocN(sizeof(MDeformWeight), "OBJ Import Deform Weight")); - } - /* Every vertex in a face is assigned the same deform group. */ - int group_idx = curr_face.vertex_group_index; - /* Deform group number (def_nr) must behave like an index into the names' list. */ - *(def_vert.dw) = {static_cast<unsigned int>(group_idx), weight}; + const int group_index = curr_face.vertex_group_index; + MDeformWeight *dw = BKE_defvert_ensure_index(mesh->dvert + mloop.v, group_index); + dw->weight = 1.0f; } } +} - if (!mesh->dvert) { +void MeshFromGeometry::create_vertex_groups(Object *obj) +{ + Mesh *mesh = static_cast<Mesh *>(obj->data); + if (mesh->dvert == nullptr) { return; } - /* Add deform group names. */ for (const std::string &name : mesh_geometry_.group_order_) { BKE_object_defgroup_add_name(obj, name.data()); } diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh b/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh index 216717f3578..c6773cfa0cb 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.hh @@ -45,10 +45,9 @@ class MeshFromGeometry : NonMovable, NonCopyable { void fixup_invalid_faces(); void create_vertices(Mesh *mesh); /** - * Create polygons for the Mesh, set smooth shading flags, deform group names, - * Materials. + * Create polygons for the Mesh, set smooth shading flags, Materials. */ - void create_polys_loops(Object *obj, Mesh *mesh); + void create_polys_loops(Object *obj, Mesh *mesh, bool use_vertex_groups); /** * Add explicitly imported OBJ edges to the mesh. */ @@ -66,6 +65,7 @@ class MeshFromGeometry : NonMovable, NonCopyable { Object *obj); void create_normals(Mesh *mesh); void create_colors(Mesh *mesh); + void create_vertex_groups(Object *obj); }; } // namespace blender::io::obj diff --git a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh index 69babc26bb0..3d6733d661e 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh @@ -113,7 +113,7 @@ struct Geometry { bool has_invalid_polys_ = false; bool has_vertex_normals_ = false; - bool use_vertex_groups_ = false; + bool has_vertex_groups_ = false; NurbsElement nurbs_element_; int total_loops_ = 0; }; diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index b67adbc9753..eeb81f5e23e 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -58,6 +58,8 @@ class obj_importer_test : public BlendfileLoadingBaseTest { params.clamp_size = 0; params.forward_axis = IO_AXIS_NEGATIVE_Z; params.up_axis = IO_AXIS_Y; + params.validate_meshes = true; + params.import_vertex_groups = false; std::string obj_path = blender::tests::flags_test_asset_dir() + "/io_tests/obj/" + path; strncpy(params.filepath, obj_path.c_str(), FILE_MAX - 1); diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 6557f35970d..8e0ce68f71a 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -105,8 +105,10 @@ typedef struct bConstraintTarget { /* bConstraintTarget -> flag */ typedef enum eConstraintTargetFlag { - /** temporary target-struct that needs to be freed after use */ + /** Temporary target-struct that needs to be freed after use. */ CONSTRAINT_TAR_TEMP = (1 << 0), + /** Temporary target for the custom space reference. */ + CONSTRAINT_TAR_CUSTOM_SPACE = (1 << 1), } eConstraintTargetFlag; /* bConstraintTarget/bConstraintOb -> type */ @@ -247,10 +249,9 @@ typedef struct bArmatureConstraint { typedef struct bTrackToConstraint { struct Object *tar; /** - * I'll be using reserved1 and reserved2 as Track and Up flags, + * NOTE(@theeth): I'll be using reserved1 and reserved2 as Track and Up flags, * not sure if that's what they were intended for anyway. * Not sure either if it would create backward incompatibility if I were to rename them. - * - theeth */ int reserved1; int reserved2; diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index 70ee7c99d01..ef35b72d2ab 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -338,7 +338,7 @@ typedef struct Ipo { #define CAM_STA 2 #define CAM_END 3 -/* yafray aperture & focal distance curves */ +/* YAFRAY aperture & focal distance curves. */ #define CAM_YF_APERT 4 #define CAM_YF_FDIST 5 diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h index 9202d7c2d51..f1bf0580b94 100644 --- a/source/blender/makesdna/DNA_light_types.h +++ b/source/blender/makesdna/DNA_light_types.h @@ -120,7 +120,7 @@ typedef struct Light { /* #define LA_NO_DIFF (1 << 11) */ /* not used anywhere */ /* #define LA_NO_SPEC (1 << 12) */ /* not used anywhere */ /* #define LA_SHAD_RAY (1 << 13) */ /* not used anywhere - cleaned */ -/* yafray: light shadowbuffer flag, softlight */ +/* YAFRAY: light shadow-buffer flag, soft-light. */ /* Since it is used with LOCAL light, can't use LA_SHAD */ /* #define LA_YF_SOFT (1 << 14) */ /* not used anymore */ /* #define LA_LAYER_SHADOW (1 << 15) */ /* not used anymore */ diff --git a/source/blender/makesdna/DNA_space_defaults.h b/source/blender/makesdna/DNA_space_defaults.h index e826cb4c2ef..66a09bc82c3 100644 --- a/source/blender/makesdna/DNA_space_defaults.h +++ b/source/blender/makesdna/DNA_space_defaults.h @@ -18,6 +18,7 @@ .draw_flag = 0, \ .draw_type = MASK_DT_OUTLINE, \ .overlay_mode = MASK_OVERLAY_ALPHACHANNEL, \ + .blend_factor = 0.7f, \ } #define _DNA_DEFAULT_SpaceClip \ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index be073ef2c15..2905ef06833 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -732,7 +732,8 @@ typedef struct MaskSpaceInfo { char draw_flag; char draw_type; char overlay_mode; - char _pad3[5]; + char _pad3[1]; + float blend_factor; } MaskSpaceInfo; /** #SpaceSeq.gizmo_flag */ diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index b725939dbab..e32d9dbe300 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -397,8 +397,7 @@ typedef struct ColorMapping { /* return value */ #define TEX_INT 0 -#define TEX_RGB (1 << 0) -#define TEX_NOR (1 << 1) +#define TEX_RGB 1 /* pr_texture in material, world, light. */ #define TEX_PR_TEXTURE 0 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index cfd0c986df9..f7aaa1186db 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -463,14 +463,19 @@ typedef struct wmKeyMap { /** #wmKeyMap.flag */ enum { - KEYMAP_MODAL = (1 << 0), /* modal map, not using operatornames */ - KEYMAP_USER = (1 << 1), /* user keymap */ + /** Modal map, not using operator-names. */ + KEYMAP_MODAL = (1 << 0), + /** User key-map. */ + KEYMAP_USER = (1 << 1), KEYMAP_EXPANDED = (1 << 2), KEYMAP_CHILDREN_EXPANDED = (1 << 3), - KEYMAP_DIFF = (1 << 4), /* diff keymap for user preferences */ - KEYMAP_USER_MODIFIED = (1 << 5), /* keymap has user modifications */ + /** Diff key-map for user preferences. */ + KEYMAP_DIFF = (1 << 4), + /** Key-map has user modifications. */ + KEYMAP_USER_MODIFIED = (1 << 5), KEYMAP_UPDATE = (1 << 6), - KEYMAP_TOOL = (1 << 7), /* keymap for active tool system */ + /** key-map for active tool system. */ + KEYMAP_TOOL = (1 << 7), }; /** diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 312c0753ce7..0bc35d86490 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -6108,7 +6108,7 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index) } if ((index == -1) || (RNA_property_array_check(prop) == false)) { - ret = BLI_sprintfN("%s", data_path); + ret = BLI_strdup(data_path); } else { ret = BLI_sprintfN("%s[%d]", data_path, index); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 8591d4abd63..4810784b3f7 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -4993,7 +4993,7 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), 0, "Object", "Use local generated coordinates of another object"}, - {MOD_DISP_MAP_UV, "UV", 0, "UV", "Use coordinates from an UV layer"}, + {MOD_DISP_MAP_UV, "UV", 0, "UV", "Use coordinates from a UV layer"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 4108baca2fa..30df8e20e8d 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -698,16 +698,18 @@ bool rna_PoseChannel_constraints_override_apply(Main *bmain, return true; } -static int rna_PoseChannel_proxy_editable(PointerRNA *ptr, const char **r_info) +static int rna_PoseChannel_proxy_editable(PointerRNA *UNUSED(ptr), const char **UNUSED(r_info)) { +# if 0 Object *ob = (Object *)ptr->owner_id; bArmature *arm = ob->data; bPoseChannel *pchan = (bPoseChannel *)ptr->data; - if (false && pchan->bone && (pchan->bone->layer & arm->layer_protected)) { + if (pchan->bone && (pchan->bone->layer & arm->layer_protected)) { *r_info = "Can't edit property of a proxy on a protected layer"; return 0; } +# endif return PROP_EDITABLE; } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index cae86801402..910e78e7a58 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -3493,6 +3493,13 @@ static void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *m RNA_def_property_enum_items(prop, overlay_mode_items); RNA_def_property_ui_text(prop, "Overlay Mode", "Overlay mode of rasterized mask"); RNA_def_property_update(prop, noteflag, NULL); + + prop = RNA_def_property(srna, "blend_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "mask_info.blend_factor"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0, 1., 0.1, 1); + RNA_def_property_ui_text(prop, "Blending Factor", "Overlay blending factor of rasterized mask"); + RNA_def_property_update(prop, noteflag, NULL); } static void rna_def_space_image_uv(BlenderRNA *brna) diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index 07504d91fea..5739de1c65c 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -447,7 +447,8 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, material_remaps, use_self, hole_tolerant, - bmd->operation); + bmd->operation, + nullptr); } #endif diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 149cf0c0cbb..1e2224e3a65 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -197,7 +197,6 @@ static void displaceModifier_do_task(void *__restrict userdata, } if (data->tex_target) { - texres.nor = NULL; BKE_texture_get_value_ex( data->scene, data->tex_target, tex_co[iter], &texres, data->pool, false); delta = texres.tin - dmd->midlevel; diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 402d7b2c99e..9693cf0c0f2 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -302,7 +302,6 @@ static void warpModifier_do(WarpModifierData *wmd, if (tex_co) { struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); TexResult texres; - texres.nor = NULL; BKE_texture_get_value(scene, tex_target, tex_co[i], &texres, false); fac *= texres.tin; } diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 73b26dc29cd..4073f028db5 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -262,7 +262,6 @@ static void waveModifier_do(WaveModifierData *md, if (tex_co) { Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); TexResult texres; - texres.nor = NULL; BKE_texture_get_value(scene, tex_target, tex_co[i], &texres, false); amplit *= texres.tin; } diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index 65393370268..3302384568b 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -162,7 +162,6 @@ void weightvg_do_mask(const ModifierEvalContext *ctx, do_color_manage = tex_use_channel != MOD_WVG_MASK_TEX_USE_INT; - texres.nor = NULL; BKE_texture_get_value(scene, texture, tex_co[idx], &texres, do_color_manage); /* Get the good channel value... */ switch (tex_use_channel) { diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index dc90073ec31..e4e4295fd3a 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -135,6 +135,7 @@ void register_node_type_geo_transform(void); void register_node_type_geo_translate_instances(void); void register_node_type_geo_triangulate(void); void register_node_type_geo_viewer(void); +void register_node_type_geo_volume_cube(void); void register_node_type_geo_volume_to_mesh(void); #ifdef __cplusplus diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 7ca013bf792..9793f133dd6 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -397,6 +397,7 @@ DefNode(GeometryNode, GEO_NODE_TRANSLATE_INSTANCES, 0, "TRANSLATE_INSTANCES", Tr DefNode(GeometryNode, GEO_NODE_TRIANGULATE, def_geo_triangulate, "TRIANGULATE", Triangulate, "Triangulate", "") DefNode(GeometryNode, GEO_NODE_TRIM_CURVE, def_geo_curve_trim, "TRIM_CURVE", TrimCurve, "Trim Curve", "") DefNode(GeometryNode, GEO_NODE_VIEWER, def_geo_viewer, "VIEWER", Viewer, "Viewer", "") +DefNode(GeometryNode, GEO_NODE_VOLUME_CUBE, 0, "VOLUME_CUBE", VolumeCube, "Volume Cube", "") DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "") /* undefine macros */ diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 54fda328ca8..015edf2d26c 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -144,6 +144,7 @@ set(SRC nodes/node_geo_translate_instances.cc nodes/node_geo_triangulate.cc nodes/node_geo_viewer.cc + nodes/node_geo_volume_cube.cc nodes/node_geo_volume_to_mesh.cc node_geometry_exec.cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index e485172d3e1..daeca311e08 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -20,6 +20,7 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_input<decl::Bool>(N_("Self Intersection")); b.add_input<decl::Bool>(N_("Hole Tolerant")); b.add_output<decl::Geometry>(N_("Mesh")); + b.add_output<decl::Bool>(N_("Intersecting Edges")).field_source(); } static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -27,6 +28,10 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); } +struct AttributeOutputs { + StrongAnonymousAttributeID intersecting_edges_id; +}; + static void node_update(bNodeTree *ntree, bNode *node) { GeometryNodeBooleanOperation operation = (GeometryNodeBooleanOperation)node->custom1; @@ -121,13 +126,21 @@ static void node_geo_exec(GeoNodeExecParams params) } } - Mesh *result = blender::meshintersect::direct_mesh_boolean(meshes, - transforms, - float4x4::identity(), - material_remaps, - use_self, - hole_tolerant, - operation); + AttributeOutputs attribute_outputs; + if (params.output_is_required("Intersecting Edges")) { + attribute_outputs.intersecting_edges_id = StrongAnonymousAttributeID("Intersecting Edges"); + } + + Vector<int> intersecting_edges; + Mesh *result = blender::meshintersect::direct_mesh_boolean( + meshes, + transforms, + float4x4::identity(), + material_remaps, + use_self, + hole_tolerant, + operation, + attribute_outputs.intersecting_edges_id ? &intersecting_edges : nullptr); if (!result) { params.set_default_remaining_outputs(); return; @@ -138,6 +151,26 @@ static void node_geo_exec(GeoNodeExecParams params) result->totcol = materials.size(); MutableSpan(result->mat, result->totcol).copy_from(materials); + /* Store intersecting edges in attribute. */ + if (attribute_outputs.intersecting_edges_id) { + MeshComponent mesh_component; + mesh_component.replace(result, GeometryOwnershipType::Editable); + OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>( + attribute_outputs.intersecting_edges_id.get(), ATTR_DOMAIN_EDGE); + MutableSpan<bool> selection = attribute.as_span(); + selection.fill(false); + for (const int i : intersecting_edges) { + selection[i] = true; + } + + attribute.save(); + + params.set_output( + "Intersecting Edges", + AnonymousAttributeFieldInput::Create<bool>( + std::move(attribute_outputs.intersecting_edges_id), params.attribute_producer_name())); + } + params.set_output("Mesh", GeometrySet::create_with_mesh(result)); #else params.error_message_add(NodeWarningType::Error, diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc new file mode 100644 index 00000000000..d7e9e38ea0d --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +# include <openvdb/tools/Dense.h> +# include <openvdb/tools/LevelSetUtil.h> +# include <openvdb/tools/ParticlesToLevelSet.h> +#endif + +#include "node_geometry_util.hh" + +#include "DNA_mesh_types.h" + +#include "BLI_task.hh" + +#include "BKE_geometry_set.hh" +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_volume.h" + +namespace blender::nodes::node_geo_volume_cube_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Float>(N_("Density")) + .description(N_("Volume density per voxel")) + .supports_field() + .default_value(1.0f); + b.add_input<decl::Float>(N_("Background")) + .description(N_("Value for voxels outside of the cube")); + + b.add_input<decl::Vector>(N_("Min")) + .description(N_("Minimum boundary of volume")) + .default_value(float3(-1.0f)); + b.add_input<decl::Vector>(N_("Max")) + .description(N_("Maximum boundary of volume")) + .default_value(float3(1.0f)); + + b.add_input<decl::Int>(N_("Resolution X")) + .description(N_("Number of voxels in the X axis")) + .default_value(32) + .min(2); + b.add_input<decl::Int>(N_("Resolution Y")) + .description(N_("Number of voxels in the Y axis")) + .default_value(32) + .min(2); + b.add_input<decl::Int>(N_("Resolution Z")) + .description(N_("Number of voxels in the Z axis")) + .default_value(32) + .min(2); + + b.add_output<decl::Geometry>(N_("Volume")); +} + +static float map(const float x, + const float in_min, + const float in_max, + const float out_min, + const float out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +class Grid3DFieldContext : public FieldContext { + private: + int3 resolution_; + float3 bounds_min_; + float3 bounds_max_; + + public: + Grid3DFieldContext(const int3 resolution, const float3 bounds_min, const float3 bounds_max) + : resolution_(resolution), bounds_min_(bounds_min), bounds_max_(bounds_max) + { + } + + int64_t points_num() const + { + return static_cast<int64_t>(resolution_.x) * static_cast<int64_t>(resolution_.y) * + static_cast<int64_t>(resolution_.z); + } + + GVArray get_varray_for_input(const FieldInput &field_input, + const IndexMask UNUSED(mask), + ResourceScope &UNUSED(scope)) const + { + const bke::AttributeFieldInput *attribute_field_input = + dynamic_cast<const bke::AttributeFieldInput *>(&field_input); + if (attribute_field_input == nullptr) { + return {}; + } + if (attribute_field_input->attribute_name() != "position") { + return {}; + } + + Array<float3> positions(this->points_num()); + + threading::parallel_for(IndexRange(resolution_.x), 1, [&](const IndexRange x_range) { + /* Start indexing at current X slice. */ + int64_t index = x_range.start() * resolution_.y * resolution_.z; + for (const int64_t x_i : x_range) { + const float x = map(x_i, 0.0f, resolution_.x - 1, bounds_min_.x, bounds_max_.x); + for (const int64_t y_i : IndexRange(resolution_.y)) { + const float y = map(y_i, 0.0f, resolution_.y - 1, bounds_min_.y, bounds_max_.y); + for (const int64_t z_i : IndexRange(resolution_.z)) { + const float z = map(z_i, 0.0f, resolution_.z - 1, bounds_min_.z, bounds_max_.z); + positions[index] = float3(x, y, z); + index++; + } + } + } + }); + return VArray<float3>::ForContainer(std::move(positions)); + } +}; + +#ifdef WITH_OPENVDB +static void node_geo_exec(GeoNodeExecParams params) +{ + const float3 bounds_min = params.extract_input<float3>("Min"); + const float3 bounds_max = params.extract_input<float3>("Max"); + + const int3 resolution = int3(params.extract_input<int>("Resolution X"), + params.extract_input<int>("Resolution Y"), + params.extract_input<int>("Resolution Z")); + + if (resolution.x < 2 || resolution.y < 2 || resolution.z < 2) { + params.error_message_add(NodeWarningType::Error, TIP_("Resolution must be greater than 1")); + params.set_default_remaining_outputs(); + return; + } + + if (bounds_min.x == bounds_max.x || bounds_min.y == bounds_max.y || + bounds_min.z == bounds_max.z) { + params.error_message_add(NodeWarningType::Error, + TIP_("Bounding box volume must be greater than 0")); + params.set_default_remaining_outputs(); + return; + } + + Field<float> input_field = params.extract_input<Field<float>>("Density"); + + /* Evaluate input field on a 3D grid. */ + Grid3DFieldContext context(resolution, bounds_min, bounds_max); + FieldEvaluator evaluator(context, context.points_num()); + Array<float> densities(context.points_num()); + evaluator.add_with_destination(std::move(input_field), densities.as_mutable_span()); + evaluator.evaluate(); + + /* Store resulting values in openvdb grid. */ + const float background = params.extract_input<float>("Background"); + openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create(background); + grid->setGridClass(openvdb::GRID_FOG_VOLUME); + + openvdb::tools::Dense<float, openvdb::tools::LayoutZYX> dense_grid{ + openvdb::math::CoordBBox({0, 0, 0}, {resolution.x - 1, resolution.y - 1, resolution.z - 1}), + densities.data()}; + openvdb::tools::copyFromDense(dense_grid, *grid, 0.0f); + + grid->transform().preTranslate(openvdb::math::Vec3<float>(-0.5f)); + const float3 scale_fac = (bounds_max - bounds_min) / float3(resolution - 1); + grid->transform().postScale(openvdb::math::Vec3<float>(scale_fac.x, scale_fac.y, scale_fac.z)); + grid->transform().postTranslate( + openvdb::math::Vec3<float>(bounds_min.x, bounds_min.y, bounds_min.z)); + + Volume *volume = (Volume *)BKE_id_new_nomain(ID_VO, nullptr); + BKE_volume_init_grids(volume); + + BKE_volume_grid_add_vdb(*volume, "density", std::move(grid)); + + GeometrySet r_geometry_set; + r_geometry_set.replace_volume(volume); + params.set_output("Volume", r_geometry_set); +} + +#else +static void node_geo_exec(GeoNodeExecParams params) +{ + params.error_message_add(NodeWarningType::Error, + TIP_("Disabled, Blender was compiled without OpenVDB")); + params.set_default_remaining_outputs(); +} +#endif /* WITH_OPENVDB */ + +} // namespace blender::nodes::node_geo_volume_cube_cc + +void register_node_type_geo_volume_cube() +{ + namespace file_ns = blender::nodes::node_geo_volume_cube_cc; + + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_VOLUME_CUBE, "Volume Cube", NODE_CLASS_GEOMETRY); + + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc index e5827c24320..e1d1c67b8c8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc @@ -41,7 +41,9 @@ static void node_declare(NodeDeclarationBuilder &b) .make_available([](bNode &node) { node_storage(node).resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT; }); - b.add_input<decl::Float>(N_("Threshold")).default_value(0.1f).min(0.0f); + b.add_input<decl::Float>(N_("Threshold")) + .default_value(0.1f) + .description(N_("Values larger than the threshold are inside the generated mesh")); b.add_input<decl::Float>(N_("Adaptivity")).min(0.0f).max(1.0f).subtype(PROP_FACTOR); b.add_output<decl::Geometry>(N_("Mesh")); } @@ -151,6 +153,16 @@ static Mesh *create_mesh_from_volume(GeometrySet &geometry_set, GeoNodeExecParam } const bke::VolumeToMeshResolution resolution = get_resolution_param(params); + + if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE && + resolution.settings.voxel_size <= 0.0f) { + return nullptr; + } + if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT && + resolution.settings.voxel_amount <= 0) { + return nullptr; + } + const Main *bmain = DEG_get_bmain(params.depsgraph()); BKE_volume_load(volume, bmain); diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index f107ec73c60..24558e4b32b 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -1007,6 +1007,7 @@ static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node) LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->type == SH_NODE_OUTPUT_AOV) { + node->tmp_flag = 1; nodeChainIterBackwards(ntree, node, ntree_branch_node_tag, nullptr, 0); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc index 94a6febe92e..d4413036555 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc @@ -48,16 +48,36 @@ class MF_SeparateXYZ : public fn::MultiFunction { void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override { const VArray<float3> &vectors = params.readonly_single_input<float3>(0, "XYZ"); - MutableSpan<float> xs = params.uninitialized_single_output<float>(1, "X"); - MutableSpan<float> ys = params.uninitialized_single_output<float>(2, "Y"); - MutableSpan<float> zs = params.uninitialized_single_output<float>(3, "Z"); - - for (int64_t i : mask) { - float3 xyz = vectors[i]; - xs[i] = xyz.x; - ys[i] = xyz.y; - zs[i] = xyz.z; + MutableSpan<float> xs = params.uninitialized_single_output_if_required<float>(1, "X"); + MutableSpan<float> ys = params.uninitialized_single_output_if_required<float>(2, "Y"); + MutableSpan<float> zs = params.uninitialized_single_output_if_required<float>(3, "Z"); + + std::array<MutableSpan<float>, 3> outputs = {xs, ys, zs}; + Vector<int> used_outputs; + if (!xs.is_empty()) { + used_outputs.append(0); } + if (!ys.is_empty()) { + used_outputs.append(1); + } + if (!zs.is_empty()) { + used_outputs.append(2); + } + + devirtualize_varray(vectors, [&](auto vectors) { + mask.to_best_mask_type([&](auto mask) { + const int used_outputs_num = used_outputs.size(); + const int *used_outputs_data = used_outputs.data(); + + for (const int64_t i : mask) { + const float3 &vector = vectors[i]; + for (const int out_i : IndexRange(used_outputs_num)) { + const int coordinate = used_outputs_data[out_i]; + outputs[coordinate][i] = vector[coordinate]; + } + } + }); + }); } }; diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 903e293a962..03dc61af9a2 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -324,7 +324,6 @@ int ntreeTexExecTree(bNodeTree *ntree, MTex *mtex) { TexCallData data; - float *nor = target->nor; int retval = TEX_INT; bNodeThreadStack *nts = NULL; bNodeTreeExec *exec = ntree->execdata; @@ -356,14 +355,7 @@ int ntreeTexExecTree(bNodeTree *ntree, ntreeExecThreadNodes(exec, nts, &data, thread); ntreeReleaseThreadStack(nts); - if (target->nor) { - retval |= TEX_NOR; - } retval |= TEX_RGB; - /* confusing stuff; the texture output node sets this to NULL to indicate no normal socket was - * set however, the texture code checks this for other reasons - * (namely, a normal is required for material). */ - target->nor = nor; return retval; } diff --git a/source/blender/nodes/texture/nodes/node_texture_output.c b/source/blender/nodes/texture/nodes/node_texture_output.c index cf5e32cb486..b300ba9ef77 100644 --- a/source/blender/nodes/texture/nodes/node_texture_output.c +++ b/source/blender/nodes/texture/nodes/node_texture_output.c @@ -13,7 +13,6 @@ /* **************** COMPOSITE ******************** */ static bNodeSocketTemplate inputs[] = { {SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_DIRECTION}, {-1, ""}, }; @@ -32,12 +31,7 @@ static void exec(void *data, TexParams params; params_from_cdata(¶ms, cdata); - if (in[1] && in[1]->hasinput && !in[0]->hasinput) { - tex_input_rgba(target->trgba, in[1], ¶ms, cdata->thread); - } - else { - tex_input_rgba(target->trgba, in[0], ¶ms, cdata->thread); - } + tex_input_rgba(target->trgba, in[0], ¶ms, cdata->thread); } else { /* 0 means don't care, so just use first */ @@ -49,15 +43,6 @@ static void exec(void *data, target->tin = (target->trgba[0] + target->trgba[1] + target->trgba[2]) / 3.0f; target->talpha = true; - - if (target->nor) { - if (in[1] && in[1]->hasinput) { - tex_input_vec(target->nor, in[1], ¶ms, cdata->thread); - } - else { - target->nor = NULL; - } - } } } } diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c index fd7e6fdfc7f..d925c9f3554 100644 --- a/source/blender/nodes/texture/nodes/node_texture_proc.c +++ b/source/blender/nodes/texture/nodes/node_texture_proc.c @@ -14,10 +14,8 @@ * In this file: wrappers to use procedural textures as nodes */ -static bNodeSocketTemplate outputs_both[] = { - {SOCK_RGBA, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f}, - {SOCK_VECTOR, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_DIRECTION}, - {-1, ""}}; +static bNodeSocketTemplate outputs_both[] = {{SOCK_RGBA, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f}, + {-1, ""}}; static bNodeSocketTemplate outputs_color_only[] = {{SOCK_RGBA, N_("Color")}, {-1, ""}}; /* Inputs common to all, #defined because nodes will need their own inputs too */ @@ -34,27 +32,15 @@ static void do_proc(float *result, TexParams *p, const float col1[4], const float col2[4], - char is_normal, Tex *tex, const short thread) { TexResult texres; int textype; - if (is_normal) { - texres.nor = result; - } - else { - texres.nor = NULL; - } - textype = multitex_nodes( tex, p->co, p->dxt, p->dyt, p->osatex, &texres, thread, 0, p->mtex, NULL); - if (is_normal) { - return; - } - if (textype & TEX_RGB) { copy_v4_v4(result, texres.trgba); } @@ -66,13 +52,8 @@ static void do_proc(float *result, typedef void (*MapFn)(Tex *tex, bNodeStack **in, TexParams *p, const short thread); -static void texfn(float *result, - TexParams *p, - bNode *node, - bNodeStack **in, - char is_normal, - MapFn map_inputs, - short thread) +static void texfn( + float *result, TexParams *p, bNode *node, bNodeStack **in, MapFn map_inputs, short thread) { Tex tex = *((Tex *)(node->storage)); float col1[4], col2[4]; @@ -81,7 +62,7 @@ static void texfn(float *result, map_inputs(&tex, in, p, thread); - do_proc(result, p, col1, col2, is_normal, &tex, thread); + do_proc(result, p, col1, col2, &tex, thread); } static int count_outputs(bNode *node) @@ -106,12 +87,7 @@ static int count_outputs(bNode *node) static void name##_colorfn( \ float *result, TexParams *p, bNode *node, bNodeStack **in, short thread) \ { \ - texfn(result, p, node, in, 0, &name##_map_inputs, thread); \ - } \ - static void name##_normalfn( \ - float *result, TexParams *p, bNode *node, bNodeStack **in, short thread) \ - { \ - texfn(result, p, node, in, 1, &name##_map_inputs, thread); \ + texfn(result, p, node, in, &name##_map_inputs, thread); \ } \ static void name##_exec(void *data, \ int UNUSED(thread), \ @@ -124,9 +100,6 @@ static int count_outputs(bNode *node) if (outs >= 1) { \ tex_output(node, execdata, in, out[0], &name##_colorfn, data); \ } \ - if (outs >= 2) { \ - tex_output(node, execdata, in, out[1], &name##_normalfn, data); \ - } \ } /* --- VORONOI -- */ diff --git a/source/blender/nodes/texture/nodes/node_texture_texture.c b/source/blender/nodes/texture/nodes/node_texture_texture.c index 2d2b4e06665..79cd8bbb1df 100644 --- a/source/blender/nodes/texture/nodes/node_texture_texture.c +++ b/source/blender/nodes/texture/nodes/node_texture_texture.c @@ -45,13 +45,11 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor else if (nodetex) { TexResult texres; int textype; - float nor[] = {0, 0, 0}; float col1[4], col2[4]; tex_input_rgba(col1, in[0], p, thread); tex_input_rgba(col2, in[1], p, thread); - texres.nor = nor; textype = multitex_nodes(nodetex, co, dxt, dyt, p->osatex, &texres, thread, 0, p->mtex, NULL); if (textype & TEX_RGB) { diff --git a/source/blender/render/RE_texture.h b/source/blender/render/RE_texture.h index be50eacd7bf..a4e30c917d5 100644 --- a/source/blender/render/RE_texture.h +++ b/source/blender/render/RE_texture.h @@ -44,8 +44,6 @@ bool RE_texture_evaluate(const struct MTex *mtex, * \param fact: Texture strength. * \param facg: Button strength value. */ -void texture_rgb_blend( - float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype); float texture_value_blend(float tex, float out, float fact, float facg, int blendtype); void RE_texture_rng_init(void); @@ -89,7 +87,6 @@ typedef struct TexResult { float trgba[4]; /* Is actually a boolean: When true -> use alpha, false -> set alpha to 1.0. */ int talpha; - float *nor; } TexResult; /* This one uses nodes. */ diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index 9f4aa642773..9992d1a507f 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -825,7 +825,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) if (rpass->rect == NULL || rpassp->rect == NULL) { continue; } - /* Renderresult have all passes, renderpart only the active view's passes. */ + /* Render-result have all passes, render-part only the active view's passes. */ if (!STREQ(rpassp->fullname, rpass->fullname)) { continue; } diff --git a/source/blender/render/intern/texture_image.c b/source/blender/render/intern/texture_image.c index 3b1eb293a3a..7da9e7c3d58 100644 --- a/source/blender/render/intern/texture_image.c +++ b/source/blender/render/intern/texture_image.c @@ -88,14 +88,13 @@ int imagewrap(Tex *tex, struct ImagePool *pool, const bool skip_load_image) { - float fx, fy, val1, val2, val3; + float fx, fy; int x, y, retval; int xi, yi; /* original values */ texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f; - /* we need to set retval OK, otherwise texture code generates normals itself... */ - retval = texres->nor ? (TEX_RGB | TEX_NOR) : TEX_RGB; + retval = TEX_RGB; /* quick tests */ if (ima == NULL) { @@ -256,47 +255,6 @@ int imagewrap(Tex *tex, ibuf_get_color(texres->trgba, ibuf, x, y); } - if (texres->nor) { - if (tex->imaflag & TEX_NORMALMAP) { - /* Normal from color: - * The invert of the red channel is to make - * the normal map compliant with the outside world. - * It needs to be done because in Blender - * the normal used in the renderer points inward. It is generated - * this way in calc_vertexnormals(). Should this ever change - * this negate must be removed. */ - texres->nor[0] = -2.0f * (texres->trgba[0] - 0.5f); - texres->nor[1] = 2.0f * (texres->trgba[1] - 0.5f); - texres->nor[2] = 2.0f * (texres->trgba[2] - 0.5f); - } - else { - /* bump: take three samples */ - val1 = texres->trgba[0] + texres->trgba[1] + texres->trgba[2]; - - if (x < ibuf->x - 1) { - float col[4]; - ibuf_get_color(col, ibuf, x + 1, y); - val2 = (col[0] + col[1] + col[2]); - } - else { - val2 = val1; - } - - if (y < ibuf->y - 1) { - float col[4]; - ibuf_get_color(col, ibuf, x, y + 1); - val3 = (col[0] + col[1] + col[2]); - } - else { - val3 = val1; - } - - /* do not mix up x and y here! */ - texres->nor[0] = (val1 - val2); - texres->nor[1] = (val1 - val3); - } - } - if (texres->talpha) { texres->tin = texres->trgba[3]; } @@ -989,7 +947,7 @@ static int imagewraposa_aniso(Tex *tex, { TexResult texr; float fx, fy, minx, maxx, miny, maxy; - float maxd, val1, val2, val3; + float maxd; int curmap, retval, intpol, extflag = 0; afdata_t AFD; @@ -1008,8 +966,7 @@ static int imagewraposa_aniso(Tex *tex, texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f; - /* we need to set retval OK, otherwise texture code generates normals itself... */ - retval = texres->nor ? (TEX_RGB | TEX_NOR) : TEX_RGB; + retval = TEX_RGB; /* quick tests */ if (ibuf == NULL && ima == NULL) { @@ -1040,7 +997,7 @@ static int imagewraposa_aniso(Tex *tex, if (ima) { if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { - texres->talpha = 1; + texres->talpha = true; } } } @@ -1301,48 +1258,17 @@ static int imagewraposa_aniso(Tex *tex, } /* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */ - - if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) { - /* color & normal */ - filterfunc(texres, curibuf, fx, fy, &AFD); - val1 = texres->trgba[0] + texres->trgba[1] + texres->trgba[2]; - filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD); - val2 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD); - val3 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - /* don't switch x or y! */ - texres->nor[0] = val1 - val2; - texres->nor[1] = val1 - val3; - if (previbuf != curibuf) { /* interpolate */ - filterfunc(&texr, previbuf, fx, fy, &AFD); - /* rgb */ - texres->trgba[0] += levf * (texr.trgba[0] - texres->trgba[0]); - texres->trgba[1] += levf * (texr.trgba[1] - texres->trgba[1]); - texres->trgba[2] += levf * (texr.trgba[2] - texres->trgba[2]); - texres->trgba[3] += levf * (texr.trgba[3] - texres->trgba[3]); - /* normal */ - val1 += levf * ((texr.trgba[0] + texr.trgba[1] + texr.trgba[2]) - val1); - filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD); - val2 += levf * ((texr.trgba[0] + texr.trgba[1] + texr.trgba[2]) - val2); - filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD); - val3 += levf * ((texr.trgba[0] + texr.trgba[1] + texr.trgba[2]) - val3); - texres->nor[0] = val1 - val2; /* vals have been interpolated above! */ - texres->nor[1] = val1 - val3; - } + filterfunc(texres, curibuf, fx, fy, &AFD); + if (previbuf != curibuf) { /* interpolate */ + filterfunc(&texr, previbuf, fx, fy, &AFD); + texres->trgba[0] += levf * (texr.trgba[0] - texres->trgba[0]); + texres->trgba[1] += levf * (texr.trgba[1] - texres->trgba[1]); + texres->trgba[2] += levf * (texr.trgba[2] - texres->trgba[2]); + texres->trgba[3] += levf * (texr.trgba[3] - texres->trgba[3]); } - else { /* color */ - filterfunc(texres, curibuf, fx, fy, &AFD); - if (previbuf != curibuf) { /* interpolate */ - filterfunc(&texr, previbuf, fx, fy, &AFD); - texres->trgba[0] += levf * (texr.trgba[0] - texres->trgba[0]); - texres->trgba[1] += levf * (texr.trgba[1] - texres->trgba[1]); - texres->trgba[2] += levf * (texr.trgba[2] - texres->trgba[2]); - texres->trgba[3] += levf * (texr.trgba[3] - texres->trgba[3]); - } - if (tex->texfilter != TXF_EWA) { - alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres); - } + if (tex->texfilter != TXF_EWA) { + alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres); } } else { /* no mipmap */ @@ -1372,23 +1298,9 @@ static int imagewraposa_aniso(Tex *tex, AFD.dusc = 1.0f / ff; AFD.dvsc = ff / (float)ibuf->y; } - if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) { - /* color & normal */ - filterfunc(texres, ibuf, fx, fy, &AFD); - val1 = texres->trgba[0] + texres->trgba[1] + texres->trgba[2]; - filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD); - val2 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD); - val3 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - /* don't switch x or y! */ - texres->nor[0] = val1 - val2; - texres->nor[1] = val1 - val3; - } - else { - filterfunc(texres, ibuf, fx, fy, &AFD); - if (tex->texfilter != TXF_EWA) { - alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres); - } + filterfunc(texres, ibuf, fx, fy, &AFD); + if (tex->texfilter != TXF_EWA) { + alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres); } } @@ -1403,18 +1315,6 @@ static int imagewraposa_aniso(Tex *tex, texres->trgba[3] = 1.0f - texres->trgba[3]; } - if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { /* normal from color */ - /* The invert of the red channel is to make - * the normal map compliant with the outside world. - * It needs to be done because in Blender - * the normal used in the renderer points inward. It is generated - * this way in calc_vertexnormals(). Should this ever change - * this negate must be removed. */ - texres->nor[0] = -2.0f * (texres->trgba[0] - 0.5f); - texres->nor[1] = 2.0f * (texres->trgba[1] - 0.5f); - texres->nor[2] = 2.0f * (texres->trgba[2] - 0.5f); - } - /* de-premul, this is being pre-multiplied in shade_input_do_shade() * TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, * so for now commented out also disabled in imagewraposa() @@ -1451,7 +1351,7 @@ int imagewraposa(Tex *tex, { TexResult texr; float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2]; - float maxd, pixsize, val1, val2, val3; + float maxd, pixsize; int curmap, retval, imaprepeat, imapextend; /* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() @@ -1466,8 +1366,7 @@ int imagewraposa(Tex *tex, texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f; - /* we need to set retval OK, otherwise texture code generates normals itself... */ - retval = texres->nor ? (TEX_RGB | TEX_NOR) : TEX_RGB; + retval = TEX_RGB; /* quick tests */ if (ibuf == NULL && ima == NULL) { @@ -1762,118 +1661,30 @@ int imagewraposa(Tex *tex, } } - if (texres->nor && (tex->imaflag & TEX_NORMALMAP) == 0) { - /* a bit extra filter */ - // minx*= 1.35f; - // miny*= 1.35f; - - boxsample( - curibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend); - val1 = texres->trgba[0] + texres->trgba[1] + texres->trgba[2]; - boxsample(curibuf, - fx - minx + dxt[0], - fy - miny + dxt[1], - fx + minx + dxt[0], - fy + miny + dxt[1], - &texr, - imaprepeat, - imapextend); - val2 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - boxsample(curibuf, - fx - minx + dyt[0], - fy - miny + dyt[1], - fx + minx + dyt[0], - fy + miny + dyt[1], - &texr, - imaprepeat, - imapextend); - val3 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - - /* don't switch x or y! */ - texres->nor[0] = (val1 - val2); - texres->nor[1] = (val1 - val3); - - if (previbuf != curibuf) { /* interpolate */ - - boxsample( - previbuf, fx - minx, fy - miny, fx + minx, fy + miny, &texr, imaprepeat, imapextend); - - /* calc rgb */ - dx = 2.0f * (pixsize - maxd) / pixsize; - if (dx >= 1.0f) { - texres->trgba[3] = texr.trgba[3]; - texres->trgba[2] = texr.trgba[2]; - texres->trgba[1] = texr.trgba[1]; - texres->trgba[0] = texr.trgba[0]; - } - else { - dy = 1.0f - dx; - texres->trgba[2] = dy * texres->trgba[2] + dx * texr.trgba[2]; - texres->trgba[1] = dy * texres->trgba[1] + dx * texr.trgba[1]; - texres->trgba[0] = dy * texres->trgba[0] + dx * texr.trgba[0]; - texres->trgba[3] = dy * texres->trgba[3] + dx * texr.trgba[3]; - } - - val1 = dy * val1 + dx * (texr.trgba[0] + texr.trgba[1] + texr.trgba[2]); - boxsample(previbuf, - fx - minx + dxt[0], - fy - miny + dxt[1], - fx + minx + dxt[0], - fy + miny + dxt[1], - &texr, - imaprepeat, - imapextend); - val2 = dy * val2 + dx * (texr.trgba[0] + texr.trgba[1] + texr.trgba[2]); - boxsample(previbuf, - fx - minx + dyt[0], - fy - miny + dyt[1], - fx + minx + dyt[0], - fy + miny + dyt[1], - &texr, - imaprepeat, - imapextend); - val3 = dy * val3 + dx * (texr.trgba[0] + texr.trgba[1] + texr.trgba[2]); - - texres->nor[0] = (val1 - val2); /* vals have been interpolated above! */ - texres->nor[1] = (val1 - val3); - - if (dx < 1.0f) { - dy = 1.0f - dx; - texres->trgba[2] = dy * texres->trgba[2] + dx * texr.trgba[2]; - texres->trgba[1] = dy * texres->trgba[1] + dx * texr.trgba[1]; - texres->trgba[0] = dy * texres->trgba[0] + dx * texr.trgba[0]; - texres->trgba[3] = dy * texres->trgba[3] + dx * texr.trgba[3]; - } - } - texres->nor[0] *= bumpscale; - texres->nor[1] *= bumpscale; - } - else { - maxx = fx + minx; - minx = fx - minx; - maxy = fy + miny; - miny = fy - miny; + maxx = fx + minx; + minx = fx - minx; + maxy = fy + miny; + miny = fy - miny; - boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend); + boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend); - if (previbuf != curibuf) { /* interpolate */ - boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend); + if (previbuf != curibuf) { /* interpolate */ + boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend); - fx = 2.0f * (pixsize - maxd) / pixsize; + fx = 2.0f * (pixsize - maxd) / pixsize; - if (fx >= 1.0f) { - texres->trgba[3] = texr.trgba[3]; - texres->trgba[2] = texr.trgba[2]; - texres->trgba[1] = texr.trgba[1]; - texres->trgba[0] = texr.trgba[0]; - } - else { - fy = 1.0f - fx; - texres->trgba[2] = fy * texres->trgba[2] + fx * texr.trgba[2]; - texres->trgba[1] = fy * texres->trgba[1] + fx * texr.trgba[1]; - texres->trgba[0] = fy * texres->trgba[0] + fx * texr.trgba[0]; - texres->trgba[3] = fy * texres->trgba[3] + fx * texr.trgba[3]; - } + if (fx >= 1.0f) { + texres->trgba[3] = texr.trgba[3]; + texres->trgba[2] = texr.trgba[2]; + texres->trgba[1] = texr.trgba[1]; + texres->trgba[0] = texr.trgba[0]; + } + else { + fy = 1.0f - fx; + texres->trgba[2] = fy * texres->trgba[2] + fx * texr.trgba[2]; + texres->trgba[1] = fy * texres->trgba[1] + fx * texr.trgba[1]; + texres->trgba[0] = fy * texres->trgba[0] + fx * texr.trgba[0]; + texres->trgba[3] = fy * texres->trgba[3] + fx * texr.trgba[3]; } } } @@ -1889,35 +1700,7 @@ int imagewraposa(Tex *tex, } } - if (texres->nor && (tex->imaflag & TEX_NORMALMAP) == 0) { - boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend); - val1 = texres->trgba[0] + texres->trgba[1] + texres->trgba[2]; - boxsample(ibuf, - fx - minx + dxt[0], - fy - miny + dxt[1], - fx + minx + dxt[0], - fy + miny + dxt[1], - &texr, - imaprepeat, - imapextend); - val2 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - boxsample(ibuf, - fx - minx + dyt[0], - fy - miny + dyt[1], - fx + minx + dyt[0], - fy + miny + dyt[1], - &texr, - imaprepeat, - imapextend); - val3 = texr.trgba[0] + texr.trgba[1] + texr.trgba[2]; - - /* don't switch x or y! */ - texres->nor[0] = (val1 - val2); - texres->nor[1] = (val1 - val3); - } - else { - boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend); - } + boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend); } if (tex->imaflag & TEX_CALCALPHA) { @@ -1932,17 +1715,6 @@ int imagewraposa(Tex *tex, texres->trgba[3] = 1.0f - texres->trgba[3]; } - if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) { - /* Normal from color: - * The invert of the red channel is to make the normal map compliant with the outside world. - * It needs to be done because in Blender the normal used in the renderer points inward. - * It is generated this way in #calc_vertexnormals(). - * Should this ever change this negate must be removed. */ - texres->nor[0] = -2.0f * (texres->trgba[0] - 0.5f); - texres->nor[1] = 2.0f * (texres->trgba[1] - 0.5f); - texres->nor[2] = 2.0f * (texres->trgba[2] - 0.5f); - } - /* de-premul, this is being pre-multiplied in shade_input_do_shade() */ /* do not de-premul for generated alpha, it is already in straight */ if (texres->trgba[3] != 1.0f && texres->trgba[3] > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) { diff --git a/source/blender/render/intern/texture_procedural.c b/source/blender/render/intern/texture_procedural.c index ce58993b7cf..37605236738 100644 --- a/source/blender/render/intern/texture_procedural.c +++ b/source/blender/render/intern/texture_procedural.c @@ -61,34 +61,6 @@ void RE_texture_rng_exit(void) /* ------------------------------------------------------------------------- */ -/* This allows color-banded textures to control normals as well. */ -static void tex_normal_derivate(const Tex *tex, TexResult *texres) -{ - if (tex->flag & TEX_COLORBAND) { - float col[4]; - if (BKE_colorband_evaluate(tex->coba, texres->tin, col)) { - float fac0, fac1, fac2, fac3; - - fac0 = (col[0] + col[1] + col[2]); - BKE_colorband_evaluate(tex->coba, texres->nor[0], col); - fac1 = (col[0] + col[1] + col[2]); - BKE_colorband_evaluate(tex->coba, texres->nor[1], col); - fac2 = (col[0] + col[1] + col[2]); - BKE_colorband_evaluate(tex->coba, texres->nor[2], col); - fac3 = (col[0] + col[1] + col[2]); - - texres->nor[0] = (fac0 - fac1) / 3.0f; - texres->nor[1] = (fac0 - fac2) / 3.0f; - texres->nor[2] = (fac0 - fac3) / 3.0f; - - return; - } - } - texres->nor[0] = texres->tin - texres->nor[0]; - texres->nor[1] = texres->tin - texres->nor[1]; - texres->nor[2] = texres->tin - texres->nor[2]; -} - static int blend(const Tex *tex, const float texvec[3], TexResult *texres) { float x, y, t; @@ -165,37 +137,7 @@ static int clouds(const Tex *tex, const float texvec[3], TexResult *texres) (tex->noisetype != TEX_NOISESOFT), tex->noisebasis); - if (texres->nor != NULL) { - /* calculate bumpnormal */ - texres->nor[0] = BLI_noise_generic_turbulence(tex->noisesize, - texvec[0] + tex->nabla, - texvec[1], - texvec[2], - tex->noisedepth, - (tex->noisetype != TEX_NOISESOFT), - tex->noisebasis); - texres->nor[1] = BLI_noise_generic_turbulence(tex->noisesize, - texvec[0], - texvec[1] + tex->nabla, - texvec[2], - tex->noisedepth, - (tex->noisetype != TEX_NOISESOFT), - tex->noisebasis); - texres->nor[2] = BLI_noise_generic_turbulence(tex->noisesize, - texvec[0], - texvec[1], - texvec[2] + tex->nabla, - tex->noisedepth, - (tex->noisetype != TEX_NOISESOFT), - tex->noisebasis); - - tex_normal_derivate(tex, texres); - rv |= TEX_NOR; - } - if (tex->stype == TEX_COLOR) { - /* in this case, int. value should really be computed from color, - * and bumpnormal from that, would be too slow, looks ok as is */ texres->trgba[0] = texres->tin; texres->trgba[1] = BLI_noise_generic_turbulence(tex->noisesize, texvec[1], @@ -298,15 +240,6 @@ static int wood(const Tex *tex, const float texvec[3], TexResult *texres) int rv = TEX_INT; texres->tin = wood_int(tex, texvec[0], texvec[1], texvec[2]); - if (texres->nor != NULL) { - /* calculate bumpnormal */ - texres->nor[0] = wood_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2]); - texres->nor[1] = wood_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2]); - texres->nor[2] = wood_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla); - - tex_normal_derivate(tex, texres); - rv |= TEX_NOR; - } BRICONT; @@ -358,17 +291,6 @@ static int marble(const Tex *tex, const float texvec[3], TexResult *texres) texres->tin = marble_int(tex, texvec[0], texvec[1], texvec[2]); - if (texres->nor != NULL) { - /* calculate bumpnormal */ - texres->nor[0] = marble_int(tex, texvec[0] + tex->nabla, texvec[1], texvec[2]); - texres->nor[1] = marble_int(tex, texvec[0], texvec[1] + tex->nabla, texvec[2]); - texres->nor[2] = marble_int(tex, texvec[0], texvec[1], texvec[2] + tex->nabla); - - tex_normal_derivate(tex, texres); - - rv |= TEX_NOR; - } - BRICONT; return rv; @@ -454,7 +376,7 @@ static int magic(const Tex *tex, const float texvec[3], TexResult *texres) /* newnoise: stucci also modified to use different noisebasis */ static int stucci(const Tex *tex, const float texvec[3], TexResult *texres) { - float nor[3], b2, ofs; + float b2, ofs; int retval = TEX_INT; b2 = BLI_noise_generic_noise(tex->noisesize, @@ -469,40 +391,13 @@ static int stucci(const Tex *tex, const float texvec[3], TexResult *texres) if (tex->stype) { ofs *= (b2 * b2); } - nor[0] = BLI_noise_generic_noise(tex->noisesize, - texvec[0] + ofs, - texvec[1], - texvec[2], - (tex->noisetype != TEX_NOISESOFT), - tex->noisebasis); - nor[1] = BLI_noise_generic_noise(tex->noisesize, - texvec[0], - texvec[1] + ofs, - texvec[2], - (tex->noisetype != TEX_NOISESOFT), - tex->noisebasis); - nor[2] = BLI_noise_generic_noise(tex->noisesize, - texvec[0], - texvec[1], - texvec[2] + ofs, - (tex->noisetype != TEX_NOISESOFT), - tex->noisebasis); - - texres->tin = nor[2]; - - if (texres->nor) { - - copy_v3_v3(texres->nor, nor); - tex_normal_derivate(tex, texres); - - if (tex->stype == TEX_WALLOUT) { - texres->nor[0] = -texres->nor[0]; - texres->nor[1] = -texres->nor[1]; - texres->nor[2] = -texres->nor[2]; - } - retval |= TEX_NOR; - } + texres->tin = BLI_noise_generic_noise(tex->noisesize, + texvec[0], + texvec[1], + texvec[2] + ofs, + (tex->noisetype != TEX_NOISESOFT), + tex->noisebasis); if (tex->stype == TEX_WALLOUT) { texres->tin = 1.0f - texres->tin; @@ -538,36 +433,6 @@ static int mg_mFractalOrfBmTex(const Tex *tex, const float texvec[3], TexResult tex->mg_octaves, tex->noisebasis); - if (texres->nor != NULL) { - float ofs = tex->nabla / tex->noisesize; /* also scaling of texvec */ - - /* calculate bumpnormal */ - texres->nor[0] = tex->ns_outscale * mgravefunc(texvec[0] + ofs, - texvec[1], - texvec[2], - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->noisebasis); - texres->nor[1] = tex->ns_outscale * mgravefunc(texvec[0], - texvec[1] + ofs, - texvec[2], - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->noisebasis); - texres->nor[2] = tex->ns_outscale * mgravefunc(texvec[0], - texvec[1], - texvec[2] + ofs, - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->noisebasis); - - tex_normal_derivate(tex, texres); - rv |= TEX_NOR; - } - BRICONT; return rv; @@ -595,42 +460,6 @@ static int mg_ridgedOrHybridMFTex(const Tex *tex, const float texvec[3], TexResu tex->mg_gain, tex->noisebasis); - if (texres->nor != NULL) { - float ofs = tex->nabla / tex->noisesize; /* also scaling of texvec */ - - /* calculate bumpnormal */ - texres->nor[0] = tex->ns_outscale * mgravefunc(texvec[0] + ofs, - texvec[1], - texvec[2], - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->mg_offset, - tex->mg_gain, - tex->noisebasis); - texres->nor[1] = tex->ns_outscale * mgravefunc(texvec[0], - texvec[1] + ofs, - texvec[2], - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->mg_offset, - tex->mg_gain, - tex->noisebasis); - texres->nor[2] = tex->ns_outscale * mgravefunc(texvec[0], - texvec[1], - texvec[2] + ofs, - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->mg_offset, - tex->mg_gain, - tex->noisebasis); - - tex_normal_derivate(tex, texres); - rv |= TEX_NOR; - } - BRICONT; return rv; @@ -649,39 +478,6 @@ static int mg_HTerrainTex(const Tex *tex, const float texvec[3], TexResult *texr tex->mg_offset, tex->noisebasis); - if (texres->nor != NULL) { - float ofs = tex->nabla / tex->noisesize; /* also scaling of texvec */ - - /* calculate bumpnormal */ - texres->nor[0] = tex->ns_outscale * BLI_noise_mg_hetero_terrain(texvec[0] + ofs, - texvec[1], - texvec[2], - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->mg_offset, - tex->noisebasis); - texres->nor[1] = tex->ns_outscale * BLI_noise_mg_hetero_terrain(texvec[0], - texvec[1] + ofs, - texvec[2], - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->mg_offset, - tex->noisebasis); - texres->nor[2] = tex->ns_outscale * BLI_noise_mg_hetero_terrain(texvec[0], - texvec[1], - texvec[2] + ofs, - tex->mg_H, - tex->mg_lacunarity, - tex->mg_octaves, - tex->mg_offset, - tex->noisebasis); - - tex_normal_derivate(tex, texres); - rv |= TEX_NOR; - } - BRICONT; return rv; @@ -694,33 +490,6 @@ static int mg_distNoiseTex(const Tex *tex, const float texvec[3], TexResult *tex texres->tin = BLI_noise_mg_variable_lacunarity( texvec[0], texvec[1], texvec[2], tex->dist_amount, tex->noisebasis, tex->noisebasis2); - if (texres->nor != NULL) { - float ofs = tex->nabla / tex->noisesize; /* also scaling of texvec */ - - /* calculate bumpnormal */ - texres->nor[0] = BLI_noise_mg_variable_lacunarity(texvec[0] + ofs, - texvec[1], - texvec[2], - tex->dist_amount, - tex->noisebasis, - tex->noisebasis2); - texres->nor[1] = BLI_noise_mg_variable_lacunarity(texvec[0], - texvec[1] + ofs, - texvec[2], - tex->dist_amount, - tex->noisebasis, - tex->noisebasis2); - texres->nor[2] = BLI_noise_mg_variable_lacunarity(texvec[0], - texvec[1], - texvec[2] + ofs, - tex->dist_amount, - tex->noisebasis, - tex->noisebasis2); - - tex_normal_derivate(tex, texres); - rv |= TEX_NOR; - } - BRICONT; return rv; @@ -788,21 +557,6 @@ static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres) } } - if (texres->nor != NULL) { - float ofs = tex->nabla / tex->noisesize; /* also scaling of texvec */ - - /* calculate bumpnormal */ - BLI_noise_voronoi(texvec[0] + ofs, texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[0] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); - BLI_noise_voronoi(texvec[0], texvec[1] + ofs, texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[1] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); - BLI_noise_voronoi(texvec[0], texvec[1], texvec[2] + ofs, da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[2] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); - - tex_normal_derivate(tex, texres); - rv |= TEX_NOR; - } - if (tex->vn_coltype) { BRICONTRGB; texres->trgba[3] = 1.0; @@ -1148,7 +902,7 @@ static int multitex(Tex *tex, const bool use_nodes) { float tmpvec[3]; - int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */ + int retval = 0; /* return value, TEX_INT or TEX_RGB. */ texres->talpha = false; /* is set when image texture returns alpha (considered premul) */ @@ -1283,14 +1037,14 @@ static int multitex_nodes_intern(Tex *tex, } if (tex->type == TEX_IMAGE) { - int rgbnor; + int retval; if (mtex) { float texvec_l[3]; copy_v3_v3(texvec_l, texvec); /* we have mtex, use it for 2d mapping images only */ do_2d_mapping(mtex, texvec_l, NULL, dxt, dyt); - rgbnor = multitex(tex, + retval = multitex(tex, texvec_l, dxt, dyt, @@ -1307,7 +1061,7 @@ static int multitex_nodes_intern(Tex *tex, ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); /* don't linearize float buffers, assumed to be linear */ - if (ibuf != NULL && ibuf->rect_float == NULL && (rgbnor & TEX_RGB) && scene_color_manage) { + if (ibuf != NULL && ibuf->rect_float == NULL && (retval & TEX_RGB) && scene_color_manage) { IMB_colormanagement_colorspace_to_scene_linear_v3(texres->trgba, ibuf->rect_colorspace); } @@ -1335,7 +1089,7 @@ static int multitex_nodes_intern(Tex *tex, } do_2d_mapping(&localmtex, texvec_l, NULL, dxt_l, dyt_l); - rgbnor = multitex(tex, + retval = multitex(tex, texvec_l, dxt_l, dyt_l, @@ -1352,7 +1106,7 @@ static int multitex_nodes_intern(Tex *tex, ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); /* don't linearize float buffers, assumed to be linear */ - if (ibuf != NULL && ibuf->rect_float == NULL && (rgbnor & TEX_RGB) && scene_color_manage) { + if (ibuf != NULL && ibuf->rect_float == NULL && (retval & TEX_RGB) && scene_color_manage) { IMB_colormanagement_colorspace_to_scene_linear_v3(texres->trgba, ibuf->rect_colorspace); } @@ -1360,7 +1114,7 @@ static int multitex_nodes_intern(Tex *tex, } } - return rgbnor; + return retval; } return multitex(tex, @@ -1456,145 +1210,6 @@ int multitex_ext_safe(Tex *tex, /* ------------------------------------------------------------------------- */ -void texture_rgb_blend( - float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype) -{ - float facm; - - switch (blendtype) { - case MTEX_BLEND: - fact *= facg; - facm = 1.0f - fact; - - in[0] = (fact * tex[0] + facm * out[0]); - in[1] = (fact * tex[1] + facm * out[1]); - in[2] = (fact * tex[2] + facm * out[2]); - break; - - case MTEX_MUL: - fact *= facg; - facm = 1.0f - fact; - in[0] = (facm + fact * tex[0]) * out[0]; - in[1] = (facm + fact * tex[1]) * out[1]; - in[2] = (facm + fact * tex[2]) * out[2]; - break; - - case MTEX_SCREEN: - fact *= facg; - facm = 1.0f - fact; - in[0] = 1.0f - (facm + fact * (1.0f - tex[0])) * (1.0f - out[0]); - in[1] = 1.0f - (facm + fact * (1.0f - tex[1])) * (1.0f - out[1]); - in[2] = 1.0f - (facm + fact * (1.0f - tex[2])) * (1.0f - out[2]); - break; - - case MTEX_OVERLAY: - fact *= facg; - facm = 1.0f - fact; - - if (out[0] < 0.5f) { - in[0] = out[0] * (facm + 2.0f * fact * tex[0]); - } - else { - in[0] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[0])) * (1.0f - out[0]); - } - if (out[1] < 0.5f) { - in[1] = out[1] * (facm + 2.0f * fact * tex[1]); - } - else { - in[1] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[1])) * (1.0f - out[1]); - } - if (out[2] < 0.5f) { - in[2] = out[2] * (facm + 2.0f * fact * tex[2]); - } - else { - in[2] = 1.0f - (facm + 2.0f * fact * (1.0f - tex[2])) * (1.0f - out[2]); - } - break; - - case MTEX_SUB: - fact = -fact; - ATTR_FALLTHROUGH; - case MTEX_ADD: - fact *= facg; - in[0] = (fact * tex[0] + out[0]); - in[1] = (fact * tex[1] + out[1]); - in[2] = (fact * tex[2] + out[2]); - break; - - case MTEX_DIV: - fact *= facg; - facm = 1.0f - fact; - - if (tex[0] != 0.0f) { - in[0] = facm * out[0] + fact * out[0] / tex[0]; - } - if (tex[1] != 0.0f) { - in[1] = facm * out[1] + fact * out[1] / tex[1]; - } - if (tex[2] != 0.0f) { - in[2] = facm * out[2] + fact * out[2] / tex[2]; - } - - break; - - case MTEX_DIFF: - fact *= facg; - facm = 1.0f - fact; - in[0] = facm * out[0] + fact * fabsf(tex[0] - out[0]); - in[1] = facm * out[1] + fact * fabsf(tex[1] - out[1]); - in[2] = facm * out[2] + fact * fabsf(tex[2] - out[2]); - break; - - case MTEX_DARK: - fact *= facg; - facm = 1.0f - fact; - - in[0] = min_ff(out[0], tex[0]) * fact + out[0] * facm; - in[1] = min_ff(out[1], tex[1]) * fact + out[1] * facm; - in[2] = min_ff(out[2], tex[2]) * fact + out[2] * facm; - break; - - case MTEX_LIGHT: - fact *= facg; - - in[0] = max_ff(fact * tex[0], out[0]); - in[1] = max_ff(fact * tex[1], out[1]); - in[2] = max_ff(fact * tex[2], out[2]); - break; - - case MTEX_BLEND_HUE: - fact *= facg; - copy_v3_v3(in, out); - ramp_blend(MA_RAMP_HUE, in, fact, tex); - break; - case MTEX_BLEND_SAT: - fact *= facg; - copy_v3_v3(in, out); - ramp_blend(MA_RAMP_SAT, in, fact, tex); - break; - case MTEX_BLEND_VAL: - fact *= facg; - copy_v3_v3(in, out); - ramp_blend(MA_RAMP_VAL, in, fact, tex); - break; - case MTEX_BLEND_COLOR: - fact *= facg; - copy_v3_v3(in, out); - ramp_blend(MA_RAMP_COLOR, in, fact, tex); - break; - case MTEX_SOFT_LIGHT: - fact *= facg; - copy_v3_v3(in, out); - ramp_blend(MA_RAMP_SOFT, in, fact, tex); - break; - case MTEX_LIN_LIGHT: - fact *= facg; - copy_v3_v3(in, out); - ramp_blend(MA_RAMP_LINEAR, in, fact, tex); - break; - } -} - float texture_value_blend(float tex, float out, float fact, float facg, int blendtype) { float in = 0.0, facm, col, scf; @@ -1703,7 +1318,6 @@ bool RE_texture_evaluate(const MTex *mtex, if (tex == NULL) { return 0; } - texr.nor = NULL; /* placement */ if (mtex->projx) { diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 63a7fb5ddaa..aaa28b1fd85 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -41,6 +41,7 @@ #include "GPU_debug.h" #include "GPU_framebuffer.h" #include "GPU_immediate.h" +#include "GPU_matrix.h" #include "GPU_state.h" #include "GPU_texture.h" #include "GPU_viewport.h" @@ -158,9 +159,13 @@ static bool wm_software_cursor_needed_for_window(const wmWindow *win, struct Gra if (GHOST_GetCursorVisibility(win->ghostwin)) { /* NOTE: The value in `win->grabcursor` can't be used as it * doesn't always match GHOST's value in the case of tablet events. */ - GHOST_GetCursorGrabState( - win->ghostwin, &grab_state->mode, &grab_state->wrap_axis, grab_state->bounds); - if (grab_state->mode == GHOST_kGrabWrap) { + bool use_software_cursor; + GHOST_GetCursorGrabState(win->ghostwin, + &grab_state->mode, + &grab_state->wrap_axis, + grab_state->bounds, + &use_software_cursor); + if (use_software_cursor) { return true; } } @@ -189,27 +194,69 @@ static void wm_software_cursor_motion_clear(void) g_software_cursor.xy[1] = -1; } -static void wm_software_cursor_draw(wmWindow *win, const struct GrabState *grab_state) +static void wm_software_cursor_draw_bitmap(const int event_xy[2], + const GHOST_CursorBitmapRef *bitmap) { - int x = win->eventstate->xy[0]; - int y = win->eventstate->xy[1]; + GPU_blend(GPU_BLEND_ALPHA); - if (grab_state->wrap_axis & GHOST_kAxisX) { - const int min = grab_state->bounds[0]; - const int max = grab_state->bounds[2]; - if (min != max) { - x = mod_i(x - min, max - min) + min; - } - } - if (grab_state->wrap_axis & GHOST_kGrabAxisY) { - const int height = WM_window_pixels_y(win); - const int min = height - grab_state->bounds[1]; - const int max = height - grab_state->bounds[3]; - if (min != max) { - y = mod_i(y - max, min - max) + max; - } - } + float gl_matrix[4][4]; + GPUTexture *texture = GPU_texture_create_2d( + "softeare_cursor", bitmap->data_size[0], bitmap->data_size[1], 1, GPU_RGBA8, NULL); + GPU_texture_update(texture, GPU_DATA_UBYTE, bitmap->data); + GPU_texture_filter_mode(texture, false); + + GPU_matrix_push(); + + const int scale = (int)U.pixelsize; + + unit_m4(gl_matrix); + + gl_matrix[3][0] = event_xy[0] - (bitmap->hot_spot[0] * scale); + gl_matrix[3][1] = event_xy[1] - ((bitmap->data_size[1] - bitmap->hot_spot[1]) * scale); + + gl_matrix[0][0] = bitmap->data_size[0] * scale; + gl_matrix[1][1] = bitmap->data_size[1] * scale; + + GPU_matrix_mul(gl_matrix); + + GPUVertFormat *imm_format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + uint texCoord = GPU_vertformat_attr_add( + imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + /* Use 3D image for correct display of planar tracked images. */ + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); + + immBindTexture("image", texture); + immUniform1f("alpha", 1.0f); + + immBegin(GPU_PRIM_TRI_FAN, 4); + + immAttr2f(texCoord, 0.0f, 1.0f); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + + immAttr2f(texCoord, 1.0f, 1.0f); + immVertex3f(pos, 1.0f, 0.0f, 0.0f); + + immAttr2f(texCoord, 1.0f, 0.0f); + immVertex3f(pos, 1.0f, 1.0f, 0.0f); + + immAttr2f(texCoord, 0.0f, 0.0f); + immVertex3f(pos, 0.0f, 1.0f, 0.0f); + + immEnd(); + immUnbindProgram(); + + GPU_matrix_pop(); + GPU_texture_unbind(texture); + GPU_texture_free(texture); + + GPU_blend(GPU_BLEND_NONE); +} + +static void wm_software_cursor_draw_crosshair(const int event_xy[2]) +{ /* Draw a primitive cross-hair cursor. * NOTE: the `win->cursor` could be used for drawing although it's complicated as some cursors * are set by the operating-system, where the pixel information isn't easily available. */ @@ -222,19 +269,64 @@ static void wm_software_cursor_draw(wmWindow *win, const struct GrabState *grab_ { const int ofs_line = (8 * unit); const int ofs_size = (2 * unit); - immRecti(pos, x - ofs_line, y - ofs_size, x + ofs_line, y + ofs_size); - immRecti(pos, x - ofs_size, y - ofs_line, x + ofs_size, y + ofs_line); + immRecti(pos, + event_xy[0] - ofs_line, + event_xy[1] - ofs_size, + event_xy[0] + ofs_line, + event_xy[1] + ofs_size); + immRecti(pos, + event_xy[0] - ofs_size, + event_xy[1] - ofs_line, + event_xy[0] + ofs_size, + event_xy[1] + ofs_line); } immUniformColor4f(0, 0, 0, 1); { const int ofs_line = (7 * unit); const int ofs_size = (1 * unit); - immRecti(pos, x - ofs_line, y - ofs_size, x + ofs_line, y + ofs_size); - immRecti(pos, x - ofs_size, y - ofs_line, x + ofs_size, y + ofs_line); + immRecti(pos, + event_xy[0] - ofs_line, + event_xy[1] - ofs_size, + event_xy[0] + ofs_line, + event_xy[1] + ofs_size); + immRecti(pos, + event_xy[0] - ofs_size, + event_xy[1] - ofs_line, + event_xy[0] + ofs_size, + event_xy[1] + ofs_line); } immUnbindProgram(); } +static void wm_software_cursor_draw(wmWindow *win, const struct GrabState *grab_state) +{ + int event_xy[2] = {UNPACK2(win->eventstate->xy)}; + + if (grab_state->wrap_axis & GHOST_kAxisX) { + const int min = grab_state->bounds[0]; + const int max = grab_state->bounds[2]; + if (min != max) { + event_xy[0] = mod_i(event_xy[0] - min, max - min) + min; + } + } + if (grab_state->wrap_axis & GHOST_kGrabAxisY) { + const int height = WM_window_pixels_y(win); + const int min = height - grab_state->bounds[1]; + const int max = height - grab_state->bounds[3]; + if (min != max) { + event_xy[1] = mod_i(event_xy[1] - max, min - max) + max; + } + } + + GHOST_CursorBitmapRef bitmap = {0}; + if (GHOST_GetCursorBitmap(win->ghostwin, &bitmap) == GHOST_kSuccess) { + wm_software_cursor_draw_bitmap(event_xy, &bitmap); + } + else { + wm_software_cursor_draw_crosshair(event_xy); + } +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 330231f3f18..f77aad24719 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -338,10 +338,10 @@ void WM_init(bContext *C, int argc, const char **argv) if (!G.background) { if (wm_start_with_console) { - setConsoleWindowState(GHOST_kConsoleWindowStateShow); + GHOST_setConsoleWindowState(GHOST_kConsoleWindowStateShow); } else { - setConsoleWindowState(GHOST_kConsoleWindowStateHideForNonConsoleLaunch); + GHOST_setConsoleWindowState(GHOST_kConsoleWindowStateHideForNonConsoleLaunch); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 9f21e952850..33c69a23558 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2072,7 +2072,7 @@ static void WM_OT_quit_blender(wmOperatorType *ot) static int wm_console_toggle_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { - setConsoleWindowState(GHOST_kConsoleWindowStateToggle); + GHOST_setConsoleWindowState(GHOST_kConsoleWindowStateToggle); return OPERATOR_FINISHED; } diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index b3268cf1701..9c97b05f79b 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -212,7 +212,7 @@ static void playanim_gl_matrix(void) /* implementation */ static void playanim_event_qual_update(void) { - int val; + bool val; /* Shift */ GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftShift, &val); @@ -871,7 +871,7 @@ static void change_frame(PlayState *ps) ps->need_frame_update = false; } -static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) +static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) { PlayState *ps = (PlayState *)ps_void; const GHOST_TEventType type = GHOST_GetEventType(evt); @@ -902,7 +902,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) default: break; } - return 1; + return true; } if (ps->wait2 && ps->stopped == false) { @@ -1335,7 +1335,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) break; } - return 1; + return true; } static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey) @@ -1555,6 +1555,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) /* initialize the font */ BLF_init(); + BLF_load_font_stack(); ps.fontid = BLF_load_mono_default(false); BLF_size(ps.fontid, 11.0f, 72); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index ef609b740c5..91ec45da6d4 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -983,7 +983,7 @@ static int query_qual(modifierKeyType qual) break; } - int val = 0; + bool val = false; GHOST_GetModifierKeyState(g_system, left, &val); if (!val) { GHOST_GetModifierKeyState(g_system, right, &val); @@ -1053,7 +1053,7 @@ void wm_window_reset_drawable(void) * * Mouse coordinate conversion happens here. */ -static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr) +static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr) { bContext *C = C_void_ptr; wmWindowManager *wm = CTX_wm_manager(C); @@ -1091,17 +1091,17 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr * but it should return if WM didn't initialize yet. * Can happen on file read (especially full size window). */ if ((wm->initialized & WM_WINDOW_IS_INIT) == 0) { - return 1; + return true; } if (!ghostwin) { /* XXX: should be checked, why are we getting an event here, and what is it? */ puts("<!> event has no window"); - return 1; + return true; } if (!GHOST_ValidWindow(g_system, ghostwin)) { /* XXX: should be checked, why are we getting an event here, and what is it? */ puts("<!> event has invalid window"); - return 1; + return true; } wmWindow *win = GHOST_GetWindowUserData(ghostwin); @@ -1444,7 +1444,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } } } - return 1; + return true; } /** @@ -1872,11 +1872,10 @@ wmWindow *WM_window_find_under_cursor(wmWindow *win, const int mval[2], int r_mv return NULL; } - wmWindow *r_win = GHOST_GetWindowUserData(ghostwin); - wm_cursor_position_from_ghost(r_win, &tmp[0], &tmp[1]); + wmWindow *win_other = GHOST_GetWindowUserData(ghostwin); + wm_cursor_position_from_ghost(win_other, &tmp[0], &tmp[1]); copy_v2_v2_int(r_mval, tmp); - - return r_win; + return win_other; } void WM_window_pixel_sample_read(const wmWindowManager *wm, |