Bladeren bron

I'm never doing shaders again
Added outline on selected object + added raycast to select object + fixed the way models where added
This took way too long

____tbvns____ 6 maanden geleden
bovenliggende
commit
9d77319b8e

+ 19 - 11
PowerGDEditor/pom.xml

@@ -25,26 +25,33 @@
     </repositories>
 
     <dependencies>
+        <!-- LibGDX -->
         <dependency>
             <groupId>com.badlogicgames.gdx</groupId>
             <artifactId>gdx</artifactId>
-            <version>1.12.1</version>
+            <version>1.13.0</version>
         </dependency>
         <dependency>
             <groupId>com.badlogicgames.gdx</groupId>
             <artifactId>gdx-backend-lwjgl3</artifactId>
-            <version>1.12.1</version>
+            <version>1.13.0</version>
         </dependency>
         <dependency>
             <groupId>com.badlogicgames.gdx</groupId>
             <artifactId>gdx-platform</artifactId>
-            <version>1.12.1</version>
+            <version>1.13.0</version>
             <classifier>natives-desktop</classifier>
         </dependency>
         <dependency>
             <groupId>com.badlogicgames.gdx</groupId>
-            <artifactId>gdx-backend-headless</artifactId>
-            <version>1.12.1</version>
+            <artifactId>gdx-bullet</artifactId>
+            <version>1.13.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.badlogicgames.gdx</groupId>
+            <artifactId>gdx-bullet-platform</artifactId>
+            <version>1.13.0</version>
+            <classifier>natives-desktop</classifier>
         </dependency>
         <!-- ImGUI -->
         <dependency>
@@ -72,17 +79,12 @@
             <artifactId>imgui-java-natives-macos</artifactId>
             <version>1.86.11</version>
         </dependency>
-        <dependency>
-            <groupId>xyz.tbvns</groupId>
-            <artifactId>GD4J</artifactId>
-            <version>1.0-ALPHA</version>
-        </dependency>
+        <!--Others -->
         <dependency>
             <groupId>tv.wunderbox</groupId>
             <artifactId>nativefiledialog</artifactId>
             <version>1.0.3</version>
         </dependency>
-        <!-- https://mvnrepository.com/artifact/org.lwjgl/lwjgl-tinyfd -->
         <dependency>
             <groupId>org.lwjgl</groupId>
             <artifactId>lwjgl-tinyfd</artifactId>
@@ -106,6 +108,12 @@
             <classifier>natives-macos</classifier>
             <version>3.3.4</version>
         </dependency>
+        <!-- GD4J -->
+        <dependency>
+            <groupId>xyz.tbvns</groupId>
+            <artifactId>GD4J</artifactId>
+            <version>1.0-ALPHA</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 14 - 0
PowerGDEditor/src/main/java/xyz/tbvns/Editor/ModelsManager.java

@@ -1,10 +1,12 @@
 package xyz.tbvns.Editor;
 
 import com.badlogic.gdx.graphics.g3d.Model;
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
 import lombok.Getter;
 import xyz.tbvns.Models.Animation;
 import xyz.tbvns.Models.GDModel;
 import xyz.tbvns.Models.OBJReader;
+import xyz.tbvns.Physics.BulletManager;
 
 import javax.swing.*;
 import java.awt.*;
