游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2311|回复: 2

求高手帮我讲解一下这段关于鼠标和地图碰撞检测的代码

[复制链接]

6

主题

13

帖子

13

积分

新手上路

Rank: 1

积分
13
发表于 2007-7-26 18:20:00 | 显示全部楼层 |阅读模式
大家好,第一次来这里学习,请大家多多指教. 最近看了一段代码这部分实在是看不懂了, 来请教大虾帮忙,代码如下,:

头文件中的内容
#ifndef AFX_CMATH_H
#define AFX_CMATH_H
#define INTERSECT_NEGATIVEY                0x10
#define INTERSECT_HORIZENTAL        0x30


//Summary:
//Description:        计算一个三角形和一个射线的交点
//Parameters:
//        orig:                射线起始点
//        dir:                射线的方向
//        v0:                        三角形的第一个顶点
//        v1:                        三角形的第二个顶点
//        v2:                        三角形的第三个顶点
//        t:                        交点到射线起始点的距离
//        u:                        交点在v1-v0上的投影的位置,
//        v:                        交点在v1-v0上的投影的位置, 交点为vRet=v0+u*(v1-v0)+v*(v2-v0)
//Returns:        是否有交点

BOOL IntersectTriangle( const D3DXVECTOR3& orig,
                                       const D3DXVECTOR3& dir, const D3DXVECTOR3& v0,
                                       const D3DXVECTOR3& v1, const D3DXVECTOR3& v2,
                                       FLOAT* t, FLOAT* u, FLOAT* v );
//Summary:        求射线和网格的交点
//Description:        求射线和用顶点缓冲区和索引缓冲区定义的网格的交点
//Parameters:
//        pIB:                索引缓冲区
//        pVB:                顶点缓冲区
//        nStide:                每个顶点的大小
//        dwNumFaces:        面数
//        vRayOrig:        射线起始点
//        vRayDir:        射线的方向
//        pVRet:                交点
//Returns:        是否有交点

BOOL IntersectIndexBuffer(LPDIRECT3DINDEXBUFFER9 pIB,
                                   LPDIRECT3DVERTEXBUFFER9 pVB,
                                   UINT nStride,UINT dwNumFaces,
                                   const D3DVECTOR *vRayOrig,const D3DVECTOR *vRayDir,
                                   D3DVECTOR *pVRet,DWORD dwFlag=0);

#endif


CPP中的内容:


#include  <d3d9.h>
#include  <d3dx9.h>
#include "CMath.h"


//Summary:        求射线和网格的交点
//Description:        求射线和用顶点缓冲区和索引缓冲区定义的网格的交点
//Parameters:
//        pIB:                索引缓冲区
//        pVB:                顶点缓冲区
//        nStide:                每个顶点的大小
//        dwNumFaces:        面数
//        vRayOrig:        射线起始点
//        vRayDir:        射线的方向
//        pVRet:                交点
//       dwFlag暂时不用
//Returns:        是否有交点
BOOL IntersectIndexBuffer(LPDIRECT3DINDEXBUFFER9 pIB,//实现碰撞检测 的全局函数(顶点缓冲)
                                   LPDIRECT3DVERTEXBUFFER9 pVB,
                                   UINT nStride,UINT dwNumFaces,
                                   const D3DVECTOR *vRayOrig,const D3DVECTOR *vRayDir,D3DVECTOR *pVRet,DWORD dwFlag)
{
        WORD*                pIndices;
        BYTE*                pVertices;
                D3DINDEXBUFFER_DESC IB_Desc;

                FLOAT fBary1, fBary2,fDist=1e+32f;

                FLOAT t_fBary1, t_fBary2,t_fDist;
                DWORD dwFace=-1;
                DWORD  dwUpperLower;       

                D3DXVECTOR3* pV[3];
                ULONG  n;

                pIB->GetDesc(&IB_Desc);
        pIB->Lock( 0, 0, (void**)&pIndices, 0 );//这里为什么前俩个参数都是0呢?
        pVB->Lock( 0, 0, (void**)&pVertices,0 );


                for( DWORD i=0; i<dwNumFaces; i++ )
                {
                        for(int j=0;j<3;j++)
                        {
                                if(IB_Desc.Format==D3DFMT_INDEX16)                        n=(WORD)pIndices[3*i+j];//此处和下面的n的区别,具体就是16位和32位算法的区别
                                else if(IB_Desc.Format==D3DFMT_INDEX32)               
          n=*(DWORD*)&pIndices[2*(3*i+j)];
                                else return FALSE;
                                pV[j]=(D3DXVECTOR3*)(pVertices+nStride*n);
                        }

                        dwUpperLower=0;
                        if(dwFlag)
                        {
                                if(dwFlag & INTERSECT_NEGATIVEY)//此处请高手帮我讲解
                                {
                                        for(j=0;j<3;j++)
                                        {
                dwUpperLower|= vRayOrig->x > pV[j]->x ? 0x0010:0x0001;
                dwUpperLower|= vRayOrig->z > pV[j]->z ? 0x1000:0x0100;
       
                                        }
                                        if(dwUpperLower!=0x1111) continue;               

                               
                                }
                                else if(dwFlag & INTERSECT_HORIZENTAL)
                                {
                                        for(j=0;j<3;j++)
                                        {
                                dwUpperLower|=(vRayOrig->y > pV[j]->y)? 0x0010:0x0001;
                                        }
                                       
                                        if(dwUpperLower!=0x0011) continue;       
                                }
                       
                       
                        }

                        // 检测是否穿过三角形
                        if( IntersectTriangle( *vRayOrig, *vRayDir, *pV[0], *pV[1], *pV[2],
                                                                        &t_fDist, &t_fBary1, &t_fBary2 ) )
                        {
                                if(        t_fDist < fDist )        //是否返回最近的一个点
                                {
                                        dwFace = i;
                                        fBary1 = t_fBary1;
                                        fBary2 = t_fBary2;
                                        fDist  = t_fDist;
                                }
                        }
                }

                if(dwFace<dwNumFaces && dwFace>=0 )
                {
                       
                        for(int j=0;j<3;j++)
                        {
                                if(IB_Desc.Format==D3DFMT_INDEX16)                        n=(WORD)pIndices[3*dwFace +j];
                                   else if(IB_Desc.Format==D3DFMT_INDEX32)               
        n=*(DWORD*)&pIndices[2*(3*dwFace+j)];
                                else return FALSE;
                                pV[j]=(D3DXVECTOR3*)(pVertices+nStride*n);
                        }
                        *pVRet=*pV[0] +fBary1*(*pV[1]-*pV[0])+fBary2*(*pV[2]-*pV[0]);  
                       

                        pVB->Unlock();
                        pIB->Unlock();
                        return 1;
                }
               

        pVB->Unlock();
        pIB->Unlock();
   


    return 0;
}


