Initial commit

This commit is contained in:
John Alanbrook 2021-12-01 03:29:18 +00:00
parent 7fb0a74b7e
commit 3dcaf6df81
72 changed files with 16530 additions and 0 deletions

126
Makefile Normal file
View file

@ -0,0 +1,126 @@
MAKEFLAGS := --jobs=$(shell nproc)
TARGET := game
INFO :=
EDITOR := 1
DEBUG := 1
UNAME := $(shell uname)
ifeq ($(OS),Windows_NT)
UNAME := Windows_NT
endif
UNAME_P := $(shell uname -m)
#CC specifies which compiler we're using
CC = clang -x c --std=c99
CXX = clang++
DEFFLAGS :=
ifeq ($(EDITOR), 1)
DEFFLAGS += -DEDITOR
TARGET = editor
endif
ifeq ($(DEBUG), 1)
DEFFALGS += -DDEBUG
INFO = dbg
endif
BINDIR := ./bin
BUILDDIR := ./obj
THIRDPARTY_DIR := ./source/thirdparty
THIRDPARTY_DIRS := ${sort ${dir ${wildcard ${THIRDPARTY_DIR}/*/}}}
THIRDPARTY_I := $(addsuffix include, ${THIRDPARTY_DIRS}) $(addsuffix src, $(THIRDPARTY_DIRS)) $(THIRDPARTY_DIRS) $(addsuffix build/include, $(THIRDPARTY_DIRS)) $(addsuffix include/chipmunk, $(THIRDPARTY_DIRS))
THIRDPARTY_L := $(addsuffix build/lib, $(THIRDPARTY_DIRS)) $(addsuffix build, ${THIRDPARTY_DIRS}) $(addsuffix build/bin, $(THIRDPARTY_DIRS) $(addsuffix build/src, $(THIRDPARTY_DIRS)))
# imgui sources
IMGUI_DIR := ${THIRDPARTY_DIR}/imgui
imgui = $(addprefix ${IMGUI_DIR}/, imgui imgui_draw imgui_widgets imgui_tables)
imguibackends = $(addprefix ${IMGUI_DIR}/backends/, imgui_impl_sdl imgui_impl_opengl3)
imguiobjs := $(addsuffix .cpp, $(imgui) $(imguibackends))
plmpeg_objs := ${THIRDPARTY_DIR}/pl_mpeg/pl_mpeg_extract_frames.c
cpobjs := $(wildcard ${THIRDPARTY_DIR}/Chipmunk2D/src/*.c)
s7objs := ${THIRDPARTY_DIR}/s7/s7.c
includeflag := $(addprefix -I, $(THIRDPARTY_I) ./source/engine ./source/editor $(IMGUI_DIR) $(IMGUI_DIR)/backends)
#LIBRARY_PATHS specifies the additional library paths we'll need
LIB_PATHS := $(addprefix -L, $(THIRDPARTY_L))
# Engine sources
sources := $(wildcard ./source/engine/*.cpp ./source/engine/*.c ./source/editor/*.c ./source/editor/*.cpp) $(imguiobjs) $(s7objs) $(cpobjs)
#COMPILER_FLAGS specifies the additional compilation options we're using
WARNING_FLAGS := -w #-pedantic -Wall -Wextra -Wwrite-strings
COMPILER_FLAGS := -g -O0 $(WARNING_FLAGS)
ifeq ($(UNAME), Windows_NT)
LINKER_FLAGS:= -static
# DYNAMIC LIBS: SDL2 opengl32
ELIBS := glew32 mingw32 SDL2main SDL2 m dinput8 dxguid dxerr8 user32 gdi32 winmm imm32 ole32 oleaut32 shell32 version uuid setupapi opengl32 stdc++ winpthread
CLIBS :=
EXT := .exe
else
LINKER_FLAGS :=
ELIBS :=
CLIBS := SDL2 GLEW GL dl pthread
EXT :=
endif
LELIBS := -Wl,-Bstatic $(addprefix -l, ${ELIBS}) -Wl,-Bdynamic $(addprefix -l, $(CLIBS))
BUILDD = -DGLEW_STATIC
dir_guard = @mkdir -p $(@D)
objprefix = ./obj/$(UNAME)/$(UNAME_P)/$(TARGET)$(INFO)
objects := $(patsubst .%.cpp, $(objprefix)%.o, $(filter %.cpp, $(sources))) $(patsubst .%.c, $(objprefix)%.o, $(filter %.c, $(sources)))
objects := $(sort $(objects))
depends := $(patsubst %.o, %.d, $(objects))
FILENAME = $(TARGET)$(INFO)_$(UNAME_P)$(EXT)
all: install
$(TARGET): $(objects)
@echo Linking $(TARGET)
@$(CXX) $^ -DGLEW_STATIC $(LINKER_FLAGS) $(LIB_PATHS) $(LELIBS) -o $@
install: $(TARGET)
mkdir -p bin/$(UNAME) && cp $(TARGET) bin/$(UNAME)/$(FILENAME)
cp $(TARGET) yugine/$(FILENAME)
rm $(TARGET)
-include $(depends)
$(objprefix)/%.o:%.cpp
$(dir_guard)
@echo Making C++ object $(notdir $@)
-@$(CXX) $(BUILDD) $(DEFFLAGS) $(includeflag) $(COMPILER_FLAGS) -MD -c $< -o $@
$(objprefix)/%.o:%.c
$(dir_guard)
@echo Making C object $(notdir $@)
-@$(CC) $(BUILDD) $(DEFFLAGS) $(includeflag) $(COMPILER_FLAGS) -MD -c $< -o $@
clean:
@echo Cleaning project
@rm -f $(objects) $(depends)
bsclean:
rm -f $(bsobjects)
gameclean:
rm -f $(gameobjects)
TAGS: $(sources) $(edsources)
@echo Generating TAGS file
@ctags -eR $^

8
source/editor/debug.c Normal file
View file

@ -0,0 +1,8 @@
#include "debug.h"
unsigned long long triCount = 0;
void resetTriangles()
{
triCount = 0;
}

9
source/editor/debug.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef DEBUG_GUI_H
#define DEBUG_GUI_H
extern unsigned long long triCount;
void resetTriangles();
#endif

154
source/editor/debugdraw.c Normal file
View file

@ -0,0 +1,154 @@
#include "debugdraw.h"
#include "openglrender.h"
#include "shader.h"
static uint32_t circleVBO;
static uint32_t circleVAO;
static struct mShader *circleShader;
static uint32_t gridVBO;
static uint32_t gridVAO;
static struct mShader *gridShader;
static uint32_t rectVBO;
static uint32_t rectVAO;
static struct mShader *rectShader;
void debugdraw_init()
{
circleShader = MakeShader("circlevert.glsl", "circlefrag.glsl");
shader_setUBO(circleShader, "Projection", 0);
glGenBuffers(1, &circleVBO);
glGenVertexArrays(1, &circleVAO);
float gridverts[] = {
-1.f, -1.f,
1.f, -1.f,
-1.f, 1.f,
1.f, 1.f
};
gridShader = MakeShader("gridvert.glsl", "gridfrag.glsl");
shader_setUBO(gridShader, "Projection", 0);
glGenBuffers(1, &gridVBO);
glGenVertexArrays(1, &gridVAO);
glBindVertexArray(gridVAO);
glBindBuffer(GL_ARRAY_BUFFER, gridVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(gridverts), &gridverts,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
rectShader = MakeShader("linevert.glsl", "linefrag.glsl");
shader_setUBO(rectShader, "Projection", 0);
glGenBuffers(1, &rectVBO);
glGenVertexArrays(1, &rectVAO);
}
void draw_line(int x1, int y1, int x2, int y2)
{
shader_use(rectShader);
float verts[] = {
x1, y1,
x2, y2
};
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_DYNAMIC_DRAW);
glBindVertexArray(rectVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_LINE_STRIP, 0, 2);
}
void draw_edge(float *points, int n)
{
shader_use(rectShader);
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * n * 2, points,
GL_DYNAMIC_DRAW);
glBindVertexArray(rectVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_LINE_STRIP, 0, n);
}
void draw_circle(int x, int y, float radius, int pixels)
{
shader_use(circleShader);
float verts[] = {
x - radius, y - radius, -1.f, -1.f,
x + radius, y - radius, 1.f, -1.f,
x - radius, y + radius, -1.f, 1.f,
x + radius, y + radius, 1.f, 1.f
};
glBindBuffer(GL_ARRAY_BUFFER, circleVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_DYNAMIC_DRAW);
shader_setfloat(circleShader, "radius", radius);
shader_setint(circleShader, "thickness", pixels);
glBindVertexArray(circleVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void draw_rect(int x, int y, int w, int h)
{
float hw = w / 2.f;
float hh = h / 2.f;
float verts[] = {
x - hw, y - hh,
x + hw, y - hh,
x + hw, y + hh,
x - hw, y + hh
};
shader_use(rectShader);
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_DYNAMIC_DRAW);
glBindVertexArray(rectVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_LINE_LOOP, 0, 4);
}
void draw_grid(int width, int span)
{
shader_use(gridShader);
shader_setint(gridShader, "thickness", width);
shader_setint(gridShader, "span", span);
glBindVertexArray(gridVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void draw_point(int x, int y, float r)
{
draw_circle(x, y, r, r);
}
void draw_poly(float *points, int n)
{
shader_use(rectShader);
glBindBuffer(GL_ARRAY_BUFFER, rectVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * n * 2, points,
GL_DYNAMIC_DRAW);
glBindVertexArray(rectVAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays(GL_LINE_LOOP, 0, n);
}
void debugdraw_flush()
{
}

16
source/editor/debugdraw.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef DEBUGDRAW_H
#define DEBUGDRAW_H
void debugdraw_init();
void draw_line(int x1, int y1, int x2, int y2);
void draw_edge(float *points, int n);
void draw_circle(int x, int y, float radius, int pixels);
void draw_grid(int width, int span);
void draw_rect(int x, int y, int w, int h);
void draw_point(int x, int y, float r);
void draw_poly(float *points, int n);
void debugdraw_flush(); /* This is called once per frame to draw all queued elements */
#endif

1432
source/editor/editor.cpp Normal file

File diff suppressed because it is too large Load diff

98
source/editor/editor.h Normal file
View file

@ -0,0 +1,98 @@
#ifndef EDITOR_H
#define EDITOR_H
#include "config.h"
#include <SDL.h>
#include <stdbool.h>
#include "resources.h"
struct mCamera;
#define ASSET_TYPE_NULL 0
#define ASSET_TYPE_IMAGE 1
#define ASSET_TYPE_TEXT 2
struct fileasset {
char *filename;
short extension_len;
short filename_len;
bool searched;
short type;
void *data;
};
struct editorVars {
bool showStats;
bool showHierarchy;
bool showLighting;
bool showGameSettings;
bool showViewmode;
bool showDebugMenu;
bool showAssetMenu;
bool showREPL;
bool showExport;
bool showLevel;
};
struct gameproject {
char name[127];
char path[MAXPATH];
};
struct Texture;
void pickGameObject(int pickID);
int is_allowed_extension(const char *ext);
void editor_init(struct mSDLWindow *mwindow);
void editor_input(SDL_Event * e);
void editor_render();
int editor_wantkeyboard();
void editor_save();
void editor_makenewobject();
void editor_project_gui();
void editor_init_project(struct gameproject *gp);
void editor_save_projects();
void editor_load_projects();
void editor_proj_select_gui();
void editor_import_project(char *path);
void editor_make_project(char *path);
void editor_selectasset(struct fileasset *asset);
void editor_selectasset_str(char *path);
void editor_asset_gui(struct fileasset *asset);
void editor_asset_tex_gui(struct Texture *tex);
void editor_asset_text_gui(char *text);
void editor_level_btn(char *level);
void editor_prefab_btn(char *prefab);
void game_start();
void game_resume();
void game_stop();
void game_pause();
void get_levels();
///////// Object GUIs
void light_gui(struct mLight *light);
void pointlight_gui(struct mPointLight *light);
void spotlight_gui(struct mSpotLight *spot);
void staticactor_gui(struct mStaticActor *sa);
void trans_drawgui(struct mTransform *T);
void object_gui(struct mGameObject *go);
void sprite_gui(struct mSprite *sprite);
void circle_gui(struct phys2d_circle *circle);
void segment_gui(struct phys2d_segment *seg);
void box_gui(struct phys2d_box *box);
void poly_gui(struct phys2d_poly *poly);
void edge_gui(struct phys2d_edge *edge);
void shape_gui(struct phys2d_shape *shape);
void pinball_flipper_gui(struct flipper *flip);
int obj_gui_hierarchy(struct mGameObject *selected);
#endif

View file

@ -0,0 +1,19 @@
#include "editorstate.h"
#include <stdio.h>
/*
void (*asset_command)(char *asset) = print_file;
void print_file(char *file)
{
printf("File path: %s\n", file);
}
void set_new_model(char *modelPath)
{
printf("Loading new model: %s\n", modelPath);
curActor->model = GetExistingModel(modelPath);
strcpy(curActor->currentModelPath, modelPath);
}
*/

View file

@ -0,0 +1,10 @@
#ifndef EDITORSTATE_H
#define EDITORSTATE_H
void set_new_model(char *modelPath);
extern void (*asset_command)(char *asset);
void print_file(char *file);
#endif

4
source/engine/2dcamera.h Normal file
View file

@ -0,0 +1,4 @@
#ifndef TWODCAMERA_H
#define TWODCAMERA_H
#endif

385
source/engine/2dphysics.c Normal file
View file

@ -0,0 +1,385 @@
#include "2dphysics.h"
#include "gameobject.h"
#include <string.h>
#include "mathc.h"
cpBody *ballBody = NULL;
cpSpace *space = NULL;
float phys2d_gravity = -50.f;
int physOn = 0;
void phys2d_init()
{
space = cpSpaceNew();
cpSpaceSetGravity(space, cpv(0, phys2d_gravity));
}
void phys2d_update(float deltaT)
{
cpSpaceStep(space, deltaT * physOn);
}
void phys2d_apply()
{
cpSpaceSetGravity(space, cpv(0, phys2d_gravity));
}
void phys2d_shape_apply(struct phys2d_shape *shape)
{
cpShapeSetFriction(shape->shape, shape->go->f);
cpShapeSetElasticity(shape->shape, shape->go->e);
}
void init_phys2dshape(struct phys2d_shape *shape, struct mGameObject *go)
{
shape->go = go;
phys2d_shape_apply(shape);
}
struct phys2d_circle *Make2DCircle(struct mGameObject *go)
{
struct phys2d_circle *new = malloc(sizeof(struct phys2d_circle));
new->radius = 10.f;
new->offset[0] = 0.f;
new->offset[1] = 0.f;
phys2d_circleinit(new, go);
return new;
}
void phys2d_circleinit(struct phys2d_circle *circle,
struct mGameObject *go)
{
circle->shape.shape =
cpSpaceAddShape(space,
cpCircleShapeNew(go->body, circle->radius,
cpvzero));
init_phys2dshape(&circle->shape, go);
}
struct phys2d_segment *Make2DSegment(struct mGameObject *go)
{
struct phys2d_segment *new = malloc(sizeof(struct phys2d_segment));
new->thickness = 1.f;
new->a[0] = 0.f;
new->a[1] = 0.f;
new->b[0] = 0.f;
new->b[1] = 0.f;
phys2d_seginit(new, go);
return new;
}
void phys2d_seginit(struct phys2d_segment *seg, struct mGameObject *go)
{
seg->shape.shape =
cpSpaceAddShape(space,
cpSegmentShapeNew(go->body, cpvzero, cpvzero,
seg->thickness));
init_phys2dshape(&seg->shape, go);
}
struct phys2d_box *Make2DBox(struct mGameObject *go)
{
struct phys2d_box *new = malloc(sizeof(struct phys2d_box));
new->w = 50.f;
new->h = 50.f;
new->r = 0.f;
new->offset[0] = 0.f;
new->offset[1] = 0.f;
phys2d_boxinit(new, go);
return new;
}
void phys2d_boxinit(struct phys2d_box *box, struct mGameObject *go)
{
cpVect verts[4] =
{ { -5.f, -5.f }, { 5.f, -5.f }, { 5.f, 5.f }, { -5.f, 5.f } };
cpTransform T = { 0 };
box->shape.shape =
cpSpaceAddShape(space,
cpBoxShapeNew(go->body, box->w, box->h, box->r));
init_phys2dshape(&box->shape, go);
phys2d_applybox(box);
}
struct phys2d_poly *Make2DPoly(struct mGameObject *go)
{
struct phys2d_poly *new = malloc(sizeof(struct phys2d_poly));
new->n = 0;
new->points = NULL;
new->radius = 0.f;
phys2d_polyinit(new, go);
return new;
}
void phys2d_polyinit(struct phys2d_poly *poly, struct mGameObject *go)
{
cpTransform T = { 0 };
poly->shape.shape =
cpSpaceAddShape(space,
cpPolyShapeNew(go->body, 0, NULL, T,
poly->radius));
init_phys2dshape(&poly->shape, go);
phys2d_applypoly(poly);
}
void phys2d_polyaddvert(struct phys2d_poly *poly)
{
poly->n++;
float *oldpoints = poly->points;
poly->points = calloc(2 * poly->n, sizeof(float));
memcpy(poly->points, oldpoints, sizeof(float) * 2 * (poly->n - 1));
free(oldpoints);
}
struct phys2d_edge *Make2DEdge(struct mGameObject *go)
{
struct phys2d_edge *new = malloc(sizeof(struct phys2d_edge));
new->n = 2;
new->points = calloc(2 * 2, sizeof(float));
new->thickness = 0.f;
new->shapes = malloc(sizeof(cpShape *));
phys2d_edgeinit(new, go);
return new;
}
void phys2d_edgeinit(struct phys2d_edge *edge, struct mGameObject *go)
{
edge->shapes[0] =
cpSpaceAddShape(space,
cpSegmentShapeNew(go->body, cpvzero, cpvzero,
edge->thickness));
edge->shape.go = go;
phys2d_edgeshapeapply(&edge->shape, edge->shapes[0]);
phys2d_applyedge(edge);
}
void phys2d_edgeshapeapply(struct phys2d_shape *mshape, cpShape * shape)
{
cpShapeSetFriction(shape, mshape->go->f);
cpShapeSetElasticity(shape, mshape->go->e);
}
void phys2d_edgeaddvert(struct phys2d_edge *edge)
{
edge->n++;
float *oldp = edge->points;
edge->points = calloc(edge->n * 2, sizeof(float));
memcpy(edge->points, oldp, sizeof(float) * 2 * (edge->n - 1));
cpShape **oldshapes = edge->shapes;
edge->shapes = malloc(sizeof(cpShape *) * (edge->n - 1));
memcpy(edge->shapes, oldshapes, sizeof(cpShape *) * (edge->n - 2));
cpVect a =
{ edge->points[(edge->n - 2) * 2],
edge->points[(edge->n - 2) * 2 + 1] };
cpVect b =
{ edge->points[(edge->n - 1) * 2],
edge->points[(edge->n - 1) * 2 + 1] };
edge->shapes[edge->n - 2] =
cpSpaceAddShape(space,
cpSegmentShapeNew(edge->shape.go->body, a, b,
edge->thickness));
phys2d_edgeshapeapply(&edge->shape, edge->shapes[edge->n - 2]);
free(oldp);
free(oldshapes);
}
#include "debugdraw.h"
#include "gameobject.h"
#include <math.h>
#include <chipmunk_unsafe.h>
void phys2d_applycircle(struct phys2d_circle *circle)
{
float radius = circle->radius * circle->shape.go->scale;
float s = circle->shape.go->scale;
cpVect offset = { circle->offset[0] * s, circle->offset[1] * s };
cpCircleShapeSetRadius(circle->shape.shape, radius);
cpCircleShapeSetOffset(circle->shape.shape, offset);
cpBodySetMoment(circle->shape.go->body,
cpMomentForCircle(circle->shape.go->mass, 0, radius,
offset));
}
void phys2d_applyseg(struct phys2d_segment *seg)
{
float s = seg->shape.go->scale;
cpVect a = { seg->a[0] * s, seg->a[1] * s };
cpVect b = { seg->b[0] * s, seg->b[1] * s };
cpSegmentShapeSetEndpoints(seg->shape.shape, a, b);
cpSegmentShapeSetRadius(seg->shape.shape, seg->thickness * s);
}
void phys2d_applybox(struct phys2d_box *box)
{
float s = box->shape.go->scale;
cpTransform T = { 0 };
T.a = s;
T.d = s;
T.tx = box->offset[0] * s;
T.ty = box->offset[1] * s;
float hh = box->h / 2.f;
float hw = box->w / 2.f;
cpVect verts[4] =
{ { -hw, -hh }, { hw, -hh }, { hw, hh }, { -hw, hh } };
cpPolyShapeSetVerts(box->shape.shape, 4, verts, T);
cpPolyShapeSetRadius(box->shape.shape, box->r);
}
void phys2d_applypoly(struct phys2d_poly *poly)
{
cpVect verts[poly->n];
for (int i = 0; i < poly->n; i++) {
verts[i].x = poly->points[i * 2];
verts[i].y = poly->points[i * 2 + 1];
}
CP_CONVEX_HULL(poly->n, verts, hullCount, hullVerts);
float s = poly->shape.go->scale;
cpTransform T = { 0 };
T.a = s;
T.d = s;
cpPolyShapeSetVerts(poly->shape.shape, hullCount, hullVerts, T);
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
}
void phys2d_applyedge(struct phys2d_edge *edge)
{
float s = edge->shape.go->scale;
for (int i = 0; i < edge->n - 1; i++) {
cpVect a =
{ edge->points[i * 2] * s, edge->points[i * 2 + 1] * s };
cpVect b =
{ edge->points[i * 2 + 2] * s, edge->points[i * 2 + 3] * s };
cpSegmentShapeSetEndpoints(edge->shapes[i], a, b);
cpSegmentShapeSetRadius(edge->shapes[i], edge->thickness);
}
}
void phys2d_dbgdrawcircle(struct phys2d_circle *circle)
{
cpVect p = cpBodyGetPosition(circle->shape.go->body);
cpVect o = cpCircleShapeGetOffset(circle->shape.shape);
float d = sqrt(pow(o.x, 2.f) + pow(o.y, 2.f));
float a = atan2(o.y, o.x) + cpBodyGetAngle(circle->shape.go->body);
draw_circle(p.x + (d * cos(a)), p.y + (d * sin(a)),
cpCircleShapeGetRadius(circle->shape.shape), 1);
}
void phys2d_dbgdrawseg(struct phys2d_segment *seg)
{
cpVect p = cpBodyGetPosition(seg->shape.go->body);
float s = seg->shape.go->scale;
cpVect a = cpSegmentShapeGetA(seg->shape.shape);
cpVect b = cpSegmentShapeGetB(seg->shape.shape);
float angle = cpBodyGetAngle(seg->shape.go->body);
float ad = sqrt(pow(a.x, 2.f) + pow(a.y, 2.f));
float bd = sqrt(pow(b.x, 2.f) + pow(b.y, 2.f));
float aa = atan2(a.y, a.x) + angle;
float ba = atan2(b.y, b.x) + angle;
draw_line(ad * cos(aa) + p.x, ad * sin(aa) + p.y, bd * cos(ba) + p.x,
bd * sin(ba) + p.y);
}
void phys2d_dbgdrawbox(struct phys2d_box *box)
{
int n = cpPolyShapeGetCount(box->shape.shape);
cpVect b = cpBodyGetPosition(box->shape.go->body);
float angle = cpBodyGetAngle(box->shape.go->body);
float points[n * 2];
for (int i = 0; i < n; i++) {
cpVect p = cpPolyShapeGetVert(box->shape.shape, i);
float d = sqrt(pow(p.x, 2.f) + pow(p.y, 2.f));
float a = atan2(p.y, p.x) + angle;
points[i * 2] = d * cos(a) + b.x;
points[i * 2 + 1] = d * sin(a) + b.y;
}
draw_poly(points, n);
}
void phys2d_dbgdrawpoly(struct phys2d_poly *poly)
{
cpVect b = cpBodyGetPosition(poly->shape.go->body);
float angle = cpBodyGetAngle(poly->shape.go->body);
float s = poly->shape.go->scale;
for (int i = 0; i < poly->n; i++) {
float point[2];
float d =
sqrt(pow(poly->points[i * 2] * s, 2.f) +
pow(poly->points[i * 2 + 1] * s, 2.f));
float a =
atan2(poly->points[i * 2 + 1], poly->points[i * 2]) + angle;
draw_point(b.x + d * cos(a), b.y + d * sin(a), 3);
}
if (poly->n >= 3) {
int n = cpPolyShapeGetCount(poly->shape.shape);
float points[n * 2];
for (int i = 0; i < n; i++) {
cpVect p = cpPolyShapeGetVert(poly->shape.shape, i);
float d = sqrt(pow(p.x, 2.f) + pow(p.y, 2.f));
float a = atan2(p.y, p.x) + angle;
points[i * 2] = d * cos(a) + b.x;
points[i * 2 + 1] = d * sin(a) + b.y;
}
draw_poly(points, n);
}
}
void phys2d_dbgdrawedge(struct phys2d_edge *edge)
{
cpVect p = cpBodyGetPosition(edge->shape.go->body);
float s = edge->shape.go->scale;
float angle = cpBodyGetAngle(edge->shape.go->body);
for (int i = 0; i < edge->n; i++) {
float point[2];
float d =
sqrt(pow(edge->points[i * 2] * s, 2.f) +
pow(edge->points[i * 2 + 1] * s, 2.f));
float a =
atan2(edge->points[i * 2 + 1], edge->points[i * 2]) + angle;
draw_point(p.x + d * cos(a), p.y + d * sin(a), 3);
}
for (int i = 0; i < edge->n - 1; i++) {
cpVect a = cpSegmentShapeGetA(edge->shapes[i]);
cpVect b = cpSegmentShapeGetB(edge->shapes[i]);
float ad = sqrt(pow(a.x, 2.f) + pow(a.y, 2.f));
float bd = sqrt(pow(b.x, 2.f) + pow(b.y, 2.f));
float aa = atan2(a.y, a.x) + angle;
float ba = atan2(b.y, b.x) + angle;
draw_line(ad * cos(aa) + p.x, ad * sin(aa) + p.y,
bd * cos(ba) + p.x, bd * sin(ba) + p.y);
}
}

90
source/engine/2dphysics.h Normal file
View file

@ -0,0 +1,90 @@
#ifndef TWODPHYSICS_H
#define TWODPHYSICS_H
#include <chipmunk.h>
struct mGameObject;
extern cpBody *ballBody;
extern float phys2d_gravity;
extern int physOn;
extern cpSpace *space;
struct phys2d_shape {
cpShape *shape;
struct mGameObject *go;
};
struct phys2d_circle {
float radius;
float offset[2];
struct phys2d_shape shape;
};
struct phys2d_segment {
float a[2];
float b[2];
float thickness;
struct phys2d_shape shape;
};
struct phys2d_box {
float w;
float h;
float r;
float offset[2];
struct phys2d_shape shape;
};
struct phys2d_edge {
int n;
float *points;
float thickness;
cpShape **shapes;
struct phys2d_shape shape;
};
struct phys2d_poly {
int n;
float *points;
float radius;
struct phys2d_shape shape;
};
struct phys2d_circle *Make2DCircle(struct mGameObject *go);
void phys2d_circleinit(struct phys2d_circle *circle,
struct mGameObject *go);
void phys2d_applycircle(struct phys2d_circle *circle);
void phys2d_dbgdrawcircle(struct phys2d_circle *circle);
struct phys2d_segment *Make2DSegment(struct mGameObject *go);
void phys2d_seginit(struct phys2d_segment *seg, struct mGameObject *go);
void phys2d_applyseg(struct phys2d_segment *seg);
void phys2d_dbgdrawseg(struct phys2d_segment *seg);
struct phys2d_box *Make2DBox(struct mGameObject *go);
void phys2d_boxinit(struct phys2d_box *box, struct mGameObject *go);
void phys2d_applybox(struct phys2d_box *box);
void phys2d_dbgdrawbox(struct phys2d_box *box);
struct phys2d_poly *Make2DPoly(struct mGameObject *go);
void phys2d_polyinit(struct phys2d_poly *poly, struct mGameObject *go);
void phys2d_applypoly(struct phys2d_poly *poly);
void phys2d_dbgdrawpoly(struct phys2d_poly *poly);
void phys2d_polyaddvert(struct phys2d_poly *poly);
struct phys2d_edge *Make2DEdge(struct mGameObject *go);
void phys2d_edgeinit(struct phys2d_edge *edge, struct mGameObject *go);
void phys2d_applyedge(struct phys2d_edge *edge);
void phys2d_edgeshapeapply(struct phys2d_shape *mshape, cpShape * shape);
void phys2d_dbgdrawedge(struct phys2d_edge *edge);
void phys2d_edgeaddvert(struct phys2d_edge *edge);
void phys2d_init();
void phys2d_update(float deltaT);
void phys2d_apply();
#endif

47
source/engine/3dphysics.c Normal file
View file

@ -0,0 +1,47 @@
#include <3dphysics.h>
/*
btDefaultCollisionConfiguration *collisionConfig {
NULL};
btCollisionDispatcher *dispatcher {
NULL};
btBroadphaseInterface *overlappingPairCache {
NULL};
btSequentialImpulseConstraintSolver *solver {
NULL};
btDiscreteDynamicsWorld *dynamicsWorld {
NULL};
btRigidBody *worldFloor {
NULL};
void btUpdate()
{
// dynamicsWorld->stepSimulation(deltaT);
}
void btInit()
{
// collisionConfig = new btDefaultCollisionConfiguration();
// dispatcher = new btCollisionDispatcher(collisionConfig);
// overlappingPairCache = new btDbvtBroadphase();
// solver = new btSequentialImpulseConstraintSolver;
// dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfig);
// dynamicsWorld->setGravity(btVector3(0.f, -9.8f, 0.f));
// btDebugDrawer = new BulletDebugDrawer_OpenGL();
// dynamicsWorld->setDebugDrawer(btDebugDrawer);
//btDebugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb);
// Add camera and plane to world
// dynamicsWorld->addRigidBody(camera.body);
// camera.body->setGravity(btVector3(0.f, 0.f, 0.f));
// Create and add plane
// btStaticPlaneShape* floorShape = new btStaticPlaneShape(btVector3(0.f, 1.f, 0.f), 0.f);
// btDefaultMotionState* motionState = new btDefaultMotionState();
// btVector3 bodyInertia;
// btRigidBody::btRigidBodyConstructionInfo bodyCI = btRigidBody::btRigidBodyConstructionInfo(0.f, motionState, floorShape, bodyInertia);
// worldFloor = new btRigidBody(bodyCI);
// dynamicsWorld->addRigidBody(worldFloor);
}
*/

View file

@ -0,0 +1,4 @@
#ifndef THREEDPHYSICS_H
#define THREEDPHYSICS_H
#endif

View file

@ -0,0 +1,4 @@
#ifndef BILLBOARD_H
#define BILLBOARD_H
#endif

137
source/engine/camera.c Normal file
View file

@ -0,0 +1,137 @@
#include "camera.h"
#include "gameobject.h"
#include "input.h"
#include <SDL.h>
const float CAMERA_MINSPEED = 1.f;
const float CAMERA_MAXSPEED = 300.f;
const float CAMERA_ROTATESPEED = 6.f;
void cam_goto_object(struct mCamera *cam, struct mTransform *transform)
{
mfloat_t fwd[3] = { 0.f };
vec3_subtract(cam->transform.position, transform->position,
vec3_multiply_f(fwd, trans_forward(fwd, transform),
10.f));
}
void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform)
{
mfloat_t fwd[3] = { 0.f };
vec3_add(transform->position, cam->transform.position,
vec3_multiply_f(fwd, trans_forward(fwd, &cam->transform),
10.f));
}
mfloat_t *getviewmatrix(mfloat_t view[16],
const struct mCamera *const camera)
{
mfloat_t fwd[3] = { 0.f };
mfloat_t look[3] = { 0.f };
vec3_rotate_quat(fwd, FORWARD, camera->transform.rotation);
vec3_add(look, camera->transform.position, fwd);
mat4_look_at(view, camera->transform.position, look, UP);
return view;
/*return mat4_look_at(view, ncam.transform.position,
vec3_add(look, ncam.transform.position,
trans_forward(fwd, &ncam.transform)),
UP); */
}
void camera_2d_update(struct mCamera *camera, float deltaT)
{
static mfloat_t holdvec[3];
static mfloat_t frame[3];
vec3_zero(frame);
if (currentKeystates[SDL_SCANCODE_W])
vec3_add(frame, frame, UP);
if (currentKeystates[SDL_SCANCODE_S])
vec3_add(frame, frame, DOWN);
if (currentKeystates[SDL_SCANCODE_A])
vec3_add(frame, frame, LEFT);
if (currentKeystates[SDL_SCANCODE_D])
vec3_add(frame, frame, RIGHT);
float speedMult = currentKeystates[SDL_SCANCODE_LSHIFT] ? 2.f : 1.f;
if (!vec3_is_zero(frame)) {
vec3_normalize(frame, frame);
vec3_add(camera->transform.position, camera->transform.position,
vec3_multiply_f(frame, frame,
camera->speed * speedMult * deltaT));
}
}
/*
void camera_update(struct mCamera * camera, float mouseX, float mouseY,
const uint8_t * keystate, int32_t mouseWheelY,
float deltaTime)
{
// if (SDL_GetRelativeMouseMode()) vec3_zero(camera->frame_move);
static mfloat_t holdvec[VEC3_SIZE];
vec3_zero(camera->frame_move);
if (currentKeystates[SDL_SCANCODE_W])
vec3_add(camera->frame_move, camera->frame_move,
trans_forward(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_S])
vec3_subtract(camera->frame_move, camera->frame_move,
trans_forward(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_A])
vec3_subtract(camera->frame_move, camera->frame_move,
trans_right(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_D])
vec3_add(camera->frame_move, camera->frame_move,
trans_right(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_E])
vec3_add(camera->frame_move, camera->frame_move,
trans_up(holdvec, &camera->transform));
if (currentKeystates[SDL_SCANCODE_Q])
vec3_subtract(camera->frame_move, camera->frame_move,
trans_up(holdvec, &camera->transform));
camera->speedMult = currentKeystates[SDL_SCANCODE_LSHIFT] ? 2.f : 1.f;
if (!vec3_is_zero(camera->frame_move)) {
vec3_normalize(camera->frame_move, camera->frame_move);
vec3_add(camera->transform.position, camera->transform.position,
vec3_multiply_f(camera->frame_move, camera->frame_move,
camera->speed * camera->speedMult *
deltaTime));
}
// Adjust speed based on mouse wheel
camera->speed =
clampf(camera->speed + mouseWheelY, CAMERA_MINSPEED,
CAMERA_MAXSPEED);
// TODO: Handle this as additive quaternions
camera->yaw -= mouseX * CAMERA_ROTATESPEED * deltaTime;
camera->pitch -= mouseY * CAMERA_ROTATESPEED * deltaTime;
if (camera->pitch > 89.f)
camera->pitch = 89.f;
if (camera->pitch < -89.f)
camera->pitch = -89.f;
mfloat_t qyaw[4] = {0.f};
mfloat_t qpitch[4] = {0.f};
quat_from_axis_angle(qyaw, UP, camera->yaw);
quat_from_axis_angle(qpitch, RIGHT, camera->pitch);
quat_multiply(camera->transform.rotation, qyaw, qpitch);
}
*/

24
source/engine/camera.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef CAMERA_H
#define CAMERA_H
#include "transform.h"
extern const float CAMERA_MINSPEED;
extern const float CAMERA_MAXSPEED;
extern const float CAMERA_ROTATESPEED;
struct mCamera {
struct mTransform transform;
float speed;
float speedMult;
mfloat_t frame_move[VEC3_SIZE];
};
void camera_2d_update(struct mCamera *camera, float deltaT);
mfloat_t *getviewmatrix(mfloat_t view[MAT4_SIZE],
const struct mCamera *const camera);
void cam_goto_object(struct mCamera *cam, struct mTransform *transform);
void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform);
#endif

View file

@ -0,0 +1 @@
#pragma once

18
source/engine/config.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef CONFIG_H
#define CONFIG_H
#define MAXPATH 256 /* 255 chars + null */
#define MAXNAME 50
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720
#define PI 3.14159265358979323846264338327950288f
#define DEG2RADS 0.0174532925199432957692369076848861271344287188854172545609719144f
#define RAD2DEGS 57.2958f
#define MSAA_SAMPLES 2
#endif

173
source/engine/datastream.c Normal file
View file

@ -0,0 +1,173 @@
#include "datastream.h"
#include <pl_mpeg.h>
#include "config.h"
#include "shader.h"
#include "resources.h"
#include <GL/glew.h>
#include <stdbool.h>
static void ds_update_texture(uint32_t unit, uint32_t texture,
plm_plane_t * plane)
{
glActiveTexture(unit);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, plane->width, plane->height, 0,
GL_RED, GL_UNSIGNED_BYTE, plane->data);
}
static void render_frame(plm_t * mpeg, plm_frame_t * frame, void *user)
{
struct datastream *ds = user;
shader_use(ds->shader);
ds_update_texture(GL_TEXTURE0, ds->texture_y, &frame->y);
ds_update_texture(GL_TEXTURE1, ds->texture_cb, &frame->cb);
ds_update_texture(GL_TEXTURE2, ds->texture_cr, &frame->cr);
}
static void render_audio(plm_t * mpeg, plm_samples_t * samples, void *user)
{
struct datastream *ds = (struct datastream *) user;
int size = sizeof(float) * samples->count * 2;
SDL_QueueAudio(ds->audio_device, samples->interleaved, size);
}
void ds_openvideo(struct datastream *ds, const char *video,
const char *adriver)
{
ds_stop(ds);
char buf[MAXPATH] = {'\0'};
sprintf(buf, "%s%s", DATA_PATH, video);
ds->plm = plm_create_with_filename(buf);
if (!ds->plm) {
SDL_Log("Couldn't open %s", video);
}
int samplerate = plm_get_samplerate(ds->plm);
SDL_Log("Opened %s - framerate: %f, samplerate: %d, duration: %f",
video,
plm_get_framerate(ds->plm),
plm_get_samplerate(ds->plm), plm_get_duration(ds->plm)
);
plm_set_video_decode_callback(ds->plm, render_frame, ds);
plm_set_audio_decode_callback(ds->plm, render_audio, ds);
plm_set_loop(ds->plm, false);
plm_set_audio_enabled(ds->plm, true);
plm_set_audio_stream(ds->plm, 0);
SDL_AudioSpec audio_spec;
SDL_memset(&audio_spec, 0, sizeof(audio_spec));
audio_spec.freq = samplerate;
audio_spec.format = AUDIO_F32;
audio_spec.channels = 2;
audio_spec.samples = 4096;
ds->audio_device =
SDL_OpenAudioDevice(adriver, 0, &audio_spec, NULL, 0);
printf("Opened audio device %d on driver %s\n", ds->audio_device,
adriver);
// if (audio_device == 0) {
// SDL_Log("Failed to open audio device: %s", SDL_GetError());
// }
SDL_PauseAudioDevice(ds->audio_device, 0);
// Adjust the audio lead time according to the audio_spec buffer size
//plm_set_audio_lead_time(plm, (double)audio_spec.samples / (double)samplerate);
ds->playing = true;
}
struct datastream *MakeDatastream(struct mShader *shader)
{
struct datastream *newds =
(struct datastream *) malloc(sizeof(struct datastream));
newds->shader = shader;
shader_use(newds->shader);
glGenTextures(1, &newds->texture_y);
glBindTexture(GL_TEXTURE_2D, newds->texture_y);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
shader_setint(newds->shader, "texture_y", 0);
glGenTextures(1, &newds->texture_cb);
glBindTexture(GL_TEXTURE_2D, newds->texture_cb);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
shader_setint(newds->shader, "texture_cb", 1);
glGenTextures(1, &newds->texture_cr);
glBindTexture(GL_TEXTURE_2D, newds->texture_cr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
shader_setint(newds->shader, "texture_cr", 2);
return newds;
}
void ds_advance(struct datastream *ds, uint32_t ms)
{
if (ds->playing) {
double advanceTime = ms / 1000.f;
plm_decode(ds->plm, advanceTime);
}
}
void ds_seek(struct datastream *ds, uint32_t time)
{
SDL_ClearQueuedAudio(0);
plm_seek(ds->plm, time, false);
}
void ds_fwdframes(struct datastream *ds, int frames)
{
for (int i = 0; i < frames; i++) {
plm_frame_t *frame = plm_decode_video(ds->plm);
render_frame(ds->plm, frame, ds);
}
}
void ds_pause(struct datastream *ds)
{
ds->playing = false;
}
void ds_stop(struct datastream *ds)
{
if (ds->plm != NULL) {
plm_destroy(ds->plm);
ds->plm = NULL;
}
if (ds->audio_device)
SDL_CloseAudioDevice(ds->audio_device);
ds->playing = false;
}
// TODO: Must be a better way
int ds_videodone(struct datastream *ds)
{
return (ds->plm == NULL)
|| plm_get_time(ds->plm) >= plm_get_duration(ds->plm);
}
double ds_remainingtime(struct datastream *ds)
{
if (ds->plm != NULL)
return plm_get_duration(ds->plm) - plm_get_time(ds->plm);
else
return 0.f;
}

View file

@ -0,0 +1,30 @@
#ifndef DATASTREAM_H
#define DATASTREAM_H
#include <SDL_audio.h>
typedef struct plm_t plm_t;
struct datastream {
plm_t *plm;
struct mShader *shader;
double last_time;
int playing;
SDL_AudioDeviceID audio_device;
uint32_t texture_y;
uint32_t texture_cb;
uint32_t texture_cr;
};
struct datastream *MakeDatastream(struct mShader *shader);
void ds_openvideo(struct datastream *ds, const char *path,
const char *adriver);
void ds_advance(struct datastream *ds, uint32_t ms);
void ds_seek(struct datastream *ds, uint32_t time);
void ds_pause(struct datastream *ds);
void ds_stop(struct datastream *ds);
int ds_videodone(struct datastream *ds);
double ds_remainingtime(struct datastream *ds);
#endif

122
source/engine/engine.c Normal file
View file

@ -0,0 +1,122 @@
#define PL_MPEG_IMPLEMENTATION
#define CGLTF_IMPLEMENTATION
#define GL_GLEXT_PROTOTYPES
//#define MATHC_USE_INT16
//#define MATHC_FLOATING_POINT_TYPE GLfloat
//#define MATHC_USE_DOUBLE_FLOATING_POINT
#define STB_DS_IMPLEMENTATION
#include <stb_ds.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <pl_mpeg.h>
#ifdef EDITOR
#include "editor.h"
#endif
#include <SDL.h>
#include "openglrender.h"
#include "window.h"
#include "camera.h"
#include "input.h"
#include "sprite.h"
#include "2dphysics.h"
#include "gameobject.h"
#include "registry.h"
#define FPS30 33
#define FPS60 17
#define FPS120 8;
#define FPS144 7
#define FPS300 3
unsigned int frameCount = 0;
Uint32 lastTick = 0;
Uint32 frameTick = 0;
Uint32 elapsed = 0;
Uint32 physMS = FPS144;
Uint32 physlag = 0;
Uint32 renderMS = FPS144;
Uint32 renderlag = 0;
int main(int argc, char **args)
{
script_init();
registry_init();
gameobjects = vec_make(sizeof(struct mGameObject), 100);
prefabs = vec_make(MAXNAME, 25);
// TODO: Init these on the heap instead
struct mCamera camera = { 0 };
camera.speed = 500;
stbi_set_flip_vertically_on_load(1);
resources_init();
openglInit();
sprite_initialize();
#ifdef EDITOR
editor_init(window);
#endif
phys2d_init();
quit = false;
SDL_Event e;
//While application is running
while (!quit) {
frameTick = SDL_GetTicks();
elapsed = frameTick - lastTick;
lastTick = frameTick;
deltaT = elapsed / 1000.f;
physlag += elapsed;
renderlag += elapsed;
input_poll();
if (physlag >= physMS) {
phys2d_update(physMS / 1000.f);
physlag -= physMS;
}
if (renderlag >= renderMS) {
if (physOn) {
vec_walk(gameobjects, gameobject_update);
}
camera_2d_update(&camera, renderMS / 1000.f);
openglRender(&camera);
#ifdef EDITOR
editor_render();
#endif
window_swap(window);
renderlag -= renderMS;
}
}
SDL_StopTextInput();
SDL_Quit();
return 0;
}

240
source/engine/font.c Normal file
View file

@ -0,0 +1,240 @@
#include "font.h"
#include <shader.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <GL/glew.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include <stb_truetype.h>
static struct Character Characters[127] = { '\0' };
static uint32_t VBO = 0;
static uint32_t VAO = 0;
unsigned char ttf_buffer[24 << 20];
unsigned char temp_bitmap[512 * 512];
struct sFont MakeFont(const char *fontfile, int height)
{
struct sFont newfont = { 0 };
newfont.height = height;
char fontpath[256];
snprintf(fontpath, 256, "fonts/%s", fontfile);
stbtt_fontinfo fontinfo = { 0 };
int i, j, ascent, baseline, ch = 0;
stbtt_InitFont(&fontinfo, ttf_buffer, 0);
stbtt_GetFontVMetrics(&fontinfo, &ascent, 0, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for (unsigned char c = 0; c < 128; c++) {
unsigned char *bitmap;
int advance, lsb, w, h;
stbtt_GetCodepointHMetrics(&fontinfo, c, &advance, &lsb);
bitmap =
stbtt_GetCodepointBitmap(&fontinfo, 0,
stbtt_ScaleForPixelHeight(&fontinfo,
newfont.
height), c,
&w, &h, 0, 0);
GLuint ftexture;
glGenTextures(1, &ftexture);
glBindTexture(GL_TEXTURE_2D, ftexture);
glTexImage2D(GL_TEXTURE_2D,
0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, bitmap);
glGenerateMipmap(GL_TEXTURE_2D);
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_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
Characters[c].TextureID = ftexture;
Characters[c].Advance = advance;
Characters[c].Size[0] = w;
Characters[c].Size[1] = h;
Characters[c].Bearing[0] = lsb;
Characters[c].Bearing[1] = 0;
}
// configure VAO/VBO for texture quads
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 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);
return newfont;
}
void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale,
struct mShader *shader, float color[3])
{
float xpos = cursor[0] + c.Bearing[0] * scale;
float ypos = cursor[1] - (c.Size[1] - c.Bearing[1]) * scale;
float w = c.Size[0] * scale;
float h = c.Size[1] * scale;
float verts[4 * 4] = {
xpos, ypos + h, 0.f, 0.f,
xpos, ypos, 0.f, 1.f,
xpos + w, ypos + h, 1.f, 0.f,
xpos + w, ypos, 1.f, 1.f
};
// float outlineWidth = 1.1;
// float ow = c.Size[0] * scale * outlineWidth;
// float oh = c.Size[1] * scale * outlineWidth;
// float oxpos = cursor[0] + c.Bearing[0] * scale * outlineWidth - ((ow-w)/2);
// float oypos = cursor[1] - (c.Size[1] - c.Bearing[1]) * scale * outlineWidth - ((oh-h)/2);
// float overts[4*4] = {
// oxpos, oypos + oh, 0.f, 0.f,
// oxpos, oypos, 0.f, 1.f,
// oxpos + ow, oypos + oh, 1.f, 0.f,
// oxpos + ow, oypos, 1.f, 1.f
// };
float shadowOffset = 6.f;
float sxpos =
cursor[0] + c.Bearing[0] * scale + (scale * shadowOffset);
float sypos =
cursor[1] - (c.Size[1] - c.Bearing[1]) * scale -
(scale * shadowOffset);
float sverts[4 * 4] = {
sxpos, sypos + h, 0.f, 0.f,
sxpos, sypos, 0.f, 1.f,
sxpos + w, sypos + h, 1.f, 0.f,
sxpos + w, sypos, 1.f, 1.f
};
glBindTexture(GL_TEXTURE_2D, c.TextureID);
//// Shadow pass
float black[3] = { 0, 0, 0 };
shader_setvec3(shader, "textColor", black);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(sverts), sverts);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//// Outline pass
shader_setvec3(shader, "textColor", color);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void renderText(struct sFont font, struct mShader *shader,
const char *text, mfloat_t pos[2], float scale,
mfloat_t color[3], float lw)
{
shader_use(shader);
shader_setvec3(shader, "textColor", color);
mfloat_t cursor[2] = { 0.f };
cursor[0] = pos[0];
cursor[1] = pos[1];
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
char modText[sizeof(*text)];
strcpy(modText, text);
char *line, *wordstart;
line = strtok(modText, "\n");
while (line != NULL) {
cursor[0] = pos[0];
int wordWidth = 0;
// iterate through all characters
while (*line != '\0') {
wordstart = line;
if (!isspace(*line)) {
struct Character ch = Characters[*line];
if (lw > 0
&& (cursor[0] + ((ch.Advance >> 6) * scale) - pos[0] >=
lw)) {
cursor[0] = pos[0];
cursor[1] -= scale * font.height;
} else {
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
cursor[0] += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
}
sdrawCharacter(ch, cursor, scale, shader, color);
++line;
} else {
while (!isspace(*line) || *line != '\0') { // Seek line to the end of the word
++line;
wordWidth += (Characters[*line].Advance >> 6) * scale;
}
// Now wordStart and stringPos surround the word, go through them. If the word that's about to be drawn goes past the line width, go to next line
if (lw > 0 && (cursor[0] + wordWidth - pos[0] >= lw)) {
cursor[0] = pos[0];
cursor[1] -= scale * font.height;
}
while (wordstart < line) { // Go through
struct Character ch = Characters[*wordstart];
sdrawCharacter(Characters[*wordstart], cursor, scale,
shader, color);
cursor[0] += (ch.Advance >> 6) * scale;
++wordstart;
}
}
}
cursor[1] -= scale * font.height;
line = strtok(NULL, "\n");
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}

29
source/engine/font.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef FONT_H
#define FONT_H
#include "mathc.h"
struct mShader;
/// Holds all state information relevant to a character as loaded using FreeType
struct Character {
uint32_t TextureID; // ID handle of the glyph texture
mfloat_t Size[2]; // Size of glyph
mfloat_t Bearing[2]; // Offset from baseline to left/top of glyph
unsigned int Advance; // Horizontal offset to advance to next glyph
};
struct sFont {
uint32_t fontTexture;
uint32_t height;
};
struct sFont MakeFont(const char *fontfile, int height);
void sdrawCharacter(struct Character c, mfloat_t cursor[2], float scale,
struct mShader *shader, float color[3]);
void renderText(struct sFont font, struct mShader *shader,
const char *text, mfloat_t pos[2], float scale,
mfloat_t color[3], float lw);
#endif

200
source/engine/gameobject.c Normal file
View file

@ -0,0 +1,200 @@
#include "gameobject.h"
#include "shader.h"
#include "sprite.h"
#include "registry.h"
#include "2dphysics.h"
#include "script.h"
#include "vec.h"
#include "input.h"
#include <string.h>
#include <chipmunk.h>
struct vec *gameobjects = NULL;
struct mGameObject *updateGO = NULL;
const int nameBuf[MAXNAME] = { 0 };
const int prefabNameBuf[MAXNAME] = { 0 };
struct mGameObject *get_gameobject_from_id(int id)
{
return vec_get(gameobjects, id - 1);
}
static void gameobject_setpickcolor(struct mGameObject *go)
{
float r = ((go->editor.id & 0x000000FF) >> 0) / 255.f;
float g = ((go->editor.id & 0x0000FF00) >> 8) / 255.f;
float b = ((go->editor.id & 0x00FF0000) >> 16) / 255.f;
go->editor.color[0] = r;
go->editor.color[1] = g;
go->editor.color[2] = b;
}
struct mGameObject *MakeGameobject()
{
struct mGameObject *go = vec_add(gameobjects, NULL);
go->editor.id = gameobjects->len - 1;
go->transform.scale = 1.f;
gameobject_setpickcolor(go);
strncpy(go->editor.mname, "New object", MAXNAME);
go->scale = 1.f;
go->bodytype = CP_BODY_TYPE_STATIC;
go->mass = 1.f;
go->body = cpSpaceAddBody(space, cpBodyNew(go->mass, 1.f));
go->components = vec_make(sizeof(struct component), 10);
return go;
}
void gameobject_addcomponent(struct mGameObject *go, struct component *c)
{
struct component *newc = vec_add(go->components, c);
newc->go = go;
newc->data = newc->make(newc->go);
}
void gameobject_delete(int id)
{
vec_delete(gameobjects, id);
}
void gameobject_delcomponent(struct mGameObject *go, int n)
{
vec_del_order(go->components, n);
}
void setup_model_transform(struct mTransform *t, struct mShader *s,
float scale)
{
mfloat_t modelT[16] = { 0.f };
mfloat_t matbuff[16] = { 0.f };
memcpy(modelT, UNITMAT4, sizeof(modelT));
mat4_translate_vec3(modelT, t->position);
mat4_multiply(modelT, modelT,
mat4_rotation_quat(matbuff, t->rotation));
mat4_scale_vec3f(modelT, scale);
shader_setmat4(s, "model", modelT);
}
void gameobject_save(struct mGameObject *go, FILE * file)
{
fwrite(go, sizeof(*go), 1, file);
vec_store(go->components, file);
for (int i = 0; i < go->components->len; i++) {
struct component *c = vec_get(go->components, i);
fwrite(c, c->datasize, 1, file);
}
}
void gameobject_saveprefab(struct mGameObject *go)
{
char prefabfname[60] = { '\0' };
strncat(prefabfname, go->editor.prefabName, MAXNAME);
strncat(prefabfname, ".yugh", 10);
FILE *pfile = fopen(prefabfname, "w+");
gameobject_save(go, pfile);
fclose(pfile);
findPrefabs();
}
void gameobject_makefromprefab(char *path)
{
FILE *fprefab = fopen(path, "r");
if (fprefab == NULL) {
return;
}
struct mGameObject *new = MakeGameobject();
fread(new, sizeof(*new), 1, fprefab);
new->editor.id = gameobjects->len - 1;
new->body = cpSpaceAddBody(space, cpBodyNew(new->mass, 1.f));
gameobject_init(new, fprefab);
fclose(fprefab);
}
void gameobject_init(struct mGameObject *go, FILE * fprefab)
{
go->body = cpSpaceAddBody(space, cpBodyNew(go->mass, 1.f));
vec_load(go->components, fprefab);
for (int i = 0; i < go->components->len; i++) {
struct component *newc =
vec_set(go->components, i,
&components[((struct component *)
vec_get(go->components, i))->id]);
newc->go = go;
newc->data = malloc(newc->datasize);
fread(newc->data, newc->datasize, 1, fprefab);
newc->init(newc->data, go);
}
}
void gameobject_syncprefabs(char *revertPath)
{
/*
struct mGameObject **go = objects;
int i = 0;
while(i != nobjects) {
if ((*go)->editor.curPrefabPath && !strcmp((*go)->editor.curPrefabPath, revertPath)) { ; }//objectRevertPrefab(go); //TODO: revertprefab
}
*/
}
void gameobject_revertprefab(struct mGameObject *go)
{
}
void toggleprefab(struct mGameObject *go)
{
go->editor.prefabSync = !go->editor.prefabSync;
if (go->editor.prefabSync) {
strcpy(go->editor.prefabName, go->editor.rootPrefabName);
gameobject_revertprefab(go); //TODO: object revert prefab
} else {
go->editor.prefabName[0] = '\0';
}
}
void component_update(struct component *c)
{
if (c->update)
c->update(c->data, c->go);
}
void gameobject_update(struct mGameObject *go)
{
if (go->update) {
updateGO = go;
script_run(updateGO->update);
}
vec_walk(go->components, component_update);
}
void gameobject_move(struct mGameObject *go, float xs, float ys)
{
cpVect p = cpBodyGetPosition(go->body);
p.x += xs * deltaT;
p.y += ys * deltaT;
cpBodySetPosition(go->body, p);
}
void gameobject_rotate(struct mGameObject *go, float as)
{
cpFloat a = cpBodyGetAngle(go->body);
a += as * deltaT;
cpBodySetAngle(go->body, a);
}

View file

@ -0,0 +1,73 @@
#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H
#include <stdio.h>
#include "mathc.h"
#include "transform.h"
#include "config.h"
#include <stdbool.h>
#include <chipmunk.h>
struct mShader;
struct mSprite;
struct component;
struct vec;
extern struct mGameObject *updateGO;
extern struct vec *gameobjects;
struct editor {
mfloat_t color[3];
int id;
bool active;
bool prefabSync;
char mname[MAXNAME];
char *curPrefabPath;
char prefabName[MAXNAME];
char rootPrefabName[MAXNAME];
};
struct mGameObject {
struct mTransform transform;
struct editor editor;
cpBodyType bodytype;
float scale;
float mass;
cpBody *body;
float f; /* friction */
float e; /* elasticity */
struct vec *components;
char *start;
char *update;
char *fixedupdate;
char *stop;
};
struct mGameObject *MakeGameobject();
void gameobject_delete(int id);
void clear_gameobjects();
int number_of_gameobjects();
void set_n_gameobjects(int n);
void setup_model_transform(struct mTransform *t, struct mShader *s,
float scale);
void toggleprefab(struct mGameObject *go);
struct mGameObject *get_gameobject_from_id(int id);
void gameobject_save(struct mGameObject *go, FILE * file);
void gameobject_addcomponent(struct mGameObject *go, struct component *c);
void gameobject_delcomponent(struct mGameObject *go, int n);
void gameobject_loadcomponent(struct mGameObject *go, int id);
void gameobject_saveprefab(struct mGameObject *go);
void gameobject_makefromprefab(char *path);
void gameobject_syncprefabs(char *revertPath);
void gameobject_revertprefab(struct mGameObject *go);
void gameobject_init(struct mGameObject *go, FILE * fprefab);
void gameobject_update(struct mGameObject *go);
void update_gameobjects();
void gameobject_move(struct mGameObject *go, float xs, float ys);
void gameobject_rotate(struct mGameObject *go, float as);
#endif

1
source/engine/gizmo.c Normal file
View file

@ -0,0 +1 @@
#include <gizmo.h>

4
source/engine/gizmo.h Normal file
View file

@ -0,0 +1,4 @@
#ifndef GIZMO_H
#define GIZMO_H
#endif

33
source/engine/input.c Normal file
View file

@ -0,0 +1,33 @@
#include "input.h"
#include "window.h"
#include <SDL.h>
int32_t mouseWheelX = 0;
int32_t mouseWheelY = 0;
int ychange = 0;
int xchange = 0;
float deltaT = 0;
int quit = 0;
SDL_Event e = { 0 };
uint8_t *currentKeystates = NULL;
void input_poll()
{
ychange = 0;
xchange = 0;
mouseWheelX = 0;
mouseWheelY = 0;
currentKeystates = SDL_GetKeyboardState(NULL);
while (SDL_PollEvent(&e)) {
window_handle_event(window, &e);
#ifdef EDITOR
editor_input(&e);
#endif
}
}

18
source/engine/input.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef INPUT_H
#define INPUT_H
#include <SDL.h>
#include <stdint.h>
extern int32_t mouseWheelX;
extern int32_t mouseWheelY;
extern int ychange;
extern int xchange;
extern float deltaT;
extern int quit;
extern SDL_Event e;
extern uint8_t *currentKeystates;
void input_poll();
#endif

50
source/engine/level.c Normal file
View file

@ -0,0 +1,50 @@
#include "level.h"
#include <stdio.h>
#include <string.h>
#include "vec.h"
#include "gameobject.h"
void save_level(char name[MAXNAME])
{
FILE *lfile = res_open(name, "w+");
if (!lfile) return;
int objs = gameobjects->len;
fwrite(&objs, sizeof(objs), 1, lfile);
for (int i = 0; i < objs; i++) {
gameobject_save(vec_get(gameobjects, i), lfile);
}
fclose(lfile);
}
void load_level(char name[MAXNAME])
{
FILE *lfile = fopen(name, "r");
if (!lfile) return;
int objs;
fread(&objs, sizeof(objs), 1, lfile);
vec_clear(gameobjects);
for (int i = 0; i < objs; i++) {
struct mGameObject *go = vec_add(gameobjects, NULL);
fread(go, sizeof(struct mGameObject), 1, lfile);
gameobject_init(go, lfile);
}
fclose(lfile);
}
void new_level()
{
vec_clear(gameobjects);
}

17
source/engine/level.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef LEVEL_H
#define LEVEL_H
#include "config.h"
// This class holds all of the entities and options for a level. Really it's nothing more than a container and access point for all the entities currently loaded into the game.
struct level {
char name[MAXNAME];
};
void save_level(char name[MAXNAME]);
void load_level(char name[MAXNAME]);
void new_level();
#endif

160
source/engine/light.c Normal file
View file

@ -0,0 +1,160 @@
#include <light.h>
#include <stdbool.h>
/*
void Light::serialize(FILE * file)
{
GameObject::serialize(file);
SerializeFloat(file, &strength);
SerializeVec3(file, (float *) &color);
SerializeBool(file, &dynamic);
}
void Light::deserialize(FILE * file)
{
GameObject::deserialize(file);
DeserializeFloat(file, &strength);
DeserializeVec3(file, (float *) &color);
DeserializeBool(file, &dynamic);
}
static const mfloat_t dlight_init_rot[3] = { 80.f, 120.f, 165.f };
struct mDirectionalLight *dLight = NULL;
struct mDirectionalLight *MakeDLight()
{
if (dLight != NULL) {
dLight =
(struct mDirectionalLight *)
malloc(sizeof(struct mDirectionalLight));
quat_from_euler(dLight->light.obj.transform.rotation,
dlight_init_rot);
return dLight;
}
return dLight;
}
void dlight_prepshader(struct mDirectionalLight *light,
struct mShader *shader)
{
mfloat_t fwd[3] = { 0.f };
trans_forward(fwd, &light->light.obj.transform);
shader_setvec3(shader, "dirLight.direction", fwd);
shader_setvec3(shader, "dirLight.color", light->light.color);
shader_setfloat(shader, "dirLight.strength", light->light.strength);
}
static struct mPointLight *pointLights[4];
static int numLights = 0;
struct mPointLight *MakePointlight()
{
if (numLights < 4) {
struct mPointLight *light =
(struct mPointLight *) malloc(sizeof(struct mPointLight));
pointLights[numLights++] = light;
light->light.strength = 0.2f;
light->constant = 1.f;
light->linear = 0.9f;
light->quadratic = 0.032f;
return light;
}
return NULL;
}
static void prepstring(char *buffer, char *prepend, const char *append)
{
snprintf(buffer, 100, "%s%s", prepend, append);
}
void pointlights_prepshader(struct mShader *shader)
{
for (int i = 0; i < numLights; i++)
pointlight_prepshader(pointLights[i], shader, i);
}
void pointlight_prepshader(struct mPointLight *light,
struct mShader *shader, int num)
{
shader_use(shader);
char prepend[100] = { '\0' };
snprintf(prepend, 100, "%s%d%s", "pointLights[", num, "].");
char str[100] = { '\0' };
prepstring(str, prepend, "position");
shader_setvec3(shader, str, light->light.obj.transform.position);
prepstring(str, prepend, "constant");
shader_setfloat(shader, str, light->constant);
prepstring(str, prepend, "linear");
shader_setfloat(shader, str, light->linear);
prepstring(str, prepend, "quadratic");
shader_setfloat(shader, str, light->quadratic);
prepstring(str, prepend, "strength");
shader_setfloat(shader, str, light->light.strength);
prepstring(str, prepend, "color");
shader_setvec3(shader, str, light->light.color);
}
static struct mSpotLight *spotLights[4];
static int numSpots = 0;
struct mSpotLight *MakeSpotlight()
{
if (numSpots < 4) {
struct mSpotLight *light =
(struct mSpotLight *) malloc(sizeof(struct mSpotLight));
spotLights[numSpots++] = light;
return light;
}
return NULL;
}
void spotlights_prepshader(struct mShader *shader)
{
for (int i = 0; i < numSpots; i++)
spotlight_prepshader(spotLights[i], shader, i);
}
void spotlight_prepshader(struct mSpotLight *light, struct mShader *shader,
int num)
{
mfloat_t fwd[3] = { 0.f };
trans_forward(fwd, &light->light.obj.transform);
shader_use(shader);
shader_setvec3(shader, "spotLight.position",
light->light.obj.transform.position);
shader_setvec3(shader, "spotLight.direction", fwd);
shader_setvec3(shader, "spotLight.color", light->light.color);
shader_setfloat(shader, "spotLight.strength", light->light.strength);
shader_setfloat(shader, "spotLight.cutoff", light->cutoff);
shader_setfloat(shader, "spotLight.distance", light->distance);
shader_setfloat(shader, "spotLight.outerCutoff", light->outerCutoff);
shader_setfloat(shader, "spotLight.linear", light->linear);
shader_setfloat(shader, "spotLight.quadratic", light->quadratic);
shader_setfloat(shader, "spotLight.constant", light->constant);
}
*/

58
source/engine/light.h Normal file
View file

@ -0,0 +1,58 @@
#ifndef LIGHT_H
#define LIGHT_H
/*
struct mLight {
struct mGameObject obj;
mfloat_t color[3];
float strength;
int dynamic;
int on;
};
struct mPointLight {
struct mLight light;
float constant;
float linear;
float quadratic;
};
struct mPointLight *MakePointlight();
void pointlight_prepshader(struct mPointLight *light,
struct mShader *shader, int num);
void pointlights_prepshader(struct mShader *shader);
struct mSpotLight {
struct mLight light;
float constant;
float linear;
float quadratic;
float distance;
float cutoff;
float outerCutoff;
};
struct mSpotLight *MakeSpotlight();
void spotlight_gui(struct mSpotLight *light);
void spotlight_prepshader(struct mSpotLight *light, struct mShader *shader,
int num);
void spotlights_prepshader(struct mShader *shader);
struct mDirectionalLight {
struct mLight light;
};
void dlight_prepshader(struct mDirectionalLight *light,
struct mShader *shader);
struct mDirectionalLight *MakeDLight();
extern struct mDirectionalLight *dLight;
*/
#endif

56
source/engine/log.c Normal file
View file

@ -0,0 +1,56 @@
#include "log.h"
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>
#define logLevel 0
void mYughLog(int category, int priority, const char *message,
int line, const char *file, ...)
{
if (priority >= logLevel) {
time_t now = time(0);
char *dt = ctime(&now);
dt[strlen(dt) - 1] = '\0'; // The above time conversion adds a \n; this removes it
va_list args;
va_start(args, message);
char msgbuffer[ERROR_BUFFER] = { '\0' };
vsnprintf(msgbuffer, ERROR_BUFFER, message, args);
va_end(args);
char buffer[ERROR_BUFFER] = { '\0' };
snprintf(buffer, ERROR_BUFFER, "LEVEL %d :: %s [ %s:%d ] %s\n",
priority, msgbuffer, file, line, dt);
//SDL_LogMessage(category, priority, buffer);
printf(buffer);
fflush(stdout);
}
}
void FlushGLErrors()
{
GLenum glErr = GL_NO_ERROR;
glErr = glGetError();
while (glErr != GL_NO_ERROR) {
YughLog(SDL_LOG_CATEGORY_RENDER, SDL_LOG_PRIORITY_ERROR,
"GL Error: %d", glErr);
glErr = glGetError();
}
}
int TestSDLError(int sdlErr)
{
if (sdlErr != 0) {
YughLog(0, SDL_LOG_PRIORITY_ERROR, "SDL Error :: %s",
SDL_GetError());
return 0;
}
return 1;
}

17
source/engine/log.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef LOG_H
#define LOG_H
#include <SDL_log.h>
#define ERROR_BUFFER 2048
#define YughLog(cat, pri, msg, ...) mYughLog(cat, pri, msg, __LINE__, __FILE__, __VA_ARGS__)
void mYughLog(int category, int priority, const char *message,
int line, const char *file, ...);
void FlushGLErrors();
int TestSDLError(int sdlErr);
#endif

7545
source/engine/mathc.c Normal file

File diff suppressed because it is too large Load diff

1659
source/engine/mathc.h Normal file

File diff suppressed because it is too large Load diff

132
source/engine/mesh.c Normal file
View file

@ -0,0 +1,132 @@
#include "mesh.h"
#include "shader.h"
#include "texture.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <GL/glew.h>
void DrawMesh(struct mMesh *mesh, struct mShader *shader)
{
// bind appropriate textures
uint32_t diffuseNr = 1;
uint32_t specularNr = 1;
uint32_t normalNr = 1;
uint32_t heightNr = 1;
for (uint32_t i = 0; i < (mesh->te - mesh->textures); i++) {
glActiveTexture(GL_TEXTURE0 + i); // active proper texture unit before binding
// retrieve texture number (the N in diffuse_textureN)
char number;
// TODO: malloc every single frame ... nope! Change to stack
char *name =
(char *) malloc(sizeof(char) *
(strlen(mesh->textures[i].type) + 2));
if (mesh->textures[i].type == "texture_diffuse")
number = diffuseNr++;
else if (mesh->textures[i].type == "texture_specular")
number = specularNr++;
else if (mesh->textures[i].type == "texture_normal")
number = normalNr++;
else if (mesh->textures[i].type == "texture_height")
number = heightNr++;
sprintf(name, "%s%d", mesh->textures[i].type, number);
// now set the sampler to the correct texture unit
glUniform1i(glGetUniformLocation(shader->id, name), i);
// and finally bind the texture
glBindTexture(GL_TEXTURE_2D, mesh->textures[i].id);
free(name);
}
// draw mesh
glBindVertexArray(mesh->VAO);
DrawMeshAgain(mesh);
// DEBUG
// triCount += indices.size() / 3;
}
void DrawMeshAgain(struct mMesh *mesh)
{
glDrawElements(GL_TRIANGLES, (mesh->ie - mesh->indices),
GL_UNSIGNED_INT, 0);
}
struct mMesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve,
uint32_t * indices, uint32_t * ie,
struct Texture *textures, struct Texture *te)
{
struct mMesh *newmesh = (struct mMesh *) malloc(sizeof(struct mMesh));
newmesh->vertices = vertices;
newmesh->ve = ve;
newmesh->indices = indices;
newmesh->ie = ie;
newmesh->textures = textures;
newmesh->te = te;
setupmesh(newmesh);
return newmesh;
}
void setupmesh(struct mMesh *mesh)
{
// create buffers/arrays
glGenVertexArrays(1, &mesh->VAO);
glGenBuffers(1, &mesh->VBO);
glGenBuffers(1, &mesh->EBO);
glBindVertexArray(mesh->VAO);
// load data into vertex buffers
glBindBuffer(GL_ARRAY_BUFFER, mesh->VBO);
// The effect is that we can simply pass a pointer to the struct and it translates perfectly to vevc array which
// again translates to 3/2 floats which translates to a byte array.
glBufferData(GL_ARRAY_BUFFER,
(mesh->ve - mesh->vertices) * sizeof(struct Vertex),
&mesh->vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
(mesh->ie - mesh->indices) * sizeof(uint32_t),
&mesh->indices[0], GL_STATIC_DRAW);
// set the vertex attribute pointers
// vertex Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) 0);
// vertex normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, Normal[3]));
// vertex texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, TexCoords[2]));
// vertex tangent
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, Tangent[3]));
// vertex bitangent
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, Bitangent[3]));
// Bone ids
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex,
m_BoneIDs
[MAX_BONE_INFLUENCE]));
// Weights
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(struct Vertex),
(void *) offsetof(struct Vertex, m_Weights));
glBindVertexArray(0);
}

