Direct3D中的Pick技术

原创 2008年09月28日 23:51:00

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

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;


}

 


 

Directx11教程三十八之Pick(拾取技术)

这节教程是关于Pick(拾取技术的),程序的结构如下: 在看这节教程前先弄懂:(1)大概了解D3D11的渲染流水线                                     ...
  • qq_29523119
  • qq_29523119
  • 2016年11月15日 23:37
  • 1621

Direct3D 中实现图元的鼠标拾取

Direct3D 中实现图元的鼠标.pdf看网上好多关于该文章的图片丢失,有幸找到个有完整图片的。BY 重剑,2004.5.28 重剑空间 索引:1、什么是拾取,拾取能做什么?2、拾取操作的步骤和实现...
  • zyq5945
  • zyq5945
  • 2010年04月08日 23:35
  • 2261

Directx11教程三十八之Pick(拾取技术)

这节教程是关于Pick(拾取技术的),程序的结构如下: 在看这节教程前先弄懂:(1)大概了解D3D11的渲染流水线                                     ...
  • qq_29523119
  • qq_29523119
  • 2016年11月15日 23:37
  • 1621

Git cherry-pick和format-patch(给分支打补丁)区别和使用场景

总结: Git cherry-pick : 把一个commit-id的commit应用到当前分支上, 一次只能选择一个"补丁" git format-patch ... -o : 一次性把多个co...
  • guyue35
  • guyue35
  • 2016年11月21日 13:07
  • 1294

Android studio配置git及使用方法

程序员开发一个项目,版本控制工具是必不可少的,常见的有SVN和Git等。前面我已经对SVN有了介绍,这里贴一下地址,不知道的可以去看看。Android studio配置svn及使用方法:http://...
  • u014727709
  • u014727709
  • 2017年01月09日 16:29
  • 3614

Direct3D通用技术与特殊效果

Direct3D提供了一套强有力的工具来帮助我们提高三维场景的逼真度。下面我们将讨论一些Direct3D产生的通用的特殊效果。但是,可能出现的效果并不只限于这里所讨论的内容。下面我们分成几个主要的部分...
  • aoying59595512
  • aoying59595512
  • 2013年05月28日 09:13
  • 489

Direct3D纹理映射技术

一、纹理映射的基本概念 IDirect3DTexture9来表示,纹理是类似于表面的像素矩阵,与表面不同的是它可以被映射到三角形单元中。 1.纹理坐标系是2D纹理图像中的uv坐标系,因为直到三角形顶点...
  • Blues1021
  • Blues1021
  • 2014年12月13日 21:41
  • 1778

Direct3D学习手记七:Alpha融合技术

本文介绍Direct3D里的融合技术来实现透明效果 在上篇文章中,介绍到深度缓存和深度测试,其效果将会时近处物体遮挡远处物体, 但是如果近处物体是玻璃等透明的物体,则紧紧使用深度测试是行不通的, ...
  • managerfeng
  • managerfeng
  • 2013年12月27日 11:26
  • 702

Direct3D学习手记八:模板技术【镜面效果】

本文介绍模板技术并实现镜面效果 模板缓存: 模板缓存和深度缓存是同时创建的,在指定深度缓存格式的时候,模板缓存的格式也被同时指定了,语句如下: d3dpp.AutoDepthStencilFormat...
  • managerfeng
  • managerfeng
  • 2013年12月28日 14:15
  • 783

DirectX学习笔记(八):Direct3D融合技术详解及物体透明效果的实现

前言: 融合技术,将当前要进行光栅化的像素的颜色与先前已经光栅化并处于同一位置的像素的颜色进行合成,即:将正在处理的图元颜色值与存储在后台缓存中的像素颜色值进行合成,利用该技术,可以获得很多种效果...
  • lishuzhai
  • lishuzhai
  • 2016年09月18日 22:03
  • 3226
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Direct3D中的Pick技术
举报原因:
原因补充:

(最多只允许输入30个字)