简体   繁体   English

使用C ++和OpenGL拖动3维对象

[英]Dragging 3-Dimensional Objects with C++ and OpenGL

I have been developing a 3d chessboard and I have been stuck trying to drag the pieces for a few days now. 我一直在开发3D棋盘,而现在我一直在试图拖拉这些棋子几天。

Once I select an object using my ray-caster, I start my dragging function which calculates the difference between the current location of the mouse (in world coordinates) and its previous location, I then translate my object by the difference of these coordinates. 一旦使用射线投射器选择了一个对象,便会启动拖动功能,该功能将计算鼠标当前位置(在世界坐标中)与其先前位置之间的差异,然后通过这些坐标的差异来转换对象。

I debug my ray-caster by drawing lines so I am sure those coordinates are accurate. 我通过画线调试射线播放器,因此可以确保这些坐标正确。

Translating my object based on the ray-caster coordinates only moves the object a fraction of the distance it should actually go. 根据射线投射器坐标平移我的对象只会使该对象移动实际应走的距离的一小部分。

Am I missing a step? 我错过了一步吗?

-Calvin -Calvin

I believe my issue is in this line of code.... 我相信我的问题在这行代码中。

glm::vec3 World_Delta = Current_World_Location - World_Start_Location;

If I multiply the equation by 20 the object start to move more like I would expect it to, but it is never completely accurate. 如果将方程式乘以20,则对象开始运动得比我期望的要快,但是它永远不会完全准确。

Below is some relevent code 下面是一些相关的事件代码


RAY-CASTING: 光线投射:

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);
}

DRAGGING 拖动如果

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);

 }
}

I have already faced similar problems to what your reporting. 我已经遇到了与您的举报类似的问题。 Instead of keeping track of the translation during mouse movement, you can do the following: In your mouse button callback, store a 'Delta' vector from the mouse position (in world coordinates) (P_mouse) to your object position (P_object). 您可以执行以下操作,而不用跟踪鼠标移动过程中的平移:在您的鼠标按钮回调中,存储从鼠标位置(在世界坐标中)(P_mouse)到对象位置(P_object)的“ Delta”向量。 It would be something like: 就像这样:

Delta = P_object - P_mouse;

For every call of your mouse motion callback, you just need to update the object position by: 对于鼠标移动回调的每次调用,您只需要通过以下方法更新对象位置:

P_object = P_mouse + Delta;

Notice that Delta is constant during the whole dragging process. 请注意,在整个拖动过程中,Delta是恒定的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM