六、模型显示位置与放缩

参考文档

# https://docs.live2d.com/zh-CHS/cubism-sdk-manual/layout/

查看 LAppLive2DManager.cpp 中的 ChangeScene 方法,

void LAppLive2DManager::ChangeScene(Csm::csmInt32 index)
{
    _sceneIndex = index;
    if (DebugLogEnable)
    {
        LAppPal::PrintLog("[APP]model index: %d", _sceneIndex);
    }

    // ModelDir[]に保持したディレクトリ名から
    // model3.jsonのパスを決定する.
    // ディレクトリ名とmodel3.jsonの名前を一致させておくこと.
    std::string model = ModelDir[index];
    std::string modelPath = ResourcesPath + model + "/";
    std::string modelJsonName = ModelDir[index];
    modelJsonName += ".model3.json";

    ReleaseAllModel();
    _models.PushBack(new LAppModel());
    _models[0]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());


    /*
     * モデル半透明表示を行うサンプルを提示する。
     * ここでUSE_RENDER_TARGET、USE_MODEL_RENDER_TARGETが定義されている場合
     * 別のレンダリングターゲットにモデルを描画し、描画結果をテクスチャとして別のスプライトに張り付ける。
     */
    {
#if defined(USE_RENDER_TARGET)
        // LAppViewの持つターゲットに描画を行う場合、こちらを選択
        LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ViewFrameBuffer;
#elif defined(USE_MODEL_RENDER_TARGET)
        // 各LAppModelの持つターゲットに描画を行う場合、こちらを選択
        LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_ModelFrameBuffer;
#else
        // デフォルトのメインフレームバッファへレンダリングする(通常)
        LAppView::SelectTarget useRenderTarget = LAppView::SelectTarget_None;
#endif

#if defined(USE_RENDER_TARGET) || defined(USE_MODEL_RENDER_TARGET)
        // モデル個別にαを付けるサンプルとして、もう1体モデルを作成し、少し位置をずらす
        _models.PushBack(new LAppModel());
        _models[1]->LoadAssets(modelPath.c_str(), modelJsonName.c_str());
        _models[1]->GetModelMatrix()->TranslateX(0.2f);
#endif

        LAppDelegate::GetInstance()->GetView()->SwitchRenderingTarget(useRenderTarget);

        // 別レンダリング先を選択した際の背景クリア色
        float clearColor[3] = { 1.0f, 1.0f, 1.0f };
        LAppDelegate::GetInstance()->GetView()->SetRenderTargetClearColor(clearColor[0], clearColor[1], clearColor[2]);
    }
}

我们可以通过调整 ModelMatrix 成员属性来进行平移或者放缩,

_models[0]->GetModelMatrix()->ScaleRelative(0.5f,0.5f);
_models[0]->GetModelMatrix()->TranslateX(1.15f);
_models[0]->GetModelMatrix()->TranslateY(-0.40f);
/**
* @brief   現在のシーンで保持しているモデルを返す
*
* @param[in]   no  モデルリストのインデックス値
* @return      モデルのインスタンスを返す。インデックス値が範囲外の場合はNULLを返す。
*/
LAppModel* GetModel(Csm::csmUint32 no) const;

一、平移、放缩实现

我们创建一个全屏、透明、无边框且始终在最前端的主窗口作为示例:窗口包含一个自定义的OpenGL小部件作为中心部件,并添加了三个滑块用于调试平移和缩放功能。这些滑块分别控制缩放、X轴平移和Y轴平移,并通过信号和槽机制将滑块值变化与相应的槽函数连接起来。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setGeometry(QRect(-1,-1,QGuiApplication::primaryScreen()->size().width() + 2, QGuiApplication::primaryScreen()->size().height() + 2));

    setAttribute(Qt::WA_TranslucentBackground);
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);

    myopengl = new MyOpenGL(this);
    setCentralWidget(myopengl);


    // 切换缩放比时,EnableHighDpiScaling 会触发 physicalDotsPerInchChanged
    // 此时 Qt6 不触发 logicalDotsPerInchChanged
    QScreen *screen = qApp->primaryScreen();
    connect(screen,&QScreen::physicalDotsPerInchChanged,this,&MainWindow::onPhysicalDotsPerInchChanged);


    // 平移、放缩 Debug
    int availableWidth = QGuiApplication::primaryScreen()->availableGeometry().width();
    int availableHeight = QGuiApplication::primaryScreen()->availableGeometry().height();

    QSlider *scaleSlider = new QSlider(this);
    scaleSlider->setOrientation(Qt::Horizontal);
    scaleSlider->setMaximum(200);
    scaleSlider->setMinimum(-200);
    scaleSlider->setSingleStep(10);
    scaleSlider->setGeometry((availableWidth - 100)/2, (availableHeight - 50)/2, 100, 50);

    connect(scaleSlider,&QSlider::valueChanged,this,&MainWindow::onScaleValueChanged);

    QSlider *translateXSlider = new QSlider(this);
    translateXSlider->setOrientation(Qt::Horizontal);
    translateXSlider->setMaximum(200);
    translateXSlider->setMinimum(-200);
    translateXSlider->setSingleStep(10);
    translateXSlider->setGeometry((availableWidth - 100)/2, (availableHeight - 50)/2 - 100, 100, 50);

    connect(translateXSlider,&QSlider::valueChanged,this,&MainWindow::onTranslateXValueChanged);

    QSlider *translateYSlider = new QSlider(this);
    translateYSlider->setOrientation(Qt::Horizontal);
    translateYSlider->setMaximum(200);
    translateYSlider->setMinimum(-200);
    translateYSlider->setSingleStep(10);
    translateYSlider->setGeometry((availableWidth - 100)/2, (availableHeight - 50)/2 - 200, 100, 50);

    connect(translateYSlider,&QSlider::valueChanged,this,&MainWindow::onTranslateYValueChanged);
}

以下是代码的详细解析,

设置窗口属性

  • ui->setupUi(this):设置用户界面。
  • setGeometry(QRect(-1, -1, QGuiApplication::primaryScreen()->size().width() + 2, QGuiApplication::primaryScreen()->size().height() + 2))
    • 设置窗口的几何形状,使其覆盖整个屏幕。
  • setAttribute(Qt::WA_TranslucentBackground)
    • 设置窗口背景为透明。
  • setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint)
    • 设置窗口无边框,并始终保持在最前端。

创建和设置OpenGL小部件

  • myopengl = new MyOpenGL(this)
    • 创建一个自定义的OpenGL小部件。
  • setCentralWidget(myopengl)
    • 将OpenGL小部件设置为主窗口的中心部件。

处理高DPI缩放

  • QScreen *screen = qApp->primaryScreen()
    • 获取主屏幕对象。
  • connect(screen, &QScreen::physicalDotsPerInchChanged, this, &MainWindow::onPhysicalDotsPerInchChanged)
    • 连接信号physicalDotsPerInchChanged到槽函数onPhysicalDotsPerInchChanged,当物理DPI变化时触发。

调试平移和缩放功能

  • 获取可用屏幕宽度和高度:
    • int availableWidth = QGuiApplication::primaryScreen()->availableGeometry().width()
    • int availableHeight = QGuiApplication::primaryScreen()->availableGeometry().height()

创建并配置缩放滑块

  • QSlider *scaleSlider = new QSlider(this)
    • 创建一个水平滑块用于缩放。
  • 设置滑块属性:
    • scaleSlider->setOrientation(Qt::Horizontal)
    • scaleSlider->setMaximum(200)
    • scaleSlider->setMinimum(-200)
    • scaleSlider->setSingleStep(10)
    • scaleSlider->setGeometry((availableWidth - 100)/2, (availableHeight - 50)/2, 100, 50)
  • 连接滑块值变化信号到槽函数:
    • connect(scaleSlider, &QSlider::valueChanged, this, &MainWindow::onScaleValueChanged)

创建并配置X轴平移滑块

  • QSlider *translateXSlider = new QSlider(this)
    • 创建一个水平滑块用于X轴平移。
  • 设置滑块属性:
    • translateXSlider->setOrientation(Qt::Horizontal)
    • translateXSlider->setMaximum(200)
    • translateXSlider->setMinimum(-200)
    • translateXSlider->setSingleStep(10)
    • translateXSlider->setGeometry((availableWidth - 100)/2, (availableHeight - 50)/2 - 100, 100, 50)
  • 连接滑块值变化信号到槽函数:
    • connect(translateXSlider, &QSlider::valueChanged, this, &MainWindow::onTranslateXValueChanged)

