Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #include <csignal>
0002 
0003 #include "SLOG.hh"
0004 #include "scuda.h"
0005 #include "sqat4.h"
0006 #include "sframe.h"
0007 #include "SCenterExtentFrame.h"
0008 
0009 #include "CSGFoundry.h"
0010 #include "CSGTarget.h"
0011 
0012 const plog::Severity CSGTarget::LEVEL = SLOG::EnvLevel("CSGTarget", "DEBUG" );
0013 
0014 CSGTarget::CSGTarget( const CSGFoundry* foundry_ )
0015     :
0016     foundry(foundry_)
0017 {
0018 }
0019 
0020 
0021 
0022 /**
0023 CSGTarget::getFrame "getFrameFromInstanceLookup"
0024 -------------------------------------------------
0025 
0026 * TODO: avoid this inverting the "m2w" instance transform to give w2m
0027 
0028 Note that there are typically multiple CSGPrim within the compound CSGSolid
0029 and that the inst_idx corresponds to the entire compound CSGSolid (aka GMergedMesh).
0030 Hence the ce included with the frame is the one from the full compound CSGSolid.
0031 
0032 * DONE: new minimal U4Tree.h/stree.h geo translation collects paired m2w and w2m transforms
0033   and uses those to give both inst and iinst in double precision
0034 
0035 * TODO: move the stree.h inst/iinst members and methods into CSGFoundry
0036   and use them from a future "CSGFoundry::CreateFromSTree" to add
0037   paired double precision transforms, avoiding Invert
0038 
0039 TODO: would be better to have sframe access from stree.h
0040 
0041 **/
0042 
0043 int CSGTarget::getFrame(sframe& fr, int inst_idx ) const
0044 {
0045     const qat4* _t = foundry->getInst(inst_idx);
0046 
0047     LOG(LEVEL)
0048         << " inst_idx " << inst_idx
0049         << " _t " << ( _t ? "YES" : "NO " )
0050         ;
0051 
0052     LOG_IF(error, _t == nullptr)
0053         << " inst_idx " << inst_idx
0054         << " failed to foundry->getInst(inst_idx), "
0055         << " foundry->getNumInst() : " << foundry->getNumInst()
0056         ;
0057     if(_t == nullptr) return 1 ;
0058 
0059 
0060     int ins_idx,  gas_idx, sensor_identifier, sensor_index ;
0061     _t->getIdentity(ins_idx,  gas_idx, sensor_identifier, sensor_index );
0062 
0063     LOG(LEVEL)
0064         << " inst_idx " << inst_idx
0065         << " _t " << ( _t ? "YES" : "NO " )
0066         << " ins_idx " << ins_idx
0067         << " gas_idx " << gas_idx
0068         << " sensor_identifier " << sensor_identifier
0069         << " sensor_index " << sensor_index
0070         ;
0071 
0072     LOG_IF( fatal , gas_idx < 0 )
0073         << " gas_idx " << gas_idx
0074         << " foundry->inst.size " << foundry->inst.size()
0075         << " BAD sqat4.h inst ? "
0076         ;
0077 
0078     assert( gas_idx > -1 );
0079 
0080     assert( ins_idx == inst_idx );
0081     fr.set_inst(inst_idx);
0082 
0083     // HMM: these values are already there inside the matrices ?
0084     fr.set_identity(ins_idx, gas_idx, sensor_identifier, sensor_index ) ;
0085 
0086     qat4 t(_t->cdata());   // copy the instance (transform and identity info)
0087     const qat4* v = Tran<double>::Invert(&t);
0088 
0089     qat4::copy(fr.m2w,  t);
0090     qat4::copy(fr.w2m, *v);
0091 
0092     delete v ;
0093 
0094     // identity info IS NOT cleared by Tran::Invert
0095     // as there is special handling to retain it (see stran.h)
0096     // the explicit clearing below fixes a bug revealed during
0097     // Raindrop revival
0098     // see notes/issues/Raindrop_revival_fix_CSGTarget_getFrame_nan_from_not_clearing_identity_info.rst
0099 
0100 
0101     fr.m2w.clearIdentity();
0102     fr.w2m.clearIdentity();
0103 
0104     // TODO: adopt sframe::setTransform
0105 
0106     const CSGSolid* solid = foundry->getSolid(gas_idx);
0107     fr.ce = solid->center_extent ;
0108 
0109 
0110     LOG(LEVEL)
0111         << " inst_idx " << inst_idx
0112         << " _t " << ( _t ? "YES" : "NO " )
0113         << " ins_idx " << ins_idx
0114         << " gas_idx " << gas_idx
0115         << " sensor_identifier " << sensor_identifier
0116         << " sensor_index " << sensor_index
0117         << " fr.m2w.q3.f.w " <<  fr.m2w.q3.f.w
0118         << " fr.m2w.q3.i.w " <<  fr.m2w.q3.i.w
0119         << " fr.w2m.q3.f.w " <<  fr.w2m.q3.f.w
0120         << " fr.w2m.q3.i.w " <<  fr.w2m.q3.i.w
0121         ;
0122 
0123     return 0 ;
0124 }
0125 
0126 
0127 
0128 /**
0129 CSGTarget::getFrame
0130 ----------------------
0131 
0132 
0133 midx
0134     mesh index (aka lv)
0135 mord
0136     mesh ordinal (picking between multipler occurrences of midx
0137 gord
0138     GAS ordinal [NB this is not the GAS index]
0139 
0140 
0141 NB the GAS index is determined from (midx, mord)
0142 and then gord picks between potentially multiple occurrences
0143 
0144 
0145 Q: is indexing by MOI and inst_idx equivalent ? OR: Can a MOI be converted into inst_idx and vice versa ?
0146 A: see notes with CSGFoundry::getFrame
0147 
0148 **/
0149 
0150 int CSGTarget::getFrame(sframe& fr,  int midx, int mord, int gord ) const
0151 {
0152     fr.set_midx_mord_gord( midx, mord, gord );
0153     int rc = getFrameComponents( fr.ce, midx, mord, gord, &fr.m2w , &fr.w2m );
0154     LOG(LEVEL) << " midx " << midx << " mord " << mord << " gord " << gord << " rc " << rc ;
0155     return rc ;
0156 }
0157 
0158 
0159 /**
0160 CSGTarget::getFrameComponents
0161 -------------------------------
0162 
0163 Used by CSGFoundry::getCenterExtent
0164 
0165 *ce*
0166     center-extent float4 set when return code is zero
0167 *midx*
0168     solid (aka mesh) index : identify the shape
0169 *mord*
0170     solid (aka mesh) ordinal : pick between shapes when there are more than one, used with global(non-instanced) geometry
0171 *gord*
0172     GAS ordinal 0,1,2,...  or when -ve special cases
0173 
0174 
0175 
0176 2022-01-03 15:06:16.746 INFO  [5325503] [CSGTarget::getLocalCenterExtent@91]  midx 88 mord 10 prim.size 64 mord_in_range 1
0177 2022-01-03 15:06:16.746 INFO  [5325503] [CSGTarget::getLocalCenterExtent@109]  lce (-17336.020,-4160.728,-809.117,66.045)
0178 
0179 
0180 -2:world2model_rtpw : scale down and rotate    ( world2model = irotate * iscale * itranslate )
0181 
0182  MOI solidXJfixture:10:-2
0183     midx 88 mord 10 gord -2
0184     gce (-17336.020,-4160.728,-809.117,66.045)
0185     q (-0.015, 0.001, 0.004, 0.000)
0186       (-0.004, 0.000,-0.015, 0.000)
0187       (-0.001,-0.015, 0.000, 0.000)
0188       (-270.221,-0.000, 0.000, 1.000)
0189 
0190 -3:model2world_rtpw : scale up and rotate      ( model2world = translate * scale * rotate )
0191 
0192  MOI solidXJfixture:10:-3
0193     midx 88 mord 10 gord -3
0194     gce (-17336.020,-4160.728,-809.117,66.045)
0195     q (-64.155,-15.397,-2.994, 0.000)
0196       ( 2.912, 0.699,-65.977, 0.000)
0197       (15.413,-64.221, 0.000, 0.000)
0198       (-17336.020,-4160.728,-809.117, 1.000)
0199 
0200 -4:world2model_xyzw : uniform scaling down only, no rotation
0201 
0202  MOI solidXJfixture:10:-4
0203     midx 88 mord 10 gord -4
0204     gce (-17336.020,-4160.728,-809.117,66.045)
0205     q ( 0.015, 0.000, 0.000, 0.000)
0206       ( 0.000, 0.015, 0.000, 0.000)
0207       ( 0.000, 0.000, 0.015, 0.000)
0208       (262.489,62.999,12.251, 1.000)
0209 
0210 -5:model2world_xyzw  : uniform scaling up only, no rotation
0211 
0212  MOI solidXJfixture:10:-5
0213     midx 88 mord 10 gord -5
0214     gce (-17336.020,-4160.728,-809.117,66.045)
0215     q (66.045, 0.000, 0.000, 0.000)
0216       ( 0.000,66.045, 0.000, 0.000)
0217       ( 0.000, 0.000,66.045, 0.000)
0218       (-17336.020,-4160.728,-809.117, 1.000)
0219 
0220 
0221 HMM : INCONSISTENCY IN THE MEANING BETWEEN THIS CSGTarget::getFrameComponents
0222 LOOKS LIKE -1 in stree::get_frame is equivalent to -2 from here
0223 
0224 WHAT USE IS THE -1 FROM HERE ?
0225 
0226 
0227 **/
0228 
0229 int CSGTarget::getFrameComponents(float4& ce, int midx, int mord, int gord, qat4* m2w, qat4* w2m ) const
0230 {
0231     LOG(LEVEL) << " (midx mord gord) " << "(" << midx << " " << mord << " " << gord << ") " ;
0232     if( gord == -1 || gord == -2 || gord == -3 )
0233     {
0234         int lrc = getLocalCenterExtent(ce, midx, mord);
0235         if(lrc != 0) return 1 ;
0236 
0237         if( gord == -1 )
0238         {
0239             LOG(info) << "(gord == -1) qptr transform will not be set, typically defaulting to identity " ;
0240             assert(0) ; // WHAT IS USING -1 WITH CE SET AND IDENTITY TRANSFORMS ?  COMMONLY 0:0:-1 default MOI
0241         }
0242         else if( gord == -2 )
0243         {
0244             bool rtp_tangential = false ;
0245             bool extent_scale = false ;  // NB recent change switching off extent scaling
0246             SCenterExtentFrame<double> cef_xyzw( ce.x, ce.y, ce.z, ce.w, rtp_tangential, extent_scale );
0247             m2w->read_narrow(cef_xyzw.model2world_data);
0248             w2m->read_narrow(cef_xyzw.world2model_data);
0249         }
0250         else if( gord == -3 )
0251         {
0252             bool rtp_tangential = true ;
0253             bool extent_scale = false ;   // NB recent change witching off extent scaling
0254             SCenterExtentFrame<double> cef_rtpw( ce.x, ce.y, ce.z, ce.w, rtp_tangential, extent_scale );
0255             m2w->read_narrow(cef_rtpw.model2world_data);
0256             w2m->read_narrow(cef_rtpw.world2model_data);
0257         }
0258     }
0259     else
0260     {
0261         int grc = getGlobalCenterExtent(ce, midx, mord, gord, m2w, w2m );
0262         //  HMM: the m2w here populated is from the (midx, mord, gord) instance transform, with identity info
0263         if(grc != 0) return 2 ;
0264     }
0265     return 0 ;
0266 }
0267 
0268 
0269 
0270 
0271 /**
0272 CSGTarget::getLocalCenterExtent : lookup (midx,mord) CSGPrim and returns its CE
0273 -------------------------------------------------------------------------------------
0274 
0275 Collects prim matching the *midx* and selects the *mord* ordinal one
0276 from which to read the localCE
0277 
0278 **/
0279 
0280 int CSGTarget::getLocalCenterExtent(float4& lce, int midx, int mord) const
0281 {
0282     std::vector<CSGPrim> prim ;
0283     foundry->getMeshPrimCopies(prim, midx );
0284     bool mord_in_range = mord < int(prim.size()) ;
0285 
0286     LOG(LEVEL)
0287         << " midx " << midx
0288         << " mord " << mord
0289         << " prim.size " << prim.size()
0290         << " mord_in_range " << mord_in_range
0291         ;
0292 
0293     if(!mord_in_range) return 1 ;
0294 
0295     const CSGPrim& lpr = prim[mord] ;
0296 
0297     float4 localCE = lpr.ce();
0298 
0299     lce.x = localCE.x ;
0300     lce.y = localCE.y ;
0301     lce.z = localCE.z ;
0302     lce.w = localCE.w ;
0303 
0304     LOG(LEVEL) << " lce " << lce  ;
0305     return 0 ;
0306 }
0307 
0308 
0309 
0310 /**
0311 CSGTarget::getGlobalCenterExtent
0312 ---------------------------------
0313 
0314 1. getInstanceTransform from (midx, mord, gord) giving m2w
0315 2. invert m2w giving w2m
0316 
0317 4. select the *gord* instance transform to construct a global-prim *gpr*
0318 5. fill in *gce* with the global center-extren from
0319 
0320 *gce*
0321     output global center extent float4
0322 *midx*
0323     input mesh index (aka lv index)
0324 *mord*
0325     input mesh ordinal : this is particularly useful with the global geometry where there are
0326     no instances to select between. But there are repeated uses of the mesh that
0327     this ordinal picks between. For instanced geometry this will mostly be zero(?)
0328 *gord*
0329     input GAS ordinal, allow to select between multiple instances of the GAS,
0330     that has also been used when negative for other selections
0331 
0332 *qptr*
0333     output instance transform pointer. When non-null the instance
0334     transform will be copied into this qat4 which will contain
0335     identity integers in its fourth column
0336 
0337 
0338 
0339 
0340 
0341 HMM with global non-instanced geometry the transforms should be identity
0342 
0343 **/
0344 
0345 int CSGTarget::getGlobalCenterExtent(float4& gce, int midx, int mord, int gord, qat4* m2w, qat4* w2m ) const
0346 {
0347     const qat4* t = getInstanceTransform(midx, mord, gord);
0348     const qat4* v = t ? Tran<double>::Invert(t ) : nullptr ;
0349 
0350     LOG_IF(fatal, t == nullptr)
0351         << " failed to get InstanceTransform (midx mord gord) " << "(" << midx << " " << mord << " " << gord << ")" ;
0352 
0353     LOG_IF(fatal, v == nullptr)
0354         << " failed Tran<double>::Invert " ;
0355 
0356     if(t == nullptr) return 1 ;
0357     if(v == nullptr) return 2 ;
0358 
0359     LOG(LEVEL)
0360         << std::endl
0361         << t->desc('t')
0362         << std::endl
0363         << v->desc('v')
0364         ;
0365 
0366     if(m2w)
0367     {
0368         qat4::copy(*m2w, *t);
0369         m2w->clearIdentity();  // recent addition
0370     }
0371     if(w2m)
0372     {
0373         qat4::copy(*w2m, *v);
0374         w2m->clearIdentity();  // recent addition
0375     }
0376 
0377     qat4 q(t->cdata());   // copy the instance (transform and identity info)
0378 
0379     int ins_idx,  gas_idx, sensor_identifier, sensor_index ;
0380     q.getIdentity(ins_idx,  gas_idx, sensor_identifier, sensor_index );
0381     q.clearIdentity();    // clearIdentity sets the (3,3) 1. : needed before doing any transforming
0382 
0383     // TODO: could incorporate this identity into the sframe ?
0384 
0385 
0386 
0387 
0388     const CSGPrim* lpr = foundry->getMeshPrim(midx, mord);
0389 
0390     CSGPrim gpr = {} ;
0391     CSGPrim::Copy(gpr, *lpr);   // start global prim from local
0392 
0393     q.transform_aabb_inplace( gpr.AABB_() );
0394 
0395     LOG(LEVEL)
0396         << std::endl
0397         << " q " << q
0398         << std::endl
0399         << " ins_idx " << ins_idx
0400         << " gas_idx " << gas_idx
0401         << " sensor_identifier " << sensor_identifier
0402         << " sensor_index " << sensor_index
0403         ;
0404     float4 globalCE = gpr.ce();
0405     gce.x = globalCE.x ;
0406     gce.y = globalCE.y ;
0407     gce.z = globalCE.z ;
0408     gce.w = globalCE.w ;
0409 
0410     LOG(LEVEL)
0411         << " gpr " << gpr.desc()
0412         << " gce " << gce
0413         ;
0414 
0415     return 0 ;
0416 }
0417 
0418 
0419 /**
0420 CSGTarget::getTransform TODO eliminate this switching instead to getInstanceTransform
0421 ----------------------------------------------------------------------------------------
0422 
0423 **/
0424 
0425 int CSGTarget::getTransform(qat4& q, int midx, int mord, int gord) const
0426 {
0427     const qat4* qi = getInstanceTransform(midx, mord, gord);
0428     if( qi == nullptr )
0429     {
0430         return 1 ;
0431     }
0432     qat4::copy(q, *qi);
0433     return 0 ;
0434 }
0435 
0436 /**
0437 CSGTarget::getInstanceTransform (midx,mord) CSGPrim -> repeatIdx -> which with gord -> instance transform
0438 ------------------------------------------------------------------------------------------------------------
0439 
0440 1. *CSGFoundry::getMeshPrim* finds the (midx, mord) (CSGPrim)lpr
0441 2. (CSGPrim)lpr gives the repeatIdx (aka:gas_idx or compound solid index)
0442 3. *CSGFoundry::getInstance_with_GAS_ordinal* finds the (gas_idx, gord) instance transform
0443 
0444 NB gord was previously named iidx (but that clashes with other uses of that)
0445 
0446 This method avoids duplication between CSGTarget::getTransform and  CSGTarget::getGlobalCenterExtent
0447 
0448 Note that the (midx,mord) CSGPrim is accessed purely to
0449 find out which gas_idx it has and then use that together with
0450 the gord gas-ordinal to get the corresponding instance transform.
0451 
0452 Using (midx,mord) as input rather than gas_idx directly is because
0453 they are more fundamental whereas the gas_idx may change when adjust
0454 instancing criteria for example.
0455 
0456 The mord is often zero, but its needed for handling possible repeats of a midx/solid.
0457 
0458 **/
0459 
0460 const qat4* CSGTarget::getInstanceTransform(int midx, int mord, int gord) const
0461 {
0462     const CSGPrim* lpr = foundry->getMeshPrim(midx, mord);
0463     if(!lpr)
0464     {
0465         LOG(fatal) << "Foundry::getMeshPrim failed for (midx mord) " << "(" << midx << " " <<  mord << ")"  ;
0466         return nullptr ;
0467     }
0468 
0469     const float4 local_ce = lpr->ce() ;
0470     unsigned repeatIdx = lpr->repeatIdx(); // use the prim to lookup indices for  the solid and prim
0471     unsigned primIdx = lpr->primIdx();
0472     unsigned gas_idx = repeatIdx ;
0473 
0474     LOG(LEVEL)
0475         << " (midx mord gord) " << "(" << midx << " " << mord << " " << gord << ") "
0476         << " lpr " << lpr
0477         << " repeatIdx " << repeatIdx
0478         << " primIdx " << primIdx
0479         << " local_ce " << local_ce
0480         ;
0481 
0482     const qat4* qi = foundry->getInstance_with_GAS_ordinal(gas_idx, gord );
0483     return qi ;
0484 }
0485 
0486 
0487 
0488