41
source/engine/mesh.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef MESH_H
#define MESH_H
#include "mathc.h"
#include <stdint.h>
struct mShader;
struct Texture;
#define MAX_BONE_INFLUENCE 4
struct Vertex {
mfloat_t Position[3];
mfloat_t Normal[3];
mfloat_t TexCoords[2];
mfloat_t Tangent[3];
mfloat_t Bitangent[3];
int m_BoneIDs[MAX_BONE_INFLUENCE];
float m_Weights[MAX_BONE_INFLUENCE];
};
struct mMesh {
struct Vertex *vertices;
struct Vertex *ve;
uint32_t *indices;
uint32_t *ie;
struct Texture *textures;
struct Texture *te;
uint32_t VAO, VBO, EBO;
};
struct mMesh *MakeMesh(struct Vertex *vertices, struct Vertex *ve,
uint32_t * indices, uint32_t * ie,
struct Texture *textures, struct Texture *te);
void setupmesh(struct mMesh *mesh); /* Loads mesh into the GPU */
void DrawMesh(struct mMesh *mesh, struct mShader *shader);
void DrawMeshAgain(struct mMesh *mesh); /* Draws whatever mesh was drawn last */
#endif

281
source/engine/model.c Normal file
View file

@ -0,0 +1,281 @@
#include "model.h"
#include "mesh.h"
#include "resources.h"
#include "shader.h"
#include <SDL_image.h>
#include <cgltf.h>
#include <string.h>
static struct mModel *lastRendered;
static struct mModel *loadedModels[100];
static struct mModel **lastModel = loadedModels;
static void processnode();
static void processmesh();
static void processtexture();
struct mModel *GetExistingModel(const char *path)
{
struct mModel **model = loadedModels;
while (model++ != lastModel) {
if (!strcmp(path, (*model)->path))
goto end;
return MakeModel(path);
}
end:
return NULL;
}
/* TODO: Make this a hash compare for speedup */
struct mModel *MakeModel(const char *path)
{
char *modelPath =
(char *) malloc(sizeof(char) *
(strlen(DATA_PATH) + strlen(path) + 1));
modelPath[0] = '\0';
strcat(modelPath, DATA_PATH);
strcat(modelPath, path);
printf
("Created new model with modelPath %s, from data_path %s and path %s\n",
modelPath, DATA_PATH, path);
struct mModel *newmodel =
(struct mModel *) malloc(sizeof(struct mModel));
newmodel->path = path;
loadmodel(newmodel);
*lastModel++ = newmodel;
return newmodel;
}
// TODO: Come back to this; simple optimization
void draw_model(struct mModel *model, struct mShader *shader)
{
if (lastRendered != model) {
lastRendered = model;
for (uint32_t i = 0; i < (model->mp - model->meshes); i++)
DrawMesh(&model->meshes[i], shader);
} else {
for (uint32_t i = 0; i < (model->mp - model->meshes); i++)
DrawMeshAgain(&model->meshes[i]);
}
}
void loadmodel(struct mModel *model)
{
printf("Loading model at path %s\n", model->path);
/*
// Load model with cgltf
cgltf_options options = {0};
cgltf_data *data = NULL;
cgltf_result result = cgltf_parse_file(&options, model->path, &data);
meshes = (struct mMesh*)malloc(sizeof(Mesh)*cgltf_data->meshes_count);
directory = get_directory_from_path(model->path);
for (int i = 0; i < data->nodes_count; i++) {
if (data->nodes[i]->mesh) {
for (int j = 0; j < data->nodes[i]->mesh->primatives_count; j++) {
for (int k = 0; k < data->nodes[i]->mesh->primatives[j]->attributes_count; k++) {
switch(data->nodes[i]->mesh->primatives[j]->attributes[k]->type) {
case cgltf_attribute_type_position:
Vertex *vs = (Vertex*)malloc(sizeof(Vertex) * cgltf_accessor_unpack_floats(:::attributes[k]->accesor, NULL, attributes[k]->accessor.count);
cgltf_accessor_unpack_floats(:::attributes[k]->accessor, vs, attributes[k]->accessor.count);
break;
case cgltf_attribute_type_normal:
break;
case cgltf_attribute_type_tangent:
break;
case cgltf_attribute_type_texcoord:
break;
}
}
}
}
}
}
*/
/* TODO: DELETE
// read file via ASSIMP
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path,
aiProcess_Triangulate |
aiProcess_GenSmoothNormals |
aiProcess_FlipUVs |
aiProcess_CalcTangentSpace);
// check for errors
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE
|| !scene->mRootNode) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"ASSIMP error: %s",
importer.GetErrorString());
return;
}
directory = get_directory_from_path(path);
meshes = (Mesh *) malloc(sizeof(Mesh) * 100);
mp = meshes;
// process ASSIMP's root node recursively
processNode(scene->mRootNode, scene); */
}
static void processnode()
{
/*
for (uint32_t i = 0; i < node->mNumMeshes; i++) {
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
*mp = processMesh(mesh, scene);
mp++;
}
for (uint32_t i = 0; i < node->mNumChildren; i++) {
processnode(node->mChildren[i], scene);
}
*/
}
static void processmesh()
{
/*
Vertex *vertices =
(Vertex *) malloc(sizeof(Vertex) * mesh->mNumVertices);
Vertex *vp = vertices + mesh->mNumVertices;
Vertex *p = vertices;
for (int i = 0; i < mesh->mNumVertices; i++) {
// positions
(p + i)->Position.x = mesh->mVertices[i][0];
(p + i)->Position.y = mesh->mVertices[i][1];
(p + i)->Position.z = mesh->mVertices[i][2];
// normals
if (mesh->HasNormals()) {
(p + i)->Normal.x = mesh->mNormals[i][0];
(p + i)->Normal.y = mesh->mNormals[i].y;
(p + i)->Normal.z = mesh->mNormals[i].z;
}
// texture coordinates
if (mesh->mTextureCoords[0]) {
glm::vec2 vec;
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
(p + i)->TexCoords.x = mesh->mTextureCoords[0][i].x;
(p + i)->TexCoords.y = mesh->mTextureCoords[0][i].y;
// tangent
(p + i)->Tangent.x = mesh->mTangents[i].x;
(p + i)->Tangent.y = mesh->mTangents[i].y;
(p + i)->Tangent.z = mesh->mTangents[i].z;
// bitangent
(p + i)->Bitangent.x = mesh->mBitangents[i].x;
(p + i)->Bitangent.y = mesh->mBitangents[i].y;
(p + i)->Bitangent.z = mesh->mBitangents[i].z;
} else
(p + i)->TexCoords = glm::vec2(0.0f, 0.0f);
}
// TODO: Done quickly, find better way. Go through for loop twice!
int numindices = 0;
// now walk through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
numindices += mesh->mFaces[i].mNumIndices;
}
uint32_t *indices = (uint32_t *) malloc(sizeof(uint32_t) * numindices);
uint32_t *ip = indices;
for (uint32_t i = 0; i < mesh->mNumFaces; i++) {
for (uint32_t j = 0; j < mesh->mFaces[i].mNumIndices; j++) {
*ip = mesh->mFaces[i].mIndices[j];
ip++;
}
}
// std::vector<Texture> textures;
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
// TODO: Allocating 100 to be safe, can probably be way less
textures_loaded = (Texture *) malloc(sizeof(Texture) * 100);
tp = textures_loaded;
// we assume a convention for sampler names in the shaders. Each diffuse texture should be named
// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.
// Same applies to other texture as the following list summarizes:
// diffuse: texture_diffuseN
// specular: texture_specularN
// normal: texture_normalN
// 1. diffuse maps
loadMaterialTextures(material, aiTextureType_DIFFUSE,
"texture_diffuse");
// 2. specular maps
loadMaterialTextures(material, aiTextureType_SPECULAR,
"texture_specular");
// 3. normal maps
loadMaterialTextures(material, aiTextureType_NORMALS,
"texture_normal");
// 4. height maps
loadMaterialTextures(material, aiTextureType_AMBIENT,
"texture_height");
// return a mesh object created from the extracted mesh data
return Mesh(vertices, vp, indices, ip, textures_loaded, tp);
*/
}
// TODO: This routine mallocs inside the function
static void processtexture()
{
/*
for (uint32_t i = 0; i < mat->GetTextureCount(type); i++) {
aiString str;
mat->GetTexture(type, i, &str);
for (Texture * tpp = textures_loaded; tpp != tp; tpp++) {
if (strcmp(tpp->path, str.data) == 0)
goto next; // Check if we already have this texture
}
tp->id = TextureFromFile(str.data, this->directory);
tp->type = (char *) malloc(sizeof(char) * strlen(typeName));
strcpy(tp->type, typeName);
tp->path = (char *) malloc(sizeof(char) * strlen(str.data));
strcpy(tp->path, str.data);
tp++;
next:;
}
*/
}

