2015-01-11 55 views
0

我一直在開發一個3d棋盤,並且我一直試圖拖動這些碎片幾天。使用C++和OpenGL拖動三維物體

一旦我使用射線輪選擇了一個物體,我開始了我的拖動功能,該功能計算鼠標當前位置(在世界座標中)和它之前的位置之間的差異,然後根據這些座標。

我通過畫線來調試我的射線輪,所以我確定這些座標是準確的。

根據射線腳輪座標平移我的物體只會移動物體一小部分距離。

我錯過了一個步驟嗎?

-Calvin

我相信我的問題是在這行代碼....

glm::vec3 World_Delta = Current_World_Location - World_Start_Location; 

如果我用20乘以方程式的對象開始將更多像我期望它,但它永遠不會完全準確。

下面是一些培訓相關代碼


光線投射:

void CastRay(int mouse_x, int mouse_y) { 

int Object_Selected = -1; 
float Closest_Object = -1; 

//getWorldCoordinates calls glm::unproject 
nearPoint = Input_Math.getWorldCoordinates(glm::vec3(mouse_x, Window_Input_Info.getScreenHeight()-mouse_y, 0.0f)); 
farPoint = Input_Math.getWorldCoordinates(glm::vec3(mouse_x, Window_Input_Info.getScreenHeight()-mouse_y, 1.0f)); 

glm::vec3 direction = Input_Math.normalize(farPoint - nearPoint); 

//getObjectStack() Retrieves all objects in the current scene 
std::vector<LoadOBJ> objectList = Object_Input_Info.getObjectStack(); 
for (int i = 0; i < objectList.size(); i++) { 
    std::vector<glm::vec3> Vertices = objectList[i].getVertices(); 
    for(int j = 0; j < Vertices.size(); j++) { 
     if ((j + 1) % 3 == 0) { 
      glm::vec3 face_normal = Input_Math.normalize(Input_Math.CrossProduct(Vertices[j-1] - Vertices[j-2], Vertices[j] - Vertices[j-2])); 
      float nDotL = glm::dot(direction, face_normal); 
      if (nDotL <= 0.0f) { //if nDotL == 0 { Perpindicular } else if nDotL < 0 { SameDirection } else { OppositeDirection } 
       float distance = glm::dot(face_normal, (Vertices[j-2] - nearPoint))/nDotL; 
       glm::vec3 p = nearPoint + distance * direction; 
       glm::vec3 n1 = Input_Math.CrossProduct(Vertices[j-1] - Vertices[j-2], p - Vertices[j-2]); 
       glm::vec3 n2 = Input_Math.CrossProduct(Vertices[j] - Vertices[j-1], p - Vertices[j-1]); 
       glm::vec3 n3 = Input_Math.CrossProduct(Vertices[j-2] - Vertices[j], p - Vertices[j]); 
       if(glm::dot(face_normal, n1) >= 0.0f && glm::dot(face_normal, n2) >= 0.0f && glm::dot(face_normal, n3) >= 0.0f) { 
        if(p.z > Closest_Object) { 

         //I Create this "dragplane" to be used by my dragging function. 
         Drag_Plane[0] = (glm::vec3(Vertices[j-2].x, Vertices[j-2].y, p.z)); 
         Drag_Plane[1] = (glm::vec3(Vertices[j-1].x, Vertices[j-1].y, p.z)); 
         Drag_Plane[2] = (glm::vec3(Vertices[j].x , Vertices[j].y , p.z)); 

         //This is the object the we selected in the scene 
         Object_Selected = i; 

         //These are the coordinate the ray intersected the object 
         World_Start_Location = p; 

        } 
       } 
      } 
     } 
    } 
} 
if(Object_Selected >= 0) { //If an object was intersected by the ray 
    //selectObject -> Simply sets the boolean "dragging" to true 
    selectObject(Object_Selected, mouse_x, mouse_y); 
} 

拖動到你的報告

void DragObject(int mouse_x, int mouse_y) { 

if(dragging) { 

    //Finds the Coordinates where the ray intersects the "DragPlane" set by original object intersection 
    farPoint = Input_Math.getWorldCoordinates(glm::vec3(mouse_x, Window_Input_Info.getScreenHeight()-mouse_y, 1.0f)); 
    nearPoint = Input_Math.getWorldCoordinates(glm::vec3(mouse_x, Window_Input_Info.getScreenHeight()-mouse_y, 0.0f)); 
    glm::vec3 direction = Input_Math.normalize(farPoint - nearPoint); 
    glm::vec3 face_normal = Input_Math.normalize(Input_Math.CrossProduct(Drag_Plane[1] - Drag_Plane[0], Drag_Plane[2] - Drag_Plane[0])); 
    float nDotL = glm::dot(direction, face_normal); 
    float distance = glm::dot(face_normal, (Drag_Plane[0] - nearPoint))/nDotL; 
    glm::vec3 Current_World_Location = nearPoint + distance * direction; 

    //Calculate the difference between the current mouse location and its previous location 
    glm::vec3 World_Delta = Current_World_Location - World_Start_Location; 

    //Set the "start location" to the current location for the next loop 
    World_Start_Location = Current_World_Location; 

    //get the current object 
    Object_Input_Info = Object_Input_Info.getObject(currentObject); 

    //adds a translation matrix to the stack 
    Object_Input_Info.TranslateVertices(World_Delta.x, World_Delta.y, World_Delta.z); 

    //calculates the new vertices 
    Object_Input_Info.Load_Data(); 

    //puts the new object back 
    Object_Input_Info.Update_Object_Stack(currentObject); 

} 
} 
+1

請發表相關的代碼。 –

回答

1

我已經遇到了類似的問題。 您可以執行以下操作,而不是在鼠標移動期間跟蹤翻譯: 在鼠標按鈕回調中,將鼠標位置(以世界座標)(P_mouse)的「Delta」向量存儲到對象位置(P_object) 。這將是這樣的:

Delta = P_object - P_mouse; 

爲了您的鼠標移動回調的每一個電話,你只需要通過更新目標位置:

P_object = P_mouse + Delta; 

注意三角洲是在整個拖動過程中不變。

+0

非常感謝您的幫助。使用你的想法作爲解決我的問題的新方法,我確定問題不在上面的代碼中,而是在我的「Load_Data()」函數中。 – Calvin