Initial commit.

Another nuke! This time, trying to do a client <-> server thing.

Also a bit of messing with Lua.
This commit is contained in:
Bubblegumdrop 2022-01-02 19:28:16 -05:00
commit 46b2ed80ae
45 changed files with 3152 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.d/
.o/
imgui/
main_client
main_server
*.png
res/

190
Makefile Normal file
View File

@ -0,0 +1,190 @@
.PHONY: all clean
.POSIX:
# {{{ Flags
SRCDIR := src
OBJDIR := .o
DEPDIR := .d
TESTDIR := test
MKDIR := mkdir -p
# }}}
PROGS := main_client main_server
IMGUI_INCLUDE := -Iimgui -Iimgui/backends
IMGUI_SRCS := \
imgui/backends/imgui_impl_glfw.cpp \
imgui/backends/imgui_impl_opengl3.cpp \
imgui/imgui.cpp \
imgui/imgui_demo.cpp \
imgui/imgui_draw.cpp \
imgui/imgui_tables.cpp \
imgui/imgui_widgets.cpp
SRCS := $(wildcard $(SRCDIR)/*.cpp) $(IMGUI_SRCS)
OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(SRCS)))
DEPS := $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))
$(shell $(MKDIR) $(dir $(OBJS)) >/dev/null)
$(shell $(MKDIR) $(dir $(DEPS)) >/dev/null)
COMMON_OBJS := \
$(OBJDIR)/src/lib_lua_common.o \
$(OBJDIR)/src/lib_SDL_common.o \
$(OBJDIR)/src/signal_common.o
SERVER_OBJS := \
$(OBJDIR)/src/server_main.o \
$(OBJDIR)/src/Server.o \
$(COMMON_OBJS)
CLIENT_OBJS := \
$(OBJDIR)/src/camera.o \
$(OBJDIR)/src/client_common.o \
$(OBJDIR)/src/client_main.o \
$(OBJDIR)/src/Client.o \
$(OBJDIR)/src/cube.o \
$(OBJDIR)/src/FileIO.o \
$(OBJDIR)/src/lib_GL_common.o \
$(OBJDIR)/src/object.o \
$(OBJDIR)/src/quad.o \
$(OBJDIR)/src/shader.o \
$(OBJDIR)/src/UDP_Write.o \
$(COMMON_OBJS)
IMGUI_OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(IMGUI_SRCS)))
TEST_OBJ_COMMON := \
$(OBJDIR)/src/FileIO.o \
$(COMMON_OBJS)
TESTS := test_FileIO test_File_Write_UDP test_Object test_lua
TEST_PROGS := $(addprefix $(TESTDIR)/,$(TESTS))
# {{{ Flags
CC := gcc
CXX := g++
LD := g++
ifeq ($(CLANG),1)
CC := clang-12
CXX := clang++-12
LD := clang-12
endif
SRCDIR := src
OBJDIR := .o
DEPDIR := .d
RM := rm -rf
PKGS := SDL2_image SDL2_mixer SDL2_ttf SDL2_net sdl2 gl glew lua54
CPPFLAGS := $(shell pkg-config --cflags $(PKGS))
LDLIBS := $(shell pkg-config --libs $(PKGS)) -lm
DEFS := -D_FILE_OFFSET_BITS=64
INCS := -Iinclude $(IMGUI_INCLUDE)
DEBUG := -g
ifeq ($(D),1)
DEBUG := -ggdb
OPT := -O0
DEFS += -DDEBUG=1
endif
OPT := -O0
ifeq ($(O),1)
OPT := -O1 -g
endif
ifeq ($(O),2)
OPT := -O2 -g
endif
ifeq ($(O),3)
OPT := -O3 -g0
endif
ifeq ($(LTO),1)
LDFLAGS += -flto -fwhole-program
endif
ifeq ($(PG),1)
CFLAGS += -pg -coverage
endif
ifeq ($(PEDANTIC),1)
CFLAGS += -pedantic
endif
CFLAGS += -std=c99
CXXFLAGS += -std=c++14
CPPFLAGS += -fPIC -W -Wextra -Wall $(DEFS) $(DEBUG) $(INCS) $(OPT)
# flags required for dependency generation; passed to compilers
DEPFLAGS = -MT $@ -MD -MP -MF $(DEPDIR)/$*.Td
# compile C source files
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@
# compile C++ source files
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -o $@
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) -o $@
LINK.so = $(LD) $(LDFLAGS) -o $@ -shared
# precompile step
PRECOMPILE =
# postcompile step
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
# }}}
.SUFFIXES: .c .cc .cpp .cxx .o .1
all: $(OBJS) $(PROGS)
main_client: $(CLIENT_OBJS)
$(LINK.o) $^ $(LDLIBS)
main_server: $(SERVER_OBJS)
$(LINK.o) $^ $(LDLIBS)
test: $(TEST_PROGS)
test/test_FileIO: $(TEST_OBJ_COMMON)
test/test_File_Write_UDP: $(TEST_OBJ_COMMON) $(OBJDIR)/src/client_common.o $(OBJDIR)/src/UDP_Write.o $(OBJDIR)/src/Client.o
test/test_Object: $(TEST_OBJ_COMMON) $(OBJDIR)/src/object.o $(OBJDIR)/src/quad.o $(OBJDIR)/src/cube.o $(OBJDIR)/src/lib_GL_common.o
test/test_lua: $(TEST_OBJ_COMMON) $(OBJDIR)/src/lib_lua_common.o
$(OBJDIR)/%.o: %.c
$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.c) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cc
$(OBJDIR)/%.o: %.cc $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cxx
$(OBJDIR)/%.o: %.cxx $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
clean:
@echo $(RM) $(DEPDIR) $(OBJDIR) $(PROGS)
@echo $(RM) $(TEST_PROGS)
.PRECIOUS: $(DEPDIR)/%.d
$(DEPDIR)/%.d: ;
-include $(DEPS)

46
glsl/header.f.glsl Normal file
View File

@ -0,0 +1,46 @@
/* vim: set ft=c: */
#version 440 core
uniform float iChannelTime[4];
uniform float iFrameRate;
uniform float iSampleRate;
uniform float iTime;
uniform float iTimeDelta;
uniform int iFrame;
uniform vec3 iChannelResolution[4];
uniform vec3 iResolution;
uniform vec4 iDate;
uniform vec4 iMouse;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform sampler2D iChannel3;
/*
TODO: Generate this section
uniform sampler2D iChannel0;
uniform samplerCube iChannel0;
uniform sampler3D iChannel0;
uniform sampler2D iChannel0;
uniform struct {
sampler2D sampler;
samplerCube sampler;
sampler3D sampler;
vec3 size;
float time;
int loaded;
} iCh0;
*/
out vec4 fragColor;
in vec2 TexCoords;
void mainImage(out vec4, in vec2);
void main(void) {
mainImage(fragColor, gl_FragCoord.xy);
}

15
glsl/new.f.glsl Normal file
View File

@ -0,0 +1,15 @@
/* vim: set ft=c: */
/* <https://www.shadertoy.com/new> */
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// Normalized pixel coordinates (from 0 to 1)
// vec2 uv = TexCoords; // fragCoord / iResolution.xy;
vec2 uv = fragCoord / iResolution.xy;
// Time varying pixel color
vec3 col = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0, 2, 4));
// Output to screen
fragColor = vec4(col, 1.0);
}

21
include/Client.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <vector>
#include <SDL_net.h>
class Client
{
std::string mHost;
Uint16 mPort;
int mChannel;
std::vector<UDPsocket> UDPsocks;
public:
Client (void)
{
}
Client (const char* host, const Uint16 port, const int channel);
UDPsocket UDP_Open (const char* host, const Uint16 port, const int channel);
void UDP_CloseAll (void);
};

43
include/FileIO.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64 /* off_t */
#endif
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#include <ctime>
#include <string>
class FileIO
{
FILE* fp;
std::string path;
public:
~FileIO (void)
{
if (fp)
{
Close ();
fp = NULL;
}
}
FileIO (const std::string&, const std::string&);
FileIO (FILE* f)
{
fp = f;
}
FILE* Open (const std::string&, const std::string&);
int Close (void);
int Seek (const off_t, const int);
off_t Tell (void);
size_t Read(void*, const size_t);
size_t Write (const void*, const size_t);
void Rewind (void);
/* I added these. */
time_t Mtime (void);
off_t Size (void);
std::string ReadToString (void);
};

6
include/SDL_clamp.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
/*
* <https://github.com/libsdl-org/SDL/commit/35c1bbfa49b1247c2c6240f7f95871f3b3331874>
*/
#define SDL_clamp(x, a, b) ((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x))

38
include/Server.h Normal file
View File

@ -0,0 +1,38 @@
#pragma once
#include <string>
#include <vector>
#include <SDL.h>
#include <SDL_net.h>
/* MTU */
#define MAX_PACKET_SIZE (1024*1024)
class Server
{
bool mProcessPacketCallbackRunning;
SDL_TimerID mProcessPacketCallbackTimerID;
static Uint32 ProcessPacketCallback (Uint32, void*);
public:
std::vector<UDPsocket> UDPsocks;
SDLNet_SocketSet SocketSet;
UDPpacket **UDPPacketV;
Server (void)
{
mProcessPacketCallbackRunning = false;
UDPsocks.clear ();
SocketSet = NULL;
UDPPacketV = NULL;
}
Server (const char* host, const Uint16 port);
UDPsocket UDP_Open (Uint16 port);
void UDP_CloseAll (void);
void ProcessPacket (UDPpacket* packet);
void Start (void);
void Stop (void);
bool ProcessPacketCallbackRunning (void)
{
return mProcessPacketCallbackRunning;
}
};

View File

