日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > 綜合技術(shù) > 射線檢測(cè)算法在游戲中應(yīng)用

射線檢測(cè)算法在游戲中應(yīng)用

來(lái)源:程序員人生   發(fā)布時(shí)間:2017-02-04 09:36:28 閱讀次數(shù):5820次

筆者介紹:姜雪偉IT公司技術(shù)合伙人,IT高級(jí)講師,CSDN社區(qū)專家,特邀編輯,暢銷書作者,國(guó)家專利發(fā)明人;已出版書籍:《手把手教你架構(gòu)3D游戲引擎》電子工業(yè)出版社和《Unity3D實(shí)戰(zhàn)核心技術(shù)詳解》電子工業(yè)出版社等。

 射線檢測(cè)在游戲中使用的非常廣泛,我們利用射線開(kāi)發(fā)時(shí),開(kāi)發(fā)者只是調(diào)用引擎的接口便可實(shí)現(xiàn),但是我們要了解其內(nèi)部實(shí)現(xiàn)原理,這樣我們也能夠自己封裝射線檢測(cè)算法,射線檢測(cè)算法利用程度非常高,不論是使用鼠標(biāo)還是觸摸屏,都需要用到射線檢測(cè),比如在虛擬仿真中,導(dǎo)彈追蹤物體時(shí),它需要通過(guò)從導(dǎo)彈上發(fā)出的射線1直朝向物體,角色尋路也能夠通過(guò)在身體發(fā)出的射線檢測(cè)與物體本身的碰撞盒接觸后,用于查看物體是不是產(chǎn)生了碰撞。射線檢測(cè)還用于對(duì)物體身上的材質(zhì)處理,比如墻體的遮擋關(guān)系,使用攝像機(jī)發(fā)出的射線方向指向角色,如果它們之間的射線檢測(cè)到物體比如墻體,可以編寫邏輯改變角色的材質(zhì)進(jìn)行透明處理,效果以下圖所示:



固然我們也能夠使用對(duì)墻體進(jìn)行透明設(shè)置,這也是1種處理方式,是將墻體進(jìn)行透明設(shè)置效果以下圖所示:


其在程序中表現(xiàn)的效果以下所示:



從相機(jī)發(fā)出兩條射線,射線與墻體的碰撞體產(chǎn)生接觸,程序會(huì)改變墻體的Shader,替換其材質(zhì),讓其透明。以下是Unity3D引擎使用案例,核心代碼以下所示:

 if (Physics.Linecast(pos, transform.position, out hit))
            {
                last_obj = hit.collider.gameObject;
                int length = last_obj.transform.childCount;
                string name_tag = last_obj.tag;

                if (name_tag == "wall")
                {
                    Material mat = new Material(Shader.Find("Transparent/Diffuse"));

                    curr_obj = last_obj;
                    for (int i = 0; i < length; i++)
                    {
                        Transform child = last_obj.transform.GetChild(i);
                        child.GetComponent<Renderer>().material = mat;
                        mat.mainTexture = (Texture)Resources.Load("Atlas/test_pub_tm");
                    }

                }  
}

射線也能夠用于物體的拾取操作,拾取物體時(shí)從觸摸點(diǎn)發(fā)出1條射線與要拾取的物體的包圍盒產(chǎn)生碰撞,表示物體被拾取到。

下面給開(kāi)發(fā)者介紹1下,射線碰撞的原理,把1個(gè)物體放到場(chǎng)景中做了1個(gè)局部坐標(biāo)到世界坐標(biāo)變換,效果以下圖所示:


將物體投影后,假定紅的表示X軸,綠的表示Y軸,中間表示物體的碰撞盒,1條射線穿過(guò)后效果以下所示:


射線穿過(guò)我們要計(jì)算其是不是與碰撞盒產(chǎn)生碰撞,主要是通過(guò)射線與碰撞盒相交值的大小進(jìn)行判斷,效果以下圖所示:


射線與碰撞體產(chǎn)生碰撞后的判定效果圖以下所示:



根據(jù)以上的判斷我們可以寫下代碼,對(duì)3D物體,我們要分別判斷X,Y,Z3個(gè)軸。核心代碼以下所示:

