Skip to content

Commit c28724b

Browse files
committed
[1.3.58] 2025-11-28
## Core - Added materials to avoid duplicating surface-level data. This Phase 1 implementation focused only on the primitive/object color or texture. - Added `WarningAggregator` class, a thread-safe utility for aggregating repetitive warnings to prevent console flooding when processing large numbers of primitives. Used throughout core functions like `fzero()`, `incrementPrimitiveData()`, and `rotatePrimitive()` to collect and report warning summaries instead of per-iteration messages. ## Plant Architecture - Users can now configure canopy-level plant parameters, such as trellis dimensions, number of tree scaffolds, etc. - Added support for "all" keyword in `optionalOutputObjectData()` to enable all optional output data fields simultaneously (case-insensitive). Invalid data labels now throw `helios_runtime_error` instead of printing warnings. ## Radiation - Added camera library with pre-configured real-world cameras including intrinsic parameters and manufacturer-measured spectral response curves. Library includes Canon EOS 20D, Nikon D700, Nikon D50, Apple iPhone 11, and Apple iPhone 12 Pro Max with full spectral response data for RGB channels. - Added `addRadiationCameraFromLibrary()` method to create cameras directly from library entries, automatically loading all camera properties, spectral responses, and creating radiation bands if needed. Supports custom band name mapping. - Enhanced camera metadata with lens properties (make, model, specification), exposure settings (mode, shutter speed), white balance mode, and agronomic properties (plant species, counts, heights, phenological stages, leaf area). Metadata now includes image_processing parameters when `applyCameraImageCorrections()` is applied. - Added `updateCameraParameters()` and `getCameraParameters()` methods for runtime modification and retrieval of camera intrinsic parameters. - Added automatic exposure and white balance application during rendering based on camera settings. New `applyCameraExposure()` and `applyCameraWhiteBalance()` methods are called automatically. Supports "auto", "manual", and ISO-based exposure modes (e.g., "ISO100") calibrated to match auto-exposure at reference settings. - Enhanced metadata API with `enableCameraMetadata()` and `getCameraMetadata()` methods for better control over automatic JSON metadata export alongside camera images. - Renamed `applyImageProcessingPipeline()` to `applyCameraImageCorrections()` for clarity. Old method is deprecated but still functional for backward compatibility. - Fixed camera ray generation pixel coordinate calculations when using camera tiling. Now correctly computes global pixel coordinates using `camera_pixel_offset_x`, `camera_pixel_offset_y`, and `camera_resolution_full` variables in OptiX kernel. ## Stomatal Conductance - Model parameters can now be set on a per-material basis ## Photosynthesis - Model parameters can now be set on a per-material basis - `twosided_flag` is now managed as part of materials ## Boundary-layer Conductance - `twosided_flag` is now managed as part of materials ## Visualizer - Fix to a visualizer test that was causing a segmentation fault when tests are run in non-headless mode ## Solar Position - Implemented SSolar-SOA model to predict full solar spectrum as a function of atmospheric conditions # [1.3.57] 2025-11-18 ## Radiation - **NEW FEATURE:** Integrated Prague Sky Model for physically-based atmospheric sky radiance in camera rendering. When camera "miss" rays don't hit any geometry, sky radiance is now computed using the advanced atmospheric physics model from Wilkie et al. (ACM SIGGRAPH 2021, CGF 2022) based on Rayleigh and Mie scattering. - Prague Sky Model data file (27 MB) and Apache 2.0 license added to `plugins/radiation/spectral_data/prague_sky_model/` ## Solar Position - Clarified turbidity parameter documentation across all methods to explicitly state it represents Ångström's aerosol turbidity coefficient (β), which is aerosol optical depth (AOD) at 500 nm wavelength - Updated documentation for `setAtmosphericConditions()`, `getAtmosphericConditions()`, `getSolarFlux()`, `getSolarFluxPAR()`, `getSolarFluxNIR()`, and `getDiffuseFraction()` to include typical turbidity values and clarify the difference from Linke turbidity. ## Leaf Optics - Added built-in species library with pre-configured optical properties for common plant species to simplify model usage and eliminate the need to manually specify PROSPECT-D biochemical parameters - Added `LeafOptics::getPropertiesFromLibrary()` method to populate `LeafOpticsProperties` structures with species-specific PROSPECT-D parameters. The method accepts case-insensitive species names (e.g., "corn", "CORN", "Corn" are equivalent) and gracefully falls back to default values with a warning if an unknown species is provided. - Species library includes 11 species fitted to LOPEX93 spectral library samples using robust optimization: default (original Helios defaults), garden_lettuce, alfalfa, corn, sunflower, english_walnut, rice, soybean, wine_grape, tomato, common_bean (from GEMINI field experiments), and cowpea (from GEMINI field experiments) - All species use PROSPECT-D mode with fitted parameters for numberlayers (N), chlorophyllcontent (Cab), carotenoidcontent (Car), anthocyancontent (Ant), brownpigments (Cbrown), watermass (Cw), and drymass (Cm) ## Plant Architecture - Added `PlantArchitecture::determinePhenologyStage()` method to determine if a plant is in dormant, vegetative, reproductive, or senescent phenological stage based on the presence and state of floral buds and leaf senescence - Added optional object data output fields for improved plant identification and analysis: `plant_name` (string), `plant_height` (float), `plant_type` (string: "herbaceous", "deciduous", or "evergreen"), and `phenology_stage` (string: "dormant", "vegetative", "reproductive", or "senescent") - Plant type classification (herbaceous, deciduous, evergreen) is now tracked internally via `plant_type_map` and automatically set during plant model registration, enabling proper phenological stage determination and classification - Fixed bug when generating plant from XML, caused by not re-generating prototype models ## Visualizer - Fixed bug where navigation gizmo would not reappear after calling `Visualizer::displayImage()` followed by `Visualizer::buildContextGeometry()`. The gizmo's enabled state is now tracked and properly restored when building geometry.
1 parent 2924dda commit c28724b

