@@ -25,10 +25,8 @@ using namespace collide;
2525// Class : CXR_CFObject
2626// Purpose : stores collision form
2727// ----------------------------------------------------------------------
28- ICollisionForm::ICollisionForm ( CObject* _owner, ECollisionFormType tp )
28+ ICollisionForm::ICollisionForm ( CObject* _owner, ECollisionFormType tp ) : owner(_owner), m_type(tp)
2929{
30- owner = _owner;
31- m_type = tp;
3230 bv_sphere.identity ( );
3331}
3432
@@ -141,8 +139,8 @@ void CCF_Skeleton::BuildState()
141139 if (!I->valid ()) continue ;
142140 SBoneShape& shape = K->LL_GetData (I->elem_id ).shape ;
143141 Fmatrix ME,T,TW;
144- const Fmatrix& Mbone = K-> LL_GetTransform (I-> elem_id ) ;
145-
142+ Fmatrix Mbone;
143+ K-> LL_GetBoneLocalTransform (I-> elem_id , Mbone);
146144 VERIFY2 ( DET (Mbone)>EPS, (make_string<const char *>(" 0 scale bone matrix, %d \n " , I->elem_id ) + dbg_object_full_dump_string ( owner ) ).c_str () );
147145
148146 switch (I->type ){
@@ -320,50 +318,64 @@ BOOL CCF_Shape::_RayQuery(const collide::ray_defs& Q, collide::rq_results& R)
320318 // Convert ray into local model space
321319 Fvector dS, dD;
322320 Fmatrix temp;
323- temp.invert (owner->XFORM ());
324- temp.transform_tiny (dS,Q.start );
325- temp.transform_dir (dD,Q.dir );
326-
327- //
328- if (!bv_sphere.intersect (dS,dD)) return FALSE ;
321+ temp.invert (owner->XFORM ());
322+ temp.transform_tiny (dS,Q.start );
323+ temp.transform_dir (dD,Q.dir );
329324
325+ if (!bv_sphere.intersect (dS,dD))
326+ return FALSE ;
327+ float & range = const_cast <float &>(Q.range );
330328 BOOL bHIT = FALSE ;
331329 for (u32 el=0 ; el<shapes.size (); el++)
332330 {
333331 shape_def& shape= shapes[el];
334- float range = Q. range ;
332+
335333 switch (shape.type )
336334 {
337- case 0 :
338- { // sphere
339- Fsphere::ERP_Result rp_res = shape.data .sphere .intersect (dS,dD,range);
340- if ((rp_res==Fsphere::rpOriginOutside)||(!(Q.flags &CDB::OPT_CULL)&&(rp_res==Fsphere::rpOriginInside))){
341- bHIT = TRUE ;
342- R.append_result (owner,range,el,Q.flags &CDB::OPT_ONLYNEAREST);
335+ case 0 : // sphere
336+ {
337+ float current_range = range;
338+ Fsphere::ERP_Result rp_res = shape.data .sphere .intersect (dS, dD, current_range);
339+ if ((rp_res==Fsphere::rpOriginOutside)||(!(Q.flags &CDB::OPT_CULL)&&(rp_res==Fsphere::rpOriginInside)))
340+ {
341+ bHIT = TRUE ;
342+ range = current_range;
343+ R.append_result (owner, range, el, Q.flags &CDB::OPT_ONLYNEAREST);
343344 if (Q.flags &CDB::OPT_ONLYFIRST) return TRUE ;
344345 }
345346 }
346347 break ;
347- case 1 : // box
348+ case 1 : // box
348349 {
349- Fbox box;
350- box.identity ();
351- Fmatrix& B = shape.data .ibox ;
352- Fvector S1,D1,P;
353- B.transform_tiny (S1,dS);
354- B.transform_dir (D1,dD);
355- Fbox::ERP_Result rp_res = box.Pick2 (S1,D1,P);
356- if ((rp_res==Fbox::rpOriginOutside)||(!(Q.flags &CDB::OPT_CULL)&&(rp_res==Fbox::rpOriginInside))){
357- float d = P.distance_to_sqr (dS);
358- if (d<range*range) {
359- range = _sqrt (d);
360- bHIT = TRUE ;
361- R.append_result (owner,range,el,Q.flags &CDB::OPT_ONLYNEAREST);
350+ Fbox box;
351+ box.identity ();
352+ Fmatrix& IB = shape.data .ibox ;
353+ Fmatrix& B = shape.data .box ;
354+ Fvector S1, D1, P_box_space;
355+ IB.transform_tiny (S1, dS);
356+ IB.transform_dir (D1, dD);
357+
358+ Fbox::ERP_Result rp_res = box.Pick2 (S1, D1, P_box_space);
359+ if ((rp_res==Fbox::rpOriginOutside)||(!(Q.flags &CDB::OPT_CULL)&&(rp_res==Fbox::rpOriginInside)))
360+ {
361+ Fvector P_world;
362+ B.transform_tiny (P_world, P_box_space);
363+
364+ Fvector ray_to_point;
365+ ray_to_point.sub (P_world, dS);
366+
367+ float dot = ray_to_point.dotproduct (dD);
368+
369+ if (dot>0 .f &&dot<range)
370+ {
371+ range = dot;
372+ bHIT = TRUE ;
373+ R.append_result (owner, range, el, Q.flags &CDB::OPT_ONLYNEAREST);
362374 if (Q.flags &CDB::OPT_ONLYFIRST) return TRUE ;
363375 }
364376 }
377+ break ;
365378 }
366- break ;
367379 }
368380 }
369381 return bHIT;
@@ -389,7 +401,13 @@ void CCF_Shape::add_box (Fmatrix& B )
389401
390402void CCF_Shape::ComputeBounds ()
391403{
392- bv_box.invalidate ();
404+ bv_box.invalidate ();
405+
406+ if (shapes.empty ())
407+ {
408+ Fsphere shphere{ zero_vel, 1 .0f };
409+ add_sphere (shphere);
410+ }
393411
394412 BOOL bCalcSphere = (shapes.size ()>1 );
395413 for (u32 el=0 ; el<shapes.size (); el++)
0 commit comments