创建并配置Y轴平移滑块

  • QSlider *translateYSlider = new QSlider(this)
    • 创建一个水平滑块用于Y轴平移。
  • 设置滑块属性:
    • translateYSlider->setOrientation(Qt::Horizontal)
    • translateYSlider->setMaximum(200)
    • translateYSlider->setMinimum(-200)
    • translateYSlider->setSingleStep(10)
    • translateYSlider->setGeometry((availableWidth - 100)/2, (availableHeight - 50)/2 - 200, 100, 50)
  • 连接滑块值变化信号到槽函数:
    • connect(translateYSlider, &QSlider::valueChanged, this, &MainWindow::onTranslateYValueChanged)

void MainWindow::onPhysicalDotsPerInchChanged(qreal dpi)
{
    //resize(QGuiApplication::primaryScreen()->availableGeometry().size());
    resize(QGuiApplication::primaryScreen()->size().width() + 2, QGuiApplication::primaryScreen()->size().height() + 2);
}

void MainWindow::onScaleValueChanged(int value)
{
    // Scale [0,1]
    qDebug() << "Scale Value " << value * 0.01f;
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->Scale(value*0.01f,value*0.01f);

}

void MainWindow::onTranslateXValueChanged(int value)
{
    // TranslateX [-2,2]
    qDebug() << "TranslateX Value " << value * 0.01f;
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->TranslateX(value*0.01f);

}
void MainWindow::onTranslateYValueChanged(int value)
{
    // TranslateY [-2,2]
    qDebug() << "TranslateY Value " << value * 0.01f;
    LAppLive2DManager::GetInstance()->GetModel(0)->GetModelMatrix()->TranslateY(value*0.01f);
}

二、效果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/942192.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

我的JAVA-Web基础(2)

1.JDBC 防止sql注入 2.JSP JSP的基本语法 基本语法是 <% %> Java代码 <% %> 输出变量 可以转换成${变量}的EL表达式 <%! %>定义变量 JSP的基本语法包括以下几个主要部分&#xff1a; 1. 表达式&#xff08;Expression&#xff09; 表达式用于将…

VR 动感单车身心调适系统的功能与作用

如今&#xff0c;人们面临着来自各方的压力&#xff0c;国家重视国民身心健康&#xff0c;但人们在实际生活中却缺乏有效的身心调节方式。无论是久坐的白领&#xff0c;还是学业繁重的学生&#xff0c;都存在身体亚健康和心理压力大的问题。传统健身方式枯燥、心理咨询成本高且…

数据中台到底是什么?

数据中台不是一套系统&#xff0c;也不是一套产品&#xff0c;而是一种机制。在传统IT架构中&#xff0c;不同部门&#xff0c;不同业务系统和不同的数据中心会产生大量数据。这些数据如同烟囱一样是垂直划分的&#xff0c;彼此之间无法连接&#xff0c;我们也把这种数据叫做数…

AI Agent 与 AI Workflow 的区别和深度解析:从自动化到智能化的演进

一、引言 在人工智能技术快速迭代的今天&#xff0c;我们正见证着 AI 应用模式的多元化发展。 其中&#xff0c;AI Agent 和 AI Workflow 作为两种截然不同的范式&#xff0c;正在重塑我们对 AI 应用的认知。 这两种模式就像是同一枚硬币的两面 - 一个追求灵活创新&#xff…

【MySQL】7.0 入门学习(七)——MySQL基本指令:帮助、清除输入、查询等

1.0 help &#xff1f; 帮助指令&#xff0c;查询某个指令的解释、用法、说明等。详情参考博文&#xff1a; 【数据库】6.0 MySQL入门学习&#xff08;六&#xff09;——MySQL启动与停止、官方手册、文档查询 https://www.cnblogs.com/xiaofu007/p/10301005.html 2.0 在cmd命…

Refusal in Language Models Is Mediated by a Single Direction

开源代码&#xff1a;https://github.com/andyrdt/refusal_direction Abstract 会话型大语言模型针对指令遵循和安全性进行了微调&#xff0c;从而产生服从良性请求但拒绝有害请求的模型。虽然这种拒绝行为在聊天模型中普遍存在&#xff0c;但其背后的机制仍然知之甚少。在这…

Web3.0安全开发实践:探索比特币DeFi生态中的PSBT

近年来&#xff0c;部分签名比特币交易&#xff08;PSBT&#xff09;在比特币生态系统中获得了显著关注。随着如Ordinal和基于铭文的资产等创新的兴起&#xff0c;安全的多方签名和复杂交易的需求不断增加&#xff0c;这使得PSBT成为应对比特币生态不断发展中不可或缺的工具。 …

springboot483基于springboot的校园失物招领系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统校园失物招领系统信息管理难度大&#xff0c;容错率低&am…

VisionPro开发使用交互反馈系统(Affordance System)