26
source/engine/model.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef MODEL_H
#define MODEL_H
struct mMesh;
struct mShader;
struct mModel {
struct mMesh *meshes;
struct mMesh *mp;
char *directory;
const char *path;
char *name;
};
/* Get the model at a path, or create and return if it doesn't exist */
struct mModel *GetExistingModel(const char *path);
/* Make a Model struct */
struct mModel *MakeModel(const char *path);
/* Load a model from memory into the GPU */
void loadmodel(struct mModel *model);
void draw_model(struct mModel *model, struct mShader *shader);
#endif

View file

@ -0,0 +1,695 @@
#include "openglrender.h"
#include <SDL.h>
#include <SDL_image.h>
#include "sprite.h"
#include "shader.h"
#include "font.h"
#include "config.h"
#include "static_actor.h"
#include "gameobject.h"
#include "camera.h"
#include "window.h"
#include "debugdraw.h"
#include "log.h"
int renderMode = 0;
static GLuint UBO;
static GLuint UBOBind = 0;
static GLuint gridVBO = 0;
static GLuint gridVAO = 0;
static GLuint quadVAO = 0;
static GLuint quadVBO = 0;
static GLuint depthMapFBO = 0;
static GLuint depthMap = 0;
const unsigned int SHADOW_WIDTH = 2048, SHADOW_HEIGHT = 2048;
static struct mShader *outlineShader;
static struct mShader *modelShader;
static struct mShader *shadowShader;
struct mShader *spriteShader = NULL;
struct mShader *animSpriteShader = NULL;
static struct mShader *textShader;
static struct mShader *diffuseShader;
struct sFont stdFont;
static struct mShader *debugDepthQuad;
static struct mShader *debugColorPickShader;
static struct mShader *debugGridShader;
static struct mShader *debugGizmoShader;
struct mStaticActor *gizmo;
float editorFOV = 45.f;
float editorClose = 0.1f;
float editorFar = 1000.f;
mfloat_t editorClearColor[4] = { 0.2f, 0.4f, 0.3f, 1.f };
float shadowLookahead = 8.5f;
mfloat_t gridSmallColor[3] = { 0.35f, 1.f, 0.9f };
mfloat_t gridBigColor[3] = { 0.92f, 0.92f, 0.68f };
float gridScale = 500.f;
float smallGridUnit = 1.f;
float bigGridUnit = 10.f;
float gridSmallThickness = 2.f;
float gridBigThickness = 7.f;
float gridOpacity = 0.3f;
mfloat_t proj[16];
float near_plane = -100.f, far_plane = 10.f, plane_size = 60.f;
// Debug render modes
bool renderGizmos = false;
bool showGrid = true;
bool debugDrawPhysics = false;
bool renderNav = false;
// Lighting effect flags
bool renderAO = true;
bool renderDynamicShadows = true;
bool renderRefraction = true;
bool renderReflection = true;
///// for editing
struct mGameObject *selectedobject = NULL;
char objectName[200] = { '\0' }; // object name buffer
uint16_t debugColorPickBO = 0;
uint16_t debugColorPickTEX = 0;
struct mSprite *tsprite = NULL;
static struct mSprite *tanim = NULL;
static unsigned int projUBO;
void openglInit()
{
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"SDL could not initialize! SDL Error: %s", SDL_GetError());
}
//Use OpenGL 3.3
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2); /* How many x MSAA */
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
// TODO: Add non starter initializtion return here for some reason?
window = MakeSDLWindow("Untitled Game", 1920, 1080,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN |
SDL_WINDOW_RESIZABLE);
//Use Vsync
if (SDL_GL_SetSwapInterval(1)) {
YughLog(0, SDL_LOG_PRIORITY_WARN,
"Unable to set VSync! SDL Error: %s", SDL_GetError());
}
////// MAKE SHADERS
outlineShader = MakeShader("outlinevert.glsl", "outline.glsl");
textShader = MakeShader("textvert.glsl", "textfrag.glsl");
spriteShader = MakeShader("spritevert.glsl", "spritefrag.glsl");
animSpriteShader =
MakeShader("animspritevert.glsl", "animspritefrag.glsl");
debugdraw_init();
stdFont = MakeFont("notosans.ttf", 300);
//glEnable(GL_STENCIL_TEST);
glClearColor(editorClearColor[0], editorClearColor[1],
editorClearColor[2], editorClearColor[3]);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(1.3f);
/*
glEnable(GL_TEXTURE_3D);
glEnable(GL_MULTISAMPLE);
glLineWidth(2);
*/
glGenBuffers(1, &projUBO);
glBindBuffer(GL_UNIFORM_BUFFER, projUBO);
glBufferData(GL_UNIFORM_BUFFER, 64, NULL, GL_DYNAMIC_DRAW);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, projUBO, 0,
sizeof(float) * 16);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
shader_setUBO(spriteShader, "Projection", 0);
shader_setUBO(textShader, "Projection", 0);
shader_setUBO(animSpriteShader, "Projection", 0);
}
void openglRender(struct mCamera *mcamera)
{
//////////// 2D projection
mfloat_t projection[16] = { 0.f };
mat4_ortho(projection, mcamera->transform.position[0],
window->width + mcamera->transform.position[0],
mcamera->transform.position[1],
window->height + mcamera->transform.position[1], -1.f, 1.f);
glBindBuffer(GL_UNIFORM_BUFFER, projUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, 64, projection);
/*
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glCullFace(GL_BACK);
*/
// Clear color and depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
////// TEXT && GUI
/*
glDepthFunc(GL_ALWAYS);
shader_use(textShader);
shader_setmat4(textShader, "projection", window->projection);
*/
/*
mfloat_t fontpos[2] = { 25.f, 25.f };
mfloat_t fontcolor[3] = { 0.5f, 0.8f, 0.2f };
renderText(stdFont, textShader, "Sample text", fontpos, 0.4f, fontcolor, -1.f);
*/
for (int i = 0; i < numSprites; i++) {
sprite_draw(sprites[i]);
}
//glDepthFunc(GL_LESS);
}
void openglInit3d(struct mSDLWindow *window)
{
//Initialize SDL
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"SDL could not initialize! SDL Error: %s", SDL_GetError());
}
//Use OpenGL 3.3
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2); /* How many x MSAA */
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
// TODO: Add non starter initializtion return here for some reason?
MakeSDLWindow("Untitled Game", 1280, 720,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN |
SDL_WINDOW_RESIZABLE);
//Use Vsync
if (!SDL_GL_SetSwapInterval(1)) {
YughLog(0, SDL_LOG_PRIORITY_WARN,
"Unable to set VSync! SDL Error: %s", SDL_GetError());
}
/* TODO: IMG init doesn't work in C+
int init =(0x00000001 | 0x00000002);
int initted =IMG_Init(init);
YughLog(0, SDL_LOG_PRIORITY_ERROR, "Init flags: %d\nInitted values: %d ", init, initted);
if ((initted & (IMG_INIT_JPG | IMG_INIT_PNG)) != (IMG_INIT_JPG | IMG_INIT_PNG)) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"IMG_Init: Failed to init required jpg and png support! SDL_IMG error: %s",
IMG_GetError());
}
*/
////// MAKE SHADERS
outlineShader = MakeShader("outlinevert.glsl", "outline.glsl");
diffuseShader = MakeShader("simplevert.glsl", "albedofrag.glsl");
modelShader = MakeShader("modelvert.glsl", "modelfrag.glsl");
shadowShader = MakeShader("shadowvert.glsl", "shadowfrag.glsl");
textShader = MakeShader("textvert.glsl", "textfrag.glsl");
spriteShader = MakeShader("spritevert.glsl", "spritefrag.glsl");
debugDepthQuad = MakeShader("postvert.glsl", "debugdepthfrag.glsl");
debugColorPickShader =
MakeShader("simplevert.glsl", "debugcolorfrag.glsl");
debugGridShader = MakeShader("gridvert.glsl", "gridfrag.glsl");
debugGizmoShader = MakeShader("gizmovert.glsl", "gizmofrag.glsl");
stdFont = MakeFont("notosans.ttf", 300);
shader_compile_all();
mat4_perspective_fov(proj, editorFOV * DEG2RADS, window->width,
window->height, editorClose, editorFar);
glEnable(GL_STENCIL_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_3D);
glEnable(GL_MULTISAMPLE);
glLineWidth(2);
////
// Shadow mapping buffers
////
glGenFramebuffers(1, &depthMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, SHADOW_WIDTH,
SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, depthMap, 0);
glDrawBuffer(GL_NONE);
//glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//// Universal buffer to hold projection and light coordinates
glGenBuffers(1, &UBO);
glBindBuffer(GL_UNIFORM_BUFFER, UBO);
glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(proj), NULL,
GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, UBO, 0, 2 * sizeof(proj));
glBindBuffer(GL_UNIFORM_BUFFER, UBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(proj), proj);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
////// debug color pick buffer
glGenFramebuffers(1, &debugColorPickBO);
glBindFramebuffer(GL_FRAMEBUFFER, debugColorPickBO);
glGenTextures(1, &debugColorPickTEX);
glBindTexture(GL_TEXTURE_2D, debugColorPickTEX);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCREEN_WIDTH, SCREEN_HEIGHT, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, debugColorPickTEX, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//////// Create grid
float gridVertices[] = {
-1.f, 0.f, 1.f, 0.f, 1.f,
-1.f, 0.f, -1.f, 0.f, 0.f,
1.f, 0.f, 1.f, 1.f, 1.f,
1.f, 0.f, -1.f, 1.f, 0.f,
};
glGenVertexArrays(1, &gridVAO);
glGenBuffers(1, &gridVBO);
glBindVertexArray(gridVAO);
glBindBuffer(GL_ARRAY_BUFFER, gridVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(gridVertices), &gridVertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float),
(void *) 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float),
(void *) (3 * sizeof(float)));
//////// Create post quad
float quadVertices[] = {
// positions // texture Coords
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
};
// setup plane VAO
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float),
(void *) 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float),
(void *) (3 * sizeof(float)));
//////
// skybox = new Skybox("skybox");
BindUniformBlock(modelShader->id, "Matrices", 0);
BindUniformBlock(outlineShader->id, "Matrices", 0);
// BindUniformBlock(skybox->shader->id, "Matrices", 0);
BindUniformBlock(diffuseShader->id, "Matrices", 0);
BindUniformBlock(debugGridShader->id, "Matrices", 0);
BindUniformBlock(debugGizmoShader->id, "Matrices", 0);
shader_use(debugDepthQuad);
shader_setint(debugDepthQuad, "depthMap", 0);
glBindTexture(GL_TEXTURE_2D, 0);
//////////// 2D projection
mfloat_t projection[16] = { 0.f };
mat4_ortho(projection, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT, 1.f, -1.f,
1.f);
shader_setmat4(textShader, "projection", projection);
shader_setmat4(spriteShader, "projection", projection);
shader_setmat4(debugGizmoShader, "proj", projection);
}
void openglRender3d(struct mSDLWindow *window, struct mCamera *mcamera)
{
//////// SET NEW PROJECTION
// TODO: Make this not happen every frame
mat4_perspective_fov(proj, editorFOV * DEG2RADS, window->width,
window->height, editorClose, editorFar);
glBindBuffer(GL_UNIFORM_BUFFER, UBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(proj), proj);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
////////// Render a depthmap from the perspective of the directional light
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glCullFace(GL_BACK);
glClear(GL_DEPTH_BUFFER_BIT);
// Configure matrices with an orthogonal
mfloat_t lightView[16] = { 0.f };
mfloat_t lightSpaceMatrix[16] = { 0.f };
/*
if (dLight) {
mfloat_t lightProjection[16] = { 0.f };
mat4_ortho(lightProjection, -plane_size, plane_size, -plane_size,
plane_size, near_plane, far_plane);
mfloat_t lookPos[3] = { 0.f };
mfloat_t cam_fwd[3] = { 0.f };
vec3_add(lookPos, mcamera->transform.position,
vec3_multiply_f(lookPos,
trans_forward(cam_fwd,
&mcamera->transform),
shadowLookahead));
lookPos[1] = 0.f;
mfloat_t lightLookPos[3] = { 0.f };
mfloat_t light_fwd[3] = { 0.f };
mat4_look_at(lightView,
vec3_subtract(lightLookPos, lookPos,
trans_forward(light_fwd,
&dLight->light.obj.
transform)), lookPos, UP);
mat4_multiply(lightSpaceMatrix, lightProjection, lightView);
//lightSpaceMatrix = lightProjection * lightView;
if (renderDynamicShadows) {
shader_use(shadowShader);
shader_setmat4(shadowShader, "lightSpaceMatrix",
lightSpaceMatrix);
staticactor_draw_shadowcasters(shadowShader);
}
}
*/
//////////////////////////
// Back to the normal render
window_makecurrent(window);
glCullFace(GL_BACK);
// Render the color thing for debug picking
glBindFramebuffer(GL_FRAMEBUFFER, debugColorPickBO);
glClearColor(editorClearColor[0], editorClearColor[1],
editorClearColor[2], editorClearColor[3]);
glClear(GL_COLOR_BUFFER_BIT);
shader_use(debugColorPickShader);
staticactor_draw_dbg_color_pick(debugColorPickShader);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Clear color and depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
if (renderMode == DIRSHADOWMAP) {
// render Depth map to quad for visual debugging
// ---------------------------------------------
shader_use(debugDepthQuad);
shader_setfloat(debugDepthQuad, "near_plane", near_plane);
shader_setfloat(debugDepthQuad, "far_plane", far_plane);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthMap);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
} else if (renderMode == OBJECTPICKER) {
// TODO: This rendering mode
shader_use(debugColorPickShader);
} else {
glClearColor(editorClearColor[0], editorClearColor[1],
editorClearColor[2], editorClearColor[3]);
glDepthMask(GL_TRUE);
mfloat_t view[16] = { 0.f };
getviewmatrix(view, mcamera);
glBindBuffer(GL_UNIFORM_BUFFER, UBO);
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(view), sizeof(view),
view);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
switch (renderMode) {
case LIT:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
shader_use(modelShader);
/*
if (dLight)
dlight_prepshader(dLight, modelShader);
pointlights_prepshader(modelShader);
spotlights_prepshader(modelShader);
*/
shader_setvec3(modelShader, "viewPos",
mcamera->transform.position);
shader_setmat4(modelShader, "lightSpaceMatrix",
lightSpaceMatrix);
shader_setint(modelShader, "shadowMap", 12);
glActiveTexture(GL_TEXTURE);
glBindTexture(GL_TEXTURE_2D, depthMap);
staticactor_draw_models(modelShader);
break;
case UNLIT:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
shader_use(diffuseShader);
staticactor_draw_models(diffuseShader);
break;
case WIREFRAME:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
shader_use(diffuseShader);
staticactor_draw_models(diffuseShader);
break;
}
//// skybox
// draw skybox as last
glDepthFunc(GL_LEQUAL);
// skybox->Draw(mcamera);
glDepthFunc(GL_LESS);
if (debugDrawPhysics) {
// Render physics world
//dynamicsWorld->debugDrawWorld();
}
// Draw outline
if (selectedobject != NULL) {
// Draw the selected object outlined
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glDepthFunc(GL_ALWAYS);
glDepthMask(false);
glColorMask(false, false, false, false);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFF);
shader_use(diffuseShader);
setup_model_transform(&selectedobject->transform,
diffuseShader, 1.f);
//selectedobject->draw(diffuseShader);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glDepthMask(true);
glColorMask(true, true, true, true);
glStencilMask(0x00);
shader_use(outlineShader);
setup_model_transform(&selectedobject->transform,
outlineShader, 1.f);
//selectedobject->draw(outlineShader);
}
glDepthFunc(GL_LESS);
glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 0, 0xFF);
}
////// TEXT && GUI
// glCullFace(GL_FRONT);
glDepthFunc(GL_ALWAYS);
shader_use(textShader);
shader_setmat4(textShader, "projection", window->projection);
mfloat_t fontpos[2] = { 25.f, 25.f };
mfloat_t fontcolor[3] = { 0.5f, 0.8f, 0.2f };
renderText(stdFont, textShader, "Sample text", fontpos, 0.4f,
fontcolor, -1.f);
sprite_draw(tsprite);
glDepthFunc(GL_LESS);
////// Render grid
if (showGrid) {
glDisable(GL_CULL_FACE);
shader_use(debugGridShader);
mfloat_t gmodel[16] = { 0.f };
mfloat_t gridscale[3] = { 0.f };
vec3(gridscale, gridScale, gridScale, gridScale);
mat4_multiply_f(gmodel, gmodel, gridScale);
// TODO: Hook into here to make the grid scalable
shader_setmat4(debugGridShader, "model", gmodel);
shader_setvec3(debugGridShader, "smallColor", gridSmallColor);
shader_setvec3(debugGridShader, "bigColor", gridBigColor);
shader_setfloat(debugGridShader, "gridScale", gridScale);
shader_setfloat(debugGridShader, "smallUnit", smallGridUnit);
shader_setfloat(debugGridShader, "bigUnit", bigGridUnit);
shader_setfloat(debugGridShader, "smallThickness",
gridSmallThickness);
shader_setfloat(debugGridShader, "largeThickness",
gridBigThickness);
shader_setfloat(debugGridShader, "opacity", gridOpacity);
glBindVertexArray(gridVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
}
///// Render gizmos
// These are things that are overlaid on everything else
// glBindFramebuffer(GL_FRAMEBUFFER, 0); // back to default
// glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// glClear(GL_COLOR_BUFFER_BIT);
// postShader.use();
// glBindVertexArray(quadVAO);
// glBindTexture(GL_TEXTURE_2D, fboTexture);
// glDrawArrays(GL_TRIANGLES, 0, 6);
}
void BindUniformBlock(GLuint shaderID, const char *bufferName,
GLuint bufferBind)
{
glUniformBlockBinding(shaderID,
glGetUniformBlockIndex(shaderID, bufferName),
bufferBind);
}

View file

@ -0,0 +1,54 @@
#ifndef OPENGL_RENDER_H
#define OPENGL_RENDER_H
#include "render.h"
struct mCamera;
struct mSDLWindow;
extern struct mShader *spriteShader;
extern struct mShader *animSpriteShader;
extern struct mSprite *tsprite;
extern int renderMode;
extern float editorClose;
extern float editorFar;
extern float gridScale;
extern float smallGridUnit;
extern float bigGridUnit;
extern float gridSmallThickness;
extern float gridBigThickness;
extern float gridBigColor[];
extern float gridSmallColor[];
extern float gridOpacity;
extern float editorFOV;
extern float shadowLookahead;
extern float plane_size;
extern float near_plane;
extern float far_plane;
extern char objectName[];
extern uint16_t debugColorPickBO;
extern struct mGameObject *selectedobject;
enum RenderMode {
LIT,
UNLIT,
WIREFRAME,
DIRSHADOWMAP,
OBJECTPICKER
};
void openglInit();
void openglRender(struct mCamera *camera);
void openglInit3d(struct mSDLWindow *window);
void openglRender3d(struct mSDLWindow *window, struct mCamera *camera);
void BindUniformBlock(GLuint shaderID, const char *bufferName,
GLuint bufferBind);
#endif

