From 1b98c6994832c6eb074e15637b53076282ac409f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 10 Jan 2025 17:30:00 +0200 Subject: [PATCH] generate skin preview Signed-off-by: Trial97 --- launcher/minecraft/skins/SkinList.cpp | 9 +- launcher/minecraft/skins/SkinModel.cpp | 106 +++++++++++++++++- launcher/minecraft/skins/SkinModel.h | 3 + .../dialogs/skins/draw/SkinOpenGLWidget.cpp | 1 + 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/launcher/minecraft/skins/SkinList.cpp b/launcher/minecraft/skins/SkinList.cpp index 2294daefc..124b69c85 100644 --- a/launcher/minecraft/skins/SkinList.cpp +++ b/launcher/minecraft/skins/SkinList.cpp @@ -239,8 +239,13 @@ QVariant SkinList::data(const QModelIndex& index, int role) const return QVariant(); auto skin = m_skinList[row]; switch (role) { - case Qt::DecorationRole: - return skin.getTexture(); + case Qt::DecorationRole: { + auto preview = skin.getPreview(); + if (preview.isNull()) { + preview = skin.getTexture(); + } + return preview; + } case Qt::DisplayRole: return skin.name(); case Qt::UserRole: diff --git a/launcher/minecraft/skins/SkinModel.cpp b/launcher/minecraft/skins/SkinModel.cpp index 63e497585..5912f7572 100644 --- a/launcher/minecraft/skins/SkinModel.cpp +++ b/launcher/minecraft/skins/SkinModel.cpp @@ -18,10 +18,13 @@ #include "SkinModel.h" #include +#include +#include #include #include "FileSystem.h" #include "Json.h" +#include "ui/dialogs/skins/draw/Scene.h" QImage improveSkin(const QImage& skin) { @@ -45,7 +48,106 @@ QImage getSkin(const QString path) return improveSkin(QImage(path)); } -SkinModel::SkinModel(QString path) : m_path(path), m_texture(getSkin(path)), m_model(Model::CLASSIC) {} +QImage generatePreviews(QImage texture, bool slim) +{ + QImage preview; + + // Set up OpenGL context and offscreen surface + QOpenGLContext context; + context.setFormat(QSurfaceFormat::defaultFormat()); + if (!context.create()) { + qWarning() << "Failed to create OpenGL context"; + return preview; + } + + QOffscreenSurface surface; + surface.setFormat(context.format()); + surface.create(); + + // Make the OpenGL context current + context.makeCurrent(&surface); + + QOpenGLFunctions* gl = context.functions(); + QOpenGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + + QOpenGLShaderProgram program; + // Compile vertex shader + if (!program.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl")) { + qWarning() << "Failed to create vertex"; + return preview; + } + // Compile fragment shader + if (!program.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl")) { + qWarning() << "Failed to create fragment"; + return preview; + } + // Link shader pipeline + if (!program.link()) { + qWarning() << "Failed to create link"; + return preview; + } + // Bind shader pipeline for use + if (!program.bind()) { + qWarning() << "Failed to create bind"; + return preview; + } + auto scene = new opengl::Scene(texture, slim, {}); + + const qreal zNear = .1, zFar = 1000., fov = 45, aspect = 1; + + // Reset projection + QMatrix4x4 m_projection; + m_projection.setToIdentity(); + + // Set perspective projection + m_projection.perspective(fov, aspect, zNear, zFar); + + // Calculate model view transformation + QMatrix4x4 matrix; + matrix.translate(0.0, 6.0, -50.); + + // Create a framebuffer object for rendering + QOpenGLFramebufferObject fbo(64, 64, fboFormat); + fbo.bind(); + + // Clear the framebuffer + gl->glViewport(0, 0, 64, 64); + gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + // Clear color and depth buffer + gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Enable depth buffer + gl->glEnable(GL_DEPTH_TEST); + gl->glDepthFunc(GL_LESS); + + // Enable back face culling + gl->glEnable(GL_CULL_FACE); + + gl->glEnable(GL_BLEND); + gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Set modelview-projection matrix + program.setUniformValue("mvp_matrix", m_projection * matrix); + + // scene->setMode(skin->getModel() == SkinModel::SLIM); + // scene->setSkin(skin->getTexture()); + + scene->draw(&program); + + // Read the framebuffer into a QImage + preview = fbo.toImage(); + + fbo.release(); + delete scene; + context.doneCurrent(); + return preview; +} + +SkinModel::SkinModel(QString path) : m_path(path), m_texture(getSkin(path)), m_model(Model::CLASSIC) +{ + m_preview = generatePreviews(m_texture, false); +} SkinModel::SkinModel(QDir skinDir, QJsonObject obj) : m_capeId(Json::ensureString(obj, "capeId")), m_model(Model::CLASSIC), m_url(Json::ensureString(obj, "url")) @@ -57,6 +159,7 @@ SkinModel::SkinModel(QDir skinDir, QJsonObject obj) } m_path = skinDir.absoluteFilePath(name) + ".png"; m_texture = QImage(getSkin(m_path)); + m_preview = generatePreviews(m_texture, m_model == Model::SLIM); } QString SkinModel::name() const @@ -99,4 +202,5 @@ bool SkinModel::isValid() const void SkinModel::refresh() { m_texture = getSkin(m_path); + m_preview = generatePreviews(m_texture, m_model == Model::SLIM); } diff --git a/launcher/minecraft/skins/SkinModel.h b/launcher/minecraft/skins/SkinModel.h index 9b2dada45..028df01f8 100644 --- a/launcher/minecraft/skins/SkinModel.h +++ b/launcher/minecraft/skins/SkinModel.h @@ -36,6 +36,7 @@ class SkinModel { bool isValid() const; QString getPath() const { return m_path; } QImage getTexture() const { return m_texture; } + QImage getPreview() const { return m_preview; } QString getCapeId() const { return m_capeId; } Model getModel() const { return m_model; } QString getURL() const { return m_url; } @@ -44,6 +45,7 @@ class SkinModel { void setCapeId(QString capeID) { m_capeId = capeID; } void setModel(Model model) { m_model = model; } void setURL(QString url) { m_url = url; } + void setPreview(const QImage& preview) { m_preview = preview; } void refresh(); QJsonObject toJSON() const; @@ -51,6 +53,7 @@ class SkinModel { private: QString m_path; QImage m_texture; + QImage m_preview; QString m_capeId; Model m_model; QString m_url; diff --git a/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.cpp b/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.cpp index a4c6c4f2d..ace085e31 100644 --- a/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.cpp +++ b/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.cpp @@ -22,6 +22,7 @@ #include #include #include + #include "minecraft/skins/SkinModel.h" #include "ui/dialogs/skins/SkinManageDialog.h" #include "ui/dialogs/skins/draw/BoxGeometry.h"