8
include/UDP_Write.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <SDL_net.h>
int Buffer_Write_UDP (UDPsocket udpsock, const int channel, const size_t mtu, const void* buf, const size_t size);
int File_Write_UDP (UDPsocket udpsock, const int channel, const size_t mtu, const char* path);
int SendFile_UDP (const char* host, const Uint16 port, const int channel, const size_t mtu, const char* path);
int SendBuffer_UDP (const char* host, const Uint16 port, const int channel, const size_t mtu, const void* buf, const size_t size);

71
include/camera.h Normal file
View File

@ -0,0 +1,71 @@
#pragma once
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/mat4x4.hpp>
/**
* Default camera values
*/
#define DEFAULT_CAMERA_YAW (-90.0f)
#define DEFAULT_CAMERA_PITCH (0.0f)
#define DEFAULT_CAMERA_ROLL (0.0f)
#define DEFAULT_CAMERA_SPEED (1.0f)
#define DEFAULT_CAMERA_SENSITIVITY (1.0f)
#define DEFAULT_CAMERA_JOYSENSITIVITY (1.0f)
#define DEFAULT_CAMERA_ZOOM (45.0f)
/*
* Decelerate at gravity speed (9.8 m/s) / ???
*/
#define DEFAULT_CAMERA_DECELERATIONSPEED (0.98f)
#define DEFAULT_CAMERA_MOUSEDECELERATIONSPEED (0.098f)
class Camera
{
/**
* An abstract camera class that processes input and calculates the corresponding
*/
glm::vec3 Position;
glm::vec3 Front;
glm::vec3 Right;
glm::vec3 Up;
glm::vec3 WorldUp;
/** Euler Angles, Vectors and Matrices for use in OpenGL. */
glm::vec3 Angles;
/* XXX Maybe we shouldn't let the camera move? */
glm::vec3 Direction; /* Position movement */
glm::vec2 ViewDirection; /* Yaw, Pitch movement */
void updateCameraVectors (void);
public:
/**
* Defines several possible options for camera movement.
* Used as abstraction to stay away from window-system specific input methods
*/
enum Movement
{
FORWARD, BACKWARD, LEFT, RIGHT, UP, DOWN, CW, CCW, NONE
};
/** Camera options */
float MovementSpeed, MouseSensitivity, Zoom;
float DecelerationSpeed, ViewDecelerationSpeed, JoystickSensitivity;
float zNear, zFar;
Camera (
const glm::vec3 position = glm::vec3(0.0f, 0.0f, 1.0f)
, const glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f)
, const float yaw = DEFAULT_CAMERA_YAW
, const float pitch = DEFAULT_CAMERA_PITCH
, const float roll = DEFAULT_CAMERA_ROLL);
glm::mat4 GetViewMatrix (const bool constrainPitch = true);
void ProcessJoystickMovement (const float xoffset, const float yoffset, const float deltaTime);
void ProcessKeyboard (const Camera::Movement direction, const float deltaTime);
void ProcessMouseMovement (const float xoffset, const float yoffset, const float deltaTime);
void ProcessMouseScroll (const float xoffset, const float yoffset, const float deltaTime);
};

12
include/cube.h Normal file
View File

@ -0,0 +1,12 @@
#include "object.h"
class Cube : Object
{
public:
Cube (void)
{
}
Cube (const GLsizei);
void Draw (void);
};

23
include/debug.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#ifdef DEBUG
#include <SDL_log.h>
#include <stdarg.h>
#define DEBUG_LOG(...) debug_log (__FILE__, __LINE__, __VA_ARGS__)
static void debug_log (const char* filename, const int lineno, const char* fmt, ...)
{
char buf[8192];
va_list ap;
SDL_memset (buf, 0, sizeof buf);
va_start (ap, fmt);
vsnprintf (buf, (sizeof buf) - 1, fmt, ap);
va_end (ap);
SDL_LogMessage (SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "%s:%d: %s", filename, lineno, buf);
}
#else
#define DEBUG_LOG(...)
#endif

5
include/events_common.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
enum {
PACKET_SDL_EVENT = SDL_USEREVENT,
};

14
include/glCheckErrors.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <stdio.h>
#include <GL/glew.h>
#define glCheckErrors() \
do \
{ \
GLenum err; \
while ((err = glGetError()) != GL_NO_ERROR) \
{ \
fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, glewGetErrorString(err)); \
} \
} while (0)

14
include/lib_GL_common.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <string>
#include <GL/glew.h>
#include <SDL_video.h>
void common_GL_Init (SDL_Window*, SDL_GLContext*, int);
void common_GL_TexParameters (const GLenum, const GLenum, const GLenum, const GLenum, const GLenum);
GLuint common_GL_SurfaceFormat (SDL_Surface*);
GLuint common_GL_LoadTextureSurface (SDL_Surface*);
GLuint common_GL_LoadTexturePath (const std::string&);

21
include/lib_SDL_common.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <GL/glew.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <SDL_net.h>
#include <SDL_ttf.h>
#include <SDL_opengl.h>
void common_SDL_Init (void);
void common_SDL_Quit (void);
void common_SDL_CreateWindow (SDL_Window**);
int common_SDL_ToggleFullscreen (SDL_Window*);
SDL_Surface* common_SDL_LoadSurfacePath (const std::string&);

17
include/lib_lua_common.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <stddef.h> /* size_t */
#ifdef __cplusplus
extern "C"
{
#endif
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#ifdef __cplusplus
};
#endif
void common_lua_stack_dump (lua_State*);
int common_lua_run (lua_State*, const char*, const char*, const size_t);

19
include/object.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <GL/glew.h>
class Object
{
protected:
GLsizei mGLsizei;
GLuint VBO, EBO;
public:
GLuint VAO;
Object (void) : mGLsizei (0)
{
}
Object (const GLsizei);
~Object (void);
};

12
include/quad.h Normal file
View File

@ -0,0 +1,12 @@
#include "object.h"
class Quad : Object
{
public:
Quad (void)
{
}
Quad (const GLsizei);
void Draw (void);
};

36
include/shader.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <map>
#include <string>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
class ShaderProgram
{
bool mUniformLocationsNeedRefresh;
std::map<const std::string, GLint> UniformLocationCache;
static GLint my_checkCompileSuccess (const GLuint id, const GLenum type);
public:
GLuint ID;
ShaderProgram (void);
ShaderProgram (const std::string&, const std::string&, const std::string&);
GLint getCachedLoc (const std::string&);
void RefreshUniformLocations (void);
void Use (void);
void Bool (const std::string&, const bool&value);
void Float (const std::string&, const float&value);
void Int (const std::string&, const int&value);
void Vec2 (const std::string&, const glm::vec2& value);
void Vec3 (const std::string&, const glm::vec3& value);
void Vec4 (const std::string&, const glm::vec4& value);
void Mat2 (const std::string&, const glm::mat2& value);
void Mat3 (const std::string&, const glm::mat3& value);
void Mat4 (const std::string&, const glm::mat4& value);
GLuint CompileShaderBuffer (const std::string&, const GLenum type);
GLuint CompileShaderPath (const std::string&, const GLenum type);
GLint LinkProgram (void);
};

3
include/signal_common.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void common_Signal_Init (void);

