Skip to content

Commit 8f8dda2

Browse files
committed
Fix shape intersection issues
1 parent d60a70d commit 8f8dda2

File tree

1 file changed

+52
-34
lines changed

1 file changed

+52
-34
lines changed

src/xrEngine/xr_collide_form.cpp

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -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

390402
void 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

Comments
 (0)