2012-01-03 72 views
0

我已经写了一些代码来预制3D采摘,由于某些原因dosn't工作完全正确! (IM使用LWJGL只是让你知道。)3D采摘lwjgl

这是怎样的代码看起来像:

if(Mouse.getEventButton() == 1) { 
    if (!Mouse.getEventButtonState()) { 
    Camera.get().generateViewMatrix(); 

    float screenSpaceX = ((Mouse.getX()/800f/2f)-1.0f)*Camera.get().getAspectRatio(); 
    float screenSpaceY = 1.0f-(2*((600-Mouse.getY())/600f)); 
    float displacementRate = (float)Math.tan(Camera.get().getFovy()/2); 

    screenSpaceX *= displacementRate; 
    screenSpaceY *= displacementRate; 

    Vector4f cameraSpaceNear = new Vector4f((float) (screenSpaceX * Camera.get().getNear()), (float) (screenSpaceY * Camera.get().getNear()), (float) (-Camera.get().getNear()), 1); 
    Vector4f cameraSpaceFar = new Vector4f((float) (screenSpaceX * Camera.get().getFar()), (float) (screenSpaceY * Camera.get().getFar()), (float) (-Camera.get().getFar()), 1); 

    Matrix4f tmpView = new Matrix4f(); 
    Camera.get().getViewMatrix().transpose(tmpView); 
    Matrix4f invertedViewMatrix = (Matrix4f)tmpView.invert(); 

    Vector4f worldSpaceNear = new Vector4f(); 
    Matrix4f.transform(invertedViewMatrix, cameraSpaceNear, worldSpaceNear); 

    Vector4f worldSpaceFar = new Vector4f(); 
    Matrix4f.transform(invertedViewMatrix, cameraSpaceFar, worldSpaceFar); 


    Vector3f rayPosition = new Vector3f(worldSpaceNear.x, worldSpaceNear.y, worldSpaceNear.z); 
    Vector3f rayDirection = new Vector3f(worldSpaceFar.x - worldSpaceNear.x, worldSpaceFar.y - worldSpaceNear.y, worldSpaceFar.z - worldSpaceNear.z); 

    rayDirection.normalise(); 

    Ray clickRay = new Ray(rayPosition, rayDirection); 

    Vector tMin = new Vector(), tMax = new Vector(), tempPoint; 
    float largestEnteringValue, smallestExitingValue, temp, closestEnteringValue = Camera.get().getFar()+0.1f; 
    Drawable closestDrawableHit = null; 
    for(Drawable d : this.worldModel.getDrawableThings()) { 
     // Calcualte AABB for each object... needs to be moved later... 
     firstVertex = true; 
     for(Surface surface : d.getSurfaces()) { 
      for(Vertex v : surface.getVertices()) { 
       worldPosition.x = (v.x+d.getPosition().x)*d.getScale().x; 
       worldPosition.y = (v.y+d.getPosition().y)*d.getScale().y; 
       worldPosition.z = (v.z+d.getPosition().z)*d.getScale().z; 
       worldPosition = worldPosition.rotate(d.getRotation()); 
       if (firstVertex) { 
        maxX = worldPosition.x; maxY = worldPosition.y; maxZ = worldPosition.z; 
        minX = worldPosition.x; minY = worldPosition.y; minZ = worldPosition.z; 
        firstVertex = false; 
       } else { 
        if (worldPosition.x > maxX) { 
         maxX = worldPosition.x; 
        } 
        if (worldPosition.x < minX) { 
         minX = worldPosition.x; 
        } 
        if (worldPosition.y > maxY) { 
         maxY = worldPosition.y; 
        } 
        if (worldPosition.y < minY) { 
         minY = worldPosition.y; 
        } 
        if (worldPosition.z > maxZ) { 
         maxZ = worldPosition.z; 
        } 
        if (worldPosition.z < minZ) { 
         minZ = worldPosition.z; 
        } 
       } 
      } 
     } 

     // ray/slabs intersection test... 


     // clickRay.getOrigin().x + clickRay.getDirection().x * f = minX 
     // clickRay.getOrigin().x - minX = -clickRay.getDirection().x * f 
     // clickRay.getOrigin().x/-clickRay.getDirection().x - minX/-clickRay.getDirection().x = f 
     // -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x = f 


     largestEnteringValue = -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x; 
     temp = -clickRay.getOrigin().y/clickRay.getDirection().y + minY/clickRay.getDirection().y; 
     if(largestEnteringValue < temp) { 
      largestEnteringValue = temp; 
     } 
     temp = -clickRay.getOrigin().z/clickRay.getDirection().z + minZ/clickRay.getDirection().z; 
     if(largestEnteringValue < temp) { 
      largestEnteringValue = temp; 
     } 

     smallestExitingValue = -clickRay.getOrigin().x/clickRay.getDirection().x + maxX/clickRay.getDirection().x; 
     temp = -clickRay.getOrigin().y/clickRay.getDirection().y + maxY/clickRay.getDirection().y; 
     if(smallestExitingValue > temp) { 
      smallestExitingValue = temp; 
     } 
     temp = -clickRay.getOrigin().z/clickRay.getDirection().z + maxZ/clickRay.getDirection().z; 
     if(smallestExitingValue < temp) { 
      smallestExitingValue = temp; 
     } 


      if(largestEnteringValue > smallestExitingValue) { 
       //System.out.println("Miss!"); 
      } else { 
       if (largestEnteringValue < closestEnteringValue) { 
        closestEnteringValue = largestEnteringValue; 
        closestDrawableHit = d; 
       } 
      } 

    } 
    if(closestDrawableHit != null) { 
     System.out.println("Hit at: (" + clickRay.setDistance(closestEnteringValue).x + ", " + clickRay.getCurrentPosition().y + ", " + clickRay.getCurrentPosition().z); 
     this.worldModel.removeDrawableThing(closestDrawableHit);  
    } 
    } 
} 

