为寻线LWJGL实现光线投射

问题描述

我目前正在从事一个项目,该项目涉及使用3d单工噪声和行进立方体算法按程序生成的水下地形。现在,我已经创建了角色模型并生成了地形网格物体。由于该项目位于水中,因此我想添加鱼类和其他实体以使其更逼真。我已经阅读了boids的基础知识,并且已经创建了用于实体在3d空间中进行交互的程序。但是,我一直坚持的问题是实体与障碍物相互作用。 video中使用的方法是将光线投射到实体周围的球体中,并检测光线是否与障碍物相交。我的想法是根据沿着每条射线的间隔检查每个点,直到检测到与三角形面相交的点。我已经有了检查3d点是否在三角形面上的代码,所以我的问题是我是否必须遍历每条射线的每个点才能计算它是否与三角形相交或是否有更好的方法对我来说做吗?

示例代码

for(Ray ray : rayList){
    for(float j = 0; j<raylength; j+= rayinterval){
        if(this.checkCollision(ray.getPos(raylenth))){
             break;
        }else if(j == raylenth-1){
             return ray.getAngles();
        }
    }
}
    public boolean checkCollision(Vector3f position){
        if(terrain != null){
            for(int i = 0; i<terrain.getVertices().length; i+=9){
                Vector3f vertex1 = new Vector3f(terrain.getVertices()[i],terrain.getVertices()[i+1],terrain.getVertices()[i+2]);
                Vector3f vertex2 = new Vector3f(terrain.getVertices()[i+3],terrain.getVertices()[i+4],terrain.getVertices()[i+5]);
                Vector3f vertex3 = new Vector3f(terrain.getVertices()[i+6],terrain.getVertices()[i+7],terrain.getVertices()[i+8]);
                
                if(inTriangle(position,vertex1,vertex2,vertex3)){
                    return true;
                }
            }
        }
        return false;
    }
    public UVList getUV(Vector3f a,Vector3f b,Vector3f c){

        //First,calculate the unit normal vector (cross product).
        Vector3f ba = b.subtract(a);
        Vector3f ca = c.subtract(a);
        Vector3f nn = ba.cross(ca);
        float unitVector = (float) Math.sqrt(nn.x*nn.x+nn.y*nn.y+nn.z*nn.z);
        Vector3f n = nn.divide(unitVector);

        //Calculate the signed distance from origin (dot product).
        float d = n.dot(a);

        //Calculate the three possible divisors.
        float div_xy = a.x*(c.y-b.y) + b.x*(a.y-c.y) + c.x*(b.y-a.y);
        float div_xz = a.x*(c.z-b.z) + b.x*(a.z-c.z) + c.x*(b.z-a.z);
        float div_yz = a.y*(c.z-b.z) + b.y*(a.z-c.z) + c.y*(b.z-a.z);
        float abs_xy = Math.abs(div_xy);
        float abs_xz = Math.abs(div_xz);
        float abs_yz = Math.abs(div_yz);
        Vector3f u,v;
        float u0,v0;
        if(abs_xy >= abs_xz && abs_xy >= abs_yz){
            //d_xy has the largest absolute value; using xy plane
            u = new Vector3f((a.y-c.y)/div_xy,(c.x-a.x)/div_xy,0);
            v = new Vector3f((b.y-a.y)/div_xy,(a.x-b.x)/div_xy,0);
            u0 = (a.x*c.y - a.y*c.x)/div_xy;
            v0 = (a.y*b.x - a.x*b.y)/div_xy;
        }else if( abs_xz >= abs_xy && abs_xz >= abs_yz){
            //d_xz has the largest absolute value; using xz plane
            u = new Vector3f((a.z-c.z)/div_xz,(c.x-a.x)/div_xz);
            v = new Vector3f((b.z-a.z)/div_xz,(a.x-b.x)/div_xz);
            u0 = (a.x*c.z - a.z*c.x)/div_xz;
            v0 = (a.z*b.x - a.x*b.z)/div_xz;
        }else{
            //d_yz has the largest absolute value; using yz plane
            u = new Vector3f(0,(a.z-c.z)/div_yz,(c.y-a.y)/div_yz);
            v = new Vector3f(0,(b.z-a.z)/div_yz,(a.y-b.y)/div_yz);
            u0 = (a.y*c.z - a.z*c.y)/div_yz;
            v0 = (a.z*b.y - a.y*b.z)/div_yz;
        }
        return new UVList(u0,v0,u,v,d,n);
    }
    public class UVList{
        Vector3f u,n;
        float u0,d;
        public UVList(float u0,float v0,Vector3f u,Vector3f v,float d,Vector3f n){
            this.u = u;
            this.v = v;
            this.u0 = u0;
            this.v0 = v0;
            this.d = d;
            this.n = n;
        }
        public Vector3f getN(){
            return n;
        }
        public Vector3f getU(){
            return u;
        }
        public Vector3f getV(){
            return v;
        }
        public float getU0(){
            return u0;
        }
        public float getV0(){
            return v0;
        }
        public float getD(){
            return d;
        }
    }
    public boolean inTriangle(Vector3f p,Vector3f v1,Vector3f v2,Vector3f v3){
        float ellipse = 1.5f;
        
        UVList uv = getUV(v1,v2,v3);
        
        
        if(Math.abs(p.dot(uv.getN())-uv.getD()) >= ellipse){
            return false;
        }
        
        float u = p.dot(uv.getU())+uv.getU0();
        
        float v = p.dot(uv.getV())+uv.getV0();

        if(u < 0 || u > 1){
            return false;
        }
        

        if(v < 0 || v > 1){
            return false;
        }
        
        if(u+v > 1){
            return false;
        }
        
        return true;
    }

二维图

2D diagram

这是我希望实体检测的地形:

地形

enter image description here

我是3d引擎和碰撞的新手,所以我的代码可能不是最好的。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)