<bdo id='PSXpE'></bdo><ul id='PSXpE'></ul>

  1. <small id='PSXpE'></small><noframes id='PSXpE'>

    <legend id='PSXpE'><style id='PSXpE'><dir id='PSXpE'><q id='PSXpE'></q></dir></style></legend>
  2. <tfoot id='PSXpE'></tfoot>

  3. <i id='PSXpE'><tr id='PSXpE'><dt id='PSXpE'><q id='PSXpE'><span id='PSXpE'><b id='PSXpE'><form id='PSXpE'><ins id='PSXpE'></ins><ul id='PSXpE'></ul><sub id='PSXpE'></sub></form><legend id='PSXpE'></legend><bdo id='PSXpE'><pre id='PSXpE'><center id='PSXpE'></center></pre></bdo></b><th id='PSXpE'></th></span></q></dt></tr></i><div id='PSXpE'><tfoot id='PSXpE'></tfoot><dl id='PSXpE'><fieldset id='PSXpE'></fieldset></dl></div>

      如何将屏幕上的鼠标坐标转换为 3D 坐标

      时间:2023-09-17
      <i id='wwwrb'><tr id='wwwrb'><dt id='wwwrb'><q id='wwwrb'><span id='wwwrb'><b id='wwwrb'><form id='wwwrb'><ins id='wwwrb'></ins><ul id='wwwrb'></ul><sub id='wwwrb'></sub></form><legend id='wwwrb'></legend><bdo id='wwwrb'><pre id='wwwrb'><center id='wwwrb'></center></pre></bdo></b><th id='wwwrb'></th></span></q></dt></tr></i><div id='wwwrb'><tfoot id='wwwrb'></tfoot><dl id='wwwrb'><fieldset id='wwwrb'></fieldset></dl></div>

    1. <small id='wwwrb'></small><noframes id='wwwrb'>

          <tfoot id='wwwrb'></tfoot>

              <bdo id='wwwrb'></bdo><ul id='wwwrb'></ul>
              • <legend id='wwwrb'><style id='wwwrb'><dir id='wwwrb'><q id='wwwrb'></q></dir></style></legend>
                  <tbody id='wwwrb'></tbody>
                本文介绍了如何将屏幕上的鼠标坐标转换为 3D 坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                问题描述

                我正在使用 C++ 中的 GLUT 创建一个 3D 应用程序.

                I'm creating a 3D application using GLUT in C++.

                现在,我想实现一个类似这样的方法:

                Now, I want to implement a method similar to this:

                Vector3* MyClass::get3DObjectfromMouse(int mouseX, int mouseY);

                如何实现这个方法?

                推荐答案

                正如 Andon M. Coleman,实现此目的的一种方法是使用未投影的屏幕坐标进行光线/对象相交测试.这种技术通常称为挑选.

                As it was commented by Andon M. Coleman, one way you can achieve this is by doing a ray/object intersection test, with unprojected screen coordinates. This technique is commonly known as picking.

                假设我们有一个 3D 对象类型/类:

                Assume we have a 3D object type/class:

                class Object3D { ... };
                

                3D 拾取函数将返回所有对象的列表,这些对象与从近平面中的给定 2D 点到远平面中的同一点的直线相交.

                A 3D picking function would return a list of all objects that are intersected by a line going from the given 2D point in the near plane to the same point in the far plane.

                struct LineSegment 
                {
                    Vector3 start;
                    Vector3 end;
                };
                
                Object3D[] Pick(float x, float y)
                {
                    LineSegment lineSeg;
                    Object3D[] intersectedObjs;
                
                    // Do both un-projections for z-near (0) and z-far (1).
                    // This produces a line segment going from z-near to far.
                    UnProject(x, y, /* z = */ 0.0, modelViewMatrix, projectionMatrix, viewport, lineSeg.start);
                    UnProject(x, y, /* z = */ 1.0, modelViewMatrix, projectionMatrix, viewport, lineSeg.end);
                
                    // Iterate all object in the scene or in the current view:
                    for (Object3D obj : scene)
                    {
                        if (TestLineIntersection(obj, lineSeg))
                        {
                            // This object is crossed by the picking line.
                            intersectedObjs.Add(obj);
                        }
                    }
                
                    // Optionally you might want sort them from distance 
                    // to the camera/viewer before returning the intersections.
                    return intersectedObjs;
                }
                

                UnProject() 函数看起来像这样:

                bool UnProject(float winX, float winY, float winZ,
                               const Matrix4 & modelView, const Matrix4 & projection,
                               const ScreenRect viewport, Vector3 & worldCoordinates)
                {
                    // Compute (projection x modelView) ^ -1:
                    const Matrix4 m = inverse(projection * modelView);
                
                    // Need to invert Y since screen Y-origin point down,
                    // while 3D Y-origin points up (this is an OpenGL only requirement):
                    winY = viewport.Height() - winY;
                
                    // Transformation of normalized coordinates between -1 and 1:
                    Vector4 in;
                    in[0] = (winX - viewport.X()) / viewport.Width()  * 2.0 - 1.0;
                    in[1] = (winY - viewport.Y()) / viewport.Height() * 2.0 - 1.0;
                    in[2] = 2.0 * winZ - 1.0;
                    in[3] = 1.0;
                
                    // To world coordinates:
                    Vector4 out(m * in);
                    if (out[3] == 0.0) // Avoid a division by zero
                    {
                        worldCoordinates = Vector3Zero;
                        return false;
                    }
                
                    out[3] = 1.0 / out[3];
                    worldCoordinates[0] = out[0] * out[3];
                    worldCoordinates[1] = out[1] * out[3];
                    worldCoordinates[2] = out[2] * out[3];
                    return true;
                }
                

                澄清一下,TestLineIntersection() 与 AABB 对比交叉测试.边界框应该转换到世界空间,因为它通常表示为局部模型空间中的一组点.

                To clarify, TestLineIntersection() does a line vs AABB intersection test. The bounding box should be transformed to world-space, since it is usually expressed as a set of points in local model-space.

                bool TestLineIntersection(const Object3D & obj, const LineSegment & lineSeg)
                {
                    AABB aabb = obj.GetAABB();
                    aabb.TransformBy(obj.modelMatrix);
                    return aabb.LineIntersection(lineSeg.start, lineSeg.end);
                }
                
                // AABB.cpp:
                bool AABB::LineIntersection(const Vector3 & start, const Vector3 & end) const
                {
                    const Vector3 center     = (mins + maxs) * 0.5;
                    const Vector3 extents    = maxs - center;
                    const Vector3 lineDir    = 0.5 * (end - start);
                    const Vector3 lineCenter = start + lineDir;
                    const Vector3 dir        = lineCenter - center;
                
                    const float ld0 = Mathf::Abs(lineDir[0]);
                    if (Mathf::Abs(dir[0]) > (extents[0] + ld0))
                    {
                        return false;
                    }
                
                    const float ld1 = Mathf::Abs(lineDir[1]);
                    if (Mathf::Abs(dir[1]) > (extents[1] + ld1))
                    {
                        return false;
                    }
                
                    const float ld2 = Mathf::Abs(lineDir[2]);
                    if (Mathf::Abs(dir[2]) > (extents[2] + ld2))
                    {
                        return false;
                    }
                
                    const Vector3 vCross = cross(lineDir, dir);
                    if (Mathf::Abs(vCross[0]) > (extents[1] * ld2 + extents[2] * ld1))
                    {
                        return false;
                    }
                    if (Mathf::Abs(vCross[1]) > (extents[0] * ld2 + extents[2] * ld0))
                    {
                        return false;
                    }
                    if (Mathf::Abs(vCross[2]) > (extents[0] * ld1 + extents[1] * ld0))
                    {
                        return false;
                    }
                
                    return true;
                }
                

                这篇关于如何将屏幕上的鼠标坐标转换为 3D 坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                上一篇:glfw3 编译未定义的引用 下一篇:glReadPixels() “数据"参数用法?

                相关文章

                最新文章

                    <bdo id='LBCf3'></bdo><ul id='LBCf3'></ul>
                  1. <legend id='LBCf3'><style id='LBCf3'><dir id='LBCf3'><q id='LBCf3'></q></dir></style></legend>

                    <i id='LBCf3'><tr id='LBCf3'><dt id='LBCf3'><q id='LBCf3'><span id='LBCf3'><b id='LBCf3'><form id='LBCf3'><ins id='LBCf3'></ins><ul id='LBCf3'></ul><sub id='LBCf3'></sub></form><legend id='LBCf3'></legend><bdo id='LBCf3'><pre id='LBCf3'><center id='LBCf3'></center></pre></bdo></b><th id='LBCf3'></th></span></q></dt></tr></i><div id='LBCf3'><tfoot id='LBCf3'></tfoot><dl id='LBCf3'><fieldset id='LBCf3'></fieldset></dl></div>

                  2. <tfoot id='LBCf3'></tfoot>

                  3. <small id='LBCf3'></small><noframes id='LBCf3'>