1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
|
/*
* Copyright (C) 2021 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2021 Vladimir Sadovnikov <sadko4u@gmail.com>
*
* This file is part of lsp-dsp-units
* Created on: 10 авг. 2021 г.
*
* lsp-dsp-units is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-dsp-units is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-dsp-units. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef LSP_PLUG_IN_DSP_UNITS_3D_RAYTRACE3D_H_
#define LSP_PLUG_IN_DSP_UNITS_3D_RAYTRACE3D_H_
#include <lsp-plug.in/dsp-units/version.h>
#include <lsp-plug.in/dsp-units/sampling/Sample.h>
#include <lsp-plug.in/dsp-units/3d/rt/types.h>
#include <lsp-plug.in/dsp-units/3d/rt/context.h>
#include <lsp-plug.in/dsp-units/3d/raytrace.h>
#include <lsp-plug.in/dsp/dsp.h>
#include <lsp-plug.in/common/status.h>
#include <lsp-plug.in/ipc/Thread.h>
#include <lsp-plug.in/ipc/Mutex.h>
#include <lsp-plug.in/lltl/parray.h>
#include <lsp-plug.in/lltl/darray.h>
namespace lsp
{
namespace dspu
{
/** Ray tracing storage implemented as a stack
*
*/
class LSP_DSP_UNITS_PUBLIC RayTrace3D
{
protected:
typedef struct sample_t
{
Sample *sample;
size_t channel;
ssize_t r_min;
ssize_t r_max;
} sample_t;
typedef struct rt_binding_t
{
lltl::darray<sample_t> bindings; // Capture bindings
} rt_binding_t;
typedef struct capture_t: public rt_capture_settings_t
{
dsp::vector3d_t direction; // Direction
dsp::bound_box3d_t bbox; // Bounding box
lltl::darray<rt::triangle_t> mesh; // Mesh associated with capture
lltl::darray<sample_t> bindings; // Capture bindings
} capture_t;
typedef struct rt_object_t
{
dsp::bound_box3d_t bbox;
lltl::darray<rtx::triangle_t> mesh;
lltl::darray<rtx::edge_t> plan;
} rt_object_t;
typedef struct stats_t
{
uint64_t root_tasks;
uint64_t local_tasks;
uint64_t calls_scan;
uint64_t calls_cull;
uint64_t calls_split;
uint64_t calls_cullback;
uint64_t calls_reflect;
uint64_t calls_capture;
} stats_t;
protected:
class TaskThread: public ipc::Thread
{
private:
RayTrace3D *trace;
stats_t stats;
lltl::parray<rt::context_t> tasks;
lltl::parray<rt_binding_t> bindings; // Bindings
lltl::parray<rt_object_t> objects;
ssize_t heavy_state;
protected:
status_t main_loop();
status_t process_context(rt::context_t *ctx);
status_t copy_objects(lltl::parray<rt_object_t> *src);
status_t scan_objects(rt::context_t *ctx);
status_t cull_view(rt::context_t *ctx);
status_t split_view(rt::context_t *ctx);
status_t cullback_view(rt::context_t *ctx);
status_t reflect_view(rt::context_t *ctx);
status_t capture(capture_t *capture, lltl::darray<sample_t> *bindings, const rt::view_t *v);
status_t generate_root_mesh();
status_t generate_capture_mesh(size_t id, capture_t *c);
status_t generate_object_mesh(ssize_t id, rt_object_t *o, rt::mesh_t *src, Object3D *obj, const dsp::matrix3d_t *m);
status_t generate_tasks(lltl::parray<rt::context_t> *tasks, float initial);
status_t check_object(rt::context_t *ctx, Object3D *obj, const dsp::matrix3d_t *m);
status_t submit_task(rt::context_t *ctx);
public:
explicit TaskThread(RayTrace3D *trace);
virtual ~TaskThread();
public:
status_t prepare_main_loop(float initial);
status_t prepare_captures();
status_t prepare_supplementary_loop(TaskThread *t);
virtual status_t run();
status_t merge_result();
inline stats_t *get_stats() { return &stats; }
};
private:
lltl::darray<rt::material_t> vMaterials;
lltl::darray<rt_source_settings_t> vSources;
lltl::parray<capture_t> vCaptures;
Scene3D *pScene;
rt::progress_func_t pProgress;
void *pProgressData;
size_t nSampleRate;
float fEnergyThresh;
float fTolerance;
float fDetalization;
bool bNormalize;
volatile bool bCancelled;
volatile bool bFailed;
lltl::parray<rt::context_t> vTasks;
size_t nQueueSize;
size_t nProgressPoints;
size_t nProgressMax;
ipc::Mutex lkTasks;
protected:
static void destroy_tasks(lltl::parray<rt::context_t> *tasks);
static void destroy_objects(lltl::parray<rt_object_t> *objects);
static void clear_stats(stats_t *stats);
static void dump_stats(const char *label, const stats_t *stats);
static void merge_stats(stats_t *dst, const stats_t *src);
static bool check_bound_box(const dsp::bound_box3d_t *bbox, const rt::view_t *view);
void remove_scene(bool destroy);
status_t resize_materials(size_t objects);
status_t report_progress(float progress);
// Main ray-tracing routines
void normalize_output();
bool is_already_passed(const sample_t *bind);
status_t do_process(size_t threads, float initial);
public:
/** Default constructor
*
*/
explicit RayTrace3D();
/** Destructor
*
*/
~RayTrace3D();
public:
/**
* Initialize raytrace object
*/
status_t init();
/** Destroy the ray tracing processor state
* @param recursive destroy the currently used scene object
*/
void destroy(bool recursive=false);
/**
* Set scene object
* @param scene scene object to set
* @param destroy destroy previously used scene
* @return status of operation
*/
status_t set_scene(Scene3D *scene, bool destroy=true);
/**
* Set/clear progress callback
* @param callback callback routine to report progress
* @param data data that will be passed to callback routine
* @return status of operation
*/
status_t set_progress_callback(rt::progress_func_t callback, void *data);
/**
* Clear progress callback
* @return status of operation
*/
status_t clear_progress_callback();
/**
* Set the material for the corresponding object
* @param idx the index of the material
* @return status of operation
*/
status_t set_material(size_t idx, const rt::material_t *material);
/**
* Get the material for the corresponding object
* @param material
* @param idx the index of the corresponding object
* @return pointer to material or NULL
*/
status_t get_material(rt::material_t *material, size_t idx);
/**
* Get the scene object
* @param idx scene object
* @return object pointer or NULL
*/
inline Object3D *object(size_t idx) { return (pScene != NULL) ? pScene->get_object(idx) : NULL; }
/**
* Set sample rate
* @param sr sample rate
*/
inline void set_sample_rate(size_t sr) { nSampleRate = sr; }
/**
* Get sample rate
* @return sample rate
*/
inline size_t get_sample_rate() const { return nSampleRate; }
/**
* Add audio source
* @param settings source settings
* @return status of operation
*/
status_t add_source(const rt_source_settings_t *settings);
/**
* Add audio capture
* @param settings capture settings
* @return non-negative capture identifier or negative error status code
*/
ssize_t add_capture(const rt_capture_settings_t *settings);
/**
* Bind audio sample to capture
* @param id capture identifier
* @param sample audio sample to bind
* @param channel number of channel of the sample that will be modified by capture
* @param r_min the minimum reflection index, negative value for any
* @param r_max the maximum reflection index, negative value for any
* @return status of operation
*/
status_t bind_capture(size_t id, Sample *sample, size_t channel, ssize_t r_min, ssize_t r_max);
/** Remove all audio sources
*
*/
inline void clear_sources() { vSources.flush(); };
/** Remove all audio captures
*
*/
inline void clear_captures() { vCaptures.flush(); };
inline float get_energy_threshold() const { return fEnergyThresh; }
void set_energy_threshold(float thresh) { fEnergyThresh = thresh; }
inline float get_tolerance() const { return fTolerance; }
inline float get_detalization() const { return fDetalization; }
void set_tolerance(float tolerance) { fTolerance = tolerance; }
void set_detalization(float detail) { fDetalization = detail; }
inline bool get_normalize() const { return bNormalize; };
inline void set_normalize(bool normalize) { bNormalize = normalize; };
/**
* This method indicates that the cancel request was sent to
* the processor, RT-safe method
* @return true if cancel request was sent to processor
*/
inline bool cancelled() const { return bCancelled; }
/**
* This method allows to cancel the execution of process() method by
* another thread, RT-safe method
*/
void cancel() { if (!bCancelled) bCancelled = true; }
/**
* Perform processing, non-RT-safe, should be launched in a thread
* @param threads number of threads used for processing
* @param initial initial energy of the signal
* @return status of operation
*/
status_t process(size_t threads, float initial);
};
} // namespace dspu
} // namespace lsp
#endif /* LSP_PLUG_IN_DSP_UNITS_3D_RAYTRACE3D_H_ */
|