25
source/engine/pinball.c Normal file
View file

@ -0,0 +1,25 @@
#include "pinball.h"
#include "gameobject.h"
#include "input.h"
struct flipper *pinball_flipper_make(struct mGameObject *go)
{
struct flipper *new = calloc(1, sizeof(struct flipper));
pinball_flipper_init(new, go);
return new;
}
void pinball_flipper_init(struct flipper *flip, struct mGameObject *go)
{
cpBodySetAngle(go->body, flip->angle1);
}
void pinball_flipper_update(struct flipper *flip, struct mGameObject *go)
{
if ((flip->left && currentKeystates[SDL_SCANCODE_LSHIFT])
|| currentKeystates[SDL_SCANCODE_RSHIFT]) {
cpBodySetAngle(go->body, flip->angle2);
} else
cpBodySetAngle(go->body, flip->angle1);
}

18
source/engine/pinball.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef PINBALL_H
#define PINBALL_H
struct mGameObject;
struct flipper {
float angle1;
float angle2;
float flipspeed;
int left;
};
struct flipper *pinball_flipper_make(struct mGameObject *go);
void pinball_flipper_init(struct flipper *flip, struct mGameObject *go);
void pinball_flipper_update(struct flipper *flip, struct mGameObject *go);
#endif

53
source/engine/registry.c Normal file
View file

