`
webcenterol
  • 浏览: 915454 次
文章分类
社区版块
存档分类
最新评论

Direct3D中的Pick技术

 
阅读更多

------------------------

pick.h

------------------------

#pragma once
#include <vector>
using std::vector;

struct PickResult
{
DWORD dwFace; // mesh face that was intersected
FLOAT fBary1, fBary2; // barycentric coords of intersection
FLOAT fDist; // distance from ray origin to intersection
FLOAT tu, tv; // texture coords of intersection
RenderObject *object;
float3 hitpoint;
};

struct D3DVERTEX
{
float3 p;
float3 normal;
FLOAT tu, tv;
static const DWORD FVF;//Flexible Vertex Format
};


class Pick
{


public:


Pick(void);
~Pick(void);
vector<PickResult> Excute(int mouseX,int mouseY,Camera* camer);
void SetMesh(vector<RenderObject*> objects);


private:


vector<RenderObject*> normalObjects;
HRESULT CreateRay(int mouseX,int mouseY);
vector<PickResult> m_IntersectionArray;
float3 vPickRayDir;//射线的方向向量
float3 vPickRayOrig;//射线的起始点
Camera* m_pCamera;


};

----------------------

pick.cpp

----------------------

#include "stdafx.h"
#include "Pick.h"
#define MAX_INTERSECTIONS 16


Pick::Pick(void)
{
}

Pick::~Pick(void)
{
}

void Pick::SetMesh(vector<RenderObject*> objects)
{
normalObjects=objects;
}

HRESULT Pick::CreateRay(int mouseX,int mouseY)
{
//获取投影矩阵
float4x4 matProj=m_pCamera->GetMatProj();
//计算从屏幕坐标到投影矩阵坐标
float3 v;
float width=D3Dsystem::GetInstance()->GetDeviceWidth();
float height=D3Dsystem::GetInstance()->GetDeviceHeight();
v.x =(((2.0f*mouseX)/width)-1)/matProj._11;
v.y =-(((2.0f*mouseY)/height)-1)/matProj._22;
v.z =1.0f;
//获取视图矩阵的逆矩阵
float4x4 matView=m_pCamera->GetMatView();
float4x4 m;
D3DXMatrixInverse( &m, NULL, &matView );//计算逆矩阵
D3DXVec3TransformNormal(&vPickRayDir,&v,&m);
D3DXVec3Normalize(&vPickRayDir,&vPickRayDir);
float3 o = float3(0,0,0);
D3DXVec3TransformCoord(&vPickRayOrig,&o,&m);//(x, y, z, 1):w=1
return S_OK;
}

bool SortFunction(const PickResult &r0,const PickResult &r1)
{

return r0.fDist< r1.fDist ? true:false;
}

vector<PickResult> Pick::Excute(int mouseX,int mouseY,Camera* camer)
{

m_pCamera=camer;
m_IntersectionArray.clear();//清除拾取记录
CreateRay(mouseX,mouseY);
HRESULT hr=S_OK;
DWORD* pIndices;
FLOAT u, v, fDist;
for (int i=0;i<normalObjects.size();i++)
{

ObjectFrame *frame=normalObjects[i]->GetObjectFrame();
int numVertex=frame->numvertex;
int numIndex=frame->numIndex;
DWORD dwNumFaces=frame->dwNumFaces;
if(1>numIndex)
{
continue;
}
pIndices=new DWORD[numIndex];
int maxWORD = 1<<16;
if(numVertex < maxWORD)
{
for(int i=0;i<numIndex;i++)
{
pIndices[i]= ((WORD*)(frame->pIndex))[i];
}
}
else
{
for(int i=0;i<numIndex;i++)
{
pIndices[i]=frame->pIndex[i];
}
}
for (DWORD f=0;f<dwNumFaces;f++)
{
float3 vert[3];
for(int j=0;j<3;j++)
{
//通过一个矩阵来变换一个三维向量 outV srcV Matri
float3 v0 = frame->pVertex[pIndices[3*f+j]].p;
D3DXVec3TransformCoord(&vert[j],&v0,&normalObjects[i]->GetTransform());
}
if(D3DXIntersectTri( &vert[0], &vert[1], &vert[2],&vPickRayOrig, &vPickRayDir, &u, &v,&fDist ) && fDist>=0)
{
PickResult Intersection;
Intersection.dwFace = f;
Intersection.fBary1 = u;
Intersection.fBary2 = v;
Intersection.fDist = fDist;
Intersection.object=normalObjects[i];
Intersection.hitpoint=vert[0] + (vert[1]-vert[0])*u + (vert[2]-vert[0])*v ;
m_IntersectionArray.push_back(Intersection);
}
}
SAFE_DELETE_ARRAY(pIndices);
}


std::sort(m_IntersectionArray.begin(),m_IntersectionArray.end(),SortFunction);
return m_IntersectionArray;


}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics