This commit is contained in:
Hoguchi-live 2023-01-19 12:11:20 +01:00
parent aae1a9224c
commit 383f8c057f
25 changed files with 0 additions and 103142 deletions

View File

@ -1,54 +0,0 @@
#include "csv.h"
using namespace std;
long int string2timestamp(const string &str)
{
struct tm tm{};
if(strptime(str.c_str(), "%Y-%m-%d %H:%M:%S",&tm) == NULL)
return -1;
return mktime(&tm);
}
void read_record()
{
// File pointer
fstream fin;
// Open an existing file
fin.open("danmaku.csv", ios::in);
// Read the Data from the file
// as String Vector
vector<string> row;
string line, word, temp;
while (fin >> temp) {
row.clear();
// read an entire row and
// store it in a string variable 'line'
getline(fin, line);
// used for breaking words
stringstream s(line);
// read every column data of a row and
// store it in a string variable, 'word'
while (getline(s, word, '|')) {
// add all the column data
// of a row to a vector
row.push_back(word);
}
cout << "Time:" << row[0] << "Timestamp" << string2timestamp("2022-01-08" + row[0]) << endl;
}
}
int main() {
read_record();
}

View File

@ -1,19 +0,0 @@
#ifndef _CSV_H_
#define _CSV_H_
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <string>
#include <sstream>
#include <iomanip>
#include <ctime>
#include <locale.h>
#include <time.h>
void read_record();
long int string2timestamp(const std::string &);
#endif

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,54 +0,0 @@
POLLING_URL_1 = 'https://bigapple.cytu.be:8443/socket.io/?EIO=4&transport=polling&t=OLd_JZ8'
POLLING_URL_2 = 'https://bigapple.cytu.be:8443/socket.io/?EIO=4&transport=polling&t=OLd_JZ8-&sid={}'
POLLING_URL_3 = 'https://bigapple.cytu.be:8443/socket.io/?EIO=4&transport=polling&t=OLd_JZY_&sid={}'
POLLING_URL_4 = 'https://bigapple.cytu.be:8443/socket.io/?EIO=4&transport=polling&t=OLd_JZ8&sid={}'
POLLING_URL_5 = 'https://bigapple.cytu.be:8443/socket.io/?EIO=4&transport=polling&t=OLd_JZ8&sid={}'
HEADER = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'
}
HEADER_WSS = {
'Host': 'bigapple.cytu.be:8443',
'Connection': 'Upgrade',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'Upgrade': 'websocket',
'Origin': 'https://cytu.be',
'Sec-WebSocket-Version': '13',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Sec-GPC': '1',
'Sec-WebSocket-Key': '7wfF6vVBt2fOUj5JRhVoPA==',
'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits'}
WSS_URL = 'wss://bigapple.cytu.be:8443/socket.io/?EIO=4&transport=websocket&sid={}'
class Parser:
'''
Makes socket messages into a python objects if possible and returns a representation (dict, df, ts, ...) thereof.
'''
def parser(self, message):
#def pyify(obj):
# # Check if obj is already a pyobj
# if not type(obj) in [str]: return obj
# try: return eval(obj)
# except Exception as e: print('Parser::parser: Error {}'.format(e))
## Check for bools
#pretty = message.replace('true', 'True')
#pretty = pretty.replace('false', 'False')
#pretty = pretty.replace('null', 'None')
# Send the raw payload to a specific sub-parser
try:
res = getattr(self, message_type)(raw_payload)
return message_type, res
except Exception as e: print('Parser::parser: Error while sending a message of type "{}" to sub-parser:\n{}'.format(message_type), e)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@
# -*- coding: UTF-8 -*-
# Reader
from datetime import datetime
import threading
import queue
import time
import sys
import csv
import sys
import socket
import fcntl, os
FILENAME = "data/danmaku.csv"
DATE_FORMAT = "%d/%m/%Y %H:%M:%S"
READER_REFRESH_RATE = 100
SEND_BUFFER_SIZE = 2048
class CSV_Reader(threading.Thread):
def __init__(self, queue, videoStartTime, *args, **kwargs):
super(CSV_Reader, self).__init__(*args, **kwargs)
self._stop_event = threading.Event()
self.queue = queue
self.is_on = False
self.video_zero_time = videoStartTime
self.video_zero_time_relative = None
self.danmaku_zero_time = None
self.danmaku_time_delta = 0
# SOCKET
self.server_ip = "localhost"
self.server_port = 10000
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.server_ip, self.server_port))
fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
def run(self):
print("::Running CSV_Reader")
self.is_on = True
with open(FILENAME, newline='') as csvfile:
spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
while self.is_on:
raw_time, raw_data = next(spamreader)
d_time = datetime.strptime(raw_time, DATE_FORMAT)
ts_time = int(datetime.timestamp(d_time))
# Set starting point
if self.danmaku_zero_time == None:
self.video_zero_time_relative = time.time()
self.video_zero_time_zero = ts_time
self.danmaku_zero_time = ts_time
video_elapsed = 0
delta_time = 1
while delta_time > video_elapsed:
# Time elapsed relative to the video
video_elapsed = time.time() - self.video_zero_time_relative
delta_time = ts_time - self.danmaku_zero_time
# Sleep
time.sleep(READER_REFRESH_RATE*0.001)
print("time: {} ## data: {} ## delta: {}".format(raw_time, raw_data, delta_time))
data = bytes(raw_data, "utf-8")
data += bytes(SEND_BUFFER_SIZE-len(data))
self.sock.send(data)
def stop(self):
print("::Stopping Watcher")
self.is_on = False
self._stop_event.set()
def toggle(self):
if self.is_on:
print("::Pausing Watcher")
self.is_on = False
elif not self.is_on:
self.run()
def stopped(self):
return self._stop_event.is_set()
def main():
videoStartTime = 0
if len(sys.argv) == 2:
VideoStartTime = sys.argv[1]
Q = queue.Queue()
R = CSV_Reader(Q, videoStartTime)
R.start()
if __name__ == "__main__":
main()

View File

@ -1,84 +0,0 @@
# -*- coding: UTF-8 -*-
# Reader
from datetime import datetime
import threading
import queue
import time
import sys
import csv
FILENAME = "data/danmaku.csv"
DATE_FORMAT = "%d/%m/%Y %H:%M:%S"
READER_REFRESH_RATE = 100
class CSV_Reader(threading.Thread):
def __init__(self, queue, videoStartTime, *args, **kwargs):
super(CSV_Reader, self).__init__(*args, **kwargs)
self._stop_event = threading.Event()
self.queue = queue
self.is_on = False
self.video_zero_time = videoStartTime
self.video_zero_time_relative = None
self.danmaku_zero_time = None
self.danmaku_time_delta = 0
def run(self):
print("::Running CSV_Reader")
self.is_on = True
with open(FILENAME, newline='') as csvfile:
spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
while self.is_on:
raw_time, raw_data = next(spamreader)
d_time = datetime.strptime(raw_time, DATE_FORMAT)
ts_time = int(datetime.timestamp(d_time))
# Set starting point
if self.danmaku_zero_time == None:
self.video_zero_time_relative = time.time()
self.video_zero_time_zero = ts_time
self.danmaku_zero_time = ts_time
video_elapsed = 0
delta_time = 1
while delta_time > video_elapsed:
# Time elapsed relative to the video
video_elapsed = time.time() - self.video_zero_time_relative
delta_time = ts_time - self.danmaku_zero_time
# Sleep
time.sleep(READER_REFRESH_RATE*0.001)
print("time: {} ## data: {} ## delta: {}".format(raw_time, raw_data, delta_time))
self.queue.put(raw_data)
def stop(self):
print("::Stopping Watcher")
self.is_on = False
self._stop_event.set()
def toggle(self):
if self.is_on:
print("::Pausing Watcher")
self.is_on = False
elif not self.is_on:
self.run()
def stopped(self):
return self._stop_event.is_set()
def main():
videoStartTime = 0
if len(sys.argv) == 2:
VideoStartTime = sys.argv[1]
Q = queue.Queue()
R = CSV_Reader(Q, videoStartTime)
R.start()
if __name__ == "__main__":
main()

View File

@ -1,21 +0,0 @@
from csv_reader import *
from csv_socket import *
def main():
Q = queue.Queue()
S = CSV_Socket(Q)
R = CSV_Reader(Q)
S.start()
R.start()
try:
while 1:
time.sleep(0.1)
except KeyboardInterrupt:
S.stop()
R.stop()
if __name__ == "__main__":
main()

View File

@ -1,87 +0,0 @@
#!/usr/bin/env python3
""" client.py - Echo client for sending/receiving C-like structs via socket
References:
- Ctypes: https://docs.python.org/3/library/ctypes.html
- Sockets: https://docs.python.org/3/library/socket.html
"""
import threading
import socket
import queue
import sys
import time
import random
from ctypes import *
DATE_FORMAT = "%d/%m/%Y %H:%M:%S"
SERVER_REFRESH_RATE = 100
""" This class defines a C-like struct """
class Payload(Structure):
_fields_ = [("id", c_uint32),
("counter", c_uint32),
("data", c_wchar_p)]
class CSV_Socket(threading.Thread):
def __init__(self, queue, *args, **kwargs):
super(CSV_Socket, self).__init__(*args, **kwargs)
self._stop_event = threading.Event()
self.queue = queue
self.is_on = False
self.server_addr = ('localhost', 2300)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def run(self):
print("::Running CSV_Server")
self.is_on = True
try:
self.socket.connect(self.server_addr)
print("Connected to {:s}".format(repr(self.server_addr)))
c = 0
while self.is_on:
if not self.queue.empty():
raw_data = self.queue.get() + "\0"
payload_out = Payload(c, len(raw_data), raw_data)
print("Sending id={:d}, counter={:d}, data={}".format(payload_out.id,
payload_out.counter,
payload_out.data))
nsent = self.socket.send(payload_out)
# Alternative: s.sendall(...): coontinues to send data until either
# all data has been sent or an error occurs. No return value.
print("Sent {:d} bytes".format(nsent))
#buff = s.recv(sizeof(Payload))
#payload_in = Payload.from_buffer_copy(buff)
#print("Received id={:d}, counter={:d}, temp={}".format(payload_in.id,
# payload_in.counter,
# payload_in.data))
c += 1
time.sleep(SERVER_REFRESH_RATE*0.001)
except AttributeError as ae:
print("Error creating the socket: {}".format(ae))
except socket.error as se:
print("Exception on socket: {}".format(se))
finally:
print("Closing socket")
self.socket.close()
def stop(self):
print("::Stopping Server")
self.is_on = False
self._stop_event.set()
def toggle(self):
if self.is_on:
print("::Pausing Server")
self.is_on = False
elif not self.is_on:
self.run()
def stopped(self):
return self._stop_event.is_set()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +0,0 @@
#!/usr/bin/env python3
""" server.py - Echo server for sending/receiving C-like structs via socket
References:
- Ctypes: https://docs.python.org/3/library/ctypes.html
- Sockets: https://docs.python.org/3/library/socket.html
"""
import codecs
import socket
import sys
import random
from ctypes import *
""" This class defines a C-like struct """
class Payload(Structure):
_fields_ = [("id", c_uint32),
("counter", c_uint32),
("data", c_wchar_p)]
def main():
PORT = 2300
server_addr = ('localhost', PORT)
ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created")
try:
# bind the server socket and listen
ssock.bind(server_addr)
print("Bind done")
ssock.listen(3)
print("Server listening on port {:d}".format(PORT))
while True:
csock, client_address = ssock.accept()
print("Accepted connection from {:s}".format(client_address[0]))
buff = csock.recv(512)
while buff:
print("\nReceived {:d} bytes".format(len(buff)))
payload_in = Payload.from_buffer_copy(buff)
t = payload_in.data
#print("Received contents id={:d}, counter={:d}, data={}".format(payload_in.id, payload_in.counter, payload_in.data))
buff = csock.recv(512)
print("Closing connection to client")
print("----------------------------")
csock.close()
except AttributeError as ae:
print("Error creating the socket: {}".format(ae))
except socket.error as se:
print("Exception on socket: {}".format(se))
except KeyboardInterrupt:
ssock.close()
finally:
print("Closing socket")
ssock.close()
if __name__ == "__main__":
main()