bool TestRayOBBIntersection(
    glm::vec3 ray_origin,        // Ray origin, in world space
    glm::vec3 ray_direction,     // Ray direction (NOT target position!), in world space. Must be normalize()'d.
    glm::vec3 aabb_min,          // Minimum X,Y,Z coords of the mesh when not transformed at all.
    glm::vec3 aabb_max,          // Maximum X,Y,Z coords. Often aabb_min*⑴ if your mesh is centered, but it's not always the case.
    glm::mat4 ModelMatrix,       // Transformation applied to the mesh (which will thus be also applied to its bounding box)
    float& intersection_distance // Output : distance between ray_origin and the intersection with the OBB
){

    // Intersection method from Real-Time Rendering and Essential Mathematics for Games

    float tMin = 0.0f;
    float tMax = 100000.0f;

    glm::vec3 OBBposition_worldspace(ModelMatrix[3].x, ModelMatrix[3].y, ModelMatrix[3].z);

    glm::vec3 delta = OBBposition_worldspace - ray_origin;

    // Test intersection with the 2 planes perpendicular to the OBB's X axis
    {
        glm::vec3 xaxis(ModelMatrix[0].x, ModelMatrix[0].y, ModelMatrix[0].z);
        float e = glm::dot(xaxis, delta);
        float f = glm::dot(ray_direction, xaxis);

        if ( fabs(f) > 0.001f ){ // Standard case

            float t1 = (e+aabb_min.x)/f; // Intersection with the "left" plane
            float t2 = (e+aabb_max.x)/f; // Intersection with the "right" plane
            // t1 and t2 now contain distances betwen ray origin and ray-plane intersections

            // We want t1 to represent the nearest intersection, 
            // so if it's not the case, invert t1 and t2
            if (t1>t2){
                float w=t1;t1=t2;t2=w; // swap t1 and t2
            }

            // tMax is the nearest "far" intersection (amongst the X,Y and Z planes pairs)
            if ( t2 < tMax )
                tMax = t2;
            // tMin is the farthest "near" intersection (amongst the X,Y and Z planes pairs)
            if ( t1 > tMin )
                tMin = t1;

            // And here's the trick :
            // If "far" is closer than "near", then there is NO intersection.
            // See the images in the tutorials for the visual explanation.
            if (tMax < tMin )
                return false;

        }else{ // Rare case : the ray is almost parallel to the planes, so they don't have any "intersection"
            if(-e+aabb_min.x > 0.0f || -e+aabb_max.x < 0.0f)
                return false;
        }
    }


    // Test intersection with the 2 planes perpendicular to the OBB's Y axis
    // Exactly the same thing than above.
    {
        glm::vec3 yaxis(ModelMatrix[1].x, ModelMatrix[1].y, ModelMatrix[1].z);
        float e = glm::dot(yaxis, delta);
        float f = glm::dot(ray_direction, yaxis);

        if ( fabs(f) > 0.001f ){

            float t1 = (e+aabb_min.y)/f;
            float t2 = (e+aabb_max.y)/f;

            if (t1>t2){float w=t1;t1=t2;t2=w;}

            if ( t2 < tMax )
                tMax = t2;
            if ( t1 > tMin )
                tMin = t1;
            if (tMin > tMax)
                return false;

        }else{
            if(-e+aabb_min.y > 0.0f || -e+aabb_max.y < 0.0f)
                return false;
        }
    }


    // Test intersection with the 2 planes perpendicular to the OBB's Z axis
    // Exactly the same thing than above.
    {
        glm::vec3 zaxis(ModelMatrix[2].x, ModelMatrix[2].y, ModelMatrix[2].z);
        float e = glm::dot(zaxis, delta);
        float f = glm::dot(ray_direction, zaxis);

        if ( fabs(f) > 0.001f ){

            float t1 = (e+aabb_min.z)/f;
            float t2 = (e+aabb_max.z)/f;

            if (t1>t2){float w=t1;t1=t2;t2=w;}

            if ( t2 < tMax )
                tMax = t2;
            if ( t1 > tMin )
                tMin = t1;
            if (tMin > tMax)
                return false;

        }else{
            if(-e+aabb_min.z > 0.0f || -e+aabb_max.z < 0.0f)
                return false;
        }
    }

    intersection_distance = tMin;
    return true;

}

射線與碰撞盒的判定就結(jié)束了,雖然市面上的各個(gè)引擎都提供了接口,我們可以直接使用,但是如果我們能明白其原理,更有助于我們理解射線碰撞算法。

生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 国产乱码一区二区三区 | 久久精品免费看 | 欧美人xxx| 干干干操操操 | 色玖玖| 日韩美女视频 | 久久精品国产免费 | 国产精品美女久久久久 | av一级毛片 | 99精品国产成人一区二区 | 精品成人 | 日本亚洲最大的色成网站www | 日韩系列在线 | 亚洲一区二区三区四区视频 | 久久九九久精品国产 | 中国一级片在线观看 | 久久久久久国产免费视网址 | 91久久精品一区二区二区 | 亚洲高清在线观看 | 久久99国产精品久久99果冻传媒 | 国产99视频精品免费视频7 | 日本精品一区二区三区视频 | 国产精品久久久久久久久久浪潮 | 国产伦精品一区二区三区在线 | 国产精品一区二区三区四区 | 久久国产精品影视 | 亚洲国产99 | 欧美国产在线观看 | 国产精品久久久久久久久久免费 | 精品国产91乱码一区二区三区 | 成人免费乱码大片a毛片视频网站 | 天堂√最新版中文在线 | 成人a视频| 亚洲午夜久久久久久久久久久 | 99久久国产综合精品女不卡 | 国产精品成人一区 | 亚洲成人av电影网站 | 91在线精品秘密一区二区 | 欧洲精品 | 亚洲精品91 | 日韩av免费在线观看 |