kopia lustrzana https://github.com/jameshball/osci-render
Create blender plugin and support gpencil
rodzic
5b4c94a5bc
commit
d0746cebcf
|
@ -0,0 +1,206 @@
|
||||||
|
bl_info = {
|
||||||
|
"name": "osci-render",
|
||||||
|
"author": "James Ball",
|
||||||
|
"version": (1, 0, 0),
|
||||||
|
"blender": (3, 1, 2),
|
||||||
|
"location": "View3D",
|
||||||
|
"description": "Addon to send frames over to osci-render",
|
||||||
|
"warning": "Requires a camera and objects",
|
||||||
|
"wiki_url": "https://github.com/jameshball/osci-render",
|
||||||
|
"category": "Development",
|
||||||
|
}
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import bmesh
|
||||||
|
import socket
|
||||||
|
import json
|
||||||
|
|
||||||
|
HOST = "localhost"
|
||||||
|
PORT = 51677
|
||||||
|
|
||||||
|
sock = None
|
||||||
|
|
||||||
|
|
||||||
|
class OBJECT_PT_osci_render_settings(bpy.types.Panel):
|
||||||
|
bl_idname = "OBJECT_PT_osci_render_settings"
|
||||||
|
bl_label = "osci-render settings"
|
||||||
|
bl_space_type = "PROPERTIES"
|
||||||
|
bl_region_type = "WINDOW"
|
||||||
|
bl_context = "render"
|
||||||
|
|
||||||
|
def draw_header(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
global sock
|
||||||
|
if sock is None:
|
||||||
|
self.layout.operator("render.osci_render_connect", text="Connect to osci-render")
|
||||||
|
else:
|
||||||
|
self.layout.operator("render.osci_render_close", text="Close osci-render connection")
|
||||||
|
|
||||||
|
|
||||||
|
class osci_render_connect(bpy.types.Operator):
|
||||||
|
bl_label = "Connect to osci-render"
|
||||||
|
bl_idname = "render.osci_render_connect"
|
||||||
|
bl_description = "Connect to osci-render"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
global sock
|
||||||
|
if sock is None:
|
||||||
|
try:
|
||||||
|
bpy.context.scene.collection["osci_render"] = {}
|
||||||
|
bpy.context.scene.collection["osci_render"]["seen_objs"] = {}
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
sock.connect((HOST, PORT))
|
||||||
|
send_scene_to_osci_render(bpy.context.scene)
|
||||||
|
except OSError as exp:
|
||||||
|
sock.close()
|
||||||
|
sock = None
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
class osci_render_close(bpy.types.Operator):
|
||||||
|
bl_label = "Close osci-render connection"
|
||||||
|
bl_idname="render.osci_render_close"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
global sock
|
||||||
|
if sock is not None:
|
||||||
|
sock.send("CLOSE\n".encode('utf-8'))
|
||||||
|
sock.close()
|
||||||
|
sock = None
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
def is_cyclic(spline):
|
||||||
|
return spline.use_cyclic_u or spline.use_cyclic_v
|
||||||
|
|
||||||
|
|
||||||
|
def append_matrix(object_info, obj):
|
||||||
|
camera_space = bpy.context.scene.camera.matrix_world.inverted() @ obj.matrix_world
|
||||||
|
object_info["matrix"] = [camera_space[i][j] for i in range(4) for j in range(4)]
|
||||||
|
return object_info
|
||||||
|
|
||||||
|
|
||||||
|
def send_scene_to_osci_render(scene):
|
||||||
|
col = bpy.context.scene.collection["osci_render"]
|
||||||
|
|
||||||
|
if sock is not None:
|
||||||
|
engine_info = {"objects": []}
|
||||||
|
new_objs = []
|
||||||
|
|
||||||
|
for obj in bpy.data.objects:
|
||||||
|
if obj.visible_get():
|
||||||
|
# if obj.type == 'MESH':
|
||||||
|
# object_info = {"name": obj.name}
|
||||||
|
# if obj.name not in col["seen_objs"]:
|
||||||
|
# col["seen_objs"][obj.name] = 1
|
||||||
|
# new_objs.append(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/faces
|
||||||
|
# for vert in mesh.verts:
|
||||||
|
# object_info["vertices"].append({
|
||||||
|
# "x": vert.co[0],
|
||||||
|
# "y": vert.co[1],
|
||||||
|
# "z": vert.co[2],
|
||||||
|
# })
|
||||||
|
|
||||||
|
# object_info["edges"] = [vert.index for edge in mesh.edges for vert in edge.verts]
|
||||||
|
# object_info["faces"] = [[vert.index for vert in face.verts] for face in mesh.faces]
|
||||||
|
|
||||||
|
# engine_info["objects"].append(append_matrix(object_info, obj))
|
||||||
|
if obj.type == 'GPENCIL':
|
||||||
|
object_info = {"name": obj.name}
|
||||||
|
strokes = obj.data.layers.active.frames.data.active_frame.strokes
|
||||||
|
|
||||||
|
print("found gpencil!")
|
||||||
|
print(strokes)
|
||||||
|
|
||||||
|
|
||||||
|
object_info["pathVertices"] = []
|
||||||
|
for stroke in strokes:
|
||||||
|
for vert in stroke.points:
|
||||||
|
object_info["pathVertices"].append({
|
||||||
|
"x": vert.co[0],
|
||||||
|
"y": vert.co[1],
|
||||||
|
"z": vert.co[2],
|
||||||
|
})
|
||||||
|
# end of path
|
||||||
|
object_info["pathVertices"].append({
|
||||||
|
"x": float("nan"),
|
||||||
|
"y": float("nan"),
|
||||||
|
"z": float("nan"),
|
||||||
|
})
|
||||||
|
|
||||||
|
engine_info["objects"].append(append_matrix(object_info, obj))
|
||||||
|
# elif obj.type == 'CURVE':
|
||||||
|
# object_info = {"name": obj.name}
|
||||||
|
# for curve in obj.data.splines:
|
||||||
|
# if curve.type == 'BEZIER':
|
||||||
|
# object_info["bezierPoints"] = []
|
||||||
|
# points = list(curve.bezier_points)
|
||||||
|
# if is_cyclic(curve) and len(points) > 0:
|
||||||
|
# points.append(points[0])
|
||||||
|
#
|
||||||
|
# for point in points:
|
||||||
|
# for co in [point.co, point.handle_left, point.handle_right]:
|
||||||
|
# object_info["bezierPoints"].append({
|
||||||
|
# "x": co[0],
|
||||||
|
# "y": co[1],
|
||||||
|
# "z": co[2],
|
||||||
|
# })
|
||||||
|
#
|
||||||
|
# engine_info["objects"].append(append_matrix(object_info, obj))
|
||||||
|
# elif curve.type == 'POLY':
|
||||||
|
# object_info["polyPoints"] = []
|
||||||
|
# points = list(curve.points)
|
||||||
|
# if is_cyclic(curve) and len(points) > 0:
|
||||||
|
# points.append(points[0])
|
||||||
|
#
|
||||||
|
# object_info["polyPoints"] = [{
|
||||||
|
# "x": point.co[0],
|
||||||
|
# "y": point.co[1],
|
||||||
|
# "z": point.co[2],
|
||||||
|
# } for point in points]
|
||||||
|
#
|
||||||
|
# engine_info["objects"].append(append_matrix(object_info, obj))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
engine_info["focalLength"] = -0.1 * bpy.data.cameras[0].lens
|
||||||
|
|
||||||
|
try:
|
||||||
|
json_str = json.dumps(engine_info, separators=(',', ':')) + '\n'
|
||||||
|
sock.sendall(json_str.encode('utf-8'))
|
||||||
|
except OSError as exc:
|
||||||
|
# Remove all newly added objects if no connection was made
|
||||||
|
# so that the object data will be sent on next attempt
|
||||||
|
for obj_name in new_objs:
|
||||||
|
col["seen_objs"].pop(obj_name)
|
||||||
|
|
||||||
|
|
||||||
|
operations = [OBJECT_PT_osci_render_settings, osci_render_connect, osci_render_close]
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
bpy.app.handlers.frame_change_pre.append(send_scene_to_osci_render)
|
||||||
|
bpy.app.handlers.depsgraph_update_post.append(send_scene_to_osci_render)
|
||||||
|
for operation in operations:
|
||||||
|
bpy.utils.register_class(operation)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
bpy.app.handlers.frame_change_pre.clear()
|
||||||
|
bpy.app.handlers.depsgraph_update_post.clear()
|
||||||
|
for operation in operations.reverse():
|
||||||
|
bpy.utils.unregister_class(operation)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
register()
|
|
@ -10,14 +10,16 @@ import sh.ball.shapes.Vector2;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
public class CameraDrawKernel extends Kernel {
|
public class CameraDrawKernel extends Kernel {
|
||||||
|
|
||||||
private WorldObject prevObject = null;
|
private WorldObject prevObject = null;
|
||||||
private List<WorldObject> prevObjects = null;
|
private List<WorldObject> prevObjects = null;
|
||||||
|
private List<Vector3[]> prevPaths = null;
|
||||||
private float[] vertices;
|
private float[] vertices;
|
||||||
private float[] vertexResult;
|
private float[] vertexResult;
|
||||||
private float[] triangles;
|
private float[] triangles = new float[1];
|
||||||
private float[] matrices = new float[1];
|
private float[] matrices = new float[1];
|
||||||
private int[] vertexNums = new int[1];
|
private int[] vertexNums = new int[1];
|
||||||
private float rotationX;
|
private float rotationX;
|
||||||
|
@ -54,38 +56,57 @@ public class CameraDrawKernel extends Kernel {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Shape> draw(ObjectSet objects, float focalLength) {
|
public synchronized List<Shape> draw(ObjectSet objects, float focalLength) {
|
||||||
this.focalLength = focalLength;
|
this.focalLength = focalLength;
|
||||||
usingObjectSet = 1;
|
usingObjectSet = 1;
|
||||||
List<WorldObject> objectList = objects.objects.stream().toList();
|
if (!objects.objects.equals(prevObjects) || !objects.pathObjects.equals(prevPaths)) {
|
||||||
if (!objectList.equals(prevObjects)) {
|
prevObjects = objects.objects;
|
||||||
prevObjects = objectList;
|
prevPaths = objects.pathObjects;
|
||||||
List<List<List<Vector3>>> vertices = objectList.stream().map(WorldObject::getVertexPath).toList();
|
List<List<List<Vector3>>> vertices = objects.objects.stream().map(WorldObject::getVertexPath).toList();
|
||||||
this.vertexNums = vertices.stream().mapToInt(
|
this.vertexNums = IntStream.concat(
|
||||||
l -> l.stream()
|
vertices.stream().mapToInt(
|
||||||
.map(List::size)
|
l -> l.stream()
|
||||||
.reduce(0, Integer::sum) + l.size()
|
.map(List::size)
|
||||||
|
.reduce(0, Integer::sum) + l.size()
|
||||||
|
),
|
||||||
|
objects.pathObjects.stream().mapToInt(
|
||||||
|
arr -> arr.length
|
||||||
|
)
|
||||||
).toArray();
|
).toArray();
|
||||||
int numVertices = Arrays.stream(vertexNums).sum();
|
int numVertices = Arrays.stream(vertexNums).sum();
|
||||||
this.vertices = new float[numVertices * 3];
|
this.vertices = new float[numVertices * 3];
|
||||||
this.vertexResult = new float[numVertices * 2];
|
this.vertexResult = new float[numVertices * 2];
|
||||||
this.matrices = new float[vertices.size() * 16];
|
this.matrices = new float[(vertices.size() + objects.pathObjects.size()) * 16];
|
||||||
List<float[]> triangles = objectList.stream().map(WorldObject::getTriangles).toList();
|
if (!objects.objects.isEmpty()) {
|
||||||
int numTriangles = triangles.stream().map(arr -> arr.length).reduce(0, Integer::sum);
|
List<float[]> triangles = objects.objects.stream().map(WorldObject::getTriangles).toList();
|
||||||
this.triangles = new float[numTriangles];
|
int numTriangles = triangles.stream().map(arr -> arr.length).reduce(0, Integer::sum);
|
||||||
int offset = 0;
|
this.triangles = new float[numTriangles];
|
||||||
for (float[] triangleArray : triangles) {
|
int offset = 0;
|
||||||
System.arraycopy(triangleArray, 0, this.triangles, offset, triangleArray.length);
|
for (float[] triangleArray : triangles) {
|
||||||
offset += triangleArray.length;
|
System.arraycopy(triangleArray, 0, this.triangles, offset, triangleArray.length);
|
||||||
|
offset += triangleArray.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (List<List<Vector3>> vertexList : vertices) {
|
for (List<List<Vector3>> vertexList : vertices) {
|
||||||
count = initialiseVertices(count, vertexList);
|
count = initialiseVertices(count, vertexList);
|
||||||
}
|
}
|
||||||
|
for (Vector3[] vectors : objects.pathObjects) {
|
||||||
|
for (Vector3 vertex : vectors) {
|
||||||
|
this.vertices[3 * count] = (float) vertex.x;
|
||||||
|
this.vertices[3 * count + 1] = (float) vertex.y;
|
||||||
|
this.vertices[3 * count + 2] = (float) vertex.z;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (float[] matrix : objects.cameraSpaceMatrices) {
|
for (float[] matrix : objects.objectMatrices) {
|
||||||
|
System.arraycopy(matrix, 0, this.matrices, offset, matrix.length);
|
||||||
|
offset += matrix.length;
|
||||||
|
}
|
||||||
|
for (float[] matrix : objects.pathMatrices) {
|
||||||
System.arraycopy(matrix, 0, this.matrices, offset, matrix.length);
|
System.arraycopy(matrix, 0, this.matrices, offset, matrix.length);
|
||||||
offset += matrix.length;
|
offset += matrix.length;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +155,11 @@ public class CameraDrawKernel extends Kernel {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(Range.create(roundUp(vertices.length / 3, maxGroupSize), maxGroupSize));
|
for (int i = 0; i < vertices.length / 3; i++) {
|
||||||
|
processVertex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//execute(Range.create(roundUp(vertices.length / 3, maxGroupSize), maxGroupSize));
|
||||||
|
|
||||||
List<Shape> linesList = new ArrayList<>();
|
List<Shape> linesList = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -167,9 +192,7 @@ public class CameraDrawKernel extends Kernel {
|
||||||
return round + multiple - remainder;
|
return round + multiple - remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void processVertex(int i) {
|
||||||
public void run() {
|
|
||||||
int i = getGlobalId();
|
|
||||||
float EPSILON = 0.00001f;
|
float EPSILON = 0.00001f;
|
||||||
|
|
||||||
float x1 = vertices[3 * i];
|
float x1 = vertices[3 * i];
|
||||||
|
@ -214,10 +237,11 @@ public class CameraDrawKernel extends Kernel {
|
||||||
int obj = -1;
|
int obj = -1;
|
||||||
for (int j = 0; j < vertexNums.length; j++) {
|
for (int j = 0; j < vertexNums.length; j++) {
|
||||||
totalVertices += vertexNums[j];
|
totalVertices += vertexNums[j];
|
||||||
if (totalVertices >= i && obj == -1) {
|
if (totalVertices > i && obj == -1) {
|
||||||
obj = j;
|
obj = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: This matrix multiplication somehow causes a NaN
|
||||||
rotatedX = matrices[16 * obj] * x1 + matrices[16 * obj + 1] * y1 + matrices[16 * obj + 2] * z1 + matrices[16 * obj + 3];
|
rotatedX = matrices[16 * obj] * x1 + matrices[16 * obj + 1] * y1 + matrices[16 * obj + 2] * z1 + matrices[16 * obj + 3];
|
||||||
rotatedY = matrices[16 * obj + 4] * x1 + matrices[16 * obj + 5] * y1 + matrices[16 * obj + 6] * z1 + matrices[16 * obj + 7];
|
rotatedY = matrices[16 * obj + 4] * x1 + matrices[16 * obj + 5] * y1 + matrices[16 * obj + 6] * z1 + matrices[16 * obj + 7];
|
||||||
rotatedZ = matrices[16 * obj + 8] * x1 + matrices[16 * obj + 9] * y1 + matrices[16 * obj + 10] * z1 + matrices[16 * obj + 11];
|
rotatedZ = matrices[16 * obj + 8] * x1 + matrices[16 * obj + 9] * y1 + matrices[16 * obj + 10] * z1 + matrices[16 * obj + 11];
|
||||||
|
@ -328,6 +352,11 @@ public class CameraDrawKernel extends Kernel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
processVertex(getGlobalId());
|
||||||
|
}
|
||||||
|
|
||||||
float crossX(float x0, float x1, float x2, float y0, float y1, float y2) {
|
float crossX(float x0, float x1, float x2, float y0, float y1, float y2) {
|
||||||
return x1 * y2 - y1 * x2;
|
return x1 * y2 - y1 * x2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.io.InputStreamReader;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ObjectServer implements Runnable {
|
public class ObjectServer implements Runnable {
|
||||||
|
|
||||||
|
@ -41,16 +40,33 @@ public class ObjectServer implements Runnable {
|
||||||
}
|
}
|
||||||
EngineInfo info = gson.fromJson(json, EngineInfo.class);
|
EngineInfo info = gson.fromJson(json, EngineInfo.class);
|
||||||
|
|
||||||
|
List<WorldObject> objectsToRender = new ArrayList<>();
|
||||||
|
List<float[]> objectMatrices = new ArrayList<>();
|
||||||
|
|
||||||
|
List<Vector3[]> pathObjects = new ArrayList<>();
|
||||||
|
List<float[]> pathMatrices = new ArrayList<>();
|
||||||
|
|
||||||
|
Set<String> currentObjects = new HashSet<>();
|
||||||
|
|
||||||
for (ObjectInfo obj : info.objects) {
|
for (ObjectInfo obj : info.objects) {
|
||||||
|
currentObjects.add(obj.name);
|
||||||
if (!objects.containsKey(obj.name)) {
|
if (!objects.containsKey(obj.name)) {
|
||||||
objects.put(obj.name, new WorldObject(obj.vertices, obj.edges, obj.faces));
|
if (obj.vertices != null) {
|
||||||
|
objects.put(obj.name, new WorldObject(obj.vertices, obj.edges, obj.faces));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj.pathVertices == null) {
|
||||||
|
objectsToRender.add(objects.get(obj.name));
|
||||||
|
objectMatrices.add(obj.matrix);
|
||||||
|
} else {
|
||||||
|
pathObjects.add(obj.pathVertices);
|
||||||
|
pathMatrices.add(obj.matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> currentObjects = Arrays.stream(info.objects).map(obj -> obj.name).collect(Collectors.toSet());
|
|
||||||
objects.entrySet().removeIf(obj -> !currentObjects.contains(obj.getKey()));
|
objects.entrySet().removeIf(obj -> !currentObjects.contains(obj.getKey()));
|
||||||
|
|
||||||
objectSet.setObjects(objects.values(), Arrays.stream(info.objects).map(obj -> obj.matrix).toList(), info.focalLength);
|
objectSet.setObjects(objectsToRender, objectMatrices, pathObjects, pathMatrices, info.focalLength);
|
||||||
}
|
}
|
||||||
disableRendering.run();
|
disableRendering.run();
|
||||||
}
|
}
|
||||||
|
@ -79,6 +95,7 @@ public class ObjectServer implements Runnable {
|
||||||
private static class ObjectInfo {
|
private static class ObjectInfo {
|
||||||
private String name;
|
private String name;
|
||||||
private Vector3[] vertices;
|
private Vector3[] vertices;
|
||||||
|
private Vector3[] pathVertices;
|
||||||
private int[] edges;
|
private int[] edges;
|
||||||
private int[][] faces;
|
private int[][] faces;
|
||||||
// Camera space matrix
|
// Camera space matrix
|
||||||
|
|
|
@ -4,7 +4,6 @@ import sh.ball.audio.FrameSource;
|
||||||
import sh.ball.shapes.Shape;
|
import sh.ball.shapes.Shape;
|
||||||
import sh.ball.shapes.Vector2;
|
import sh.ball.shapes.Vector2;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -12,16 +11,20 @@ public class ObjectSet implements FrameSource<List<Shape>> {
|
||||||
|
|
||||||
private final CameraDrawKernel kernel = new CameraDrawKernel();
|
private final CameraDrawKernel kernel = new CameraDrawKernel();
|
||||||
|
|
||||||
public Collection<WorldObject> objects;
|
public List<WorldObject> objects;
|
||||||
public Collection<float[]> cameraSpaceMatrices;
|
public List<float[]> objectMatrices;
|
||||||
|
public List<Vector3[]> pathObjects;
|
||||||
|
public List<float[]> pathMatrices;
|
||||||
private boolean active = true;
|
private boolean active = true;
|
||||||
private float focalLength;
|
private float focalLength;
|
||||||
|
|
||||||
public ObjectSet() {}
|
public ObjectSet() {}
|
||||||
|
|
||||||
public void setObjects(Collection<WorldObject> objects, Collection<float[]> matrices, float focalLength) {
|
public synchronized void setObjects(List<WorldObject> objects, List<float[]> matrices, List<Vector3[]> pathObjects, List<float[]> pathMatrices, float focalLength) {
|
||||||
this.objects = objects;
|
this.objects = objects;
|
||||||
this.cameraSpaceMatrices = matrices;
|
this.objectMatrices = matrices;
|
||||||
|
this.pathObjects = pathObjects;
|
||||||
|
this.pathMatrices = pathMatrices;
|
||||||
this.focalLength = focalLength;
|
this.focalLength = focalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,19 +37,21 @@ public class ObjectSet implements FrameSource<List<Shape>> {
|
||||||
|
|
||||||
if (!Objects.equals(objects, objectSet.objects))
|
if (!Objects.equals(objects, objectSet.objects))
|
||||||
return false;
|
return false;
|
||||||
return Objects.equals(cameraSpaceMatrices, objectSet.cameraSpaceMatrices);
|
return Objects.equals(objectMatrices, objectSet.objectMatrices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = objects != null ? objects.hashCode() : 0;
|
int result = objects != null ? objects.hashCode() : 0;
|
||||||
result = 31 * result + (cameraSpaceMatrices != null ? cameraSpaceMatrices.hashCode() : 0);
|
result = 31 * result + (objectMatrices != null ? objectMatrices.hashCode() : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Shape> next() {
|
public synchronized List<Shape> next() {
|
||||||
if (objects == null || cameraSpaceMatrices == null) {
|
if ((objects == null || objectMatrices == null || objects.isEmpty() || objectMatrices.isEmpty())
|
||||||
|
&& (pathObjects == null || pathMatrices == null || pathObjects.isEmpty() || pathMatrices.isEmpty())) {
|
||||||
|
System.out.println("nothing to draw!");
|
||||||
return List.of(new Vector2());
|
return List.of(new Vector2());
|
||||||
}
|
}
|
||||||
return kernel.draw(this, focalLength);
|
return kernel.draw(this, focalLength);
|
||||||
|
|
Ładowanie…
Reference in New Issue