This commit is contained in:
mrbesen 2021-04-09 18:47:08 +02:00
commit c72bf3be8e
Signed by: MrBesen
GPG Key ID: 596B2350DCD67504
11 changed files with 501 additions and 0 deletions

17
.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
*.bin
*.out
build/
*.exe
*.dll
.gdb_history
*.so
*.bmp
*.d
test
.vscode/settings.json
chac
chac_strip
log.txt

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "thirdparty/openvr"]
path = thirdparty/openvr
url = https://github.com/ValveSoftware/openvr
[submodule "thirdparty/rawdraw"]
path = thirdparty/rawdraw
url = git@github.com:cntools/rawdraw.git

41
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,41 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/thirdparty/Log/",
"${workspaceFolder}/thirdparty/openvr/headers",
"${workspaceFolder}/thirdparty/libmrbesen/inc",
"${workspaceFolder}/inc/",
"${workspaceFolder}/thirdparty/rawdraw/",
"${workspaceFolder}/thirdparty/openvr/headers"
],
"defines": ["ENABLE_DEBUG=1"],
"compilerPath": "/usr/bin/g++",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "gcc-x64"
},
{
"name": "Win64",
"includePath": [
"${workspaceFolder}/thirdparty/Log/",
"${workspaceFolder}/thirdparty/openvr/headers",
"${workspaceFolder}/thirdparty/libmrbesen/inc",
"${workspaceFolder}/thirdparty/FreeImage/Dist/x64",
"${workspaceFolder}/thirdparty/glew-2.1.0/include",
"${workspaceFolder}/thirdparty/glfw-3.3.2.bin.WIN64/include",
"${workspaceFolder}/thirdparty/",
"${workspaceFolder}/inc/",
"${workspaceFolder}/thirdparty/rawdraw/",
"${workspaceFolder}/thirdparty/openvr/headers"
],
"defines": ["ENABLE_DEBUG=1"],
"compilerPath": "C:/mingw64/bin/g++.exe",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
}

71
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,71 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debuggen (gdb)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/chac",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [{"name": "LD_LIBRARY_PATH", "value": "thirdparty/openvr/bin/linux64/" }],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Automatische Strukturierung und Einrückung für \"gdb\" aktivieren",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "make all",
"miDebuggerPath": "/usr/bin/gdb"
},
{
"name": "Debuggen WIN64 (gdb)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/chac.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Automatische Strukturierung und Einrückung für \"gdb\" aktivieren",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "make win64",
"miDebuggerPath": "C:/mingw64/bin/gdb.exe"
},
{
"name": "test Debuggen (gdb)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/test",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Automatische Strukturierung und Einrückung für \"gdb\" aktivieren",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "make test",
"miDebuggerPath": "/usr/bin/gdb"
}
]
}

43
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,43 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "make all",
"type": "shell",
"command": "make -j all",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "make win64",
"type": "shell",
"command": "mingw32-make.exe -f Makefile.win -j chac.exe",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "make clean",
"type": "shell",
"command": "make clean",
"problemMatcher": []
},
{
"label": "make test",
"type": "shell",
"command": "make -j test",
"problemMatcher": ["$gcc"],
}
]
}

75
Makefile Normal file
View File

@ -0,0 +1,75 @@
# Author Yannis Gerlach
# `make clean all` nicht mit -j verwenden! -> race condition im make file
# statdessen: `make clean; make all -j` verwenden
NAME = chac
NAMETEST = test
CFLAGS = -O2 -g -pipe -Wall -Wextra -Wno-unused-parameter -Wpedantic # -rdynamic
CXX = gcc
SRCF = src/
BUILDDIR = build/
TESTF = tests/
DEPF = $(BUILDDIR)deps/
INCF = inc/
INCFS = $(shell find $(INCF) -type d)
TPF = ./thirdparty/
OPENVRPATH ?= $(TPF)openvr/bin/linux64/
RAWDRAWF = $(TPF)rawdraw/
INCLUDES += -I$(RAWDRAWF) -I$(TPF)openvr/headers/
LDFLAGS = -lX11 -lm -lpthread -lXinerama -lXext -lGL -L$(TPF)openvr/bin/linux64/ -lopenvr_api
DEFINES = ENABLE_DEBUG=1
SRCFILES = $(shell find $(SRCF) -name "*.c")
OBJFILES = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(patsubst %.c, %.o, $(SRCFILES)))
DEPFILES = $(wildcard $(DEPF)*.d)
SOURCEDIRS = $(shell find $(SRCF) -type d -printf "%p/\n")
BUILDDIRS = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(SOURCEDIRS))
OBJFILESTEST = $(filter-out $(BUILDDIR)main.o, $(OBJFILES))
INCLUDES += $(addprefix -I, $(INCFS))
CFLAGS += $(addprefix -D, $(DEFINES))
all: $(NAME) # runtest
$(NAME): $(BUILDDIRS) $(DEPF) $(OBJFILES)
@echo "Linking $@"
$(CXX) $(CFLAGS) -o $@ $(filter %.o, $^) $(filter %.a, $^) $(LDFLAGS)
$(BUILDDIR)%.o: $(SRCF)%.c
@echo "Compiling: $@"
@$(CXX) $(CFLAGS) $(INCLUDES) $< -MM -MT $@ > $(DEPF)$(subst /,_,$*).d
@$(CXX) -c -o $@ $(CFLAGS) $(INCLUDES) $<
$(NAME)_strip: $(NAME)
@echo "Strip $<"
@strip -o $@ $<
%/:
mkdir -p $@
clean-depends:
$(RM) -r $(DEPF)
clean:
$(RM) -r $(NAME) $(BUILDDIR) $(NAMETEST) $(NAME)_strip
$(NAMETEST): $(BUILDDIRS) $(DEPF) $(TESTF)*.c $(OBJFILESTEST)
@echo "Compiling tests"
@$(CXX) -o $@ $(filter %.o, $^) $(filter %.c, $^) $(CFLAGS) -I$(SRCF) $(INCLUDES) $(LDFLAGS)
runtest: $(NAMETEST)
@echo "Running tests"
./$<
# fix assets :
# find assets/ -name '*.*' -exec sh -c 'a=$(echo "$0" | sed -r "s/([^.]*)\$/\L\1/"); [ "$a" != "$0" ] && mv "$0" "$a" ' {} \;
.PHONY: clean all $(NAMETEST) clean-depends runtest
include $(DEPFILES)

