From 7798483d15b32ebbdd0d9aa56c9faf477e93e937 Mon Sep 17 00:00:00 2001 From: Skye Terran Date: Mon, 30 Aug 2021 13:07:33 -0700 Subject: [PATCH] ton of tests --- README.md | 169 +++----------------------------- python/DEVOURTest.json | 72 +++++++++----- python/NeutrinoParser.ipynb | 170 +++++++++++++++++++++++++++++++++ python/NeutrinoTest_Cache.json | 18 ++++ python/ORCTest.ipynb | 135 +++++++++++++++++++------- python/Test.neu | 14 +++ 6 files changed, 363 insertions(+), 215 deletions(-) create mode 100644 python/NeutrinoParser.ipynb create mode 100644 python/NeutrinoTest_Cache.json create mode 100644 python/Test.neu diff --git a/README.md b/README.md index c19a8a5..fb7f3e7 100644 --- a/README.md +++ b/README.md @@ -40,164 +40,21 @@ Neutrino should have: ## Neutrino Alpha -- settings [dict] - - assets [dict] - *Defines properties relating to the on-disk assets referenced.* - - root_directory [string] - *The root directory/path which will be prepended to each of the file paths referenced. Setting this to "" will allow file paths to be absolute, but that's a terrible idea. Please don't do that.* - - units [dict] - *The unit systems used by this scene. Currently only length is relevant, but it's safer to keep this as a dictionary for future extensibility for other types of measurement.* - - length [string] - *The unit of measurement used by the scene ("centimeters", "meters", "feet", etc.)* - - axes [dict] - *Describes the handedness of the axes used in the scene (what the up/right/forward axes are)* - - up [string] - *Describes the up axis of the scene ("x", "-x", "y", "-y", "z", or "-z")* - - forward [string] - *Describes the right axis of the scene ("x", "-x", "y", "-y", "z", or "-z")* -- scene [dict] -*The hierarchy of objects in the scene, stored as a recursive tree of objects and their children.* - - {object name} [dict] - *The name of the object in the scene hierarchy is the same as its name in the objects dictionary which details its properties below.* - - transform [dict] - *The object's transform in the scene.* - - location [array] - *List declaring X, Y, Z location values.* - - rotation [array] - *List declaring X, Y, Z rotation values.* - - scale [array] - *List declaring X, Y, Z scale values.* - - children [dict] - *A named dictionary of the object's children.* - - {object name} [dict] - *A child object, following the same dictionary format as its parent (including its own children)* -- objects [dict] -*A dictionary of named objects in the scene, each containing their properties.* - - {object name} [dict] - *The name of the object in the scene.* - - type [string] - *The type of object ("null", "mesh", "spotlight", etc.)* - - properties [dict] [optional] - *Data specific to the object's type.* - - source_file [string] [optional] [used by: mesh] - *The relative file path of the source file for this object, for example: an FBX file for a mesh.* - - materials [array] [optional] [used by: mesh] - *List of the names of the materials applied to the mesh, in order of material assignment.* -- materials [dict] -*A list of named materials in the scene.* - - {material name} [dict] - - parameters [dict] - *A list of the material's parameters.* - - {parameter name} [string] - *The name of the material parameter.* - - type [string] - *The datatype of the parameter ("scalar", "vector", or "texture")* - - value [array or string] - *The value of the parameter, which depends on the parameter type:* - - *If it's a scalar: a float declaring the value.* - - *If it's a vector: an array of length 4 declaring RGBA values.* - - *If it's a texture: the relative file path of the texture map.* - ### Example ``` -{ - "settings": { - "assets": { - "root_directory": "/" - }, - "units": { - "length": "centimeters" - }, - "axes": { - "up": "z", - "forward": "x" - }, - }, - "scene": { - "Light_Group": { - "transform": {...}, - "children": { - "KeyLight": {...}, - "FillLight": {...} - } - }, - "LargeWindow": { - "transform": { - "location": [ - 88.61341857910156, - -0.7978610992431641, - 4.113158702850342 - ], - "rotation": [ - -45.0, - 0.0, - 89.9997 - ], - "scale": [ - 1.0, - 1.0, - 1.0 - ] - }, - "children": { - "WindowHandle": { - "transform": {...}, - "children": {...} - } - } - }, - "MetalDoorframe": { - "transform": {...}, - "children": { - "WoodDoor_Damaged": {...} - } - } - }, - "objects": { - "Light_Group": { - "type": "null" - }, - "KeyLight": { - "type": "spotlight", - "properties": {...} - }, - "FillLight": {...}, - "LargeWindow": { - "type": "mesh", - "properties": { - "source_file": "Meshes/SM_LargeWindow_A.obj", - "materials": [ - "M_Windows" - ] - } - }, - "WindowHandle": {...}, - "MetalDoorFrame": {...}, - "WoodDoor_Damaged": {...} - }, - "materials": { - "M_Windows": { - "parameters": { - "base_color": { - "type": "texture", - "value": "Textures/T_Windows_DiffColor.png" - }, - "roughness": { - "type": "scalar", - "value": 0.23 - }, - "normal": { - "type": "vector", - "value": [ - 0.5, - 0.5, - 1.0, - 1.0 - ] - } - } - } - } +@{ + string, + float, + int +} +#{ + 2:"100" +} +*{ + &0, + 0:"Hello, world! Here's a bunch of special characters: @#*{},,/|,{{}#@*", + 1:"512.0", + &0 } ``` diff --git a/python/DEVOURTest.json b/python/DEVOURTest.json index 9e73231..33b8302 100644 --- a/python/DEVOURTest.json +++ b/python/DEVOURTest.json @@ -1,29 +1,57 @@ { "shape": [ - [ - "0", - "1" - ], - [ - "0", - "1" - ], - [ - "0", - "2" - ], - [ - "0", - "2" - ], - [ - "0", - "1" - ] + "#0x0", + "#0x0", + "#0x1", + "#0x1", + "#0x0", + "#0x5", + "#0x5", + "#0xb", + "#0xe", + "#0xb", + "#0x10" ], "memory": [ - "float", 1.0, - 3.0 + 3.0, + "name", + "TestObject", + "visible", + { + "#0x2": "#0x3", + "#0x4": "#0x0" + }, + "position", + [ + 0.0, + 0.0, + 0.0 + ], + "rotation", + "scale", + [ + 1.0, + 1.0, + 1.0 + ], + { + "#0x6": "#0x7", + "#0x8": "#0x7", + "#0x9": "#0xa" + }, + "transform", + "#0xb", + { + "#0x2": "#0x3", + "#0x4": "#0x0", + "#0xc": "#0xd" + }, + "#0xe", + { + "#0x2": "#0x3", + "#0x4": "#0x0", + "#0xc": "#0xf" + } ] } \ No newline at end of file diff --git a/python/NeutrinoParser.ipynb b/python/NeutrinoParser.ipynb new file mode 100644 index 0000000..6cd2f6e --- /dev/null +++ b/python/NeutrinoParser.ipynb @@ -0,0 +1,170 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 109, + "source": [ + "# load up the test file\r\n", + "data = open(\"Test.neu\").read()\r\n", + "\r\n", + "# deal with newlines\r\n", + "data = data.split(\"\\n\")\r\n", + "for i, line in enumerate(data):\r\n", + " data[i] = line.strip()\r\n", + "data = \"\".join(data)\r\n", + "\r\n", + "data" + ], + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'@{string,float,int}#{2:\"100\"}*{&0,0:\"Hello, world! :@#*\",1:\"512.0\",&0}'" + ] + }, + "metadata": {}, + "execution_count": 109 + } + ], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 110, + "source": [ + "cache = {\r\n", + " \"names\": [],\r\n", + " \"cache\": [],\r\n", + " \"objects\": []\r\n", + "}\r\n", + "\r\n", + "# parse a string entry according to its type and return a dict\r\n", + "def parse_entry(entry_type, entry_value):\r\n", + " # convert values to proper types as needed\r\n", + " if entry_type == \"float\":\r\n", + " converted_value = float(entry_value)\r\n", + " elif entry_type == \"int\":\r\n", + " converted_value = int(entry_value)\r\n", + " else:\r\n", + " converted_value = entry_value\r\n", + "\r\n", + " # return a dictionary of the parsed entry\r\n", + " return {\"type\": entry_type, \"value\": converted_value}\r\n", + "\r\n", + "# iterate through each character in the raw data and create a cache of parsed strings\r\n", + "stage = \"\"\r\n", + "entry_type = \"\"\r\n", + "entry_value = \"\"\r\n", + "consume = False\r\n", + "is_literal = False\r\n", + "is_reference = False\r\n", + "for char in data:\r\n", + " if char == '\"':\r\n", + " # enter/exit literal consumption (handle special characters in values)\r\n", + " is_literal = not is_literal\r\n", + " continue\r\n", + " # ignore special characters if they're within a literal value\r\n", + " if not is_literal:\r\n", + " if char == \"@\":\r\n", + " stage = \"names\"\r\n", + " continue\r\n", + " elif char == \"*\":\r\n", + " stage = \"objects\"\r\n", + " continue\r\n", + " elif char == \"#\":\r\n", + " stage = \"cache\"\r\n", + " continue\r\n", + " elif char == \"{\":\r\n", + " # start consuming at the start of each stage\r\n", + " consume = True\r\n", + " continue\r\n", + " elif char == \"}\":\r\n", + " # commit entry\r\n", + " if stage != \"names\":\r\n", + " cache[stage].append(parse_entry(entry_type, entry_value))\r\n", + " else:\r\n", + " cache[stage].append(entry_value)\r\n", + " entry_value = \"\"\r\n", + "\r\n", + " is_reference = False\r\n", + "\r\n", + " # stop consuming at the end of each stage\r\n", + " consume = False\r\n", + " elif char == \",\":\r\n", + " # commit entry\r\n", + " if stage != \"names\":\r\n", + " cache[stage].append(parse_entry(entry_type, entry_value))\r\n", + " else:\r\n", + " cache[stage].append(entry_value)\r\n", + " entry_value = \"\"\r\n", + " \r\n", + " is_reference = False\r\n", + "\r\n", + " continue\r\n", + " elif char == \":\":\r\n", + " # handle names/types\r\n", + " entry_type = cache[\"names\"][int(entry_value, base = 16)]\r\n", + " entry_value = \"\"\r\n", + " continue\r\n", + "\r\n", + " if consume:\r\n", + " # handle cache references\r\n", + " if entry_value == \"&\":\r\n", + " cached_object = cache[\"cache\"][int(char, base = 16)]\r\n", + " entry_type = cached_object[\"type\"]\r\n", + " entry_value = cached_object[\"value\"]\r\n", + " continue\r\n", + " else:\r\n", + " entry_value += char" + ], + "outputs": [], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 111, + "source": [ + "graph = cache[\"objects\"]" + ], + "outputs": [], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 112, + "source": [ + "# DEBUG\r\n", + "import json\r\n", + "with open(\"NeutrinoTest_Cache.json\", \"w\") as outfile:\r\n", + " json.dump(graph, outfile, indent = 4)" + ], + "outputs": [], + "metadata": {} + } + ], + "metadata": { + "orig_nbformat": 4, + "language_info": { + "name": "python", + "version": "3.7.8", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "pygments_lexer": "ipython3", + "nbconvert_exporter": "python", + "file_extension": ".py" + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3.7.8 64-bit" + }, + "interpreter": { + "hash": "57baa5815c940fdaff4d14510622de9616cae602444507ba5d0b6727c008cbd6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/python/NeutrinoTest_Cache.json b/python/NeutrinoTest_Cache.json new file mode 100644 index 0000000..6656408 --- /dev/null +++ b/python/NeutrinoTest_Cache.json @@ -0,0 +1,18 @@ +[ + { + "type": "int", + "value": 100 + }, + { + "type": "string", + "value": "Hello, world! Here's a bunch of special characters: @#*{},,/|,{{}#@*" + }, + { + "type": "float", + "value": 512.0 + }, + { + "type": "int", + "value": 100 + } +] \ No newline at end of file diff --git a/python/ORCTest.ipynb b/python/ORCTest.ipynb index c2e8fd1..14ed367 100644 --- a/python/ORCTest.ipynb +++ b/python/ORCTest.ipynb @@ -20,61 +20,122 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 98, "source": [ - "class DevourObject:\r\n", - " def __init__(self, type, value):\r\n", - " self.type = type\r\n", - " self.value = value\r\n", - "\r\n", - "class DevourGraph:\r\n", + "class Graph:\r\n", " def __init__(self):\r\n", " self.graph = []\r\n", + " self.cache = {\r\n", + " \"shape\": [],\r\n", + " \"memory\": []\r\n", + " }\r\n", "\r\n", " # adds a new object to the graph\r\n", - " def add(self, type, value):\r\n", - " self.graph.append(DevourObject(type, value))\r\n", + " def add(self, node):\r\n", + " # add to graph\r\n", + " self.graph.append(node)\r\n", + "\r\n", + " def redirect_node(self, node):\r\n", + " shape = self.cache[\"shape\"]\r\n", + " memory = self.cache[\"memory\"]\r\n", + "\r\n", + " # for dictionaries, add each member node\r\n", + " if type(node) == dict:\r\n", + " # cache keys and values\r\n", + " new_dict = {}\r\n", + " for key, value in node.items():\r\n", + " if type(value) == dict:\r\n", + " value = self.redirect_node(value)\r\n", + "\r\n", + " # add dict key to memory\r\n", + " if key not in memory:\r\n", + " memory.append(key)\r\n", + " key_index = \"#\" + hex(len(memory) - 1)\r\n", + " else:\r\n", + " key_index = \"#\" + hex(memory.index(key))\r\n", + "\r\n", + " # add dict value to memory\r\n", + " if value not in memory:\r\n", + " memory.append(value)\r\n", + " value_index = \"#\" + hex(len(memory) - 1)\r\n", + " else:\r\n", + " value_index = \"#\" + hex(memory.index(value))\r\n", + "\r\n", + " new_dict[key_index] = value_index\r\n", + "\r\n", + " # check if the dict is in memory already\r\n", + " if new_dict in memory:\r\n", + " node = \"#\" + hex(memory.index(new_dict))\r\n", + " else:\r\n", + " node = new_dict\r\n", + "\r\n", + " # redirect object to virtual memory\r\n", + " if type(node) == str:\r\n", + " is_pointer = node[0] == \"#\"\r\n", + " else:\r\n", + " is_pointer = False\r\n", + " \r\n", + " if not is_pointer:\r\n", + " if node not in memory:\r\n", + " memory.append(node)\r\n", + " value_pointer = \"#\" + hex(len(memory) - 1)\r\n", + " else:\r\n", + " value_pointer = \"#\" + hex(memory.index(node))\r\n", + "\r\n", + " # add a redirector to shape\r\n", + " shape.append(value_pointer)\r\n", + "\r\n", + " # return a pointer to the node\r\n", + " return \"#\" + hex(len(memory) - 1)\r\n", "\r\n", " # exports the graph as a single dictionary object\r\n", " def serialize(self):\r\n", - " shape = []\r\n", - " memory = []\r\n", - "\r\n", " # serialize DevourObject instances\r\n", - " for object in self.graph:\r\n", - " # redirect the type name to virtual memory\r\n", - " if object.type not in memory:\r\n", - " memory.append(object.type)\r\n", - " type_pointer = hex(len(memory) - 1)[2:]\r\n", - " else:\r\n", - " type_pointer = hex(memory.index(object.type))[2:]\r\n", - " \r\n", - " # redirect object to virtual memory\r\n", - " if object.value not in memory:\r\n", - " memory.append(object.value)\r\n", - " value_pointer = hex(len(memory) - 1)[2:]\r\n", - " else:\r\n", - " value_pointer = hex(memory.index(object.value))[2:]\r\n", + " for node in self.graph:\r\n", + " self.redirect_node(node)\r\n", "\r\n", - " # add a redirector to shape\r\n", - " shape.append((type_pointer, value_pointer))\r\n", - "\r\n", - " return {\"shape\": shape, \"memory\": memory}" + " return self.cache" ], "outputs": [], "metadata": {} }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 99, "source": [ "# test\r\n", - "graph = DevourGraph()\r\n", - "graph.add(\"float\", 1.0)\r\n", - "graph.add(\"float\", 1.0)\r\n", - "graph.add(\"float\", 3.0)\r\n", - "graph.add(\"float\", 3.0)\r\n", - "graph.add(\"float\", 1.0)\r\n", + "graph = Graph()\r\n", + "graph.add(1.0)\r\n", + "graph.add(1.0)\r\n", + "graph.add(3.0)\r\n", + "graph.add(3.0)\r\n", + "graph.add(1.0)\r\n", + "graph.add({\r\n", + " \"name\": \"TestObject\",\r\n", + " \"visible\": True\r\n", + " })\r\n", + "graph.add({\r\n", + " \"name\": \"TestObject\",\r\n", + " \"visible\": True\r\n", + " })\r\n", + "graph.add({\r\n", + " \"name\": \"TestObject\",\r\n", + " \"visible\": True,\r\n", + " \"transform\": {\r\n", + " \"position\": [0.0, 0.0, 0.0],\r\n", + " \"rotation\": [0.0, 0.0, 0.0],\r\n", + " \"scale\": [1.0, 1.0, 1.0]\r\n", + " }\r\n", + " })\r\n", + "graph.add({\r\n", + " \"name\": \"TestObject\",\r\n", + " \"visible\": True,\r\n", + " \"transform\": {\r\n", + " \"position\": [0.0, 0.0, 0.0],\r\n", + " \"rotation\": [0.0, 0.0, 0.0],\r\n", + " \"scale\": [1.0, 1.0, 1.0]\r\n", + " }\r\n", + " })\r\n", "\r\n", "# write to disk\r\n", "import json\r\n", diff --git a/python/Test.neu b/python/Test.neu new file mode 100644 index 0000000..688260a --- /dev/null +++ b/python/Test.neu @@ -0,0 +1,14 @@ +@{ + string, + float, + int +} +#{ + 2:"100" +} +*{ + &0, + 0:"Hello, world! Here's a bunch of special characters: @#*{},,/|,{{}#@*", + 1:"512.0", + &0 +} \ No newline at end of file