@ -0,0 +1,53 @@
#include "registry.h"
#include "gameobject.h"
#include "2dphysics.h"
#include "editor.h"
#include "sprite.h"
#include "pinball.h"
struct component components[MAXNAME] = { 0 };
int ncomponent = 0;
void registry_init()
{
register_component("Sprite", sizeof(struct mSprite), &MakeSprite, NULL,
sprite_gui, &sprite_init, NULL);
register_component("2D Circle Collider", sizeof(struct phys2d_circle),
&Make2DCircle, &phys2d_dbgdrawcircle, &circle_gui,
&phys2d_circleinit, NULL);
register_component("2D Segment", sizeof(struct phys2d_segment),
&Make2DSegment, &phys2d_dbgdrawseg, &segment_gui,
&phys2d_seginit, NULL);
register_component("2D Box", sizeof(struct phys2d_box), &Make2DBox,
&phys2d_dbgdrawbox, &box_gui, &phys2d_boxinit,
NULL);
register_component("2D Polygon", sizeof(struct phys2d_poly),
&Make2DPoly, &phys2d_dbgdrawpoly, &poly_gui,
&phys2d_polyinit, NULL);
register_component("2D Edge", sizeof(struct phys2d_edge), &Make2DEdge,
&phys2d_dbgdrawedge, &edge_gui, &phys2d_edgeinit,
NULL);
register_component("Flipper", sizeof(struct flipper),
&pinball_flipper_make, NULL, &pinball_flipper_gui,
&pinball_flipper_init, &pinball_flipper_update);
}
void register_component(const char *name, size_t size,
void (*make)(struct mGameObject * go,
struct component * c),
void(*draw_debug)(void *data),
void(*draw_gui)(void *data),
void(*init)(void *data, struct mGameObject * go),
void(*update)(void *data, struct mGameObject * go))
{
struct component *c = &components[ncomponent++];
c->name = name;
c->make = make;
c->draw_debug = draw_debug;
c->draw_gui = draw_gui;
c->init = init;
c->data = NULL;
c->id = ncomponent - 1;
c->datasize = size;
}

35
source/engine/registry.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef REGISTRY_H
#define REGISTRY_H
#include <stddef.h>
#include "config.h"
struct mGameObject;
struct component {
const char *name;
void *(*make)(struct mGameObject * go);
void *data;
struct mGameObject *go;
void (*draw_debug)(void *data);
void (*draw_gui)(void *data);
void (*update)(void *data, struct mGameObject * go);
int id;
int datasize;
void (*init)(void *data, struct mGameObject * go);
};
extern struct component components[MAXNAME];
extern int ncomponent;
void registry_init();
void register_component(const char *name, size_t size,
void (*make)(struct mGameObject * go,
struct component * c),
void(*draw_debug)(void *data),
void(*draw_gui)(void *data),
void(*init)(void *data, struct mGameObject * go),
void(*update)(void *data,
struct mGameObject * go));
#endif

0
source/engine/render.c Normal file
View file

9
source/engine/render.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef RENDER_H
#define RENDER_H
#define GL_GLEXT_PROTOTYPES
#include <GL/glew.h>
#include <SDL_opengl.h>
#endif

112
source/engine/resources.c Normal file
View file

@ -0,0 +1,112 @@
#include "resources.h"
#include "config.h"
#include <dirent.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "vec.h"
#include <ftw.h>
#include <stdarg.h>
#include <stdio.h>
char *DATA_PATH = NULL;
char *PREF_PATH = NULL;
struct vec *prefabs = NULL;
const char *EXT_PREFAB = ".prefab";
const char *EXT_LEVEL = ".level";
int stemlen = 0;
static const char *cur_ext = NULL;
static DIR *cur_dir = NULL;
struct dirent *c_dirent = NULL;
struct vec *c_vec = NULL;
char pathbuf[MAXPATH];
void resources_init()
{
char *dpath = SDL_GetBasePath();
DATA_PATH = malloc(strlen(dpath) + 1);
strcpy(DATA_PATH, dpath);
char *ppath = SDL_GetPrefPath("Odplot", "Test Game");
PREF_PATH = malloc(strlen(ppath) + 1);
strcpy(PREF_PATH, ppath);
}
char *get_filename_from_path(char *path, int extension)
{
char *dirpos = strrchr(path, '/');
if (!dirpos)
dirpos = path;
char *end = strrchr(path, '\0');
int offset = 0;
if (!extension) {
char *ext = strrchr(path, '.');
offset = end - ext;
printf("Making without extension ...\n");
}
char *filename =
(char *) malloc(sizeof(char) * (end - dirpos - offset + 1));
strncpy(filename, dirpos, end - dirpos - offset);
return filename;
}
char *get_directory_from_path(char *path)
{
const char *dirpos = strrchr(path, '/');
char *directory = (char *) malloc(sizeof(char) * (dirpos - path + 1));
strncpy(directory, path, dirpos - path);
return directory;
}
FILE *res_open(char *path, const char *tag)
{
strncpy(pathbuf, DATA_PATH, MAXPATH);
strncat(pathbuf, path, MAXPATH);
FILE *f = fopen(pathbuf, tag);
return f;
}
static int ext_check(const char *path, const struct stat *sb, int typeflag,
struct FTW *ftwbuf)
{
if (typeflag == FTW_F) {
const char *ext = strrchr(path, '.');
if (ext != NULL && !strcmp(ext, cur_ext))
vec_add(c_vec, path);
}
return 0;
}
void fill_extensions(struct vec *vec, char *path, const char *ext)
{
c_vec = vec;
cur_ext = ext;
vec_clear(c_vec);
nftw(path, &ext_check, 10, 0);
}
void findPrefabs()
{
fill_extensions(prefabs, DATA_PATH, EXT_PREFAB);
}
FILE *path_open(const char *fmt, const char *tag, ...)
{
va_list args;
va_start(args, fmt);
vsprintf(pathbuf, fmt, args);
va_end(args);
FILE *f = fopen(pathbuf, tag);
return f;
}

27
source/engine/resources.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef RESOURCES_H
#define RESOURCES_H
#include <stdio.h>
struct vec;
extern char *DATA_PATH;
extern char *PREF_PATH;
extern const char *EXT_PREFAB;
extern const char *EXT_LEVEL;
extern int stemlen;
void resources_init();
extern struct vec *prefabs;
void findPrefabs();
void fill_extensions(struct vec *vec, char *path, const char *ext);
char *get_filename_from_path(char *path, int extension);
char *get_directory_from_path(char *path);
FILE *res_open(char *path, const char *tag);
FILE *path_open(const char *fmt, const char *tag, ...);
#endif

54
source/engine/script.c Normal file
View file

@ -0,0 +1,54 @@
#include "script.h"
#include "gameobject.h"
#include <s7.h>
s7_scheme *s7 = NULL;
s7_pointer s7square(s7_scheme * sc, s7_pointer args)
{
if (s7_is_integer(s7_car(args)))
return (s7_make_integer
(sc, s7_integer(s7_car(args)) * s7_integer(s7_car(args))));
return (s7_wrong_type_arg_error
(sc, "square", 1, s7_car(args), "an integer"));
}
s7_pointer s7move(s7_scheme * sc, s7_pointer args)
{
if (s7_is_number(s7_car(args)) && s7_is_number(s7_cadr(args))) {
gameobject_move(updateGO, s7_real(s7_car(args)),
s7_real(s7_cadr(args)));
return args;
}
return args;
}
s7_pointer s7rotate(s7_scheme * sc, s7_pointer args)
{
if (s7_is_number(s7_car(args))) {
gameobject_rotate(updateGO, s7_real(s7_car(args)));
return (s7_make_real(sc, cpBodyGetAngle(updateGO->body)));
}
return (s7_wrong_type_arg_error
(sc, "rotate", 1, s7_car(args), "a number"));
}
void script_init()
{
s7 = s7_init();
s7_define_function(s7, "square", s7square, 1, 0, 0,
"(square int) squares int");
s7_define_function(s7, "move", s7move, 1, 0, 0,
"(move (xs ys)) moves at xs and ys pixels per second");
s7_define_function(s7, "rotate", s7rotate, 1, 0, 0,
"(rotate ms) rotates at ms meters per second");
}
void script_run(const char *script)
{
s7_eval_c_string(s7, script);
}

10
source/engine/script.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef SCRIPT_H
#define SCRIPT_H
struct s7_scheme;
extern struct s7_scheme *s7;
void script_init();
void script_run(const char *script);
#endif

176
source/engine/shader.c Normal file
View file

@ -0,0 +1,176 @@
#include "shader.h"
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "log.h"
#include "resources.h"
#include <GL/glew.h>
#define SHADER_BUF 10000
struct mShader *mshaders[255];
struct mShader **lastShader = mshaders;
struct mShader *MakeShader(const char *vertpath, const char *fragpath)
{
struct mShader init = { 0, vertpath, fragpath };
struct mShader *newshader =
(struct mShader *) malloc(sizeof(struct mShader));
memcpy(newshader, &init, sizeof(*newshader));
*lastShader++ = newshader;
shader_compile(newshader);
return newshader;
}
int shader_compile_error(GLuint shader)
{
GLint success = 0;
GLchar infoLog[ERROR_BUFFER] = { '\0' };
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (success) return 0;
glGetShaderInfoLog(shader, ERROR_BUFFER, NULL, infoLog);
YughLog(0, SDL_LOG_PRIORITY_ERROR, "Shader compilation error.\nLog: %s", infoLog);
return 1;
}
int shader_link_error(GLuint shader)
{
GLint success = 0;
GLchar infoLog[ERROR_BUFFER] = { '\0' };
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (success) return 0;
glGetProgramInfoLog(shader, ERROR_BUFFER, NULL, infoLog);
YughLog(0, SDL_LOG_PRIORITY_ERROR, "Shader link error.\nLog: %s", infoLog);
return 1;
}
GLuint load_shader_from_file(char *path, int type)
{
char spath[MAXPATH] = {'\0'};
sprintf(spath, "%s%s%s", DATA_PATH, "shaders/", path);
FILE *f = fopen(spath, "r'");
if (!path)
perror(spath), exit(1);
char buf[SHADER_BUF] = {'\0'};
long int fsize;
fseek(f, 0, SEEK_END);
fsize = ftell(f);
rewind(f);
fread(buf, fsize, 1, f);
fclose(f);
GLuint id = glCreateShader(type);
const char *code = buf;
glShaderSource(id, 1, &code, NULL);
glCompileShader(id);
if ( shader_compile_error(id))
return 0;
return id;
}
void shader_compile(struct mShader *shader)
{
GLuint vert = load_shader_from_file(shader->vertpath, GL_VERTEX_SHADER);
GLuint frag = load_shader_from_file(shader->fragpath, GL_FRAGMENT_SHADER);
shader->id = glCreateProgram();
glAttachShader(shader->id, vert);
glAttachShader(shader->id, frag);
glLinkProgram(shader->id);
shader_link_error(shader->id);
glDeleteShader(vert);
glDeleteShader(frag);
}
void shader_use(struct mShader *shader)
{
glUseProgram(shader->id);
}
void shader_setbool(struct mShader *shader, const char *name, int val)
{
glUniform1i(glGetUniformLocation(shader->id, name), val);
}
void shader_setint(struct mShader *shader, const char *name, int val)
{
glUniform1i(glGetUniformLocation(shader->id, name), val);
}
void shader_setfloat(struct mShader *shader, const char *name, float val)
{
glUniform1f(glGetUniformLocation(shader->id, name), val);
}
void shader_setvec2(struct mShader *shader, const char *name,
mfloat_t val[2])
{
glUniform2fv(glGetUniformLocation(shader->id, name), 1, val);
}
void shader_setvec3(struct mShader *shader, const char *name,
mfloat_t val[3])
{
glUniform3fv(glGetUniformLocation(shader->id, name), 1, val);
}
void shader_setvec4(struct mShader *shader, const char *name,
mfloat_t val[4])
{
glUniform4fv(glGetUniformLocation(shader->id, name), 1, val);
}
void shader_setmat2(struct mShader *shader, const char *name,
mfloat_t val[4])
{
glUniformMatrix2fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE,
val);
}
void shader_setmat3(struct mShader *shader, const char *name,
mfloat_t val[9])
{
glUniformMatrix3fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE,
val);
}
void shader_setmat4(struct mShader *shader, const char *name,
mfloat_t val[16])
{
shader_use(shader);
glUniformMatrix4fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE,
val);
}
void shader_setUBO(struct mShader *shader, const char *name,
unsigned int index)
{
glUniformBlockBinding(shader->id,
glGetUniformBlockIndex(shader->id, name), index);
}
void shader_compile_all()
{
struct mShader **curshader = mshaders;
do {
YughLog(0, SDL_LOG_PRIORITY_INFO, "Compiled Shader %d", 1);
shader_compile(*curshader);
} while (++curshader != lastShader);
}

37
source/engine/shader.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef SHADER_H
#define SHADER_H
#include "mathc.h"
struct mShader {
unsigned int id;
const char *vertpath;
const char *fragpath;
};
void shader_compile_all();
struct mShader *MakeShader(const char *vertpath, const char *fragpath);
void shader_compile(struct mShader *shader);
void shader_use(struct mShader *shader);
void shader_setbool(struct mShader *shader, const char *name, int val);
void shader_setint(struct mShader *shader, const char *name, int val);
void shader_setfloat(struct mShader *shader, const char *name, float val);
void shader_setvec2(struct mShader *shader, const char *name,
mfloat_t val[2]);
void shader_setvec3(struct mShader *shader, const char *name,
mfloat_t val[3]);
void shader_setvec4(struct mShader *shader, const char *name,
mfloat_t val[4]);
void shader_setmat2(struct mShader *shader, const char *name,
mfloat_t val[4]);
void shader_setmat3(struct mShader *shader, const char *name,
mfloat_t val[9]);
void shader_setmat4(struct mShader *shader, const char *name,
mfloat_t val[16]);
void shader_setUBO(struct mShader *shader, const char *name,
unsigned int index);
#endif

123
source/engine/skybox.c Normal file
View file

@ -0,0 +1,123 @@
#include "skybox.h"
#include "shader.h"
#include "camera.h"
#include <SDL_image.h>
#include <string.h>
#include "openglrender.h"
static const float skyboxVertices[216] = {
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
struct mSkybox *MakeSkybox(const char *cubemap)
{
struct mSkybox *newskybox =
(struct mSkybox *) malloc(sizeof(struct mSkybox));
newskybox->shader = MakeShader("skyvert.glsl", "skyfrag.glsl");
shader_compile(newskybox->shader);
glGenVertexArrays(1, &newskybox->VAO);
glGenBuffers(1, &newskybox->VBO);
glBindVertexArray(newskybox->VAO);
glBindBuffer(GL_ARRAY_BUFFER, newskybox->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),
(void *) 0);
shader_use(newskybox->shader);
shader_setint(newskybox->shader, "skybox", 0);
const char *faces[6] =
{ "right.jpg", "left.jpg", "top.jpg", "bottom.jpg", "front.jpg",
"back.jpg"
};
glGenTextures(1, &newskybox->id);
glBindTexture(GL_TEXTURE_CUBE_MAP, newskybox->id);
char buf[100] = { '\0' };
for (unsigned int i = 0; i < 6; i++) {
buf[0] = '\0';
strcat(buf, cubemap);
strcat(buf, "/");
strcat(buf, faces[i]);
SDL_Surface *data = NULL; //IMG_Load(buf);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 2048,
2048, 0, GL_RGB, GL_UNSIGNED_BYTE, data->pixels);
SDL_FreeSurface(data);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R,
GL_CLAMP_TO_EDGE);
return newskybox;
}
void skybox_draw(const struct mSkybox *skybox,
const struct mCamera *camera)
{
shader_use(skybox->shader);
mfloat_t view[16] = { 0.f };
getviewmatrix(view, camera);
shader_setmat4(skybox->shader, "skyview", view);
// skybox cube
glBindVertexArray(skybox->VAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->id);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
}

17
source/engine/skybox.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef SKYBOX_H
#define SKYBOX_H
struct mCamera;
struct mSkybox {
unsigned int VAO;
unsigned int VBO;
unsigned int id;
struct mShader *shader;
};
struct mSkybox *MakeSkybox(const char *cubemap);
void skybox_draw(const struct mSkybox *skybox,
const struct mCamera *camera);
#endif

206
source/engine/sprite.c Normal file
View file

