小编cma*_*t85的帖子

懒惰的评估和const正确性的问题

我制作了一个openGL相机类,它使用延迟评估通过getter函数提供最终投影或模型 - 视图 - 投影矩阵.用户在实例的整个生命周期(FOV,位置等)中提供各种相机参数,但不是每次更改参数时都重新计算投影矩阵和/或MVP矩阵,而是设置"已更改"标志(即旧的缓存矩阵现在无效).只要用户随后请求更新的最终矩阵,就会重新计算,结果缓存,并返回const引用.

一切都听起来不错,直到我打电话给我:

const QMatrix4x4& oE_GLCamera::getModelViewProjection() const;
Run Code Online (Sandbox Code Playgroud)

来自const oE_GLCamera实例的函数...我在我的应用程序中使用const引用来从CAD视口中提取相机数据而不更改相机,但是如果它们无效,我的getter函数会对成员变量执行惰性求值 - 因此会破坏const正确性.

是否有语言功能或设计范例我不知道如何帮助解决这个问题?或者懒惰的评估从根本上与const正确性不兼容?我知道const_cast <>,我自己从未使用过它,但读了一些关于它的内容,可以归结为:如果你使用它,你已经在某个地方出错了.还是会成为我的救世主?

Cam,任何建议都会得到很好的接受

c++ const-correctness lazy-evaluation

5
推荐指数
1
解决办法
634
查看次数

共享 OpenGL VAO/VBO/等。通过 QGLWidget

我正在使用 QGLWidgets 的 3 层层次结构在我的 CAD 类应用程序中的 5 个 OpenGL 视口之间共享着色器和顶点数据。根上下文用于编译应用程序范围的着色器,每个文档上下文用于共享模型顶点数据,视口上下文是实际进行渲染的上下文(并且还包含网格顶点数据和其他每个视口的东西)。

着色器共享似乎工作正常,网格绘图也是如此,但是在共享顶点数据时它失败了,老实说 - 我看不出它应该如何工作......

我为一个项目构建了一个 3D 图标,同时模型上下文是当前的,因为它是第一个 VAO,它的“名称”为 1。当我开始绘制对象时,视口上下文(与模型上下文共享,记住) 是当前的,所以 VAO 1 被调用,但绘制的是视口的VAO 1 - 我漂亮的红色网格中心线。可以共享 OpenGL 上下文,但是由于名称不是唯一的,您如何指定每个项目所属的“命名空间”?

我尝试在模型 VAO 调用之前使模型上下文成为当前状态,但是绘制了正确的 VAO 和视口,我认为在 QPainter::beginNativePainting() 块期间切换上下文不会让 OpenGL 满意。

这对我来说似乎是一件非常基本的事情,所以我一定是在做一些愚蠢的事情 - 有什么建议吗?

opengl qt qpainter qglwidget

5
推荐指数
1
解决办法
1238
查看次数

将FBO混合到默认帧缓冲区

澄清的是,当我说'默认帧缓冲'时,我的意思是窗口系统提供的那个以及显示器上的内容.

为了提高我的CAD应用程序的渲染速度,我设法将Qt处理的2D元素中的3D元素分离出来,现在它们都渲染到自己的FBO中.当我们将它们放到屏幕上时,我将3D FBO blit到默认的FB上,然后我想将我的2D FBO混合在它上面.

我已经完成了blitting部分,但我看不出如何将我的2D FBO混合到它上面?两个FBO的大小和格式都相同,它们都与默认FB相同.

我确信这是一个简单的操作,但我在网上找不到任何东西 - 大概我错过了正在尝试做的事情.虽然我正在使用Qt,但我可以毫无问题地使用原生OpenGL命令.

c++ opengl qt framebuffer

5
推荐指数
1
解决办法
2010
查看次数

从物品中获取窗口

在QML中有没有办法获得Window任何视觉对象的顶级?优选地,不通过视觉parent层级递归.

我正在尝试找到顶层窗口的几何体,因此后代对象可以检测它们的边界是否越过了窗口.

qt qml qtquick2

5
推荐指数
1
解决办法
1431
查看次数

QML:在派生类中使属性只读

我很确定答案是否定的,但我想我还是应该问一下。可以在纯 QML 派生类中将继承的属性设为只读/常量吗?

// Base.qml
Item {
    property int foo: 42
}

// Derived.qml
Base {
    foo: 99 // Make constant somehow!
}
Run Code Online (Sandbox Code Playgroud)

我目前正在通过检测更改foo并将错误打印到控制台来解决此问题,但这几乎不是良好 API 的标志......

我有一个菜单项类,它可以表示菜单项、子菜单、分隔符等。我需要专门化它的行为,但仅限于它处于子菜单模式时。我可以更改继承树,以便为每个菜单类型创建一个子类,但这似乎很愚蠢,因为每个子类只包含一个readonly属性。但是,如果没有其他方法,我将不得不这样做。

qt qml

5
推荐指数
2
解决办法
2038
查看次数

使用宏来创建QObject派生类

我试图简化(即摆脱样板代码的负载)创建QObject包装类,转发其他QObject派生类的属性访问.

从小处开始,我只是尝试使用一个属性:

// Sy_test.h - The wrapped class
class Sy_test : public QObject
{
    Q_OBJECT
    Q_PROPERTY( bool prop READ getProp WRITE setProp NOTIFY propChanged )

public:
    Sy_test( QObject* parent = nullptr ) :
        QObject{ parent },
        prop_{ false } {}

