|
@@ -0,0 +1,107 @@
|
|
|
|
+package xyz.tbvns.GeometryDash;
|
|
|
|
+
|
|
|
|
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
|
|
|
|
+import com.badlogic.gdx.math.Vector3;
|
|
|
|
+import org.joml.Matrix4d;
|
|
|
|
+import org.joml.Vector3d;
|
|
|
|
+import org.joml.Vector4d;
|
|
|
|
+import org.joml.Vector4f;
|
|
|
|
+import xyz.tbvns.Editor.ModelsManager;
|
|
|
|
+import xyz.tbvns.GDConstant;
|
|
|
|
+import xyz.tbvns.LevelInfo;
|
|
|
|
+import xyz.tbvns.LevelStringBuilder;
|
|
|
|
+import xyz.tbvns.Models.Face;
|
|
|
|
+import xyz.tbvns.Models.GDInstance;
|
|
|
|
+import xyz.tbvns.Models.GDModel;
|
|
|
|
+
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.List;
|
|
|
|
+
|
|
|
|
+import static xyz.tbvns.GDConstant.*;
|
|
|
|
+
|
|
|
|
+public class Render {
|
|
|
|
+ public double currentPercent;
|
|
|
|
+ public double currentDistance;
|
|
|
|
+ public HashMap<GDInstance, Integer> animationToCurrentframe = new HashMap<>();
|
|
|
|
+ public String fullRender(double fps) {
|
|
|
|
+ LevelStringBuilder builder = new LevelStringBuilder(LevelInfo.getLevelString(), 10); //TODO: make the editor layer configurable
|
|
|
|
+ while (currentPercent <= 1) {
|
|
|
|
+ double speed = LevelInfo.getLevel().getSpeedAt((float) currentPercent);
|
|
|
|
+ double distancePerFrame = (speed / fps);
|
|
|
|
+ currentPercent += distancePerFrame;
|
|
|
|
+ double realDistancePerFrame = (speed / fps) / 30;
|
|
|
|
+ double distancePerFramePercent = realDistancePerFrame / LevelInfo.getLevel().getMaxPos();
|
|
|
|
+ currentPercent += distancePerFramePercent;
|
|
|
|
+
|
|
|
|
+ Matrix4d camera = new Matrix4d();
|
|
|
|
+ camera.perspective(Math.toRadians(2), (double) 16/9, 0.001, 1000);
|
|
|
|
+ Vector3d cameraTranslation = new Vector3d(realDistancePerFrame * currentPercent, 5, 10);
|
|
|
|
+ camera.translation(cameraTranslation); //TODO: make that follow a new camera path editor
|
|
|
|
+ builder.add(1, 1, X_PROPERTY_ID, projectPoint(camera, new Vector4f((float) cameraTranslation.x, (float) cameraTranslation.y, (float) cameraTranslation.z, 0)).x, projectPoint(camera, new Vector4f((float) cameraTranslation.x, (float) cameraTranslation.y, (float) cameraTranslation.z, 0)).y);
|
|
|
|
+
|
|
|
|
+ for (ModelInstance model : ModelsManager.getLoadedModels()) {
|
|
|
|
+ GDInstance instance = (GDInstance) model.userData;
|
|
|
|
+ if (instance.isAnimation()) {
|
|
|
|
+ //TODO: the code under here will cause issue with the first frame being drawn at the start of the level but not the others
|
|
|
|
+ int frame = instance.getFrameOnPercent(currentPercent);
|
|
|
|
+ if (animationToCurrentframe.containsKey(instance) && animationToCurrentframe.get(instance) != frame) {
|
|
|
|
+ animationToCurrentframe.put(instance, frame);
|
|
|
|
+ GDModel gdModel = instance.getAnimationObject().getFrames().get(frame);
|
|
|
|
+ for (Face face : gdModel.getFaces()) {
|
|
|
|
+ for (Vector4f point : face.points) {
|
|
|
|
+ Vector3 translation = instance.getInstance().transform.getTranslation(Vector3.Zero);
|
|
|
|
+ point = point.add(translation.x, translation.y, translation.z, 0);
|
|
|
|
+ Vector4d projected = projectPoint(camera, point);
|
|
|
|
+ builder.add(1, POINT_OBJECT_ID, X_PROPERTY_ID, projected.x, Y_PROPERTY_ID, projected.y);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ animationToCurrentframe.put(instance, frame);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ GDModel gdModel = instance.getGdModel();
|
|
|
|
+ for (Face face : gdModel.getFaces()) {
|
|
|
|
+ for (Vector4f point : face.points) {
|
|
|
|
+ Vector3 translation = instance.getInstance().transform.getTranslation(Vector3.Zero);
|
|
|
|
+ point = point.add(translation.x, translation.y, translation.z, 0);
|
|
|
|
+ Vector4d projected = projectPoint(camera, point);
|
|
|
|
+ builder.add(1, POINT_OBJECT_ID, X_PROPERTY_ID, projected.x, Y_PROPERTY_ID, projected.y);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return builder.getLevelString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public Vector4d projectPoint(Matrix4d camera, Vector4f input) {
|
|
|
|
+ Vector4d point = camera.transform(new Vector4d(input.x, input.y, input.z, input.w));
|
|
|
|
+
|
|
|
|
+ point.x = (float) (point.x / point.w);
|
|
|
|
+ point.y = (float) (point.y / point.w);
|
|
|
|
+ point.z = (float) (point.z / point.w);
|
|
|
|
+
|
|
|
|
+ return point;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static float getZ(Face face) {
|
|
|
|
+ //TODO: REDO ALL OF THIS WITH MY SAVIOUR "JOML" !
|
|
|
|
+ //d = √[(x2 − x1)2 + (y2 − y1)2 + (z2 − z1)2]
|
|
|
|
+ List<Double> dist = new ArrayList<>();
|
|
|
|
+
|
|
|
|
+ face.points.forEach(p -> {
|
|
|
|
+ dist.add((double) p.w);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ double temp = 0;
|
|
|
|
+
|
|
|
|
+ for (Double d : dist) {
|
|
|
|
+ temp += d;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ temp = temp / dist.size();
|
|
|
|
+
|
|
|
|
+ return (float) temp;
|
|
|
|
+ }
|
|
|
|
+}
|