36
include/trim.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
/* https://stackoverflow.com/a/217605 */
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
// trim from start
static inline
std::string&
ltrim (std::string& s)
{
s.erase (s.begin (), std::find_if (s.begin (), s.end (), std::not1 (std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
static inline
std::string&
rtrim (std::string& s)
{
s.erase (std::find_if (s.rbegin (), s.rend (), std::not1 (std::ptr_fun <int, int>(std::isspace))).base (), s.end ());
return s;
}
// trim from both ends
static inline
std::string&
trim (std::string& s)
{
return ltrim (rtrim (s));
}

7
include/unused.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#ifdef UNUSED
#undef UNUSED
#endif
#define UNUSED(x) ((void)(x))

53
src/Client.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "debug.h"
#include "Client.h"
Client::Client (const char* host, const Uint16 port, const int channel)
{
UDPsocket udpsock;
if (NULL != (udpsock = UDP_Open (host, SDL_SwapBE16 (port), channel)))
{
mHost = host;
mPort = port;
mChannel = channel;
UDPsocks.push_back (udpsock);
}
}
UDPsocket
Client::UDP_Open (const char* host, const Uint16 port, const int channel)
{
IPaddress address;
UDPsocket udpsock;
if (!(udpsock = SDLNet_UDP_Open (0)))
{
DEBUG_LOG ("SDLNet_UDP_Open: %s", SDLNet_GetError ());
return NULL;
}
if (SDLNet_ResolveHost (&address, host, port) < 0)
{
DEBUG_LOG ("SDLNet_ResolveHost: %s", SDLNet_GetError ());
return NULL;
}
if (SDLNet_UDP_Bind (udpsock, channel, &address) < 0)
{
DEBUG_LOG ("SDLNet_UDP_Bind: %s", SDLNet_GetError ());
return NULL;
}
return udpsock;
}
void
Client::UDP_CloseAll (void)
{
size_t i;
const size_t nclients = UDPsocks.size ();
for (i = 0; i < nclients; i++)
{
SDLNet_UDP_Unbind (UDPsocks[i], mChannel);
SDLNet_UDP_Close (UDPsocks[i]);
UDPsocks[i] = NULL;
}
UDPsocks.clear ();
}

100
src/FileIO.cpp Normal file
View File

@ -0,0 +1,100 @@
#include "FileIO.h"
#include <vector>
#include <errno.h> /* errno */
#include <stdio.h> /* FILE* */
#include <sys/stat.h> /* stat */
#include <sys/types.h> /* stat */
#include <unistd.h> /* stat */
FileIO::FileIO (const std::string& filename, const std::string& mode)
{
if (!(fp = Open (filename, mode)))
throw errno;
path = filename;
}
FILE*
FileIO::Open (const std::string& filename, const std::string& mode)
{
return fopen (filename.c_str (), mode.c_str ());
}
int
FileIO::Close (void)
{
return fclose (fp);
}
int
FileIO::Seek (const off_t offset, const int whence)
{
return fseeko (fp, offset, whence);
}
off_t
FileIO::Tell (void)
{
return ftello (fp);
}
size_t
FileIO::Read (void *dst, const size_t size)
{
return fread (dst, sizeof (char), size, fp);
}
size_t
FileIO::Write (const void *dst, const size_t size)
{
return fwrite (dst, sizeof (char), size, fp);
}
void
FileIO::Rewind (void)
{
rewind (fp);
}
time_t
FileIO::Mtime (void)
{
time_t rc;
struct stat sb;
rc = 0;
if (!stat (path.c_str (),&sb))
rc = sb.st_mtime;
else
throw errno;
return rc;
}
off_t
FileIO::Size (void)
{
off_t rc;
Seek (0, SEEK_END);
rc = Tell ();
Rewind ();
return rc;
}
std::string
FileIO::ReadToString (void)
{
off_t size = Size () + 1;
std::vector<char> b (size);
off_t nread = Read (b.data (), size);
return std::string ((const char *) b.data (), nread);
}

34
src/SDL_ReadWrite64.cpp Normal file
View File

@ -0,0 +1,34 @@
#include <SDL.h>
#include <SDL_net.h>
/* Write a 64-bit value to network packet buffer */
#define SDLNet_Write64(value, areap) _SDLNet_Write64 (value, areap)
/* Read a 64-bit value from network packet buffer */
#define SDLNet_Read64(areap) _SDLNet_Read64 (areap)
SDL_FORCE_INLINE void
_SDLNet_Write64 (Uint64 value, void* areap)
{
Uint8* area = (Uint8*) areap;
area[0] = (value >> 56) & 0xFF;
area[1] = (value >> 48) & 0xFF;
area[2] = (value >> 40) & 0xFF;
area[3] = (value >> 32) & 0xFF;
area[4] = (value >> 24) & 0xFF;
area[5] = (value >> 16) & 0xFF;
area[6] = (value >> 8) & 0xFF;
area[7] = value & 0xFF;
}
SDL_FORCE_INLINE Uint64
_SDLNet_Read64 (const void* areap)
{
const Uint8* area = (const Uint8*) areap;
return (
((Uint64) area[0]) << 56) | (((Uint64) area[1]) << 48) |
(((Uint64) area[2]) << 40) | (((Uint64) area[3]) << 32) |
(((Uint64) area[4]) << 24) | (((Uint64) area[5]) << 16) |
(((Uint64) area[6]) << 8) | (((Uint64) area[7]));
}

179
src/Server.cpp Normal file
View File

@ -0,0 +1,179 @@
#include "debug.h"
#include "Server.h"
#include "events_common.h"
#include <arpa/inet.h> /* inet_ntop */
Server::Server (const char *host, const Uint16 port)
{
IPaddress ipaddress;
UDPsocket udpsock;
char hoststring[128];
if (SDLNet_ResolveHost (&ipaddress, host, SDL_SwapBE16 (port)) < 0)
{
DEBUG_LOG ("SDLNet_ResolveHost: %s", SDLNet_GetError ());
return;
}
if (NULL != (udpsock = UDP_Open (ipaddress.port)))
{
UDPsocks.push_back (udpsock);
mProcessPacketCallbackRunning = false;
inet_ntop (AF_INET, &ipaddress.host, hoststring, 128);
SDL_Log ("Listening on %s:%d", hoststring, ipaddress.port);
}
else
{
SDL_Log ("Unable to bind to port %d; is it in use?", ipaddress.port);
}
}
void
Server::UDP_CloseAll (void)
{
size_t i, nclients;
nclients = UDPsocks.size ();
SDL_Log ("Server::~Server %ld", nclients);
for (i = 0; i < nclients; i++)
{
SDLNet_UDP_Close (UDPsocks[i]);
UDPsocks[i] = NULL;
}
UDPsocks.clear ();
}
/*
* Open and keep track of a UDP socket.
*/
UDPsocket
Server::UDP_Open (const Uint16 port)
{
UDPsocket udpsock;
if (!(udpsock = SDLNet_UDP_Open (port)))
{
DEBUG_LOG ("SDLNet_UDP_Open: %s", SDLNet_GetError ());
return NULL;
}
return udpsock;
}
void
Server::ProcessPacket (UDPpacket * packet)
{
size_t len;
SDL_Event event;
SDL_UserEvent userevent;
UDPpacket *temp;
len = packet->len;
temp = SDLNet_AllocPacket (len);
SDL_memcpy (&temp->address, &packet->address, sizeof (IPaddress));
SDL_memcpy (temp->data, packet->data, len);
temp->len = len;
SDL_zero (event);
SDL_zero (userevent);
userevent.type = PACKET_SDL_EVENT;
userevent.code = 0;
userevent.data1 = (void *) temp;
userevent.data2 = (void *) NULL;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent (&event);
}
void
Server::Start (void)
{
size_t i;
int nclients, numused;
nclients = (int) UDPsocks.size ();
SDL_Log ("Server %d clients", nclients);
if (!(UDPPacketV = SDLNet_AllocPacketV (nclients, MAX_PACKET_SIZE)))
{
DEBUG_LOG ("SDLNet_AllocPacketV: %s", SDLNet_GetError ());
return;
}
if (!(SocketSet = SDLNet_AllocSocketSet (nclients)))
{
DEBUG_LOG ("SDLNet_AllocSocketSet: %s", SDLNet_GetError ());
return;
}
for (i = 0; i < (size_t) nclients; i++)
{
numused = SDLNet_UDP_AddSocket (SocketSet, UDPsocks[i]);
if (numused < 0)
{
DEBUG_LOG ("SDLNet_AddSocket: %s", SDLNet_GetError ());
return;
}
}
mProcessPacketCallbackRunning = true;
mProcessPacketCallbackTimerID = SDL_AddTimer (10, Server::ProcessPacketCallback, (void *) this);
}
void
Server::Stop (void)
{
size_t i, nclients;
mProcessPacketCallbackRunning = false;
SDL_RemoveTimer (mProcessPacketCallbackTimerID);
nclients = UDPsocks.size ();
for (i = 0; i < nclients; i++)
{
SDLNet_UDP_DelSocket (SocketSet, UDPsocks[i]);
}
SDLNet_FreeSocketSet (SocketSet);
SocketSet = NULL;
SDLNet_FreePacketV (UDPPacketV);
UDPPacketV = NULL;
}
Uint32
Server::ProcessPacketCallback (Uint32 interval, void *param)
{
int numrecv, numready;
size_t i, j;
SDL_assert (NULL != param);
Server & server = *(Server *) param;
if (!server.ProcessPacketCallbackRunning ())
return 0;
numready = SDLNet_CheckSockets (server.SocketSet, ~0);
if (numready < 0)
{
DEBUG_LOG ("SDLNet_CheckSockets: %s", SDLNet_GetError ());
return 0;
}
else if (numready > 0)
{
DEBUG_LOG ("There are %d sockets with activity!", numready);
}
/* check all sockets with SDLNet_SocketReady and handle the active ones. */
for (i = 0; i < (size_t) numready; i++)
{
if (SDLNet_SocketReady (server.UDPsocks[i]))
{
numrecv = SDLNet_UDP_RecvV (server.UDPsocks[i], &server.UDPPacketV[i]);
if (numrecv < 0)
{
DEBUG_LOG ("SDLNet_UDP_RecvV: %s", SDLNet_GetError ());
break;
}
for (j = 0; j < (size_t) numrecv; j++)
{
server.ProcessPacket (server.UDPPacketV[i]);
}
}
}
return interval;
}

123
src/UDP_Write.cpp Normal file
View File

@ -0,0 +1,123 @@
#include "debug.h"
#include "FileIO.h"
#include "Client.h"
#include <vector>
#include <math.h>
#include <SDL.h>
#include <SDL_net.h>
#include <errno.h>
#include <string.h>
/* XXX gross */
int
Buffer_Write_UDP (UDPsocket udpsock, const int channel, const size_t mtu, const void *buf, const size_t size)
{
const char *bufPtr;
const char *bufPtrEnd;
int numsent, npackets;
IPaddress *address;
size_t i, our_nsent, our_mtu;
UDPpacket **packetV;
SDL_assert (mtu > 0);
SDL_assert (size > 0);
numsent = 0;
our_mtu = mtu;
if (size < our_mtu)
our_mtu = size;
npackets = ceil ((double) size / (double) our_mtu);
if (!npackets)
{
DEBUG_LOG ("File_Write_UDP: zero length packet\n");
return 0;
}
packetV = SDLNet_AllocPacketV (npackets, our_mtu);
if (!packetV)
{
DEBUG_LOG ("SDLNet_AllocPacketV: %s\n", SDLNet_GetError ());
return 0;
}
i = 0;
bufPtr = (const char *) buf;
bufPtrEnd = bufPtr + size;
address = SDLNet_UDP_GetPeerAddress (udpsock, channel);
size_t nsent = size;
while (i < (size_t) npackets && bufPtr < bufPtrEnd)
{
our_nsent = nsent;
if (our_nsent > our_mtu)
our_nsent = our_mtu;
packetV[i]->channel = channel;
SDL_memcpy (&packetV[i]->address, address, sizeof (IPaddress));
SDL_memset (packetV[i]->data, 0, our_mtu);
SDL_memcpy (packetV[i]->data, bufPtr, our_nsent);
packetV[i]->len = our_nsent;
bufPtr += our_mtu;
nsent -= our_mtu;
i++;
}
numsent = SDLNet_UDP_SendV (udpsock, packetV, npackets);
if (!numsent)
{
SDL_Log ("SDLNet_UDP_SendV (%d): %s\n", npackets, SDLNet_GetError ());
}
SDLNet_FreePacketV (packetV);
return numsent;
}
int
File_Write_UDP (UDPsocket udpsock, const int channel, const char *path, const size_t mtu)
{
int numsent;
Sint64 size;
numsent = 0;
try
{
FileIO f (path, "r");
size = f.Size ();
std::vector<char> b (size + 1);
f.Read (b.data (), size);
numsent = Buffer_Write_UDP (udpsock, channel, mtu, b.data (), b.size ());
}
catch (int err)
{
SDL_Log ("File_Write_UDP: %s", strerror (errno));
}
return numsent;
}
int
SendBuffer_UDP (const char *host, const Uint16 port, const int channel, const size_t mtu, const void *buf, const size_t size)
{
int numsent;
UDPsocket udpsock;
numsent = 0;
Client client (host, port, channel);
if (udpsock)
{
numsent = Buffer_Write_UDP (udpsock, channel, mtu, buf, size);
client.UDP_CloseAll ();
}
return numsent;
}
int
SendFile_UDP (const char *host, const Uint16 port, const int channel, const size_t mtu, const char *path)
{
int numsent;
UDPsocket udpsock;
numsent = 0;
Client client (host, port, channel);
if (udpsock)
{
numsent = File_Write_UDP (udpsock, channel, path, mtu);
client.UDP_CloseAll ();
}
return numsent;
}

160
src/camera.cpp Normal file
View File

@ -0,0 +1,160 @@
#include "camera.h"
#include "SDL_clamp.h"
#include <assert.h>
#include <math.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
/* https://graphicscompendium.com/opengl/22-interpolation */
static inline
glm::vec2
lerp (const glm::vec2 x, const glm::vec2 y, const float t)
{
return x * (1.f - t) + y * t;
}
static inline
glm::vec3
lerp (const glm::vec3 x, const glm::vec3 y, const float t)
{
return x * (1.f - t) + y * t;
}
Camera::Camera (const glm::vec3 position, const glm::vec3 up, const float yaw, const float pitch, const float roll)
{
Front = glm::vec3 (0.0f, 0.0f, -1.0f);
WorldUp = up;
MovementSpeed = DEFAULT_CAMERA_SPEED;
MouseSensitivity = DEFAULT_CAMERA_SENSITIVITY;
Zoom = DEFAULT_CAMERA_ZOOM;
DecelerationSpeed = DEFAULT_CAMERA_DECELERATIONSPEED;
ViewDecelerationSpeed = DEFAULT_CAMERA_MOUSEDECELERATIONSPEED;
JoystickSensitivity = DEFAULT_CAMERA_JOYSENSITIVITY;
Position = position;
Angles = glm::vec3 (yaw, pitch, roll);
Direction = glm::vec3 (0);
ViewDirection = glm::vec2 (0);
zNear = 0.1f;
zFar = 1000.0f;
updateCameraVectors ();
}
/**
* Calculates the front vector from the Camera's (updated) Euler Angles
*/
void
Camera::updateCameraVectors (void)
{
const glm::mat4 roll_mat =
glm::rotate (glm::mat4 (1.0f), glm::radians (Angles.z), Front);
/**
* Calculate the new Front vector
*/
Front = glm::normalize (glm::vec3
( cos (glm::radians (Angles.x)) * cos (glm::radians (Angles.y))
, sin (glm::radians (Angles.y))
, sin (glm::radians (Angles.x)) * cos (glm::radians (Angles.y))));
// std::cout << glm::to_string (roll_mat) << std::endl;
/**
* Also re-calculate the Right and Up vector
* normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
*/
Right = glm::normalize (glm::cross (Front, WorldUp));
Up = glm::mat3 (roll_mat) * glm::normalize (glm::cross (Right, Front));
}
/**
* Returns the view matrix calculated using Euler Angles and the LookAt Matrix
*/
glm::mat4 Camera::GetViewMatrix (const bool constrainPitch)
{
/*
* XXX Where to handle acceleration?
*
* Seems like since we're probably calling this every frame, this is the place to do it!
*/
Position += Direction;
Angles.x = fmod (Angles.x + ViewDirection.x, 360.0f);
Angles.y += ViewDirection.y;
if (constrainPitch)
{
Angles.y = SDL_clamp (Angles.y, -89.9f, 89.9f);
}
Zoom = SDL_clamp (Zoom, 1.0f, 45.0f);
/**
* Update Front, Right and Up Vectors using the updated Euler angles
*/
updateCameraVectors ();
Direction = lerp (Direction, glm::vec3 (0.0f), DecelerationSpeed);
ViewDirection =
lerp (ViewDirection, glm::vec2 (0.0f), ViewDecelerationSpeed);
// std::cout << glm::to_string (Position) << std::endl;
return glm::lookAt (Position, Position + Front, Up);
}
/**
* Processes input received from any keyboard-like input system.
* Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
*/
void
Camera::ProcessKeyboard (Camera::Movement direction, const float deltaTime)
{
const float velocity = MovementSpeed * deltaTime;
switch (direction)
{
case FORWARD: Direction += Front * velocity; break;
case BACKWARD: Direction -= Front * velocity; break;
case LEFT: Direction -= Right * velocity; break;
case RIGHT: Direction += Right * velocity; break;
case UP: Direction += Up * velocity; break;
case DOWN: Direction -= Up * velocity; break;
case CW: Angles.z += velocity; break;
case CCW: Angles.z -= velocity; break;
default:
break;
}
}
// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
void
Camera::ProcessJoystickMovement (const float xoffset, const float yoffset, const float deltaTime)
{
const float velocity = JoystickSensitivity * deltaTime;
const float Xoffset = xoffset * velocity;
const float Yoffset = yoffset * velocity;
ViewDirection.x += Xoffset;
ViewDirection.y += Yoffset;
}
// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
void
Camera::ProcessMouseMovement (const float xoffset, const float yoffset, const float deltaTime)
{
const float velocity = MouseSensitivity * deltaTime;
const float Xoffset = xoffset * velocity;
const float Yoffset = yoffset * velocity;
ViewDirection.x += Xoffset;
ViewDirection.y += Yoffset;
}
/**
* Processes input received from a mouse scroll-wheel event.
* Only requires input on the vertical wheel-axis.
*/
void
Camera::ProcessMouseScroll (const float xoffset, const float yoffset, const float deltaTime)
{
(void) xoffset;
(void) deltaTime;
// Angles.z += (float) xoffset;
Zoom += (float) yoffset;
}

417
src/client_main.cpp Normal file
View File

@ -0,0 +1,417 @@
#include "camera.h"
#include "Client.h"
#include "cube.h"
#include "debug.h"
#include "glCheckErrors.h"
#include "lib_GL_common.h"
#include "lib_SDL_common.h"
#include "quad.h"
#include "shader.h"
#include "signal_common.h"
#include "UDP_Write.h"
#include "unused.h"
#include <memory>
#include <vector>
#include <getopt.h> /* getopt */
#include <stdlib.h> /* exit */
#include <string.h> /* memset */
#include <unistd.h> /* getopt */
#include <glm/vec3.hpp>
#include <glm/gtc/type_ptr.hpp>
#define Perf_Diff(a, b) ((double) 1000 * ((double)(((double) (b) - (double) (a)) / (double) SDL_GetPerformanceFrequency ())))
#define MIN_FRAME_MS 7 /* 144 Hz */
static int my_AnalogInput (void);
static int my_Input (SDL_Event *);
static int my_Input_Key (SDL_Event *);
static int my_SDL_WindowEvent (SDL_Event *);
static void my_GetOpt (int, char **);
static void my_Init (int, char**);
static void my_Render (void);
static void my_UpdateValues (void);
static void my_Usage (const char *);
struct Uniform_Values
{
int iFrame;
float iFrameRate;
float iSampleRate;
float iTime;
float iTimeDelta;
glm::vec3 iResolution;
glm::vec4 iDate;
glm::vec4 iMouse;
std::vector<unsigned int> iChannel;
std::vector<float> iChannelTime;
std::vector<glm::vec3> iChannelResolution;
};
struct Client_State
{
int quit;
Uint64 start, end;
double diff;
UDPsocket udpsock;
const char* host;
Uint16 port;
int channel;
int mtu;
SDL_GLContext GLContext;
SDL_Window *Window;
int Window_Height;
int Window_Width;
double ShaderTimeDividend;
bool ImGuiEnabled;
bool ShaderPlaying;
bool InputCaptureMouse;
bool InputFirstMouse;
bool InputRelativeMouseMode;
bool RenderShowQuad;
};
static std::shared_ptr<Cube> cube;
static std::shared_ptr<Quad> quad;
static Camera camera;
static ShaderProgram shader;
static struct Client_State state;
static struct Uniform_Values values;
int
main (int argc, char **argv)
{
SDL_Event event;
glm::mat4 model, view, projection;
my_Init (argc, argv);
shader = ShaderProgram ("../handmade-x/glsl/camera.v.glsl", "", "./glsl/new.f.glsl");
if (!shader.ID)
{
SDL_Log ("Unable to load shader.");
goto _out;
}
camera = Camera ();
cube = std::make_shared<Cube> (1);
quad = std::make_shared<Quad> (1);
state.mtu = 1450;
state.quit = 0;
if (NULL == (state.udpsock = Client::UDP_Open (state.host, state.port, state.channel)))
{
SDL_Log ("Unable to open client port");
goto _out;
}
while (!state.quit)
{
state.end = SDL_GetPerformanceCounter ();
state.diff = Perf_Diff (state.start, state.end);
while (state.diff < MIN_FRAME_MS)
{
SDL_Delay (1);
state.end = SDL_GetPerformanceCounter ();
state.diff = Perf_Diff (state.start, state.end);
}
state.start = SDL_GetPerformanceCounter ();
SDL_SetRelativeMouseMode ((SDL_bool) state.InputRelativeMouseMode);
SDL_CaptureMouse ((SDL_bool) state.InputCaptureMouse);
while (!state.quit && SDL_PollEvent (&event))
{
state.quit = my_Input (&event);
}
my_AnalogInput ();
my_UpdateValues ();
projection = glm::perspective (glm::radians (camera.Zoom), (float) values.iResolution.x / (float) values.iResolution.y, camera.zNear, camera.zFar);
view = camera.GetViewMatrix ();
model = glm::mat4 (1.0f);
shader.Use ();
shader.Int ("iFrame", values.iFrame);
shader.Float ("iTime", values.iTime);
shader.Float ("iTimeDelta", values.iTimeDelta);
shader.Vec3 ("iResolution", values.iResolution);
shader.Mat4 ("Projection", projection);
shader.Mat4 ("View", view);
shader.Mat4 ("Model", model);
my_Render ();
SDL_GL_SwapWindow (state.Window);
}
_out:
client.UDP_CloseAll ();
SDL_GL_DeleteContext (state.GLContext);
SDL_DestroyWindow (state.Window);
common_SDL_Quit ();
return 0;
}
static void
my_Init (int argc, char** argv)
{
common_Signal_Init ();
my_GetOpt (argc, argv);
state.start = state.end = SDL_GetPerformanceCounter ();
common_SDL_Init ();
common_SDL_CreateWindow (&state.Window);
common_GL_Init (state.Window, &state.GLContext, 1);
SDL_GetWindowSize (state.Window, &state.Window_Width, &state.Window_Height);
state.ShaderPlaying = true;
state.ShaderTimeDividend = 1000;
state.InputRelativeMouseMode = false;
state.InputCaptureMouse = false;
}
static void
my_UpdateValues (void)
{
values.iFrame++;
if (state.ShaderPlaying)
{
values.iTime += ((double) state.diff / (double) state.ShaderTimeDividend);
}
values.iTimeDelta = ((double) state.diff / (double) 1000);
values.iResolution.x = state.Window_Width;
values.iResolution.y = state.Window_Height;
values.iResolution.z = 1.0;
}
static void
my_Render (void)
{
glClearColor (0, 0, 0, 1);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (state.RenderShowQuad)
{
// glEnable (GL_DEPTH_TEST);
cube->Draw ();
}
else
quad->Draw ();
}
static int
my_SDL_MouseMotion (SDL_Event * event)
{
SDL_assert (NULL != event);
const float
xpos = event->motion.x;
const float
ypos = event->motion.y;
if (!state.InputCaptureMouse || state.ImGuiEnabled)
return SDL_FALSE;
if (state.InputFirstMouse)
{
values.iMouse.x = xpos;
values.iMouse.y = ypos;
state.InputFirstMouse = false;
}
// reversed since y-coordinates go from bottom to top
const float
Xoffset = xpos - values.iMouse.x;
const float
Yoffset = values.iMouse.y - ypos;
values.iMouse.x = xpos;
values.iMouse.y = ypos;
camera.ProcessMouseMovement (Xoffset, Yoffset, 0.1);
return SDL_FALSE;
}
static int
my_SDL_MouseButton (SDL_Event * event)
{
int down;
int quit;
SDL_assert (NULL != event);
down = event->type == SDL_MOUSEBUTTONDOWN;
quit = SDL_FALSE;
return quit;
}
static int
my_Input (SDL_Event * event)
{
int quit;
SDL_assert (NULL != event);
quit = SDL_FALSE;
switch (event->type)
{
case SDL_QUIT:
quit = SDL_TRUE;
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
quit = my_Input_Key (event);
break;
case SDL_MOUSEMOTION:
my_SDL_MouseMotion (event);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
my_SDL_MouseButton (event);
break;
case SDL_WINDOWEVENT:
my_SDL_WindowEvent (event);
break;
default:
break;
}
return quit;
}
static int
my_AnalogInput (void)
{
const Uint8 *
kbd = SDL_GetKeyboardState (NULL);
const float
dt = 0.016;
(void) state;
camera.ProcessKeyboard (kbd[SDL_SCANCODE_W] ? Camera::Movement::FORWARD : Camera::Movement::NONE, dt);
camera.ProcessKeyboard (kbd[SDL_SCANCODE_S] ? Camera::Movement::BACKWARD : Camera::Movement::NONE, dt);
camera.ProcessKeyboard (kbd[SDL_SCANCODE_A] ? Camera::Movement::LEFT : Camera::Movement::NONE, dt);
camera.ProcessKeyboard (kbd[SDL_SCANCODE_D] ? Camera::Movement::RIGHT : Camera::Movement::NONE, dt);
camera.ProcessKeyboard (kbd[SDL_SCANCODE_LSHIFT] ? Camera::Movement::DOWN : Camera::Movement::NONE, dt);
camera.ProcessKeyboard (kbd[SDL_SCANCODE_SPACE] ? Camera::Movement::UP : Camera::Movement::NONE, dt);
camera.ProcessKeyboard (kbd[SDL_SCANCODE_Q] ? Camera::Movement::CW : Camera::Movement::NONE, dt);
camera.ProcessKeyboard (kbd[SDL_SCANCODE_E] ? Camera::Movement::CCW : Camera::Movement::NONE, dt);
return SDL_FALSE;
}
static int
my_Input_Key (SDL_Event * event)
{
int down;
int quit;
SDL_assert (NULL != event);
down = event->type == SDL_KEYDOWN;
quit = SDL_FALSE;
switch (event->key.keysym.sym)
{
case SDLK_ESCAPE:
quit = SDL_TRUE;
break;
case SDLK_F11:
{
if (down)
{
state.InputCaptureMouse = true;
state.InputFirstMouse = true;
state.InputRelativeMouseMode = true;
common_SDL_ToggleFullscreen (SDL_GetWindowFromID (event->key.windowID));
}
}
break;
case SDLK_r:
{
if (down)
camera = Camera ();
}
break;
case SDLK_c:
{
if (down)
state.RenderShowQuad = !state.RenderShowQuad;
}
break;
default:
{
Buffer_Write_UDP (state.udpsock, state.channel, state.mtu, event, sizeof (SDL_Event));
}
}
return quit;
}
static int
my_SDL_WindowEvent (SDL_Event * event)
{
int quit;
SDL_assert (NULL != event);
quit = SDL_FALSE;
switch (event->window.event)
{
case SDL_WINDOWEVENT_RESIZED:
{
state.Window_Width = event->window.data1;
state.Window_Height = event->window.data2;
glViewport (0, 0, (float) state.Window_Width, (float) state.Window_Height);
}
break;
default:
break;
}
return quit;
}
static void
my_Usage (const char *argv0)
{
fprintf (stderr, "Usage: %s [-h] [-s host] [-p port]\n", argv0);
}
static void
my_GetOpt (int argc, char **argv)
{
int opt;
state.channel = 1;
state.host = "localhost";
state.port = 6666;
while ((opt = getopt (argc, argv, "hp:s:")) != -1)
{
switch (opt)
{
case 'p':
state.port = strtol (optarg, NULL, 0);
break;
case 's':
state.host = optarg;
break;
case 'h':
default:
my_Usage (argv[0]);
exit (EXIT_FAILURE);
break;
}
}
}

73
src/cube.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "cube.h"
Cube::Cube (const GLsizei size)
: Object (size)
{
const float vertices[] = {
// positions // normals // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
glBindVertexArray (VAO);
glBindBuffer (GL_ARRAY_BUFFER, VBO);
glBufferData (GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
glBindVertexArray (VAO);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray (0);
// glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
// glEnableVertexAttribArray (1);
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray (1);
}
void
Cube::Draw (void)
{
glBindVertexArray (VAO);
glDrawArrays (GL_TRIANGLES, 0, 36);
}

104
src/lib_GL_common.cpp Normal file
View File

@ -0,0 +1,104 @@
#include "FileIO.h"
#include "lib_SDL_common.h"
#include "lib_GL_common.h"
#include "glCheckErrors.h"
#include <algorithm>
#include <GL/glew.h>
#include <SDL.h>
#include <SDL_image.h>
void
common_GL_Init (SDL_Window * wind, SDL_GLContext * ctx, int SwapInterval)
{
GLenum err;
SDL_assert (NULL != ctx);
*ctx = SDL_GL_CreateContext (wind);
SDL_assert (NULL != *ctx);
SDL_GL_MakeCurrent (wind, *ctx);
SDL_GL_SetSwapInterval (SwapInterval);
glewExperimental = true;
if ((err = glewInit ()) != GLEW_OK)
{
SDL_Log ("glewInit: %s", glewGetErrorString (err));
exit (EXIT_FAILURE);
}
SDL_assert (err == GLEW_OK);
glCheckErrors ();
}
void
common_GL_TexParameters (const GLenum id, const GLenum wrap_s, const GLenum wrap_t, const GLenum min_filter, const GLenum mag_filter)
{
/* all upcoming GL_TEXTURE_2D operations now have effect on this texture object */
glBindTexture (GL_TEXTURE_2D, id);
/* set the texture wrapping parameters
* set texture wrapping to GL_REPEAT (default wrapping method) */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
/* set texture filtering parameters */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
}
GLenum
common_GL_SurfaceFormat (SDL_Surface * surface)
{
SDL_assert (NULL != surface);
switch (surface->format->BytesPerPixel)
{
case 1: return GL_RED;
case 3: return GL_RGB;
case 4: return GL_RGBA;
}
return GL_RED;
}
GLuint
common_GL_LoadTextureSurface (SDL_Surface* surface)
{
GLenum format;
GLuint texture;
glGenTextures (1, &texture);
if (!texture)
return 0;
if (!SDL_LockSurface (surface))
{
common_GL_TexParameters (texture, GL_REPEAT, GL_REPEAT, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
format = common_GL_SurfaceFormat (surface);
glBindTexture (GL_TEXTURE_2D, texture);
glTexImage2D (GL_TEXTURE_2D, 0, format, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);
glGenerateMipmap (GL_TEXTURE_2D);
SDL_UnlockSurface (surface);
}
else
{
SDL_Log ("SDL_LockSurface: %s", SDL_GetError ());
texture = 0;
}
return texture;
}
GLuint
common_GL_LoadTexturePath (const char *path)
{
GLuint id;
SDL_Surface *surface;
if (NULL != (surface = common_SDL_LoadSurfacePath (path)))
{
id = common_GL_LoadTextureSurface (surface);
SDL_FreeSurface (surface);
}
else
{
SDL_Log ("common_SDL_LoadSurfacePath: error");
id = 0;
}
return id;
}

146
src/lib_SDL_common.cpp Normal file
View File

@ -0,0 +1,146 @@
#include "debug.h"
#include "unused.h"
#include "lib_SDL_common.h"
#include <stdlib.h> /* exit */
#define DEFAULT_WINDOW_TITLE "Unicorn's Horn"
#define DEFAULT_WINDOW_WIDTH 800
#define DEFAULT_WINDOW_HEIGHT 600
static void
my_SDLNet_Init (void)
{
if (SDLNet_Init () == -1)
{
SDL_Log ("SDLNet_Init: %s", SDLNet_GetError ());
exit (EXIT_FAILURE);
}
}
static void
my_IMG_Init (int flags)
{
int initted;
initted = IMG_Init (flags);
if ((initted & flags) != flags)
{
SDL_Log ("IMG_Init: %s\n", IMG_GetError ());
exit (EXIT_FAILURE);
}
SDL_assert ((initted & flags) == flags);
}
static void
my_TTF_Init (void)
{
if (TTF_Init () == -1)
{
SDL_Log ("TTF_Init: %s", TTF_GetError ());
exit (EXIT_FAILURE);
}
SDL_assert (1 == TTF_WasInit ());
}
static void
my_Mix_Init (int flags)
{
int initted;
initted = Mix_Init (flags);
if ((initted & flags) != flags)
{
SDL_Log ("Mix_Init: %s\n", Mix_GetError ());
exit (EXIT_FAILURE);
}
SDL_assert ((initted & flags) == flags);
}
static SDL_AssertState
my_SDL_AssertionHandler(const SDL_AssertData* data, void* userdata)
{
UNUSED (data);
UNUSED (userdata);
return SDL_ASSERTION_ABORT;
}
static void
my_SDL_Assert_Init (void)
{
SDL_SetAssertionHandler(my_SDL_AssertionHandler, NULL);
}
void
common_SDL_Init (void)
{
Uint32 Flags;
Flags = SDL_INIT_EVERYTHING;
if (SDL_Init (Flags) < 0)
{
SDL_Log ("SDL_Init: %s", SDL_GetError ());
exit (EXIT_FAILURE);
}
my_SDLNet_Init ();
my_IMG_Init (IMG_INIT_JPG | IMG_INIT_PNG);
my_TTF_Init ();
my_Mix_Init (MIX_INIT_OGG);
SDL_LogSetPriority (SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
my_SDL_Assert_Init ();
}
void
common_SDL_Quit (void)
{
SDL_SetAssertionHandler (SDL_GetDefaultAssertionHandler (), NULL);
IMG_Quit ();
SDLNet_Quit ();
TTF_Quit ();
SDL_Quit ();
}
void
common_SDL_CreateWindow (SDL_Window ** wind)
{
Uint32 Flags;
SDL_assert (NULL != wind);
Flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL;
*wind = SDL_CreateWindow (DEFAULT_WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT, Flags);
SDL_assert (NULL != *wind);
}
int
common_SDL_ToggleFullscreen (SDL_Window * window)
{
Uint32 Flags = SDL_GetWindowFlags (window);
if (Flags & SDL_WINDOW_FULLSCREEN_DESKTOP)
{
Flags ^= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
else
{
Flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
SDL_SetWindowFullscreen (window, Flags);
return Flags & SDL_WINDOW_FULLSCREEN_DESKTOP;
}
SDL_Surface *
common_SDL_LoadSurfacePath (const std::string& path)
{
SDL_Surface *image;
if (!(image = IMG_Load (path.c_str ())))
{
DEBUG_LOG ("IMG_Load: %s", IMG_GetError ());
exit (EXIT_FAILURE);
}
return image;
}

197
src/lib_lua_common.cpp Normal file
View File

@ -0,0 +1,197 @@
#include "lib_lua_common.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int l_map (lua_State*);
static int l_split (lua_State*);
static void call_va (lua_State*, const char*, const char*, ...);
static void error (lua_State*, const char*, ...);
int
common_lua_run (lua_State* L, const char* name, const char* buff, const size_t buff_len)
{
int error;
error = luaL_loadbuffer (L, buff, buff_len, name) || lua_pcall (L, 0, 0, 0);
if (error)
{
fprintf (stderr, "%s\n", lua_tostring (L, -1));
lua_pop (L, 1); /* pop error message from the stack */
}
// common_lua_stack_dump (L);
return error;
}
void
common_lua_stack_dump (lua_State* L)
{
int i, t, top;
top = lua_gettop (L);
for (i = 1; i <= top; i++)
{ /* repeat for each level */
t = lua_type (L, i);
switch (t)
{
case LUA_TSTRING: /* strings */
printf ("`%s'", lua_tostring (L, i));
break;
case LUA_TBOOLEAN: /* booleans */
printf (lua_toboolean (L, i) ? "true" : "false");
break;
case LUA_TNUMBER: /* numbers */
printf ("%g", lua_tonumber (L, i));
break;
default: /* other values */
printf ("%s", lua_typename (L, t));
break;
}
printf (" "); /* put a separator */
}
printf ("\n"); /* end the listing */
}
static void
error (lua_State* L, const char* fmt, ...)
{
va_list argp;
va_start (argp, fmt);
vfprintf (stderr, fmt, argp);
va_end (argp);
lua_close (L);
exit (EXIT_FAILURE);
}
static void
load (const char* filename, int* width, int* height)
{
lua_State* L = luaL_newstate ();
luaL_openlibs (L);
if (luaL_loadfile (L, filename) || lua_pcall (L, 0, 0, 0))
error (L, "cannot run configuration file: %s", lua_tostring (L, -1));
lua_getglobal (L, "width");
lua_getglobal (L, "height");
if (!lua_isnumber (L, -2))
error (L, "`width' should be a number\n");
if (!lua_isnumber (L, -1))
error (L, "`height' should be a number\n");
*width = (int) lua_tonumber (L, -2);
*height = (int) lua_tonumber (L, -1);
lua_close (L);
}
static void
call_va (lua_State* L, const char* func, const char* sig, ...)
{
va_list vl;
int narg, nres; /* number of arguments and results */
va_start (vl, sig);
lua_getglobal (L, func); /* get function */
/* push arguments */
narg = 0;
while (*sig)
{ /* push arguments */
switch (*sig++)
{
case 'd': /* double argument */
lua_pushnumber (L, va_arg (vl, double));
break;
case 'i': /* int argument */
lua_pushnumber (L, va_arg (vl, int));
break;
case 's': /* string argument */
lua_pushstring (L, va_arg (vl, char *));
break;
case '>':
goto endwhile;
default:
error (L, "invalid option (%c)", *(sig - 1));
}
narg++;
luaL_checkstack (L, 1, "too many arguments");
}
endwhile:
/* do the call */
nres = strlen (sig); /* number of expected results */
/* do the call */
if (lua_pcall (L, narg, nres, 0) != 0)
error (L, "error running function `%s': %s", func, lua_tostring (L, -1));
/* retrieve results */
nres = -nres; /* stack index of first result */
while (*sig)
{ /* get results */
switch (*sig++)
{
case 'd': /* double result */
if (!lua_isnumber (L, nres))
error (L, "wrong result type");
*va_arg (vl, double *) = lua_tonumber (L, nres);
break;
case 'i': /* int result */
if (!lua_isnumber (L, nres))
error (L, "wrong result type");
*va_arg (vl, int *) = (int) lua_tonumber (L, nres);
break;
case 's': /* string result */
if (!lua_isstring (L, nres))
error (L, "wrong result type");
*va_arg (vl, const char **) = lua_tostring (L, nres);
break;
default:
error (L, "invalid option (%c)", *(sig - 1));
}
nres++;
}
va_end (vl);
}
static int
l_map (lua_State * L)
{
int i, n;
/* 1st argument must be a table (t) */
luaL_checktype (L, 1, LUA_TTABLE);
/* 2nd argument must be a function (f) */
luaL_checktype (L, 2, LUA_TFUNCTION);
n = luaL_len (L, 1); /* get size of table */
for (i = 1; i <= n; i++)
{
lua_pushvalue (L, 2); /* push f */
lua_rawgeti (L, 1, i); /* push t[i] */
lua_call (L, 1, 1); /* call f(t[i]) */
lua_rawseti (L, 1, i); /* t[i] = result */
}
return 0; /* no results */
}
static int
l_split (lua_State* L)
{
int i;
const char* s;
const char* e;
const char* sep;
i = 1;
s = luaL_checkstring (L, 1);
sep = luaL_checkstring (L, 2);
lua_newtable (L); /* result */
/* repeat for each separator */
while ((e = strchr (s, *sep)) != NULL)
{
/* push substring */
lua_pushlstring (L, s, e - s);
lua_rawseti (L, -2, i++);
s = e + 1; /* skip separator */
}
/* push last substring */
lua_pushstring (L, s);
lua_rawseti (L, -2, i);
return 1; /* return the table */
}

24
src/object.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "object.h"
Object::Object (const GLsizei size)
: mGLsizei (size)
{
if (mGLsizei > 0)
{
glGenVertexArrays (mGLsizei, &VAO);
glGenBuffers (mGLsizei, &VBO);
glGenBuffers (mGLsizei, &EBO);
}
}
Object::~Object (void)
{
if (mGLsizei > 0)
{
glDeleteVertexArrays (mGLsizei, &VAO);
glDeleteBuffers (mGLsizei, &VBO);
glDeleteBuffers (mGLsizei, &EBO);
mGLsizei = 0;
}
}

48
src/quad.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "quad.h"
Quad::Quad (const GLsizei size)
: Object (size)
{
const unsigned int indices[] =
{
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
const float vertices[] =
{
// positions // texture coords
// top right
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
// bottom right
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
// bottom left
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
// top left
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
glBindVertexArray (VAO);
glBindBuffer (GL_ARRAY_BUFFER, VBO);
glBufferData (GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof indices, indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof (float), (void *) 0);
glEnableVertexAttribArray (0);
// texture coord attribute
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof (float), (void *) (3 * sizeof (float)));
glEnableVertexAttribArray (1);
}
void
Quad::Draw (void)
{
glBindVertexArray (VAO);
glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

245
src/server_main.cpp Normal file
View File

@ -0,0 +1,245 @@
#include "debug.h"
#include "lib_SDL_common.h" /* SDL* */
#include "Server.h"
#include "signal_common.h"
#include "unused.h"
#include "events_common.h"
#include "trim.h"
#include "lib_lua_common.h"
#include <vector>
#include <stdlib.h> /* exit */
#include <unistd.h> /* getopt */
#include <getopt.h> /* getopt */
#include <arpa/inet.h> /* inet_ntop */
static bool my_SDL_UserEvent (SDL_Event *);
static void my_Usage (const char *);
static void my_GetOpt (int, char **);
static void my_ProcessPacket (UDPpacket *);
static const char* host = NULL;
static Uint16 port = 6666;
int
main (int argc, char **argv)
{
bool done;
SDL_Event ev;
Server server;
my_GetOpt (argc, argv);
common_Signal_Init ();
common_SDL_Init ();
server = Server (host, port);
server.Start ();
done = false;
while (!done)
{
SDL_Delay (1);
while (!done && SDL_PollEvent (&ev))
{
switch (ev.type)
{
case SDL_QUIT:
done = true;
break;
case SDL_USEREVENT:
{
done = my_SDL_UserEvent (&ev);
}
break;
default:
break;
}
}
}
server.UDP_CloseAll ();
server.Stop ();
common_SDL_Quit ();
return 0;
}
static bool
my_SDL_UserEvent (SDL_Event * ev)
{
SDL_assert (NULL != ev);
switch (ev->user.type)
{
case PACKET_SDL_EVENT:
{
UDPpacket *packet = (UDPpacket *) ev->user.data1;
my_ProcessPacket (packet);
SDLNet_FreePacket (packet);
}
break;
default:
break;
}
return false;
}
/* XXX gross */
static std::vector<char> server_data;
static bool left_shift = false;
/* XXX gross */
static void
my_ProcessPacket (UDPpacket* packet)
{
char c;
size_t len;
char hoststring[128];
SDL_Event event;
if (!packet)
return;
SDL_assert (NULL != packet);
if (!packet->len)
return;
SDL_assert (packet->len > 0);
len = packet->len;
SDL_memcpy (&event, packet->data, len);
if ((event.type != SDL_KEYDOWN) && (event.type != SDL_KEYUP))
{
return;
}
if (event.key.keysym.scancode != SDL_GetScancodeFromKey (event.key.keysym.sym))
{
DEBUG_LOG ("Physical %s key acting as %s key", SDL_GetScancodeName (event.key.keysym.scancode), SDL_GetKeyName (event.key.keysym.sym));
}
std::string str = std::string (SDL_GetKeyName (event.key.keysym.sym));
bool down = (event.type == SDL_KEYDOWN);
inet_ntop (AF_INET, &packet->address.host, hoststring, 128);
DEBUG_LOG ("%d bytes from %s:%d:\n%s", packet->len, hoststring, ntohs (packet->address.port), str.c_str ());
// SDL_Log ("%d \"%s\"", str.length(), str.c_str ());
/* XXX ultra gross */
if (down) {
if (str.length () > 1)
{
if (str == "Return")
{
server_data.push_back ('\0');
lua_State* L = luaL_newstate ();
luaL_openlibs (L);
std::string buf = std::string ((const char*)server_data.data ());
printf ("\n => ");
fflush (stdout);
common_lua_run (L, "line", buf.c_str (), buf.length ());
fflush (stdout);
lua_close (L);
server_data.clear ();
}
else if (str == "Left Shift")
{
left_shift = (bool) true;
}
else if (str == "Space")
{
server_data.push_back (' ');
putchar (' ');
fflush (stdout);
}
else if (str == "Backspace")
{
off_t size = server_data.size () - 1;
if (size < 0)
size = 0;
server_data.resize (size);
printf ("\x08\e[0K");
fflush(stdout);
}
}
else
{
c = tolower (str[0]);
if (isalpha (c))
{
if (left_shift)
c = toupper (c);
}
else if (isdigit (c))
{
const char* sym = ")!@#$%^&*(";
if (left_shift)
c = sym[c - '0'];
}
else
{
if (left_shift)
{
switch (c)
{
case '\'': c = '"'; break;
case ',': c = '<'; break;
case '-': c = '_'; break;
case '.': c = '>'; break;
case '/': c = '?'; break;
case ';': c = ':'; break;
case '=': c = '+'; break;
case '[': c = '{'; break;
case '\\': c = '|'; break;
case ']': c = '}'; break;
case '`': c = '~'; break;
default: break;
}
}
}
server_data.push_back (c);
putchar (c);
fflush (stdout);
}
}
else
{
if (str == "Left Shift")
{
left_shift = (bool) false;
}
}
}
static void
my_Usage (const char *argv0)
{
fprintf (stderr, "Usage: %s [-h] [-s server] [-p port]\n", argv0);
}
static void
my_GetOpt (int argc, char **argv)
{
int opt;
while ((opt = getopt (argc, argv, "hp:s:")) != -1)
{
switch (opt)
{
case 'p':
port = strtol (optarg, NULL, 0);
break;
case 's':
host = optarg;
break;
case 'h':
default:
my_Usage (argv[0]);
exit (EXIT_FAILURE);
break;
}
}
}

258
src/shader.cpp Normal file
View File

@ -0,0 +1,258 @@
#include "debug.h"
#include "shader.h"
#include "FileIO.h"
#include "lib_GL_common.h"
#include <SDL_assert.h>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#define DEFAULT_FRAGMENT_HEADER "./glsl/header.f.glsl"
ShaderProgram::ShaderProgram (void)
{
}
ShaderProgram::ShaderProgram (const std::string& vertexPath, const std::string& geometryPath, const std::string& fragmentPath)
{
GLuint vertex, geometry, fragment;
ID = glCreateProgram ();
if (ID)
{
vertex = CompileShaderPath (vertexPath, GL_VERTEX_SHADER);
geometry = 0;
if (!geometryPath.empty ())
geometry = CompileShaderPath (geometryPath, GL_GEOMETRY_SHADER);
FileIO f1 (DEFAULT_FRAGMENT_HEADER, "r");
FileIO f2 (fragmentPath, "r");
std::string buf = f1.ReadToString () + "\n" + f2.ReadToString ();
fragment = CompileShaderBuffer (buf.c_str (), GL_FRAGMENT_SHADER);
if (vertex)
glAttachShader (ID, vertex);
if (geometry)
glAttachShader (ID, geometry);
if (fragment)
glAttachShader (ID, fragment);
glLinkProgram (ID);
if (!my_checkCompileSuccess (ID, GL_PROGRAM))
{
throw "glLinkProgram error";
ID = 0;
}
glDeleteShader (vertex);
glDeleteShader (geometry);
glDeleteShader (fragment);
RefreshUniformLocations ();
}
else
{
ID = 0;
throw "ShaderProgram error";
}
}
void
ShaderProgram::Use (void)
{
glUseProgram (ID);
}
GLint ShaderProgram::getCachedLoc (const std::string& name)
{
if (mUniformLocationsNeedRefresh)
RefreshUniformLocations ();
auto const& ref = UniformLocationCache.find (name);
if (ref == UniformLocationCache.end ())
{
/* It didn't exist */
int loc = glGetUniformLocation (ID, name.c_str ());
if (loc == -1)
{
}
UniformLocationCache[name] = loc;
}
return UniformLocationCache[name];
}
void
ShaderProgram::RefreshUniformLocations (void)
{
for (auto& itm : UniformLocationCache)
{
itm.second = glGetUniformLocation (ID, itm.first.c_str ());
if (itm.second == -1)
UniformLocationCache.erase (itm.first);
}
mUniformLocationsNeedRefresh = false;
}
void
ShaderProgram::Bool (const std::string& name, const bool&value)
{
glUniform1i (getCachedLoc (name), (int) value);
}
void
ShaderProgram::Float (const std::string& name, const float&value)
{
glUniform1f (getCachedLoc (name), (float) value);
}
void
ShaderProgram::Int (const std::string& name, const int&value)
{
glUniform1i (getCachedLoc (name), (int) value);
}
void
ShaderProgram::Vec2 (const std::string& name, const glm::vec2& value)
{
glUniform2fv (getCachedLoc (name), 1, glm::value_ptr (value));
}
void
ShaderProgram::Vec3 (const std::string& name, const glm::vec3& value)
{
glUniform3fv (getCachedLoc (name), 1, glm::value_ptr (value));
}
void
ShaderProgram::Vec4 (const std::string& name, const glm::vec4& value)
{
glUniform4fv (getCachedLoc (name), 1, glm::value_ptr (value));
}
void
ShaderProgram::Mat2 (const std::string& name, const glm::mat2& value)
{
glUniformMatrix2fv (getCachedLoc (name), 1, GL_FALSE, glm::value_ptr (value));
}
void
ShaderProgram::Mat3 (const std::string& name, const glm::mat3& value)
{
glUniformMatrix3fv (getCachedLoc (name), 1, GL_FALSE, glm::value_ptr (value));
}
void
ShaderProgram::Mat4 (const std::string& name, const glm::mat4& value)
{
glUniformMatrix4fv (getCachedLoc (name), 1, GL_FALSE, glm::value_ptr (value));
}
GLuint ShaderProgram::CompileShaderPath (const std::string& path, const GLenum type)
{
FileIO f (path, "r");
std::string buf = f.ReadToString ();
if (buf.empty ())
return 0;
return CompileShaderBuffer (buf.c_str (), type);
}
GLuint ShaderProgram::CompileShaderBuffer (const std::string& buf, const GLenum type)
{
GLuint id;
if (buf.empty ())
return 0;
id = glCreateShader (type);
if (id)
{
SDL_assert (0 != id);
const char* code = buf.c_str ();
glShaderSource (id, 1, &code, NULL);
glCompileShader (id);
if (!my_checkCompileSuccess (id, type))
{
DEBUG_LOG ("CompileShaderBuffer error");
id = 0;
}
}
return id;
}
GLint
ShaderProgram::my_checkCompileSuccess (const GLuint id, const GLenum type)
{
GLint infoLogLength, success;
std::string infoLog;
std::string typeName = "UNKNOWN";
infoLogLength = 0;
success = GL_FALSE;
switch (type)
{
case GL_VERTEX_SHADER:
typeName = "GL_VERTEX_SHADER";
goto HANDLE_SHADER;
case GL_GEOMETRY_SHADER:
typeName = "GL_GEOMETRY_SHADER";
goto HANDLE_SHADER;
case GL_FRAGMENT_SHADER:
typeName = "GL_FRAGMENT_SHADER";
HANDLE_SHADER:
glGetShaderiv (id, GL_COMPILE_STATUS,&success);
if (GL_FALSE == success)
glGetShaderiv (id, GL_INFO_LOG_LENGTH,&infoLogLength);
break;
case GL_PROGRAM:
typeName = "PROGRAM";
glGetProgramiv (id, GL_LINK_STATUS,&success);
if (GL_FALSE == success)
glGetProgramiv (id, GL_INFO_LOG_LENGTH,&success);
break;
default:
break;
}
if (!infoLogLength)
{
return success;
}
infoLog.reserve (infoLogLength);
switch (type)
{
case GL_VERTEX_SHADER:
case GL_GEOMETRY_SHADER:
case GL_FRAGMENT_SHADER:
glGetShaderInfoLog (id, infoLogLength, NULL, &infoLog.front ());
break;
case GL_PROGRAM:
glGetProgramInfoLog (id, infoLogLength, NULL, &infoLog.front ());
break;
default:
break;
}
if (infoLog[0] != '\0')
{
DEBUG_LOG ("%8s ERROR ============================================================\n%s", typeName.c_str (), infoLog.c_str ());
}
return success;
}

63
src/signal_common.cpp Normal file
View File

@ -0,0 +1,63 @@
#define _POSIX_C_SOURCE
#include "signal_common.h" /* conflict with signal.h probably */
#include "unused.h"
#include <stdio.h> /* fputs */
#include <signal.h> /* struct sigaction */
#include <stdlib.h> /* exit */
#include <SDL.h>
/* TODO longjmp to cleanup handler */
/* #include <setjmp.h> */
/* sigjmp_buf env; */
static void
my_Signal_Handler (int sig, siginfo_t* si, void* uap)
{
SDL_Event QUIT_EVENT = {SDL_QUIT};
UNUSED (sig);
UNUSED (uap);
UNUSED (si);
SDL_PushEvent (&QUIT_EVENT);
exit (EXIT_FAILURE);
/* siglongjmp (env, sig); */
}
void
common_Signal_Init (void)
{
struct sigaction sa;
sa.sa_sigaction = my_Signal_Handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (SIGINT, &sa, NULL) == -1)
{
fputs ("Failed to setup SIGINT handler\n", stderr);
}
if (sigaction (SIGTERM, &sa, NULL) == -1)
{
fputs ("Failed to setup SIGTERM handler\n", stderr);
}
if (sigaction (SIGILL, &sa, NULL) == -1)
{
fputs ("Failed to setup SIGILL handler\n", stderr);
}
if (sigaction (SIGBUS, &sa, NULL) == -1)
{
fputs ("Failed to setup SIGBUS handler\n", stderr);
}
if (sigaction (SIGSEGV, &sa, NULL) == -1)
{
fputs ("Failed to setup SIGSEGV handler\n", stderr);
}
if (sigaction (SIGABRT, &sa, NULL) == -1)
{
fputs ("Failed to setup SIGABRT handler\n", stderr);
}
}

4
test/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
test_FileIO
test_File_Write_UDP
test_lua
test_Object

77
test/test_FileIO.cpp Normal file
View File

@ -0,0 +1,77 @@
#include "FileIO.h"
#include <stdint.h> /* uint8_t */
#include <stdio.h>
#include <math.h>
#include <errno.h> /* errno */
#include <string.h> /* strerror */
static int
IsProbablyAscii (const void *buf, const size_t len)
{
const uint8_t *bufPtr;
const uint8_t *bufPtrEnd;
size_t nAsciiCount;
nAsciiCount = 0;
bufPtr = (const uint8_t *) buf;
bufPtrEnd = bufPtr + len;
while (bufPtr < bufPtrEnd && (NULL != bufPtr) && (*bufPtr != '\0'))
{
nAsciiCount += (*bufPtr >= ' ') && (*bufPtr <= '~');
bufPtr++;
}
return (int) round ((double) nAsciiCount / (double) len);
}
static void
HexDump (const void *buf, const size_t len)
{
const uint8_t *bufPtr;
const uint8_t *bufPtrEnd;
const size_t width = 16;
size_t nout;
nout = 0;
bufPtr = (const uint8_t *) buf;
bufPtrEnd = bufPtr + len;
while (bufPtr < bufPtrEnd && (NULL != bufPtr))
{
if (nout == width)
{
printf ("\n");
nout = 0;
}
printf ("%02x ", *bufPtr);
bufPtr++;
nout++;
}
puts ("");
}
int
main (int argc, char **argv)
{
int rc;
rc = 1;
try
{
while (argc-- > 1)
{
FileIO f (argv[argc], "r");
std::string buf = f.ReadToString ();
if (IsProbablyAscii (buf.c_str (), buf.size ()))
printf ("%s", buf.c_str ());
else
HexDump (buf.c_str (), buf.size ());
rc = 0;
}
}
catch (int err)
{
puts (strerror (errno));
}
return rc;
}

View File

@ -0,0 +1,89 @@
#include "FileIO.h"
#include "UDP_Write.h"
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <SDL_net.h>
static void usage (const char* argv0)
{
fprintf (stderr, "Usage: %s [-f path] [-h] [-p port] [-s server]\n", argv0);
}
int
main (int argc, char** argv)
{
int opt;
int numsent;
int mtu;
int channel;
const char* path;
const char* server;
Uint16 port;
path = NULL;
server = "localhost";
port = 6666;
channel = 1;
mtu = 1450;
numsent = 0;
while ((opt = getopt (argc, argv, "hs:p:f:")) != -1)
{
switch (opt)
{
case 'h':
usage (argv[0]);
exit (EXIT_FAILURE);
break;
case 's':
server = optarg;
if (!strcmp (server, "NULL"))
server = NULL;
break;
case 'p':
port = strtol (optarg, NULL, 0);
break;
case 'f':
path = optarg;
break;
default:
break;
}
}
#if 0
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
#endif
if ((optind < argc) && (argv[optind][0] == '-'))
{
const size_t size = 8192;
std::vector<char> buf (size);
std::fill (buf.begin(), buf.end(), 0);
size_t nread = fread (buf.data (), sizeof (char), size - 1, stdin);
numsent = SendBuffer_UDP (server, port, channel, mtu, buf.data (), nread);
}
else
{
if (path)
{
numsent = SendFile_UDP (server, port, channel, mtu, path);
}
}
SDL_Log ("%d", numsent);
return 0;
}

70
test/test_Object.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "lib_SDL_common.h"
#include "lib_GL_common.h"
#include "object.h"
#include "cube.h"
#include "quad.h"
#include <SDL.h>
int main(void)
{
int Window_Height;
int Window_Width;
SDL_GLContext GLContext;
SDL_Window *Window;
common_SDL_Init ();
common_SDL_CreateWindow (&Window);
common_GL_Init (Window, &GLContext, 1);
SDL_GetWindowSize (Window, &Window_Width, &Window_Height);
try {
SDL_Log ("Object o;");
Object o;
SDL_Log ("Cube c;");
Cube c;
SDL_Log ("Quad q;");
Quad q;
}
catch (int e)
{
printf ("%d\n", e);
}
try {
SDL_Log ("Object (1);");
Object o = Object (1);
SDL_Log ("Cube (1);");
Cube c = Cube (1);
SDL_Log ("Quad (1);");
Quad q = Quad (1);
}
catch (int e)
{
printf ("%d\n", e);
}
try {
SDL_Log ("Object o;");
Object o;
SDL_Log ("Cube c;");
Cube c;
SDL_Log ("Quad q;");
Quad q;
SDL_Log ("Object (1);");
o = Object (1);
SDL_Log ("Cube (1);");
c = Cube (1);
SDL_Log ("Quad (1);");
q = Quad (1);
}
catch (int e)
{
printf ("%d\n", e);
}
SDL_GL_DeleteContext (GLContext);
SDL_DestroyWindow (Window);
common_SDL_Quit ();
}

24
test/test_lua.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "lib_lua_common.h"
#include <string.h>
int main(int argc, char** argv)
{
char buf[8192];
lua_State* L;
L = luaL_newstate ();
luaL_openlibs (L);
while (fgets (buf, 8191, stdin))
{
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = 0;
if (strlen (buf) > 0)
{
printf (" => ");
fflush (stdout);
common_lua_run (L, "line", buf, strlen (buf));
}
}
lua_close (L);
return 0;
}