////////////////////////////////////////////////////////////////////////////////////////////////// // // File: pickSample.cpp // // Author: Frank Luna (C) All Rights Reserved // // Edited by Tom Plick, 28 July 2005 ////////////////////////////////////////////////////////////////////////////////////////////////// #include "d3dUtility.h" extern IDirect3DDevice9* Device; // // Functions // d3d::Ray CalcPickingRay(int x, int y) { float px = 0.0f; float py = 0.0f; D3DVIEWPORT9 vp; Device->GetViewport(&vp); D3DXMATRIX proj; Device->GetTransform(D3DTS_PROJECTION, &proj); px = ((( 2.0f*x) / vp.Width) - 1.0f) / proj(0, 0); py = (((-2.0f*y) / vp.Height) + 1.0f) / proj(1, 1); d3d::Ray ray; ray._origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f); ray._direction = D3DXVECTOR3(px, py, 1.0f); return ray; } void TransformRay(d3d::Ray* ray, D3DXMATRIX* T) { // transform the ray's origin, w = 1. D3DXVec3TransformCoord( &ray->_origin, &ray->_origin, T); // transform the ray's direction, w = 0. D3DXVec3TransformNormal( &ray->_direction, &ray->_direction, T); // normalize the direction D3DXVec3Normalize(&ray->_direction, &ray->_direction); } bool RaySphereIntTest(d3d::Ray* ray, d3d::BoundingSphere* sphere) { D3DXVECTOR3 v = ray->_origin - sphere->_center; float b = 2.0f * D3DXVec3Dot(&ray->_direction, &v); float c = D3DXVec3Dot(&v, &v) - (sphere->_radius * sphere->_radius); // find the discriminant float discriminant = (b * b) - (4.0f * c); // test for imaginary number if( discriminant < 0.0f ) return false; discriminant = sqrtf(discriminant); float s0 = (-b + discriminant) / 2.0f; float s1 = (-b - discriminant) / 2.0f; // if a solution is >= 0, then we intersected the sphere if( s0 >= 0.0f || s1 >= 0.0f ) return true; return false; } // // GetRay // d3d::Ray GetPickingRay(LPARAM lParam) { // compute the ray in view space given the clicked screen point d3d::Ray ray = CalcPickingRay(LOWORD(lParam), HIWORD(lParam)); // transform the ray to world space D3DXMATRIX view; Device->GetTransform(D3DTS_VIEW, &view); D3DXMATRIX viewInverse; D3DXMatrixInverse(&viewInverse, 0, &view); TransformRay(&ray, &viewInverse); return ray; } char * StringifyRay(d3d::Ray ray) { static char s[200]; sprintf(s, "origin (%.2f, %.2f, %.2f);\ndirection <%.2f, %.2f, %.2f>", ray._origin.x, ray._origin.y, ray._origin.z, ray._direction.x, ray._direction.y, ray._direction.z); return s; }