@@ -19,6 +21,10 @@ public class ModelsManager {
 
     @Getter
     private static Model selectedModel;
+    @Getter
+    private static ModelInstance selectedModelInstance;
+    @Getter
+    private static List<ModelInstance> loadedModels = new ArrayList<>();
 
     public static void addAnimated(File folder) throws FileNotFoundException {
         List<File> OBJs = new ArrayList<>();
@@ -58,5 +64,13 @@ public class ModelsManager {
 
     public static void select(Model model) {
         selectedModel = model;
+        selectedModelInstance = new ModelInstance(model);
+        BulletManager.addModel(selectedModelInstance);
+        loadedModels.add(selectedModelInstance);
+    }
+
+    public static void select(ModelInstance model) {
+        selectedModelInstance = model;
+        selectedModel = model.model;
     }
 }

+ 30 - 0
PowerGDEditor/src/main/java/xyz/tbvns/Inputs/inputManager.java

@@ -4,7 +4,13 @@ import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.Input;
 import com.badlogic.gdx.graphics.Camera;
 import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
+import com.badlogic.gdx.math.Octree;
 import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.math.collision.Ray;
+import com.badlogic.gdx.physics.bullet.collision.btCollisionObject;
+import xyz.tbvns.Editor.ModelsManager;
+import xyz.tbvns.Main;
+import xyz.tbvns.Physics.BulletManager;
 
 public class inputManager extends CameraInputController {
     private float startX, startY;
@@ -60,4 +66,28 @@ public class inputManager extends CameraInputController {
 
         return super.touchUp(screenX, screenY, pointer, button);
     }
+
+    @Override
+    public boolean touchDown(float x, float y, int pointer, int button) {
+        x-=100;
+        y+=100;
+        Vector3 unprojected = Main.getCamera().unproject(new Vector3(x, y, 0));
+        Vector3 pos = Main.getCamera().position;
+
+        float x3 = unprojected.x + (unprojected.x - pos.x) * 10000;
+        float y3 = unprojected.y + (unprojected.y - pos.y) * 10000;
+        float z3 = unprojected.z + (unprojected.z - pos.z) * 10000;
+
+        btCollisionObject object = BulletManager.raycast(pos, new Vector3(x3, y3, z3));
+        if (object != null) {
+            BulletManager.getModelCollisiontHashMap().forEach((k, v) -> {
+                if (v == object) {
+                    System.out.println(true);
+                    ModelsManager.select(k);
+                }
+            });
+        }
+
+        return super.touchDown(x, y, pointer, button);
+    }
 }

+ 22 - 5
PowerGDEditor/src/main/java/xyz/tbvns/Main.java

@@ -8,15 +8,21 @@ import com.badlogic.gdx.graphics.GL20;
 import com.badlogic.gdx.graphics.PerspectiveCamera;
 import com.badlogic.gdx.graphics.g3d.*;
 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
+import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader;
 import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
 import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.physics.bullet.Bullet;
 import com.badlogic.gdx.utils.viewport.Viewport;
+import lombok.Getter;
 import org.lwjgl.opengl.GL11;
 import xyz.tbvns.Editor.ModelsManager;
 import xyz.tbvns.Inputs.Shortcut;
 import xyz.tbvns.Inputs.inputManager;
 import xyz.tbvns.LWJGL3.CustomViewport;
 import xyz.tbvns.Managers.TexturesManager;
+import xyz.tbvns.Models.GDModel;
+import xyz.tbvns.Models.Shaders;
+import xyz.tbvns.Physics.BulletManager;
 import xyz.tbvns.ui.UIManager;
 import xyz.tbvns.ui.Ui;
 import xyz.tbvns.ui.Windows.LevelSelector;
@@ -26,7 +32,7 @@ import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
 /** {@link com.badlogic.gdx.ApplicationListener} implementation shared by all platforms. */
 public class Main extends ApplicationAdapter {
     private ModelBatch batch;
-    private Camera camera;
+    @Getter static private Camera camera;
     private Model worldGrid;
     private Model levelGrid;
     private ModelInstance worldGridInstance;
@@ -39,6 +45,8 @@ public class Main extends ApplicationAdapter {
     @Override
     public void create() {
         Setup.run();
+        Bullet.init();
+        BulletManager.innit();
         Ui.initImGui();
         UIManager.loadUi();
         UIManager.getActiveUI().put(LevelSelector.class, true);
@@ -51,6 +59,7 @@ public class Main extends ApplicationAdapter {
 
         Gdx.gl.glEnable(GL11.GL_BLEND);
         Gdx.gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+        Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
 
         ModelBuilder builder = new ModelBuilder();
 
@@ -68,6 +77,8 @@ public class Main extends ApplicationAdapter {
 
     @Override
     public void render() {
+        BulletManager.update();
+
         Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
         Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT | (Gdx.graphics.getBufferFormat().coverageSampling ? GL20.GL_COVERAGE_BUFFER_BIT_NV : 0));
@@ -76,6 +87,7 @@ public class Main extends ApplicationAdapter {
         viewport.setScreenPosition(200, 200);
         viewport.update(Gdx.graphics.getWidth() - 200, Gdx.graphics.getHeight(), false);
 
+        //TODO: move grid rendering elsewhere
         Vector3 gridPos = new Vector3(camera.position);
         gridPos.x = Math.round(gridPos.x);
         gridPos.y = -0.01f;
@@ -90,17 +102,22 @@ public class Main extends ApplicationAdapter {
 
         levelGridInstance.transform.setTranslation(gridPos);
 
-//        cameraInputController.update();
         batch.begin(camera);
         if (modelCache != null) {
             batch.render(modelCache);
         }
-        if (ModelsManager.getSelectedModel() != null) {
-            batch.render(new ModelInstance(ModelsManager.getSelectedModel()));
-        }
         batch.render(worldGridInstance);
         batch.render(levelGridInstance);
+        for (ModelInstance model : ModelsManager.getLoadedModels()) {
+            if (ModelsManager.getSelectedModelInstance() == model) {
+                Shaders.renderOutline(model);
+            }
+        }
+        for (ModelInstance model : ModelsManager.getLoadedModels()) {
+            batch.render(model);
+        }
         batch.end();
+
         Ui.render();
         Shortcut.check();
     }

+ 2 - 1
PowerGDEditor/src/main/java/xyz/tbvns/Models/Animation.java

@@ -18,8 +18,9 @@ public class Animation implements Renderable {
         ImGui.separator();
         ImGui.text(name);
         ImGui.text("Frames:" + frames.size());
-        if (ImGui.button("Select")) {
+        if (ImGui.button("Add " + name)) {
             ModelsManager.select(frames.get(0).toModel());
+            System.out.println(name);
         }
     }
 }

+ 9 - 1
PowerGDEditor/src/main/java/xyz/tbvns/Models/GDModel.java

@@ -51,7 +51,15 @@ public class GDModel implements Renderable {
                 );
 
             } else {
-                throw new RuntimeException("Triangles are not yet supported !");
+                meshBuilder.setColor(face.color.getRed(), face.color.getGreen(), face.color.getBlue(), face.color.getAlpha());
+                meshBuilder.triangle(
+                        new Vector3(face.points.get(0).x, face.points.get(0).y, face.points.get(0).z),
+                        Color.BLACK,
+                        new Vector3(face.points.get(1).x, face.points.get(1).y, face.points.get(1).z),
+                        Color.BLACK,
+                        new Vector3(face.points.get(2).x, face.points.get(2).y, face.points.get(2).z),
+                        Color.BLACK
+                );
             }
         }
         return builder.end();

+ 61 - 0
PowerGDEditor/src/main/java/xyz/tbvns/Models/Shaders.java

@@ -0,0 +1,61 @@
+package xyz.tbvns.Models;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Mesh;
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
+import com.badlogic.gdx.graphics.g3d.model.Node;
+import com.badlogic.gdx.graphics.g3d.model.NodePart;
+import com.badlogic.gdx.graphics.glutils.ShaderProgram;
+import com.badlogic.gdx.utils.GdxRuntimeException;
+import org.apache.commons.codec.Resources;
+import xyz.tbvns.Main;
+
+import java.io.IOException;
+
+public class Shaders {
+    public static final ShaderProgram outlineShader;
+
+    static {
+        try {
+            outlineShader = new ShaderProgram(
+                    new String(Resources.getInputStream("shaders/outline.vs.glsl").readAllBytes()),
+                    new String(Resources.getInputStream("shaders/outline.fs.glsl").readAllBytes())
+            );
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        if(!outlineShader.isCompiled())
+            throw new GdxRuntimeException("Outline Shader failed: " + outlineShader.getLog());
+    }
+
+    public static void renderOutline(ModelInstance instance) {
+        // Enable face culling (front-face culling to show only backfaces)
+        Gdx.gl.glEnable(GL20.GL_CULL_FACE);
+        Gdx.gl.glCullFace(GL20.GL_FRONT);  // Cull front faces to render only the back
+
+        // Bind the outline shader
+        outlineShader.bind();
+
+        // Set shader uniforms
+        outlineShader.setUniformMatrix("u_projTrans", Main.getCamera().combined);
+        outlineShader.setUniformf("u_outlineThickness", 0.02f);  // Adjust this for outline thickness
+        outlineShader.setUniformf("u_outlineColor", new Color(1f, 0.5f, 0, 0));  // Outline color
+
+        // Render the modelInstance with the outline shader
+        for (Node node : instance.nodes) {
+            if (node.parts.size > 0) {
+                for (NodePart part : node.parts) {
+                    Mesh mesh = part.meshPart.mesh;
+                    mesh.bind(outlineShader);
+                    mesh.render(outlineShader, part.meshPart.primitiveType);
+                    mesh.unbind(outlineShader);
+                }
+            }
+        }
+
+        // Disable face culling after rendering
+        Gdx.gl.glDisable(GL20.GL_CULL_FACE);
+    }
+}

+ 98 - 0
PowerGDEditor/src/main/java/xyz/tbvns/Physics/BulletManager.java

@@ -0,0 +1,98 @@
+package xyz.tbvns.Physics;
+
+import com.badlogic.gdx.graphics.g3d.ModelInstance;
+import com.badlogic.gdx.math.Vector3;
+import com.badlogic.gdx.physics.bullet.Bullet;
+import com.badlogic.gdx.physics.bullet.DebugDrawer;
+import com.badlogic.gdx.physics.bullet.collision.*;
+import com.badlogic.gdx.physics.bullet.dynamics.btConstraintSolver;
+import com.badlogic.gdx.physics.bullet.dynamics.btDiscreteDynamicsWorld;
+import com.badlogic.gdx.physics.bullet.dynamics.btDynamicsWorld;
+import com.badlogic.gdx.physics.bullet.dynamics.btSequentialImpulseConstraintSolver;
+import lombok.Getter;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class BulletManager {
+    private static btDynamicsWorld dynamicsWorld;
+    private static btConstraintSolver constraintSolver;
+    private static btDefaultCollisionConfiguration collisionConfig;
+    private static btCollisionDispatcher dispatcher;
+    private static btDbvtBroadphase broadphase;
+    private static RayResultCallback rayResultCallback;
+
+    static public DebugDrawer debugDrawer;
+
+    @Getter private static List<btCollisionObject> objects = new ArrayList<>();
+    @Getter private static List<btCollisionShape> shapes = new ArrayList<>();
+    @Getter private static HashMap<ModelInstance, btCollisionObject> modelCollisiontHashMap = new HashMap<>();
+
+    public static void innit() {
+        collisionConfig = new btDefaultCollisionConfiguration();
+        dispatcher = new btCollisionDispatcher(collisionConfig);
+        broadphase = new btDbvtBroadphase();
+        constraintSolver = new btSequentialImpulseConstraintSolver();
+        dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, constraintSolver, collisionConfig);
+        dynamicsWorld.setGravity(new Vector3(0, -20f, 0));
+    }
+
+    public static void update() {
+        modelCollisiontHashMap.forEach((i, o) -> {
+            o.setWorldTransform(i.transform);
+        });
+    }
+
+    public static btCollisionObject addModel(ModelInstance instance) {
+        btCollisionShape shape = Bullet.obtainStaticNodeShape(instance.model.nodes);
+        btCollisionObject collisionObject = new btCollisionObject();
+        collisionObject.setCollisionShape(shape);
+        collisionObject.setWorldTransform(instance.transform);
+        dynamicsWorld.addCollisionObject(collisionObject);
+        objects.add(collisionObject);
+        shapes.add(shape);
+        modelCollisiontHashMap.put(instance, collisionObject);
+        return collisionObject;
+    }
+
+    public static void removeModel(ModelInstance instance) {
+        btCollisionObject object = modelCollisiontHashMap.get(instance);
+        dynamicsWorld.removeCollisionObject(object);
+        objects.remove(object);
+        shapes.remove(object.getCollisionShape());
+        modelCollisiontHashMap.remove(instance);
+        object.getCollisionShape().dispose();
+        object.dispose();
+    }
+
+    @Nullable
+    public static btCollisionObject raycast(Vector3 start, Vector3 end) {
+        rayResultCallback = new ClosestRayResultCallback(start, end);
+        dynamicsWorld.rayTest(start, end, rayResultCallback);
+        return rayResultCallback.getCollisionObject();
+    }
+
+    public static void dispose() {
+        for (btCollisionObject collisionObject : objects) {
+            collisionObject.dispose();
+        }
+        objects.clear();
+
+        for (btCollisionShape shape : shapes) {
+            shape.dispose();
+        }
+        shapes.clear();
+
+        modelCollisiontHashMap.clear();
+
+        dynamicsWorld.dispose();
+        constraintSolver.dispose();
+        collisionConfig.dispose();
+        dispatcher.dispose();
+        broadphase.dispose();
+        debugDrawer.dispose();
+        rayResultCallback.dispose();
+    }
+}

+ 9 - 0
PowerGDEditor/src/main/resources/shaders/outline.fs.glsl

@@ -0,0 +1,9 @@
+#version 330 core
+
+uniform vec4 u_outlineColor;  // Outline color
+
+out vec4 FragColor;  // Final fragment color
+
+void main() {
+	FragColor = u_outlineColor;  // Solid outline color
+}

+ 13 - 0
PowerGDEditor/src/main/resources/shaders/outline.vs.glsl

@@ -0,0 +1,13 @@
+#version 330 core
+
+uniform mat4 u_projTrans;  // Projection-view transformation matrix
+uniform float u_outlineThickness;  // Thickness of the outline
+
+in vec3 a_position;  // Vertex position
+in vec3 a_normal;    // Vertex normal
+
+void main() {
+    // Slightly push the vertices along their normals to "expand" the model for the outline
+    vec3 scaledPosition = a_position + a_normal * u_outlineThickness;
+    gl_Position = u_projTrans * vec4(scaledPosition, 0.9);
+}