Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:48:57

0001 #pragma once
0002 #include "squad.h"
0003 
0004 #if defined(__CUDACC__) || defined(__CUDABE__)
0005    #define NODE_METHOD __device__
0006 #else
0007    #define NODE_METHOD
0008 #endif
0009 
0010 
0011 #if defined(__CUDACC__) || defined(__CUDABE__)
0012 #else
0013 #endif
0014 
0015 #include "CSG_API_EXPORT.hh"
0016 
0017 
0018 /**
0019 CSGNode (synonymous with Part)
0020 ==============================
0021 
0022 NB elements are used for different purposes depending on typecode,
0023 eg planeIdx, planeNum are used only with CSG_CONVEXPOLYHEDRON.  Marked "cx:" below.
0024 
0025 
0026 sp:sphere
0027    center, radius
0028 
0029 zs:zsphere
0030    center, radius, z1, z2 cuts
0031 
0032 cy:cylinder
0033    center, radius, z1, z2
0034 
0035 ds:disc
0036    very flat cylinder
0037 
0038 cn:cone
0039    r1, z1, r2, z2
0040 
0041 hy:hyperboloid
0042    r0 (z=0 waist), ...
0043 
0044 pl:plane (unbounded)
0045    normal and distance from origin
0046 
0047 sl:slab (unbounded)
0048    normal and two distances from origin
0049 
0050 cx:convexpolyhedron
0051    planeOffset and number of planes
0052 
0053 
0054 * TODO : it would be convenient for debugging for the lvid to be in the node,
0055   for example via bitpack with the boundary or typecode
0056 
0057 
0058 * CONSIDER REJIG TO ALLOW 8-PARAM : OR USE PLANE REFERENCING FOR EXTRA PARAM
0059 
0060   * boundary and typecode are small, they could easily be colocated
0061   * simliarly index, gtransformIdx, complement could be combined
0062 
0063 
0064 * vim replace : shift-R
0065 
0066 
0067     +----+----------------+----------------+----------------+----------------+-------------------------------------------------+
0068     | q  |      x         |      y         |     z          |      w         |  notes                                          |
0069     +====+================+================+================+================+=================================================+
0070     |    | sp/zs/cy:cen_x | sp/zs/cy:cen_y | sp/zs/cy:cen_z | sp/zs/cy:radius|  eliminate center? as can be done by transform  |
0071     | q0 | cn:r1          | cn:z1          | cn:r2          | cn:z2          |  cn:z2 > z1                                     |
0072     |    | hy:r0 z=0 waist| hy:zf          | hy:z1          | hy:z2          |  hy:z2 > z1                                     |
0073     |    | b3:fx          | b3:fy          | b3:fz          |                |  b3: fullside dimensions, center always origin  |
0074     |    | pl/sl:nx       | pl/sl:ny       | pl/sl:nz       | pl:d           |  pl: NB Node plane distinct from plane array    |
0075     |    |                |                | ds:inner_r     | ds:radius      |                                                 |
0076     |    | co:subNum      | co:subOffset   |                | radius()       |                                                 |
0077     |    | cx:planeIdx    | cx:planeNum    |                |                |                                                 |
0078     +----+----------------+----------------+----------------+----------------+-------------------------------------------------+
0079     |    | zs:zdelta_0    | zs:zdelta_1    | boundary       | index          |                                                 |
0080     |    | sl:a           | sl:b           |  (1,2)         | (within solid) |  sl:a,b offsets from origin                     |
0081     | q1 | cy:z1          | cy:z2          |                | (1,3)          |  cy:z2 > z1                                     |
0082     |    | ds:z1          | ds:z2          |                |                |                                                 |
0083     |    | z1()           | z2()           |                |                |                                                 |
0084     +----+----------------+----------------+----------------+----------------+-------------------------------------------------+
0085     |    |                |                |                |                |  q2.w was previously typecode                   |
0086     |    |                |                |                |                |                                                 |
0087     | q2 |  BBMin_x       |  BBMin_y       |  BBMin_z       |  BBMax_x       |                                                 |
0088     |    |                |                |                |                |                                                 |
0089     |    |                |                |                |                |                                                 |
0090     +----+----------------+----------------+----------------+----------------+-------------------------------------------------+
0091     |    |                |                |  typecode      | gtransformIdx  |  a.node[:,3,3].view(np.int32) & 0x7fffffff      |
0092     |    |                |                |  (3,2)         | complement     |                                                 |
0093     | q3 |  BBMax_y       |  BBMax_z       |                | (3,3)          |                                                 |
0094     |    |                |                |                |                |                                                 |
0095     |    |                |                |                |                |                                                 |
0096     |    |                |                |                |                |                                                 |
0097     |    |                |                |                |                |                                                 |
0098     +----+----------------+----------------+----------------+----------------+-------------------------------------------------+
0099 
0100 
0101 
0102 typecode gtransformIdx complement
0103 -----------------------------------
0104 
0105 * moved typecode from q2.w in order to give 6 contiguous slots for aabb
0106 
0107 ::
0108 
0109     typecode = cf.node.view(np.uint32)[:,3,2]
0110     complement = ( cf.node.view(np.uint32)[:,3,3] & 0x80000000 ) >> 31
0111     gtransformIdx = cf.node.view(np.uint32)[:,3,3] & 0x7fffffff
0112 
0113 * TODO: complement is naturally related with typecode (not with gtransformIdx)
0114   so should put them together : could simply flip the sign of the typecode for complemented
0115 
0116 
0117 gtransformIdx
0118     integer "pointer" into the tran and itra arrays : containing final "flat" transforms
0119 
0120     * final transforms are obtained from the product of structural and CSG transforms
0121     * CSGNode within instances : transform product starts inside the outer structural transform.
0122     * CSGNode within global remainder : transform product is within root (root always has identity anyhow)
0123 
0124     Only leaf nodes use these transforms in csg intersection, intersection onto boolean
0125     operator nodes are obtained by choosing between intersects onto leaf nodes : so any transform
0126     associated with an operator node is ignored
0127 
0128 
0129 **Operator nodes pick between intersect distances from their leaf nodes, they never use their own gtransforms.**
0130 
0131 
0132 
0133 Interpret (3,3) zero to mean no transform, so much subtract 1 prior to tran lookup
0134 -----------------------------------------------------------------------------------
0135 
0136 ::
0137 
0138     In [23]: trIdx = a.node.view(np.int32)[:,3,3] & 0x7fffffff
0139 
0140     In [28]: np.c_[np.unique(trIdx, return_counts=True)]
0141     Out[28]:
0142     array([[   0, 8577],
0143            [   1,    1],
0144            [   2,    1],
0145            [   3,    1],
0146            ...,
0147            [7389,    1],
0148            [7390,    1],
0149            [7391,    1]])
0150 
0151     In [29]: a.tran.shape
0152     Out[29]: (7391, 4, 4)
0153 
0154     In [31]: a.tran[7391-1]
0155     Out[31]:
0156     array([[  1. ,   0. ,   0. ,   0. ],
0157            [  0. ,   1. ,   0. ,   0. ],
0158            [  0. ,   0. ,   1. ,   0. ],
0159            [  0. , 831.6,   0. ,   1. ]], dtype=float32)
0160 
0161 
0162 
0163 
0164 tree transforms vs final "flat" transforms
0165 --------------------------------------------
0166 
0167 Must not conflate these two sets of transforms, as
0168 their nature and considerations for them are very different.
0169 
0170 The tree transforms, both structural and CSG, are local to the their nodes
0171 and are obtained from source geometry. They are held by stree.h/snode.h/snd.hh/sxf.h
0172 The final flat transforms are obtained from the tree transforms via matrix products
0173 (see stree::get_combined_transform).
0174 
0175 The final transforms should not be regarded as modifiable.
0176 Any editing such as for coincidence avoidance nudging needs
0177 to be done on the tree transforms level prior to flattening,
0178 eg with CSGImport::importTree.
0179 This means should NOT be tempted to associate transforms
0180 with every CSGNode in order to allow subsequent modification.
0181 
0182 As the flat transforms are what is on GPU it is beneficial
0183 to keep the tran/itra arrays as small as possible, eg via unique-ing.
0184 Conversely the tree transforms do not have size concerns.
0185 
0186 
0187 subNum subOffset
0188 ------------------
0189 
0190 Used by compound node types such as CSG_CONTIGUOUS, CSG_DISCONTIGUOUS and the rootnode of boolean trees CSG_UNION/CSG_INTERSECTION/CSG_DIFFERENCE...
0191 Note that because subNum uses q0.u.x and subOffset used q0.u.y this should not (and cannot) be used for leaf nodes.
0192 
0193 
0194 **/
0195 
0196 struct CSG_API CSGNode
0197 {
0198     quad q0 ;
0199     quad q1 ;
0200     quad q2 ;
0201     quad q3 ;
0202 
0203     // only used for CSG_CONVEXPOLYHEDRON and similar prim like CSG_TRAPEZOID which are composed of planes
0204     NODE_METHOD unsigned planeIdx()      const { return q0.u.x ; }  // 1-based, 0 meaning None
0205     NODE_METHOD unsigned planeNum()      const { return q0.u.y ; }
0206     NODE_METHOD void setPlaneIdx(unsigned idx){  q0.u.x = idx ; }
0207     NODE_METHOD void setPlaneNum(unsigned num){  q0.u.y = num ; }
0208 
0209     // used for compound node types such as CSG_CONTIGUOUS, CSG_DISCONTIGUOUS and the rootnode of boolean trees CSG_UNION/CSG_INTERSECTION/CSG_DIFFERENCE...
0210     NODE_METHOD unsigned subNum()        const { return q0.u.x ; }
0211     NODE_METHOD unsigned subOffset()     const { return q0.u.y ; }
0212 
0213     NODE_METHOD void setSubNum(unsigned num){    q0.u.x = num ; }
0214     NODE_METHOD void setSubOffset(unsigned num){ q0.u.y = num ; }
0215 
0216 
0217 
0218 #if defined(__CUDACC__) || defined(__CUDABE__)
0219 #else
0220     NODE_METHOD void getParam_( double& x , double& y , double& z , double& w , double& z1, double& z2 ) const
0221     {
0222         x = q0.f.x ;
0223         y = q0.f.y ;
0224         z = q0.f.z ;
0225         w = q0.f.w ;
0226         z1 = q1.f.x ;
0227         z2 = q1.f.y ;
0228     }
0229 #endif
0230 
0231     NODE_METHOD void getParam( float& x , float& y , float& z , float& w , float& z1, float& z2 ) const
0232     {
0233         x = q0.f.x ;
0234         y = q0.f.y ;
0235         z = q0.f.z ;
0236         w = q0.f.w ;
0237         z1 = q1.f.x ;
0238         z2 = q1.f.y ;
0239     }
0240     NODE_METHOD void setParam( float  x , float  y , float  z , float  w , float  z1, float  z2 )
0241     {
0242         q0.f.x = x  ;
0243         q0.f.y = y  ;
0244         q0.f.z = z  ;
0245         q0.f.w = w  ;
0246         q1.f.x = z1 ;
0247         q1.f.y = z2 ;
0248     }
0249 
0250 
0251     /**
0252     HUNTING FOR OLD WORKFLOW BUG : WITH INT32 OVERWRITES IN UNION/DIFFERENCE CSGNode
0253 
0254     ACTUALLY : THIS IS NOT A BUG : THAT IS subNum set by CSG_GGeo_Convert::convertPrim
0255     **/
0256     NODE_METHOD bool hasStrayInt() const
0257     {
0258         return (  q3.u.z == 1 || q3.u.z == 2 ) && ( q0.u.x == 3 || q0.u.x == 7 || q0.u.x == 15 ) ;
0259 
0260     }
0261 
0262     NODE_METHOD void setParam(const float* p)
0263     {
0264         if(!p) return ;
0265         q0.f.x = *(p+0) ;
0266         q0.f.y = *(p+1) ;
0267         q0.f.z = *(p+2) ;
0268         q0.f.w = *(p+3) ;
0269         q1.f.x = *(p+4) ;
0270         q1.f.y = *(p+5) ;
0271     }
0272 
0273     NODE_METHOD void setParam_Narrow(const double* p)
0274     {
0275         if(!p) return ;
0276         q0.f.x = *(p+0) ;
0277         q0.f.y = *(p+1) ;
0278         q0.f.z = *(p+2) ;
0279         q0.f.w = *(p+3) ;
0280         q1.f.x = *(p+4) ;
0281         q1.f.y = *(p+5) ;
0282     }
0283 
0284 
0285 
0286     NODE_METHOD void getYRange(float& y0, float& y1) const ;
0287 
0288     NODE_METHOD void setAABBLocal();
0289     NODE_METHOD void setAABB(  float x0, float y0, float z0, float x1, float y1, float z1){  q2.f.x = x0 ; q2.f.y = y0 ; q2.f.z = z0 ; q2.f.w = x1 ; q3.f.x = y1 ; q3.f.y = z1 ; }
0290     NODE_METHOD void setAABB(  float e ){                                                    q2.f.x = -e ; q2.f.y = -e ; q2.f.z = -e ; q2.f.w =  e ; q3.f.x =  e ; q3.f.y =  e ; }
0291     NODE_METHOD void setAABB(const float* p)
0292     {
0293         if(!p) return ;
0294         q2.f.x = *(p+0) ;
0295         q2.f.y = *(p+1) ;
0296         q2.f.z = *(p+2) ;
0297         q2.f.w = *(p+3) ;
0298         q3.f.x = *(p+4) ;
0299         q3.f.y = *(p+5) ;
0300     }
0301 
0302     NODE_METHOD void setAABB_Narrow(const double* p)
0303     {
0304         if(!p) return ;
0305         q2.f.x = *(p+0) ;
0306         q2.f.y = *(p+1) ;
0307         q2.f.z = *(p+2) ;
0308         q2.f.w = *(p+3) ;
0309         q3.f.x = *(p+4) ;
0310         q3.f.y = *(p+5) ;
0311     }
0312 
0313     NODE_METHOD       float* AABB()       {  return &q2.f.x ; }
0314     NODE_METHOD const float* AABB() const {  return &q2.f.x ; }
0315     NODE_METHOD const float3 mn() const {    return make_float3(q2.f.x, q2.f.y, q2.f.z) ; }
0316     NODE_METHOD const float3 mx() const {    return make_float3(q2.f.w, q3.f.x, q3.f.y) ; }
0317     NODE_METHOD float extent() const
0318     {
0319         float3 d = make_float3( q2.f.w - q2.f.x, q3.f.x - q2.f.y, q3.f.y - q2.f.z );
0320         return fmaxf(fmaxf(d.x, d.y), d.z) /2.f ;
0321     }
0322 
0323 
0324     NODE_METHOD unsigned boundary()  const {      return q1.u.z ; }
0325     NODE_METHOD void setBoundary(unsigned bnd){          q1.u.z = bnd ; }
0326 
0327     NODE_METHOD unsigned index()     const {      return q1.u.w ; }
0328     NODE_METHOD void setIndex(unsigned idx){             q1.u.w = idx ; }
0329 
0330     NODE_METHOD unsigned typecode()  const {      return q3.u.z ; }  //  OptickCSG_t enum
0331     NODE_METHOD void setTypecode(unsigned tc){           q3.u.z = tc ; }
0332 
0333     NODE_METHOD unsigned typemask()  const {      return 1 << q3.u.z ; } //  mask integer suitable for bitwise-oring
0334 
0335     NODE_METHOD void zeroTransformComplement(){         q3.u.w = 0 ; }
0336     NODE_METHOD void setTransform(  unsigned idx ){     setTransformComplement(idx,  is_complement() )   ; }
0337     NODE_METHOD void setComplement( bool complement ){  setTransformComplement( gtransformIdx(), complement) ; }
0338     NODE_METHOD void setTransformComplement( unsigned idx, bool complement ){ q3.u.w = ( idx & 0x7fffffff ) | ( (int(complement) << 31) & 0x80000000) ; }
0339 
0340     NODE_METHOD unsigned gtransformIdx() const { return q3.u.w & 0x7fffffff ; }  //  gtransformIdx is 1-based, 0 meaning None
0341     NODE_METHOD bool     is_complement() const { return q3.u.w & 0x80000000 ; }
0342 
0343 
0344     NODE_METHOD float radius() const { return q0.f.w ; } ;
0345     NODE_METHOD float z1() const {     return q1.f.x ; } ;
0346     NODE_METHOD float z2() const {     return q1.f.y ; } ;
0347 
0348 
0349 
0350 #if defined(__CUDACC__) || defined(__CUDABE__)
0351 #else
0352     static bool IsDiff( const CSGNode& a , const CSGNode& b );
0353     static std::string Addr(unsigned repeatIdx, unsigned primIdx, unsigned partIdxRel );
0354 
0355     static std::string Desc(const float* fval, int numval=6, int wid=7, int prec=1 );
0356     std::string desc() const ;
0357     std::string tag() const ;
0358 
0359 
0360     std::string brief() const ;
0361     static void Dump(const CSGNode* n, unsigned ni, const char* label);
0362 
0363     bool is_compound() const ;
0364     bool is_operator() const ;
0365     bool is_intersection() const ;
0366     bool is_union() const ;
0367     bool is_difference() const ;
0368     bool is_primitive() const ;
0369     bool is_complemented_primitive() const ;
0370     bool is_zero() const ;
0371 
0372     static unsigned AncestorTypeMask( const CSGNode* root, unsigned partIdxRel, bool dump  );
0373     static unsigned Depth( unsigned partIdxRel );
0374     static bool     IsOnlyUnionMask( unsigned atm );
0375     static bool     IsOnlyIntersectionMask( unsigned atm );
0376     static bool     IsOnlyDifferenceMask( unsigned atm );
0377 
0378     static void Copy(CSGNode& b, const CSGNode& a)
0379     {
0380         b.q0.f.x = a.q0.f.x ; b.q0.f.y = a.q0.f.y ; b.q0.f.z = a.q0.f.z ; b.q0.f.w = a.q0.f.w ;
0381         b.q1.f.x = a.q1.f.x ; b.q1.f.y = a.q1.f.y ; b.q1.f.z = a.q1.f.z ; b.q1.f.w = a.q1.f.w ;
0382         b.q2.f.x = a.q2.f.x ; b.q2.f.y = a.q2.f.y ; b.q2.f.z = a.q2.f.z ; b.q2.f.w = a.q2.f.w ;
0383         b.q3.f.x = a.q3.f.x ; b.q3.f.y = a.q3.f.y ; b.q3.f.z = a.q3.f.z ; b.q3.f.w = a.q3.f.w ;
0384     }
0385 
0386     static const float UNBOUNDED_DEFAULT_EXTENT ;
0387 
0388     static CSGNode Union();
0389     static CSGNode Intersection();
0390     static CSGNode Difference();
0391     static CSGNode BooleanOperator(unsigned op, int num_sub);
0392 
0393     static CSGNode Overlap(      int num_sub, int sub_offset);
0394     static CSGNode Contiguous(   int num_sub, int sub_offset);
0395     static CSGNode Discontiguous(int num_sub, int sub_offset);
0396     static CSGNode ListHeader(unsigned type, int num_sub, int sub_offset);
0397 
0398 
0399     static CSGNode Zero();
0400     static CSGNode Sphere(float radius);
0401     static CSGNode ZSphere(float radius, float z1, float z2);
0402     static CSGNode Cone(float r1, float z1, float r2, float z2);
0403     static CSGNode OldCone(float r1, float z1, float r2, float z2);
0404     static CSGNode Hyperboloid(float r0, float zf, float z1, float z2);
0405     static CSGNode Box3(float fx, float fy, float fz );
0406     static CSGNode Box3(float fullside);
0407     static CSGNode Plane(float nx, float ny, float nz, float d);
0408     static CSGNode Slab(float nx, float ny, float nz, float d1, float d2 ) ;
0409     static CSGNode HalfSpace(float nx, float ny, float nz, float nw );
0410 
0411     static CSGNode* HalfCylinder(float nx, float ny, float nz, float nw, float radius, float z0, float z1 );
0412     static CSGNode* HalfCylinder();
0413 
0414 
0415     static CSGNode Cylinder(   float radius, float z1, float z2) ;
0416     static CSGNode OldCylinder(float radius, float z1, float z2);
0417 
0418     static CSGNode InfCylinder(float radius, float hz ) ;
0419     static CSGNode InfPhiCut(  float startPhi_pi, float deltaPhi_pi ) ;
0420     static CSGNode InfThetaCut(float startTheta_pi, float deltaTheta_pi ) ;
0421     static CSGNode Disc(float px, float py, float ir, float r, float z1, float z2);
0422 
0423     static CSGNode MakeDemo(const char* name);
0424     static CSGNode Make(       unsigned typecode );
0425     static CSGNode Make(       unsigned typecode, const float*  param6, const float*  aabb);
0426     static CSGNode MakeNarrow( unsigned typecode, const double* param6, const double* aabb);
0427 
0428 #endif
0429 
0430 };
0431 
0432 
0433 
0434 #if defined(__CUDACC__) || defined(__CUDABE__)
0435 #else
0436 
0437 
0438 inline std::ostream& operator<<(std::ostream& os, const CSGNode& n)
0439 {
0440     os
0441        << std::endl
0442        << "q0 " << n.q0 << std::endl
0443        << "q1 " << n.q1 << std::endl
0444        << "q2 " << n.q2 << std::endl
0445        << "q3 " << n.q3 << std::endl
0446        ;
0447     return os;
0448 }
0449 
0450 #endif
0451 
0452 
0453 
0454