Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenGL中的轨迹球旋转_Opengl - Fatal编程技术网

OpenGL中的轨迹球旋转

OpenGL中的轨迹球旋转,opengl,Opengl,我在OpenGL上实现轨迹球旋转时遇到问题。当我使用轨迹球沿X轴向右旋转90度(在屏幕上从左向右拖动鼠标)旋转立方体,然后尝试将其从屏幕顶部拖动到底部时,我希望立方体沿透视图的y轴旋转。相反,它在旋转后会沿着y轴旋转,从我的角度来看是侧向旋转 有人能告诉我我做错了什么吗?听起来你没有用四元数来表示旋转。如果你搜索“Arcball Graphics Gems”,你应该能够在Graphic Gems IV中找到Ken Shoemake的代码 或者,如果您只需要代码,.+1以获取Daniel关于四元数

我在OpenGL上实现轨迹球旋转时遇到问题。当我使用轨迹球沿X轴向右旋转90度(在屏幕上从左向右拖动鼠标)旋转立方体,然后尝试将其从屏幕顶部拖动到底部时,我希望立方体沿透视图的y轴旋转。相反,它在旋转后会沿着y轴旋转,从我的角度来看是侧向旋转


有人能告诉我我做错了什么吗?

听起来你没有用四元数来表示旋转。如果你搜索“Arcball Graphics Gems”,你应该能够在Graphic Gems IV中找到Ken Shoemake的代码


或者,如果您只需要代码,.

+1以获取Daniel关于四元数和Arcball的建议。您应该始终使用四元数来表示方向和旋转

另外一个提示:Gavin Bell实现的Arcball的扩展使鼠标在旋转球体外的点击更加直观。它在Glut库的示例中随一起分发,以及

它与实现类似,但球体内部和外部之间的过渡是平滑的。Bell的方法用于许多开源3D库,包括:

  • Meshlab/

我找到了一种既便宜又肮脏的方法。 所以OpenGL中的矩阵是这样的
0123
4567
891011
12 13 14 15

如果你把3个垂直数字作为你的旋转矢量,你会得到你想要的效果。例如:

如果围绕向量(0、4、8)旋转,则将围绕x轴旋转。
类似地,(1,5,9)将是y,(3,6,10)将是z.
为什么有效?。。。。当你取垂直数时,你做了一个原始矩阵的转置副本,这给了你一个与旋转矩阵相比的原点矩阵。。。。。对不起,我不是数学家,但它是有效的。相信我;)

我在OpenGL ES上的示例代码:

        Matrix.rotateM(Settings.anchorMatrix, 0, rX, Settings.anchorMatrix[0], Settings.anchorMatrix[4], Settings.anchorMatrix[8]);
        Matrix.rotateM(Settings.anchorMatrix, 0, rY, Settings.anchorMatrix[1], Settings.anchorMatrix[5], Settings.anchorMatrix[9]);
        Matrix.rotateM(Settings.anchorMatrix, 0, rZ, Settings.anchorMatrix[2], Settings.anchorMatrix[6], Settings.anchorMatrix[10]);

从技术上讲,anchorMatrix是我为跟踪而创建的主要矩阵。Android OpenGL ES不允许我从状态机获取当前矩阵。

这是一个非常古老的问题,但我遇到了完全相同的问题,因为我试图将learnopengl.com中的摄像头代码改编为Arcball模型。。。重要的是,我不想转移到四元数,因为用四元数做的任何事情都可以用标准线性代数来完成

我找到的一个解决方案是将弧球的坐标转换为相机坐标(就像弧球随相机旋转一样)

我还使用Rodrigues公式旋转相机的位置、前向和上向向量,然后使用glm:LookAt返回最终的ViewMatrix(输入顶点着色器的ViewMatrix)

目前,我有一个快速而肮脏的解决方案,如下所示:

// Processes input received from a mouse input system. 
void ProcessMouseMovement(glm::vec2 prevMouse, glm::vec2 curMouse)
{
    glm::vec3 p1 = screen_to_arcball( curMouse );
    glm::vec3 p2 = screen_to_arcball( prevMouse );

    // Rotate arcball to camera coordinates
    p1 = glm::vec3( glm::inverse(ViewMatrix) * glm::vec4(p1, 0.0));
    p2 = glm::vec3( glm::inverse(ViewMatrix) * glm::vec4(p2, 0.0));

    glm::vec3 axis = glm::cross(p1, p2);

    float angle = std::acos(glm::dot(p1,p2));

    if ( angle > 0.001f)
    {
        // Rotate
        Position = rotate_axis_angle(Position, axis, angle);
        Front = rotate_axis_angle(Front, axis, angle);
        Up = rotate_axis_angle(Up, axis, angle);

        ViewMatrix = glm::lookAt(Position, Position + Front, Up);
    }
}

// Get Arcball coordinates from screen
glm::vec3 screen_to_arcball(const glm::vec2 &p)
{
    const float dist = glm::dot(p, p);
    if (dist < 0.999f) 
    {
        // If we're on/in the sphere return the point on it
        return glm::vec3(p.x, p.y, std::sqrt(1.f - dist));
    } 
    else 
    {
        // otherwise we project the point onto the sphere
        const glm::vec2 proj = glm::normalize(p);
        return glm::vec3(proj.x, proj.y, 0.f);
    }
}

// Rotate vector given (angle,axis) using Rodrigues' formula
glm::vec3 rotate_axis_angle(glm:: vec3 &vec, glm:: vec3 axis, float angle)
{
    axis = glm::normalize(axis);
    glm::vec3 cross_axis = glm::cross(axis, vec);
    vec = vec * std::cos(angle) + axis * glm::dot(axis,vec) * (1.0f - std::cos(angle)) + cross_axis * std::sin(angle); 
    return vec;
}
//处理从鼠标输入系统接收的输入。
void ProcessMouseMovement(glm::vec2 prevMouse,glm::vec2 curMouse)
{
glm::vec3 p1=屏幕到弧球(鼠标);
glm::vec3 p2=屏幕到弧球(鼠标前);
//将弧球旋转到摄影机坐标
p1=glm::vec3(glm::逆(ViewMatrix)*glm::vec4(p1,0.0));
p2=glm::vec3(glm::inverse(ViewMatrix)*glm::vec4(p2,0.0));
glm::vec3轴=glm::交叉(p1,p2);
浮动角度=std::acos(glm::dot(p1,p2));
如果(角度>0.001f)
{
//轮换
位置=旋转轴角度(位置、轴、角度);
前=旋转轴角度(前、轴、角度);
向上=旋转轴角度(向上,轴,角度);
ViewMatrix=glm::注视(位置、位置+前方、上方);
}
}
//从屏幕获取弧球坐标
glm::vec3屏幕至电弧球(常量glm::vec2&p)
{
常量浮点距离=glm::点(p,p);
如果(距离<0.999f)
{
//如果我们在球体上,返回球体上的点
返回glm::vec3(p.x,p.y,std::sqrt(1.f-dist));
} 
其他的
{
//否则,我们将点投影到球体上
常量glm::vec2 proj=glm::normalize(p);
返回glm::vec3(项目x、项目y、0.f);
}
}
//使用罗德里格斯公式旋转给定矢量(角度、轴)
glm::vec3旋转\轴\角度(glm::vec3&vec,glm::vec3轴,浮动角度)
{
axis=glm::规格化(axis);
glm::vec3交叉轴=glm::交叉轴(轴,vec);
vec=vec*std::cos(角度)+轴*glm::dot(轴,vec)*(1.0f-std::cos(角度))+十字轴*std::sin(角度);
返回向量;
}

顺便说一句,我从中获取了screen-to-arcball函数。

你能发布一个最小过剩程序来演示这个问题吗?还有一些ArcBall代码。