gpt4 book ai didi

c++ - 在 SFML 中对对象进行分组的最佳方法是什么?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:34:02 67 4
gpt4 key购买 nike

例如,如果我在 SFML 中有 3 种不同的形状,并且我想将它们全部相对于一个中心旋转,就好像这 3 种形状在一个正方形内一样,最好的方法是什么?是否会将它们留在 View 中并旋转 View ?或者有什么更实用的方法吗?

最佳答案

虽然我将要提出的方法并不是那么简单,在某种程度上违反直觉,但功能更强大,每个渲染引擎都以一种或另一种形式使用它。大多数渲染和游戏引擎,如 Ogre3dUnreal Engine(实际上,它的渲染引擎)使用诸如场景图之类的东西来对对象和关系坐标进行分组绘制它们的系统,如果您想深入研究计算机图形学,则需要习惯这些东西。

假设您要编写一个程序来可视化地球和月球围绕太阳的自转。假设,太阳是中心并且不动。地球绕着太阳转,这很容易实现。但也有围绕地球旋转的月球,它的轨迹很难计算,我什至没有提到行星的旋转不是完美的圆形。如果我们有另一个围绕月球旋转的鹅卵石呢?这将是一团糟。

人类提出的解决方案是从太阳的旋转中抽象出月亮的旋转。月球绕地球转,对吧?所以诀窍就是将月球的坐标系与地球严格绑定(bind),并像太阳不存在一样实现月球的自转。另一个技巧是将地球坐标系与太阳严格绑定(bind)并实现地球自转,就像月球和其他宇宙不存在一样。如您所见,对象的层次结构清晰:Sun->Earth->Moon。在计算机图形学方面,太阳是地球的对象,而地球是太阳的对象。地球和月球也是如此:地球是月球的对象,而月球是地球的对象。整个系统称为场景图

不幸的是,与渲染引擎不同,SFML 没有为场景图提供现成的类,但它为我们提供了实现它的工具。这是我的实现:

//SceneNode.h
class SceneNode :
public sf::Transformable,
public sf::Drawable,
private sf::NonCopyable {
public:
typedef std::unique_ptr<SceneNode> Ptr;
typedef std::pair<SceneNode*, SceneNode*> Pair;

explicit SceneNode();

void AttachChild( Ptr child );
Ptr DetachChild( const SceneNode& node );

private:
virtual void draw(
sf::RenderTarget& target,
sf::RenderStates states
) const;
virtual void DrawCurrent(
sf::RenderTarget& target,
sf::RenderStates states
) const;
void DrawChildren(
sf::RenderTarget& target,
sf::RenderStates states
) const;

std::vector<Ptr> mChildren;
SceneNode* mParent;
};

//SceneNode.cpp
SceneNode::SceneNode( Category::Type category ) :
mChildren(),
mParent( nullptr ) {}

void
SceneNode::AttachChild( Ptr child ) {
child->mParent = this;
mChildren.push_back( std::move( child ) );
}

SceneNode::Ptr
SceneNode::DetachChild( const SceneNode& node ) {
auto found = std::find_if(
mChildren.begin(),
mChildren.end(),
[&] ( Ptr& p ) { return p.get() == &node; }
);
assert( found != mChildren.end() );

Ptr result = std::move( *found );
result->mParent = nullptr;
mChildren.erase( found );
return result;
}

void
SceneNode::draw( sf::RenderTarget& target, sf::RenderStates states ) const {
states.transform *= getTransform();

DrawCurrent( target, states );
DrawChildren( target, states );
}

void
SceneNode::DrawCurrent(
sf::RenderTarget& target,
sf::RenderStates states
) const {}

void
SceneNode::DrawChildren(
sf::RenderTarget& target,
sf::RenderStates states
) const {
for ( const Ptr& child : mChildren ) {
child->draw( target, states );
}
}

任何 SceneNode 都可以像矩形一样简单地绘制,但是在绘制它自己之后,SceneNode 会绘制它的所有子节点,如果你没有忘记实现 SceneNode::DrawCurrent 方法。

关于c++ - 在 SFML 中对对象进行分组的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50031880/

67 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com