Get that binary up in here

pull/279/head
DJLevel3 2025-01-21 16:34:25 -05:00
rodzic ec3838ba5d
commit 73f7bf6f22
6 zmienionych plików z 400 dodań i 59 usunięć

Wyświetl plik

@ -23,8 +23,9 @@ TxtComponent::TxtComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
audioProcessor.font.setBold(bold.getToggleState()); audioProcessor.font.setBold(bold.getToggleState());
audioProcessor.font.setItalic(italic.getToggleState()); audioProcessor.font.setItalic(italic.getToggleState());
} }
if (audioProcessor.currentFileId > 0 && audioProcessor.parsers[audioProcessor.currentFileId - 1]->getText() != nullptr) {
audioProcessor.openFile(audioProcessor.currentFile); audioProcessor.openFile(audioProcessor.currentFile);
}
}; };
font.onChange = updateFont; font.onChange = updateFont;

Wyświetl plik

@ -43,6 +43,7 @@ void ShapeVoice::startNote(int midiNoteNumber, float velocity, juce::Synthesiser
// TODO this is the slowest part of the program - any way to improve this would help! // TODO this is the slowest part of the program - any way to improve this would help!
void ShapeVoice::incrementShapeDrawing() { void ShapeVoice::incrementShapeDrawing() {
if (frame.size() <= 0) return;
double length = currentShape < frame.size() ? frame[currentShape]->len : 0.0; double length = currentShape < frame.size() ? frame[currentShape]->len : 0.0;
frameDrawn += lengthIncrement; frameDrawn += lengthIncrement;
shapeDrawn += lengthIncrement; shapeDrawn += lengthIncrement;

Wyświetl plik

@ -5,10 +5,209 @@ LineArtParser::LineArtParser(juce::String json) {
parseJsonFrames(json); parseJsonFrames(json);
} }
LineArtParser::LineArtParser(char* data, int dataLength) {
parseBinaryFrames(data, dataLength);
if (numFrames == 0) {
parseJsonFrames(juce::String(BinaryData::fallback_gpla, BinaryData::fallback_gplaSize));
}
}
LineArtParser::~LineArtParser() { LineArtParser::~LineArtParser() {
frames.clear(); frames.clear();
} }
double LineArtParser::makeDouble(int64_t data) {
return *(double*)&data;
}
void LineArtParser::makeChars(int64_t data, char* chars) {
for (int i = 0; i < 8; i++) {
chars[i] = (data >> (i * 8)) & 0xFF;
}
}
void LineArtParser::parseBinaryFrames(char* bytes, int bytesLength) {
frames.clear();
numFrames = 0;
int64_t* data = (int64_t*)bytes;
int dataLength = bytesLength / 4;
int index = 0;
int64_t rawData = data[index];
index++;
char tag[9] = " ";
makeChars(rawData, tag);
if (strcmp(tag, "GPLA ") != 0) return;
// Major
rawData = data[index];
index++;
// Minor
rawData = data[index];
index++;
// Patch
rawData = data[index];
index++;
rawData = data[index];
index++;
makeChars(rawData, tag);
if (strcmp(tag, "FILE ") != 0) return;
int reportedNumFrames = 0;
int frameRate = 0;
rawData = data[index];
index++;
makeChars(rawData, tag);
while (strcmp(tag, "DONE ") != 0) {
rawData = data[index];
index++;
if (strcmp(tag, "fCount ") == 0) {
reportedNumFrames = rawData;
} else if (strcmp(tag, "fRate ") == 0) {
frameRate = rawData;
}
rawData = data[index];
index++;
makeChars(rawData, tag);
}
rawData = data[index];
index++;
makeChars(rawData, tag);
while (strcmp(tag, "END GPLA") != 0) {
if (strcmp(tag, "FRAME ") == 0) {
std::vector<std::vector<double>> allMatrices;
std::vector<std::vector<std::vector<OsciPoint>>> allVertices;
double focalLength;
rawData = data[index];
index++;
makeChars(rawData, tag);
while (strcmp(tag, "OBJECTS ") != 0) {
rawData = data[index];
index++;
if (strcmp(tag, "focalLen") == 0) {
focalLength = makeDouble(rawData);
}
rawData = data[index];
index++;
makeChars(rawData, tag);
}
rawData = data[index];
index++;
makeChars(rawData, tag);
while (strcmp(tag, "DONE ") != 0) {
if (strcmp(tag, "OBJECT ") == 0) {
std::vector<std::vector<OsciPoint>> vertices;
std::vector<double> matrix;
int strokeNum = 0;
rawData = data[index];
index++;
makeChars(rawData, tag);
while (strcmp(tag, "DONE ") != 0) {
if (strcmp(tag, "MATRIX ") == 0) {
matrix.clear();
for (int i = 0; i < 16; i++) {
rawData = data[index];
index++;
matrix.push_back(makeDouble(rawData));
}
rawData = data[index];
index++;
} else if (strcmp(tag, "STROKES ") == 0) {
rawData = data[index];
index++;
makeChars(rawData, tag);
while (strcmp(tag, "DONE ") != 0) {
if (strcmp(tag, "STROKE ") == 0) {
vertices.push_back(std::vector<OsciPoint>());
rawData = data[index];
index++;
makeChars(rawData, tag);
int vertexCount = 0;
while (strcmp(tag, "DONE ") != 0) {
if (strcmp(tag, "vertexCt") == 0) {
rawData = data[index];
index++;
vertexCount = rawData;
}
else if (strcmp(tag, "VERTICES") == 0) {
double x = 0;
double y = 0;
double z = 0;
for (int i = 0; i < vertexCount; i++) {
rawData = data[index];
index++;
x = makeDouble(rawData);
rawData = data[index];
index++;
y = makeDouble(rawData);
rawData = data[index];
index++;
z = makeDouble(rawData);
vertices[strokeNum].push_back(OsciPoint(x, y, z));
}
rawData = data[index];
index++;
makeChars(rawData, tag);
while (strcmp(tag, "DONE ") != 0) {
rawData = data[index];
index++;
makeChars(rawData, tag);
}
}
rawData = data[index];
index++;
makeChars(rawData, tag);
}
strokeNum++;
}
rawData = data[index];
index++;
makeChars(rawData, tag);
}
}
rawData = data[index];
index++;
makeChars(rawData, tag);
}
allVertices.push_back(reorderVertices(vertices));
allMatrices.push_back(matrix);
vertices.clear();
matrix.clear();
}
rawData = data[index];
index++;
makeChars(rawData, tag);
}
frames.push_back(assembleFrame(allVertices, allMatrices, focalLength));
}
rawData = data[index];
index++;
makeChars(rawData, tag);
}
numFrames = frames.size();
return;
}
void LineArtParser::parseJsonFrames(juce::String jsonStr) { void LineArtParser::parseJsonFrames(juce::String jsonStr) {
frames.clear(); frames.clear();
numFrames = 0; numFrames = 0;
@ -97,36 +296,10 @@ std::vector<std::unique_ptr<Shape>> LineArtParser::draw() {
return tempShapes; return tempShapes;
} }
std::vector<std::vector<OsciPoint>> LineArtParser::reorderVertices(std::vector<std::vector<OsciPoint>> vertices) {
std::vector<Line> LineArtParser::generateFrame(juce::Array <juce::var> objects, double focalLength)
{
std::vector<std::vector<double>> allMatrices;
std::vector<std::vector<std::vector<OsciPoint>>> allVertices;
for (int i = 0; i < objects.size(); i++) {
auto verticesArray = *objects[i].getProperty("vertices", juce::Array<juce::var>()).getArray();
std::vector<std::vector<OsciPoint>> vertices;
for (auto& vertexArrayVar : verticesArray) {
vertices.push_back(std::vector<OsciPoint>());
auto& vertexArray = *vertexArrayVar.getArray();
for (auto& vertex : vertexArray) {
double x = vertex.getProperty("x", 0);
double y = vertex.getProperty("y", 0);
double z = vertex.getProperty("z", 0);
vertices[vertices.size() - 1].push_back(OsciPoint(x, y, z));
}
}
auto matrix = *objects[i].getProperty("matrix", juce::Array<juce::var>()).getArray();
allMatrices.push_back(std::vector<double>());
for (auto& value : matrix) {
allMatrices[i].push_back(value);
}
std::vector<std::vector<OsciPoint>> reorderedVertices; std::vector<std::vector<OsciPoint>> reorderedVertices;
if (vertices.size() > 0 && matrix.size() == 16) { if (vertices.size() > 0) {
std::vector<bool> visited = std::vector<bool>(vertices.size(), false); std::vector<bool> visited = std::vector<bool>(vertices.size(), false);
std::vector<int> order = std::vector<int>(vertices.size(), 0); std::vector<int> order = std::vector<int>(vertices.size(), 0);
visited[0] = true; visited[0] = true;
@ -165,14 +338,45 @@ std::vector<Line> LineArtParser::generateFrame(juce::Array <juce::var> objects,
reorderedVertices.push_back(reorderedVertex); reorderedVertices.push_back(reorderedVertex);
} }
} }
return reorderedVertices;
allVertices.push_back(reorderedVertices);
} }
std::vector<Line> LineArtParser::generateFrame(juce::Array <juce::var> objects, double focalLength)
{
std::vector<std::vector<double>> allMatrices;
std::vector<std::vector<std::vector<OsciPoint>>> allVertices;
for (int i = 0; i < objects.size(); i++) {
auto verticesArray = *objects[i].getProperty("vertices", juce::Array<juce::var>()).getArray();
std::vector<std::vector<OsciPoint>> vertices;
for (auto& vertexArrayVar : verticesArray) {
vertices.push_back(std::vector<OsciPoint>());
auto& vertexArray = *vertexArrayVar.getArray();
for (auto& vertex : vertexArray) {
double x = vertex.getProperty("x", 0);
double y = vertex.getProperty("y", 0);
double z = vertex.getProperty("z", 0);
vertices[vertices.size() - 1].push_back(OsciPoint(x, y, z));
}
}
auto matrix = *objects[i].getProperty("matrix", juce::Array<juce::var>()).getArray();
allMatrices.push_back(std::vector<double>());
for (auto& value : matrix) {
allMatrices[i].push_back(value);
}
allVertices.push_back(reorderVertices(vertices));
}
return assembleFrame(allVertices, allMatrices, focalLength);
}
std::vector<Line> LineArtParser::assembleFrame(std::vector<std::vector<std::vector<OsciPoint>>> allVertices, std::vector<std::vector<double>> allMatrices, double focalLength) {
// generate a frame from the vertices and matrix // generate a frame from the vertices and matrix
std::vector<Line> frame; std::vector<Line> frame;
for (int i = 0; i < objects.size(); i++) { for (int i = 0; i < allVertices.size(); i++) {
for (int j = 0; j < allVertices[i].size(); j++) { for (int j = 0; j < allVertices[i].size(); j++) {
for (int k = 0; k < allVertices[i][j].size() - 1; k++) { for (int k = 0; k < allVertices[i][j].size() - 1; k++) {
auto start = allVertices[i][j][k]; auto start = allVertices[i][j][k];

Wyświetl plik

@ -8,6 +8,7 @@
class LineArtParser { class LineArtParser {
public: public:
LineArtParser(juce::String json); LineArtParser(juce::String json);
LineArtParser(char* data, int dataLength);
~LineArtParser(); ~LineArtParser();
void setFrame(int fNum); void setFrame(int fNum);
@ -16,6 +17,11 @@ public:
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); void parseJsonFrames(juce::String jsonStr);
void parseBinaryFrames(char* data, int dataLength);
double makeDouble(int64_t data);
void makeChars(int64_t data, char* chars);
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);
int frameNumber = 0; int frameNumber = 0;
std::vector<std::vector<Line>> frames; std::vector<std::vector<Line>> frames;
int numFrames = 0; int numFrames = 0;

Wyświetl plik

@ -30,7 +30,22 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
} else if (extension == ".lua") { } else if (extension == ".lua") {
lua = std::make_shared<LuaParser>(fileId, stream->readEntireStreamAsString(), errorCallback, fallbackLuaScript); lua = std::make_shared<LuaParser>(fileId, stream->readEntireStreamAsString(), errorCallback, fallbackLuaScript);
} else if (extension == ".gpla") { } else if (extension == ".gpla") {
juce::MemoryBlock buffer{};
int bytesRead = stream->readIntoMemoryBlock(buffer);
if (bytesRead < 8) return;
char* gplaData = (char*)buffer.getData();
const char tag[] = "GPLA ";
bool isBinary = true;
for (int i = 0; i < 8; i++) {
isBinary = isBinary && tag[i] == gplaData[i];
}
if (isBinary) {
gpla = std::make_shared<LineArtParser>(gplaData, bytesRead);
}
else {
stream->setPosition(0);
gpla = std::make_shared<LineArtParser>(stream->readEntireStreamAsString()); gpla = std::make_shared<LineArtParser>(stream->readEntireStreamAsString());
}
} else if (extension == ".gif" || extension == ".png" || extension == ".jpg" || extension == ".jpeg") { } else if (extension == ".gif" || extension == ".png" || extension == ".jpg" || extension == ".jpeg") {
juce::MemoryBlock buffer{}; juce::MemoryBlock buffer{};
int bytesRead = stream->readIntoMemoryBlock(buffer); int bytesRead = stream->readIntoMemoryBlock(buffer);

Wyświetl plik

@ -1,7 +1,7 @@
bl_info = { bl_info = {
"name": "osci-render", "name": "osci-render",
"author": "James Ball", "author": "James Ball",
"version": (1, 0, 3), "version": (1, 1, 0),
"blender": (3, 1, 2), "blender": (3, 1, 2),
"location": "View3D", "location": "View3D",
"description": "Addon to send gpencil frames over to osci-render", "description": "Addon to send gpencil frames over to osci-render",
@ -16,6 +16,7 @@ import bmesh
import socket import socket
import json import json
import atexit import atexit
import struct
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
@ -26,9 +27,14 @@ PORT = 51677
sock = None sock = None
GPLA_MAJOR = 2
GPLA_MINOR = 0
GPLA_PATCH = 0
class OBJECT_PT_osci_render_settings(bpy.types.Panel): class OBJECT_PT_osci_render_settings(bpy.types.Panel):
bl_idname = "OBJECT_PT_osci_render_settings" bl_idname = "OBJECT_PT_osci_render_settings"
bl_label = "osci-render settings" bl_label = "DEVELOPMENT osci-render settings"
bl_space_type = "PROPERTIES" bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW" bl_region_type = "WINDOW"
bl_context = "render" bl_context = "render"
@ -161,24 +167,132 @@ def get_frame_info():
@persistent @persistent
def save_scene_to_file(scene, file_path): def save_scene_to_file(scene, file_path):
return_frame = scene.frame_current return_frame = scene.frame_current
bin = bytearray()
scene_info = {"frames": []} # header
for frame in range(0, scene.frame_end - scene.frame_start): 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"))
for frame in range(0, scene.frame_end - scene.frame_start + 1):
scene.frame_set(frame + scene.frame_start) scene.frame_set(frame + scene.frame_start)
scene_info["frames"].append(get_frame_info()) bin.extend(get_frame_info_binary())
json_str = json.dumps(scene_info, separators=(',', ':')) bin.extend(("END GPLA").encode("utf8"))
if file_path is not None: if file_path is not None:
f = open(file_path, "w") with open(file_path, "wb") as f:
f.write(json_str) f.write(bytes(bin))
f.close()
else: else:
return 1 return 1
scene.frame_set(return_frame) scene.frame_set(return_frame)
return 0 return 0
def get_frame_info_binary():
frame_info = bytearray()
frame_info.extend(("FRAME ").encode("utf8"))
frame_info.extend(("focalLen").encode("utf8"))
frame_info.extend(struct.pack("d", -0.05 * bpy.data.cameras[0].lens))
frame_info.extend(("OBJECTS ").encode("utf8"))
if (bpy.app.version[0] > 4) or (bpy.app.version[0] == 4 and bpy.app.version[1] >= 3):
for obj in bpy.data.objects:
if obj.visible_get() and obj.type == 'GREASEPENCIL':
frame_info.extend(("OBJECT ").encode("utf8"))
# matrix
frame_info.extend(("MATRIX ").encode("utf8"))
camera_space = bpy.context.scene.camera.matrix_world.inverted() @ obj.matrix_world
for i in range(4):
for j in range(4):
frame_info.extend(struct.pack("d", camera_space[i][j]))
frame_info.extend(("DONE ").encode("utf8"))
# strokes
frame_info.extend(("STROKES ").encode("utf8"))
strokes = obj.data.layers.active.frames.data.current_frame().drawing.strokes
for stroke in strokes:
frame_info.extend(("STROKE ").encode("utf8"))
frame_info.extend(("vertexCt").encode("utf8"))
frame_info.extend(len(stroke.points).to_bytes(8, "little"))
frame_info.extend(("VERTICES").encode("utf8"))
for vert in stroke.points:
frame_info.extend(struct.pack("d", vert.position.x))
frame_info.extend(struct.pack("d", vert.position.y))
frame_info.extend(struct.pack("d", vert.position.z))
# VERTICES
frame_info.extend(("DONE ").encode("utf8"))
# STROKE
frame_info.extend(("DONE ").encode("utf8"))
# STROKES
frame_info.extend(("DONE ").encode("utf8"))
# OBJECT
frame_info.extend(("DONE ").encode("utf8"))
else:
for obj in bpy.data.objects:
if obj.visible_get() and obj.type == 'GPENCIL':
frame_info.extend(("OBJECT ").encode("utf8"))
# matrix
frame_info.extend(("MATRIX ").encode("utf8"))
camera_space = bpy.context.scene.camera.matrix_world.inverted() @ obj.matrix_world
for i in range(4):
for j in range(4):
frame_info.extend(camera_space[i][j].to_bytes(8, "little"))
# MATRIX
frame_info.extend(("DONE ").encode("utf8"))
# strokes
frame_info.extend(("STROKES ").encode("utf8"))
strokes = obj.data.layers.active.frames.data.active_frame.strokes
for stroke in strokes:
frame_info.extend(("STROKE ").encode("utf8"))
frame_info.extend(("vertexCt").encode("utf8"))
frame_info.extend(len(stroke.points).to_bytes(8, "little"))
frame_info.extend(("VERTICES").encode("utf8"))
for vert in stroke.points:
frame_info.extend(struct.pack("d", vert.co[0]))
frame_info.extend(struct.pack("d", vert.co[1]))
frame_info.extend(struct.pack("d", vert.co[2]))
# VERTICES
frame_info.extend(("DONE ").encode("utf8"))
# STROKE
frame_info.extend(("DONE ").encode("utf8"))
# STROKES
frame_info.extend(("DONE ").encode("utf8"))
# OBJECT
frame_info.extend(("DONE ").encode("utf8"))
# OBJECTS
frame_info.extend(("DONE ").encode("utf8"))
# FRAME
frame_info.extend(("DONE ").encode("utf8"))
return frame_info
@persistent @persistent
def send_scene_to_osci_render(scene): def send_scene_to_osci_render(scene):