游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1982|回复: 6

请教关于地面拾取出错的问题

[复制链接]

2

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2007-9-11 18:27:00 | 显示全部楼层 |阅读模式

什么值都对, 就是结果不对, matView matProj matWorld 都没问题, 地形的顶点与索引也没有问题, 就是不知道什么地方出错  具体请看下图

绿点为鼠标的位置, 鼠标是相对位置, bHit 为 1 说明拾取到地面  Face 是所拾取到的第几个面
所有移动 都是摄像机在移动 地形没有移动
下面图片 前两张是拾取没有问题的情况, 最后一张 拾取有问题



当摄像机距离地面比较近, 并且在地面的里面时, 拾取就会出错, 本来这种情况是拾取不到的,
但是竟然显示拾取到了




我都弄了好久了, 请高手帮帮忙吧

地形是这样画的

                        g_Vertices.p.x = (FLOAT)(i%128) * 50.0f;
                        g_Vertices.p.z = (FLOAT)(128 - i/128) * 50.0f;
                        g_Vertices.p.y = 0;



这是拾取

VOID Pick(HWND hWnd )
{
        POINT                        ptCursor;                                                /// 鼠标位置
        D3DXVECTOR3                vPickRayDir, vPickRayOrig;                /// 原点 射线
        D3DXMATRIX m;        /// m: 世界观察矩阵的逆矩阵

        /// 获得鼠标在当前窗口的相对位置
        GetCursorPos( &ptCursor );
        ScreenToClient( hWnd, &ptCursor );

        /// 获得世界观察矩阵的逆矩阵
        D3DXMATRIX        mWorldView = matWorld * matView;
        D3DXMatrixInverse( &m, NULL, &mWorldView);

        /// 通过计算出鼠标在投影变换下的坐标 计算出射线
        D3DXVECTOR3        v;
        v.x =        (( 2.0f * ptCursor.x / (640.0f-10.0f) ) - 1) / matProj( 0,0);
        v.y =  -(( 2.0f * ptCursor.y / (480.0f-35.0f) ) - 1) / matProj( 1,1);
        v.z =        1.0f;

        /// 设置射线与原点
        vPickRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
        vPickRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
        vPickRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
        vPickRayOrig.x = m._41;
        vPickRayOrig.y = m._42;
        vPickRayOrig.z = m._43;

        /// 计算与模型相交
        DWORD                                bHit                        = 0;
        FLOAT                                fBary1                        = 0;
        FLOAT                                fBary2                        = 0;
        FLOAT                                fDist                        = 0;
        DWORD                                dwNumFaces                = 0;
        DWORD                                dwFace                        = 0;

        LPDIRECT3DVERTEXBUFFER9 pVB;
        LPDIRECT3DINDEXBUFFER9        pIB;
        CUSTOMVERTEX*        pVertices;
        WORD*                pIndices;

        g_pMesh->GetVertexBuffer(&pVB);
        g_pMesh->GetIndexBuffer(&pIB);

        pVB->Lock(0,0,(LPVOID*)&pVertices,0);
        pIB->Lock(0,0,(LPVOID*)&pIndices,0);

        dwNumFaces = g_pMesh->GetNumFaces();

        D3DXVECTOR3 v0,v1,v2;
        for ( WORD i=0; i<dwNumFaces; i++)
        {
                D3DXVECTOR3 v0 = pVertices[pIndices[3*i+0]].p;
                D3DXVECTOR3 v1 = pVertices[pIndices[3*i+1]].p;
                D3DXVECTOR3 v2 = pVertices[pIndices[3*i+2]].p;

                if ( IntersectTriangle( vPickRayOrig, vPickRayDir, v0, v1, v2, &fDist, &fBary1, &fBary2 ) )
                {
                        bHit = 1;
                        dwFace = i+1;
                }
        }
        pIB->Unlock();
        pVB->Unlock();

    ZeroMemory(g_cBuffer,sizeof(g_cBuffer));
        sprintf(g_cBuffer,"vPickRayOrig.x=%f  vPickRayOrig.y=%f  vPickRayOrig.z=%f \n vPickRayDir.x=%f  vPickRayDir.y=%f  vPickRayDir.z=%f \n bHit=%d  Cursor.x=%d Cursor.y=%d Face=%d ",
                                                vPickRayOrig.x, vPickRayOrig.y, vPickRayOrig.z,
                                                vPickRayDir.x, vPickRayDir.y, vPickRayDir.z,
                                                bHit, ptCursor.x, ptCursor.y, dwFace );
}