我只是不明白什么是错的,光线的拍摄,我也打的东西,被删除但是光线的结果是非常奇怪的,它有时会消除点击的东西,有时它消除的东西甚至不接近点击的东西,有时甚至没有消除任何东西。

编辑:

好了,所以我继续寻找错误和调试光线(由画SMaL公司点在那里travles)我现在可以瑟,有一些oviously错即时通讯发送射线出来...它的起源在世界中心附近,并且总是拍摄到相同的位置,无论我在哪里指导我的相机...

我最初的想法是在计算我的viewMatrix时可能会出现一些错误(因为无法从lwjgl中的glulookat方法获取视图矩阵;我必须将其构建为自己,我猜这就是问题所在)...

EDIT2:

这是我如何计算它目前:

private double[][] viewMatrixDouble = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,1}}; 

public Vector getCameraDirectionVector() { 
    Vector actualEye = this.getActualEyePosition(); 
    return new Vector(lookAt.x-actualEye.x, lookAt.y-actualEye.y, lookAt.z-actualEye.z); 
} 

public Vector getActualEyePosition() { 
    return eye.rotate(this.getRotation()); 
} 

public void generateViewMatrix() { 

    Vector cameraDirectionVector = getCameraDirectionVector().normalize(); 
    Vector side = Vector.cross(cameraDirectionVector, this.upVector).normalize(); 
    Vector up = Vector.cross(side, cameraDirectionVector); 

    viewMatrixDouble[0][0] = side.x;     viewMatrixDouble[0][1] = up.x;     viewMatrixDouble[0][2] = -cameraDirectionVector.x;     
    viewMatrixDouble[1][0] = side.y;     viewMatrixDouble[1][1] = up.y;     viewMatrixDouble[1][2] = -cameraDirectionVector.y;     
    viewMatrixDouble[2][0] = side.z;     viewMatrixDouble[2][1] = up.z;     viewMatrixDouble[2][2] = -cameraDirectionVector.z;     


    /* 
    Vector actualEyePosition = this.getActualEyePosition(); 
    Vector zaxis = new Vector(this.lookAt.x - actualEyePosition.x, this.lookAt.y - actualEyePosition.y, this.lookAt.z - actualEyePosition.z).normalize(); 
    Vector xaxis = Vector.cross(upVector, zaxis).normalize(); 
    Vector yaxis = Vector.cross(zaxis, xaxis); 
    viewMatrixDouble[0][0] = xaxis.x;     viewMatrixDouble[0][1] = yaxis.x;     viewMatrixDouble[0][2] = zaxis.x;     
    viewMatrixDouble[1][0] = xaxis.y;     viewMatrixDouble[1][1] = yaxis.y;     viewMatrixDouble[1][2] = zaxis.y;     
    viewMatrixDouble[2][0] = xaxis.z;     viewMatrixDouble[2][1] = yaxis.z;     viewMatrixDouble[2][2] = zaxis.z;     
    viewMatrixDouble[3][0] = -Vector.dot(xaxis, actualEyePosition); viewMatrixDouble[3][1] =-Vector.dot(yaxis, actualEyePosition); viewMatrixDouble[3][2] = -Vector.dot(zaxis, actualEyePosition); 
    */ 
    viewMatrix = new Matrix4f(); 
    viewMatrix.load(getViewMatrixAsFloatBuffer()); 
} 

将柠greatfull如果任何人都可以验证,如果这是错还是对,如果它是错的;为我提供这样做的正确的方式... 我已经阅读了很多线程及文件的有关这一点,但我不能缝wrapp我围绕它的头......

回答

0

好吧,我最终在gamedev和朋友们的帮助下解决了这个问题,这里是链接到answer,我已经发布了代码!

0

我只是不明白什么是错误的,射线正在拍摄,我打的东西被删除,但事情并没有消失,我在屏幕上按下。

OpenGL不是一个场景图,它是一个绘图库。因此,在从内部表示中删除某些内容后,必须重新绘制场景。而你的代码缺少一些调用触发重绘的函数。

+0

感谢您的回复!我很抱歉,如果我有点不清楚,但这不是我的整个程序,只是处理3D采摘(位于世界控制器)的部分。场景的渲染是在程序的单独部分完成的(在世界视图中)。 我可以选择删除对象的结果,但由于某种原因删除了错误的对象。 – Wirde 2012-01-03 17:47:20