• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NREL / SolTrace / 15616310463

12 Jun 2025 04:42PM UTC coverage: 61.112% (-1.4%) from 62.5%
15616310463

push

github

taylorbrown75
Make bounding box tests.

Move bounding box equations to dedicated namespace.

2 of 13 new or added lines in 1 file covered. (15.38%)

5 existing lines in 1 file now uncovered.

2813 of 4603 relevant lines covered (61.11%)

14477923.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.22
/coretrace/embree_helper.cpp
1
/*******************************************************************************************************
2
*  Copyright 2018 Alliance for Sustainable Energy, LLC
3
*
4
*  NOTICE: This software was developed at least in part by Alliance for Sustainable Energy, LLC
5
*  ("Alliance") under Contract No. DE-AC36-08GO28308 with the U.S. Department of Energy and the U.S.
6
*  The Government retains for itself and others acting on its behalf a nonexclusive, paid-up,
7
*  irrevocable worldwide license in the software to reproduce, prepare derivative works, distribute
8
*  copies to the public, perform publicly and display publicly, and to permit others to do so.
9
*
10
*  Redistribution and use in source and binary forms, with or without modification, are permitted
11
*  provided that the following conditions are met:
12
*
13
*  1. Redistributions of source code must retain the above copyright notice, the above government
14
*  rights notice, this list of conditions and the following disclaimer.
15
*
16
*  2. Redistributions in binary form must reproduce the above copyright notice, the above government
17
*  rights notice, this list of conditions and the following disclaimer in the documentation and/or
18
*  other materials provided with the distribution.
19
*
20
*  3. The entire corresponding source code of any redistribution, with or without modification, by a
21
*  research entity, including but not limited to any contracting manager/operator of a United States
22
*  National Laboratory, any institution of higher learning, and any non-profit organization, must be
23
*  made publicly available under this license for as long as the redistribution is made available by
24
*  the research entity.
25
*
26
*  4. Redistribution of this software, without modification, must refer to the software by the same
27
*  designation. Redistribution of a modified version of this software (i) may not refer to the modified
28
*  version by the same designation, or by any confusingly similar designation, and (ii) must refer to
29
*  the underlying software originally provided by Alliance as "SolTrace". Except to comply with the
30
*  foregoing, the term "SolTrace", or any confusingly similar designation may not be used to refer to
31
*  any modified version of this software or any modified version of the underlying software originally
32
*  provided by Alliance without the prior written consent of Alliance.
33
*
34
*  5. The name of the copyright holder, contributors, the United States Government, the United States
35
*  Department of Energy, or any of their employees may not be used to endorse or promote products
36
*  derived from this software without specific prior written permission.
37
*
38
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39
*  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
40
*  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER,
41
*  CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR
42
*  EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43
*  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
45
*  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
46
*  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
*******************************************************************************************************/
48

49
#include "embree_helper.h"
50
#include <stdio.h>
51
#include "procs.h"
52
#include <cctype>
53
#include <algorithm>
54
#include "bbox_calculator.h"
55

