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.setItalic(italic.getToggleState());
}
audioProcessor.openFile(audioProcessor.currentFile);
if (audioProcessor.currentFileId > 0 && audioProcessor.parsers[audioProcessor.currentFileId - 1]->getText() != nullptr) {
audioProcessor.openFile(audioProcessor.currentFile);
}
};
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!
void ShapeVoice::incrementShapeDrawing() {
if (frame.size() <= 0) return;
double length = currentShape < frame.size() ? frame[currentShape]->len : 0.0;
frameDrawn += lengthIncrement;
shapeDrawn += lengthIncrement;

Wyświetl plik

@ -5,10 +5,209 @@ LineArtParser::LineArtParser(juce::String 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() {
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) {
frames.clear();
numFrames = 0;
@ -97,6 +296,50 @@ std::vector<std::unique_ptr<Shape>> LineArtParser::draw() {
return tempShapes;
}
std::vector<std::vector<OsciPoint>> LineArtParser::reorderVertices(std::vector<std::vector<OsciPoint>> vertices) {
std::vector<std::vector<OsciPoint>> reorderedVertices;
if (vertices.size() > 0) {
std::vector<bool> visited = std::vector<bool>(vertices.size(), false);
std::vector<int> order = std::vector<int>(vertices.size(), 0);
visited[0] = true;
auto endPoint = vertices[0].back();
for (int i = 1; i < vertices.size(); i++) {
int minPath = 0;
double minDistance = 9999999;
for (int j = 0; j < vertices.size(); j++) {
if (!visited[j]) {
auto startPoint = vertices[j][0];
double diffX = endPoint.x - startPoint.x;
double diffY = endPoint.y - startPoint.y;
double diffZ = endPoint.z - startPoint.z;
double distance = std::sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ);
if (distance < minDistance) {
minPath = j;
minDistance = distance;
}
}
}
visited[minPath] = true;
order[i] = minPath;
endPoint = vertices[minPath].back();
}
for (int i = 0; i < vertices.size(); i++) {
std::vector<OsciPoint> reorderedVertex;
int index = order[i];
for (int j = 0; j < vertices[index].size(); j++) {
reorderedVertex.push_back(vertices[index][j]);
}
reorderedVertices.push_back(reorderedVertex);
}
}
return reorderedVertices;
}
std::vector<Line> LineArtParser::generateFrame(juce::Array <juce::var> objects, double focalLength)
{
@ -124,55 +367,16 @@ std::vector<Line> LineArtParser::generateFrame(juce::Array <juce::var> objects,
allMatrices[i].push_back(value);
}
std::vector<std::vector<OsciPoint>> reorderedVertices;
if (vertices.size() > 0 && matrix.size() == 16) {
std::vector<bool> visited = std::vector<bool>(vertices.size(), false);
std::vector<int> order = std::vector<int>(vertices.size(), 0);
visited[0] = true;
auto endPoint = vertices[0].back();
for (int i = 1; i < vertices.size(); i++) {
int minPath = 0;
double minDistance = 9999999;
for (int j = 0; j < vertices.size(); j++) {
if (!visited[j]) {
auto startPoint = vertices[j][0];
double diffX = endPoint.x - startPoint.x;
double diffY = endPoint.y - startPoint.y;
double diffZ = endPoint.z - startPoint.z;
double distance = std::sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ);
if (distance < minDistance) {
minPath = j;
minDistance = distance;
}
}
}
visited[minPath] = true;
order[i] = minPath;
endPoint = vertices[minPath].back();
}
for (int i = 0; i < vertices.size(); i++) {
std::vector<OsciPoint> reorderedVertex;
int index = order[i];
for (int j = 0; j < vertices[index].size(); j++) {
reorderedVertex.push_back(vertices[index][j]);
}
reorderedVertices.push_back(reorderedVertex);
}
}
allVertices.push_back(reorderedVertices);
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
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 k = 0; k < allVertices[i][j].size() - 1; k++) {
auto start = allVertices[i][j][k];

Wyświetl plik

@ -8,6 +8,7 @@
class LineArtParser {
public:
LineArtParser(juce::String json);
LineArtParser(char* data, int dataLength);
~LineArtParser();
void setFrame(int fNum);
@ -16,6 +17,11 @@ public:
static std::vector<Line> generateFrame(juce::Array < juce::var> objects, double focalLength);
private:
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;
std::vector<std::vector<Line>> frames;
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") {
lua = std::make_shared<LuaParser>(fileId, stream->readEntireStreamAsString(), errorCallback, fallbackLuaScript);
} else if (extension == ".gpla") {
gpla = std::make_shared<LineArtParser>(stream->readEntireStreamAsString());
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());
}
} else if (extension == ".gif" || extension == ".png" || extension == ".jpg" || extension == ".jpeg") {
juce::MemoryBlock buffer{};
int bytesRead = stream->readIntoMemoryBlock(buffer);

Wyświetl plik

@ -1,7 +1,7 @@
bl_info = {
"name": "osci-render",
"author": "James Ball",
"version": (1, 0, 3),
"version": (1, 1, 0),
"blender": (3, 1, 2),
"location": "View3D",
"description": "Addon to send gpencil frames over to osci-render",
@ -16,6 +16,7 @@ import bmesh
import socket
import json
import atexit
import struct
from bpy.props import StringProperty
from bpy.app.handlers import persistent
from bpy_extras.io_utils import ImportHelper
@ -26,9 +27,14 @@ PORT = 51677
sock = None
GPLA_MAJOR = 2
GPLA_MINOR = 0
GPLA_PATCH = 0
class OBJECT_PT_osci_render_settings(bpy.types.Panel):
bl_idname = "OBJECT_PT_osci_render_settings"
bl_label = "osci-render settings"
bl_label = "DEVELOPMENT osci-render settings"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
@ -157,28 +163,136 @@ def get_frame_info():
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()
scene_info = {"frames": []}
for frame in range(0, scene.frame_end - scene.frame_start):
# 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"))
for frame in range(0, scene.frame_end - scene.frame_start + 1):
scene.frame_set(frame + scene.frame_start)
scene_info["frames"].append(get_frame_info())
json_str = json.dumps(scene_info, separators=(',', ':'))
bin.extend(get_frame_info_binary())
bin.extend(("END GPLA").encode("utf8"))
if file_path is not None:
f = open(file_path, "w")
f.write(json_str)
f.close()
with open(file_path, "wb") as f:
f.write(bytes(bin))
else:
return 1
scene.frame_set(return_frame)
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
def send_scene_to_osci_render(scene):