File indexing completed on 2026-04-09 07:48:55
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #if defined(__CUDACC__) || defined(__CUDABE__)
0013 # define TREE_FUNC __forceinline__ __device__
0014 #else
0015 # define TREE_FUNC inline
0016 #endif
0017
0018 #if defined(__CUDACC__) || defined(__CUDABE__)
0019 #include <stdio.h>
0020 #else
0021 #include <cmath> // signbit
0022 using std::signbit ;
0023 #endif
0024
0025 #include "sflow.h"
0026 #include "csg_error.h"
0027 #include "csg_tranche.h"
0028 #include "csg_stack.h"
0029 #include "csg_postorder.h"
0030 #include "csg_pack.h"
0031 #include "csg_classify.h"
0032
0033 #include "f4_stack.h"
0034
0035 #ifdef DEBUG_RECORD
0036 #include "sc4u.h"
0037 #include "sbibit.h"
0038 #include "sbit_.h"
0039 #endif
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 TREE_FUNC
0072 float distance_tree( const float3& global_position, const CSGNode* node, const float4* plan0, const qat4* itra0 )
0073 {
0074 const int numNode = node->subNum();
0075 unsigned height = TREE_HEIGHT(numNode) ;
0076
0077
0078 unsigned beginIdx = 1 << height ;
0079 unsigned endIdx = 0 ;
0080 unsigned nodeIdx = beginIdx ;
0081
0082 F4_Stack stack = {} ;
0083 stack.curr = -1 ;
0084 float distance = 0.f ;
0085
0086 while( nodeIdx != endIdx )
0087 {
0088 unsigned depth = TREE_DEPTH(nodeIdx) ;
0089 unsigned elevation = height - depth ;
0090
0091 const CSGNode* nd = node + nodeIdx - 1 ;
0092 OpticksCSG_t typecode = (OpticksCSG_t)nd->typecode() ;
0093
0094 if( typecode == CSG_ZERO )
0095 {
0096 nodeIdx = POSTORDER_NEXT( nodeIdx, elevation ) ;
0097 continue ;
0098 }
0099
0100 bool node_or_leaf = typecode >= CSG_NODE ;
0101 if( node_or_leaf )
0102 {
0103
0104 distance = distance_node(global_position, nd, node, plan0, itra0 ) ;
0105 stack.push(distance) ;
0106 }
0107 else
0108 {
0109 float lhs(0.f) ;
0110 float rhs(0.f) ;
0111 stack.pop2( lhs, rhs );
0112
0113 switch( typecode )
0114 {
0115 case CSG_UNION: distance = fminf( lhs, rhs ) ; break ;
0116 case CSG_INTERSECTION: distance = fmaxf( lhs, rhs ) ; break ;
0117 case CSG_DIFFERENCE: distance = fmaxf( lhs, -rhs ) ; break ;
0118 default: distance = 0.f ; break ;
0119 }
0120 stack.push(distance) ;
0121 }
0122 nodeIdx = POSTORDER_NEXT( nodeIdx, elevation ) ;
0123 }
0124 stack.pop(distance);
0125 return distance ;
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 TREE_FUNC
0138 float distance_list( const float3& global_position, const CSGNode* node, const float4* plan0, const qat4* itra0 )
0139 {
0140 const int numNode = node->subNum() ;
0141 float distance = RT_DEFAULT_MAX ;
0142 for(int nodeIdx=1 ; nodeIdx < numNode ; nodeIdx++)
0143 {
0144 const CSGNode* nd = node + nodeIdx ;
0145 float sd = distance_node(global_position, nd, node, plan0, itra0 ) ;
0146 distance = fminf( distance, sd ) ;
0147 }
0148 return distance ;
0149 }
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276 TREE_FUNC
0277 void intersect_tree( bool& valid_isect, float4& isect, const CSGNode* node, const float4* plan0, const qat4* itra0, const float t_min , const float3& ray_origin, const float3& ray_direction, bool dumpxyz )
0278 {
0279 const int numNode=node->subNum() ;
0280 unsigned height = TREE_HEIGHT(numNode) ;
0281 float propagate_epsilon = 0.0001f ;
0282 int ierr = 0 ;
0283
0284 LUT lut ;
0285 Tranche tr ;
0286 tr.curr = -1 ;
0287
0288 unsigned fullTree = PACK4(0,0, 1 << height, 0 ) ;
0289
0290 #ifdef DEBUG
0291 printf("//intersect_tree numNode(subNum) %d height %d fullTree(hex) %x \n", numNode, height, fullTree );
0292 assert( numNode > 0 );
0293 #endif
0294
0295 #ifdef DEBUG_PIDXYZ
0296
0297 #endif
0298
0299
0300
0301
0302 tranche_push( tr, fullTree, t_min );
0303
0304 CSG_Stack csg ;
0305 csg.curr = -1 ;
0306 #ifdef DEBUG_RECORD
0307 int tloop = -1 ;
0308 #endif
0309
0310 while (tr.curr > -1)
0311 {
0312 #ifdef DEBUG_RECORD
0313 tloop++ ;
0314 #endif
0315 unsigned slice ;
0316 float tmin ;
0317
0318 ierr = tranche_pop(tr, slice, tmin );
0319 if(ierr) break ;
0320
0321
0322 unsigned beginIdx = UNPACK4_2(slice);
0323 unsigned endIdx = UNPACK4_3(slice);
0324
0325 #ifdef DEBUG_RECORD
0326 if(CSGRecord::ENABLED)
0327 printf("// tranche_pop : tloop %d tmin %10.4f beginIdx %d endIdx %d tr.curr %d csg.curr %d \n", tloop, tmin, beginIdx, endIdx, tr.curr, csg.curr );
0328 assert( ierr == 0 );
0329 #endif
0330
0331 unsigned nodeIdx = beginIdx ;
0332 while( nodeIdx != endIdx )
0333 {
0334 unsigned depth = TREE_DEPTH(nodeIdx) ;
0335 unsigned elevation = height - depth ;
0336
0337 const CSGNode* nd = node + nodeIdx - 1 ;
0338 OpticksCSG_t typecode = (OpticksCSG_t)nd->typecode() ;
0339 #ifdef DEBUG
0340 printf("//intersect_tree nodeIdx %d CSG::Name %10s depth %d elevation %d \n", nodeIdx, CSG::Name(typecode), depth, elevation );
0341 #endif
0342 #ifdef DEBUG_PIDXYZ
0343
0344 #endif
0345
0346 if( typecode == CSG_ZERO )
0347 {
0348 nodeIdx = POSTORDER_NEXT( nodeIdx, elevation ) ;
0349 continue ;
0350 }
0351 bool node_or_leaf = typecode >= CSG_NODE ;
0352 #ifdef DEBUG_PIDXYZ
0353
0354 #endif
0355
0356 if(node_or_leaf)
0357 {
0358 float4 nd_isect = make_float4(0.f, 0.f, 0.f, 0.f) ;
0359
0360 bool nd_valid_isect(false);
0361 intersect_node( nd_valid_isect, nd_isect, nd, node, plan0, itra0, tmin, ray_origin, ray_direction, dumpxyz );
0362
0363
0364 #ifdef DEBUG_PIDXYZ
0365
0366 #endif
0367
0368
0369 nd_isect.w = copysignf( nd_isect.w, nodeIdx % 2 == 0 ? -1.f : 1.f );
0370
0371 #ifdef DEBUG_PIDXYZ
0372
0373 #endif
0374 ierr = csg_push(csg, nd_isect, nodeIdx );
0375
0376
0377 #ifdef DEBUG_RECORD
0378 assert( ierr == 0 );
0379 #endif
0380 if(ierr) break ;
0381 }
0382 else
0383 {
0384 if(csg.curr < 1)
0385 {
0386 #ifdef DEBUG
0387 printf("//intersect_tree ERROR_POP_EMPTY nodeIdx %4d typecode %d csg.curr %d \n", nodeIdx, typecode, csg.curr );
0388 #endif
0389 ierr |= ERROR_POP_EMPTY ;
0390 break ;
0391 }
0392
0393
0394
0395 bool firstLeft = signbit(csg.data[csg.curr].w) ;
0396 bool secondLeft = signbit(csg.data[csg.curr-1].w) ;
0397
0398 #ifdef DEBUG_PIDXYZ
0399
0400 #endif
0401
0402
0403 if(!(firstLeft ^ secondLeft))
0404 {
0405 #ifdef DEBUG
0406 printf("//intersect_tree ERROR_XOR_SIDE nodeIdx %4d typecode %d tl %10.3f tr %10.3f sl %d sr %d \n",
0407 nodeIdx, typecode, csg.data[csg.curr].w, csg.data[csg.curr-1].w, firstLeft, secondLeft );
0408 #endif
0409 ierr |= ERROR_XOR_SIDE ;
0410 break ;
0411 }
0412 int left = firstLeft ? csg.curr : csg.curr-1 ;
0413 int right = firstLeft ? csg.curr-1 : csg.curr ;
0414
0415 IntersectionState_t l_state = CSG_CLASSIFY( csg.data[left], ray_direction, tmin );
0416 IntersectionState_t r_state = CSG_CLASSIFY( csg.data[right], ray_direction, tmin );
0417
0418 float t_left = fabsf( csg.data[left].w );
0419 float t_right = fabsf( csg.data[right].w );
0420
0421 bool leftIsCloser = t_left <= t_right ;
0422
0423 #ifdef DEBUG_PIDXYZ
0424
0425
0426 #endif
0427
0428 #ifdef DEBUG_COS
0429 {
0430
0431 float l_cos = csg.data[left].x*ray_direction.x + csg.data[left].y*ray_direction.y + csg.data[left].z*ray_direction.z ;
0432 float r_cos = csg.data[right].x*ray_direction.x + csg.data[right].y*ray_direction.y + csg.data[right].z*ray_direction.z ;
0433
0434 printf("\n//intersect_tree nodeIdx %3d t_left %10.4f t_right %10.4f leftIsCloser %d l_state %5s r_state %5s l_cos*1e6f %10.4f r_cos*1e6f %10.4f \n",
0435 nodeIdx, t_left, t_right, leftIsCloser,
0436 IntersectionState::Name(l_state),
0437 IntersectionState::Name(r_state),
0438 l_cos*1e6f,
0439 r_cos*1e6f
0440 );
0441
0442 }
0443 #endif
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455 bool l_complement = signbit(csg.data[left].x) ;
0456 bool r_complement = signbit(csg.data[right].x) ;
0457
0458
0459 bool l_unbounded = signbit(csg.data[left].y) ;
0460 bool r_unbounded = signbit(csg.data[right].y) ;
0461
0462 bool l_promote_miss = l_state == State_Miss && ( l_complement || l_unbounded ) ;
0463 bool r_promote_miss = r_state == State_Miss && ( r_complement || r_unbounded ) ;
0464
0465 #ifdef DEBUG_PIDXYZ
0466
0467
0468 #endif
0469
0470 if(r_promote_miss)
0471 {
0472 #ifdef DEBUG_RECORD
0473 if(CSGRecord::ENABLED)
0474 {
0475 printf("// %3d : r_promote_miss setting leftIsCloser %d to true and r_state %5s to Exit \n",
0476 nodeIdx, leftIsCloser, IntersectionState::Name(l_state) );
0477 }
0478 #endif
0479 r_state = State_Exit ;
0480 leftIsCloser = true ;
0481 }
0482
0483 if(l_promote_miss)
0484 {
0485 #ifdef DEBUG_RECORD
0486 if(CSGRecord::ENABLED)
0487 {
0488 printf("// %3d : l_promote_miss setting leftIsCloser %d to false and l_state %5s to Exit \n",
0489 nodeIdx, leftIsCloser, IntersectionState::Name(r_state) );
0490 }
0491 #endif
0492 l_state = State_Exit ;
0493 leftIsCloser = false ;
0494 }
0495
0496 int ctrl = lut.lookup( typecode , l_state, r_state, leftIsCloser ) ;
0497
0498 #ifdef DEBUG
0499 printf("// %3d : stack peeking : left %d right %d (stackIdx) %15s l:%5s %10.4f r:%5s %10.4f leftIsCloser %d -> %s \n",
0500 nodeIdx,left,right,
0501 CSG::Name(typecode),
0502 IntersectionState::Name(l_state), t_left,
0503 IntersectionState::Name(r_state), t_right,
0504 leftIsCloser,
0505 CTRL::Name(ctrl) );
0506 #endif
0507
0508
0509 #ifdef DEBUG_RECORD
0510 if(CSGRecord::ENABLED)
0511 {
0512 printf("// %3d CSG decision : left %d right %d (stackIdx) %15s l:%5s %10.4f r:%5s %10.4f leftIsCloser %d -> %s \n",
0513 nodeIdx,left,right,
0514 CSG::Name(typecode),
0515 IntersectionState::Name(l_state), t_left,
0516 IntersectionState::Name(r_state), t_right,
0517 leftIsCloser,
0518 CTRL::Name(ctrl) );
0519
0520 quad6 rec ;
0521 rec.zero();
0522
0523 rec.q0.f = csg.data[left] ;
0524 rec.q1.f = csg.data[right] ;
0525
0526 U4U uu ;
0527 uu.u4.x = sbibit_PACK4( typecode, l_state, r_state, leftIsCloser ) ;
0528 uu.u4.y = sbit_rPACK8( l_promote_miss, l_complement, l_unbounded, false, r_promote_miss, r_complement, r_unbounded, false );
0529 uu.u4.z = tloop ;
0530 uu.u4.w = nodeIdx ;
0531
0532 rec.q2.u.x = uu.u ;
0533 rec.q2.u.y = ctrl ;
0534 rec.q2.u.z = 0u ;
0535 rec.q2.u.w = 0u ;
0536
0537
0538 rec.q3.f.x = tmin ;
0539 rec.q3.f.y = t_min ;
0540 rec.q3.f.z = 0.f ;
0541 rec.q3.f.w = 0.f ;
0542
0543
0544
0545
0546 CSGRecord::record.push_back(rec);
0547 }
0548 #endif
0549
0550
0551 unsigned act = UNDEFINED ;
0552
0553 if(ctrl < CTRL_LOOP_A)
0554 {
0555 float4 result = ctrl == CTRL_RETURN_MISS ? make_float4(0.f, 0.f, 0.f, 0.f ) : csg.data[ctrl == CTRL_RETURN_A ? left : right] ;
0556 if(ctrl == CTRL_RETURN_FLIP_B)
0557 {
0558 result.x = -result.x ;
0559 result.y = -result.y ;
0560 result.z = -result.z ;
0561 }
0562 result.w = copysignf( result.w , nodeIdx % 2 == 0 ? -1.f : 1.f );
0563
0564
0565 ierr = csg_pop0(csg); if(ierr) break ;
0566 ierr = csg_pop0(csg); if(ierr) break ;
0567 ierr = csg_push(csg, result, nodeIdx ); if(ierr) break ;
0568
0569 act = CONTINUE ;
0570
0571 #ifdef DEBUG_RECORD
0572 if(CSGRecord::ENABLED)
0573 {
0574 quad6& rec = CSGRecord::record.back();
0575 rec.q4.f = result ;
0576 }
0577 #endif
0578
0579 }
0580 else
0581 {
0582 int loopside = ctrl == CTRL_LOOP_A ? left : right ;
0583 int otherside = ctrl == CTRL_LOOP_A ? right : left ;
0584
0585 unsigned leftIdx = 2*nodeIdx ;
0586 unsigned rightIdx = leftIdx + 1;
0587 unsigned otherIdx = ctrl == CTRL_LOOP_A ? rightIdx : leftIdx ;
0588
0589 float tminAdvanced = fabsf(csg.data[loopside].w) + propagate_epsilon ;
0590 float4 other = csg.data[otherside] ;
0591
0592 ierr = csg_pop0(csg); if(ierr) break ;
0593 ierr = csg_pop0(csg); if(ierr) break ;
0594 ierr = csg_push(csg, other, otherIdx ); if(ierr) break ;
0595
0596
0597
0598 unsigned endTree = PACK4( 0, 0, nodeIdx, endIdx );
0599 unsigned leftTree = PACK4( 0, 0, leftIdx << (elevation-1), rightIdx << (elevation-1)) ;
0600
0601 unsigned rightTree = PACK4( 0, 0, rightIdx << (elevation-1), nodeIdx );
0602
0603 unsigned loopTree = ctrl == CTRL_LOOP_A ? leftTree : rightTree ;
0604
0605 #ifdef DEBUG_RECORD
0606 if(CSGRecord::ENABLED)
0607 {
0608 printf("// %3d : looping one side tminAdvanced %10.4f with eps %10.4f \n", nodeIdx, tminAdvanced, propagate_epsilon );
0609 quad6& rec = CSGRecord::record.back();
0610 rec.q3.f.z = tminAdvanced ;
0611 }
0612 #endif
0613
0614 #ifdef DEBUG
0615 printf("//intersect_tree nodeIdx %2d height %2d depth %2d elevation %2d endTree %8x leftTree %8x rightTree %8x \n",
0616 nodeIdx,
0617 height,
0618 depth,
0619 elevation,
0620 endTree,
0621 leftTree,
0622 rightTree);
0623 #endif
0624
0625
0626
0627
0628 ierr = tranche_push( tr, endTree, tmin ); if(ierr) break ;
0629 ierr = tranche_push( tr, loopTree, tminAdvanced ); if(ierr) break ;
0630
0631 act = BREAK ;
0632
0633 #ifdef DEBUG_RECORD
0634 if(CSGRecord::ENABLED)
0635 printf("// %3d : looping : act BREAK \n", nodeIdx );
0636 #endif
0637
0638 }
0639
0640
0641 if(act == BREAK)
0642 {
0643 #ifdef DEBUG_RECORD
0644 if(CSGRecord::ENABLED)
0645 printf("// %3d : break for backtracking \n", nodeIdx );
0646 #endif
0647 break ;
0648 }
0649 }
0650 nodeIdx = POSTORDER_NEXT( nodeIdx, elevation ) ;
0651 }
0652 if(ierr) break ;
0653 }
0654
0655 ierr |= (( csg.curr != 0) ? ERROR_END_EMPTY : 0) ;
0656
0657 #ifdef DEBUG_RECORD
0658 if(CSGRecord::ENABLED)
0659 printf("// intersect_tree ierr %d csg.curr %d \n", ierr, csg.curr );
0660 #endif
0661 if(csg.curr == 0)
0662 {
0663 const float4& ret = csg.data[0] ;
0664 isect.x = ret.x ;
0665 isect.y = ret.y ;
0666 isect.z = ret.z ;
0667 isect.w = ret.w ;
0668 }
0669
0670 valid_isect = isect.w > 0.f ;
0671 return ;
0672 }
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683 TREE_FUNC
0684 bool intersect_prim( float4& isect, const CSGNode* node, const float4* plan, const qat4* itra, const float t_min , const float3& ray_origin, const float3& ray_direction, bool dumpxyz )
0685 {
0686 const unsigned typecode = node->typecode() ;
0687 #ifdef DEBUG
0688 printf("//intersect_prim typecode %u1 name %s \n", typecode, CSG::Name(typecode) );
0689 #endif
0690 #ifdef DEBUG_PIDXYZ
0691
0692 #endif
0693
0694
0695 bool valid_isect = false ;
0696 if( typecode >= CSG_LEAF )
0697 {
0698 intersect_leaf( valid_isect, isect, node, plan, itra, t_min, ray_origin, ray_direction, dumpxyz ) ;
0699 }
0700 else if( typecode < CSG_NODE )
0701 {
0702 intersect_tree( valid_isect, isect, node, plan, itra, t_min, ray_origin, ray_direction, dumpxyz ) ;
0703 }
0704 #ifdef WITH_CONTIGUOUS
0705 else if( typecode == CSG_CONTIGUOUS )
0706 {
0707 intersect_node_contiguous( valid_isect, isect, node, node, plan, itra, t_min, ray_origin, ray_direction, dumpxyz ) ;
0708 }
0709 #endif
0710 else if( typecode == CSG_DISCONTIGUOUS )
0711 {
0712 intersect_node_discontiguous( valid_isect, isect, node, node, plan, itra, t_min, ray_origin, ray_direction, dumpxyz ) ;
0713 }
0714 else if( typecode == CSG_OVERLAP )
0715 {
0716 intersect_node_overlap( valid_isect, isect, node, node, plan, itra, t_min, ray_origin, ray_direction, dumpxyz ) ;
0717 }
0718 return valid_isect ;
0719 }
0720
0721
0722 TREE_FUNC
0723 float distance_prim( const float3& global_position, const CSGNode* node, const float4* plan, const qat4* itra )
0724 {
0725
0726 const unsigned typecode = node->typecode() ;
0727 float distance = -1.f ;
0728 if( typecode >= CSG_LEAF )
0729 {
0730 distance = distance_leaf(global_position, node, plan, itra );
0731 }
0732 else if( typecode < CSG_NODE )
0733 {
0734 distance = distance_tree(global_position, node, plan, itra );
0735 }
0736 else
0737 {
0738 distance = distance_node_list( typecode, global_position, node, node, plan, itra ) ;
0739 }
0740 return distance ;
0741 }
0742
0743