56
namespace embree_helper 
57
{
58

59
        inline void CopyVec3(double dest[3], double src[3])
532,203✔
60
        {
61
                dest[0] = src[0];
532,203✔
62
                dest[1] = src[1];
532,203✔
63
                dest[2] = src[2];
532,203✔
64
        }
532,203✔
65

66
        template<typename T>
67
        bool compare_Vec3(T vec1[3], T vec2[3], double tol_diff)
×
68
        {
69
                for (int i = 0; i < 3; i++)
×
70
                {
71
                        if ((std::abs(vec1[i] / vec2[i] - 1) > tol_diff)
×
72
                                && (std::abs(vec1[i] - vec2[i]) > 1e-5))
×
73
                                return false;
×
74
                }
75
                return true;
×
76
        }
77

78
        void error_function(void* userPtr, RTCError error, const char* str)
×
79
        {
80
                printf("error %d: %s\n", error, str);
×
81
        }
×
82

NEW
83
        int bounds_error(const RTCBoundsFunctionArguments* args, const bbox_calculator::BBOXERRORS error_enum)
×
84
        {
NEW
85
                char* str = "";
×
NEW
86
                switch (error_enum)
×
87
                {
NEW
88
                        case bbox_calculator::NONE:
×
NEW
89
                                str = "None";
×
UNCOV
90
                                break;
×
NEW
91
                        case bbox_calculator::BOUNDS_APERTURE_ERROR:
×
NEW
92
                                str = "Aperture bounds error";
×
UNCOV
93
                                break;
×
NEW
94
                        case bbox_calculator::BOUNDS_SURFACE_ERROR:
×
NEW
95
                                str = "Surface bounds error";
×
UNCOV
96
                                break;
×
UNCOV
97
                        default:
×
NEW
98
                                str = "Unknown error";
×
99
                                break;
×
100
                }
101

102
                // Set bounds to zero and report error
UNCOV
103
                RTCBounds* bounds_o = args->bounds_o;
×
104
                bounds_o->lower_x = std::numeric_limits<float>::quiet_NaN();
×
105
                bounds_o->upper_x = std::numeric_limits<float>::quiet_NaN();
×
106
                bounds_o->lower_y = std::numeric_limits<float>::quiet_NaN();
×
107
                bounds_o->upper_y = std::numeric_limits<float>::quiet_NaN();
×
108
                bounds_o->lower_z = std::numeric_limits<float>::quiet_NaN();
×
109
                bounds_o->upper_z = std::numeric_limits<float>::quiet_NaN();
×
110

111
                error_function(args->geometryUserPtr, RTC_ERROR_INVALID_OPERATION,
×
112
                        str);
113

114
                throw std::runtime_error("Embree scene commit failed");
×
115
        }
116

117
        void bounds_function(const RTCBoundsFunctionArguments* args)
20✔
118
        {
119
                // Get element
120
                TElement* st_element = (TElement*)args->geometryUserPtr;
20✔
121
                
122
                // Get bounds
123
                float min_coord_global[3];
124
                float max_coord_global[3];
125
                bbox_calculator::BBOXERRORS error = bbox_calculator::get_bounds(st_element, min_coord_global, max_coord_global);
20✔
126
                
127
                // Check error
128
                if (error != bbox_calculator::NONE)
20✔
129
                {
NEW
130
                        bounds_error(args, error);
×
131
                }
132

133
                // Assign bounds
134
                RTCBounds* bounds_o = args->bounds_o;
20✔
135
                bounds_o->lower_x = min_coord_global[0];
20✔
136
                bounds_o->upper_x = max_coord_global[0];
20✔
137
                bounds_o->lower_y = min_coord_global[1];
20✔
138
                bounds_o->upper_y = max_coord_global[1];
20✔
139
                bounds_o->lower_z = min_coord_global[2];
20✔
140
                bounds_o->upper_z = max_coord_global[2];
20✔
141
        }
20✔
142

143
        void intersect_function(const RTCIntersectFunctionNArguments* args)
110,939✔
144
        {
145
                // Retrieve ray data (GLOBAL coordinates, may NOT be normalized/unit)
146
                //const RTCRayHit* rayhit = (const RTCRayHit*)args->rayhit;
147
                //double PosRayGlob[3] = { rayhit->ray.org_x, rayhit->ray.org_y, rayhit->ray.org_z };
148
                //double CosRayGlob[3] = { rayhit->ray.dir_x, rayhit->ray.dir_y, rayhit->ray.dir_z };        // ASSUMING these are normalized (dangerous)
149

150
                // Get payload object
151
                RayIntersectPayload* payload = (RayIntersectPayload*)args->context;
110,939✔
152

153
                double PosRayGlob[3], CosRayGlob[3];
154
                CopyVec3(PosRayGlob, payload->PosRayGlobIn);
110,939✔
155
                CopyVec3(CosRayGlob, payload->CosRayGlobIn);
110,939✔
156

157
                // Get Element data
158
                TElement* st_element = (TElement*)args->geometryUserPtr;
110,939✔
159
                TStage* st_stage = (TStage*)st_element->parent_stage;
110,939✔
160
                
161

162
                // First, convert ray coordinates to element
163
                // Global -> stage -> element
164
                // transform the global incoming ray to local stage coordinates
165
                double PosRayStage[3], CosRayStage[3];
166
                ::TransformToLocal(PosRayGlob, CosRayGlob,
110,939✔
167
                        st_stage->Origin, st_stage->RRefToLoc,
110,939✔
168
                        PosRayStage, CosRayStage);
169

170
                //  {Transform ray to element[j] coord system of Stage[i]}
171
                double PosRayElement[3], CosRayElement[3];
172
                ::TransformToLocal(PosRayStage, CosRayStage,
110,939✔
173
                        st_element->Origin, st_element->RRefToLoc,
110,939✔
174
                        PosRayElement, CosRayElement);
175

176
                // increment position by tiny amount to get off the element if tracing to the same element
177
                PosRayElement[0] = PosRayElement[0] + 1.0e-4 * CosRayElement[0];
110,939✔
178
                PosRayElement[1] = PosRayElement[1] + 1.0e-4 * CosRayElement[1];
110,939✔
179
                PosRayElement[2] = PosRayElement[2] + 1.0e-4 * CosRayElement[2];
110,939✔
180

181
                // Call DeterminElementIntersectionNew
182
                double PosRaySurfElement[3] = { 0.0, 0.0, 0.0 };
110,939✔
183
                double CosRaySurfElement[3] = { 0.0, 0.0, 0.0 };
110,939✔
184
                double DFXYZ[3] = { 0.0, 0.0, 0.0 };
110,939✔
185
                double PathLength = 0;
110,939✔
186

187
                int InterceptFlag = 0;
110,939✔
188
                int HitBackSide = 0;
110,939✔
189
                ::DetermineElementIntersectionNew(st_element, PosRayElement, CosRayElement,
110,939✔
190
                        PosRaySurfElement, CosRaySurfElement, DFXYZ,
191
                        &PathLength, &payload->ErrorFlag, &InterceptFlag, &HitBackSide);
192

193
                // Update rayhit info (if hit)
194
                if (InterceptFlag != 0)
110,939✔
195
                {
196
                        // Get rayhit data
197
                        RTCRayHit* rayhit_out = (RTCRayHit*)args->rayhit;
62,216✔
198

199
                        // Check if hit is closer than other hits
200
                        // Using payload pathlength for double precision
201
                        // If pathlength == lastpathlength, use which element number is lower
202
                        // to match results with original code
203
                        if ((PathLength < payload->LastPathLength) 
62,216✔
204
                                || ((PathLength == payload->LastPathLength) 
24✔
205
                                        && (st_element->element_number < payload->element_number)))
×
206
                        {
207

208
                                if (PosRaySurfElement[2] <= st_element->ZAperture
62,192✔
209
                                        || st_element->SurfaceIndex == 'm'
128✔
210
                                        || st_element->SurfaceIndex == 'M'
127✔
211
                                        || st_element->SurfaceIndex == 'r'
127✔
212
                                        || st_element->SurfaceIndex == 'R')
127✔
213
                                {
214

215
                                        // Transform ray back to stage coordinate system
216
                                        double PosRaySurfStage[3] = { 0.0, 0.0, 0.0 };
62,065✔
217
                                        double CosRaySurfStage[3] = { 0.0, 0.0, 0.0 };
62,065✔
218
                                        ::TransformToReference(PosRaySurfElement, CosRaySurfElement,
62,065✔
219
                                                st_element->Origin, st_element->RLocToRef,
62,065✔
220
                                                PosRaySurfStage, CosRaySurfStage);
221

222
                                        rayhit_out->ray.tfar = (float)PathLength; // Update intersection distance
62,065✔
223
                                        rayhit_out->hit.geomID = args->geomID;
62,065✔
224
                                        rayhit_out->hit.primID = 0; // Single primitive
62,065✔
225

226
                                        // Define Ng (will not be used)
227
                                        rayhit_out->hit.Ng_x = std::numeric_limits<float>::quiet_NaN();
62,065✔
228
                                        rayhit_out->hit.Ng_y = std::numeric_limits<float>::quiet_NaN();
62,065✔
229
                                        rayhit_out->hit.Ng_z = std::numeric_limits<float>::quiet_NaN();
62,065✔
230

231
                                        // Assign custom outputs
232
                                        payload->LastHitBackSide = HitBackSide;
62,065✔
233
                                        CopyVec3(payload->LastDFXYZ, DFXYZ);
62,065✔
234
                                        //CopyVec3(payload->LastPosRaySurfGlob, PosRaySurfGlob);
235
                                        //CopyVec3(payload->LastCosRaySurfGlob, CosRaySurfGlob);
236
                                        CopyVec3(payload->LastPosRaySurfStage, PosRaySurfStage);
62,065✔
237
                                        CopyVec3(payload->LastCosRaySurfStage, CosRaySurfStage);
62,065✔
238
                                        CopyVec3(payload->LastPosRaySurfElement, PosRaySurfElement);
62,065✔
239
                                        CopyVec3(payload->LastCosRaySurfElement, CosRaySurfElement);
62,065✔
240
                                        payload->element_number = st_element->element_number;
62,065✔
241
                                        payload->LastPathLength = PathLength;
62,065✔
242

243
                                }
244
                        }
245
                        
246
                }
247
                else
248
                {
249
                        return;
48,723✔
250
                }
251
        }
252

253
        RTCScene make_scene(RTCDevice& device, TSystem& system)
3✔
254
        {
255
                // Make scene
256
                RTCScene scene = rtcNewScene(device);
3✔
257

258
                // Loop through stages
259
                unsigned int stage_index = 1;
3✔
260
                for (TStage* stage : system.StageList)
8✔
261
                {
262
                        // Loop through elements in each stage
263
                        int j = 0;
5✔
264
                        unsigned int stage_mask = 1u << stage_index;
5✔
265
                        for (TElement* st_element : stage->ElementList)
28✔
266
                        {
267
                                // Skip if not enabled
268
                                if (st_element->Enabled == false)
23✔
269
                                {
270
                                        j++;
3✔
271
                                        continue;
3✔
272
                                }
273

274
                                // Add ptr to parent stage to st_element
275
                                st_element->parent_stage = stage;
20✔
276
                                st_element->element_number = j + 1;
20✔
277
                                st_element->embree_mask = stage_mask;
20✔
278

279
                                // Make embree geometry for each element
280
                                RTCGeometry embree_geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_USER);
20✔
281
                                rtcSetGeometryUserPrimitiveCount(embree_geom, 1);
20✔
282

283
                                // Attach st element to embree geometry
284
                                rtcSetGeometryUserData(embree_geom, st_element);
20✔
285

286
                                // Assign bounds function
287
                                rtcSetGeometryBoundsFunction(embree_geom, bounds_function, NULL);
20✔
288

289
                                // Assign intersect function
290
                                rtcSetGeometryIntersectFunction(embree_geom, intersect_function);
20✔
291

292
                                // Set mask (stage number)
293
                                rtcSetGeometryMask(embree_geom, stage_mask);
20✔
294

295
                                // Commit geometry
296
                                rtcCommitGeometry(embree_geom);
20✔
297

298
                                // Attach geometry
299
                                unsigned int geomID = rtcAttachGeometry(scene, embree_geom);
20✔
300

301
                                // Release geometry (it is owned by the scene now)
302
                                rtcReleaseGeometry(embree_geom);
20✔
303

304
                                j++;
20✔
305
                        }
306

307
                        stage_index++;
5✔
308
                }
309

310
                return scene;
3✔
311
        }
