Files
window-axis-innovators-box/src/main/java/com/chuangzhou/vivid2D/test/ModelLayerPanelTest.java
tzdwindows 7 71aa2b8699 feat(render): 实现独立的 OpenGL 上下文管理器
- 将 GL 上下文管理从 ModelRenderPanel 抽离到独立的 GLContextManager 类- 实现离屏渲染上下文的创建、初始化和资源管理
- 支持动态调整渲染缓冲区大小和缩放功能
- 提供线程安全的任务队列机制用于在 GL 线程执行操作
- 实现像素数据读取和转换为 BufferedImage 的完整流程- 添加摄像机拖拽状态和缩放控制的支持
-重构 ModelRenderPanel以使用新的 GLContextManager- 更新所有 GL 相关操作的调用方式指向新的上下文管理器
- 修改 dispose 流程以正确释放所有 OpenGL 资源
- 优化渲染循环和平滑缩放逻辑实现
2025-10-26 10:57:54 +08:00

150 lines
6.6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.chuangzhou.vivid2D.test;
import com.chuangzhou.vivid2D.render.awt.ModelLayerPanel;
import com.chuangzhou.vivid2D.render.awt.ModelRenderPanel;
import com.chuangzhou.vivid2D.render.awt.TransformPanel;
import com.chuangzhou.vivid2D.render.model.Model2D;
import com.chuangzhou.vivid2D.render.model.ModelPart;
import javax.swing.*;
import java.awt.*;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* 简单的测试示例:创建一个 Model2D添加几层部件
* 然后在 JFrame 中展示 ModelLayerPanel左侧、ModelRenderPanel中间渲染区
* 和模型树(右侧)以便观察变化。
*/
public class ModelLayerPanelTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
System.setOut(new PrintStream(System.out, true, StandardCharsets.UTF_8));
System.setErr(new PrintStream(System.err, true, StandardCharsets.UTF_8));
// 创建示例模型并添加图层
Model2D model = new Model2D("示例模型");
// 调整一些初始属性(可选)
ModelPart person = model.getPart("人物");
if (person != null) {
try {
person.setOpacity(0.85f);
} catch (Exception ignored) {
}
}
// 创建 UI
JFrame frame = new JFrame("ModelLayerPanel 测试(含渲染面板和变换面板)");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(new BorderLayout());
// 左侧:图层面板(传入 renderPanel 后可在面板中绑定贴图到 GL 上下文)
// 先创建一个占位 renderPanel再把它传给 layerPanelModelRenderPanel 构造需要尺寸)
ModelRenderPanel renderPanel = new ModelRenderPanel(model, 640, 480);
ModelLayerPanel layerPanel = new ModelLayerPanel(model, renderPanel);
layerPanel.setPreferredSize(new Dimension(260, 600));
frame.add(layerPanel, BorderLayout.WEST);
// 中间:渲染面板
renderPanel.setPreferredSize(new Dimension(640, 480));
frame.add(renderPanel, BorderLayout.CENTER);
// 创建变换面板
TransformPanel transformPanel = new TransformPanel(renderPanel);
// 右侧:创建选项卡面板,包含模型树和变换面板
JTabbedPane rightTabbedPane = new JTabbedPane();
// 模型树选项卡
JTree tree = new JTree(model.toTreeNode());
JScrollPane treeScroll = new JScrollPane(tree);
treeScroll.setPreferredSize(new Dimension(280, 600));
rightTabbedPane.addTab("模型结构", treeScroll);
// 变换面板选项卡
JScrollPane transformScroll = new JScrollPane(transformPanel);
transformScroll.setPreferredSize(new Dimension(280, 600));
rightTabbedPane.addTab("变换控制", transformScroll);
rightTabbedPane.setPreferredSize(new Dimension(300, 600));
frame.add(rightTabbedPane, BorderLayout.EAST);
// 底部:演示按钮(刷新树以反映面板中对模型的更改)
JPanel bottom = new JPanel(new FlowLayout(FlowLayout.LEFT));
JButton refreshBtn = new JButton("刷新模型树");
refreshBtn.addActionListener(e -> {
tree.setModel(new javax.swing.tree.DefaultTreeModel(model.toTreeNode()));
for (int i = 0; i < tree.getRowCount(); i++) tree.expandRow(i);
// 同步通知渲染面板(如果需要)去刷新模型
try {
renderPanel.setModel(model);
} catch (Exception ignored) {
}
});
bottom.add(refreshBtn);
JButton printOrderBtn = new JButton("打印部件顺序(控制台)");
printOrderBtn.addActionListener(e -> {
System.out.println("当前模型部件顺序:");
for (ModelPart p : model.getParts()) {
System.out.println(" - " + p.getName() + " (可见=" + p.isVisible() + ", 不透明度=" + p.getOpacity() + ")");
}
});
bottom.add(printOrderBtn);
// 添加选中部件更新按钮
JButton updateSelectionBtn = new JButton("更新选中部件");
updateSelectionBtn.addActionListener(e -> {
renderPanel.getGlContextManager().executeInGLContext(() -> {
List<ModelPart> selectedPart = renderPanel.getSelectedParts();
transformPanel.setSelectedParts(selectedPart);
});
});
bottom.add(updateSelectionBtn);
frame.add(bottom, BorderLayout.SOUTH);
// 添加模型点击监听器,自动更新变换面板的选中部件
renderPanel.addModelClickListener((mesh, modelX, modelY, screenX, screenY) -> {
if (mesh == null) return;
System.out.println("点击了模型:" + mesh.getName() + ",模型坐标:" + modelX + ", " + modelY + ",屏幕坐标:" + screenX + ", " + screenY);
// 自动更新变换面板的选中部件
List<ModelPart> selectedPart = renderPanel.getSelectedParts();
transformPanel.setSelectedParts(selectedPart);
// 切换到变换控制选项卡
rightTabbedPane.setSelectedIndex(1);
});
// 监听窗口关闭,确保释放 GL 资源
frame.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
// 先释放渲染面板相关 GL 资源与线程
//try {
// renderPanel.dispose();
//} catch (Throwable t) {
// t.printStackTrace();
//}
}
@Override
public void windowClosed(java.awt.event.WindowEvent e) {
// 进程退出(确保彻底关闭)
try {
renderPanel.getGlContextManager().dispose();
} catch (Throwable ignored) {
}
model.saveToFile("C:\\Users\\Administrator\\Desktop\\testing.model");
System.exit(0);
}
});
frame.setSize(1300, 700);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}