    bool getProp() const { return prop_; }

public slots:
    void setProp( bool value )
    {
        if ( value != prop_ ) {
            prop_ = value;
            emit propChanged( prop_ );
        }
    }

signals:
    void propChanged( bool value …
Run Code Online (Sandbox Code Playgroud)

c++ macros qt moc c-preprocessor

5
推荐指数
1
解决办法
540
查看次数

reinterpret_cast std :: function*来往于void*

当我从主可执行文件中调用std :: function时,通过将其地址转换为/从中,我在插件中遇到段错误void*.我可以在几个自包含的行中重现这个问题:

#include <iostream>
#include <functional>

int main()
{
    using func_t = std::function<const std::string& ()>;

    auto hn_getter = func_t{[]() {
        return "Hello";
    }};

    auto ptr = reinterpret_cast<void*>(&hn_getter);

    auto getter = reinterpret_cast<func_t*>(ptr);
    std::cout << (*getter)() << std::endl;   // Bang!

    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

即使我正在使用原始类型,它仍然是segfaulting.谁能看到我哪里出错了?

c++ void-pointers reinterpret-cast std-function

5
推荐指数
1
解决办法
663
查看次数

boost::asio::co_spawn 不会传播异常

我正在涉足关于 boost::asio 的协程,并且我对异常处理感到困惑。从文档中的示例 来看,看起来任何“失败”都会变成异常 - 所以我希望假设抛出的任何异常也会传播回调用。但情况似乎并非如此:error_codeco_spawn

#define BOOST_ASIO_HAS_CO_AWAIT
#define BOOST_ASIO_HAS_STD_COROUTINE

#include <iostream>

#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/executor_work_guard.hpp>

namespace this_coro = boost::asio::this_coro;

boost::asio::awaitable<void> async_op()
{
    std::cout << "About to throw" << std::endl;
    throw std::runtime_error{"Bang!"};
}

int main()
{
    auto ctx = boost::asio::io_context{};
    auto guard = boost::asio::make_work_guard(ctx.get_executor());

    boost::asio::co_spawn(ctx, async_op, boost::asio::detached);

    ctx.run();
}
Run Code Online (Sandbox Code Playgroud)

如果这是在调试器中运行,您可以看到抛出异常,但它似乎只是挂起。暂停调试器表明正在ctx.run()等待新的工作(由于executor_work_guard)。所以看起来 boost::asio 内部的某些东西已经默默地吞噬了异常。

作为实验,我将异步操作切换为使用 boost::asio 库调用:

boost::asio::awaitable<void> async_op()
{
    auto executor = co_await this_coro::executor;
    auto …
Run Code Online (Sandbox Code Playgroud)

c++ boost exception coroutine

5
推荐指数
1
解决办法
1359
查看次数

在64位操作系统中使用glMultiDrawElements

我最近从32位环境迁移到64位环境,除了一个问题之外它已经顺利完成了:glMultiDrawElements使用一些在64位操作系统下没有一些调整就无法工作的阵列.

glMultiDrawElements( GL_LINE_LOOP, fCount_, GL_UNSIGNED_INT,
                     reinterpret_cast< const GLvoid** >( iOffset_ ),
                     mesh().faces().size() );
Run Code Online (Sandbox Code Playgroud)

我正在使用VBO来处理顶点和顶点索引. fCount_并且iOffset_是数组GLsizei.由于缓冲区是绑定到GL_ELEMENT_ARRAY_BUFFER,iOffset_的元件被用作从VBO开始字节偏移.这在32位操作系统下完美运行.

如果我改变glMultiDrawElementsglDrawElements并把它变成一个循环,它工作在两个平台上罚款:

int offset = 0;
for ( Sy_meshData::Faces::ConstIterator i  = mesh().faces().constBegin();
                                        i != mesh().faces().constEnd(); ++i ) {
    glDrawElements( GL_LINE_LOOP, i->vertexIndices.size(), GL_UNSIGNED_INT,
                    reinterpret_cast< const GLvoid* >( sizeof( GLsizei ) * offset ) );
    offset += i->vertexIndices.size();
 }
Run Code Online (Sandbox Code Playgroud)

我认为我所看到的是OpenGL读取64位块iOffset_导致大量数字,但glMultiDrawElements不支持任何类型超过32位(GL_UNSIGNED_INT),所以我不知道如何纠正它.

有没有其他人有这种情况并解决了它?或者我处理这个完全错误并且在32位操作系统上运气真的很幸运?

更新

换掉我现有的代码:

typedef void ( *testPtr …
Run Code Online (Sandbox Code Playgroud)

c++ opengl 64-bit vbo

4
推荐指数
1
解决办法
1002
查看次数

使用编译器定义的宏连接

这应该很简单,但我很难弄明白.我有PROJECT_NAME一个编译器(g++)-D定义,我想将它与其他一些文本连接起来形成一个命名空间名称.我目前的做法是:

#define VERSION_NAMESPACE PROJECT_NAME ## Versioning
Run Code Online (Sandbox Code Playgroud)

对于我目前的项目,我希望VERSION_NAMESPACE如此Syren_DLLVersioning.相反,我得到一个编译器错误:

error: 'PROJECT_NAMEVersioning' has not been declared
Run Code Online (Sandbox Code Playgroud)

但根据g++电话,PROJECT_NAME正在正确定义:

ccache g++ ... -DPROJECT_NAME=Syren_DLL ...
Run Code Online (Sandbox Code Playgroud)

PROJECT_NAME在连接发生之前为什么不被替换?

c c++ c-preprocessor

4
推荐指数
1
解决办法
375
查看次数