66 files changed

Lines changed: 13793 additions & 711 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/include/Context.h

Lines changed: 773 additions & 8 deletions
Large diffs are not rendered by default.

core/include/global.h

Lines changed: 80 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,6 @@
1616
#ifndef HELIOS_GLOBAL
1717
#define HELIOS_GLOBAL
1818

19-
//! Macro for marking functions as deprecated with optional custom message.
20-
// MSVC requires __declspec to come BEFORE the function declaration
21-
#if __cplusplus >= 201402L && defined(__has_cpp_attribute) && __has_cpp_attribute(deprecated)
22-
#define DEPRECATED_MSG(msg, func) [[deprecated(msg)]] func
23-
#define DEPRECATED_NOMSG(func) [[deprecated]] func
24-
#elif defined(__GNUC__) || defined(__clang__)
25-
#define DEPRECATED_MSG(msg, func) func __attribute__((deprecated(msg)))
26-
#define DEPRECATED_NOMSG(func) func __attribute__((deprecated))
27-
#elif defined(_MSC_VER)
28-
// MSVC has issues with custom deprecation messages, use simple deprecation
29-
#define DEPRECATED_MSG(msg, func) __declspec(deprecated) func
30-
#define DEPRECATED_NOMSG(func) __declspec(deprecated) func
31-
#else
32-
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
33-
#define DEPRECATED_MSG(msg, func) func
34-
#define DEPRECATED_NOMSG(func) func
35-
#endif
36-
37-
// Helper macro to count arguments
38-
#define GET_ARG_COUNT(...) GET_ARG_COUNT_IMPL(__VA_ARGS__, 2, 1)
39-
#define GET_ARG_COUNT_IMPL(_1, _2, N, ...) N
40-
41-
// Main DEPRECATED macro that dispatches based on argument count with corrected parameter order
42-
#define DEPRECATED(...) GET_DEPRECATED_MACRO(__VA_ARGS__)(__VA_ARGS__)
43-
#define GET_DEPRECATED_MACRO(...) GET_DEPRECATED_MACRO_IMPL(GET_ARG_COUNT(__VA_ARGS__))
44-
#define GET_DEPRECATED_MACRO_IMPL(count) GET_DEPRECATED_MACRO_IMPL2(count)
45-
#define GET_DEPRECATED_MACRO_IMPL2(count) DEPRECATED_##count##_ARGS
46-
47-
#define DEPRECATED_1_ARGS(func) DEPRECATED_NOMSG(func)
48-
#define DEPRECATED_2_ARGS(func, msg) DEPRECATED_MSG(msg, func)
49-
5019
//! Pi constant.
5120
#ifndef M_PI
5221
#define M_PI 3.14159265358979323846
@@ -102,6 +71,9 @@ constexpr To scast(From &&v) noexcept {
10271
// Standard library for file path resolution
10372
#include <filesystem>
10473

74+
// Thread synchronization
75+
#include <mutex>
76+
10577
// *** Groups *** //
10678

10779
//! Miscellaneous helper functions
@@ -1043,6 +1015,9 @@ namespace helios {
10431015
*/
10441016
[[nodiscard]] helios::RGBAcolor XMLloadrgba(pugi::xml_node node, const char *field);
10451017

1018+
// Forward declaration for fzero()
1019+
class WarningAggregator;
1020+
10461021
//! Use Newton-Raphson method to find the zero of a function
10471022
/**
10481023
* \param[in] function Function to be evaluated. The function should take as its first argument the value at which the function should be evaluated, as second argument any function arguments.
@@ -1051,8 +1026,9 @@ namespace helios {
10511026
* \param[in] init_guess Initial guess for the zero of the function.
10521027
* \param[in] err_tol [optional] Maximum allowable relative error in solution.
10531028
* \param[in] max_iterations [optional] Maximum number of iterations to allow before exiting solver.
1029+
* \param[in] warnings [optional] Pointer to WarningAggregator for collecting convergence warnings. If nullptr, warnings are not collected.
10541030
*/
1055-
[[nodiscard]] float fzero(float (*function)(float value, std::vector<float> &variables, const void *parameters), std::vector<float> &variables, const void *parameters, float init_guess, float err_tol = 0.0001f, int max_iterations = 100);
1031+
[[nodiscard]] float fzero(float (*function)(float value, std::vector<float> &variables, const void *parameters), std::vector<float> &variables, const void *parameters, float init_guess, float err_tol = 0.0001f, int max_iterations = 100, WarningAggregator* warnings = nullptr);
10561032

10571033
//! Use Newton-Raphson method to find the zero of a function with convergence status
10581034
/**
@@ -1411,6 +1387,78 @@ namespace helios {
14111387
};
14121388

14131389

1390+
//! Warning message aggregator for reducing console flooding
1391+
/**
1392+
* \brief Accumulates warning messages during loops/iterations and reports aggregated summaries.
1393+
*
1394+
* This class helps prevent console flooding when processing millions of primitives/objects
1395+
* by collecting warnings and reporting counts with example messages instead of printing
1396+
* each warning individually. Thread-safe for use in OpenMP parallel regions.
1397+
*
1398+
* Example usage:
1399+
* \code{.cpp}
1400+
* WarningAggregator warnings;
1401+
* for(uint UUID : UUIDs) {
1402+
* if(someCondition) {
1403+
* warnings.addWarning("category_name", "Warning message here");
1404+
* }
1405+
* }
1406+
* warnings.report(std::cerr); // Prints aggregated summary
1407+
* \endcode
1408+
*
1409+
* \ingroup functions
1410+
*/
1411+
class WarningAggregator {
1412+
public:
1413+
//! Constructor
1414+
WarningAggregator() = default;
1415+
1416+
//! Add a warning to be aggregated
1417+
/**
1418+
* \param[in] category Category identifier for this warning type (e.g., "fzero_convergence_failure")
1419+
* \param[in] message The warning message text
1420+
* \note Thread-safe: can be called from OpenMP parallel regions
1421+
*/
1422+
void addWarning(const std::string &category, const std::string &message);
1423+
1424+
//! Report all accumulated warnings and clear
1425+
/**
1426+
* \param[in] stream Output stream to write warnings to (default: std::cerr)
1427+
* \note Outputs format: "WARNING: N instances of 'category' (showing first 3):"
1428+
*/
1429+
void report(std::ostream &stream = std::cerr);
1430+
1431+
//! Get the count of warnings for a specific category
1432+
/**
1433+
* \param[in] category Category identifier
1434+
* \return Number of warnings accumulated for this category
1435+
*/
1436+
[[nodiscard]] size_t getCount(const std::string &category) const;
1437+
1438+
//! Clear all accumulated warnings
1439+
void clear();
1440+
1441+
//! Enable or disable warning accumulation
1442+
/**
1443+
* \param[in] enabled True to enable, false to disable
1444+
* \note When disabled, calls to addWarning() are ignored
1445+
*/
1446+
void setEnabled(bool enabled);
1447+
1448+
//! Check if warning accumulation is enabled
1449+
/**
1450+
* \return True if enabled, false otherwise
1451+
*/
1452+
[[nodiscard]] bool isEnabled() const;
1453+
1454+
private:
1455+
mutable std::mutex mutex_; //!< Thread safety for OpenMP
1456+
std::unordered_map<std::string, std::vector<std::string>> warnings_; //!< Storage: category -> messages
1457+
std::unordered_map<std::string, size_t> counts_; //!< Total count per category (may exceed stored messages)
1458+
bool enabled_ = true; //!< Whether to accumulate warnings
1459+
static constexpr size_t MAX_EXAMPLES = 100; //!< Maximum examples to store per category
1460+
};
1461+
14141462
//! Default null SphericalCoord that applies no rotation
14151463
extern SphericalCoord nullrotation;
14161464
//! Default null vec3 that gives the origin (0,0,0)

0 commit comments

Comments
 (0)