2025-10-12 08:01:25 +08:00
|
|
|
package com.chuangzhou.vivid2D.test;
|
|
|
|
|
|
|
|
|
|
import com.chuangzhou.vivid2D.render.ModelRender;
|
|
|
|
|
import com.chuangzhou.vivid2D.render.model.Model2D;
|
|
|
|
|
import com.chuangzhou.vivid2D.render.model.ModelPart;
|
|
|
|
|
import com.chuangzhou.vivid2D.render.model.util.Mesh2D;
|
|
|
|
|
import com.chuangzhou.vivid2D.render.model.util.Texture;
|
|
|
|
|
import org.lwjgl.glfw.GLFWVidMode;
|
|
|
|
|
import org.lwjgl.opengl.GL;
|
|
|
|
|
import org.lwjgl.system.MemoryUtil;
|
|
|
|
|
|
|
|
|
|
import static org.lwjgl.glfw.GLFW.*;
|
|
|
|
|
import static org.lwjgl.opengl.GL11.*;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Texture Render Test Class - Debug Version
|
2025-10-25 17:11:51 +08:00
|
|
|
*
|
2025-10-12 08:01:25 +08:00
|
|
|
* @author tzdwindows 7
|
|
|
|
|
*/
|
|
|
|
|
public class ModelRenderTextureTest {
|
|
|
|
|
|
|
|
|
|
private long window;
|
|
|
|
|
private Model2D model;
|
|
|
|
|
|
|
|
|
|
// Window dimensions
|
|
|
|
|
private static final int WINDOW_WIDTH = 800;
|
|
|
|
|
private static final int WINDOW_HEIGHT = 600;
|
|
|
|
|
|
|
|
|
|
// Debug flags
|
|
|
|
|
private int frameCount = 0;
|
|
|
|
|
private double lastFpsTime = 0;
|
|
|
|
|
private boolean enableWireframe = false;
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
new ModelRenderTextureTest().run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
|
try {
|
|
|
|
|
init();
|
|
|
|
|
loop();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
} finally {
|
|
|
|
|
cleanup();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void init() {
|
|
|
|
|
// Initialize GLFW
|
|
|
|
|
if (!glfwInit()) {
|
|
|
|
|
throw new IllegalStateException("Unable to initialize GLFW");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure GLFW
|
|
|
|
|
glfwDefaultWindowHints();
|
|
|
|
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
|
|
|
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
|
|
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
|
|
|
|
|
|
|
|
// Create window
|
|
|
|
|
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "ModelRender Texture Test - DEBUG", MemoryUtil.NULL, MemoryUtil.NULL);
|
|
|
|
|
if (window == MemoryUtil.NULL) {
|
|
|
|
|
throw new RuntimeException("Failed to create the GLFW window");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Center window
|
|
|
|
|
GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
|
|
|
|
glfwSetWindowPos(
|
|
|
|
|
window,
|
|
|
|
|
(vidMode.width() - WINDOW_WIDTH) / 2,
|
|
|
|
|
(vidMode.height() - WINDOW_HEIGHT) / 2
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Set callbacks
|
|
|
|
|
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
|
|
|
|
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
|
|
|
|
|
glfwSetWindowShouldClose(window, true);
|
|
|
|
|
}
|
|
|
|
|
if (key == GLFW_KEY_SPACE && action == GLFW_RELEASE) {
|
|
|
|
|
enableWireframe = !enableWireframe;
|
|
|
|
|
System.out.println("Wireframe mode: " + (enableWireframe ? "ON" : "OFF"));
|
|
|
|
|
}
|
|
|
|
|
if (key == GLFW_KEY_R && action == GLFW_RELEASE) {
|
|
|
|
|
recreateModel();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Create OpenGL context
|
|
|
|
|
glfwMakeContextCurrent(window);
|
|
|
|
|
GL.createCapabilities();
|
|
|
|
|
|
|
|
|
|
// Show window
|
|
|
|
|
glfwShowWindow(window);
|
|
|
|
|
|
|
|
|
|
// Initialize ModelRender
|
|
|
|
|
ModelRender.initialize();
|
|
|
|
|
|
|
|
|
|
// Create test model
|
|
|
|
|
createTestModel();
|
|
|
|
|
|
|
|
|
|
System.out.println("=== DEBUG INFO ===");
|
|
|
|
|
System.out.println("Press SPACE to toggle wireframe mode");
|
|
|
|
|
System.out.println("Press R to recreate model");
|
|
|
|
|
System.out.println("Press ESC to exit");
|
|
|
|
|
System.out.println("==================");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void createTestModel() {
|
|
|
|
|
if (model != null) {
|
|
|
|
|
// Clean up previous model if exists
|
|
|
|
|
System.out.println("Cleaning up previous model...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model = new Model2D("TextureTestModel");
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Load Trump image texture
|
|
|
|
|
String texturePath = "G:\\鬼畜素材\\川普\\图片\\7(DJ0MH9}`)GJYHHADQDHYN.png";
|
|
|
|
|
System.out.println("Loading texture: " + texturePath);
|
|
|
|
|
|
|
|
|
|
Texture texture = Texture.createFromFile("trump_texture", texturePath);
|
|
|
|
|
model.addTexture(texture);
|
|
|
|
|
|
|
|
|
|
System.out.println("Texture loaded: " + texture.getWidth() + "x" + texture.getHeight());
|
|
|
|
|
System.out.println("Texture ID: " + texture.getTextureId());
|
|
|
|
|
System.out.println("Texture format: " + texture.getFormat());
|
|
|
|
|
|
|
|
|
|
// 使用与工作示例相同的方式创建网格
|
|
|
|
|
// 根据纹理尺寸创建合适大小的四边形
|
|
|
|
|
float width = texture.getWidth() / 2.0f; // 缩小以适应屏幕
|
|
|
|
|
float height = texture.getHeight() / 2.0f;
|
|
|
|
|
|
|
|
|
|
// 使用 Mesh2D.createQuad 方法创建网格(如果可用)
|
|
|
|
|
Mesh2D mesh;
|
|
|
|
|
try {
|
|
|
|
|
// 尝试使用 createQuad 方法
|
|
|
|
|
mesh = Mesh2D.createQuad("trump_mesh", width, height);
|
|
|
|
|
System.out.println("Using Mesh2D.createQuad method");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 回退到手动创建顶点
|
|
|
|
|
System.out.println("Using manual vertex creation");
|
|
|
|
|
float[] vertices = {
|
2025-10-25 17:11:51 +08:00
|
|
|
-width / 2, -height / 2, // bottom left
|
|
|
|
|
width / 2, -height / 2, // bottom right
|
|
|
|
|
width / 2, height / 2, // top right
|
|
|
|
|
-width / 2, height / 2 // top left
|
2025-10-12 08:01:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
float[] uvs = {
|
|
|
|
|
0.0f, 1.0f, // bottom left
|
|
|
|
|
1.0f, 1.0f, // bottom right
|
|
|
|
|
1.0f, 0.0f, // top right
|
|
|
|
|
0.0f, 0.0f // top left
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int[] indices = {
|
|
|
|
|
0, 1, 2, // first triangle
|
|
|
|
|
2, 3, 0 // second triangle
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
mesh = model.createMesh("trump_mesh", vertices, uvs, indices);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mesh.setTexture(texture);
|
|
|
|
|
|
|
|
|
|
// Create part and add mesh
|
|
|
|
|
ModelPart part = model.createPart("trump_part");
|
|
|
|
|
|
|
|
|
|
part.addMesh(mesh);
|
|
|
|
|
part.setVisible(true);
|
|
|
|
|
|
|
|
|
|
// 设置部件位置到屏幕中心(使用像素坐标)
|
|
|
|
|
part.setPosition(0, 0); // 800x600 窗口的中心
|
|
|
|
|
|
|
|
|
|
System.out.println("Model created:");
|
|
|
|
|
System.out.println(" - Part count: " + model.getParts().size());
|
|
|
|
|
System.out.println(" - Mesh count: " + model.getMeshes().size());
|
|
|
|
|
System.out.println(" - Mesh dimensions: " + width + "x" + height);
|
|
|
|
|
System.out.println(" - Part position: " + part.getPosition());
|
|
|
|
|
System.out.println(" - Mesh vertex count: " + mesh.getVertexCount());
|
|
|
|
|
// 测试模型保存
|
|
|
|
|
model.saveToFile("C:\\Users\\Administrator\\Desktop\\trump_texture.model");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("Failed to create test model: " + e.getMessage());
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
createFallbackModel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void createFallbackModel() {
|
|
|
|
|
System.out.println("Creating fallback checkerboard model...");
|
|
|
|
|
|
|
|
|
|
// 使用与工作示例相同的模式
|
|
|
|
|
float width = 200;
|
|
|
|
|
float height = 200;
|
|
|
|
|
|
|
|
|
|
Mesh2D mesh;
|
|
|
|
|
try {
|
|
|
|
|
mesh = Mesh2D.createQuad("fallback_mesh", width, height);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 手动创建
|
|
|
|
|
float[] vertices = {
|
2025-10-25 17:11:51 +08:00
|
|
|
-width / 2, -height / 2,
|
|
|
|
|
width / 2, -height / 2,
|
|
|
|
|
width / 2, height / 2,
|
|
|
|
|
-width / 2, height / 2
|
2025-10-12 08:01:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
float[] uvs = {
|
|
|
|
|
0.0f, 1.0f,
|
|
|
|
|
1.0f, 1.0f,
|
|
|
|
|
1.0f, 0.0f,
|
|
|
|
|
0.0f, 0.0f
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int[] indices = {
|
|
|
|
|
0, 1, 2,
|
|
|
|
|
2, 3, 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
mesh = model.createMesh("fallback_mesh", vertices, uvs, indices);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create checkerboard texture
|
|
|
|
|
Texture fallbackTexture = Texture.createCheckerboard(
|
|
|
|
|
"fallback_texture",
|
|
|
|
|
512, 512, 32,
|
|
|
|
|
0xFFFF0000, // red
|
|
|
|
|
0xFF0000FF // blue
|
|
|
|
|
);
|
|
|
|
|
model.addTexture(fallbackTexture);
|
|
|
|
|
mesh.setTexture(fallbackTexture);
|
|
|
|
|
|
|
|
|
|
ModelPart part = model.createPart("fallback_part");
|
|
|
|
|
part.addMesh(mesh);
|
|
|
|
|
part.setVisible(true);
|
|
|
|
|
part.setPosition(400, 300);
|
|
|
|
|
|
|
|
|
|
System.out.println("Fallback model created with size: " + width + "x" + height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void recreateModel() {
|
|
|
|
|
System.out.println("Recreating model...");
|
|
|
|
|
createTestModel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void loop() {
|
|
|
|
|
// Set clear color (light gray for better visibility)
|
|
|
|
|
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
|
|
|
|
|
|
|
|
|
|
double lastTime = glfwGetTime();
|
|
|
|
|
|
|
|
|
|
while (!glfwWindowShouldClose(window)) {
|
|
|
|
|
double currentTime = glfwGetTime();
|
|
|
|
|
float deltaTime = (float) (currentTime - lastTime);
|
|
|
|
|
lastTime = currentTime;
|
|
|
|
|
|
|
|
|
|
// Calculate FPS
|
|
|
|
|
frameCount++;
|
|
|
|
|
if (currentTime - lastFpsTime >= 1.0) {
|
|
|
|
|
System.out.printf("FPS: %d, Delta: %.3fms\n", frameCount, deltaTime * 1000);
|
|
|
|
|
frameCount = 0;
|
|
|
|
|
lastFpsTime = currentTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Render
|
|
|
|
|
render(deltaTime);
|
|
|
|
|
|
|
|
|
|
// Swap buffers and poll events
|
|
|
|
|
glfwSwapBuffers(window);
|
|
|
|
|
glfwPollEvents();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void render(float deltaTime) {
|
|
|
|
|
// Clear screen
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
|
|
// Set wireframe mode if enabled
|
|
|
|
|
if (enableWireframe) {
|
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
|
|
|
} else {
|
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print debug info occasionally
|
|
|
|
|
if (frameCount % 120 == 0) {
|
|
|
|
|
System.out.println("=== RENDER DEBUG ===");
|
|
|
|
|
System.out.println("Model null: " + (model == null));
|
|
|
|
|
if (model != null) {
|
|
|
|
|
System.out.println("Parts: " + model.getParts().size());
|
|
|
|
|
System.out.println("Meshes: " + model.getMeshes().size());
|
|
|
|
|
if (!model.getParts().isEmpty()) {
|
|
|
|
|
ModelPart part = model.getParts().get(0);
|
|
|
|
|
System.out.println("First part visible: " + part.isVisible());
|
|
|
|
|
System.out.println("First part position: " + part.getPosition());
|
|
|
|
|
System.out.println("First part meshes: " + part.getMeshes().size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
System.out.println("===================");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Render using ModelRender
|
|
|
|
|
try {
|
|
|
|
|
ModelRender.render(deltaTime, model);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("Rendering error: " + e.getMessage());
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check OpenGL errors
|
|
|
|
|
int error = glGetError();
|
|
|
|
|
if (error != GL_NO_ERROR) {
|
|
|
|
|
System.err.println("OpenGL error: " + getGLErrorString(error));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getGLErrorString(int error) {
|
|
|
|
|
switch (error) {
|
2025-10-25 17:11:51 +08:00
|
|
|
case GL_INVALID_ENUM:
|
|
|
|
|
return "GL_INVALID_ENUM";
|
|
|
|
|
case GL_INVALID_VALUE:
|
|
|
|
|
return "GL_INVALID_VALUE";
|
|
|
|
|
case GL_INVALID_OPERATION:
|
|
|
|
|
return "GL_INVALID_OPERATION";
|
|
|
|
|
case GL_OUT_OF_MEMORY:
|
|
|
|
|
return "GL_OUT_OF_MEMORY";
|
|
|
|
|
default:
|
|
|
|
|
return "Unknown Error (0x" + Integer.toHexString(error) + ")";
|
2025-10-12 08:01:25 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void cleanup() {
|
|
|
|
|
System.out.println("Cleaning up resources...");
|
|
|
|
|
|
|
|
|
|
// Cleanup ModelRender
|
|
|
|
|
ModelRender.cleanup();
|
|
|
|
|
|
|
|
|
|
// Cleanup texture cache
|
|
|
|
|
Texture.cleanupAll();
|
|
|
|
|
|
|
|
|
|
// Destroy window and terminate GLFW
|
|
|
|
|
if (window != MemoryUtil.NULL) {
|
|
|
|
|
glfwDestroyWindow(window);
|
|
|
|
|
}
|
|
|
|
|
glfwTerminate();
|
|
|
|
|
|
|
|
|
|
System.out.println("Cleanup completed");
|
|
|
|
|
}
|
|
|
|
|
}
|