//Summary:
//Description:        计算一个三角形和一个射线的交点
//Parameters:
//        orig:                射线起始点
//        dir:                射线的方向
//        v0:                        三角形的第一个顶点
//        v1:                        三角形的第二个顶点
//        v2:                        三角形的第三个顶点
//        t:                        交点到射线起始点的距离
//        u:                        交点在v1-v0上的投影的位置,
//        v:                        交点在v1-v0上的投影的位置, 交点为vRet=v0+u*(v1-v0)+v*(v2-v0)
//Returns:        是否有交点
//Sample:       
//IntersectIndexBuffer(pIB,pVB,
//                        dwVSize,
//                        dwNumFace,
//                        pRayOrig,pRayDir,pVRet,dwFlag);

BOOL IntersectTriangle( const D3DXVECTOR3& orig,//实现碰撞检测 的全局函数(三角面)
                                       const D3DXVECTOR3& dir, const D3DXVECTOR3& v0,
                                       const D3DXVECTOR3& v1, const D3DXVECTOR3& v2,
                                       FLOAT* t, FLOAT* u, FLOAT* v )
{
    // Find vectors for two edges sharing vert0
    D3DXVECTOR3 edge1 = v1 - v0;
    D3DXVECTOR3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
        //交点p=edge1*u+edge2*v;

    D3DXVECTOR3 pvec;
    D3DXVec3Cross( &pvec, &dir, &edge2 );        //|a×b|=|a||b|sinθ

    // 如果det接近0,表明射线平行于三角形
    FLOAT det = D3DXVec3Dot( &edge1, &pvec );        //|a dot b|=|a||b|cosθ

       
    D3DXVECTOR3 tvec;
    if( det > 0 )
    {
        tvec = orig - v0;

    }
    else
    {        return FALSE;        //方向相反
        tvec = v0 - orig;
        det = -det;
    }
        //if(D3DXVec3Dot(&dir,&tvec)>0) return FALSE;

    if( det < 0.0001f )
        return FALSE;

    // Calculate U parameter and test bounds
    *u = D3DXVec3Dot( &tvec, &pvec );
    if( *u < 0.0f || *u > det )
        return FALSE;
         
    // Prepare to test V parameter
    D3DXVECTOR3 qvec;
    D3DXVec3Cross( &qvec, &tvec, &edge1 );

    // Calculate V parameter and test bounds
    *v = D3DXVec3Dot( &dir, &qvec );
    if( *v < 0.0f || *u + *v > det )
        return FALSE;

    // Calculate t, scale parameters, ray intersects triangle
    *t = D3DXVec3Dot( &edge2, &qvec );

    FLOAT fInvDet = 1.0f / det;
    *t *= fInvDet;
    *u *= fInvDet;
    *v *= fInvDet;
        if(*t<0) return FALSE;

    return TRUE;
};


[em3]

5

主题

755

帖子

757

积分

高级会员

Rank: 4

积分
757
发表于 2007-7-27 16:15:00 | 显示全部楼层

Re:求高手帮我讲解一下这段关于鼠标和地图碰撞检测的代码

这怎么说?一句一句翻译?简单来说就是用射线检查是否和某个三角相交~~

6

主题

13

帖子

13

积分

新手上路

Rank: 1

积分
13
 楼主| 发表于 2007-7-27 22:09:00 | 显示全部楼层

Re:求高手帮我讲解一下这段关于鼠标和地图碰撞检测的代码

但是这段内容确实看不懂,最好能一句句的翻译,我是菜鸟,希望楼上的大哥能帮忙,顺便问一下,这里传递的参数,IB,和VB,我用高度图生成的地图,在创建顶点的时候所得到的IB和VB,效果和MESH里用函数得到的VB和IB一样么?效果总是不好,头大了,
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 17:16

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表