Ray Cast Normal

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Ray Cast Normal

Postby Firefly » Fri Nov 06, 2009 10:39 pm

What's the correct way to get the normal of a surface from a ray cast? I'm using this code at the moment but I'm not sure if gets the correct normal every time:
Code: Select all
static dFloat RayCastPlacement (const NewtonBody* body, const dFloat* normal, int collisionID, void* userData, dFloat intersetParam)
   {
      sRayCastData* pRayData;
      pRayData = (sRayCastData*)userData;
      
      if (intersetParam < pRayData->fParam)
      {
         pRayData->fParam = intersetParam;
      }

      pRayData->vNormal = D3DXVECTOR3(normal[0], normal[1], normal[2]);
      pRayData->pBody = (NewtonBody*)body;

      return pRayData->fParam;
   }

   sRayCastData FindFloor (const NewtonWorld* world, const D3DXVECTOR3& p0, const D3DXVECTOR3& p1)
   {
      sRayCastData rayData;
      rayData.fParam = 1.2f;
   
      // shoot a ray from p0 to p1 and find the point where it hits
      NewtonWorldRayCast (world, &p0[0], &p1[0], RayCastPlacement, &rayData, NULL);

      // the intersection is the interpolated value
      rayData.vHit = (p0 + (p1 - p0) * rayData.fParam);
      
      return rayData;
   }


I'm trying to align an object to my terrains surface and it seems to work 70% of the time,but other times the object spins around upside down or goes all wobbly and doesn't orientate properly so I thought maybe the surface normal is wrong sometimes. My other thought was maybe my code to orientate is wrong so I'll provide that too just in case:

Code: Select all
// cast a ray to the ground and position the unit just above ground
   NewtonWorld* world = g_pEngine->GetNewtonWorld();
   D3DXVECTOR3 startpos = m_vPosition;
   D3DXVECTOR3 endpos = m_vPosition;
   startpos.y += 100;
   endpos.y -= 1000;
   Util::sRayCastData rayData = Util::FindFloor(world, m_vPosition, endpos);

   rayData.vHit.y += 3;
   m_vPosition.y = rayData.vHit.y;

   // rotate unit to match ground angle
   D3DXQUATERNION tankAligned;
   D3DXVECTOR3 terrainNormal = rayData.vNormal;
   D3DXVECTOR3 rotationAxis;
   D3DXVec3Cross(&rotationAxis, &m_vUp, &terrainNormal);
   D3DXVec3Normalize(&rotationAxis, &rotationAxis);

   float angle = acos( D3DXVec3Dot(&m_vUp, &terrainNormal) );
   
   D3DXQuaternionRotationAxis(&tankAligned, &rotationAxis, angle);
   D3DXQuaternionNormalize(&tankAligned, &tankAligned);

   D3DXQUATERNION newOrientation = m_HeadingOrient * tankAligned;

   D3DXQuaternionSlerp(&m_Orientation, &m_Orientation, &newOrientation, 0.7f);


Thanks!
Firefly
 
Posts: 32
Joined: Wed Jan 17, 2007 4:58 am

Re: Ray Cast Normal

Postby Julio Jerez » Sat Nov 07, 2009 12:13 am

maybe like this

Code: Select all
     if (intersetParam < pRayData->fParam)
      {
         pRayData->fParam = intersetParam;
         pRayData->vNormal = D3DXVECTOR3(normal[0], normal[1], normal[2]);
         pRayData->pBody = (NewtonBody*)body;
      }
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Ray Cast Normal

Postby Firefly » Mon Nov 09, 2009 2:59 am

That makes sense but technically with my code it should always hit the surface below the game unit. I made the change anyway and in my quick test it seems a tiny bit better but some units still wobble a bit sometimes.

Can you take a look at my alignment code and see if theres something wrong there? My math isn't the greatest so it's possible I'm doing something slightly wrong in that section.

Thanks!
Firefly
 
Posts: 32
Joined: Wed Jan 17, 2007 4:58 am

Re: Ray Cast Normal

Postby Julio Jerez » Mon Nov 09, 2009 10:25 am

well in this code
Code: Select all
D3DXVec3Cross(&rotationAxis, &m_vUp, &terrainNormal);
D3DXVec3Normalize(&rotationAxis, &rotationAxis);

when m_vUp and terrainNormal are colineal
the cross prodict will be zero, are you sure thsy are never colinear?

also in this code, and I beleiev this is the bigger Bug
Code: Select all
D3DXQUATERNION newOrientation = m_HeadingOrient * tankAligned;
D3DXQuaternionSlerp(&m_Orientation, &m_Orientation, &newOrientation, 0.7f);

if m_Orientation and newOrientation are quaternion, it is possible that one of the quaterion flip and slerp take the shorter route
My guess this is the bug, you can fix it eassily like this

Code: Select all
D3DXQUATERNION newOrientation = m_HeadingOrient * tankAligned;
float dot = DotProduct (m_Orientation,  newOrientation)
if (dot < 0)  {
     newOrientation = newOrientation * -1.0;
}
D3DXQuaternionSlerp(&m_Orientation, &m_Orientation, &newOrientation, 0.7f);
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Ray Cast Normal

Postby Firefly » Thu Nov 12, 2009 3:32 am

I tried that flipping bug fix you mentioned but it made it worse :( I didn't think aligning an object to the surface would be so difficult.

Is there a way I can render the normals to make sure they are all correct?

And do you have any other ideas of what could be causing this weird problem?
Firefly
 
Posts: 32
Joined: Wed Jan 17, 2007 4:58 am

Re: Ray Cast Normal

Postby Stucuk » Thu Nov 12, 2009 6:50 am

Firefly wrote:Is there a way I can render the normals to make sure they are all correct?


If you can render a line in Direct X like you can in OpenGL then you just need to make a line which goes from the Position to say Position + Normal*5 . 5 Can be any number.
User avatar
Stucuk
 
Posts: 801
Joined: Sat Mar 12, 2005 3:54 pm
Location: Scotland

Re: Ray Cast Normal

Postby Julio Jerez » Thu Nov 12, 2009 7:46 am

It is not dificult.

beside the normal and m_up I do not know wha the the values are.
also I do no knwo what you are usinhg acos fo find the angle.
My guess is the yu have a geomerical misrepresentaion of some value.

if you make a disgram of how the line are orinentd I migh be able to write a pseudo function for you.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 0 guests

cron