View File

@ -1,5 +0,0 @@
from wsInterface import *
if __name__ == "__main__":
S = Socket_()
S.listenForever()

View File

@ -1,104 +0,0 @@
import json
import queue
import requests
import websocket
from helper import *
import sys
import socket
import fcntl, os
SEND_BUFFER_SIZE = 2048
connected = 0
try: import thread
except ImportError: import _thread as thread
class Socket_:
def __init__(self, queue = None):
self.URL = None
self.sid = None
self.sidWSS = None
self.parser = Parser().parser
self.queue = queue
self.ws = None
self.sock = None
# Start the connection
self.handshake()
def handshake(self):
# First, establish a polling-transport HTTP connection
resp_1 = requests.get(POLLING_URL_1, headers = HEADER)
print('Resp 1: ', resp_1.text)
# Ignore the bin-packed preliminaries and extract the session ID
# WOTOS: self.sid = json.loads(str(resp_1.content)[3:-1])['sid']
self.sid = json.loads(str(resp_1.content)[3:-1])['sid']
# Second polling with POST, response should be 'ok'
resp_2 = requests.post(POLLING_URL_2.format(self.sid), headers = HEADER, data = b'40')
print('Resp 2: ', resp_2.text)
# Third polling
resp_3 = requests.get(POLLING_URL_3.format(self.sid), headers = HEADER)
print('Resp 3: ', resp_3.text)
# WOTOS: self.sid = json.loads(str(resp_1.content)[3:-1])['sid']
index = str(resp_3.content).find('\\x1e42[')
substr = str(resp_3.content)[4:index]
self.sidWSS = json.loads(substr)['sid']
# Fourth polling with POST
resp_4 = requests.post(POLLING_URL_4.format(self.sid), headers = HEADER, data = b'42["joinChannel",{"name":"testam"}]')
print('Resp 4: ', resp_4.text)
# Fourth polling with GET
resp_5 = requests.get(POLLING_URL_5.format(self.sid), headers = HEADER)
print('Resp 5: ', resp_5.text)
# WSS url
self.URL = WSS_URL.format(self.sid)
print(self.URL)
def on_open(self, ws):
print('### Socket open ###')
ws.send("2probe")
def on_close(self, ws):
print("### Socket closed ###")
self.sock.close()
def on_error(self, ws, error):
print('\nSocket error :\n{}\n'.format(error))
def on_message(self, ws, message):
if message == '2': ws.send('3')
elif message == '3probe': ws.send('5')
elif message[:2] == '42':
j = message[2:].replace("'", '"')
parsed = json.loads(j)
print("received: ", message)
reason = parsed[0]
if reason == 'chatMsg':
data = bytes(parsed[1]['msg'], "utf-8")
data += bytes(SEND_BUFFER_SIZE-len(data))
self.sock.send(data)
print(data)
else: pass
def listenForever(self):
# SOCKET
server_ip = "localhost"
server_port = 10000
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((server_ip, server_port))
fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
try:
#websocket.enableTrace(True)
self.ws = websocket.WebSocketApp(self.URL,
on_open = self.on_open,
on_message = self.on_message,
on_error = self.on_error,
on_close = self.on_close,
header = HEADER_WSS
)
self.ws.run_forever(ping_interval = 25, ping_timeout = 5 )
except Exception as e:
print("Socket::ListenForever: Exception {}", format(e))

View File

