Convert live object rendering to binary (leaving legacy support in)

pull/279/head
DJLevel3 2025-01-22 08:37:45 -05:00
rodzic 12233f7954
commit 9d2829b2ea
4 zmienionych plików z 147 dodań i 117 usunięć

Wyświetl plik

@ -2,14 +2,18 @@
LineArtParser::LineArtParser(juce::String json) { LineArtParser::LineArtParser(juce::String json) {
parseJsonFrames(json); frames.clear();
numFrames = 0;
frames = parseJsonFrames(json);
numFrames = frames.size();
} }
LineArtParser::LineArtParser(char* data, int dataLength) { LineArtParser::LineArtParser(char* data, int dataLength) {
parseBinaryFrames(data, dataLength); frames.clear();
if (numFrames == 0) { numFrames = 0;
parseJsonFrames(juce::String(BinaryData::fallback_gpla, BinaryData::fallback_gplaSize)); frames = parseBinaryFrames(data, dataLength);
} numFrames = frames.size();
if (numFrames == 0) frames = epicFail();
} }
LineArtParser::~LineArtParser() { LineArtParser::~LineArtParser() {
@ -26,11 +30,16 @@ void LineArtParser::makeChars(int64_t data, char* chars) {
} }
} }
void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) { std::vector<std::vector<Line>> LineArtParser::epicFail() {
frames.clear(); return parseJsonFrames(juce::String(BinaryData::fallback_gpla, BinaryData::fallback_gplaSize));
numFrames = 0; }
std::vector<std::vector<Line>> LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
int64_t* data = (int64_t*)bytes; int64_t* data = (int64_t*)bytes;
int dataLength = bytesLength / 4; int dataLength = bytesLength / 8;
std::vector<std::vector<Line>> tFrames;
if (dataLength < 4) return epicFail();
int index = 0; int index = 0;
int64_t rawData = data[index]; int64_t rawData = data[index];
@ -39,31 +48,37 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
char tag[9] = " "; char tag[9] = " ";
makeChars(rawData, tag); makeChars(rawData, tag);
if (strcmp(tag, "GPLA ") != 0) return; if (strcmp(tag, "GPLA ") != 0) return epicFail();
// Major // Major
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
// Minor // Minor
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
// Patch // Patch
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
if (strcmp(tag, "FILE ") != 0) return; if (strcmp(tag, "FILE ") != 0) return epicFail();
int reportedNumFrames = 0; int reportedNumFrames = 0;
int frameRate = 0; int frameRate = 0;
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
while (strcmp(tag, "DONE ") != 0) { while (strcmp(tag, "DONE ") != 0) {
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
@ -73,24 +88,29 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
frameRate = rawData; frameRate = rawData;
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
while (strcmp(tag, "END GPLA") != 0) { while (strcmp(tag, "END GPLA") != 0) {
if (strcmp(tag, "FRAME ") == 0) { if (strcmp(tag, "FRAME ") == 0) {
std::vector<std::vector<double>> allMatrices; if (index >= dataLength) return epicFail();
std::vector<std::vector<std::vector<OsciPoint>>> allVertices;
double focalLength;
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
double focalLength;
std::vector<std::vector<double>> allMatrices;
std::vector<std::vector<std::vector<OsciPoint>>> allVertices;
while (strcmp(tag, "OBJECTS ") != 0) { while (strcmp(tag, "OBJECTS ") != 0) {
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
@ -98,11 +118,13 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
focalLength = makeDouble(rawData); focalLength = makeDouble(rawData);
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
@ -111,6 +133,7 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
if (strcmp(tag, "OBJECT ") == 0) { if (strcmp(tag, "OBJECT ") == 0) {
std::vector<std::vector<OsciPoint>> vertices; std::vector<std::vector<OsciPoint>> vertices;
std::vector<double> matrix; std::vector<double> matrix;
if (index >= dataLength) return epicFail();
int strokeNum = 0; int strokeNum = 0;
rawData = data[index]; rawData = data[index];
index++; index++;
@ -119,13 +142,16 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
if (strcmp(tag, "MATRIX ") == 0) { if (strcmp(tag, "MATRIX ") == 0) {
matrix.clear(); matrix.clear();
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
matrix.push_back(makeDouble(rawData)); matrix.push_back(makeDouble(rawData));
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
} else if (strcmp(tag, "STROKES ") == 0) { } else if (strcmp(tag, "STROKES ") == 0) {
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
@ -133,6 +159,7 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
while (strcmp(tag, "DONE ") != 0) { while (strcmp(tag, "DONE ") != 0) {
if (strcmp(tag, "STROKE ") == 0) { if (strcmp(tag, "STROKE ") == 0) {
vertices.push_back(std::vector<OsciPoint>()); vertices.push_back(std::vector<OsciPoint>());
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
@ -140,6 +167,7 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
int vertexCount = 0; int vertexCount = 0;
while (strcmp(tag, "DONE ") != 0) { while (strcmp(tag, "DONE ") != 0) {
if (strcmp(tag, "vertexCt") == 0) { if (strcmp(tag, "vertexCt") == 0) {
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
vertexCount = rawData; vertexCount = rawData;
@ -149,6 +177,7 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
double y = 0; double y = 0;
double z = 0; double z = 0;
for (int i = 0; i < vertexCount; i++) { for (int i = 0; i < vertexCount; i++) {
if (index + 2 >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
x = makeDouble(rawData); x = makeDouble(rawData);
@ -163,26 +192,31 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
vertices[strokeNum].push_back(OsciPoint(x, y, z)); vertices[strokeNum].push_back(OsciPoint(x, y, z));
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
while (strcmp(tag, "DONE ") != 0) { while (strcmp(tag, "DONE ") != 0) {
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
} }
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
} }
strokeNum++; strokeNum++;
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
} }
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
@ -192,25 +226,24 @@ void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
vertices.clear(); vertices.clear();
matrix.clear(); matrix.clear();
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
} }
std::vector<Line> frame = assembleFrame(allVertices, allMatrices, focalLength);
frames.push_back(assembleFrame(allVertices, allMatrices, focalLength)); tFrames.push_back(frame);
} }
if (index >= dataLength) return epicFail();
rawData = data[index]; rawData = data[index];
index++; index++;
makeChars(rawData, tag); makeChars(rawData, tag);
} }
numFrames = frames.size(); return tFrames;
return;
} }
void LineArtParser::parseJsonFrames(juce::String jsonStr) { std::vector<std::vector<Line>> LineArtParser::parseJsonFrames(juce::String jsonStr) {
frames.clear(); std::vector<std::vector<Line>> frames;
numFrames = 0;
// format of json is: // format of json is:
// { // {
@ -243,19 +276,13 @@ void LineArtParser::parseJsonFrames(juce::String jsonStr) {
auto json = juce::JSON::parse(jsonStr); auto json = juce::JSON::parse(jsonStr);
// If json parse failed, stop and parse default fallback instead // If json parse failed, stop and parse default fallback instead
if (json.isVoid()) { if (json.isVoid()) return epicFail();
parseJsonFrames(juce::String(BinaryData::fallback_gpla, BinaryData::fallback_gplaSize));
return;
}
auto jsonFrames = *json.getProperty("frames", juce::Array<juce::var>()).getArray(); auto jsonFrames = *json.getProperty("frames", juce::Array<juce::var>()).getArray();
numFrames = jsonFrames.size(); int numFrames = jsonFrames.size();
// If json does not contain any frames, stop and parse no-frames fallback instead // If json does not contain any frames, stop and parse no-frames fallback instead
if (numFrames == 0) { if (numFrames == 0) return parseJsonFrames(juce::String(BinaryData::noframes_gpla, BinaryData::noframes_gplaSize));
parseJsonFrames(juce::String(BinaryData::noframes_gpla, BinaryData::noframes_gplaSize));
return;
}
bool hasValidFrames = false; bool hasValidFrames = false;
@ -275,10 +302,7 @@ void LineArtParser::parseJsonFrames(juce::String jsonStr) {
} }
// If no frames were valid, stop and parse invalid fallback instead // If no frames were valid, stop and parse invalid fallback instead
if (!hasValidFrames) { if (!hasValidFrames) return parseJsonFrames(juce::String(BinaryData::invalid_gpla, BinaryData::invalid_gplaSize));
parseJsonFrames(juce::String(BinaryData::invalid_gpla, BinaryData::invalid_gplaSize));
return;
}
} }
void LineArtParser::setFrame(int fNum) { void LineArtParser::setFrame(int fNum) {

Wyświetl plik

@ -14,12 +14,14 @@ public:
void setFrame(int fNum); void setFrame(int fNum);
std::vector<std::unique_ptr<Shape>> draw(); std::vector<std::unique_ptr<Shape>> draw();
static std::vector<std::vector<Line>> parseJsonFrames(juce::String jsonStr);
static std::vector<std::vector<Line>> parseBinaryFrames(char* data, int dataLength);
static std::vector<Line> generateFrame(juce::Array < juce::var> objects, double focalLength); static std::vector<Line> generateFrame(juce::Array < juce::var> objects, double focalLength);
private: private:
void parseJsonFrames(juce::String jsonStr); static std::vector<std::vector<Line>> epicFail();
void parseBinaryFrames(char* data, int dataLength); static double makeDouble(int64_t data);
double makeDouble(int64_t data); static void makeChars(int64_t data, char* chars);
void makeChars(int64_t data, char* chars);
static std::vector<std::vector<OsciPoint>> reorderVertices(std::vector<std::vector<OsciPoint>> vertices); static std::vector<std::vector<OsciPoint>> reorderVertices(std::vector<std::vector<OsciPoint>> vertices);
static std::vector<Line> assembleFrame(std::vector<std::vector<std::vector<OsciPoint>>> allVertices, std::vector<std::vector<double>> allMatrices, double focalLength); static std::vector<Line> assembleFrame(std::vector<std::vector<std::vector<OsciPoint>>> allVertices, std::vector<std::vector<double>> allMatrices, double focalLength);
int frameNumber = 0; int frameNumber = 0;

Wyświetl plik

@ -25,6 +25,7 @@ void ObjectServer::run() {
while (!threadShouldExit() && connection->isConnected()) { while (!threadShouldExit() && connection->isConnected()) {
if (connection->waitUntilReady(true, 200) == 1) { if (connection->waitUntilReady(true, 200) == 1) {
int i = 0; int i = 0;
std::vector<Line> frameContainer;
// read until we get a newline // read until we get a newline
while (!threadShouldExit()) { while (!threadShouldExit()) {
@ -52,36 +53,55 @@ void ObjectServer::run() {
break; break;
} }
// format of json is: if (strncmp(message.get(), "R1BMQSAg", 8) == 0) {
// { juce::MemoryOutputStream binStream;
// "objects": [ juce::String messageString = message.get();
// { if (juce::Base64::convertFromBase64(binStream, messageString)) {
// "name": "Line Art", std::vector< std::vector<Line>> receivedFrames;
// "vertices": [ int bytesRead = binStream.getDataSize();
// [ if (bytesRead < 8) return;
// { char* gplaData = (char*)binStream.getData();
// "x": double value, receivedFrames = LineArtParser::parseBinaryFrames(gplaData, bytesRead);
// "y": double value, if (receivedFrames.size() <= 0) continue;
// "z": double value frameContainer = receivedFrames[0];
// }, }
// ... else {
// ], continue;
// ... }
// ], }
// "matrix": [ else {
// 16 double values
// ]
// }
// ],
// "focalLength": double value
// }
auto json = juce::JSON::parse(message.get()); // format of json is:
// {
// "objects": [
// {
// "name": "Line Art",
// "vertices": [
// [
// {
// "x": double value,
// "y": double value,
// "z": double value
// },
// ...
// ],
// ...
// ],
// "matrix": [
// 16 double values
// ]
// }
// ],
// "focalLength": double value
// }
juce::Array<juce::var> objects = *json.getProperty("objects", juce::Array<juce::var>()).getArray(); auto json = juce::JSON::parse(message.get());
double focalLength = json.getProperty("focalLength", 1);
std::vector<Line> frameContainer = LineArtParser::generateFrame(objects, focalLength); juce::Array<juce::var> objects = *json.getProperty("objects", juce::Array<juce::var>()).getArray();
double focalLength = json.getProperty("focalLength", 1);
frameContainer = LineArtParser::generateFrame(objects, focalLength);
}
std::vector<std::unique_ptr<Shape>> frame; std::vector<std::unique_ptr<Shape>> frame;

Wyświetl plik

@ -17,6 +17,7 @@ import socket
import json import json
import atexit import atexit
import struct import struct
import base64
from bpy.props import StringProperty from bpy.props import StringProperty
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
from bpy_extras.io_utils import ImportHelper from bpy_extras.io_utils import ImportHelper
@ -125,53 +126,7 @@ def close_osci_render():
except socket.error as exp: except socket.error as exp:
sock = None sock = None
def get_gpla_file_allframes(scene):
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 get_frame_info():
frame_info = {"objects": []}
if (bpy.app.version[0] > 4) or (bpy.app.version[0] == 4 and bpy.app.version[1] >= 3):
for object in bpy.data.objects:
if object.visible_get() and object.type == 'GREASEPENCIL':
dg = bpy.context.evaluated_depsgraph_get()
obj = object.evaluated_get(dg)
object_info = {"name": object.name}
for layer in obj.data.layers:
strokes = layer.frames.data.current_frame().drawing.strokes
object_info["vertices"] = []
for stroke in strokes:
object_info["vertices"].append([{
"x": vert.position.x,
"y": vert.position.y,
"z": vert.position.z,
} for vert in stroke.points])
frame_info["objects"].append(append_matrix(object_info, object))
else:
for object in bpy.data.objects:
if object.visible_get() and object.type == 'GPENCIL':
dg = bpy.context.evaluated_depsgraph_get()
obj = object.evaluated_get(dg)
object_info = {"name": object.name}
strokes = obj.data.layers.active.frames.data.active_frame.strokes
object_info["vertices"] = []
for stroke in strokes:
object_info["vertices"].append([{
"x": vert.co[0],
"y": vert.co[1],
"z": vert.co[2],
} for vert in stroke.points])
frame_info["objects"].append(append_matrix(object_info, obj))
frame_info["focalLength"] = -0.05 * bpy.data.cameras[0].lens
return frame_info
@persistent
def save_scene_to_file(scene, file_path):
return_frame = scene.frame_current
bin = bytearray() bin = bytearray()
# header # header
@ -194,6 +149,37 @@ def save_scene_to_file(scene, file_path):
bin.extend(("END GPLA").encode("utf8")) bin.extend(("END GPLA").encode("utf8"))
return bin
def get_gpla_file(scene):
bin = bytearray()
# header
bin.extend(("GPLA ").encode("utf8"))
bin.extend(GPLA_MAJOR.to_bytes(8, "little"))
bin.extend(GPLA_MINOR.to_bytes(8, "little"))
bin.extend(GPLA_PATCH.to_bytes(8, "little"))
# file info
bin.extend(("FILE ").encode("utf8"))
bin.extend(("fCount ").encode("utf8"))
bin.extend((scene.frame_end - scene.frame_start + 1).to_bytes(8, "little"))
bin.extend(("fRate ").encode("utf8"))
bin.extend(scene.render.fps.to_bytes(8, "little"))
bin.extend(("DONE ").encode("utf8"))
bin.extend(get_frame_info_binary())
bin.extend(("END GPLA").encode("utf8"))
return bin
@persistent
def save_scene_to_file(scene, file_path):
return_frame = scene.frame_current
bin = get_gpla_file_allframes(scene)
if file_path is not None: if file_path is not None:
with open(file_path, "wb") as f: with open(file_path, "wb") as f:
f.write(bytes(bin)) f.write(bytes(bin))
@ -308,11 +294,9 @@ def send_scene_to_osci_render(scene):
global sock global sock
if sock is not None: if sock is not None:
frame_info = get_frame_info() bin = get_gpla_file(scene)
json_str = json.dumps(frame_info, separators=(',', ':')) + '\n'
try: try:
sock.sendall(json_str.encode('utf-8')) sock.sendall(base64.b64encode(bytes(bin)) + "\n".encode("utf8"))
except socket.error as exp: except socket.error as exp:
sock = None sock = None