@ -0,0 +1,206 @@
#include "sprite.h"
#include "render.h"
#include "openglrender.h"
#include "texture.h"
#include "shader.h"
#include "datastream.h"
#include "gameobject.h"
#include <string.h>
/*
static struct mShader *spriteShader = NULL;
static struct mShader *animSpriteShader = NULL;
*/
struct TextureOptions TEX_SPRITE = { 1, 0 };
struct mSprite *sprites[100] = { NULL };
int numSprites = 0;
static uint32_t quadVAO;
static uint32_t VBO;
struct mSprite *MakeSprite(struct mGameObject *go)
{
struct mSprite *sprite = malloc(sizeof(struct mSprite));
sprites[numSprites++] = sprite;
sprite->color[0] = 1.f;
sprite->color[1] = 1.f;
sprite->color[2] = 1.f;
sprite->pos[0] = 0.f;
sprite->pos[1] = 0.f;
sprite->size[0] = 1.f;
sprite->size[1] = 1.f;
sprite->tex = NULL;
sprite_init(sprite, go);
return sprite;
}
void sprite_init(struct mSprite *sprite, struct mGameObject *go)
{
sprite->go = go;
}
void sprite_loadtex(struct mSprite *sprite, const char *path)
{
sprite->tex = texture_loadfromfile(sprite->tex, path);
}
void sprite_loadanim(struct mSprite *sprite, const char *path,
struct Anim2D anim)
{
sprite->tex = texture_loadfromfile(sprite->tex, path);
sprite->anim = anim;
sprite->anim.timer =
SDL_AddTimer(sprite->anim.ms, incrementAnimFrame, sprite);
/*
sprite->tex = texture_loadanimfromfile(sprite->tex, path, sprite->anim.frames,
sprite->anim.dimensions);
*/
}
Uint32 incrementAnimFrame(Uint32 interval, struct mSprite *sprite)
{
sprite->anim.frame = (sprite->anim.frame + 1) % sprite->anim.frames;
return interval;
}
// TODO: This should be done once for all sprites
void sprite_initialize()
{
uint32_t VBO;
float vertices[] = {
// pos
0.f, 0.f,
1.0f, 0.0f,
0.f, 1.f,
1.f, 1.f
};
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &VBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void sprite_draw(struct mSprite *sprite)
{
if (sprite->tex != NULL) {
shader_use(spriteShader);
mfloat_t model[16] = { 0.f };
mfloat_t r_model[16] = { 0.f };
mfloat_t s_model[16] = { 0.f };
memcpy(model, UNITMAT4, sizeof(UNITMAT4));
memcpy(r_model, UNITMAT4, sizeof(UNITMAT4));
memcpy(s_model, UNITMAT4, sizeof(UNITMAT4));
mfloat_t t_move[2] = { 0.f };
mfloat_t t_scale[2] = { 0.f };
t_scale[0] =
sprite->size[0] * sprite->tex->width * sprite->go->scale;
t_scale[1] =
sprite->size[1] * sprite->tex->height * sprite->go->scale;
t_move[0] = sprite->pos[0] * t_scale[0];
t_move[1] = sprite->pos[1] * t_scale[1];
mat4_translate_vec2(model, t_move);
mat4_scale_vec2(model, t_scale);
mat4_rotation_z(r_model, cpBodyGetAngle(sprite->go->body));
mat4_multiply(model, r_model, model);
cpVect pos = cpBodyGetPosition(sprite->go->body);
t_move[0] = pos.x;
t_move[1] = pos.y;
mat4_translate_vec2(model, t_move);
shader_setmat4(spriteShader, "model", model);
shader_setvec3(spriteShader, "spriteColor", sprite->color);
//tex_bind(sprite->tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, sprite->tex->id);
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
void spriteanim_draw(struct mSprite *sprite)
{
shader_use(animSpriteShader);
mfloat_t model[16] = { 0.f };
memcpy(model, UNITMAT4, sizeof(UNITMAT4));
mat4_translate_vec2(model, sprite->pos);
mfloat_t msize[2] =
{ sprite->size[0] * sprite->anim.dimensions[0],
sprite->size[1] * sprite->anim.dimensions[1] };
mat4_scale_vec2(model, msize);
shader_setmat4(animSpriteShader, "model", model);
shader_setvec3(animSpriteShader, "spriteColor", sprite->color);
shader_setfloat(animSpriteShader, "frame", sprite->anim.frame);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, sprite->tex->id);
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void video_draw(struct datastream *stream, mfloat_t position[2],
mfloat_t size[2], float rotate, mfloat_t color[3])
{
shader_use(spriteShader);
static mfloat_t model[16];
memcpy(model, UNITMAT4, sizeof(UNITMAT4));
mat4_translate_vec2(model, position);
mat4_scale_vec2(model, size);
shader_setmat4(spriteShader, "model", model);
shader_setvec3(spriteShader, "spriteColor", color);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, stream->texture_y);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, stream->texture_cb);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, stream->texture_cr);
// TODO: video bind VAO
//glBindVertexArray(stream->quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
}

47
source/engine/sprite.h Normal file
View file

@ -0,0 +1,47 @@
#ifndef SPRITE_H
#define SPRITE_H
#include <SDL_timer.h>
#include "mathc.h"
struct datastream;
struct mGameObject;
struct Anim2D {
int frames;
int frame;
int dimensions[2];
SDL_TimerID timer;
int ms;
};
struct mSprite {
struct Texture *tex;
mfloat_t pos[2];
mfloat_t size[2];
float rotation;
mfloat_t color[3];
struct Anim2D anim;
struct mGameObject *go;
};
extern struct mSprite *sprites[100];
extern int numSprites;
struct mSprite *MakeSprite(struct mGameObject *go);
void sprite_init(struct mSprite *sprite, struct mGameObject *go);
void sprite_loadtex(struct mSprite *sprite, const char *path);
void sprite_loadanim(struct mSprite *sprite, const char *path,
struct Anim2D anim);
void sprite_initalize();
void sprite_draw(struct mSprite *sprite);
void spriteanim_draw(struct mSprite *sprite);
void video_draw(struct datastream *ds, mfloat_t pos[2], mfloat_t size[2],
float rotate, mfloat_t color[3]);
Uint32 incrementAnimFrame(Uint32 interval, struct mSprite *sprite);
void sprite_draw_all();
#endif

View file

@ -0,0 +1,77 @@
#include "static_actor.h"
#include "editorstate.h"
//ADDMAKE(StaticActor);
static struct mStaticActor *models[100];
static int numModels = 0;
static struct mStaticActor *shadow_casters[100];
static int numShadowCasters = 0;
struct mStaticActor *curActor = NULL;
void staticactor_draw_dbg_color_pick(struct mShader *s)
{
for (int i = 0; i < numModels; i++) {
shader_setvec3(s, "PickingColor", models[i]->obj.editor.color);
setup_model_transform(&models[i]->obj.transform, s, 1.f);
//models[i]->obj.draw(s);
}
}
void staticactor_draw_models(struct mShader *s)
{
for (int i = 0; i < numModels; i++) {
setup_model_transform(&models[i]->obj.transform, s, 1.f);
draw_model(models[i]->model, s);
}
}
void staticactor_draw_shadowcasters(struct mShader *s)
{
for (int i = 0; i < numShadowCasters; i++) {
setup_model_transform(&shadow_casters[i]->obj.transform, s, 1.f);
//models[i]->obj.draw(s);
}
}
/*
void StaticActor::serialize(FILE * file)
{
GameObject::serialize(file);
SerializeBool(file, &castShadows);
Serializecstr(file, currentModelPath);
}
void StaticActor::deserialize(FILE * file)
{
GameObject::deserialize(file);
DeserializeBool(file, &castShadows);
Deserializecstr(file, currentModelPath, MAXPATH);
curActor = this;
set_new_model(currentModelPath);
}
*/
struct mStaticActor *MakeStaticActor(const char *modelPath)
{
struct mStaticActor *newsa =
(struct mStaticActor *) malloc(sizeof(struct mStaticActor));
newsa->model = GetExistingModel(modelPath);
models[numModels++] = newsa;
return newsa;
}
/*
Serialize *make_staticactor()
{
StaticActor *nactor = (StaticActor *) malloc(sizeof(StaticActor));
return nactor;
}
*/

View file

@ -0,0 +1,24 @@
#ifndef STATIC_ACTOR_H
#define STATIC_ACTOR_H
#include "gameobject.h"
#include "model.h"
#include "shader.h"
struct mStaticActor {
struct mGameObject obj;
struct mModel *model;
char *modelPath;
char currentModelPath[MAXPATH];
bool castShadows;
};
void staticactor_draw_dbg_color_pick(struct mShader *s);
void staticactor_draw_models(struct mShader *s);
void staticactor_draw_shadowcasters(struct mShader *s);
struct mStaticActor *MakeStaticActor();
extern struct mStaticActor *curActor;
#endif

265
source/engine/texture.c Normal file
View file

@ -0,0 +1,265 @@
#include "texture.h"
#define STBI_FAILURE_USERMSG
#include <stdio.h>
#include <stb_image.h>
#include <stb_ds.h>
#include <GL/glew.h>
#include <SDL_image.h>
#include "log.h"
static struct {
char *key;
struct Texture *value;
} *texhash = NULL;
struct Texture *texture_loadfromfile(struct Texture *tex, const char *path)
{
int index = shgeti(texhash, path);
if (index != -1)
return texhash[index].value;
tex = calloc(1, sizeof(*tex));
tex->path = malloc(strlen(path) + 1);
strncpy(tex->path, path, strlen(path) + 1);
tex->flipy = 0;
tex->opts.sprite = 1;
tex->opts.gamma = 0;
tex->anim.frames = 1;
tex->anim.ms = 1;
glGenTextures(1, &tex->id);
uint8_t n;
stbi_set_flip_vertically_on_load(0);
tex->data = stbi_load(tex->path, &tex->width, &tex->height, &n, 4);
if (stbi_failure_reason())
YughLog(0, 3, "STBI failed to load file %s with message: %s",
tex->path, stbi_failure_reason());
shput(texhash, tex->path, tex);
tex_gpu_load(tex);
return tex;
}
void tex_reload(struct Texture *tex)
{
tex_free(tex);
tex_gpu_load(tex);
}
void tex_gpu_load(struct Texture *tex)
{
if (tex->anim.frames >= 0) {
glBindTexture(GL_TEXTURE_2D, tex->id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->width, tex->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, tex->data);
glGenerateMipmap(GL_TEXTURE_2D);
if (tex->opts.sprite) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
} else {
glBindTexture(GL_TEXTURE_2D_ARRAY, tex->id);
glTexImage3D(GL_TEXTURE_2D_ARRAY,
0,
GL_RGBA,
tex->anim.dimensions[0],
tex->anim.dimensions[1],
tex->anim.frames, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
SDL_Surface *loadedSurface =
SDL_CreateRGBSurfaceFrom(tex->data, tex->width, tex->height,
32, (4 * tex->width),
0x000000ff, 0x0000ff00, 0x00ff0000,
0xff000000);
SDL_Surface *tempSurface;
tempSurface =
SDL_CreateRGBSurfaceWithFormat(0, tex->anim.dimensions[0],
tex->anim.dimensions[1], 32,
SDL_PIXELFORMAT_RGBA32);
SDL_Rect srcRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = tex->anim.dimensions[0];
srcRect.h = tex->anim.dimensions[1];
for (int i = 0; i < tex->anim.frames; i++) {
srcRect.x = i * srcRect.w;
SDL_FillRect(tempSurface, NULL, 0x000000);
TestSDLError(SDL_BlitSurface
(loadedSurface, &srcRect, tempSurface, NULL));
//SDL_UnlockSurface(tempSurface);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i,
tex->anim.dimensions[0],
tex->anim.dimensions[1], 1, GL_RGBA,
GL_UNSIGNED_BYTE, tempSurface->pixels);
}
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
SDL_FreeSurface(loadedSurface);
SDL_FreeSurface(tempSurface);
}
}
Uint32 tex_incr_anim(Uint32 interval, struct TexAnimation *tex_anim)
{
anim_incr(tex_anim);
if (!tex_anim->tex->anim.loop
&& tex_anim->frame == tex_anim->tex->anim.frames)
anim_pause(tex_anim);
return interval;
}
void anim_incr(struct TexAnimation *anim)
{
anim->frame = (anim->frame + 1) % anim->tex->anim.frames;
tex_anim_calc_uv(anim);
}
void anim_decr(struct TexAnimation *anim)
{
anim->frame =
(anim->frame + anim->tex->anim.frames -
1) % anim->tex->anim.frames;
tex_anim_calc_uv(anim);
}
void tex_anim_set(struct TexAnimation *anim)
{
if (anim->playing) {
SDL_RemoveTimer(anim->timer);
anim->timer =
SDL_AddTimer(floor(1000.f / anim->tex->anim.ms), tex_incr_anim,
anim);
}
tex_anim_calc_uv(anim);
}
void tex_free(struct Texture *tex)
{
if (tex->id != 0) {
glDeleteTextures(1, &tex->id);
tex->id = 0;
}
}
void tex_anim_calc_uv(struct TexAnimation *anim)
{
struct Rect uv;
uv.w = 1.f / anim->tex->anim.frames;
uv.h = 1.f;
uv.y = 0.f;
uv.x = uv.w * (anim->frame);
anim->uv = uv;
}
unsigned int powof2(unsigned int num)
{
if (num != 0) {
num--;
num |= (num >> 1);
num |= (num >> 2);
num |= (num >> 4);
num |= (num >> 8);
num |= (num >> 16);
num++;
}
return num;
}
int ispow2(int num)
{
return (num && !(num & (num - 1)));
}
void tex_bind(struct Texture *tex)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex->id);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex->id);
}
void anim_play(struct TexAnimation *anim)
{
if (anim->playing)
return;
if (anim->frame == anim->tex->anim.frames)
anim->frame = 0;
anim->playing = 1;
SDL_RemoveTimer(anim->timer);
anim->timer =
SDL_AddTimer(floor(1000.f / anim->tex->anim.ms), tex_incr_anim,
anim);
}
void anim_stop(struct TexAnimation *anim)
{
if (!anim->playing)
return;
anim->playing = 0;
anim->frame = 0;
anim->pausetime = 0;
SDL_RemoveTimer(anim->timer);
tex_anim_calc_uv(anim);
}
void anim_pause(struct TexAnimation *anim)
{
if (!anim->playing)
return;
anim->playing = 0;
SDL_RemoveTimer(anim->timer);
}
void anim_fwd(struct TexAnimation *anim)
{
anim_incr(anim);
}
void anim_bkwd(struct TexAnimation *anim)
{
anim_decr(anim);
}

73
source/engine/texture.h Normal file
View file

@ -0,0 +1,73 @@
#ifndef TEXTURE_H
#define TEXTURE_H
#include <SDL_timer.h>
struct Rect {
float x;
float y;
float w;
float h;
};
struct TexAnimation {
int frame;
int playing;
int pausetime;
SDL_TimerID timer;
struct Rect uv;
struct Texture *tex;
};
struct TexAnim {
int frames;
int dimensions[2];
int ms;
int loop;
};
struct TextureOptions {
int sprite;
unsigned int gamma:1;
int animation;
};
struct Texture {
char *type;
unsigned int id;
char *path;
unsigned int width;
unsigned int height;
short flipy;
unsigned char *data;
struct TextureOptions opts;
struct TexAnim anim;
};
struct Texture *texture_loadfromfile(struct Texture *tex,
const char *path);
void tex_gpu_load(struct Texture *tex);
void tex_reload(struct Texture *tex);
void tex_free(struct Texture *tex);
void tex_bind(struct Texture *tex);
unsigned int powof2(unsigned int num);
int ispow2(int num);
void anim_play(struct TexAnimation *anim);
void anim_stop(struct TexAnimation *anim);
void anim_pause(struct TexAnimation *anim);
void anim_fwd(struct TexAnimation *anim);
void anim_bkwd(struct TexAnimation *anim);
void anim_incr(struct TexAnimation *anim);
void anim_decr(struct TexAnimation *anim);
Uint32 tex_incr_anim(Uint32 interval, struct TexAnimation *tex_anim);
void tex_anim_calc_uv(struct TexAnimation *anim);
void tex_anim_set(struct TexAnimation *anim);
#endif

View file

@ -0,0 +1,226 @@
// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit.
#include "thirdpersonfollow.h"
#include <math.h>
// void ThirdPersonFollow::_ready() {
// Target = dynamic_cast<Spatial*>(get_node(TargetPath));
// ExternalFrame = dynamic_cast<Spatial*>(get_node(ExternalFramePath));
// }
// void ThirdPersonFollow::_process(float delta_time) {
// if (Target != nullptr) {
// // Get the frame of reference
// if (has_node(ExternalFramePath) && get_node(ExternalFramePath) != this)
// TFOR = dynamic_cast<Spatial*>(get_node(ExternalFramePath))->get_global_transform();
// else
// TFOR = Transform(Basis(glm::vec3::RIGHT(), glm::vec3::UP(), glm::vec3::FORWARD()), glm::vec3::ZERO());
// CalculateTargetOffset();
// TargetPosition = CalculatePosition();
// translate(to_local(FrameBasedVectorLerp(get_global_translation(), TargetPosition, PositionSpeeds, delta_time)));
// set_rotation_degrees(get_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time));
// }
// // For rotation
// // TODO: Add rotation offset in properly
// //this->SetActorRotation(FMath::Lerp(this->GetActorRotation(), TargetRotation, RotationSpeed * DeltaTime));
// //this->set_rotation(glm::quat(this->get_rotation().slerp(RotationOffset, RotationSpeed * DeltaTime)).get_euler());
// //set_global_rotation_degrees(get_global_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time));
// // TODO: Figure out how to translate rotation to a global rotation
// }
mfloat_t *follow_calcpos()
{
mfloat_t p1[3] = { 0 };
mfloat_t p2[3] = { 0 };
}
/*
glm::vec3 ThirdPersonFollow::CalculatePosition()
{
glm::vec3 p1 = CalculateCenter();
glm::vec3 p2 =
XDirPosts ? GetPostsOffset(TFOR.Right(),
FloatWidths.
x) : GetExtentsOffset(TFOR.Right(),
FloatWidths.x,
TargetOffset.x,
AnchorWidths.x);
glm::vec3 p3 =
YDirPosts ? GetPostsOffset(TFOR.Up(),
FloatWidths.
y) : GetExtentsOffset(TFOR.Up(),
FloatWidths.y,
TargetOffset.y,
AnchorWidths.y);
glm::vec3 p4 =
ZDirPosts ? GetPostsOffset(TFOR.Back(),
FloatWidths.
z) : GetExtentsOffset(TFOR.Back(),
FloatWidths.z,
TargetOffset.z,
AnchorWidths.z);
return p1 + p2 + p3 + p4;
}
glm::vec3 ThirdPersonFollow::CalculateCenter()
{
return Target->get_global_translation() +
TFOR.TransformDirection(Offset) + (mytransform->Back() * Distance);
}
glm::vec3 ThirdPersonFollow::
GetPostsOffset(const glm::vec3 & DirectionVector, float AnchorWidth)
{
float dot = glm::dot(Target->Forward(), DirectionVector);
return DirectionVector * (dot >= 0 ? AnchorWidth : AnchorWidth * -1);
}
glm::vec3 ThirdPersonFollow::
GetExtentsOffset(const glm::vec3 & DirectionVector, float AnchorWidth,
float TOffset, float Width)
{
float negated_offset_sign = ((0 <= TOffset) - (TOffset < 0)) * -1.f;
float TotalWidth = AnchorWidth + Width;
if (glm::abs(TOffset) > TotalWidth
&& !glm::epsilonEqual(glm::abs(TOffset), TotalWidth, 0.5f))
return DirectionVector * TotalWidth * negated_offset_sign;
else {
if (glm::abs(TOffset) >= AnchorWidth)
return DirectionVector * AnchorWidth * negated_offset_sign;
else
return DirectionVector * TOffset * -1.f;
}
return glm::vec3(0.f);
}
glm::vec3 ThirdPersonFollow::FrameBasedVectorLerp(const glm::vec3 & From,
const glm::vec3 & To,
const glm::vec3 & Speeds,
float Tick)
{
// Previously "FORTransform.TransformVector(Speeds)
glm::vec3 TSpeed = glm::abs(TFOR.TransformDirection(Speeds));
glm::vec3 TOffset = glm::abs(TFOR.TransformDirection(TargetOffset));
glm::vec3 TAnchorWidths =
glm::abs(TFOR.TransformDirection(AnchorWidths));
glm::vec3 TFloatWidths =
glm::abs(TFOR.TransformDirection(FloatWidths));
// If these are true, that means to use the anchor speed instead of the normal speed.
// True if the offset is beyond the anchor plus the width
bool bUseX = GetLerpParam(TOffset.x, TAnchorWidths.x, TFloatWidths.x);
bool bUseY = GetLerpParam(TOffset.y, TAnchorWidths.y, TFloatWidths.y);
bool bUseZ = GetLerpParam(TOffset.z, TAnchorWidths.z, TFloatWidths.z);
float xAlpha =
glm::clamp((bUseX ? AnchorSpeed : TSpeed.x) * Tick, 0.f, 1.f);
float yAlpha =
glm::clamp((bUseY ? AnchorSpeed : TSpeed.y) * Tick, 0.f, 1.f);
float zAlpha =
glm::clamp((bUseZ ? AnchorSpeed : TSpeed.z) * Tick, 0.f, 1.f);
return VectorLerpPiecewise(From, To,
glm::vec3(xAlpha, yAlpha, zAlpha));
}
int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e)
{
return fabs(a - b) < e;
}
int lerpparam(float offset, float anchorwidth, float floatwidth)
{
return (offset > (anchorwidth + floatwidth)) && !float_epsilon(anchorwidth + floatwidth, offset, 0.5f);
}
mfloat_t *vec3lerp(mfloat_t from[3], mfloat_t to[3], mfloat_t a[3])
{
from[0] = from[0] + (to[0] - from[0]) * a[0];
from[1] = from[1] + (to[1] - from[1]) * a[1];
from[2] = from[2] + (to[2] - from[2]) * a[2];
}
void follow_calctargets()
{
}
void ThirdPersonFollow::CalculateTargets()
{
// For translation
TargetPosition = CalculatePosition();
// For rotation
// TODO: Check of this implementation is the same as UKismetMath FindLookAtRotation
TargetRotation =
RemoveLockedRotation(glm::quat
(mytransform->
get_global_transform()->get_origin() -
Target->
get_global_transform()->get_origin()));
}
follow_removelockedrot()
{
}
glm::quat ThirdPersonFollow::
RemoveLockedRotation(const glm::quat & CurrentRotation)
{
glm::vec3 NewRotator;
glm::vec3 CurrentRotator = glm::eulerAngles(CurrentRotation);
//
NewRotator.x =
LockRoll ? mytransform->get_rotation().x : CurrentRotator.x;
NewRotator.y =
LockPitch ? mytransform->get_rotation().y : CurrentRotator.y;
NewRotator.z =
LockYaw ? mytransform->get_rotation().z : CurrentRotator.z;
return glm::quat(NewRotator);
}
// The target offset is the value of where the target is compared to where he "should" be based on where
// the camera is. It is what the camera needs to move to be centered on the target
void ThirdPersonFollow::CalculateTargetOffset()
{
glm::vec3 p1 =
(mytransform->Forward() * Distance) +
TFOR.TransformDirection(Offset) +
mytransform->get_global_translation();
glm::vec3 p2 =
TFOR.InverseTransformDirection(Target->get_global_translation());
glm::vec3 p3 = TFOR.InverseTransformDirection(p1);
TargetOffset = p2 - p3;
}
void follow_targetoffset()
{
mfloat_t p1[3], p2[3], p3[3] = {0};
}
*/