312

313
        bool validate_intersect(double(&LastPosRaySurfElement1)[3], double(&LastCosRaySurfElement1)[3], double(&LastDFXYZ1)[3],
×
314
                st_uint_t& LastElementNumber1, st_uint_t& LastRayNumber1,
315
                double(&LastPosRaySurfStage1)[3], double(&LastCosRaySurfStage1)[3],
316
                int& ErrorFlag1, int& LastHitBackSide1,
317
                bool& StageHit1,
318

319
                double(&LastPosRaySurfElement2)[3], double(&LastCosRaySurfElement2)[3], double(&LastDFXYZ2)[3],
320
                st_uint_t& LastElementNumber2, st_uint_t& LastRayNumber2,
321
                double(&LastPosRaySurfStage2)[3], double(&LastCosRaySurfStage2)[3],
322
                int& ErrorFlag2, int& LastHitBackSide2,
323
                bool& StageHit2)
324
        {
325
                if (StageHit1 == false && StageHit2 == false)
×
326
                        return true;
×
327

328
                double tol_diff = 1e-4;
×
329
                if (StageHit1 != StageHit2) return false;
×
330
                if (LastElementNumber1 != LastElementNumber2) return false;
×
331
                if (LastHitBackSide1 != LastHitBackSide2) return false;
×
332
                if (!compare_Vec3(LastPosRaySurfElement1, LastPosRaySurfElement2, tol_diff)) return false;
×
333
                if (!compare_Vec3(LastCosRaySurfElement1, LastCosRaySurfElement2, tol_diff)) return false;
×
334
                if (!compare_Vec3(LastDFXYZ1, LastDFXYZ2, tol_diff)) return false;
×
335
                if (!compare_Vec3(LastPosRaySurfStage1, LastPosRaySurfStage2, tol_diff)) return false;
×
336
                if (!compare_Vec3(LastCosRaySurfStage1, LastCosRaySurfStage2, tol_diff)) return false;
×
337

338
                return true;
×
339
        }
340

341
}        // namespace embree_helper
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc