在 C++/OpenGL 中投影一个围绕另一个对象旋转的对象

Posted

技术标签:

【中文标题】在 C++/OpenGL 中投影一个围绕另一个对象旋转的对象【英文标题】:Project an object with rotation around another object in C++/OpenGL 【发布时间】:2016-03-10 16:11:36 【问题描述】:

我正在使用 OpenGL/C++ 创建游戏。

我正在开发的这款游戏的一个方面是让一个角色以所述角色面对的方式发射弹丸。为此,我有一个“玩家”和一个“射弹”。

我将字符 x 和 y 坐标(玩家面对的角度)传递给射弹。从这里我想朝那个方向发射弹丸。

在我的绘图中,我目前正在使用带有字符 x 和 y 的 glTranslate,并在角色面对的方向上旋转弹丸。这会将我的弹丸移动到玩家面对的方向。

glTranslatef(this->m_X, this->m_Y, 0);
        glRotatef(angle, 0, 0, 1);

这是我卡住的地方,我可以通过增加/减少平移中的 X 和 Y 值来移动弹丸位置。但我想问的是如何沿着玩家面对的线移动弹丸。

感谢您的帮助!

【问题讨论】:

如果你的角色面对的方向是dir=(dirx,diry,dirz),那么只需将当前位置增加dir*s = (dirx*s,diry*s,dirz*s),其中s表示弹丸的速度 问题是每次只会对角发送。我想按照玩家面对的方向(鼠标)发送它。我用鼠标转动播放器,这给了我播放器旋转的角度。我不知何故需要用它来移动我假设的弹丸? 确实希望弹丸飞行 a) 弹丸开始时玩家面向的方向或 b) 使其在飞行时改变方向以始终朝玩家面向的方向飞行或c) 让它改变方向,朝着玩家面对的方向飞向地平线上的点? 我希望弹丸在弹丸开始时朝玩家所面对的方向飞行 【参考方案1】:

您可以使用极向量进行这些计算。

http://mathworld.wolfram.com/PolarVector.html

极向量可以让您以简单的方式进行一些通常很复杂且令人费解的计算。使用他们的应用数学,您的请求不会成为问题。

这是我的极向量的实现。

头文件:

#include <cmath>

//Using SFML Vector2 class, making a similar class is easy.
//Check this URL: http://www.sfml-dev.org/documentation/2.3.2/classsf_1_1Vector2.php

class PolarVector 

    public:
        float r;
        float t; ///Angle stored in degrees.

        PolarVector();
        PolarVector(float radius, float angle);
        PolarVector(const sf::Vector2f V2); ///Conversion constructor.

        sf::Vector2f TurnToRectangular() const;

;

PolarVector TurnToPolar(const sf::Vector2f point);

float getConvertedRadius(const sf::Vector2f point);

float getConvertedAngle(sf::Vector2f point);

bool operator ==(const PolarVector& left, const PolarVector& right);

bool operator !=(const PolarVector& left, const PolarVector& right);

还有源文件:

#include "PolarVector.hpp"

PolarVector::PolarVector()
  :r(0.f)
  ,t(0.f)


PolarVector::PolarVector(float radius, float angle)
  :r(radius)
  ,t(angle)


PolarVector::PolarVector(const sf::Vector2f V2)
 :r(getConvertedRadius(V2))
 ,t(getConvertedAngle(V2))


sf::Vector2f PolarVector::TurnToRectangular() const
 return sf::Vector2f(static_cast<float>(r* std::cos(t)),    static_cast<float>(r* std::sin(t))); 

PolarVector TurnToPolar(const sf::Vector2f point)

    PolarVector PV;
    PV.r = getConvertedAngle(point);
    PV.t = getConvertedRadius(point);
    return PV;


float getConvertedRadius(const sf::Vector2f point)
 return std::sqrt((point.x * point.x) + (point.y * point.y) ); 

float getConvertedAngle(const sf::Vector2f point)
 return std::atan2(point.y, point.x); 

bool operator ==(const PolarVector& left, const PolarVector& right)

    float diffR = left.r - right.r;
    float diffA = left.t - right.t;
    return ((diffR <= EPSILON) && (diffA <= EPSILON));


bool operator !=(const PolarVector& left, const PolarVector& right)

    float diffR = left.r - right.r;
    float diffA = left.t - right.t;
    return !((diffR <= EPSILON) && (diffA <= EPSILON));

我之所以建议这样做是因为您可以执行以下操作。

假设你有一个二维向量:

sf::Vector2f character(0.f, 0.f); //Origin point. First parameter is X, second is Y
float angleCharFacesAt = 0.698132; //40 degrees in radians. C++ Trigonometry uses Radians. std::cos, std::sin and std::atan2 are used internally.

对于第一个对象或字符。您希望另一个对象具有相同的角度,但位置不同。

假设另一个对象在其上方有一个位置:

sf::Vector2f object(0.f, 10.f); //Above the origin point.
float angleObjectFacesAt = 0.f; //0 degrees.

所以您需要做的就是使用极向量旋转它:

PolarVector PV = TurnToPolar(object); //Use this for calculations.
PV.t += angleCharFacesAt; //t is the angle parameter of the polar vector.

object = PV.TurnToRectangular(object);

通过这样做,您将获得对象的旋转位置。

一个对象与另一个对象之间的距离将始终是极向量的 r(半径)值。因此,您可以通过以下方式使距离变长或变短:

PolarVector PV = TurnToPolar(object); //Use this for calculations.
PV.r += 10; //Increase the radius to increase the distance between the objects.

object = PV.TurnToRectangular(object);

您应该尝试了解旋转矩阵和极坐标数学,以便能够通过此实现更多目标,但使用此代码是可能的。您还应该将所有这些代码放在一个类中,但要先玩它,直到您完全理解为止。

抱歉,回答冗长,但如果不深入研究线性代数,这是一个不容易解释的话题。这些类用于实际的代码可管理性(我在自己的游戏中使用它们),但您可以仅通过计算重现相同的效果。

我个人更喜欢极向量而不是使用旋转矩阵,因为它们不仅仅用于旋转对象。但这里有一个链接可以更好地理解旋转矩阵:https://en.wikipedia.org/wiki/Rotation_matrix

用极向量完成变换后,您可以直接平移到极向量给出的最终位置。您必须确保围绕您使用的原点旋转。否则可能不会按照您的意愿进行轮换。

【讨论】:

请注意,对于我使用的示例,我只专注于围绕另一个点旋转,您可能使用纹理、三角形或四边形等,因此必须根据这些计算来调整这些计算案例。这个答案是为了解释一些极坐标数学在单二维点旋转中的用例。 感谢您的辛勤工作。然而,我意识到有一点是我从中得到原始角度的。因此我使用了这一点,这使公式变得更加容易......我确实需要实现向量所以这绝对不会浪费! np,很高兴我能帮上忙。

以上是关于在 C++/OpenGL 中投影一个围绕另一个对象旋转的对象的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL中投影矩阵基础知识

OpenGL中投影变换函数的实现

如何从对象数组中投影所有嵌套文档?

在 Winforms 控件中投影?

在 Pig 中投影分组元组

从与数组上的查询条件匹配的第一个元素中投影特定字段