@ -1,208 +0,0 @@
#include "danmaku.h"
/// This is so fucking bad, just store everything and redraw with a translation in the shader holy shit
float RenderText(Shader s, std::string text, float x, float y, float scale, glm::vec3 color, uint &VAO, uint &VBO, std::map<char, Character>& Characters, float window_width)
{
// activate corresponding render state
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
s.use();
glUniform3f(glGetUniformLocation(s.ID, "textColor"), color.x, color.y, color.z);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
Character ch;
float xpos;
float ypos;
float w;
float h;
// iterate through all characters
std::string::const_iterator c;
for (c = text.begin(); c != text.end(); c++)
{
ch = Characters[*c];
xpos = x + ch.Bearing.x * scale;
ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
w = ch.Size.x * scale;
h = ch.Size.y * scale;
// update VBO for each character
float vertices[6][4] = {
{ xpos, ypos + h, 0.0f, 0.0f },
{ xpos, ypos, 0.0f, 1.0f },
{ xpos + w, ypos, 1.0f, 1.0f },
{ xpos, ypos + h, 0.0f, 0.0f },
{ xpos + w, ypos, 1.0f, 1.0f },
{ xpos + w, ypos + h, 1.0f, 0.0f }
};
// render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
// update content of VBO memory
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
x += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
return xpos;
}
//// Create bitmaps for text rendering
void makeBitmaps(std::map<char, Character>& Characters){
///////// FREETYPE2 INIT
FT_Library ft;
if (FT_Init_FreeType(&ft)){
std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
exit(EXIT_FAILURE);
}
FT_Face face;
if (FT_New_Face(ft, "/usr/share/fonts/TTF/DejaVuSans.ttf", 0, &face)){
std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
exit(EXIT_FAILURE);
}
FT_Set_Pixel_Sizes(face, 0, GLYPH_SIZE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
glEnable(GL_BLEND);
for (unsigned char c = 0; c < 128; c++){
// load character glyph
if (FT_Load_Char(face, c, FT_LOAD_RENDER)){
std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
continue;
}
// generate texture
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
// set texture options
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// now store character for later use
Character character = {
texture,
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
face->glyph->advance.x
};
Characters.insert(std::pair<char, Character>(c, character));
}
/// Clear glyphs
FT_Done_Face(face);
FT_Done_FreeType(ft);
}
//TODO: Status <->
/*
Sets nextRow to the index of the next free danmaku row and returns 1 if one is available, returns 0 otherwise.
*/
int getNextDanmakuRow(uint *ph_danmakuRows, int length, uint *nextRow) {
for(int row = 0; row < length; row++) {
if( (ph_danmakuRows)[row] ){
*nextRow = row;
return 1;
}
}
return 0;
}
/*
Flips the status of the danmaku row.
*/
int updateDanmakuRow(uint *ph_danmakuRows, uint row) {
ph_danmakuRows[row] = !ph_danmakuRows[row];
return 0;
}
/*
Updates danmaku array according to the delta between last frame and current frame.
*/
int updateDanmakus(Render *r){
// Amount of pixels to translate the danmakus by
float deltaPix = DANMAKU_SPEED*delta;
// Last glyph x-position (last pixel on the string)
float lastPix = 0.0f;
// Keep track of danmaku index
uint danmakuIndex = 0;
for(Danmaku &danmaku : danmakus) {
if(danmaku.isNew) {
// Try to assign the new danmaku's row to a free slot
if(getNextDanmakuRow(ph_danmakuRows, nb_danmakuRows, &(danmaku.row))){
// Compute the height for that row
danmaku.ypos = (r->h - DANMAKU_MARGIN_TOP) -
(danmaku.row + 1) * (DANMAKU_PADDING_V + GLYPH_SIZE);
danmaku.xpos = r->w;
// Set the slot to unavailable
updateDanmakuRow(ph_danmakuRows, danmaku.row);
danmaku.tailCheck = 0;
}
danmaku.isNew = 0;
}
else {
// Translate danmaku
danmaku.xpos -= deltaPix;
}
// Draw the danmaku and get tail position
lastPix = RenderText(r, danmaku.text, danmaku.xpos, danmaku.ypos, 1.0f, glm::vec3(0.0, 0.26f, 0.0f));
if(lastPix + DANMAKU_PADDING_H < 0) {
danmakus.erase(danmakus.begin() + danmakuIndex);
}
// Check if the tail of the danmaku is free (only check once)
if(!danmaku.tailCheck && (r->w > lastPix + (float)DANMAKU_PADDING_H)) {
// Free the row slot
updateDanmakuRow(ph_danmakuRows, danmaku.row);
danmaku.tailCheck = 1;
}
}
danmakuIndex++;
}
return 1;
}
OverlayHandler() {
init();
}
int OverlayHandler::init() {
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

View File

@ -1,65 +0,0 @@
#ifndef _DANMAKU_H_
#define _DANMAKU_H_
#include <shader.h>
#include <map>
#include <vector>
#include "stdlib.h"
#include "stdio.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#define GLYPH_SIZE 36
#define DANMAKU_MARGIN_TOP 50
#define DANMAKU_MARGIN_BOT 50
#define DANMAKU_PADDING_H 200
#define DANMAKU_PADDING_V 20
#define DANMAKU_SPEED_V 200.0f
// Glyphs
typedef struct Character {
unsigned int TextureID; // ID handle of the glyph texture
glm::ivec2 Size; // Size of glyph
glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
long int Advance; // Offset to advance to next glyph
} Character;
// Danmaku
typedef struct Danmaku {
std::string text;
uint isActive;
float xpos;
float ypos;
uint isNew;
uint row;
uint tailCheck;
} Danmaku;
class OverlayHandler() {
public:
OverlayHandler();
float RenderText(Shader, std::string, float, float, float, glm::vec3, uint &, uint &, std::map<char, Character>&);
int init();
private:
unsigned int VAO, VBO;
void makeBitmaps(std::map<char, Character> &);
Shader *glyphShader = new Shader("shaders/glyph_vs.glsl", "shaders/glyph_fs.glsl");
}
int getNextDanmakuRow(uint *, int, uint* );
int updateDanmakuRow(uint *, uint);
int updateDanmakus(Danmaku *, float);
#endif

View File

@ -1,59 +0,0 @@
#include "danmaku.h"
//// Create bitmaps for text rendering
void makeBitmaps(std::map<char, Character>& Characters){
///////// FREETYPE2 INIT
FT_Library ft;
if (FT_Init_FreeType(&ft)){
std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
exit(EXIT_FAILURE);
}
FT_Face face;
if (FT_New_Face(ft, "/usr/share/fonts/TTF/DejaVuSans.ttf", 0, &face)){
std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
exit(EXIT_FAILURE);
}
FT_Set_Pixel_Sizes(face, 0, GLYPH_SIZE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
glEnable(GL_BLEND);
for (unsigned char c = 0; c < 128; c++){
// load character glyph
if (FT_Load_Char(face, c, FT_LOAD_RENDER)){
std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
continue;
}
// generate texture
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
// set texture options
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// now store character for later use
Character character = {
texture,
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
face->glyph->advance.x
};
Characters.insert(std::pair<char, Character>(c, character));
}
/// Clear glyphs
FT_Done_Face(face);
FT_Done_FreeType(ft);
}

View File

@ -1,48 +0,0 @@
#ifndef _OVERLAY_H_
#define _OVERLAY_H_
#include <shader.h>
#include <map>
#include <vector>
#include "stdlib.h"
#include "stdio.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#define GLYPH_SIZE 36
#define DANMAKU_MARGIN_TOP 50
#define DANMAKU_MARGIN_BOT 50
#define DANMAKU_PADDING_H 200
#define DANMAKU_PADDING_V 20
#define DANMAKU_SPEED_V 200.0f
// Glyphs
typedef struct Character {
unsigned int TextureID; // ID handle of the glyph texture
glm::ivec2 Size; // Size of glyph
glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
long int Advance; // Offset to advance to next glyph
} Character;
// Danmaku
typedef struct Danmaku {
std::string text;
uint isActive;
float xpos;
float ypos;
uint isNew;
uint row;
uint tailCheck;
} Danmaku;
class Overlay() {
public:
OverlayHandler();
int init();
private:
void makeBitmaps(std::map<char, Character> &);
}
#endif