#include "d3dUtility.h"
#pragma warning(disable : 4100)constintWIDTH = 640;constintHEIGHT = 480;
IDirect3DDevice9* g_device;
ID3DXMesh* g_teapot;
ID3DXMesh* g_sphere;
D3DXMATRIX g_world_matrix;
cBoundingSphere g_bounding_sphere;sRay calculate_picking_ray(intx,inty)
{
D3DVIEWPORT9 viewport;
g_device->GetViewport(&viewport);
D3DXMATRIX proj_matrix;
g_device->GetTransform(D3DTS_PROJECTION, &proj_matrix);floatpx = ((( 2.0f * x) / viewport.Width) - 1.0f) / proj_matrix(0, 0);floatpy = (((-2.0f * y) / viewport.Height) + 1.0f) / proj_matrix(1, 1);
sRay ray;
ray.origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
ray.direction = D3DXVECTOR3(px, py, 1.0f);returnray;
}voidtransform_ray(sRay* ray, D3DXMATRIX* trans_matrix)
{// transform the ray's origin, w = 1.D3DXVec3TransformCoord(&ray->origin, &ray->origin, trans_matrix);// transform the ray's direction, w = 0.D3DXVec3TransformNormal(&ray->direction, &ray->direction, trans_matrix);// normalize the directionD3DXVec3Normalize(&ray->direction, &ray->direction);
}boolray_sphere_intersect(sRay* ray, cBoundingSphere* sphere)
{
D3DXVECTOR3 v = ray->origin - sphere->m_center;floatb = 2.0f * D3DXVec3Dot(&ray->direction, &v);floatc = D3DXVec3Dot(&v, &v) - (sphere->m_radius * sphere->m_radius);floatdiscriminant = (b * b) - (4.0f * c);if(discriminant
discriminant = sqrt(discriminant);floats0 = (-b + discriminant) / 2.0f;floats1 = (-b - discriminant) / 2.0f;// if one solution is >= 0, then we intersected the sphere.return(s0 >= 0.0f || s1 >= 0.0f);
}boolsetup()
{
D3DXCreateTeapot(g_device, &g_teapot, NULL);// compute the bounding sphereBYTE* v;
g_teapot->LockVertexBuffer(0, (void**)&v);
D3DXComputeBoundingSphere(
(D3DXVECTOR3*)v,
g_teapot->GetNumVertices(),
D3DXGetFVFVertexSize(g_teapot->GetFVF()),
&g_bounding_sphere.m_center,
&g_bounding_sphere.m_radius);
g_teapot->UnlockVertexBuffer();// build a sphere mesh that describes the teapot's bounding sphereD3DXCreateSphere(g_device, g_bounding_sphere.m_radius, 20, 20, &g_sphere, NULL);// set lightD3DXVECTOR3 dir(0.707f, -0.0f, 0.707f);
D3DXCOLOR color(1.0f, 1.0f, 1.0f, 1.0f);
D3DLIGHT9 light = init_directional_light(&dir, &color);
g_device->SetLight(0, &light);
g_device->LightEnable(0, TRUE);
g_device->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
g_device->SetRenderState(D3DRS_SPECULARENABLE, FALSE);// Set view matrixD3DXVECTOR3 pos(0.0f, 0.0f, -10.0f);
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX view_matrix;
D3DXMatrixLookAtLH(&view_matrix, &pos, &target, &up);
g_device->SetTransform(D3DTS_VIEW, &view_matrix);// set the projection matrixD3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
g_device->SetTransform(D3DTS_PROJECTION, &proj);returntrue;
}///voidcleanup()
{
safe_release(g_teapot);
safe_release(g_sphere);
}///booldisplay(floattime_delta)
{// update teapotstaticfloatradius = 0.0f;staticfloatangle = 0.0f;
D3DXMatrixTranslation(&g_world_matrix, cos(angle) * radius, sin(angle) * radius, 10.0f);// transform the bounding sphere to match the teapot's position in the worldg_bounding_sphere.m_center = D3DXVECTOR3(cos(angle) * radius, sin(angle) * radius, 10.0f);staticfloatvelocity = 1.0f;
radius += velocity * time_delta;if(radius >= 8.0f || radius <= 0.0f)
velocity = -velocity;// reverse directionangle += D3DX_PI * time_delta;if(angle >= D3DX_PI * 2.0f)
angle = 0.0f;// render nowg_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
g_device->BeginScene();
g_device->SetTransform(D3DTS_WORLD, &g_world_matrix);
g_device->SetMaterial(&RED_MATERIAL);
g_teapot->DrawSubset(0);// render the bounding sphere with alpha blending so we can see through itg_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
D3DMATERIAL9 yellow_material = YELLOW_MATERIAL;
yellow_material.Diffuse.a = 0.25f;// 25% opacityg_device->SetMaterial(&yellow_material);
g_sphere->DrawSubset(0);
g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
g_device->EndScene();
g_device->Present(NULL, NULL, NULL, NULL);returntrue;
}///LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
{switch(msg)
{caseWM_DESTROY:
PostQuitMessage(0);break;caseWM_KEYDOWN:if(word_param == VK_ESCAPE)
DestroyWindow(hwnd);break;caseWM_LBUTTONDOWN:// compute the ray in view space given by the clicked screen pointsRay ray = calculate_picking_ray(LOWORD(long_param), HIWORD(long_param));// transform the ray to world spaceD3DXMATRIX view_matrix, view_inverse_matrix;
g_device->GetTransform(D3DTS_VIEW, &view_matrix);
D3DXMatrixInverse(&view_inverse_matrix, NULL, &view_matrix);
transform_ray(&ray, &view_inverse_matrix);if(ray_sphere_intersect(&ray, &g_bounding_sphere))
MessageBox(NULL, "Hit teapot's bounding sphere!", "HIT", MB_OK);break;
}returnDefWindowProc(hwnd, msg, word_param, long_param);
}///intWINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line,intcmd_show)
{if(! init_d3d(inst, WIDTH, HEIGHT,true, D3DDEVTYPE_HAL, &g_device))
{
MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);return0;
}if(! setup())
{
MessageBox(NULL, "Steup() - failed.", 0, MB_OK);return0;
}
enter_msg_loop(display);
cleanup();
g_device->Release();return0;
}