View file

@ -0,0 +1,190 @@
// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit.
#ifndef THIRDPERSONFOLLOW_H
#define THIRDPERSONFOLLOW_H
#include "transform.h"
struct follow {
float distance;
mfloat_t target_rot[4];
};
mfloat_t *follow_calcpos();
mfloat_t *follow_calccenter();
mfloat_t *follow_postoffset();
mfloat_t *extentsoffset();
mfloat_t *framebasedveclerp();
int lerpparam(float offset, float anchorwidth, float floatwidth);
mfloat_t *vec3lerp(mfloat_t from[3], mfloat_t to[3], mfloat_t a[3]);
void follow_calctargets();
mfloat_t *follow_removelockedrot();
void follow_targetoffset(struct follow *follow);
int float_epsilon(mfloat_t a, mfloat_t b, mfloat_t e);
/*
//////////////////////////////////////////////////////////////////////////
// A good camera.
//////////////////////////////////////////////////////////////////////////
class ThirdPersonFollow {
public:
enum CameraType {
STATIONARY,
TRANSLATING,
ROTATING,
SPLINE
};
enum CameraTransition {
NONE,
CROSSDISSOLVE,
WIPE,
DIP
};
enum FrameOfReference {
LOCAL,
WORLD,
EXTERNAL
};
ThirdPersonFollow() {
// Rotation
RotationSpeed = 10.0f;
LockPitch = LockYaw = LockRoll = true;
XDirPosts = false;
YDirPosts = false;
ZDirPosts = false;
// Translation
//FloatWidths = AnchorWidths = CenterVector = glm::vec3(0, 0, 0);
PositionSpeeds = glm::vec3(2.f, 2.f, 2.f);
//TranslationScales = glm::vec3(1, 1, 1);
// Frame settings
Offset = glm::vec3(0.f, 0.f, 0.f);
Distance = 10;
AnchorSpeed = 80;
} ~ThirdPersonFollow() {
}
Transform *mytransform;
// An actor that can be given for the camera to base its movement around
// instead of itself. Makes most sense for this to be stationary
Transform *ExternalFrame = nullptr;
void SetExternalFrame(Transform * val) {
ExternalFrame = val;
}
// The target the camera "looks" at, used for calculations
Transform *Target = nullptr;
void SetTarget(Transform * val) {
Target = val;
}
// Offset from the target
glm::vec3 Offset;
// How far away should the camera act from the target
float Distance;
///////////////////////////////////////////////////////////////////////////
// Translation variables. In this mode, the camera doesn't rotate to look
// at the target, it only moves around the world.
///////////////////////////////////////////////////////////////////////////
/// "Posts" for each direction in 3D space. These are items that the target
/// is allowed to move within without the camera following along.
bool XDirPosts;
bool YDirPosts;
bool ZDirPosts;
/// The range in ecah direction the camera floats. While within this range,
/// the camera will smoothly glide to the desired position.
glm::vec3 FloatWidths;
/// The clamp range for each direction. If the camera reaches this range,
/// it will stick and not move any further.
glm::vec3 AnchorWidths;
/// When floating to the target, the speed to float.
glm::vec3 PositionSpeeds;
//////////////////////////////////////////////////////////////////////////
// Rotation variables. Used for the camera's rotation mode, where it
// follows the Target without translating.
//////////////////////////////////////////////////////////////////////////
/// Variables to lock its rotation in any of the three directions
bool LockRoll;
bool LockPitch;
bool LockYaw;
glm::vec3 RotationOffset;
/// The speed of rotation
float RotationSpeed;
private:
void CalculateTargetOffset();
// Transform of frame of reference
Transform TFOR;
/// The calculated offset based on frames of reference
glm::vec3 TargetOffset;
glm::vec3 TargetPosition;
glm::quat TargetRotation;
void CalculateTargets();
// Calculates
glm::vec3 CalculatePosition();
glm::vec3 CalculateCenter();
/// Given a direction and width, find the offsets.
glm::vec3 GetPostsOffset(const glm::vec3 & DirectionVector,
float AnchorWidth);
/// Given anchors, what's the anchor width?
glm::vec3 GetExtentsOffset(const glm::vec3 & DirectionVector,
float AnchorWidth, float TOffset,
float Width);
glm::quat RemoveLockedRotation(const glm::quat & CurrentRotation);
glm::vec3 FrameBasedVectorLerp(const glm::vec3 & From,
const glm::vec3 & To,
const glm::vec3 & Speeds, float Tick);
glm::vec3 VectorLerpPiecewise(const glm::vec3 & From,
const glm::vec3 & To,
const glm::vec3 & Alpha);
bool GetLerpParam(const float Offst, const float AnchorWidth,
const float FloatWidth);
/// Set to a value that gives good clamping, smoothly. Activates when
/// the target is out of range.
float AnchorSpeed;
};
*/
#endif

44
source/engine/transform.c Normal file
View file

@ -0,0 +1,44 @@
#include "transform.h"
#include <string.h>
struct mTransform MakeTransform(mfloat_t pos[3], mfloat_t rotation[4],
float scale)
{
struct mTransform newT;
memcpy(newT.position, pos, sizeof(*pos));
memcpy(newT.rotation, rotation, sizeof(*rotation));
newT.scale = scale;
return newT;
}
mfloat_t *trans_forward(mfloat_t * res,
const struct mTransform *const trans)
{
// YughLog(0, SDL_LOG_PRIORITY_WARN, "Rotation is %f", trans->rotation[0]);
return vec3_rotate_quat(res, FORWARD, trans->rotation);
}
mfloat_t *trans_back(mfloat_t * res, const struct mTransform *trans)
{
return vec3_rotate_quat(res, BACK, trans->rotation);
}
mfloat_t *trans_up(mfloat_t * res, const struct mTransform *trans)
{
return vec3_rotate_quat(res, UP, trans->rotation);
}
mfloat_t *trans_down(mfloat_t * res, const struct mTransform *trans)
{
return vec3_rotate_quat(res, DOWN, trans->rotation);
}
mfloat_t *trans_right(mfloat_t * res, const struct mTransform *trans)
{
return vec3_rotate_quat(res, RIGHT, trans->rotation);
}
mfloat_t *trans_left(mfloat_t * res, const struct mTransform *trans)
{
return vec3_rotate_quat(res, LEFT, trans->rotation);
}

27
source/engine/transform.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef TRANSFORM_H
#define TRANSFORM_H
#include "mathc.h"
struct mTransform {
mfloat_t position[3];
mfloat_t rotation[4];
float scale;
};
struct mTransform MakeTransform(mfloat_t pos[3], mfloat_t rotation[3],
float scale);
mfloat_t *trans_forward(mfloat_t * res,
const struct mTransform *const trans);
mfloat_t *trans_back(mfloat_t * res, const struct mTransform *trans);
mfloat_t *trans_up(mfloat_t * res, const struct mTransform *trans);
mfloat_t *trans_down(mfloat_t * res, const struct mTransform *trans);
mfloat_t *trans_right(mfloat_t * res, const struct mTransform *trans);
mfloat_t *trans_left(mfloat_t * res, const struct mTransform *trans);
//extern Serialize *make_transform();
#endif

132
source/engine/vec.c Normal file
View file

@ -0,0 +1,132 @@
#include "vec.h"
#include "log.h"
struct vec *vec_make(int width, int size)
{
struct vec *new = calloc(1, sizeof(struct vec));
new->size = size;
new->width = width;
new->data = calloc(new->size, new->width);
return new;
}
void *vec_get(struct vec *vec, int n)
{
if (n < vec->len)
return (char *) vec->data + (n * vec->width);
YughLog(0, 4,
"Attempted to access element %d of a vec with %d elements.", n,
vec->len);
return NULL;
}
void vec_walk(struct vec *vec, void (*fn)(void *data))
{
for(int i = 0; i < vec->len; i++)
fn((char *) (vec->data + (i * vec->width)));
}
void vec_delete(struct vec *vec, int n)
{
if (n < vec->len) {
vec->len--;
memcpy(vec_p(vec, n), vec_p(vec, vec->len), vec->width);
}
}
void vec_del_order(struct vec *vec, int n)
{
if (n < vec->len) {
vec->len--;
memmove(vec_p(vec, n), vec_p(vec, n + 1),
vec->width * (vec->len - n));
}
}
void *vec_add(struct vec *vec, void *data)
{
if (vec->size == vec->len)
vec_expand(vec);
if (data)
memcpy(vec_p(vec, vec->len), data, vec->width);
else
memset(vec_p(vec, vec->len), 0, vec->width);
vec->len++;
return vec_get(vec, vec->len - 1);
}
void *vec_add_sort(struct vec *vec, void *data,
int (*sort)(void *a, void *b))
{
if(vec->size == vec->len)
vec_expand(vec);
int n = vec->len - 1;
while (sort(vec_p(vec, n), data))
n--;
vec_insert(vec, data, n);
}
void *vec_insert(struct vec *vec, void *data, int n)
{
if (vec->size == vec->len)
vec_expand(vec);
memmove(vec_p(vec, n), vec_p(vec, n + 1), vec->width * (vec->len - n));
vec->len++;
memcpy(vec_p(vec, n), data, vec->width);
return vec_get(vec, n);
}
char *vec_p(struct vec *vec, int n)
{
return ((char *) vec->data + (vec->width * n));
}
void *vec_set(struct vec *vec, int n, void *data)
{
if (vec->len >= n)
return NULL;
memcpy(vec_p(vec, n), data, vec->width);
return vec_get(vec, n);
}
void vec_expand(struct vec *vec)
{
vec->size *= 2;
vec->data = realloc(vec->data, vec->size * vec->width);
}
void vec_store(struct vec *vec, FILE * f)
{
fwrite(&vec->len, sizeof(vec->len), 1, f);
fwrite(&vec->size, sizeof(vec->size), 1, f);
fwrite(&vec->width, sizeof(vec->width), 1, f);
fwrite(vec->data, vec->width, vec->len, f);
}
void vec_load(struct vec *vec, FILE * f)
{
fread(&vec->len, sizeof(vec->len), 1, f);
fread(&vec->size, sizeof(vec->size), 1, f);
fread(&vec->width, sizeof(vec->width), 1, f);
fread(vec->data, vec->width, vec->len, f);
}
void vec_clear(struct vec *vec)
{
vec->len = 0;
}
void vec_fit(struct vec *vec)
{
vec->size = vec->len;
vec->data = realloc(vec->data, vec->size * vec->width);
}

32
source/engine/vec.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef VEC_H
#define VEC_H
#include <stdio.h>
struct vec {
int len;
int size;
int width;
void *data;
};
struct vec *vec_make(int width, int size);
void *vec_get(struct vec *vec, int n);
void vec_walk(struct vec *vec, void (*fn)(void *data));
void vec_clear(struct vec *vec);
void *vec_add(struct vec *vec, void *data);
/* sort returns 0 for a<=b, 1 for a>b */
void *vec_add_sort(struct vec *vec, void *data,
int (*sort)(void *a, void *b));
void *vec_insert(struct vec *vec, void *data, int n);
void *vec_set(struct vec *vec, int n, void *data);
void vec_delete(struct vec *vec, int n);
void vec_del_order(struct vec *vec, int n);
void vec_store(struct vec *vec, FILE *f);
void vec_load(struct vec *vec, FILE *f);
char *vec_p(struct vec *vec, int n);
void vec_expand(struct vec *vec);
void vec_fit(struct vec *vec);
#endif

157
source/engine/window.c Normal file
View file

@ -0,0 +1,157 @@
#include "window.h"
#include "openglrender.h"
#include <string.h>
#include "log.h"
struct mSDLWindow *window = NULL;
static struct mSDLWindow *windows[5];
static int numWindows = 0;
struct mSDLWindow *MakeSDLWindow(const char *name, int width, int height,
uint32_t flags)
{
struct mSDLWindow *w = calloc(1, sizeof(struct mSDLWindow));
w->width = width;
w->height = height;
w->window = SDL_CreateWindow(name, 0, 0, width, height, flags);
if (w->window == NULL) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"Window could not be created! SDL Error: %s",
SDL_GetError());
} else {
w->glContext = SDL_GL_CreateContext(w->window);
if (w->glContext == NULL) {
YughLog(0, SDL_LOG_PRIORITY_ERROR,
"OpenGL context could not be created! SDL Error: %s",
SDL_GetError());
}
w->id = SDL_GetWindowID(w->window);
glewExperimental = GL_TRUE;
glewInit();
SDL_GL_SetSwapInterval(1);
if (numWindows < 5)
windows[numWindows++] = w;
}
return w;
}
void window_handle_event(struct mSDLWindow *w, SDL_Event * e)
{
if (e->type == SDL_WINDOWEVENT && e->window.windowID == w->id) { // TODO: Check ptr direct?
switch (e->window.event) {
case SDL_WINDOWEVENT_SHOWN:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Showed window %d.", w->id);
w->shown = true;
break;
case SDL_WINDOWEVENT_HIDDEN:
w->shown = false;
YughLog(0, SDL_LOG_PRIORITY_INFO, "Hid window %d.", w->id);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
w->width = e->window.data1;
w->height = e->window.data2;
YughLog(0, SDL_LOG_PRIORITY_INFO,
"Changed size of window %d: width %d, height %d.",
w->id, w->width, w->height);
window_makecurrent(w);
/*w.projection =
glm::ortho(0.f, (float) width, 0.f, (float) height, -1.f,
1.f); */
w->render = true;
break;
case SDL_WINDOWEVENT_EXPOSED:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Exposed window %d.", w->id);
w->render = true;
break;
case SDL_WINDOWEVENT_ENTER:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Entered window %d.", w->id);
w->mouseFocus = true;
SDL_RaiseWindow(w->window);
break;
case SDL_WINDOWEVENT_LEAVE:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Left window %d.", w->id);
w->mouseFocus = false;
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
YughLog(0, SDL_LOG_PRIORITY_INFO,
"Lost focus on window %d.", w->id);
w->keyboardFocus = false;
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
YughLog(0, SDL_LOG_PRIORITY_INFO,
"Gained focus on window %d.", w->id);
w->keyboardFocus = true;
break;
case SDL_WINDOWEVENT_MINIMIZED:
YughLog(0, SDL_LOG_PRIORITY_INFO,
"Minimized window %d.", w->id);
w->minimized = true;
break;
case SDL_WINDOWEVENT_MAXIMIZED:
YughLog(0, SDL_LOG_PRIORITY_INFO,
"Maximized window %d.", w->id);
w->minimized = false;
break;
case SDL_WINDOWEVENT_RESTORED:
YughLog(0, SDL_LOG_PRIORITY_INFO,
"Restored window %d.", w->id);
w->minimized = false;
break;
case SDL_WINDOWEVENT_CLOSE:
YughLog(0, SDL_LOG_PRIORITY_INFO, "Closed window %d.", w->id);
break;
}
}
}
void window_makefullscreen(struct mSDLWindow *w)
{
SDL_SetWindowFullscreen(w->window, SDL_WINDOW_FULLSCREEN_DESKTOP);
w->fullscreen = true;
}
void window_togglefullscreen(struct mSDLWindow *w)
{
w->fullscreen = !w->fullscreen;
if (w->fullscreen) {
window_makefullscreen(w);
} else {
SDL_SetWindowFullscreen(w->window, 0);
}
}
void window_makecurrent(struct mSDLWindow *w)
{
if (w->window != SDL_GL_GetCurrentWindow())
SDL_GL_MakeCurrent(w->window, w->glContext);
glViewport(0, 0, w->width, w->height);
}
void window_swap(struct mSDLWindow *w)
{
SDL_GL_SwapWindow(w->window);
}

34
source/engine/window.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef WINDOW_H
#define WINDOW_H
#include <SDL.h>
#include <stdbool.h>
struct mSDLWindow {
SDL_Window *window;
SDL_GLContext glContext;
int id;
int width;
int height;
/* TODO: Bitfield these */
bool render;
bool mouseFocus;
bool keyboardFocus;
bool fullscreen;
bool minimized;
bool shown;
float projection[16];
};
extern struct mSDLWindow *window;
struct mSDLWindow *MakeSDLWindow(const char *name, int width, int height,
uint32_t flags);
void window_handle_event(struct mSDLWindow *w, SDL_Event * e);
void window_focus(struct mSDLWindow *w);
void window_makecurrent(struct mSDLWindow *w);
void window_makefullscreen(struct mSDLWindow *w);
void window_togglefullscreen(struct mSDLWindow *w);
void window_swap(struct mSDLWindow *w);
#endif