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.ShaderManagement;
|
||||||
import com.chuangzhou.vivid2D.render.systems.sources.ShaderProgram;
|
import com.chuangzhou.vivid2D.render.systems.sources.ShaderProgram;
|
||||||
import org.joml.Vector4f;
|
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.STBTTAlignedQuad;
|
||||||
import org.lwjgl.stb.STBTTBakedChar;
|
import org.lwjgl.stb.STBTTBakedChar;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
@@ -15,10 +18,12 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
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 文本渲染器
|
* 支持 ASCII + 中文的 OpenGL 文本渲染器
|
||||||
|
*
|
||||||
* @author tzdwindows 7
|
* @author tzdwindows 7
|
||||||
*/
|
*/
|
||||||
public final class TextRenderer {
|
public final class TextRenderer {
|
||||||
@@ -317,7 +322,15 @@ public final class TextRenderer {
|
|||||||
logger.debug("TextRenderer cleaned up");
|
logger.debug("TextRenderer cleaned up");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInitialized() { return initialized; }
|
public boolean isInitialized() {
|
||||||
public int getAsciiTextureId() { return asciiTextureId; }
|
return initialized;
|
||||||
public int getChineseTextureId() { return chineseTextureId; }
|
}
|
||||||
|
|
||||||
|
public int getAsciiTextureId() {
|
||||||
|
return asciiTextureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChineseTextureId() {
|
||||||
|
return chineseTextureId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,10 @@ public class PsdParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
try { reader.dispose(); } catch (Exception ignored) {}
|
try {
|
||||||
|
reader.dispose();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.chuangzhou.vivid2D.render.model;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 模型事件
|
* 模型事件
|
||||||
|
*
|
||||||
* @author tzdwindows 7
|
* @author tzdwindows 7
|
||||||
*/
|
*/
|
||||||
public interface ModelEvent {
|
public interface ModelEvent {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* LightSource 的序列化数据类(扩展:包含辉光/Glow 的序列化字段)
|
* LightSource 的序列化数据类(扩展:包含辉光/Glow 的序列化字段)
|
||||||
|
*
|
||||||
* @author tzdwindows 7
|
* @author tzdwindows 7
|
||||||
*/
|
*/
|
||||||
public class LightSourceData implements Serializable {
|
public class LightSourceData implements Serializable {
|
||||||
|
|||||||
@@ -80,8 +80,7 @@ public class PartData implements Serializable {
|
|||||||
// 期望的方法签名: public List<YourStrokeClass> getLiquifyStrokes()
|
// 期望的方法签名: public List<YourStrokeClass> getLiquifyStrokes()
|
||||||
java.lang.reflect.Method m = part.getClass().getMethod("getLiquifyStrokes");
|
java.lang.reflect.Method m = part.getClass().getMethod("getLiquifyStrokes");
|
||||||
Object strokesObj = m.invoke(part);
|
Object strokesObj = m.invoke(part);
|
||||||
if (strokesObj instanceof List<?>) {
|
if (strokesObj instanceof List<?> strokes) {
|
||||||
List<?> strokes = (List<?>) strokesObj;
|
|
||||||
for (Object s : strokes) {
|
for (Object s : strokes) {
|
||||||
// 支持两种情况:存储为自定义类型(有 getMode/getRadius/getStrength/getIterations/getPoints 方法)
|
// 支持两种情况:存储为自定义类型(有 getMode/getRadius/getStrength/getIterations/getPoints 方法)
|
||||||
// 或者直接存储为通用 Map/POJO。我们做宽松处理:通过反射尽可能读取常见字段。
|
// 或者直接存储为通用 Map/POJO。我们做宽松处理:通过反射尽可能读取常见字段。
|
||||||
@@ -91,37 +90,39 @@ public class PartData implements Serializable {
|
|||||||
java.lang.reflect.Method gm = s.getClass().getMethod("getMode");
|
java.lang.reflect.Method gm = s.getClass().getMethod("getMode");
|
||||||
Object modeObj = gm.invoke(s);
|
Object modeObj = gm.invoke(s);
|
||||||
if (modeObj != null) strokeData.mode = modeObj.toString();
|
if (modeObj != null) strokeData.mode = modeObj.toString();
|
||||||
} catch (NoSuchMethodException ignored) {}
|
} catch (NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
java.lang.reflect.Method gr = s.getClass().getMethod("getRadius");
|
java.lang.reflect.Method gr = s.getClass().getMethod("getRadius");
|
||||||
Object r = gr.invoke(s);
|
Object r = gr.invoke(s);
|
||||||
if (r instanceof Number) strokeData.radius = ((Number) r).floatValue();
|
if (r instanceof Number) strokeData.radius = ((Number) r).floatValue();
|
||||||
} catch (NoSuchMethodException ignored) {}
|
} catch (NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
java.lang.reflect.Method gs = s.getClass().getMethod("getStrength");
|
java.lang.reflect.Method gs = s.getClass().getMethod("getStrength");
|
||||||
Object st = gs.invoke(s);
|
Object st = gs.invoke(s);
|
||||||
if (st instanceof Number) strokeData.strength = ((Number) st).floatValue();
|
if (st instanceof Number) strokeData.strength = ((Number) st).floatValue();
|
||||||
} catch (NoSuchMethodException ignored) {}
|
} catch (NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
java.lang.reflect.Method gi = s.getClass().getMethod("getIterations");
|
java.lang.reflect.Method gi = s.getClass().getMethod("getIterations");
|
||||||
Object it = gi.invoke(s);
|
Object it = gi.invoke(s);
|
||||||
if (it instanceof Number) strokeData.iterations = ((Number) it).intValue();
|
if (it instanceof Number) strokeData.iterations = ((Number) it).intValue();
|
||||||
} catch (NoSuchMethodException ignored) {}
|
} catch (NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
// 读取点列表
|
// 读取点列表
|
||||||
try {
|
try {
|
||||||
java.lang.reflect.Method gp = s.getClass().getMethod("getPoints");
|
java.lang.reflect.Method gp = s.getClass().getMethod("getPoints");
|
||||||
Object ptsObj = gp.invoke(s);
|
Object ptsObj = gp.invoke(s);
|
||||||
if (ptsObj instanceof List<?>) {
|
if (ptsObj instanceof List<?> pts) {
|
||||||
List<?> pts = (List<?>) ptsObj;
|
|
||||||
for (Object p : pts) {
|
for (Object p : pts) {
|
||||||
// 支持 Vector2f 或自定义点类型(有 getX/getY/getPressure)
|
// 支持 Vector2f 或自定义点类型(有 getX/getY/getPressure)
|
||||||
LiquifyPointData pd = new LiquifyPointData();
|
LiquifyPointData pd = new LiquifyPointData();
|
||||||
if (p instanceof org.joml.Vector2f) {
|
if (p instanceof Vector2f v) {
|
||||||
org.joml.Vector2f v = (org.joml.Vector2f) p;
|
|
||||||
pd.x = v.x;
|
pd.x = v.x;
|
||||||
pd.y = v.y;
|
pd.y = v.y;
|
||||||
pd.pressure = 1.0f;
|
pd.pressure = 1.0f;
|
||||||
@@ -144,8 +145,7 @@ public class PartData implements Serializable {
|
|||||||
}
|
}
|
||||||
} catch (NoSuchMethodException ex) {
|
} catch (NoSuchMethodException ex) {
|
||||||
// 最后尝试 Map 形式(键 x,y)
|
// 最后尝试 Map 形式(键 x,y)
|
||||||
if (p instanceof Map<?, ?>) {
|
if (p instanceof Map<?, ?> mapP) {
|
||||||
Map<?, ?> mapP = (Map<?, ?>) p;
|
|
||||||
Object ox = mapP.get("x");
|
Object ox = mapP.get("x");
|
||||||
Object oy = mapP.get("y");
|
Object oy = mapP.get("y");
|
||||||
if (ox instanceof Number && oy instanceof Number) {
|
if (ox instanceof Number && oy instanceof Number) {
|
||||||
@@ -160,7 +160,8 @@ public class PartData implements Serializable {
|
|||||||
strokeData.points.add(pd);
|
strokeData.points.add(pd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NoSuchMethodException ignored) {}
|
} catch (NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
// 如果没有 mode,则用默认 PUSH
|
// 如果没有 mode,则用默认 PUSH
|
||||||
if (strokeData.mode == null) strokeData.mode = ModelPart.LiquifyMode.PUSH.name();
|
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;
|
ModelPart.LiquifyMode modeEnum = ModelPart.LiquifyMode.PUSH;
|
||||||
try {
|
try {
|
||||||
modeEnum = ModelPart.LiquifyMode.valueOf(stroke.mode);
|
modeEnum = ModelPart.LiquifyMode.valueOf(stroke.mode);
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
// 对每个点进行重放:调用 applyLiquify(存在于 ModelPart)
|
// 对每个点进行重放:调用 applyLiquify(存在于 ModelPart)
|
||||||
if (stroke.points != null) {
|
if (stroke.points != null) {
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import com.chuangzhou.vivid2D.render.model.util.Mesh2D;
|
|||||||
import com.chuangzhou.vivid2D.render.model.util.SaveVector2f;
|
import com.chuangzhou.vivid2D.render.model.util.SaveVector2f;
|
||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缩放变形器 - 围绕中心点缩放顶点
|
* 缩放变形器 - 围绕中心点缩放顶点
|
||||||
|
*
|
||||||
* @author tzdwindows 7
|
* @author tzdwindows 7
|
||||||
*/
|
*/
|
||||||
public class ScaleDeformer extends Deformer {
|
public class ScaleDeformer extends Deformer {
|
||||||
@@ -94,11 +94,23 @@ public class ScaleDeformer extends Deformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter/Setter
|
// Getter/Setter
|
||||||
public Vector2f getBaseScale() { return new Vector2f(baseScale); }
|
public Vector2f getBaseScale() {
|
||||||
public void setBaseScale(Vector2f baseScale) { this.baseScale.set(baseScale); }
|
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 author;
|
||||||
private String description;
|
private String description;
|
||||||
private long creationTime;
|
private final long creationTime;
|
||||||
private long lastModifiedTime;
|
private long lastModifiedTime;
|
||||||
private Map<String, String> userData;
|
private Map<String, String> userData;
|
||||||
|
|
||||||
@@ -554,9 +554,17 @@ public class AnimationClip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter方法
|
// Getter方法
|
||||||
public String getParameterId() { return parameterId; }
|
public String getParameterId() {
|
||||||
public List<Keyframe> getKeyframes() { return Collections.unmodifiableList(keyframes); }
|
return parameterId;
|
||||||
public float getDefaultValue() { return defaultValue; }
|
}
|
||||||
|
|
||||||
|
public List<Keyframe> getKeyframes() {
|
||||||
|
return Collections.unmodifiableList(keyframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -578,9 +586,17 @@ public class AnimationClip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter方法
|
// Getter方法
|
||||||
public float getTime() { return time; }
|
public float getTime() {
|
||||||
public float getValue() { return value; }
|
return time;
|
||||||
public InterpolationType getInterpolation() { return interpolation; }
|
}
|
||||||
|
|
||||||
|
public float getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InterpolationType getInterpolation() {
|
||||||
|
return interpolation;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -621,10 +637,21 @@ public class AnimationClip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter方法
|
// Getter方法
|
||||||
public String getName() { return name; }
|
public String getName() {
|
||||||
public float getTime() { return time; }
|
return name;
|
||||||
public Runnable getAction() { return action; }
|
}
|
||||||
public boolean isTriggered() { return triggered; }
|
|
||||||
|
public float getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Runnable getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTriggered() {
|
||||||
|
return triggered;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -646,23 +673,39 @@ public class AnimationClip {
|
|||||||
|
|
||||||
// ==================== Getter/Setter ====================
|
// ==================== Getter/Setter ====================
|
||||||
|
|
||||||
public String getName() { return name; }
|
public String getName() {
|
||||||
public UUID getUuid() { return uuid; }
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
public float getDuration() { return duration; }
|
|
||||||
public void setDuration(float duration) {
|
public void setDuration(float duration) {
|
||||||
this.duration = Math.max(0.0f, duration);
|
this.duration = Math.max(0.0f, duration);
|
||||||
markModified();
|
markModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getFramesPerSecond() { return framesPerSecond; }
|
public float getFramesPerSecond() {
|
||||||
|
return framesPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
public void setFramesPerSecond(float framesPerSecond) {
|
public void setFramesPerSecond(float framesPerSecond) {
|
||||||
this.framesPerSecond = Math.max(1.0f, framesPerSecond);
|
this.framesPerSecond = Math.max(1.0f, framesPerSecond);
|
||||||
markModified();
|
markModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLooping() { return looping; }
|
public boolean isLooping() {
|
||||||
public void setLooping(boolean looping) { this.looping = looping; }
|
return looping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLooping(boolean looping) {
|
||||||
|
this.looping = looping;
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String, AnimationCurve> getCurves() {
|
public Map<String, AnimationCurve> getCurves() {
|
||||||
return Collections.unmodifiableMap(curves);
|
return Collections.unmodifiableMap(curves);
|
||||||
@@ -676,18 +719,34 @@ public class AnimationClip {
|
|||||||
return Collections.unmodifiableMap(defaultValues);
|
return Collections.unmodifiableMap(defaultValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAuthor() { return author; }
|
public String getAuthor() {
|
||||||
public void setAuthor(String author) { this.author = author; }
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDescription() { return description; }
|
public void setAuthor(String author) {
|
||||||
public void setDescription(String description) { this.description = description; }
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
public long getCreationTime() { return creationTime; }
|
public String getDescription() {
|
||||||
public long getLastModifiedTime() { return lastModifiedTime; }
|
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() {
|
public Map<String, String> getUserData() {
|
||||||
return Collections.unmodifiableMap(userData);
|
return Collections.unmodifiableMap(userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserData(Map<String, String> userData) {
|
public void setUserData(Map<String, String> userData) {
|
||||||
this.userData = new ConcurrentHashMap<>(userData);
|
this.userData = new ConcurrentHashMap<>(userData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -516,10 +516,21 @@ public class BoundingBox {
|
|||||||
|
|
||||||
// ==================== Getter方法 ====================
|
// ==================== Getter方法 ====================
|
||||||
|
|
||||||
public float getMinX() { return minX; }
|
public float getMinX() {
|
||||||
public float getMinY() { return minY; }
|
return minX;
|
||||||
public float getMaxX() { return maxX; }
|
}
|
||||||
public float getMaxY() { return maxY; }
|
|
||||||
|
public float getMinY() {
|
||||||
|
return minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMaxX() {
|
||||||
|
return maxX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMaxY() {
|
||||||
|
return maxY;
|
||||||
|
}
|
||||||
|
|
||||||
public float getWidth() {
|
public float getWidth() {
|
||||||
return valid ? maxX - minX : 0.0f;
|
return valid ? maxX - minX : 0.0f;
|
||||||
@@ -529,12 +540,25 @@ public class BoundingBox {
|
|||||||
return valid ? maxY - minY : 0.0f;
|
return valid ? maxY - minY : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getLeft() { return minX; }
|
public float getLeft() {
|
||||||
public float getRight() { return maxX; }
|
return minX;
|
||||||
public float getBottom() { return minY; }
|
}
|
||||||
public float getTop() { return maxY; }
|
|
||||||
|
|
||||||
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 com.chuangzhou.vivid2D.render.systems.sources.ShaderProgram;
|
||||||
import org.joml.Matrix3f;
|
import org.joml.Matrix3f;
|
||||||
import org.joml.Vector2f;
|
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.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
@@ -19,12 +27,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
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模型的几何数据
|
* 2D网格类,用于存储和管理2D模型的几何数据
|
||||||
* 支持顶点、UV坐标、索引和变形操作
|
* 支持顶点、UV坐标、索引和变形操作
|
||||||
@@ -42,7 +44,7 @@ public class Mesh2D {
|
|||||||
private ModelPart modelPart;
|
private ModelPart modelPart;
|
||||||
|
|
||||||
// ==================== 二级顶点支持 ====================
|
// ==================== 二级顶点支持 ====================
|
||||||
private List<SecondaryVertex> secondaryVertices = new ArrayList<>();
|
private final List<SecondaryVertex> secondaryVertices = new ArrayList<>();
|
||||||
private boolean showSecondaryVertices = false;
|
private boolean showSecondaryVertices = false;
|
||||||
public Vector4f secondaryVertexColor = new Vector4f(0.0f, 1.0f, 0.0f, 1.0f); // 绿色二级顶点
|
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); // 红色选中的二级顶点
|
public Vector4f selectedSecondaryVertexColor = new Vector4f(1.0f, 0.0f, 0.0f, 1.0f); // 红色选中的二级顶点
|
||||||
@@ -77,14 +79,14 @@ public class Mesh2D {
|
|||||||
|
|
||||||
// ==================== 液化状态渲染 ====================
|
// ==================== 液化状态渲染 ====================
|
||||||
public boolean showLiquifyOverlay = false;
|
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 PuppetPin selectedPuppetPin = null;
|
||||||
private boolean showPuppetPins = true;
|
private boolean showPuppetPins = true;
|
||||||
private Vector4f puppetPinColor = new Vector4f(1.0f, 0.0f, 0.0f, 1.0f); // 红色控制点
|
private final 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 selectedPuppetPinColor = new Vector4f(1.0f, 1.0f, 0.0f, 1.0f); // 黄色选中的控制点
|
||||||
private float puppetPinSize = 8.0f;
|
private float puppetPinSize = 8.0f;
|
||||||
|
|
||||||
// ==================== 常量 ====================
|
// ==================== 常量 ====================
|
||||||
@@ -377,6 +379,7 @@ public class Mesh2D {
|
|||||||
public boolean getShowPuppetPins() {
|
public boolean getShowPuppetPins() {
|
||||||
return showPuppetPins;
|
return showPuppetPins;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制木偶控制点
|
* 绘制木偶控制点
|
||||||
*/
|
*/
|
||||||
@@ -2296,11 +2299,7 @@ public class Mesh2D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float squaredLength = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
float squaredLength = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
||||||
if (dot > squaredLength) {
|
return !(dot > squaredLength); // 在线段终点之后
|
||||||
return false; // 在线段终点之后
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsPoint(Vector2f point) {
|
public boolean containsPoint(Vector2f point) {
|
||||||
@@ -2385,6 +2384,7 @@ public class Mesh2D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 状态管理 ====================
|
// ==================== 状态管理 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标记数据已修改
|
* 标记数据已修改
|
||||||
*/
|
*/
|
||||||
@@ -2614,8 +2614,7 @@ public class Mesh2D {
|
|||||||
|
|
||||||
// 恢复之前的 program(如果我们切换过)
|
// 恢复之前的 program(如果我们切换过)
|
||||||
if (switchedProgram) {
|
if (switchedProgram) {
|
||||||
if (prevProgram != 0) RenderSystem.useProgram(prevProgram);
|
RenderSystem.useProgram(prevProgram);
|
||||||
else RenderSystem.useProgram(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选中框绘制(需要切换到固色 shader)
|
// 选中框绘制(需要切换到固色 shader)
|
||||||
@@ -3039,6 +3038,7 @@ public class Mesh2D {
|
|||||||
bb.vertex(centerX - arrowSize, rotationHandleY + arrowSize, 0.0f, 0.0f);
|
bb.vertex(centerX - arrowSize, rotationHandleY + arrowSize, 0.0f, 0.0f);
|
||||||
bb.endImmediate();
|
bb.endImmediate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawCenterPoint(BufferBuilder bb, float minX, float minY, float maxX, float maxY) {
|
private void drawCenterPoint(BufferBuilder bb, float minX, float minY, float maxX, float maxY) {
|
||||||
// 使用 Mesh2D 的 pivot 作为中心点位置,但当 pivot 不在 bounds 内时回退为 bounds 中心(避免渲染时跳回 0,0 的情况)
|
// 使用 Mesh2D 的 pivot 作为中心点位置,但当 pivot 不在 bounds 内时回退为 bounds 中心(避免渲染时跳回 0,0 的情况)
|
||||||
float centerX = pivot.x;
|
float centerX = pivot.x;
|
||||||
@@ -3233,6 +3233,7 @@ public class Mesh2D {
|
|||||||
bounds[3] + expand
|
bounds[3] + expand
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw() {
|
public void draw() {
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
if (indices == null || indices.length == 0) return;
|
if (indices == null || indices.length == 0) return;
|
||||||
@@ -3456,17 +3457,26 @@ public class Mesh2D {
|
|||||||
*/
|
*/
|
||||||
public String getDrawModeString() {
|
public String getDrawModeString() {
|
||||||
switch (drawMode) {
|
switch (drawMode) {
|
||||||
case POINTS: return "POINTS";
|
case POINTS:
|
||||||
case LINES: return "LINES";
|
return "POINTS";
|
||||||
case LINE_STRIP: return "LINE_STRIP";
|
case LINES:
|
||||||
case TRIANGLES: return "TRIANGLES";
|
return "LINES";
|
||||||
case TRIANGLE_STRIP: return "TRIANGLE_STRIP";
|
case LINE_STRIP:
|
||||||
case TRIANGLE_FAN: return "TRIANGLE_FAN";
|
return "LINE_STRIP";
|
||||||
default: return "UNKNOWN";
|
case TRIANGLES:
|
||||||
|
return "TRIANGLES";
|
||||||
|
case TRIANGLE_STRIP:
|
||||||
|
return "TRIANGLE_STRIP";
|
||||||
|
case TRIANGLE_FAN:
|
||||||
|
return "TRIANGLE_FAN";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 标记或查询网格顶点是否已经被烘焙到世界坐标 */
|
/**
|
||||||
|
* 标记或查询网格顶点是否已经被烘焙到世界坐标
|
||||||
|
*/
|
||||||
public void setBakedToWorld(boolean baked) {
|
public void setBakedToWorld(boolean baked) {
|
||||||
this.bakedToWorld = baked;
|
this.bakedToWorld = baked;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,16 @@ import com.chuangzhou.vivid2D.render.model.Model2D;
|
|||||||
import com.chuangzhou.vivid2D.render.model.ModelPart;
|
import com.chuangzhou.vivid2D.render.model.ModelPart;
|
||||||
import org.joml.Vector2f;
|
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;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2D物理系统,用于处理模型的物理模拟
|
* 2D物理系统,用于处理模型的物理模拟
|
||||||
* 支持弹簧系统、碰撞检测、重力等物理效果
|
* 支持弹簧系统、碰撞检测、重力等物理效果
|
||||||
*
|
* <p>
|
||||||
* 调整点:
|
* 调整点:
|
||||||
* - 使用半隐式(symplectic)Euler 积分,替代之前的纯 Verlet(更稳定且直观)
|
* - 使用半隐式(symplectic)Euler 积分,替代之前的纯 Verlet(更稳定且直观)
|
||||||
* - 在约束迭代后同步速度(根据位置变化计算),避免约束把位置推回后速度不一致导致僵化
|
* - 在约束迭代后同步速度(根据位置变化计算),避免约束把位置推回后速度不一致导致僵化
|
||||||
@@ -471,8 +474,7 @@ public class PhysicsSystem {
|
|||||||
private void applyToModel(Model2D model) {
|
private void applyToModel(Model2D model) {
|
||||||
for (PhysicsParticle particle : particles.values()) {
|
for (PhysicsParticle particle : particles.values()) {
|
||||||
Object userData = particle.getUserData();
|
Object userData = particle.getUserData();
|
||||||
if (userData instanceof ModelPart) {
|
if (userData instanceof ModelPart part) {
|
||||||
ModelPart part = (ModelPart) userData;
|
|
||||||
part.setPosition(particle.getPosition());
|
part.setPosition(particle.getPosition());
|
||||||
|
|
||||||
// 可选:根据速度设置旋转
|
// 可选:根据速度设置旋转
|
||||||
@@ -611,11 +613,8 @@ public class PhysicsSystem {
|
|||||||
Vector2f positionDelta = new Vector2f(particle.getPosition())
|
Vector2f positionDelta = new Vector2f(particle.getPosition())
|
||||||
.sub(particle.getPreviousPosition()); // 现在可以正常使用了
|
.sub(particle.getPreviousPosition()); // 现在可以正常使用了
|
||||||
float positionDeltaSquared = positionDelta.lengthSquared();
|
float positionDeltaSquared = positionDelta.lengthSquared();
|
||||||
if (positionDeltaSquared > 0.001f) { // 位置变化阈值,可调整
|
// 位置变化阈值,可调整
|
||||||
return true;
|
return positionDeltaSquared > 0.001f;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 检查是否有活跃的约束
|
// 检查是否有活跃的约束
|
||||||
@@ -731,31 +730,78 @@ public class PhysicsSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter/Setter 方法
|
// Getter/Setter 方法
|
||||||
public String getId() { return id; }
|
public String getId() {
|
||||||
public Vector2f getPosition() { return new Vector2f(position); }
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2f getPosition() {
|
||||||
|
return new Vector2f(position);
|
||||||
|
}
|
||||||
|
|
||||||
public void setPosition(Vector2f position) {
|
public void setPosition(Vector2f position) {
|
||||||
this.position.set(position);
|
this.position.set(position);
|
||||||
}
|
}
|
||||||
public Vector2f getVelocity() { return new Vector2f(velocity); }
|
|
||||||
|
public Vector2f getVelocity() {
|
||||||
|
return new Vector2f(velocity);
|
||||||
|
}
|
||||||
|
|
||||||
public void setVelocity(Vector2f velocity) {
|
public void setVelocity(Vector2f velocity) {
|
||||||
this.velocity.set(velocity);
|
this.velocity.set(velocity);
|
||||||
}
|
}
|
||||||
public Vector2f getAcceleration() { return new Vector2f(acceleration); }
|
|
||||||
|
public Vector2f getAcceleration() {
|
||||||
|
return new Vector2f(acceleration);
|
||||||
|
}
|
||||||
|
|
||||||
public float getMass() {
|
public float getMass() {
|
||||||
if (Float.isInfinite(mass)) return Float.POSITIVE_INFINITY;
|
if (Float.isInfinite(mass)) return Float.POSITIVE_INFINITY;
|
||||||
return mass;
|
return mass;
|
||||||
}
|
}
|
||||||
public float getInverseMass() { return inverseMass; }
|
|
||||||
public float getRadius() { return radius; }
|
public float getInverseMass() {
|
||||||
public void setRadius(float radius) { this.radius = radius; }
|
return inverseMass;
|
||||||
public boolean isMovable() { return movable; }
|
}
|
||||||
public void setMovable(boolean movable) { this.movable = movable; }
|
|
||||||
public boolean isAffectedByGravity() { return affectedByGravity; }
|
public float getRadius() {
|
||||||
public void setAffectedByGravity(boolean affectedByGravity) { this.affectedByGravity = affectedByGravity; }
|
return radius;
|
||||||
public Object getUserData() { return userData; }
|
}
|
||||||
public void setUserData(Object userData) { this.userData = userData; }
|
|
||||||
public boolean isAffectedByWind() { return affectedByWind; }
|
public void setRadius(float radius) {
|
||||||
public void setAffectedByWind(boolean affectedByWind) { this.affectedByWind = affectedByWind; }
|
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 方法
|
// Getter/Setter 方法
|
||||||
public String getId() { return id; }
|
public String getId() {
|
||||||
public PhysicsParticle getParticleA() { return particleA; }
|
return id;
|
||||||
public PhysicsParticle getParticleB() { return particleB; }
|
}
|
||||||
public float getRestLength() { return restLength; }
|
|
||||||
public float getStiffness() { return stiffness; }
|
public PhysicsParticle getParticleA() {
|
||||||
public float getDamping() { return damping; }
|
return particleA;
|
||||||
public boolean isEnabled() { return enabled; }
|
}
|
||||||
public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
|
||||||
|
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 {
|
public interface PhysicsConstraint {
|
||||||
void apply(float deltaTime);
|
void apply(float deltaTime);
|
||||||
|
|
||||||
PhysicsParticle getParticle();
|
PhysicsParticle getParticle();
|
||||||
|
|
||||||
boolean isEnabled();
|
boolean isEnabled();
|
||||||
|
|
||||||
void setEnabled(boolean enabled);
|
void setEnabled(boolean enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,13 +935,36 @@ public class PhysicsSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter/Setter 方法
|
// Getter/Setter 方法
|
||||||
@Override public PhysicsParticle getParticle() { return particle; }
|
@Override
|
||||||
@Override public boolean isEnabled() { return enabled; }
|
public PhysicsParticle getParticle() {
|
||||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
return particle;
|
||||||
public Vector2f getTargetPosition() { return new Vector2f(targetPosition); }
|
}
|
||||||
public void setTargetPosition(Vector2f targetPosition) { this.targetPosition.set(targetPosition); }
|
|
||||||
public float getStrength() { return strength; }
|
@Override
|
||||||
public void setStrength(float strength) { this.strength = Math.max(0.0f, Math.min(1.0f, strength)); }
|
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 方法
|
// Getter/Setter 方法
|
||||||
@Override public PhysicsParticle getParticle() { return particle; }
|
@Override
|
||||||
@Override public boolean isEnabled() { return enabled; }
|
public PhysicsParticle getParticle() {
|
||||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
return particle;
|
||||||
public PhysicsParticle getTarget() { return target; }
|
}
|
||||||
public float getMaxDistance() { return maxDistance; }
|
|
||||||
|
@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 {
|
public interface PhysicsCollider {
|
||||||
boolean collidesWith(PhysicsParticle particle);
|
boolean collidesWith(PhysicsParticle particle);
|
||||||
|
|
||||||
void resolveCollision(PhysicsParticle particle, float deltaTime);
|
void resolveCollision(PhysicsParticle particle, float deltaTime);
|
||||||
|
|
||||||
String getId();
|
String getId();
|
||||||
|
|
||||||
boolean isEnabled();
|
boolean isEnabled();
|
||||||
|
|
||||||
void setEnabled(boolean enabled);
|
void setEnabled(boolean enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -973,12 +1089,32 @@ public class PhysicsSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getter/Setter 方法
|
// Getter/Setter 方法
|
||||||
@Override public String getId() { return id; }
|
@Override
|
||||||
@Override public boolean isEnabled() { return enabled; }
|
public String getId() {
|
||||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
return id;
|
||||||
public Vector2f getCenter() { return new Vector2f(center); }
|
}
|
||||||
public void setCenter(Vector2f center) { this.center.set(center); }
|
|
||||||
public float getRadius() { return radius; }
|
@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 方法
|
// Getter/Setter 方法
|
||||||
@Override public String getId() { return id; }
|
@Override
|
||||||
@Override public boolean isEnabled() { return enabled; }
|
public String getId() {
|
||||||
@Override public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
return id;
|
||||||
public Vector2f getCenter() { return new Vector2f(center); }
|
}
|
||||||
public void setCenter(Vector2f center) { this.center.set(center); }
|
|
||||||
public float getWidth() { return width; }
|
@Override
|
||||||
public float getHeight() { return height; }
|
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 方法
|
// Getter 方法
|
||||||
public int getParticleCount() { return particleCount; }
|
public int getParticleCount() {
|
||||||
public int getSpringCount() { return springCount; }
|
return particleCount;
|
||||||
public int getConstraintCount() { return constraintCount; }
|
}
|
||||||
public int getColliderCount() { return colliderCount; }
|
|
||||||
public float getAverageUpdateTime() { return averageUpdateTime; }
|
public int getSpringCount() {
|
||||||
public int getTotalUpdates() { return totalUpdates; }
|
return springCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConstraintCount() {
|
||||||
|
return constraintCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColliderCount() {
|
||||||
|
return colliderCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAverageUpdateTime() {
|
||||||
|
return averageUpdateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalUpdates() {
|
||||||
|
return totalUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
package com.chuangzhou.vivid2D.render.model.util;
|
package com.chuangzhou.vivid2D.render.model.util;
|
||||||
|
|
||||||
import com.chuangzhou.vivid2D.render.systems.RenderSystem;
|
import com.chuangzhou.vivid2D.render.systems.RenderSystem;
|
||||||
import org.lwjgl.opengl.GL;
|
import org.lwjgl.opengl.*;
|
||||||
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.stb.STBImage;
|
import org.lwjgl.stb.STBImage;
|
||||||
import org.lwjgl.stb.STBImageWrite;
|
import org.lwjgl.stb.STBImageWrite;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
@@ -75,9 +70,17 @@ public class Texture {
|
|||||||
this.glFormat = glFormat;
|
this.glFormat = glFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getComponents() { return components; }
|
public int getComponents() {
|
||||||
public int getGLInternalFormat() { return glInternalFormat; }
|
return components;
|
||||||
public int getGLFormat() { return glFormat; }
|
}
|
||||||
|
|
||||||
|
public int getGLInternalFormat() {
|
||||||
|
return glInternalFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGLFormat() {
|
||||||
|
return glFormat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TextureType {
|
public enum TextureType {
|
||||||
@@ -95,7 +98,9 @@ public class Texture {
|
|||||||
this.glType = glType;
|
this.glType = glType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getGLType() { return glType; }
|
public int getGLType() {
|
||||||
|
return glType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TextureFilter {
|
public enum TextureFilter {
|
||||||
@@ -112,7 +117,9 @@ public class Texture {
|
|||||||
this.glFilter = glFilter;
|
this.glFilter = glFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getGLFilter() { return glFilter; }
|
public int getGLFilter() {
|
||||||
|
return glFilter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TextureWrap {
|
public enum TextureWrap {
|
||||||
@@ -127,7 +134,9 @@ public class Texture {
|
|||||||
this.glWrap = glWrap;
|
this.glWrap = glWrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getGLWrap() { return glWrap; }
|
public int getGLWrap() {
|
||||||
|
return glWrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== STB 图像加载 ====================
|
// ==================== STB 图像加载 ====================
|
||||||
@@ -244,7 +253,8 @@ public class Texture {
|
|||||||
// 恢复原先的 UNPACK_ALIGNMENT
|
// 恢复原先的 UNPACK_ALIGNMENT
|
||||||
try {
|
try {
|
||||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, prevUnpack);
|
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, prevUnpack);
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -869,10 +879,14 @@ public class Texture {
|
|||||||
*/
|
*/
|
||||||
public static TextureFormat getTextureFormat(int components) {
|
public static TextureFormat getTextureFormat(int components) {
|
||||||
switch (components) {
|
switch (components) {
|
||||||
case 1: return TextureFormat.RED;
|
case 1:
|
||||||
case 2: return TextureFormat.RG;
|
return TextureFormat.RED;
|
||||||
case 3: return TextureFormat.RGB;
|
case 2:
|
||||||
case 4: return TextureFormat.RGBA;
|
return TextureFormat.RG;
|
||||||
|
case 3:
|
||||||
|
return TextureFormat.RGB;
|
||||||
|
case 4:
|
||||||
|
return TextureFormat.RGBA;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unsupported number of components: " + components);
|
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) {
|
private String getGLErrorString(int error) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case GL11.GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
case GL11.GL_INVALID_ENUM:
|
||||||
case GL11.GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
return "GL_INVALID_ENUM";
|
||||||
case GL11.GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
case GL11.GL_INVALID_VALUE:
|
||||||
case GL11.GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
return "GL_INVALID_VALUE";
|
||||||
case GL11.GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
|
case GL11.GL_INVALID_OPERATION:
|
||||||
case GL11.GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
|
return "GL_INVALID_OPERATION";
|
||||||
default: return "Unknown Error (0x" + Integer.toHexString(error) + ")";
|
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 {
|
public final class RenderSystem {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(RenderSystem.class);
|
private static final Logger logger = LoggerFactory.getLogger(RenderSystem.class);
|
||||||
|
|
||||||
private RenderSystem() { /* no instances */ }
|
private RenderSystem() { /* no instances */ }
|
||||||
|
|
||||||
// ================== 线程管理 ==================
|
// ================== 线程管理 ==================
|
||||||
@@ -657,6 +658,7 @@ public final class RenderSystem {
|
|||||||
assertOnRenderThread();
|
assertOnRenderThread();
|
||||||
GL11.glLineWidth(width);
|
GL11.glLineWidth(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void drawElements(int mode, int count, int type, long indices) {
|
public static void drawElements(int mode, int count, int type, long indices) {
|
||||||
if (!isOnRenderThread()) {
|
if (!isOnRenderThread()) {
|
||||||
recordRenderCall(() -> _drawElements(mode, count, type, indices));
|
recordRenderCall(() -> _drawElements(mode, count, type, indices));
|
||||||
@@ -1206,6 +1208,7 @@ public final class RenderSystem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置着色器纹理
|
* 设置着色器纹理
|
||||||
|
*
|
||||||
* @param textureUnit 纹理单元 (0, 1, 2, ...)
|
* @param textureUnit 纹理单元 (0, 1, 2, ...)
|
||||||
* @param texture 纹理对象
|
* @param texture 纹理对象
|
||||||
*/
|
*/
|
||||||
@@ -1247,6 +1250,7 @@ public final class RenderSystem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置着色器纹理 - 接受纹理ID的版本
|
* 设置着色器纹理 - 接受纹理ID的版本
|
||||||
|
*
|
||||||
* @param textureUnit 纹理单元
|
* @param textureUnit 纹理单元
|
||||||
* @param textureId 纹理ID
|
* @param textureId 纹理ID
|
||||||
*/
|
*/
|
||||||
@@ -1433,6 +1437,7 @@ public final class RenderSystem {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void pixelStore(int pname, int param) {
|
public static void pixelStore(int pname, int param) {
|
||||||
if (!isOnRenderThread()) {
|
if (!isOnRenderThread()) {
|
||||||
recordRenderCall(() -> _pixelStore(pname, param));
|
recordRenderCall(() -> _pixelStore(pname, param));
|
||||||
@@ -1514,6 +1519,7 @@ public final class RenderSystem {
|
|||||||
logger.info("Max Texture Units: {}",
|
logger.info("Max Texture Units: {}",
|
||||||
GL11.glGetInteger(GL20.GL_MAX_TEXTURE_IMAGE_UNITS));
|
GL11.glGetInteger(GL20.GL_MAX_TEXTURE_IMAGE_UNITS));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setupDefaultState() {
|
public static void setupDefaultState() {
|
||||||
beginInitialization();
|
beginInitialization();
|
||||||
|
|
||||||
@@ -1559,17 +1565,22 @@ public final class RenderSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.error("OpenGL error during {}: {}\n{}",
|
logger.error("OpenGL error during {}: {}\n{}",
|
||||||
operation, getGLErrorString(error), stackTraceBuilder.toString());
|
operation, getGLErrorString(error), stackTraceBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getGLErrorString(int error) {
|
private static String getGLErrorString(int error) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case GL11.GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
case GL11.GL_INVALID_ENUM:
|
||||||
case GL11.GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
return "GL_INVALID_ENUM";
|
||||||
case GL11.GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
case GL11.GL_INVALID_VALUE:
|
||||||
case GL11.GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
return "GL_INVALID_VALUE";
|
||||||
default: return "Unknown (0x" + Integer.toHexString(error) + ")";
|
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;
|
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;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文本着色器
|
* 文本着色器
|
||||||
|
*
|
||||||
* @author tzdwindows 7
|
* @author tzdwindows 7
|
||||||
*/
|
*/
|
||||||
public class TextShader implements CompleteShader {
|
public class TextShader implements CompleteShader {
|
||||||
|
|
||||||
private final VertexShader vertexShader = new VertexShader();
|
private final VertexShader vertexShader = new VertexShader();
|
||||||
private final FragmentShader fragmentShader = new FragmentShader();
|
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) {
|
public void setColor(Vector4f color) {
|
||||||
this.color.set(color);
|
this.color.set(color);
|
||||||
|
|||||||
Reference in New Issue
Block a user