feat: Quaternions + cv!
This commit is contained in:
parent
52158d293e
commit
e10a07c784
3 changed files with 4180 additions and 164 deletions
254
cv.json
Normal file
254
cv.json
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
{
|
||||||
|
"contacts": {
|
||||||
|
"name": "Violette Paulin",
|
||||||
|
"email": "vi@violette.town",
|
||||||
|
"website": "violette.town",
|
||||||
|
"nationality": "French",
|
||||||
|
"git": "https://git.violette.town/violette"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"name": "Programming Languages",
|
||||||
|
"items": [
|
||||||
|
"C / C++ / Rust",
|
||||||
|
"Java",
|
||||||
|
"Python / Shell Scripting",
|
||||||
|
"JavaScript / TypeScript"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Data Analysis",
|
||||||
|
"items": [
|
||||||
|
"Data Visualization",
|
||||||
|
"Statistics"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "System Development",
|
||||||
|
"items": [
|
||||||
|
"Embedded",
|
||||||
|
"Distributed Systems",
|
||||||
|
"BSD / Linux / Unix like"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Database Management",
|
||||||
|
"items": [
|
||||||
|
"noSQL",
|
||||||
|
"SQL",
|
||||||
|
"Blockchain"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Web Development",
|
||||||
|
"items": [
|
||||||
|
"Spring",
|
||||||
|
"Angular.js"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"name": "French",
|
||||||
|
"proficiency": 5,
|
||||||
|
"comment": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "English",
|
||||||
|
"proficiency": 4,
|
||||||
|
"comment": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "German",
|
||||||
|
"proficiency": 2,
|
||||||
|
"comment": "None"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"jobs": [
|
||||||
|
{
|
||||||
|
"position": "R & D, Software Developer Intern",
|
||||||
|
"company": {
|
||||||
|
"name": "TransTech innovations",
|
||||||
|
"link": "https://transtechinnovations.com"
|
||||||
|
},
|
||||||
|
"from": "2024 Sept.",
|
||||||
|
"to": "2025 Feb.",
|
||||||
|
"description": [
|
||||||
|
"Creating a parser for a proprietary logger (java spring boot, angular JS)",
|
||||||
|
"Creating a proof of concept for a module in embedded devices (C++23)"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Embedded systems",
|
||||||
|
"Fullstack",
|
||||||
|
"Java Spring Boot",
|
||||||
|
"Angular",
|
||||||
|
"C / C++"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": "SysAdmin",
|
||||||
|
"company": {
|
||||||
|
"name": "TransEstrie",
|
||||||
|
"link": "https://transestrie.org"
|
||||||
|
},
|
||||||
|
"from": "2024 Jul",
|
||||||
|
"to": "2024 Aug.",
|
||||||
|
"description": [
|
||||||
|
"Maintaining and upgrading the internal network",
|
||||||
|
"Setting up diverse services (NextCloud, VPN, securing data, creating backups...)"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"SysAdmin",
|
||||||
|
"Autonomy",
|
||||||
|
"Self Teaching"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": "R & D, Software Developer Intern",
|
||||||
|
"company": {
|
||||||
|
"name": "LISTIC Annecy",
|
||||||
|
"link": "https://www.univ-smb.fr/listic/en/"
|
||||||
|
},
|
||||||
|
"from": "2023 May.",
|
||||||
|
"to": "2023 Aug.",
|
||||||
|
"description": [
|
||||||
|
"Building a distributed caching system, and storing logs within a Blockchain",
|
||||||
|
"Internship in a informatic research laboratory",
|
||||||
|
"Suppervised by Sébastien Monnet & Kavé Salamatian"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Distributed System design",
|
||||||
|
"Rust",
|
||||||
|
"Blockchain Programming",
|
||||||
|
"Web Programming - Backend & Frontend",
|
||||||
|
"Self Teaching"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": "SEO Agent",
|
||||||
|
"company": {
|
||||||
|
"name": "BIWA Annecy",
|
||||||
|
"link": "https://box-evidence.com"
|
||||||
|
},
|
||||||
|
"from": "2022 May.",
|
||||||
|
"to": "2022 Jul.",
|
||||||
|
"description": [
|
||||||
|
"Optimise web ranking of different websites"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Autonomy",
|
||||||
|
"SEO"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"education": [
|
||||||
|
{
|
||||||
|
"university": {
|
||||||
|
"name": "Polytech Annecy Chambéry",
|
||||||
|
"link": "https://www.polytech.univ-smb.fr/"
|
||||||
|
},
|
||||||
|
"degree": "Engineering Degree (France)",
|
||||||
|
"major": "Computer Science",
|
||||||
|
"track": "Informatic Data Usage",
|
||||||
|
"from": "2021",
|
||||||
|
"to": "Current"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"university": {
|
||||||
|
"name": "Sherbrooke University",
|
||||||
|
"link": "https://usherbrooke.ca"
|
||||||
|
},
|
||||||
|
"degree": "M.Sc.",
|
||||||
|
"major": "Computer Science",
|
||||||
|
"track": "None",
|
||||||
|
"from": "2023",
|
||||||
|
"to": "Current"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"projects": {
|
||||||
|
"personnal": [
|
||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"name": "Discsord Bot",
|
||||||
|
"link": "https://github.com/storca/vhbot"
|
||||||
|
},
|
||||||
|
"description": [
|
||||||
|
"Automate actions during class",
|
||||||
|
"Useful for our teachers",
|
||||||
|
"List people attending class",
|
||||||
|
"Wishes birthday to our teachers"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Python",
|
||||||
|
"Teamwork",
|
||||||
|
"Git"
|
||||||
|
],
|
||||||
|
"year": 2020
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"school": [
|
||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"name": "DHTea",
|
||||||
|
"link": "https://github.com/phoqueEberlue/DHTea"
|
||||||
|
},
|
||||||
|
"description": [
|
||||||
|
"Distributed hash table",
|
||||||
|
"Written in rust from scratch",
|
||||||
|
"Stores files / data"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Rust",
|
||||||
|
"Distributed system",
|
||||||
|
"Self Teaching",
|
||||||
|
"Git",
|
||||||
|
"Shell scripting"
|
||||||
|
],
|
||||||
|
"year": 2023
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"name": "Proxy",
|
||||||
|
"link": "https://github.com/TheBigBlase/proxy"
|
||||||
|
},
|
||||||
|
"description": [
|
||||||
|
"Proxy",
|
||||||
|
"Written in Python and Rust"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Teamwork / Team management",
|
||||||
|
"Git"
|
||||||
|
],
|
||||||
|
"year": 2022
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"name": "kr00k",
|
||||||
|
"link": "https://github.com/thebigblase/kr00k"
|
||||||
|
},
|
||||||
|
"description": [
|
||||||
|
"Proof of concept for a security vulnerability (CVE-2019-15126)",
|
||||||
|
"Used as my final projects for MPSI / MP classes."
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Cybersecurity",
|
||||||
|
"Python",
|
||||||
|
"Self Teaching"
|
||||||
|
],
|
||||||
|
"year": 2021
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hobbies": {
|
||||||
|
"tech": [
|
||||||
|
"seeing how things are done under the hood",
|
||||||
|
"low level-ish dev",
|
||||||
|
"resurecting old tech"
|
||||||
|
],
|
||||||
|
"other": [
|
||||||
|
"music",
|
||||||
|
"playing the guitar",
|
||||||
|
"cooking"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
628
main.c
628
main.c
|
@ -5,17 +5,22 @@
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include "json.h"
|
||||||
|
|
||||||
#define SCREEN_WIDTH 100
|
#define SCREEN_WIDTH 80
|
||||||
#define SCREEN_HEIGHT 50
|
#define SCREEN_HEIGHT 32
|
||||||
#define CUBE_WIDTH 10
|
#define CUBE_WIDTH 10
|
||||||
|
|
||||||
#define FACE_FRONT '#'
|
enum faces {
|
||||||
#define FACE_BACK '0'
|
FACE_FRONT = 0,
|
||||||
#define FACE_BOTTOM '!'
|
FACE_LEFT,
|
||||||
#define FACE_LEFT '%'
|
FACE_RIGHT,
|
||||||
#define FACE_RIGHT '@'
|
FACE_BOTTOM,
|
||||||
#define FACE_TOP '-'
|
FACE_TOP,
|
||||||
|
FACE_BACK,
|
||||||
|
NUM_FACES,
|
||||||
|
};
|
||||||
|
|
||||||
#define STEP 0.2
|
#define STEP 0.2
|
||||||
|
|
||||||
|
@ -28,101 +33,306 @@
|
||||||
#define K1 100
|
#define K1 100
|
||||||
#define K2 50
|
#define K2 50
|
||||||
|
|
||||||
#define _RESET_ANGLE(input) do {\
|
#define SQ(n) n * n
|
||||||
Angle.currentTarget = 0;\
|
|
||||||
input = 0; \
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
#define RESET_A_ANGLE(input) do {\
|
#define GET_ROTATE_X_Q(a) ({ double _a = (a) ; struct Quaternions q = {}; q.w = cos(_a/2); q.x = sin(_a/2); q; })
|
||||||
Angle.A = Angle.ATarget; \
|
#define GET_ROTATE_Y_Q(a) ({ double _a = (a) ; struct Quaternions q = {}; q.w = cos(_a/2); q.y = sin(_a/2); q; })
|
||||||
_RESET_ANGLE(input); \
|
#define GET_ROTATE_Z_Q(a) ({ double _a = (a) ; struct Quaternions q = {}; q.w = cos(_a/2); q.z = sin(_a/2); q; })
|
||||||
} while (0);
|
|
||||||
#define RESET_B_ANGLE(input) do {\
|
//TODO Idle animations
|
||||||
Angle.B = Angle.BTarget; \
|
#define IS_IDLE (Idle.x || Idle.y || Idle.z)
|
||||||
_RESET_ANGLE(input); \
|
#define RESET_IDLE {Idle.x = 0; Idle.y = 0; Idle.z = 0;}
|
||||||
} while (0);
|
|
||||||
#define RESET_C_ANGLE(input) do {\
|
|
||||||
Angle.C = Angle.CTarget; \
|
|
||||||
_RESET_ANGLE(input); \
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
double A, B, C;
|
char x;
|
||||||
double ATarget, BTarget, CTarget;
|
char y;
|
||||||
char currentTarget;
|
char z;
|
||||||
double cosA, sinA;
|
} Idle;
|
||||||
double cosB, sinB;
|
|
||||||
double cosC, sinC;
|
|
||||||
} Angle;
|
|
||||||
|
|
||||||
void initAngles() {
|
|
||||||
Angle.A = 0, Angle.B = 0, Angle.C = 0;
|
|
||||||
Angle.ATarget = 0, Angle.BTarget = 0, Angle.CTarget = 0;
|
|
||||||
Angle.currentTarget = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double zBuffer[SCREEN_HEIGHT * SCREEN_WIDTH];
|
struct Quaternions {
|
||||||
char output[SCREEN_HEIGHT * SCREEN_WIDTH];
|
double w;
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} Target, Current, Last;
|
||||||
|
|
||||||
|
double interpolationStep = 0;
|
||||||
|
double zBuffer[SCREEN_HEIGHT * SCREEN_WIDTH];
|
||||||
|
char output[SCREEN_HEIGHT * SCREEN_WIDTH];
|
||||||
|
|
||||||
static volatile char shouldBreak = 1;
|
static volatile char shouldBreak = 1;
|
||||||
|
static volatile char currentlyMoving = 0;
|
||||||
static struct termios originalTerm = {};
|
static struct termios originalTerm = {};
|
||||||
|
|
||||||
double calcX(double x, double y, double z){
|
void
|
||||||
return
|
normalize(struct Quaternions *q)
|
||||||
x * Angle.cosC * Angle.cosB +
|
{
|
||||||
y * Angle.sinC * Angle.cosB
|
double n = sqrt(SQ(q->w) + SQ(q->x) + SQ(q->y) + SQ(q->z));
|
||||||
-z * Angle.sinB;
|
if (n == 0)
|
||||||
|
return;
|
||||||
|
q->w /= n;
|
||||||
|
q->x /= n;
|
||||||
|
q->y /= n;
|
||||||
|
q->z /= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
double calcY(double x, double y, double z){
|
struct Quaternions
|
||||||
return
|
mult(struct Quaternions q, double x, double y, double z)
|
||||||
x * (Angle.cosC * Angle.sinB * Angle.sinA - Angle.sinC * Angle.cosA) +
|
{
|
||||||
y * (Angle.sinC * Angle.sinB * Angle.sinA + Angle.cosC * Angle.cosA) +
|
//p = q * p * qbar
|
||||||
z * Angle.cosB * Angle.sinA;
|
struct Quaternions res;
|
||||||
|
|
||||||
|
res.w = 0;
|
||||||
|
res.x = x * (SQ(q.w) + SQ(q.x) - SQ(q.y) - SQ(q.z))
|
||||||
|
+ 2 * y * (q.x * q.y - q.w * q.z)
|
||||||
|
+ 2 * z * (q.x * q.z + q.w * q.y);
|
||||||
|
|
||||||
|
res.y = 2 * x * (q.x * q.y + q.w * q.z)
|
||||||
|
+ y * (SQ(q.w) - SQ(q.x) + SQ(q.y) - SQ(q.z))
|
||||||
|
+ 2 * z * (q.y * q.z - q.w * q.x);
|
||||||
|
|
||||||
|
res.z = 2 * x * (q.x * q.z - q.w * q.y)
|
||||||
|
+ 2 * y * (q.y * q.z + q.w * q.x)
|
||||||
|
+ z * (SQ(q.w) - SQ(q.x) - SQ(q.y) + SQ(q.z));
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
double calcZ(double x, double y, double z){
|
struct Quaternions
|
||||||
return
|
multQ(struct Quaternions p, struct Quaternions q)
|
||||||
x * (Angle.cosC * Angle.sinB * Angle.cosA + Angle.sinC * Angle.sinA) +
|
{
|
||||||
y * (Angle.sinC * Angle.sinB * Angle.cosA - Angle.cosC * Angle.sinA) +
|
if (p.x <= 0.001 && p.x >= -0.001
|
||||||
z * Angle.cosB * Angle.cosA;
|
&& p.y <= 0.001 && p.y >= -0.001
|
||||||
|
&& p.z <= 0.001 && p.z >= -0.001)
|
||||||
|
return q;
|
||||||
|
if (q.x <= 0.001 && q.x >= -0.001
|
||||||
|
&& q.y <= 0.001 && q.y >= -0.001
|
||||||
|
&& q.z <= 0.001 && q.z >= -0.001)
|
||||||
|
return p;
|
||||||
|
|
||||||
|
struct Quaternions res = {
|
||||||
|
.w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z,
|
||||||
|
.x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y,
|
||||||
|
.y = p.w * q.y - p.x * q.z + p.y * q.w + p.z * q.x,
|
||||||
|
.z = p.w * q.z + p.x * q.y - p.y * q.x + p.z * q.w,
|
||||||
|
};
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcAngle(){
|
char *
|
||||||
Angle.cosA = cos(Angle.A);
|
chooseColor(char c)
|
||||||
Angle.sinA = sin(Angle.A);
|
{
|
||||||
Angle.cosB = cos(Angle.B);
|
switch (c) {
|
||||||
Angle.sinB = sin(Angle.B);
|
case FACE_FRONT:
|
||||||
Angle.cosC = cos(Angle.C);
|
return "\033[31;1;4m#\033[0m";
|
||||||
Angle.sinC = sin(Angle.C);
|
case FACE_BACK:
|
||||||
}
|
return "\033[32;1;4m0\033[0m";
|
||||||
|
case FACE_BOTTOM:
|
||||||
char *chooseColor(char c){
|
return "\033[33;1;4m!\033[0m";
|
||||||
switch(c) {
|
case FACE_LEFT:
|
||||||
case '#':
|
return "\033[34;1;4m%\033[0m";
|
||||||
return "\033[31;1;4m#\033[0m";
|
case FACE_RIGHT:
|
||||||
case '0':
|
return "\033[35;1;4m@\033[0m";
|
||||||
return "\033[32;1;4m0\033[0m";
|
case FACE_TOP:
|
||||||
case '!':
|
return "\033[36;1;4m-\033[0m";
|
||||||
return "\033[33;1;4m!\033[0m";
|
case ' ':
|
||||||
case '%':
|
return " ";
|
||||||
return "\033[34;1;4m%\033[0m";
|
default:
|
||||||
case '@':
|
//unused, but issues no warning
|
||||||
return "\033[35;1;4m@\033[0m";
|
|
||||||
case '-':
|
|
||||||
return "\033[36;1;4m-\033[0m";
|
|
||||||
case ' ':
|
|
||||||
return " ";
|
|
||||||
default: // unused, but issues no warning
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAscii() {
|
char
|
||||||
|
chooseMainFace()
|
||||||
|
{
|
||||||
|
int total;
|
||||||
|
int faces[NUM_FACES] = {0};
|
||||||
|
|
||||||
|
for (int k = 0; k < SCREEN_WIDTH * SCREEN_HEIGHT; ++k)
|
||||||
|
if (output[k] >= 0 && output[k] < NUM_FACES) {
|
||||||
|
faces[output[k]]++;
|
||||||
|
++total;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max = 0, idx = 0;
|
||||||
|
for (int k = 0; k < NUM_FACES; ++k)
|
||||||
|
if (faces[k] > max) {
|
||||||
|
max = faces[k];
|
||||||
|
idx = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return max > total * 0.9 ? idx : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printFrontFace(struct json_object_element_s *elt)
|
||||||
|
{
|
||||||
|
printf("Contacts:\r\n");
|
||||||
|
struct json_object_element_s *obj = json_value_as_object(elt->value)->start;
|
||||||
|
while (obj != NULL) {
|
||||||
|
struct json_string_s *str = json_value_as_string(obj->value);
|
||||||
|
printf(" %s: %s\r\n", obj->name->string, str->string);
|
||||||
|
obj = obj->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printLefttFace(struct json_object_element_s *elt)
|
||||||
|
{
|
||||||
|
printf("Skills:\r\n");
|
||||||
|
struct json_array_element_s *arr = json_value_as_array(elt->value)->start;
|
||||||
|
while (arr != NULL) {
|
||||||
|
struct json_object_element_s *obj = json_value_as_object(arr->value)->start;
|
||||||
|
printf(" %s\r\n", json_value_as_string(obj->value)->string);
|
||||||
|
struct json_array_element_s *arr2 = json_value_as_array(obj->next->value)->start;
|
||||||
|
while (arr2 != NULL) {
|
||||||
|
struct json_string_s *str = json_value_as_string(arr2->value);
|
||||||
|
printf(" %s\r\n", str->string);
|
||||||
|
arr2 = arr2->next;
|
||||||
|
}
|
||||||
|
arr = arr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printRightFace(struct json_object_element_s *elt)
|
||||||
|
{
|
||||||
|
printf("Languages:\r\n");
|
||||||
|
struct json_array_element_s *arr = json_value_as_array(elt->value)->start;
|
||||||
|
while (arr != NULL) {
|
||||||
|
struct json_object_element_s *obj = json_value_as_object(arr->value)->start;
|
||||||
|
printf(" %s: %s / 5\r\n", json_value_as_string(obj->value)->string, json_value_as_number(obj->next->value)->number);
|
||||||
|
arr = arr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printBottomFace(struct json_object_element_s *elt)
|
||||||
|
{
|
||||||
|
printf("Professional experience:\r\n");
|
||||||
|
struct json_array_element_s *arr = json_value_as_array(elt->value)->start;
|
||||||
|
while (arr != NULL) {
|
||||||
|
struct json_object_element_s *obj = json_value_as_object(arr->value)->start;
|
||||||
|
struct json_string_s *position = json_value_as_string(obj->value);
|
||||||
|
struct json_object_element_s *company = json_value_as_object(obj->next->value)->start;
|
||||||
|
struct json_string_s *from = json_value_as_string(obj->next->next->value);
|
||||||
|
struct json_string_s *to = json_value_as_string(obj->next->next->next->value);
|
||||||
|
struct json_array_element_s *descr = json_value_as_array(obj->next->next->next->next->value)->start;
|
||||||
|
|
||||||
|
printf(" %s: %s ; %s -> %s\r\n", json_value_as_string(company->value)->string, position->string, from->string, to->string);
|
||||||
|
while (descr != NULL) {
|
||||||
|
printf(" %s\r\n", json_value_as_string(descr->value)->string);
|
||||||
|
descr = descr->next;
|
||||||
|
}
|
||||||
|
printf("\r\n");
|
||||||
|
arr = arr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printBackFace(struct json_object_element_s *elt)
|
||||||
|
{
|
||||||
|
printf("Projects:\r\n");
|
||||||
|
struct json_object_element_s *obj = json_value_as_object(elt->value)->start;
|
||||||
|
//ignore personnal projects
|
||||||
|
printf(" - This cube! its made using Quaternion for 3d rotation, "
|
||||||
|
"from scratch (except the CV text), in C\r\n");
|
||||||
|
printf("\r\n");
|
||||||
|
struct json_array_element_s *arr = json_value_as_array(obj->next->value)->start;
|
||||||
|
while (arr != NULL) {
|
||||||
|
struct json_string_s *main = json_value_as_string(json_value_as_object(arr->value)->start->value);
|
||||||
|
struct json_string_s *link = json_value_as_string(json_value_as_object(arr->value)->start->next->value);
|
||||||
|
struct json_array_element_s *descr = json_value_as_array(json_value_as_object(arr->value)->start->next->value)->start;
|
||||||
|
struct json_number_s *year = json_value_as_number(json_value_as_object(arr->value)->start->next->next->next->value);
|
||||||
|
|
||||||
|
printf(" - %s, %s\r\n", json_value_as_string(descr->value)->string, year->number);
|
||||||
|
while (descr != NULL) {
|
||||||
|
printf(" o %s\r\n", json_value_as_string(descr->value)->string);
|
||||||
|
descr = descr->next;
|
||||||
|
}
|
||||||
|
printf("\r\n");
|
||||||
|
arr = arr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printTopFace(struct json_object_element_s *elt)
|
||||||
|
{
|
||||||
|
printf("Education:\r\n");
|
||||||
|
struct json_array_element_s *arr = json_value_as_array(elt->value)->start;
|
||||||
|
while (arr != NULL) {
|
||||||
|
struct json_object_element_s *obj = json_value_as_object(arr->value)->start;
|
||||||
|
struct json_string_s *univ_name =
|
||||||
|
json_value_as_string(json_value_as_object(obj->value)->start->value);
|
||||||
|
struct json_string_s *degree = json_value_as_string(obj->next->value);
|
||||||
|
struct json_string_s *major = json_value_as_string(obj->next->next->value);
|
||||||
|
struct json_string_s *track =
|
||||||
|
json_value_as_string(obj->next->next->next->value);
|
||||||
|
struct json_string_s *from =
|
||||||
|
json_value_as_string(obj->next->next->next->next->value);
|
||||||
|
struct json_string_s *to =
|
||||||
|
json_value_as_string(obj->next->next->next->next->next->value);
|
||||||
|
|
||||||
|
printf(" %s: %s -> %s \r\n", univ_name->string, from->string, to->string);
|
||||||
|
if (track == NULL || strcmp(track->string, "None") == 0)
|
||||||
|
printf(" %s, %s\r\n", degree->string, major->string);
|
||||||
|
else
|
||||||
|
printf(" %s %s, %s\r\n", degree->string, major->string, track->string);
|
||||||
|
printf("\r\n");
|
||||||
|
arr = arr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printCV(char face, struct json_object_element_s *r)
|
||||||
|
{
|
||||||
|
struct json_object_element_s start = *r;
|
||||||
|
struct json_object_element_s *next = &start;
|
||||||
|
|
||||||
|
char k = 0;
|
||||||
|
if (face >= 0)
|
||||||
|
for (; k < face; ++k)
|
||||||
|
next = next->next;
|
||||||
|
|
||||||
|
char *res;
|
||||||
|
switch (face) {
|
||||||
|
case FACE_FRONT:
|
||||||
|
printFrontFace(next);
|
||||||
|
break;
|
||||||
|
case FACE_LEFT:
|
||||||
|
printLefttFace(next);
|
||||||
|
break;
|
||||||
|
case FACE_RIGHT:
|
||||||
|
printRightFace(next);
|
||||||
|
break;
|
||||||
|
case FACE_BOTTOM:
|
||||||
|
printBottomFace(next);
|
||||||
|
break;
|
||||||
|
case FACE_BACK:
|
||||||
|
printBackFace(next);
|
||||||
|
break;
|
||||||
|
case FACE_TOP:
|
||||||
|
printTopFace(next);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printAscii(struct json_value_s *json)
|
||||||
|
{
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
fcntl(STDOUT_FILENO, F_SETFL, ~O_NONBLOCK);
|
fcntl(STDOUT_FILENO, F_SETFL, ~O_NONBLOCK);
|
||||||
#endif
|
#endif
|
||||||
for (int k = 0 ; k < SCREEN_WIDTH * SCREEN_HEIGHT ; ++k)
|
char face = chooseMainFace();
|
||||||
|
struct json_object_element_s *root = json_value_as_object(json)->start;
|
||||||
|
printCV(face, root);
|
||||||
|
|
||||||
|
for (int k = 0; k < SCREEN_WIDTH * SCREEN_HEIGHT; ++k)
|
||||||
printf("%s", k % SCREEN_WIDTH ? chooseColor(output[k]) : "\r\n");
|
printf("%s", k % SCREEN_WIDTH ? chooseColor(output[k]) : "\r\n");
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
@ -130,145 +340,235 @@ void printAscii() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void rotateCube(double cubeX, double cubeY, double cubeZ, char ch){
|
void
|
||||||
calcAngle();
|
rotateCube(double cubeX, double cubeY, double cubeZ, char ch)
|
||||||
double x = calcX(cubeX, cubeY, cubeZ);
|
{
|
||||||
double y = calcY(cubeX, cubeY, cubeZ);
|
struct Quaternions q = mult(Current, cubeX, cubeY, cubeZ);
|
||||||
double invZ = 1 / (calcZ(cubeX, cubeY, cubeZ) + K2);
|
|
||||||
|
|
||||||
int screenX = (int)(SCREEN_WIDTH / 2) + floor((x) * K1) * invZ;
|
double x = q.x;
|
||||||
int screenY = (int)(SCREEN_HEIGHT / 2) + floor(((y) * K1 / 2 ) * invZ);
|
double y = q.y;
|
||||||
// TODO luminescence
|
double invZ = 1 / (q.z + K2);
|
||||||
|
|
||||||
if (screenX > SCREEN_WIDTH || screenX < 0) return;
|
int screenX = (int)(SCREEN_WIDTH / 2) + floor((x) * K1) * invZ;
|
||||||
|
int screenY = (int)(SCREEN_HEIGHT / 2) + floor(((y) * K1 / 2) * invZ);
|
||||||
|
//TODO luminescence
|
||||||
|
|
||||||
int idx = screenY * SCREEN_WIDTH + screenX;
|
if (screenX > SCREEN_WIDTH || screenX < 0)
|
||||||
if(idx >= 0 && idx < SCREEN_WIDTH * SCREEN_HEIGHT)
|
return;
|
||||||
if(zBuffer[idx] < invZ) {
|
|
||||||
|
int idx = screenY * SCREEN_WIDTH + screenX;
|
||||||
|
if (idx >= 0 && idx < SCREEN_WIDTH * SCREEN_HEIGHT)
|
||||||
|
if (zBuffer[idx] < invZ) {
|
||||||
zBuffer[idx] = invZ;
|
zBuffer[idx] = invZ;
|
||||||
output[idx] = ch;
|
output[idx] = ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void intHandler(int unused) {
|
void
|
||||||
|
intHandler(int unused)
|
||||||
|
{
|
||||||
shouldBreak = 0;
|
shouldBreak = 0;
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm);
|
tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printBanner(char keyboardInput) {
|
void
|
||||||
printf("Last input character: %c", keyboardInput);
|
printBanner(char keyboardInput)
|
||||||
|
{
|
||||||
|
printf("Last input character: %c, "
|
||||||
|
"Current: w:%f x:%f y%f z:%f | "
|
||||||
|
"Last: w:%f x:%f y%f z:%f | "
|
||||||
|
"Target: w:%f x:%f y%f z:%f\r\n",
|
||||||
|
keyboardInput,
|
||||||
|
Current.w, Current.x, Current.y, Current.z,
|
||||||
|
Last.w, Last.x, Last.y, Last.z,
|
||||||
|
Target.w, Target.x, Target.y, Target.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleAngle(char *input) {
|
struct Quaternions
|
||||||
if (!Angle.currentTarget) {
|
interpolate(struct Quaternions qa, struct Quaternions qb)
|
||||||
Angle.currentTarget = *input;
|
{
|
||||||
|
struct Quaternions res;
|
||||||
|
double cosHalfTheta =
|
||||||
|
qa.w * qb.w +
|
||||||
|
qa.x * qb.x +
|
||||||
|
qa.y * qb.y +
|
||||||
|
qa.z * qb.z;
|
||||||
|
//if qa = qb or qa = -qb then theta = 0 and we can return qa
|
||||||
|
if (fabs(cosHalfTheta) >= 1.0) {
|
||||||
|
res.w = qa.w;
|
||||||
|
res.x = qa.x;
|
||||||
|
res.y = qa.y;
|
||||||
|
res.z = qa.z;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (cosHalfTheta < 0) {
|
||||||
|
qb.w = -qb.w;
|
||||||
|
qb.x = -qb.x;
|
||||||
|
qb.y = -qb.y;
|
||||||
|
qb.z = qb.z;
|
||||||
|
cosHalfTheta = -cosHalfTheta;
|
||||||
|
}
|
||||||
|
|
||||||
|
double halfTheta = acos(cosHalfTheta);
|
||||||
|
double sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta);
|
||||||
|
//if theta = 180 degrees then result is not fully defined
|
||||||
|
// we could rotate around any axis normal to qa or qb
|
||||||
|
if (fabs(sinHalfTheta) < 0.001) {
|
||||||
|
res.w = (qa.w * 0.5 + qb.w * 0.5);
|
||||||
|
res.x = (qa.x * 0.5 + qb.x * 0.5);
|
||||||
|
res.y = (qa.y * 0.5 + qb.y * 0.5);
|
||||||
|
res.z = (qa.z * 0.5 + qb.z * 0.5);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
interpolationStep += ACTION_STEP;
|
||||||
|
double ratioA = sin((1 - interpolationStep) * halfTheta) / sinHalfTheta;
|
||||||
|
double ratioB = sin(interpolationStep * halfTheta) / sinHalfTheta;
|
||||||
|
|
||||||
|
res.w = (qa.w * ratioA + qb.w * ratioB);
|
||||||
|
res.x = (qa.x * ratioA + qb.x * ratioB);
|
||||||
|
res.y = (qa.y * ratioA + qb.y * ratioB);
|
||||||
|
res.z = (qa.z * ratioA + qb.z * ratioB);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
handleAngle(char *input)
|
||||||
|
{
|
||||||
|
if (!currentlyMoving) {
|
||||||
|
currentlyMoving = *input;
|
||||||
|
Last = Current;
|
||||||
switch (*input) {
|
switch (*input) {
|
||||||
|
case 'w':
|
||||||
case 'W':
|
case 'W':
|
||||||
Angle.ATarget = Angle.A - M_PI_2;
|
Target = multQ(GET_ROTATE_X_Q(M_PI_2), Target);
|
||||||
break;
|
break;
|
||||||
|
case 'a':
|
||||||
case 'A':
|
case 'A':
|
||||||
Angle.BTarget = Angle.B + M_PI_2;
|
Target = multQ(GET_ROTATE_Y_Q(-M_PI_2), Target);
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
Angle.ATarget = Angle.A + M_PI_2;
|
Target = multQ(GET_ROTATE_X_Q(-M_PI_2), Target);
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
case 'D':
|
case 'D':
|
||||||
Angle.BTarget = Angle.B - M_PI_2;
|
Target = multQ(GET_ROTATE_Y_Q(M_PI_2), Target);
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
Target = multQ(GET_ROTATE_Z_Q(-M_PI_2), Target);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
Target = multQ(GET_ROTATE_Z_Q(M_PI_2), Target);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Angle.currentTarget = 0;
|
currentlyMoving = 0;
|
||||||
|
//TODO idle movement
|
||||||
}
|
}
|
||||||
|
normalize(&Target);
|
||||||
// idle animation
|
} else {
|
||||||
//Angle.A += ROLL_STEP;
|
if (interpolationStep < 1 - ACTION_STEP)
|
||||||
Angle.B += YAW_STEP;
|
Current = interpolate(Last, Target);
|
||||||
//Angle.C += PITCH_STEP;
|
else {
|
||||||
}
|
//RESET_IDLE;
|
||||||
|
Current = Target;
|
||||||
else
|
*input = 0;
|
||||||
switch(Angle.currentTarget) {
|
interpolationStep = 0;
|
||||||
case 'W':
|
currentlyMoving = 0;
|
||||||
Angle.A -= ACTION_STEP;
|
}
|
||||||
if (Angle.A <= Angle.ATarget) RESET_A_ANGLE(*input);
|
normalize(&Current);
|
||||||
break;
|
|
||||||
case 'A':
|
|
||||||
Angle.B += ACTION_STEP;
|
|
||||||
if (Angle.B >= Angle.BTarget) RESET_B_ANGLE(*input);
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
Angle.A += ACTION_STEP;
|
|
||||||
if (Angle.A >= Angle.ATarget) RESET_A_ANGLE(*input);
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
Angle.B -= ACTION_STEP;
|
|
||||||
if (Angle.B <= Angle.BTarget) RESET_B_ANGLE(*input);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char getInput(char *keyboardInput) {
|
char
|
||||||
|
getInput(char *keyboardInput)
|
||||||
|
{
|
||||||
char c = getchar();
|
char c = getchar();
|
||||||
if (c == '\033') { // if the first value is esc
|
if (c == '\033') {
|
||||||
if ((c = getchar()) == '[')
|
if ((c = getchar()) == '[')
|
||||||
switch(c = getchar()) { // the real value
|
switch (c = getchar()) {
|
||||||
case 'A':
|
//the real value
|
||||||
c = 'W';
|
case 'A':
|
||||||
break;
|
c = 'W';
|
||||||
case 'B':
|
break;
|
||||||
c = 'S';
|
case 'B':
|
||||||
break;
|
c = 'S';
|
||||||
case 'C':
|
break;
|
||||||
c = 'D';
|
case 'C':
|
||||||
break;
|
c = 'D';
|
||||||
case 'D':
|
break;
|
||||||
c = 'A';
|
case 'D':
|
||||||
break;
|
c = 'A';
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c != EOF)
|
if (c != EOF)
|
||||||
*keyboardInput = c;
|
*keyboardInput = c;
|
||||||
while((c = getchar()) != '\n' && c != EOF) {} // clean stdin
|
while ((c = getchar()) != '\n' && c != EOF) {} //clean stdin
|
||||||
|
|
||||||
handleAngle(keyboardInput);
|
handleAngle(keyboardInput);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(){
|
struct json_value_s *
|
||||||
|
readJson()
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
FILE *fp = fopen("./cv.json", "r");
|
||||||
|
char *json;
|
||||||
|
|
||||||
|
if (fp) {
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
size = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
|
||||||
|
json = (char *)malloc(sizeof(char) * size);
|
||||||
|
fread(json, 1, size, fp);
|
||||||
|
}
|
||||||
|
return json_parse(json, strlen(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
char keyboardInput = 0;
|
char keyboardInput = 0;
|
||||||
signal(SIGINT, intHandler);
|
signal(SIGINT, intHandler);
|
||||||
tcgetattr(STDIN_FILENO, &originalTerm);
|
tcgetattr(STDIN_FILENO, &originalTerm);
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct termios t = {};
|
struct termios t = {};
|
||||||
cfmakeraw(&t);
|
cfmakeraw(&t);
|
||||||
t.c_lflag |= ISIG;
|
t.c_lflag |= ISIG;
|
||||||
t.c_cc[VINTR] = 3;
|
t.c_cc[VINTR] = 3;
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &t);
|
tcsetattr(STDIN_FILENO, TCSANOW, &t);
|
||||||
|
|
||||||
initAngles();
|
Current = GET_ROTATE_Z_Q(0);
|
||||||
|
|
||||||
while(shouldBreak) {
|
struct json_value_s *json = readJson();
|
||||||
|
|
||||||
|
while (shouldBreak) {
|
||||||
memset(output, ' ', SCREEN_WIDTH * SCREEN_HEIGHT);
|
memset(output, ' ', SCREEN_WIDTH * SCREEN_HEIGHT);
|
||||||
memset(zBuffer, 0, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(double));
|
memset(zBuffer, DBL_MIN, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(double));
|
||||||
|
|
||||||
for(double cubeX = -CUBE_WIDTH + STEP ; cubeX < CUBE_WIDTH - STEP ; cubeX += STEP) {
|
for (double cubeX = -CUBE_WIDTH + STEP; cubeX < CUBE_WIDTH - STEP; cubeX += STEP) {
|
||||||
for(double cubeY = -CUBE_WIDTH + STEP ; cubeY < CUBE_WIDTH - STEP ; cubeY += STEP) {
|
for (double cubeY = -CUBE_WIDTH + STEP; cubeY < CUBE_WIDTH - STEP; cubeY += STEP) {
|
||||||
rotateCube(cubeX, cubeY, -CUBE_WIDTH, FACE_FRONT);//front
|
rotateCube(cubeX, cubeY, -CUBE_WIDTH, FACE_FRONT);
|
||||||
rotateCube(cubeX, cubeY, CUBE_WIDTH, FACE_BACK);//back
|
rotateCube(cubeX, cubeY, CUBE_WIDTH, FACE_BACK);
|
||||||
rotateCube(CUBE_WIDTH, cubeX, cubeY, FACE_RIGHT);//right
|
rotateCube(CUBE_WIDTH, cubeX, cubeY, FACE_RIGHT);
|
||||||
rotateCube(-CUBE_WIDTH, cubeX, cubeY, FACE_LEFT);//left
|
rotateCube(-CUBE_WIDTH, cubeX, cubeY, FACE_LEFT);
|
||||||
rotateCube(cubeX, CUBE_WIDTH, cubeY, FACE_BOTTOM);//bottom
|
rotateCube(cubeX, CUBE_WIDTH, cubeY, FACE_BOTTOM);
|
||||||
rotateCube(cubeX, -CUBE_WIDTH, cubeY, FACE_TOP);//top
|
rotateCube(cubeX, -CUBE_WIDTH, cubeY, FACE_TOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\x1b[2J");
|
printf("\x1b[2J");
|
||||||
printBanner(keyboardInput);
|
printAscii(json);
|
||||||
printAscii();
|
|
||||||
getInput(&keyboardInput);
|
getInput(&keyboardInput);
|
||||||
usleep(100000);
|
usleep(10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue