In practical applications, we often use a ball or a box to test the intersection of an object and a ray. Assume that the ray is intersecting with the box or ball, in fact, many calculations in the 3D world are inaccurate, just simple simulation and similar operations. Because it does not need to be completely accurate.
Taking the ball as an example, the ball can be represented by the ball center O and the radius R. Assume that the point P is on the ball, that is, the condition is met:
| P-o | = r
That is, the distance from P to o is equal to the sphere radius R,
The ray equation is:
P (t) = PO + TU
Po indicates the starting point of the ray, and u indicates the direction of the ray. t indicates a scalar. Therefore, we can use these two vectors to define the structure of the ray,
The following structure is defined:
Struct Ray
{
D3dxvector3 _ origin; // Ray start point
D3dxvector3 _ derction; // Ray Direction
};
Assuming that the ray and sphere intersect, there must be a point PT on both the ray and the sphere. Then we can bring the ray equation into the spherical equation:
| Pt-o | = r // PT on the circular surface, the distance from PT to the center o is equal to R
| PO + TU |-r = O // if p (t) = PO + TU is on the circular surface, so satisfied | PO + TU | = r the point PT on the ray obtained by this equation is satisfied on the circle
Obviously, to satisfy this condition is to solve the T value in the equation and convert the formula:
(PO + TU-O) 2 = R2
Convert the final company into a quadratic equation:
A = u2
B = 2u (p0-0)
C = (po-O) 2-r2
At2 + bt + c = 0
Since the direction of the ray U is the unit vector, so a = 1, the above equation can be solved to get the following two answers:
T0= (-B + (B2-4c) Square)/2
T1= (-B-(B2-4c) Square)/2
Void cgame: handlemessage (hwnd, uint message, wparam, lparam)
{
Switch (Message)
{
Case wm_lbuttondown:
{
Point pt;
Getcursorpos (& pt );
Screentoclient (hwnd, & pt );
Ray = calculateray (Pt. X, Pt. y );
D3dxmatrix MAT;
M_pdevice-> gettransform (d3dts_view, & mat );
D3dxmatrixinverse (& mat, null, & mat );
Ray = transformray (Ray, & mat );
For (INT I = 0; I <2; ++ I)
{
If (checkintersection (& ray, & m_boundsphere [I])
M_brotate [I] = true;
Else
M_brotate [I] = false;
}
}
Break;
}
}
Cgame: Ray cgame: calculateray (int x, int y)
{
Float PX = 0.0f;
Float py = 0.0f;
// Obtain the size of the view.
D3dviewport9 VP;
M_pdevice-> getviewport (& vp );
// Obtain the Projection Matrix
D3dxmatrix proj;
M_pdevice-> gettransform (d3dts_projection, & proj );
// Calculate the pickup Ray
Px = (2.0f * X)/VP. width)-1.0f)/proj. _ 11;
Py = (-2.0f * Y)/VP. Height) + 1.0f)/proj. _ 22;
Ray;
Ray. _ origin = d3dxvector3 (0.0f, 0.0f, 0.0f );
Ray. _ dirction = d3dxvector3 (PX, Py, 1.0f );
Return Ray;
}
Cgame: Ray cgame: transformray (Ray, d3dxmatrix * t)
{
Ray transray;
// Start point of the conversion Ray
D3dxvec3transformcoord (& transray. _ origin, & ray. _ origin, t );
// Convert the direction of the ray
D3dxvec3transformnormal (& transray. _ dirction, & ray. _ dirction, t );
D3dxvec3normalize (& transray. _ dirction, & transray. _ dirction );
Return transray;
}
Bool cgame: checkintersection (Ray * Ray, boundsphere * sphere)
{
// Calculate the T0 and T1 values
D3dxvector3 v = Ray-> _ origin-sphere-> _ center;
Float B = 2.0f * d3dxvec3dot (& ray-> _ dirction, & V );
Float c = d3dxvec3dot (& V, & V)-(sphere-> radius * sphere-> radius );
Float n = (B * B)-(4.0f * C );
If (n <0.0f)
{
Return false;
}
N = sqrtf (N );
Float T0 = (-B + N)/2.0f;
Float T1 = (-B-N)/2.0f;
// Determine whether the intersection exists
If (T0> = 0 | T1> = 0)
{
Return true;
}
Return false;
}