Ray vs Box Issue

Started by
1 comment, last by Cydriic 9 years, 2 months ago

Sup Everyone,

I'm having a problem where my Ray vs Box algorithm doesn't seem to work.

Sometimes it return a collision, but 98% of the time it doesn't.

The algorithm seems good though.

Can anyone tell me if you see anything misplaced or missing?

This is a code snippet from my Wall3x3 Object.

m_x, m_y, m_z is the center of my wall.

x,y,z are the coordinates of the Origin of the Ray.

Roty and Rotx are the angles of the Ray's direction.

m_Cx, m_Cy and m_Cz are the coordinates of the collision point.

Finally, my wall is 600 wide by 20 thick by 600 high. Thus the m_x - 300 and m_x + 300 and ect and my Box boundaries.

bool CWall3x3::FastProjectileCollisions( GLfloat x, GLfloat y, GLfloat z, GLfloat Rotx, GLfloat Roty )
{

//COMPUTE Ts
GLfloat T0x = (m_x - 300.0f - x)/( -(float)sin(Roty*piover180) );
GLfloat T1x = (m_x + 300.0f - x)/( -(float)sin(Roty*piover180) );
GLfloat T0y = (m_y - 300.0f - y)/( -(float)sin(Rotx*piover180) );
GLfloat T1y = (m_y + 300.0f - y)/( -(float)sin(Rotx*piover180) );
GLfloat T0z = (m_z + 10.0f - z)/( -(float)cos(Roty*piover180) );
GLfloat T1z = (m_z - 10.0f - z)/( -(float)cos(Roty*piover180) );
//COMPUTE TMIN AND TMAX
GLfloat Tmin;
GLfloat Tmax;
//Tmin
if(T0x > T0y)
Tmin = T0x;
if(T0y > T0x)
Tmin = T0y;
//Tmax
if(T1x > T1y)
Tmax = T1x;
if(T1y > T1x)
Tmax = T1y;
//FIRST MISS BOX CHECK
if(T0x > T1y || T0y > T1x)
return false;
//EXTEND TO 3D
//SECOND MISS BOX CHECK
if(Tmin > T1z || T0z > Tmax)
return false;
//ALSO
if(T0z > Tmin)
Tmin = T0z;
if(T1z < Tmax)
Tmax = T1z;
//COMPUTE COLLISION COORDINATES
m_Cx = x - (float)sin(Roty*piover180) * Tmin;
m_Cy = y - (float)sin(Rotx*piover180) * Tmin;
m_Cz = z - (float)cos(Roty*piover180) * Tmin;
//RAY INTERSECTS RETURN TRUE
return true;
}
Advertisement
I highly suggest you set up a simple test case with a ray that is known to collide (but doesn't work with your code) and step through your logic in a debugger.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Thank Apoch,

I followed your advice and went to work! Fixed it, now it works awesome here is the code.

So basically I compute all my potential intersection point Ts.

Then I test the potential itersection points on the Box collision mesh, discarding all point related to a negative T, because that would mean my Ray is colliding with a Box that is behind the character firing.

So here is the fixed code for my Ray Vs Box, thanks everyone.

Note that the collision test is different depending on the Rotation of the Box around the Y (up vector) Axis. Because, this code applies for Boxes that are Aligned with the Grid (where Y is the Up vector). Therefore, my box will only have two possible Rotations in the world 0.0f and 90.0f.

I use it for outside containers, crates, tables and walls in my game. Other objects use a Ray vs Sphere Collision test for now.

bool CWall3x3::FastProjectileCollisions( GLfloat x, GLfloat y, GLfloat z, GLfloat Rotx, GLfloat Roty )
{
if(m_Roty == 0.0f)
{
//COMPUTE Ts
GLfloat T0x = (m_x - 300.0f - x)/( -(float)sin(Roty*piover180) );
GLfloat T1x = (m_x + 300.0f - x)/( -(float)sin(Roty*piover180) );
GLfloat T0y = (m_y - 300.0f - y)/( -(float)sin(Rotx*piover180) );
GLfloat T1y = (m_y + 300.0f - y)/( -(float)sin(Rotx*piover180) );
GLfloat T0z = (m_z - 10.0f - z)/( -(float)cos(Roty*piover180) );
GLfloat T1z = (m_z + 10.0f - z)/( -(float)cos(Roty*piover180) );
//COMPUTE COLLISION COORDINATES
if(T0x > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T0x;
m_Cy = y - (float)sin(Rotx*piover180) * T0x;
m_Cz = z - (float)cos(Roty*piover180) * T0x;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 300.0f && m_Cx <= m_x + 300.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 10.0f && m_Cz <= m_z + 10.0f)
return true;
}
if(T1x > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T1x;
m_Cy = y - (float)sin(Rotx*piover180) * T1x;
m_Cz = z - (float)cos(Roty*piover180) * T1x;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 300.0f && m_Cx <= m_x + 300.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 10.0f && m_Cz <= m_z + 10.0f)
return true;
}
if(T0y > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T0y;
m_Cy = y - (float)sin(Rotx*piover180) * T0y;
m_Cz = z - (float)cos(Roty*piover180) * T0y;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 300.0f && m_Cx <= m_x + 300.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 10.0f && m_Cz <= m_z + 10.0f)
return true;
}
if(T1y > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T1y;
m_Cy = y - (float)sin(Rotx*piover180) * T1y;
m_Cz = z - (float)cos(Roty*piover180) * T1y;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 300.0f && m_Cx <= m_x + 300.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 10.0f && m_Cz <= m_z + 10.0f)
return true;
}
if(T0z > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T0z;
m_Cy = y - (float)sin(Rotx*piover180) * T0z;
m_Cz = z - (float)cos(Roty*piover180) * T0z;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 300.0f && m_Cx <= m_x + 300.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 10.0f && m_Cz <= m_z + 10.0f)
return true;
}
if(T1z > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T1z;
m_Cy = y - (float)sin(Rotx*piover180) * T1z;
m_Cz = z - (float)cos(Roty*piover180) * T1z;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 300.0f && m_Cx <= m_x + 300.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 10.0f && m_Cz <= m_z + 10.0f)
return true;
}
}
if(m_Roty == 90.0f)
{
//COMPUTE Ts
GLfloat T0x = (m_x - 10.0f - x)/( -(float)sin(Roty*piover180) );
GLfloat T1x = (m_x + 10.0f - x)/( -(float)sin(Roty*piover180) );
GLfloat T0y = (m_y - 300.0f - y)/( -(float)sin(Rotx*piover180) );
GLfloat T1y = (m_y + 300.0f - y)/( -(float)sin(Rotx*piover180) );
GLfloat T0z = (m_z - 300.0f - z)/( -(float)cos(Roty*piover180) );
GLfloat T1z = (m_z + 300.0f - z)/( -(float)cos(Roty*piover180) );
//COMPUTE COLLISION COORDINATES
if(T0x > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T0x;
m_Cy = y - (float)sin(Rotx*piover180) * T0x;
m_Cz = z - (float)cos(Roty*piover180) * T0x;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 10.0f && m_Cx <= m_x + 10.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 300.0f && m_Cz <= m_z + 300.0f)
return true;
}
if(T1x > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T1x;
m_Cy = y - (float)sin(Rotx*piover180) * T1x;
m_Cz = z - (float)cos(Roty*piover180) * T1x;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 10.0f && m_Cx <= m_x + 10.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 300.0f && m_Cz <= m_z + 300.0f)
return true;
}
if(T0y > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T0y;
m_Cy = y - (float)sin(Rotx*piover180) * T0y;
m_Cz = z - (float)cos(Roty*piover180) * T0y;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 10.0f && m_Cx <= m_x + 10.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 300.0f && m_Cz <= m_z + 300.0f)
return true;
}
if(T1y > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T1y;
m_Cy = y - (float)sin(Rotx*piover180) * T1y;
m_Cz = z - (float)cos(Roty*piover180) * T1y;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 10.0f && m_Cx <= m_x + 10.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 300.0f && m_Cz <= m_z + 300.0f)
return true;
}
if(T0z > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T0z;
m_Cy = y - (float)sin(Rotx*piover180) * T0z;
m_Cz = z - (float)cos(Roty*piover180) * T0z;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 10.0f && m_Cx <= m_x + 10.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 300.0f && m_Cz <= m_z + 300.0f)
return true;
}
if(T1z > 0)
{
m_Cx = x - (float)sin(Roty*piover180) * T1z;
m_Cy = y - (float)sin(Rotx*piover180) * T1z;
m_Cz = z - (float)cos(Roty*piover180) * T1z;
//RAY INTERSECTS RETURN TRUE
if(m_Cx >= m_x - 10.0f && m_Cx <= m_x + 10.0f && m_Cy >= m_y - 300.0f && m_Cy <= m_y + 300.0f && m_Cz >= m_z - 300.0f && m_Cz <= m_z + 300.0f)
return true;
}
}
return false;
}

This topic is closed to new replies.

Advertisement