这个是整个代码的下载地址

http://mumayi1.999kb.com/pic/2007-09-11/h00si6dj2ww093cwrv0u.rar

2

主题

429

帖子

435

积分

中级会员

Rank: 3Rank: 3

积分
435
发表于 2007-9-12 00:25:00 | 显示全部楼层

Re:请教关于地面拾取出错的问题

请先用D3DXIntersect确定你半截没问题。

另外matProj的部分你贴掉了吧?

当摄像机距离地面比较近, 并且在地面的里面时, 拾取就会出错
=====================================
比较近,里面? 没看明白。如果你的意思是,视点在地面以下,拣选地面上空白的地方,对射线来说确实和地面有交点。当然能拾取到了。

8

主题

284

帖子

296

积分

中级会员

Rank: 3Rank: 3

积分
296
QQ
发表于 2007-9-12 01:12:00 | 显示全部楼层

Re:请教关于地面拾取出错的问题

代码计算PICK RAY处有错,看看D3D的范例代码,再琢磨琢磨。

2

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
 楼主| 发表于 2007-9-12 10:50:00 | 显示全部楼层

Re:请教关于地面拾取出错的问题

发现出问题之后 matView matProj matWorld 都改成全局的了,
摄像机在地图里面 意思就是 摄像机的坐标大于地形的最小xz坐标, 小于地形的最大xz坐标

King_jinjing 兄说的 PICK RAY 具体那里出错了, 可以具体说说么?
我这个就是照着 D3D范例改的,PICK RAY的算法 怎么看都和 D3D的范例一样啊, 是在看不出了*_*  请指教

8

主题

284

帖子

296

积分

中级会员

Rank: 3Rank: 3

积分
296
QQ
发表于 2007-9-12 14:45:00 | 显示全部楼层

Re:请教关于地面拾取出错的问题

// Compute the vector of the pick ray in screen space
        D3DXVECTOR3 v;
        v.x =  ( ( ( 2.0f * ptCursor.x ) / m_d3dsdBackBuffer.Width  ) - 1 ) / matProj._11;
        v.y = -( ( ( 2.0f * ptCursor.y ) / m_d3dsdBackBuffer.Height ) - 1 ) / matProj._22;
        v.z =  1.0f;

        // Get the inverse view matrix
        D3DXMATRIX matView, m;
        m_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );
        D3DXMatrixInverse( &m, NULL, &matView );

        // Transform the screen space pick ray into 3D space
        vPickRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
        vPickRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
        vPickRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
        vPickRayOrig.x = m._41;
        vPickRayOrig.y = m._42;
        vPickRayOrig.z = m._43;


自己对照一下。

2

主题

429

帖子

435

积分

中级会员

Rank: 3Rank: 3

积分
435
发表于 2007-9-12 15:37:00 | 显示全部楼层

Re: Re:请教关于地面拾取出错的问题

korben: Re:请教关于地面拾取出错的问题

发现出问题之后 matView matProj matWorld 都改成全局的了,
摄像机在地图里面 意思就是 摄像机的坐标大于...


无论y值是多少都这样?

请先用D3DXIntersect替换你后面的求交计算,看看问题出在哪部分。

2

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
 楼主| 发表于 2007-9-13 12:33:00 | 显示全部楼层

Re:请教关于地面拾取出错的问题

问题解决了, 别人告诉我的, 可是不知道为什么,
根据sdk里的
bool IntersectTriangle( const D3DXVECTOR3& orig, const D3DXVECTOR3& dir,
                                           D3DXVECTOR3& v0, D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                                           FLOAT* t, FLOAT* u, FLOAT* v )

在最后面
        // 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;
就可以了, 可是不知道为什么
t 是什么啊, 不是原点到相交点的距离么?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-6-21 18:15

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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