feat(render): 实现模型旋转中心点支持- 为 ModelPart 添加 pivot 属性,支持设置旋转中心点
- 更新局部变换矩阵计算,考虑 pivot 对旋转和平移的影响 - 在 Mesh2D 中增强着色器 uniform 设置,兼容 uModelMatrix 和 uModel- 添加 setPivot 和 getPivot 方法,支持动态调整旋转中心- 创建测试用例 ModelRenderTest2,验证不同 pivot 点的旋转效果 -修复纹理绑定逻辑,确保渲染时正确应用纹理 - 添加调试纹理生成功能,便于视觉验证 pivot 效果
This commit is contained in:
@@ -127,7 +127,6 @@ public final class ModelRender {
|
||||
FragColor = vec4(vDebugPos * 0.5 + 0.5, 0.0, 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 tex = texture(uTexture, vTexCoord);
|
||||
vec4 finalColor = tex * uColor;
|
||||
if (uBlendMode == 1) finalColor.rgb = tex.rgb + uColor.rgb;
|
||||
@@ -347,24 +346,27 @@ public final class ModelRender {
|
||||
}
|
||||
|
||||
private static void renderMesh(Mesh2D mesh, Matrix3f modelMatrix) {
|
||||
// 使用默认 shader(保证 shader 已被 use)
|
||||
if (!mesh.isVisible()) return;
|
||||
|
||||
// 使用默认 shader
|
||||
defaultProgram.use();
|
||||
|
||||
// 如果 mesh 已经被烘焙到世界坐标,则传 identity 矩阵给 shader(防止重复变换)
|
||||
Matrix3f matToUse = mesh.isBakedToWorld() ? new Matrix3f().identity() : modelMatrix;
|
||||
|
||||
// 确保 shader 中的矩阵 uniform 已更新(再次设置以防遗漏)
|
||||
setUniformMatrix3(defaultProgram, "uModelMatrix", matToUse);
|
||||
setUniformMatrix3(defaultProgram, "uModel", matToUse);
|
||||
|
||||
// 调用 Mesh2D 的 draw 重载(传 program id 与实际矩阵)
|
||||
try {
|
||||
mesh.draw(defaultProgram.programId, matToUse);
|
||||
} catch (AbstractMethodError | NoSuchMethodError e) {
|
||||
// 回退:仍然兼容旧的无参 draw(在这种情况下 shader 的 uModelMatrix 已经被设置)
|
||||
mesh.draw();
|
||||
// 设置纹理相关的uniform
|
||||
if (mesh.getTexture() != null) {
|
||||
mesh.getTexture().bind(0); // 绑定到纹理单元0
|
||||
setUniformIntInternal(defaultProgram, "uTexture", 0);
|
||||
} else {
|
||||
// 使用默认白色纹理
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, defaultTextureId);
|
||||
setUniformIntInternal(defaultProgram, "uTexture", 0);
|
||||
}
|
||||
|
||||
// 调用 Mesh2D 的 draw 方法,传入当前使用的着色器程序和变换矩阵
|
||||
mesh.draw(defaultProgram.programId, matToUse);
|
||||
|
||||
checkGLError("renderMesh");
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ public class ModelPart {
|
||||
private final Vector2f scale;
|
||||
private final Matrix3f localTransform;
|
||||
private final Matrix3f worldTransform;
|
||||
private final Vector2f pivot = new Vector2f(0, 0);
|
||||
|
||||
// ==================== 渲染属性 ====================
|
||||
private boolean visible;
|
||||
@@ -42,6 +43,7 @@ public class ModelPart {
|
||||
// ==================== 状态标记 ====================
|
||||
private boolean transformDirty;
|
||||
private boolean boundsDirty;
|
||||
private boolean pivotInitialized;
|
||||
|
||||
// ==================== 构造器 ====================
|
||||
|
||||
@@ -191,16 +193,22 @@ public class ModelPart {
|
||||
|
||||
// 更新局部矩阵
|
||||
private void updateLocalTransform() {
|
||||
float cos = (float)Math.cos(rotation);
|
||||
float sin = (float)Math.sin(rotation);
|
||||
float cos = (float) Math.cos(rotation);
|
||||
float sin = (float) Math.sin(rotation);
|
||||
|
||||
float m00 = cos * scale.x;
|
||||
float m01 = -sin * scale.y;
|
||||
float m10 = sin * scale.x;
|
||||
float m11 = cos * scale.y;
|
||||
float sx = scale.x;
|
||||
float sy = scale.y;
|
||||
|
||||
float m02 = position.x; // 平移直接用 position
|
||||
float m12 = position.y;
|
||||
// 旋转 + 缩放矩阵
|
||||
float m00 = cos * sx;
|
||||
float m01 = -sin * sy;
|
||||
float m10 = sin * sx;
|
||||
float m11 = cos * sy;
|
||||
|
||||
// 平移部分考虑 pivot
|
||||
// pivot 影响旋转中心,而 position 是最终放置位置
|
||||
float m02 = position.x - (m00 * pivot.x + m01 * pivot.y) + pivot.x;
|
||||
float m12 = position.y - (m10 * pivot.x + m11 * pivot.y) + pivot.y;
|
||||
|
||||
localTransform.set(
|
||||
m00, m01, m02,
|
||||
@@ -360,6 +368,44 @@ public class ModelPart {
|
||||
boundsDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置中心点
|
||||
*/
|
||||
public void setPivot(float x, float y) {
|
||||
if (!pivotInitialized) {
|
||||
// 确保第一次设置 pivot 的时候,必须是 (0,0) 因为这个为非0,0时后面如果想要热变换就会出问题
|
||||
if (x != 0 || y != 0) {
|
||||
System.out.println("The first time you set the pivot, it must be (0,0), which is automatically adjusted to (0,0).");
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
pivotInitialized = true;
|
||||
}
|
||||
float dx = x - pivot.x;
|
||||
float dy = y - pivot.y;
|
||||
|
||||
pivot.set(x, y);
|
||||
|
||||
for (Mesh2D mesh : meshes) {
|
||||
for (int i = 0; i < mesh.getVertexCount(); i++) {
|
||||
Vector2f v = mesh.getVertex(i);
|
||||
v.sub(dx, dy);
|
||||
mesh.setVertex(i, v.x, v.y);
|
||||
}
|
||||
}
|
||||
|
||||
markTransformDirty();
|
||||
updateLocalTransform();
|
||||
recomputeWorldTransformRecursive();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取旋转中心
|
||||
*/
|
||||
public Vector2f getPivot() {
|
||||
return new Vector2f(pivot);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除网格
|
||||
*/
|
||||
|
||||
@@ -475,18 +475,33 @@ public class Mesh2D {
|
||||
// 绑定 VAO
|
||||
GL30.glBindVertexArray(vaoId);
|
||||
|
||||
// 将 modelMatrix 上传到 shader 的 uniform "uModel"(如果 shader 有此 uniform)
|
||||
int loc = GL20.glGetUniformLocation(shaderProgram, "uModel");
|
||||
// 关键修改:使用传入的着色器程序
|
||||
GL20.glUseProgram(shaderProgram);
|
||||
|
||||
// 将 modelMatrix 上传到 shader 的 uniform "uModelMatrix"(与ModelRender中的命名一致)
|
||||
int loc = GL20.glGetUniformLocation(shaderProgram, "uModelMatrix");
|
||||
if (loc == -1) {
|
||||
// 如果找不到 uModelMatrix,尝试 uModel
|
||||
loc = GL20.glGetUniformLocation(shaderProgram, "uModel");
|
||||
}
|
||||
|
||||
if (loc != -1) {
|
||||
// 用一个 FloatBuffer 传递 3x3 矩阵
|
||||
java.nio.FloatBuffer fb = org.lwjgl.system.MemoryUtil.memAllocFloat(9);
|
||||
try {
|
||||
modelMatrix.get(fb); // JOML 将矩阵写入 buffer(列主序,适合 OpenGL)
|
||||
modelMatrix.get(fb);
|
||||
fb.flip();
|
||||
GL20.glUniformMatrix3fv(loc, false, fb);
|
||||
|
||||
// 调试信息
|
||||
//System.out.println("Mesh2D: 应用模型矩阵到着色器 - " + name);
|
||||
//System.out.printf(" [%.2f, %.2f, %.2f]\n", modelMatrix.m00(), modelMatrix.m01(), modelMatrix.m02());
|
||||
//System.out.printf(" [%.2f, %.2f, %.2f]\n", modelMatrix.m10(), modelMatrix.m11(), modelMatrix.m12());
|
||||
//System.out.printf(" [%.2f, %.2f, %.2f]\n", modelMatrix.m20(), modelMatrix.m21(), modelMatrix.m22());
|
||||
} finally {
|
||||
org.lwjgl.system.MemoryUtil.memFree(fb);
|
||||
}
|
||||
} else {
|
||||
System.err.println("警告: 着色器中未找到 uModelMatrix 或 uModel uniform");
|
||||
}
|
||||
|
||||
// 绘制
|
||||
|
||||
Reference in New Issue
Block a user