209
src/main.c Normal file
View File

@ -0,0 +1,209 @@
// this is mostly copied / inspired by this: https://gist.github.com/cnlohr/6e452dc6cc2df7f48d5ade66059358d9
// made for this video: https://www.youtube.com/watch?v=r6kM3tR03g4
// thanks @cnlohr for rawdraw, alot of other functions, my motivation and the idea
#include <time.h>
#include <stdint.h>
#include <stdbool.h>
#define CNFG_IMPLEMENTATION
#define CNFGOGL
#include "os_generic.h"
#include "CNFG.h"
#undef EXTERN_C
#include "openvr_capi.h"
intptr_t VR_InitInternal( EVRInitError *peError, EVRApplicationType eType );
void VR_ShutdownInternal();
bool VR_IsHmdPresent();
intptr_t VR_GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError );
bool VR_IsRuntimeInstalled();
const char * VR_GetVRInitErrorAsSymbol( EVRInitError error );
const char * VR_GetVRInitErrorAsEnglishDescription( EVRInitError error );
//rawdraw callbacks
void HandleKey( int keycode, int bDown ) { }
void HandleButton( int x, int y, int button, int bDown ) { }
void HandleMotion( int x, int y, int mask ) { }
void HandleDestroy() {
exit(0);
}
// This function was copy-pasted from cnovr.
void* CNOVRGetOpenVRFunctionTable( const char * interfacename ) {
EVRInitError e;
char fnTableName[128];
int result1 = snprintf( fnTableName, 128, "FnTable:%s", interfacename );
void* ret = (void *)VR_GetGenericInterface( fnTableName, &e );
printf( "Getting System FnTable: %s = %p (%d)\n", fnTableName, ret, e );
if( !ret ) {
exit( 1 );
}
return ret;
}
// These are interfaces into OpenVR, they are basically function call tables.
struct VR_IVRSystem_FnTable* oSystem;
struct VR_IVROverlay_FnTable* oOverlay;
// The OpenVR Overlay handle.
VROverlayHandle_t overlayID;
const uint32_t WIDTH = 120, HEIGHT = 24;
int initVR() {
EVRInitError ierr;
uint32_t token = VR_InitInternal( &ierr, EVRApplicationType_VRApplication_Overlay );
if( !token ) {
printf( "Error!!!! Could not initialize OpenVR\n" );
return 1;
}
// Get the system and overlay interfaces. We pass in the version of these
// interfaces that we wish to use, in case the runtime is newer, we can still
// get the interfaces we expect.
oSystem = CNOVRGetOpenVRFunctionTable( IVRSystem_Version );
oOverlay = CNOVRGetOpenVRFunctionTable( IVROverlay_Version );
oOverlay->CreateOverlay( "controlerhandmountedclock", "Controller Hand Mounted Clock", &overlayID );
oOverlay->SetOverlayWidthInMeters( overlayID, .2 );
oOverlay->SetOverlayColor( overlayID, 1., .8, .7 );
// Control texture bounds to control the way the texture is mapped to the overlay.
VRTextureBounds_t bounds;
bounds.uMin = 0;
bounds.uMax = 1;
bounds.vMin = 0;
bounds.vMax = 1;
oOverlay->SetOverlayTextureBounds( overlayID, &bounds );
return 0;
}
GLuint initOverlayTexture() {
// Initialize the texture with junk data.
uint8_t * myjunkdata = malloc( 128 * 128 * 4 );
int x, y;
for( y = 0; y < 128; y++ )
for( x = 0; x < 128; x++ )
{
myjunkdata[ ( x + y * 128 ) * 4 + 0 ] = x * 2;
myjunkdata[ ( x + y * 128 ) * 4 + 1 ] = y * 2;
myjunkdata[ ( x + y * 128 ) * 4 + 2 ] = 0;
myjunkdata[ ( x + y * 128 ) * 4 + 3 ] = 255;
}
// We aren't doing it, but we could write directly into the overlay.
//err = oOverlay->SetOverlayRaw( overlayID, myjunkdata, 128, 128, 4 );
// Generate the texture.
GLuint textureid;
glGenTextures( 1, &textureid );
glBindTexture( GL_TEXTURE_2D, textureid );
// It is required to setup the min and mag filter of the texture.
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
// Load the texture with our dummy data. Optionally we could pass 0 in where we are
// passing in myjunkdata. That would allocate the RAM on the GPU but not do anything with it.
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, myjunkdata);
free(myjunkdata);
return textureid;
}
void attach() {
TrackedDeviceIndex_t index;
index = oSystem->GetTrackedDeviceIndexForControllerRole( ETrackedControllerRole_TrackedControllerRole_LeftHand );
if( index == k_unTrackedDeviceIndexInvalid || index == k_unTrackedDeviceIndex_Hmd ) {
printf( "Couldn't find your controller to attach our overlay to (%d)\n", index );
} else {
// We have a ETrackedControllerRole_TrackedControllerRole_LeftHand. Associate it.
EVROverlayError err;
// Transform that puts the text somewhere reasonable.
HmdMatrix34_t transform = { 0 };
//rotation
transform.m[0][0] = -1;
transform.m[1][2] = -1;
transform.m[2][1] = -1;
//offset
transform.m[0][3] = 0;
transform.m[1][3] = -0.05;
transform.m[2][3] = 0.15;
// Apply the transform and attach the overlay to that tracked device object.
err = oOverlay->SetOverlayTransformTrackedDeviceRelative( overlayID, index, &transform );
// Notify the terminal that this was associated.
printf( "Successfully associated your clock to the tracked device (%d %d %08x).\n",
err, index, overlayID );
}
}
int main() {
if(initVR()) return 1;
CNFGSetup( "CHAC", -WIDTH, -HEIGHT );
oOverlay->ShowOverlay( overlayID );
GLuint texture = initOverlayTexture();
//associate with controller
attach();
CNFGBGColor = 0x00000000; //Background
while(1) {
CNFGClearFrame();
//Change color to white.
CNFGColor( 0xffffffff );
CNFGPenX = 1; CNFGPenY = 1;
//draw clock
char clock[9];
time_t curr = time(NULL);
struct tm * formtime = localtime(&curr);
strftime(clock, 9, "%H:%M:%S", formtime);
CNFGDrawText( clock, 5 );
// Finish rendering any pending draw operations.
CNFGFlushRender();
// Bind the texture we will be sending to OpenVR.
glBindTexture( GL_TEXTURE_2D, texture );
// Copy the current framebuffer into that texture.
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, WIDTH, HEIGHT, 0 );
{
// Setup a Texture_t object to send in the texture.
struct Texture_t tex;
tex.eColorSpace = EColorSpace_ColorSpace_Auto;
tex.eType = ETextureType_TextureType_OpenGL;
tex.handle = (void*)(intptr_t)texture;
// Send texture into OpenVR as the overlay.
oOverlay->SetOverlayTexture( overlayID, &tex );
}
// We have to process through texture events.
{
struct VREvent_t nEvent;
oOverlay->PollNextOverlayEvent( overlayID, &nEvent, 0xffffff );
}
// Display the image and wait for time to display next frame.
CNFGSwapBuffers();
OGUSleep( (int)( 0.1 * 1000000 ) );
}
}

26
tests/main.cpp Normal file
View File

@ -0,0 +1,26 @@
#include <stdio.h>
#include "test.h"
//tests
test_t tests[] = {NULL};
int main(int argc, char** argv) {
test_t* current = tests;
int failcount = 0;
int testcount = 0;
for(; *current; current++) {
testcount++;
printf("\033[1mRunning test number: %d ", testcount);
if((*current)()) {
printf("\033[1;92msucceeded\033[0;1m!\n");
} else {
printf("\033[1;91mfailed\033[0;1m\n");
failcount++;
}
}
printf("\033[1;93m%d\033[0;1m/%d failed\n", failcount, testcount);
return failcount > 0;
}

11
tests/test.h Normal file
View File

@ -0,0 +1,11 @@
#define TESTFAILED 0
#define TESTGOOD 1
#include <iostream>
#define TESTDATA "./tests/data/"
#define ASSERT(BED, ERR) if(!(BED)) { std::cout << __FILE__ << ":" << __LINE__ << " " << ERR << std::endl; return TESTFAILED; }
// #define ASSERT(BED) ASSERT(BED, "")
typedef int (*test_t)();

1
thirdparty/openvr vendored Submodule

@ -0,0 +1 @@
Subproject commit 4c85abcb7f7f1f02adaf3812018c99fc593bc341

1
thirdparty/rawdraw vendored Submodule

@ -0,0 +1 @@
Subproject commit e352fc1dfb050a30aa5b86c4943dda5c30790316