diff --git a/blender/plugin.py b/blender/plugin.py new file mode 100644 index 0000000..e8ec548 --- /dev/null +++ b/blender/plugin.py @@ -0,0 +1,62 @@ +import bpy +import bmesh +import socket +import json + +HOST = "localhost" +PORT = 51677 + +# Persistent global storage for knowing which meshes +# have already been sent to osci-render +bpy.context.scene.collection["osci_render"] = {} +col = bpy.context.scene.collection["osci_render"] +col["seen_objs"] = {} + +camera = bpy.context.scene.camera + + +def my_osci_render_func(scene): + engine_info = {"objects": []} + + for obj in bpy.data.objects: + if obj.type == 'MESH': + object_info = {"name": obj.name} + if obj.name not in col["seen_objs"]: + col["seen_objs"][obj.name] = 1 + print("new object! ", obj.name) + + mesh = bmesh.new() + mesh.from_mesh(obj.data) + + object_info["vertices"] = [] + # If there are bugs, the vertices here might not match up with the vert.index in edges + for vert in mesh.verts: + object_info["vertices"].append({ + "x": vert.co[0], + "y": vert.co[1], + "z": vert.co[2], + }) + + object_info["edges"] = [] + for edge in mesh.edges: + for vert in edge.verts: + object_info["edges"].append(vert.index) + + camera_space = camera.matrix_world.inverted() @ obj.matrix_world + object_info["matrix"] = [] + for i in range(4): + for j in range(4): + object_info["matrix"].append(camera_space[i][j]) + + engine_info["objects"].append(object_info) + + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((HOST, PORT)) + + sock.sendall(json.dumps(engine_info, separators=(',', ':')).encode('utf-8')) + sock.close() + + +bpy.app.handlers.frame_change_pre.clear() +bpy.app.handlers.frame_change_pre.append(my_osci_render_func) \ No newline at end of file diff --git a/pom.xml b/pom.xml index b38756e..ca2447b 100644 --- a/pom.xml +++ b/pom.xml @@ -170,6 +170,12 @@ aparapi 3.0.0 + + + com.google.code.gson + gson + 2.9.0 + diff --git a/src/main/java/sh/ball/engine/CameraDrawKernel.java b/src/main/java/sh/ball/engine/CameraDrawKernel.java index cec03fd..f9abfe5 100644 --- a/src/main/java/sh/ball/engine/CameraDrawKernel.java +++ b/src/main/java/sh/ball/engine/CameraDrawKernel.java @@ -8,9 +8,7 @@ import sh.ball.shapes.Shape; import sh.ball.shapes.Vector2; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.concurrent.ThreadLocalRandom; public class CameraDrawKernel extends Kernel { diff --git a/src/main/java/sh/ball/engine/ObjectServer.java b/src/main/java/sh/ball/engine/ObjectServer.java new file mode 100644 index 0000000..681f7fe --- /dev/null +++ b/src/main/java/sh/ball/engine/ObjectServer.java @@ -0,0 +1,65 @@ +package sh.ball.engine; + +import com.google.gson.Gson; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Arrays; + +public class ObjectServer implements Runnable { + + private static final int PORT = 51677; + private final Gson gson = new Gson(); + + @Override + public void run() { + try { + ServerSocket Server = new ServerSocket(PORT); + + while (true) { + System.out.println("Waiting for connection"); + Socket socket = Server.accept(); + BufferedReader clientReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String json = clientReader.readLine(); + System.out.println(json); + EngineInfo info = gson.fromJson(json, EngineInfo.class); + System.out.println(info); + socket.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static class EngineInfo { + private ObjectInfo[] objects; + + @Override + public String toString() { + return "EngineInfo{" + + "objects=" + Arrays.toString(objects) + + '}'; + } + } + + private static class ObjectInfo { + private String name; + private Vector3[] vertices; + private int[] edges; + // Camera space matrix + private float[] matrix; + + @Override + public String toString() { + return "ObjectInfo{" + + "name='" + name + '\'' + + ", vertices=" + Arrays.toString(vertices) + + ", edges=" + Arrays.toString(edges) + + ", matrix=" + Arrays.toString(matrix) + + '}'; + } + } +} diff --git a/src/main/java/sh/ball/engine/WorldObject.java b/src/main/java/sh/ball/engine/WorldObject.java index c64b465..b92968e 100644 --- a/src/main/java/sh/ball/engine/WorldObject.java +++ b/src/main/java/sh/ball/engine/WorldObject.java @@ -24,6 +24,15 @@ public class WorldObject { private Vector3 rotation; private boolean hideEdges = false; + private WorldObject(Vector3[] vertices, int[] edgeIndices) { + objVertices = Arrays.stream(vertices).toList(); + Set edges = new HashSet<>(); + for (int i = 0; i < edgeIndices.length; i += 2) { + edges.add(new Line3D(vertices[i], vertices[i + 1])); + } + getDrawPath(edges); + } + private WorldObject(List objVertices, List> vertexPath, Vector3 position, Vector3 rotation) { this.objVertices = objVertices; diff --git a/src/main/java/sh/ball/gui/controller/MainController.java b/src/main/java/sh/ball/gui/controller/MainController.java index a772b2a..906fcba 100644 --- a/src/main/java/sh/ball/gui/controller/MainController.java +++ b/src/main/java/sh/ball/gui/controller/MainController.java @@ -48,6 +48,7 @@ import sh.ball.audio.engine.AudioInputListener; import sh.ball.audio.engine.JavaAudioInput; import sh.ball.audio.midi.MidiListener; import sh.ball.audio.midi.MidiNote; +import sh.ball.engine.ObjectServer; import sh.ball.gui.Gui; import sh.ball.parser.obj.ObjFrameSettings; import sh.ball.parser.obj.ObjParser; @@ -450,6 +451,8 @@ public class MainController implements Initializable, FrequencyListener, MidiLis } } } + + new Thread(new ObjectServer()).start(); } // used when a file is chosen so that the same folder is reopened when a