refactor(animation):优化动画系统字段不可变性与getter方法格式- 将AnimationClip中的creationTime字段设为final
- 将AnimationLayer中的parameterOverrides字段设为final - 将AnimationParameter中的id、defaultValue、minValue、maxValue字段设为final - 将LightSource中的position、color、intensity字段设为final - 统一所有getter方法的代码格式,增加换行与大括号 - 优化Mesh2D中部分条件判断逻辑与字段final声明- 调整部分JavaDoc注释格式与空行位置提升可读性
This commit is contained in:
@@ -6,7 +6,10 @@ import com.chuangzhou.vivid2D.render.systems.buffer.Tesselator;
|
||||
import com.chuangzhou.vivid2D.render.systems.sources.ShaderManagement;
|
||||
import com.chuangzhou.vivid2D.render.systems.sources.ShaderProgram;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.*;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
import org.lwjgl.stb.STBTTAlignedQuad;
|
||||
import org.lwjgl.stb.STBTTBakedChar;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
@@ -15,10 +18,12 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.lwjgl.stb.STBTruetype.*;
|
||||
import static org.lwjgl.stb.STBTruetype.stbtt_BakeFontBitmap;
|
||||
import static org.lwjgl.stb.STBTruetype.stbtt_GetBakedQuad;
|
||||
|
||||
/**
|
||||
* 支持 ASCII + 中文的 OpenGL 文本渲染器
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public final class TextRenderer {
|
||||
@@ -153,7 +158,7 @@ public final class TextRenderer {
|
||||
width += bakedChar.xadvance() * scale;
|
||||
} else {
|
||||
// 对于未找到的字符,使用空格宽度
|
||||
width += 0.5f * scale; // 估计值
|
||||
width += 0.5f * scale; // 估计值
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,7 +322,15 @@ public final class TextRenderer {
|
||||
logger.debug("TextRenderer cleaned up");
|
||||
}
|
||||
|
||||
public boolean isInitialized() { return initialized; }
|
||||
public int getAsciiTextureId() { return asciiTextureId; }
|
||||
public int getChineseTextureId() { return chineseTextureId; }
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
public int getAsciiTextureId() {
|
||||
return asciiTextureId;
|
||||
}
|
||||
|
||||
public int getChineseTextureId() {
|
||||
return chineseTextureId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,10 @@ public class PsdParser {
|
||||
}
|
||||
|
||||
} finally {
|
||||
try { reader.dispose(); } catch (Exception ignored) {}
|
||||
try {
|
||||
reader.dispose();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -2,8 +2,9 @@ package com.chuangzhou.vivid2D.render.model;
|
||||
|
||||
/**
|
||||
* 模型事件
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public interface ModelEvent {
|
||||
void trigger(String eventName,Object eventBus);
|
||||
void trigger(String eventName, Object eventBus);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* LightSource 的序列化数据类(扩展:包含辉光/Glow 的序列化字段)
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class LightSourceData implements Serializable {
|
||||
|
||||
@@ -80,8 +80,7 @@ public class PartData implements Serializable {
|
||||
// 期望的方法签名: public List<YourStrokeClass> getLiquifyStrokes()
|
||||
java.lang.reflect.Method m = part.getClass().getMethod("getLiquifyStrokes");
|
||||
Object strokesObj = m.invoke(part);
|
||||
if (strokesObj instanceof List<?>) {
|
||||
List<?> strokes = (List<?>) strokesObj;
|
||||
if (strokesObj instanceof List<?> strokes) {
|
||||
for (Object s : strokes) {
|
||||
// 支持两种情况:存储为自定义类型(有 getMode/getRadius/getStrength/getIterations/getPoints 方法)
|
||||
// 或者直接存储为通用 Map/POJO。我们做宽松处理:通过反射尽可能读取常见字段。
|
||||
@@ -91,37 +90,39 @@ public class PartData implements Serializable {
|
||||
java.lang.reflect.Method gm = s.getClass().getMethod("getMode");
|
||||
Object modeObj = gm.invoke(s);
|
||||
if (modeObj != null) strokeData.mode = modeObj.toString();
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
java.lang.reflect.Method gr = s.getClass().getMethod("getRadius");
|
||||
Object r = gr.invoke(s);
|
||||
if (r instanceof Number) strokeData.radius = ((Number) r).floatValue();
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
java.lang.reflect.Method gs = s.getClass().getMethod("getStrength");
|
||||
Object st = gs.invoke(s);
|
||||
if (st instanceof Number) strokeData.strength = ((Number) st).floatValue();
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
java.lang.reflect.Method gi = s.getClass().getMethod("getIterations");
|
||||
Object it = gi.invoke(s);
|
||||
if (it instanceof Number) strokeData.iterations = ((Number) it).intValue();
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
|
||||
// 读取点列表
|
||||
try {
|
||||
java.lang.reflect.Method gp = s.getClass().getMethod("getPoints");
|
||||
Object ptsObj = gp.invoke(s);
|
||||
if (ptsObj instanceof List<?>) {
|
||||
List<?> pts = (List<?>) ptsObj;
|
||||
if (ptsObj instanceof List<?> pts) {
|
||||
for (Object p : pts) {
|
||||
// 支持 Vector2f 或自定义点类型(有 getX/getY/getPressure)
|
||||
LiquifyPointData pd = new LiquifyPointData();
|
||||
if (p instanceof org.joml.Vector2f) {
|
||||
org.joml.Vector2f v = (org.joml.Vector2f) p;
|
||||
if (p instanceof Vector2f v) {
|
||||
pd.x = v.x;
|
||||
pd.y = v.y;
|
||||
pd.pressure = 1.0f;
|
||||
@@ -144,8 +145,7 @@ public class PartData implements Serializable {
|
||||
}
|
||||
} catch (NoSuchMethodException ex) {
|
||||
// 最后尝试 Map 形式(键 x,y)
|
||||
if (p instanceof Map<?, ?>) {
|
||||
Map<?, ?> mapP = (Map<?, ?>) p;
|
||||
if (p instanceof Map<?, ?> mapP) {
|
||||
Object ox = mapP.get("x");
|
||||
Object oy = mapP.get("y");
|
||||
if (ox instanceof Number && oy instanceof Number) {
|
||||
@@ -160,7 +160,8 @@ public class PartData implements Serializable {
|
||||
strokeData.points.add(pd);
|
||||
}
|
||||
}
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
|
||||
// 如果没有 mode,则用默认 PUSH
|
||||
if (strokeData.mode == null) strokeData.mode = ModelPart.LiquifyMode.PUSH.name();
|
||||
@@ -236,7 +237,8 @@ public class PartData implements Serializable {
|
||||
ModelPart.LiquifyMode modeEnum = ModelPart.LiquifyMode.PUSH;
|
||||
try {
|
||||
modeEnum = ModelPart.LiquifyMode.valueOf(stroke.mode);
|
||||
} catch (Exception ignored) {}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
// 对每个点进行重放:调用 applyLiquify(存在于 ModelPart)
|
||||
if (stroke.points != null) {
|
||||
|
||||
@@ -115,10 +115,10 @@ public class TextureData implements Serializable {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int index = (y * width + x) * components;
|
||||
if (components >= 1) data[index] = (byte)((x * 255) / width); // R
|
||||
if (components >= 2) data[index + 1] = (byte)((y * 255) / height); // G
|
||||
if (components >= 3) data[index + 2] = (byte)128; // B
|
||||
if (components >= 4) data[index + 3] = (byte)255; // A
|
||||
if (components >= 1) data[index] = (byte) ((x * 255) / width); // R
|
||||
if (components >= 2) data[index + 1] = (byte) ((y * 255) / height); // G
|
||||
if (components >= 3) data[index + 2] = (byte) 128; // B
|
||||
if (components >= 4) data[index + 3] = (byte) 255; // A
|
||||
}
|
||||
}
|
||||
return data;
|
||||
|
||||
@@ -5,11 +5,11 @@ import com.chuangzhou.vivid2D.render.model.util.Mesh2D;
|
||||
import com.chuangzhou.vivid2D.render.model.util.SaveVector2f;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 缩放变形器 - 围绕中心点缩放顶点
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class ScaleDeformer extends Deformer {
|
||||
@@ -94,11 +94,23 @@ public class ScaleDeformer extends Deformer {
|
||||
}
|
||||
|
||||
// Getter/Setter
|
||||
public Vector2f getBaseScale() { return new Vector2f(baseScale); }
|
||||
public void setBaseScale(Vector2f baseScale) { this.baseScale.set(baseScale); }
|
||||
public Vector2f getBaseScale() {
|
||||
return new Vector2f(baseScale);
|
||||
}
|
||||
|
||||
public Vector2f getScaleRange() { return new Vector2f(scaleRange); }
|
||||
public void setScaleRange(Vector2f scaleRange) { this.scaleRange.set(scaleRange); }
|
||||
public void setBaseScale(Vector2f baseScale) {
|
||||
this.baseScale.set(baseScale);
|
||||
}
|
||||
|
||||
public Vector2f getCurrentScale() { return new Vector2f(currentScale); }
|
||||
public Vector2f getScaleRange() {
|
||||
return new Vector2f(scaleRange);
|
||||
}
|
||||
|
||||
public void setScaleRange(Vector2f scaleRange) {
|
||||
this.scaleRange.set(scaleRange);
|
||||
}
|
||||
|
||||
public Vector2f getCurrentScale() {
|
||||
return new Vector2f(currentScale);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class AnimationClip {
|
||||
// ==================== 元数据 ====================
|
||||
private String author;
|
||||
private String description;
|
||||
private long creationTime;
|
||||
private final long creationTime;
|
||||
private long lastModifiedTime;
|
||||
private Map<String, String> userData;
|
||||
|
||||
@@ -554,9 +554,17 @@ public class AnimationClip {
|
||||
}
|
||||
|
||||
// Getter方法
|
||||
public String getParameterId() { return parameterId; }
|
||||
public List<Keyframe> getKeyframes() { return Collections.unmodifiableList(keyframes); }
|
||||
public float getDefaultValue() { return defaultValue; }
|
||||
public String getParameterId() {
|
||||
return parameterId;
|
||||
}
|
||||
|
||||
public List<Keyframe> getKeyframes() {
|
||||
return Collections.unmodifiableList(keyframes);
|
||||
}
|
||||
|
||||
public float getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -578,9 +586,17 @@ public class AnimationClip {
|
||||
}
|
||||
|
||||
// Getter方法
|
||||
public float getTime() { return time; }
|
||||
public float getValue() { return value; }
|
||||
public InterpolationType getInterpolation() { return interpolation; }
|
||||
public float getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public InterpolationType getInterpolation() {
|
||||
return interpolation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -621,10 +637,21 @@ public class AnimationClip {
|
||||
}
|
||||
|
||||
// Getter方法
|
||||
public String getName() { return name; }
|
||||
public float getTime() { return time; }
|
||||
public Runnable getAction() { return action; }
|
||||
public boolean isTriggered() { return triggered; }
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public float getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public Runnable getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public boolean isTriggered() {
|
||||
return triggered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -646,23 +673,39 @@ public class AnimationClip {
|
||||
|
||||
// ==================== Getter/Setter ====================
|
||||
|
||||
public String getName() { return name; }
|
||||
public UUID getUuid() { return uuid; }
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public float getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public float getDuration() { return duration; }
|
||||
public void setDuration(float duration) {
|
||||
this.duration = Math.max(0.0f, duration);
|
||||
markModified();
|
||||
}
|
||||
|
||||
public float getFramesPerSecond() { return framesPerSecond; }
|
||||
public float getFramesPerSecond() {
|
||||
return framesPerSecond;
|
||||
}
|
||||
|
||||
public void setFramesPerSecond(float framesPerSecond) {
|
||||
this.framesPerSecond = Math.max(1.0f, framesPerSecond);
|
||||
markModified();
|
||||
}
|
||||
|
||||
public boolean isLooping() { return looping; }
|
||||
public void setLooping(boolean looping) { this.looping = looping; }
|
||||
public boolean isLooping() {
|
||||
return looping;
|
||||
}
|
||||
|
||||
public void setLooping(boolean looping) {
|
||||
this.looping = looping;
|
||||
}
|
||||
|
||||
public Map<String, AnimationCurve> getCurves() {
|
||||
return Collections.unmodifiableMap(curves);
|
||||
@@ -676,18 +719,34 @@ public class AnimationClip {
|
||||
return Collections.unmodifiableMap(defaultValues);
|
||||
}
|
||||
|
||||
public String getAuthor() { return author; }
|
||||
public void setAuthor(String author) { this.author = author; }
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public long getCreationTime() { return creationTime; }
|
||||
public long getLastModifiedTime() { return lastModifiedTime; }
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public long getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public long getLastModifiedTime() {
|
||||
return lastModifiedTime;
|
||||
}
|
||||
|
||||
public Map<String, String> getUserData() {
|
||||
return Collections.unmodifiableMap(userData);
|
||||
}
|
||||
|
||||
public void setUserData(Map<String, String> userData) {
|
||||
this.userData = new ConcurrentHashMap<>(userData);
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ public class BoundingBox {
|
||||
return new Vector2f[0];
|
||||
}
|
||||
|
||||
return new Vector2f[] {
|
||||
return new Vector2f[]{
|
||||
new Vector2f(minX, minY), // 左下
|
||||
new Vector2f(maxX, minY), // 右下
|
||||
new Vector2f(maxX, maxY), // 右上
|
||||
@@ -516,10 +516,21 @@ public class BoundingBox {
|
||||
|
||||
// ==================== Getter方法 ====================
|
||||
|
||||
public float getMinX() { return minX; }
|
||||
public float getMinY() { return minY; }
|
||||
public float getMaxX() { return maxX; }
|
||||
public float getMaxY() { return maxY; }
|
||||
public float getMinX() {
|
||||
return minX;
|
||||
}
|
||||
|
||||
public float getMinY() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
public float getMaxX() {
|
||||
return maxX;
|
||||
}
|
||||
|
||||
public float getMaxY() {
|
||||
return maxY;
|
||||
}
|
||||
|
||||
public float getWidth() {
|
||||
return valid ? maxX - minX : 0.0f;
|
||||
@@ -529,12 +540,25 @@ public class BoundingBox {
|
||||
return valid ? maxY - minY : 0.0f;
|
||||
}
|
||||
|
||||
public float getLeft() { return minX; }
|
||||
public float getRight() { return maxX; }
|
||||
public float getBottom() { return minY; }
|
||||
public float getTop() { return maxY; }
|
||||
public float getLeft() {
|
||||
return minX;
|
||||
}
|
||||
|
||||
public boolean isValid() { return valid; }
|
||||
public float getRight() {
|
||||
return maxX;
|
||||
}
|
||||
|
||||
public float getBottom() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
public float getTop() {
|
||||
return maxY;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
// ==================== 静态工厂方法 ====================
|
||||
|
||||
|
||||
@@ -11,6 +11,14 @@ import com.chuangzhou.vivid2D.render.systems.sources.ShaderManagement;
|
||||
import com.chuangzhou.vivid2D.render.systems.sources.ShaderProgram;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
@@ -19,12 +27,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.*;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 2D网格类,用于存储和管理2D模型的几何数据
|
||||
* 支持顶点、UV坐标、索引和变形操作
|
||||
@@ -42,7 +44,7 @@ public class Mesh2D {
|
||||
private ModelPart modelPart;
|
||||
|
||||
// ==================== 二级顶点支持 ====================
|
||||
private List<SecondaryVertex> secondaryVertices = new ArrayList<>();
|
||||
private final List<SecondaryVertex> secondaryVertices = new ArrayList<>();
|
||||
private boolean showSecondaryVertices = false;
|
||||
public Vector4f secondaryVertexColor = new Vector4f(0.0f, 1.0f, 0.0f, 1.0f); // 绿色二级顶点
|
||||
public Vector4f selectedSecondaryVertexColor = new Vector4f(1.0f, 0.0f, 0.0f, 1.0f); // 红色选中的二级顶点
|
||||
@@ -77,14 +79,14 @@ public class Mesh2D {
|
||||
|
||||
// ==================== 液化状态渲染 ====================
|
||||
public boolean showLiquifyOverlay = false;
|
||||
private Vector4f liquifyOverlayColor = new Vector4f(1.0f, 0.5f, 0.0f, 0.3f); // 半透明橙色
|
||||
private final Vector4f liquifyOverlayColor = new Vector4f(1.0f, 0.5f, 0.0f, 0.3f); // 半透明橙色
|
||||
|
||||
// ==================== 木偶工具 ====================
|
||||
private List<PuppetPin> puppetPins = new ArrayList<>();
|
||||
private final List<PuppetPin> puppetPins = new ArrayList<>();
|
||||
private PuppetPin selectedPuppetPin = null;
|
||||
private boolean showPuppetPins = true;
|
||||
private Vector4f puppetPinColor = new Vector4f(1.0f, 0.0f, 0.0f, 1.0f); // 红色控制点
|
||||
private Vector4f selectedPuppetPinColor = new Vector4f(1.0f, 1.0f, 0.0f, 1.0f); // 黄色选中的控制点
|
||||
private final Vector4f puppetPinColor = new Vector4f(1.0f, 0.0f, 0.0f, 1.0f); // 红色控制点
|
||||
private final Vector4f selectedPuppetPinColor = new Vector4f(1.0f, 1.0f, 0.0f, 1.0f); // 黄色选中的控制点
|
||||
private float puppetPinSize = 8.0f;
|
||||
|
||||
// ==================== 常量 ====================
|
||||
@@ -377,6 +379,7 @@ public class Mesh2D {
|
||||
public boolean getShowPuppetPins() {
|
||||
return showPuppetPins;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制木偶控制点
|
||||
*/
|
||||
@@ -516,7 +519,7 @@ public class Mesh2D {
|
||||
* 绘制控制点信息
|
||||
*/
|
||||
private void drawPuppetPinInfo(BufferBuilder bb, PuppetPin pin, float x, float y) {
|
||||
String infoText = pin.getName() + " (R:" + (int)pin.getInfluenceRadius() + ")";
|
||||
String infoText = pin.getName() + " (R:" + (int) pin.getInfluenceRadius() + ")";
|
||||
TextRenderer textRenderer = ModelRender.getTextRenderer();
|
||||
if (textRenderer != null) {
|
||||
float textWidth = textRenderer.getTextWidth(infoText);
|
||||
@@ -986,8 +989,8 @@ public class Mesh2D {
|
||||
float[] vertices = {
|
||||
-hw, -hh, // 左下
|
||||
hw, -hh, // 右下
|
||||
hw, hh, // 右上
|
||||
-hw, hh // 左上
|
||||
hw, hh, // 右上
|
||||
-hw, hh // 左上
|
||||
};
|
||||
|
||||
float[] uvs = {
|
||||
@@ -2296,11 +2299,7 @@ public class Mesh2D {
|
||||
}
|
||||
|
||||
float squaredLength = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
||||
if (dot > squaredLength) {
|
||||
return false; // 在线段终点之后
|
||||
}
|
||||
|
||||
return true;
|
||||
return !(dot > squaredLength); // 在线段终点之后
|
||||
}
|
||||
|
||||
public boolean containsPoint(Vector2f point) {
|
||||
@@ -2385,6 +2384,7 @@ public class Mesh2D {
|
||||
}
|
||||
|
||||
// ==================== 状态管理 ====================
|
||||
|
||||
/**
|
||||
* 标记数据已修改
|
||||
*/
|
||||
@@ -2614,8 +2614,7 @@ public class Mesh2D {
|
||||
|
||||
// 恢复之前的 program(如果我们切换过)
|
||||
if (switchedProgram) {
|
||||
if (prevProgram != 0) RenderSystem.useProgram(prevProgram);
|
||||
else RenderSystem.useProgram(0);
|
||||
RenderSystem.useProgram(prevProgram);
|
||||
}
|
||||
|
||||
// 选中框绘制(需要切换到固色 shader)
|
||||
@@ -3039,6 +3038,7 @@ public class Mesh2D {
|
||||
bb.vertex(centerX - arrowSize, rotationHandleY + arrowSize, 0.0f, 0.0f);
|
||||
bb.endImmediate();
|
||||
}
|
||||
|
||||
private void drawCenterPoint(BufferBuilder bb, float minX, float minY, float maxX, float maxY) {
|
||||
// 使用 Mesh2D 的 pivot 作为中心点位置,但当 pivot 不在 bounds 内时回退为 bounds 中心(避免渲染时跳回 0,0 的情况)
|
||||
float centerX = pivot.x;
|
||||
@@ -3233,6 +3233,7 @@ public class Mesh2D {
|
||||
bounds[3] + expand
|
||||
};
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
if (!visible) return;
|
||||
if (indices == null || indices.length == 0) return;
|
||||
@@ -3332,7 +3333,7 @@ public class Mesh2D {
|
||||
// ==================== Getter/Setter ====================
|
||||
|
||||
public String getName() {
|
||||
if (modelPart != null){
|
||||
if (modelPart != null) {
|
||||
return modelPart.getName();
|
||||
}
|
||||
return name;
|
||||
@@ -3456,17 +3457,26 @@ public class Mesh2D {
|
||||
*/
|
||||
public String getDrawModeString() {
|
||||
switch (drawMode) {
|
||||
case POINTS: return "POINTS";
|
||||
case LINES: return "LINES";
|
||||
case LINE_STRIP: return "LINE_STRIP";
|
||||
case TRIANGLES: return "TRIANGLES";
|
||||
case TRIANGLE_STRIP: return "TRIANGLE_STRIP";
|
||||
case TRIANGLE_FAN: return "TRIANGLE_FAN";
|
||||
default: return "UNKNOWN";
|
||||
case POINTS:
|
||||
return "POINTS";
|
||||
case LINES:
|
||||
return "LINES";
|
||||
case LINE_STRIP:
|
||||
return "LINE_STRIP";
|
||||
case TRIANGLES:
|
||||
return "TRIANGLES";
|
||||
case TRIANGLE_STRIP:
|
||||
return "TRIANGLE_STRIP";
|
||||
case TRIANGLE_FAN:
|
||||
return "TRIANGLE_FAN";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/** 标记或查询网格顶点是否已经被烘焙到世界坐标 */
|
||||
/**
|
||||
* 标记或查询网格顶点是否已经被烘焙到世界坐标
|
||||
*/
|
||||
public void setBakedToWorld(boolean baked) {
|
||||
this.bakedToWorld = baked;
|
||||
}
|
||||
|
||||
@@ -4,13 +4,16 @@ import com.chuangzhou.vivid2D.render.model.Model2D;
|
||||
import com.chuangzhou.vivid2D.render.model.ModelPart;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 2D物理系统,用于处理模型的物理模拟
|
||||
* 支持弹簧系统、碰撞检测、重力等物理效果
|
||||
*
|
||||
* <p>
|
||||
* 调整点:
|
||||
* - 使用半隐式(symplectic)Euler 积分,替代之前的纯 Verlet(更稳定且直观)
|
||||
* - 在约束迭代后同步速度(根据位置变化计算),避免约束把位置推回后速度不一致导致僵化
|
||||
@@ -471,8 +474,7 @@ public class PhysicsSystem {
|
||||
private void applyToModel(Model2D model) {
|
||||
for (PhysicsParticle particle : particles.values()) {
|
||||
Object userData = particle.getUserData();
|
||||
if (userData instanceof ModelPart) {
|
||||
ModelPart part = (ModelPart) userData;
|
||||
if (userData instanceof ModelPart part) {
|
||||
part.setPosition(particle.getPosition());
|
||||
|
||||
// 可选:根据速度设置旋转
|
||||
@@ -611,11 +613,8 @@ public class PhysicsSystem {
|
||||
Vector2f positionDelta = new Vector2f(particle.getPosition())
|
||||
.sub(particle.getPreviousPosition()); // 现在可以正常使用了
|
||||
float positionDeltaSquared = positionDelta.lengthSquared();
|
||||
if (positionDeltaSquared > 0.001f) { // 位置变化阈值,可调整
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
// 位置变化阈值,可调整
|
||||
return positionDeltaSquared > 0.001f;
|
||||
});
|
||||
|
||||
// 检查是否有活跃的约束
|
||||
@@ -731,31 +730,78 @@ public class PhysicsSystem {
|
||||
}
|
||||
|
||||
// Getter/Setter 方法
|
||||
public String getId() { return id; }
|
||||
public Vector2f getPosition() { return new Vector2f(position); }
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Vector2f getPosition() {
|
||||
return new Vector2f(position);
|
||||
}
|
||||
|
||||
public void setPosition(Vector2f position) {
|
||||
this.position.set(position);
|
||||
}
|
||||
public Vector2f getVelocity() { return new Vector2f(velocity); }
|
||||
|
||||
public Vector2f getVelocity() {
|
||||
return new Vector2f(velocity);
|
||||
}
|
||||
|
||||
public void setVelocity(Vector2f velocity) {
|
||||
this.velocity.set(velocity);
|
||||
}
|
||||
public Vector2f getAcceleration() { return new Vector2f(acceleration); }
|
||||
|
||||
public Vector2f getAcceleration() {
|
||||
return new Vector2f(acceleration);
|
||||
}
|
||||
|
||||
public float getMass() {
|
||||
if (Float.isInfinite(mass)) return Float.POSITIVE_INFINITY;
|
||||
return mass;
|
||||
}
|
||||
public float getInverseMass() { return inverseMass; }
|
||||
public float getRadius() { return radius; }
|
||||
public void setRadius(float radius) { this.radius = radius; }
|
||||
public boolean isMovable() { return movable; }
|
||||
public void setMovable(boolean movable) { this.movable = movable; }
|
||||
public boolean isAffectedByGravity() { return affectedByGravity; }
|
||||
public void setAffectedByGravity(boolean affectedByGravity) { this.affectedByGravity = affectedByGravity; }
|
||||
public Object getUserData() { return userData; }
|
||||
public void setUserData(Object userData) { this.userData = userData; }
|
||||
public boolean isAffectedByWind() { return affectedByWind; }
|
||||
public void setAffectedByWind(boolean affectedByWind) { this.affectedByWind = affectedByWind; }
|
||||
|
||||
public float getInverseMass() {
|
||||
return inverseMass;
|
||||
}
|
||||
|
||||
public float getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
public void setRadius(float radius) {
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public boolean isMovable() {
|
||||
return movable;
|
||||
}
|
||||
|
||||
public void setMovable(boolean movable) {
|
||||
this.movable = movable;
|
||||
}
|
||||
|
||||
public boolean isAffectedByGravity() {
|
||||
return affectedByGravity;
|
||||
}
|
||||
|
||||
public void setAffectedByGravity(boolean affectedByGravity) {
|
||||
this.affectedByGravity = affectedByGravity;
|
||||
}
|
||||
|
||||
public Object getUserData() {
|
||||
return userData;
|
||||
}
|
||||
|
||||
public void setUserData(Object userData) {
|
||||
this.userData = userData;
|
||||
}
|
||||
|
||||
public boolean isAffectedByWind() {
|
||||
return affectedByWind;
|
||||
}
|
||||
|
||||
public void setAffectedByWind(boolean affectedByWind) {
|
||||
this.affectedByWind = affectedByWind;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -814,14 +860,37 @@ public class PhysicsSystem {
|
||||
}
|
||||
|
||||
// Getter/Setter 方法
|
||||
public String getId() { return id; }
|
||||
public PhysicsParticle getParticleA() { return particleA; }
|
||||
public PhysicsParticle getParticleB() { return particleB; }
|
||||
public float getRestLength() { return restLength; }
|
||||
public float getStiffness() { return stiffness; }
|
||||
public float getDamping() { return damping; }
|
||||
public boolean isEnabled() { return enabled; }
|
||||
public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public PhysicsParticle getParticleA() {
|
||||
return particleA;
|
||||
}
|
||||
|
||||
public PhysicsParticle getParticleB() {
|
||||
return particleB;
|
||||
}
|
||||
|
||||
public float getRestLength() {
|
||||
return restLength;
|
||||
}
|
||||
|
||||
public float getStiffness() {
|
||||
return stiffness;
|
||||
}
|
||||
|
||||
public float getDamping() {
|
||||
return damping;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -829,8 +898,11 @@ public class PhysicsSystem {
|
||||
*/
|
||||
public interface PhysicsConstraint {
|
||||
void apply(float deltaTime);
|
||||
|
||||
PhysicsParticle getParticle();
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
void setEnabled(boolean enabled);
|
||||
}
|
||||
|
||||
@@ -863,13 +935,36 @@ public class PhysicsSystem {
|
||||
}
|
||||
|
||||
// Getter/Setter 方法
|
||||
@Override public PhysicsParticle getParticle() { return particle; }
|
||||
@Override public boolean isEnabled() { return enabled; }
|
||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
||||
public Vector2f getTargetPosition() { return new Vector2f(targetPosition); }
|
||||
public void setTargetPosition(Vector2f targetPosition) { this.targetPosition.set(targetPosition); }
|
||||
public float getStrength() { return strength; }
|
||||
public void setStrength(float strength) { this.strength = Math.max(0.0f, Math.min(1.0f, strength)); }
|
||||
@Override
|
||||
public PhysicsParticle getParticle() {
|
||||
return particle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Vector2f getTargetPosition() {
|
||||
return new Vector2f(targetPosition);
|
||||
}
|
||||
|
||||
public void setTargetPosition(Vector2f targetPosition) {
|
||||
this.targetPosition.set(targetPosition);
|
||||
}
|
||||
|
||||
public float getStrength() {
|
||||
return strength;
|
||||
}
|
||||
|
||||
public void setStrength(float strength) {
|
||||
this.strength = Math.max(0.0f, Math.min(1.0f, strength));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -902,11 +997,28 @@ public class PhysicsSystem {
|
||||
}
|
||||
|
||||
// Getter/Setter 方法
|
||||
@Override public PhysicsParticle getParticle() { return particle; }
|
||||
@Override public boolean isEnabled() { return enabled; }
|
||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
||||
public PhysicsParticle getTarget() { return target; }
|
||||
public float getMaxDistance() { return maxDistance; }
|
||||
@Override
|
||||
public PhysicsParticle getParticle() {
|
||||
return particle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public PhysicsParticle getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public float getMaxDistance() {
|
||||
return maxDistance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -914,9 +1026,13 @@ public class PhysicsSystem {
|
||||
*/
|
||||
public interface PhysicsCollider {
|
||||
boolean collidesWith(PhysicsParticle particle);
|
||||
|
||||
void resolveCollision(PhysicsParticle particle, float deltaTime);
|
||||
|
||||
String getId();
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
void setEnabled(boolean enabled);
|
||||
}
|
||||
|
||||
@@ -973,12 +1089,32 @@ public class PhysicsSystem {
|
||||
}
|
||||
|
||||
// Getter/Setter 方法
|
||||
@Override public String getId() { return id; }
|
||||
@Override public boolean isEnabled() { return enabled; }
|
||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
||||
public Vector2f getCenter() { return new Vector2f(center); }
|
||||
public void setCenter(Vector2f center) { this.center.set(center); }
|
||||
public float getRadius() { return radius; }
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Vector2f getCenter() {
|
||||
return new Vector2f(center);
|
||||
}
|
||||
|
||||
public void setCenter(Vector2f center) {
|
||||
this.center.set(center);
|
||||
}
|
||||
|
||||
public float getRadius() {
|
||||
return radius;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1059,13 +1195,36 @@ public class PhysicsSystem {
|
||||
}
|
||||
|
||||
// Getter/Setter 方法
|
||||
@Override public String getId() { return id; }
|
||||
@Override public boolean isEnabled() { return enabled; }
|
||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
||||
public Vector2f getCenter() { return new Vector2f(center); }
|
||||
public void setCenter(Vector2f center) { this.center.set(center); }
|
||||
public float getWidth() { return width; }
|
||||
public float getHeight() { return height; }
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Vector2f getCenter() {
|
||||
return new Vector2f(center);
|
||||
}
|
||||
|
||||
public void setCenter(Vector2f center) {
|
||||
this.center.set(center);
|
||||
}
|
||||
|
||||
public float getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public float getHeight() {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1090,12 +1249,29 @@ public class PhysicsSystem {
|
||||
}
|
||||
|
||||
// Getter 方法
|
||||
public int getParticleCount() { return particleCount; }
|
||||
public int getSpringCount() { return springCount; }
|
||||
public int getConstraintCount() { return constraintCount; }
|
||||
public int getColliderCount() { return colliderCount; }
|
||||
public float getAverageUpdateTime() { return averageUpdateTime; }
|
||||
public int getTotalUpdates() { return totalUpdates; }
|
||||
public int getParticleCount() {
|
||||
return particleCount;
|
||||
}
|
||||
|
||||
public int getSpringCount() {
|
||||
return springCount;
|
||||
}
|
||||
|
||||
public int getConstraintCount() {
|
||||
return constraintCount;
|
||||
}
|
||||
|
||||
public int getColliderCount() {
|
||||
return colliderCount;
|
||||
}
|
||||
|
||||
public float getAverageUpdateTime() {
|
||||
return averageUpdateTime;
|
||||
}
|
||||
|
||||
public int getTotalUpdates() {
|
||||
return totalUpdates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
package com.chuangzhou.vivid2D.render.model.util;
|
||||
|
||||
import com.chuangzhou.vivid2D.render.systems.RenderSystem;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.*;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
import org.lwjgl.stb.STBImageWrite;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
@@ -75,9 +70,17 @@ public class Texture {
|
||||
this.glFormat = glFormat;
|
||||
}
|
||||
|
||||
public int getComponents() { return components; }
|
||||
public int getGLInternalFormat() { return glInternalFormat; }
|
||||
public int getGLFormat() { return glFormat; }
|
||||
public int getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public int getGLInternalFormat() {
|
||||
return glInternalFormat;
|
||||
}
|
||||
|
||||
public int getGLFormat() {
|
||||
return glFormat;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureType {
|
||||
@@ -95,7 +98,9 @@ public class Texture {
|
||||
this.glType = glType;
|
||||
}
|
||||
|
||||
public int getGLType() { return glType; }
|
||||
public int getGLType() {
|
||||
return glType;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureFilter {
|
||||
@@ -112,7 +117,9 @@ public class Texture {
|
||||
this.glFilter = glFilter;
|
||||
}
|
||||
|
||||
public int getGLFilter() { return glFilter; }
|
||||
public int getGLFilter() {
|
||||
return glFilter;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureWrap {
|
||||
@@ -127,7 +134,9 @@ public class Texture {
|
||||
this.glWrap = glWrap;
|
||||
}
|
||||
|
||||
public int getGLWrap() { return glWrap; }
|
||||
public int getGLWrap() {
|
||||
return glWrap;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== STB 图像加载 ====================
|
||||
@@ -244,7 +253,8 @@ public class Texture {
|
||||
// 恢复原先的 UNPACK_ALIGNMENT
|
||||
try {
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, prevUnpack);
|
||||
} catch (Exception ignored) {}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
unbind();
|
||||
}
|
||||
}
|
||||
@@ -333,10 +343,10 @@ public class Texture {
|
||||
* 从当前纹理裁剪出一个子纹理并返回新的 Texture。
|
||||
* 仅支持 UNSIGNED_BYTE 类型的纹理(常见的 8-bit per component 图像)。
|
||||
*
|
||||
* @param x 裁剪区域左上角 X(像素)
|
||||
* @param y 裁剪区域左上角 Y(像素)
|
||||
* @param w 裁剪区域宽度(像素)
|
||||
* @param h 裁剪区域高度(像素)
|
||||
* @param x 裁剪区域左上角 X(像素)
|
||||
* @param y 裁剪区域左上角 Y(像素)
|
||||
* @param w 裁剪区域宽度(像素)
|
||||
* @param h 裁剪区域高度(像素)
|
||||
* @param newName 新纹理名称
|
||||
* @return 新创建的子纹理
|
||||
*/
|
||||
@@ -869,10 +879,14 @@ public class Texture {
|
||||
*/
|
||||
public static TextureFormat getTextureFormat(int components) {
|
||||
switch (components) {
|
||||
case 1: return TextureFormat.RED;
|
||||
case 2: return TextureFormat.RG;
|
||||
case 3: return TextureFormat.RGB;
|
||||
case 4: return TextureFormat.RGBA;
|
||||
case 1:
|
||||
return TextureFormat.RED;
|
||||
case 2:
|
||||
return TextureFormat.RG;
|
||||
case 3:
|
||||
return TextureFormat.RGB;
|
||||
case 4:
|
||||
return TextureFormat.RGBA;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported number of components: " + components);
|
||||
}
|
||||
@@ -1071,7 +1085,6 @@ public class Texture {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 从字节数组创建纹理
|
||||
*/
|
||||
@@ -1196,13 +1209,20 @@ public class Texture {
|
||||
*/
|
||||
private String getGLErrorString(int error) {
|
||||
switch (error) {
|
||||
case GL11.GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
||||
case GL11.GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
||||
case GL11.GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
||||
case GL11.GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
||||
case GL11.GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
|
||||
case GL11.GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
|
||||
default: return "Unknown Error (0x" + Integer.toHexString(error) + ")";
|
||||
case GL11.GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM";
|
||||
case GL11.GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE";
|
||||
case GL11.GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION";
|
||||
case GL11.GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY";
|
||||
case GL11.GL_STACK_OVERFLOW:
|
||||
return "GL_STACK_OVERFLOW";
|
||||
case GL11.GL_STACK_UNDERFLOW:
|
||||
return "GL_STACK_UNDERFLOW";
|
||||
default:
|
||||
return "Unknown Error (0x" + Integer.toHexString(error) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.function.Supplier;
|
||||
*/
|
||||
public final class RenderSystem {
|
||||
private static final Logger logger = LoggerFactory.getLogger(RenderSystem.class);
|
||||
|
||||
private RenderSystem() { /* no instances */ }
|
||||
|
||||
// ================== 线程管理 ==================
|
||||
@@ -155,7 +156,7 @@ public final class RenderSystem {
|
||||
java.nio.FloatBuffer floatBuf = org.lwjgl.system.MemoryUtil.memAllocFloat(4);
|
||||
try {
|
||||
GL11.glGetFloatv(GL11.GL_COLOR_CLEAR_VALUE, floatBuf);
|
||||
this.clearColor = new float[] {
|
||||
this.clearColor = new float[]{
|
||||
floatBuf.get(0), floatBuf.get(1),
|
||||
floatBuf.get(2), floatBuf.get(3)
|
||||
};
|
||||
@@ -166,7 +167,7 @@ public final class RenderSystem {
|
||||
java.nio.IntBuffer viewportBuf = org.lwjgl.system.MemoryUtil.memAllocInt(4);
|
||||
try {
|
||||
GL11.glGetIntegerv(GL11.GL_VIEWPORT, viewportBuf);
|
||||
this.viewport = new int[] {
|
||||
this.viewport = new int[]{
|
||||
viewportBuf.get(0), viewportBuf.get(1),
|
||||
viewportBuf.get(2), viewportBuf.get(3)
|
||||
};
|
||||
@@ -187,8 +188,8 @@ public final class RenderSystem {
|
||||
this.blendDstFactor = GL11.GL_ONE_MINUS_SRC_ALPHA;
|
||||
this.activeTexture = GL13.GL_TEXTURE0;
|
||||
this.boundTexture = 0;
|
||||
this.clearColor = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
this.viewport = new int[] {0, 0, viewportWidth, viewportHeight};
|
||||
this.clearColor = new float[]{0.0f, 0.0f, 0.0f, 1.0f};
|
||||
this.viewport = new int[]{0, 0, viewportWidth, viewportHeight};
|
||||
}
|
||||
|
||||
public void restore() {
|
||||
@@ -657,6 +658,7 @@ public final class RenderSystem {
|
||||
assertOnRenderThread();
|
||||
GL11.glLineWidth(width);
|
||||
}
|
||||
|
||||
public static void drawElements(int mode, int count, int type, long indices) {
|
||||
if (!isOnRenderThread()) {
|
||||
recordRenderCall(() -> _drawElements(mode, count, type, indices));
|
||||
@@ -1206,8 +1208,9 @@ public final class RenderSystem {
|
||||
|
||||
/**
|
||||
* 设置着色器纹理
|
||||
*
|
||||
* @param textureUnit 纹理单元 (0, 1, 2, ...)
|
||||
* @param texture 纹理对象
|
||||
* @param texture 纹理对象
|
||||
*/
|
||||
public static void setShaderTexture(int textureUnit, com.chuangzhou.vivid2D.render.model.util.Texture texture) {
|
||||
if (!isOnRenderThread()) {
|
||||
@@ -1247,8 +1250,9 @@ public final class RenderSystem {
|
||||
|
||||
/**
|
||||
* 设置着色器纹理 - 接受纹理ID的版本
|
||||
*
|
||||
* @param textureUnit 纹理单元
|
||||
* @param textureId 纹理ID
|
||||
* @param textureId 纹理ID
|
||||
*/
|
||||
public static void setShaderTexture(int textureUnit, int textureId) {
|
||||
if (!isOnRenderThread()) {
|
||||
@@ -1433,6 +1437,7 @@ public final class RenderSystem {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void pixelStore(int pname, int param) {
|
||||
if (!isOnRenderThread()) {
|
||||
recordRenderCall(() -> _pixelStore(pname, param));
|
||||
@@ -1514,6 +1519,7 @@ public final class RenderSystem {
|
||||
logger.info("Max Texture Units: {}",
|
||||
GL11.glGetInteger(GL20.GL_MAX_TEXTURE_IMAGE_UNITS));
|
||||
}
|
||||
|
||||
public static void setupDefaultState() {
|
||||
beginInitialization();
|
||||
|
||||
@@ -1559,17 +1565,22 @@ public final class RenderSystem {
|
||||
}
|
||||
|
||||
logger.error("OpenGL error during {}: {}\n{}",
|
||||
operation, getGLErrorString(error), stackTraceBuilder.toString());
|
||||
operation, getGLErrorString(error), stackTraceBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getGLErrorString(int error) {
|
||||
switch (error) {
|
||||
case GL11.GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
||||
case GL11.GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
||||
case GL11.GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
||||
case GL11.GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
||||
default: return "Unknown (0x" + Integer.toHexString(error) + ")";
|
||||
case GL11.GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM";
|
||||
case GL11.GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE";
|
||||
case GL11.GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION";
|
||||
case GL11.GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY";
|
||||
default:
|
||||
return "Unknown (0x" + Integer.toHexString(error) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package com.chuangzhou.vivid2D.render.systems.sources.def;
|
||||
|
||||
import com.chuangzhou.vivid2D.render.systems.sources.*;
|
||||
|
||||
import com.chuangzhou.vivid2D.render.systems.sources.CompleteShader;
|
||||
import com.chuangzhou.vivid2D.render.systems.sources.Shader;
|
||||
import com.chuangzhou.vivid2D.render.systems.sources.ShaderProgram;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
/**
|
||||
* 文本着色器
|
||||
*
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public class TextShader implements CompleteShader {
|
||||
|
||||
private final VertexShader vertexShader = new VertexShader();
|
||||
private final FragmentShader fragmentShader = new FragmentShader();
|
||||
private Vector4f color = new Vector4f(1,1,1,1);
|
||||
private final Vector4f color = new Vector4f(1, 1, 1, 1);
|
||||
|
||||
public void setColor(Vector4f color) {
|
||||
this.color.set(color);
|
||||
@@ -50,20 +52,20 @@ public class TextShader implements CompleteShader {
|
||||
@Override
|
||||
public String getShaderCode() {
|
||||
return """
|
||||
#version 330 core
|
||||
layout(location = 0) in vec2 aPosition;
|
||||
layout(location = 1) in vec2 aTexCoord;
|
||||
#version 330 core
|
||||
layout(location = 0) in vec2 aPosition;
|
||||
layout(location = 1) in vec2 aTexCoord;
|
||||
|
||||
uniform mat3 uProjectionMatrix;
|
||||
uniform mat3 uProjectionMatrix;
|
||||
|
||||
out vec2 vTexCoord;
|
||||
out vec2 vTexCoord;
|
||||
|
||||
void main() {
|
||||
vec3 p = uProjectionMatrix * vec3(aPosition, 1.0);
|
||||
gl_Position = vec4(p.xy, 0.0, 1.0);
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
""";
|
||||
void main() {
|
||||
vec3 p = uProjectionMatrix * vec3(aPosition, 1.0);
|
||||
gl_Position = vec4(p.xy, 0.0, 1.0);
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,19 +78,19 @@ public class TextShader implements CompleteShader {
|
||||
@Override
|
||||
public String getShaderCode() {
|
||||
return """
|
||||
#version 330 core
|
||||
in vec2 vTexCoord;
|
||||
out vec4 FragColor;
|
||||
#version 330 core
|
||||
in vec2 vTexCoord;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D uTexture;
|
||||
uniform vec4 uColor;
|
||||
uniform sampler2D uTexture;
|
||||
uniform vec4 uColor;
|
||||
|
||||
void main() {
|
||||
// 使用 .r 通道读取单通道纹理
|
||||
float alpha = texture(uTexture, vTexCoord).r;
|
||||
FragColor = vec4(uColor.rgb, uColor.a * alpha);
|
||||
}
|
||||
""";
|
||||
void main() {
|
||||
// 使用 .r 通道读取单通道纹理
|
||||
float alpha = texture(uTexture, vTexCoord).r;
|
||||
FragColor = vec4(uColor.rgb, uColor.a * alpha);
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user