XR Interaction Toolkit 提供了一个affordance system 可供性系统&#xff0c;使用户能够创建对交互状态的视觉和听觉反馈。一般的信息流从向Affordance State Provider场景中添加一个&#xff08;通常是可交互的&#xff09;并将其指向我们要监视其交互状态的可交互对象开始。…

Stable-diffusion-WebUI 的API调用(内含文生图和图生图实例)

前情提要 在之前尝试使用Diffusers库来进行stable-diffusion的接口调用以及各种插件功能实现&#xff0c;但发现diffusers库中各复杂功能的添加较为麻烦&#xff0c;而且难以实现对采样器的添加&#xff0c;safetensors格式模型的读取。在官网上找到了webui有专门的api接口&am…

重温设计模式--备忘录模式

文章目录 备忘录模式&#xff08;Memento Pattern&#xff09;概述定义&#xff1a; 作用&#xff1a;实现状态的保存与恢复支持撤销 / 恢复操作 备忘录模式UML图备忘录模式的结构原发器&#xff08;Originator&#xff09;&#xff1a;备忘录&#xff08;Memento&#xff09;&…

WPS工具栏灰色怎么办

WPS离线不登录&#xff0c;开启工具栏等相关功能 当你在使用WPS的过程中&#xff0c;若因网络问题或其他特殊原因&#xff0c;导致无法登录使用WPS时&#xff0c;可根据以下步骤开启离线兼容模式&#xff0c;开启此模式后&#xff0c;可在未登录的状态下&#xff0c;激活并使用…

【C++基础】09、结构体

一、结构体(struct) C/C 数组允许定义可存储相同类型数据项的变量&#xff0c;但是结构体是 C 中另一种用户自定义的可用的数据类型&#xff0c;它允许存储不同类型的数据项。 结构体用于表示一条记录&#xff0c;假设现在想要跟踪图书馆中书本的动态&#xff0c;可能需要跟踪每…

安卓蓝牙扫描流程

目录 系统广播 流程图 源码跟踪 系统广播 扫描开启广播&#xff1a;BluetoothAdapter.ACTION_DISCOVERY_STARTED "android.bluetooth.adapter.action.DISCOVERY_STARTED";扫描关闭广播&#xff1a;BluetoothAdapter.ACTION_DISCOVERY_FINISHED "android.b…

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集BIM介绍基本原理算法流程 BIM代码实现BIM算法实现攻击效果 代码汇总bim.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构建AlexNet对CIFAR10进行分类 Py…

如何查看pad的console输出,以便我们更好的进行调试,查看并了解实际可能的问题。

1、以下是baidu AI回复&#xff1a; 2、说明&#xff1a; 1&#xff09;如果小伙伴们经常做android开发的话&#xff0c;这个不陌生&#xff0c;因为调试都是要开启这个开发者模式。并启用USB调试模式。 2&#xff09;需要连上USB线&#xff0c;有的时候会忘记&#xff0c;然…

外贸企业需要部署SD-WAN专线吗?

随着外贸行业对互联网和数字化技术依赖的加深&#xff0c;网络质量已成为影响企业运营效率和竞争力的重要因素。本文将深入探讨SD-WAN专线如何助力外贸企业优化业务运营。 外贸企业面临的网络挑战 1. 跨国访问速度缓慢 在访问海外服务器或目标网站时&#xff0c;外贸企业常常遭…

MySQL什么情况下会导致索引失效

MySQL什么情况下会导致索引失效 索引&#xff08;Index&#xff09;是数据库中一种用于快速查找和访问表中数据的结构&#xff0c;它类似于书的目录&#xff0c;通过索引可以快速定位到目标数据&#xff0c;而无需遍历整个表&#xff0c;索引的存在可以显著提高查询速度&#x…

两分钟解决:vscode卡在设置SSH主机,VS Code-正在本地初始化VSCode服务器

问题原因 remote-ssh还是有一些bug的&#xff0c;在跟新之后可能会一直加载初始化SSH主机解决方案 1.打开终端2.登录链接vscode的账号&#xff0c;到家目录下3.找到 .vscode-server文件,删掉这个文件4.重启 vscode 就没问题了

uniapp登录

第一步整登录 先整个appid APPID和APPSecret https://developers.weixin.qq.com/community/develop/article/doc/000ca4601b8f70e379febac985b413 一个账号只能整一个小程序 正确流程 调用uni.login https://juejin.cn/post/7126553599445827621 https://www.jb51.net/a…