Compare commits
54 Commits
e43391caa3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7c0b0780c | ||
|
|
46bd5e8d5e | ||
|
|
d614e2ced4 | ||
|
|
57fffeb0a3 | ||
|
|
def545450d | ||
|
|
9b7ecb3ae7 | ||
|
|
9c2e4ffae1 | ||
|
|
3e14195bf7 | ||
|
|
055ff4f5ce | ||
|
|
4d0e043f4c | ||
|
|
3da728c768 | ||
|
|
8857b93f90 | ||
|
|
cf0f402da3 | ||
|
|
db46d5506c | ||
|
|
e87417603e | ||
|
|
0f68c8c7ae | ||
|
|
2211193a96 | ||
|
|
6d821cb361 | ||
|
|
a2039557bb | ||
|
|
a1439664ca | ||
|
|
0453585751 | ||
|
|
5f6dc66a0f | ||
|
|
2e730baf33 | ||
|
|
462412c31a | ||
|
|
e4b5f8d361 | ||
|
|
f7a429cfbc | ||
|
|
3c372a3024 | ||
|
|
f65891932a | ||
|
|
177d259304 | ||
|
|
dbced43b2b | ||
|
|
96da001734 | ||
|
|
943601bc3a | ||
|
|
b32671567e | ||
|
|
f4cf597a95 | ||
|
|
5f2e84d8cf | ||
|
|
7754e410fd | ||
|
|
5a3a524cb3 | ||
|
|
55b8e827c2 | ||
|
|
368664d246 | ||
|
|
90f0e2dd42 | ||
|
|
355df2ee44 | ||
|
|
e126db573a | ||
|
|
ceb8ccb7d4 | ||
|
|
e81750300d | ||
|
|
446ff24fcf | ||
|
|
309af8f59e | ||
|
|
7b6ce73fa5 | ||
|
|
ce465ef449 | ||
|
|
9478bca2ad | ||
|
|
da59158fd1 | ||
|
|
ff2924a0b7 | ||
|
|
24ddb047aa | ||
|
|
0ba2cdee1c | ||
|
|
ae4a62f584 |
@@ -14,11 +14,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
- run: mkdir build build/k3 build/k3/compr bin bin/assets
|
- run: mkdir build build/k3 build/k3/compr bin bin/assets
|
||||||
- run: CC="i686-w64-mingw32-gcc" CFLAGS="-I/usr/i686-w64-mingw32/include -I/usr/i686-w64-mingw32/include/lua5.3 -L/usr/i686-w64-mingw32/lib -Wno-error" make -B
|
- run: LIBS="-lfreetype -l:libz.a" CC="i686-w64-mingw32-gcc" CFLAGS="-I/usr/i686-w64-mingw32/include -I/usr/i686-w64-mingw32/include/lua5.3 -L/usr/i686-w64-mingw32/lib -Wno-error" make -B
|
||||||
- run: CC="i686-linux-gnu-gcc" CFLAGS="-I/usr/i686-linux-gnu/include -I/usr/i686-linux-gnu/include/lua5.3 -L/usr/i686-linux-gnu/lib -Wno-error" make -B
|
- run: cp /usr/lib/gcc/i686-w64-mingw32/14-win32/libgcc_s_dw2-1.dll /usr/lib/gcc/i686-w64-mingw32/14-win32/libstdc++-6.dll /usr/i686-w64-mingw32/lib/libportaudio-2.dll /usr/i686-w64-mingw32/lib/libwinpthread-1.dll /usr/lib/gcc/i686-w64-mingw32/14-win32/libgomp-1.dll bin/
|
||||||
- run: cp /usr/lib/gcc/i686-w64-mingw32/10-win32/libgcc_s_dw2-1.dll /usr/lib/gcc/i686-w64-mingw32/10-win32/libstdc++-6.dll /usr/i686-w64-mingw32/lib/libportaudio-2.dll /usr/i686-w64-mingw32/lib/libwinpthread-1.dll bin/
|
- run: curl "http://127.0.0.1:9898/build?root=${{ github.workspace }}"
|
||||||
- run: cp -r /home/git/k4templateassets/* bin/assets/
|
- run: cp -r /home/git/k4templateassets/* bin/assets/
|
||||||
- run: zip -9r "k4${{ github.ref_name }}.zip" bin/
|
- run: mv bin k4
|
||||||
|
- run: zip -9r "k4${{ github.ref_name }}.zip" k4/
|
||||||
- name: Create package
|
- name: Create package
|
||||||
uses: akkuman/gitea-release-action@v1
|
uses: akkuman/gitea-release-action@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -10,14 +10,14 @@ k3_HDRS := $(call rwildcard,k3/src,*.h)
|
|||||||
k3_OBJS := $(patsubst k3/src/%.c, build/k3/%.o, $(k3_SRCS))
|
k3_OBJS := $(patsubst k3/src/%.c, build/k3/%.o, $(k3_SRCS))
|
||||||
k3_DEPS := $(patsubst k3/src/%.c, build/k3/%.d, $(k3_SRCS))
|
k3_DEPS := $(patsubst k3/src/%.c, build/k3/%.d, $(k3_SRCS))
|
||||||
|
|
||||||
CFLAGS := $(CFLAGS) -Ik3/src -O2 -fopenmp
|
CFLAGS := $(CFLAGS) -D_GNU_SOURCE -D_DEFAULT_SOURCE -DGLCA_CUSTOM_GLYPH_DATA -Ik3/src -fopenmp -O2 -flto -fwhole-program -Wno-error=incompatible-pointer-types -Wno-error=int-conversion
|
||||||
|
|
||||||
ifneq (,$(findstring mingw,$(CC)))
|
ifneq (,$(findstring mingw,$(CC)))
|
||||||
CFLAGS := -static-libgcc -static-libstdc++ -std=gnu99 -march=pentium4 -D_WIN32_WINNT=0x600 -DENET_FEATURE_ADDRESS_MAPPING -fno-pic -no-pie -fms-extensions -fno-pie -Isrc $(CFLAGS)
|
CFLAGS := -static-libgcc -static-libstdc++ -std=gnu99 -march=pentium4 -D_WIN32_WINNT=0x600 -DENET_FEATURE_ADDRESS_MAPPING -fno-pic -no-pie -fms-extensions -fno-pie -Isrc $(CFLAGS)
|
||||||
LIBS := -l:libglfw3.a -lopengl32 -pthread -lm -l:libode.a -l:libvorbisfile.a -l:libvorbis.a -l:libogg.a -lportaudio -lgdi32 -lws2_32 -lwinmm -lstdc++ -lole32 -lsetupapi -lhid -l:liblua5.3.a $(LIBS)
|
LIBS := -l:libglfw3.a -lopengl32 -pthread -lm -l:libode.a -l:libvorbisfile.a -l:libvorbis.a -l:libogg.a -lportaudio -lgdi32 -lws2_32 -lwinmm -lstdc++ -lole32 -lsetupapi -lhid -l:liblua5.3.a -liphlpapi $(LIBS)
|
||||||
else
|
else
|
||||||
CFLAGS := -march=opteron $(SAN) -std=gnu99 -DENET_FEATURE_ADDRESS_MAPPING -fms-extensions -fno-pic -no-pie -fno-pie -Isrc $(CFLAGS)
|
CFLAGS := -march=opteron $(SAN) -std=gnu99 -DENET_FEATURE_ADDRESS_MAPPING -fms-extensions -fno-pic -no-pie -fno-pie -Isrc $(CFLAGS)
|
||||||
LIBS := -lglfw3 -pthread -ldl -lm -lode -lstdc++ -llua5.3 -lvorbis -lvorbisfile -lportaudio $(LIBS)
|
LIBS := -lglfw3 -pthread -ldl -lm -lode -lstdc++ -llua5.3 -lvorbis -lvorbisfile -logg -lasound -lfreetype -lportaudio -lz $(LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS := $(CFLAGS) -DLOCALHOST_ONLY
|
CFLAGS := $(CFLAGS) -DLOCALHOST_ONLY
|
||||||
|
|||||||
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
Homepage: https://mid.net.ua/k4.html
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
## v2
|
||||||
|
|
||||||
|
1. k3Menu objects now have stylable properties ala CSS
|
||||||
|
2. Exposed `game.ui.obj` "base object" which allows you to create your own widgets
|
||||||
|
3. Revamped the animation system to one with blend trees
|
||||||
|
4. Added scrollboxes and image objects to k3Menu
|
||||||
|
5. Replaced the font subsystem with one that uses TrueType fonts directly, and they are drawn using signed distance fields when possible
|
||||||
|
6. Added `game.near` and `game.far` values for editing the camera planes
|
||||||
|
7. Added vsync parameter to command line
|
||||||
|
8. Graphics bug fixes
|
||||||
|
9. Improved mipmapping
|
||||||
|
10. Frustum culling
|
||||||
|
11. Added support for 32-bit indices in models
|
||||||
|
|
||||||
|
## v1
|
||||||
|
|
||||||
|
Initial release.
|
||||||
1
k3
Submodule
1
k3
Submodule
Submodule k3 added at 56ecba05b1
2
k3ex.py
2
k3ex.py
@@ -115,6 +115,8 @@ def write_some_data(context, filepath, doExportEverything):
|
|||||||
out.write(struct.pack("4f", m.col[c][0], m.col[c][1], m.col[c][2], m.col[c][3]))
|
out.write(struct.pack("4f", m.col[c][0], m.col[c][1], m.col[c][2], m.col[c][3]))
|
||||||
for b in dabones:
|
for b in dabones:
|
||||||
out.write(struct.pack("B", dabones.index(b.parent) if b.parent else 255))
|
out.write(struct.pack("B", dabones.index(b.parent) if b.parent else 255))
|
||||||
|
for b in dabones:
|
||||||
|
out.write(b.name.encode("UTF-8") + b'\x00')
|
||||||
|
|
||||||
for v in vertdict.keys():
|
for v in vertdict.keys():
|
||||||
out.write(struct.pack("3f", v[0][0], v[0][2], -v[0][1]))
|
out.write(struct.pack("3f", v[0][0], v[0][2], -v[0][1]))
|
||||||
|
|||||||
294
src/game.c
294
src/game.c
@@ -5,6 +5,8 @@
|
|||||||
#include"resman.h"
|
#include"resman.h"
|
||||||
#include<cglm/vec3.h>
|
#include<cglm/vec3.h>
|
||||||
|
|
||||||
|
#define SUBFEET(cp) (cp->capsule.radius)
|
||||||
|
|
||||||
struct Game Game;
|
struct Game Game;
|
||||||
|
|
||||||
void game_init() {
|
void game_init() {
|
||||||
@@ -29,8 +31,8 @@ void game_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct CollisionPair {
|
struct CollisionPair {
|
||||||
dGeomID g1; // greater
|
uint16_t e1; // greater
|
||||||
dGeomID g2; // lesser
|
uint16_t e2; // lesser
|
||||||
uint8_t x;
|
uint8_t x;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
static size_t activeCollisionCount, activeCollisionCapacity;
|
static size_t activeCollisionCount, activeCollisionCapacity;
|
||||||
@@ -38,22 +40,22 @@ static struct CollisionPair *activeCollisions;
|
|||||||
int pair_comparator(const void *a_, const void *b_) {
|
int pair_comparator(const void *a_, const void *b_) {
|
||||||
const struct CollisionPair *a = a_;
|
const struct CollisionPair *a = a_;
|
||||||
const struct CollisionPair *b = b_;
|
const struct CollisionPair *b = b_;
|
||||||
if(a->g1 == b->g1) {
|
if(a->e1 == b->e1) {
|
||||||
return (uintptr_t) a->g2 - (uintptr_t) b->g2;
|
return (intmax_t) a->e2 - (intmax_t) b->e2;
|
||||||
} else {
|
} else {
|
||||||
return (uintptr_t) a->g1 - (uintptr_t) b->g1;
|
return (intmax_t) a->e1 - (intmax_t) b->e1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int activate_pair(dGeomID g1, dGeomID g2) {
|
static int activate_pair(uint16_t e1, uint16_t e2) {
|
||||||
struct CollisionPair p = {
|
struct CollisionPair p = {
|
||||||
.g1 = g1 > g2 ? g1 : g2,
|
.e1 = e1 > e2 ? e1 : e2,
|
||||||
.g2 = g1 > g2 ? g2 : g1,
|
.e2 = e1 > e2 ? e2 : e1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CollisionPair *peepee = bsearch(&p, activeCollisions, activeCollisionCount, sizeof(struct CollisionPair), pair_comparator);
|
struct CollisionPair *peepee = bsearch(&p, activeCollisions, activeCollisionCount, sizeof(struct CollisionPair), pair_comparator);
|
||||||
|
|
||||||
if(peepee) {
|
if(peepee) {
|
||||||
peepee->x++;
|
peepee->x = 2;
|
||||||
return TRIGGER_EV_CONTINUOUS;
|
return TRIGGER_EV_CONTINUOUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +74,8 @@ static int activate_pair(dGeomID g1, dGeomID g2) {
|
|||||||
static void tick_pairs() {
|
static void tick_pairs() {
|
||||||
for(size_t i = 0; i < activeCollisionCount;) {
|
for(size_t i = 0; i < activeCollisionCount;) {
|
||||||
if(--activeCollisions[i].x == 0) {
|
if(--activeCollisions[i].x == 0) {
|
||||||
uint16_t e1 = (uintptr_t) dGeomGetData(activeCollisions[i].g1);
|
uint16_t e1 = activeCollisions[i].e1;
|
||||||
uint16_t e2 = (uintptr_t) dGeomGetData(activeCollisions[i].g2);
|
uint16_t e2 = activeCollisions[i].e2;
|
||||||
|
|
||||||
if(e1 != ENT_ID_INVALID) {
|
if(e1 != ENT_ID_INVALID) {
|
||||||
struct CPhysics *p1 = game_getcomponent(e1, physics);
|
struct CPhysics *p1 = game_getcomponent(e1, physics);
|
||||||
@@ -97,10 +99,21 @@ static void tick_pairs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vec3_project_to_plane(vec3 v, vec3 n, vec3 ret) {
|
||||||
|
float scale = glm_vec3_dot(v, n) / glm_vec3_dot(n, n);
|
||||||
|
|
||||||
|
vec3 n2;
|
||||||
|
glm_vec3_scale(n, scale, n2);
|
||||||
|
|
||||||
|
glm_vec3_sub(v, n2, ret);
|
||||||
|
}
|
||||||
|
|
||||||
static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
||||||
uint16_t e1 = (uintptr_t) dGeomGetData(g1);
|
uint16_t e1 = (uintptr_t) dGeomGetData(g1);
|
||||||
uint16_t e2 = (uintptr_t) dGeomGetData(g2);
|
uint16_t e2 = (uintptr_t) dGeomGetData(g2);
|
||||||
|
|
||||||
|
if(e1 != ENT_ID_INVALID && e1 == e2) return;
|
||||||
|
|
||||||
dBodyID b1 = dGeomGetBody(g1);
|
dBodyID b1 = dGeomGetBody(g1);
|
||||||
dBodyID b2 = dGeomGetBody(g2);
|
dBodyID b2 = dGeomGetBody(g2);
|
||||||
|
|
||||||
@@ -124,8 +137,6 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
|||||||
if(movingPlatform) {
|
if(movingPlatform) {
|
||||||
const dReal *platvel = dBodyGetLinearVel(movingPlatform == 1 ? b1 : b2);
|
const dReal *platvel = dBodyGetLinearVel(movingPlatform == 1 ? b1 : b2);
|
||||||
|
|
||||||
//if(i == 0)printf("get %f %f %f\n", platvel[0], platvel[1], platvel[2]);
|
|
||||||
|
|
||||||
contact[i].surface.mode |= dContactMotion1 | dContactMotion2 | dContactMotionN | dContactFDir1;
|
contact[i].surface.mode |= dContactMotion1 | dContactMotion2 | dContactMotionN | dContactFDir1;
|
||||||
contact[i].surface.mode |= dContactSoftERP;
|
contact[i].surface.mode |= dContactSoftERP;
|
||||||
contact[i].surface.soft_erp = 0.9;
|
contact[i].surface.soft_erp = 0.9;
|
||||||
@@ -146,31 +157,44 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
|||||||
|
|
||||||
int ghost = 0;
|
int ghost = 0;
|
||||||
|
|
||||||
|
if(dGeomGetCategoryBits(g1) & CATEGORY_GHOST) ghost = 1;
|
||||||
|
if(dGeomGetCategoryBits(g2) & CATEGORY_GHOST) ghost = 1;
|
||||||
|
|
||||||
if(numc) {
|
if(numc) {
|
||||||
int triggerType = activate_pair(g1, g2);
|
int triggerType = activate_pair(e1, e2);
|
||||||
|
|
||||||
if(e1 != ENT_ID_INVALID) {
|
if(e1 != ENT_ID_INVALID) {
|
||||||
struct CPhysics *cp = game_getcomponent(e1, physics);
|
struct CPhysics *cp = game_getcomponent(e1, physics);
|
||||||
if(!cp) {
|
if(!cp) {
|
||||||
// Entity being killed
|
// Entity being killed maybe
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cp->dynamics & CPHYSICS_GHOST) {
|
if(cp->dynamics & CPHYSICS_GHOST) {
|
||||||
ghost = 1;
|
ghost = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CMovement *cm = game_getcomponent(e1, movement);
|
||||||
|
if(cm && cm->holding != ENT_ID_INVALID && cm->holding == e2) {
|
||||||
|
ghost = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e2 != ENT_ID_INVALID) {
|
if(e2 != ENT_ID_INVALID) {
|
||||||
struct CPhysics *cp = game_getcomponent(e2, physics);
|
struct CPhysics *cp = game_getcomponent(e2, physics);
|
||||||
if(!cp) {
|
if(!cp) {
|
||||||
// Entity being killed
|
// Entity being killed maybe
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cp->dynamics & CPHYSICS_GHOST) {
|
if(cp->dynamics & CPHYSICS_GHOST) {
|
||||||
ghost = 1;
|
ghost = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CMovement *cm = game_getcomponent(e2, movement);
|
||||||
|
if(cm && cm->holding != ENT_ID_INVALID && cm->holding == e1) {
|
||||||
|
ghost = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float friction = 1;
|
float friction = 1;
|
||||||
@@ -180,37 +204,6 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
|||||||
|
|
||||||
friction *= c->friction;
|
friction *= c->friction;
|
||||||
|
|
||||||
vec4 q;
|
|
||||||
if(b1) {
|
|
||||||
memcpy(q, dBodyGetQuaternion(b1), sizeof(q));
|
|
||||||
} else {
|
|
||||||
dGeomGetQuaternion(c->geom, q);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
float temp = q[0];
|
|
||||||
q[0] = q[1];
|
|
||||||
q[1] = q[2];
|
|
||||||
q[2] = q[3];
|
|
||||||
q[3] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 n = {0, 1, 0};
|
|
||||||
glm_quat_rotatev(q, n, n);
|
|
||||||
|
|
||||||
if(!ghost) for(int i = 0; i < numc; i++) {
|
|
||||||
if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) {
|
|
||||||
struct CMovement *m = game_getcomponent(e1, movement);
|
|
||||||
if(m) {
|
|
||||||
if(m->holding != ENT_ID_INVALID && m->holding == e2) {
|
|
||||||
ghost = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m->canJump = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(c->trigger != TRIGGER_INVALID) {
|
if(c->trigger != TRIGGER_INVALID) {
|
||||||
Game.triggers[c->trigger - 1](c->trigger, e1, e2, triggerType);
|
Game.triggers[c->trigger - 1](c->trigger, e1, e2, triggerType);
|
||||||
}
|
}
|
||||||
@@ -221,37 +214,6 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
|||||||
|
|
||||||
friction *= c->friction;
|
friction *= c->friction;
|
||||||
|
|
||||||
vec4 q;
|
|
||||||
if(b2) {
|
|
||||||
memcpy(q, dBodyGetQuaternion(b2), sizeof(q));
|
|
||||||
} else {
|
|
||||||
dGeomGetQuaternion(c->geom, q);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
float temp = q[0];
|
|
||||||
q[0] = q[1];
|
|
||||||
q[1] = q[2];
|
|
||||||
q[2] = q[3];
|
|
||||||
q[3] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 n = {0, -1, 0};
|
|
||||||
glm_quat_rotatev(q, n, n);
|
|
||||||
|
|
||||||
if(!ghost) for(int i = 0; i < numc; i++) {
|
|
||||||
if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) {
|
|
||||||
struct CMovement *m = game_getcomponent(e2, movement);
|
|
||||||
if(m) {
|
|
||||||
if(m->holding != ENT_ID_INVALID && m->holding == e1) {
|
|
||||||
ghost = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m->canJump = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(c->trigger != TRIGGER_INVALID) {
|
if(c->trigger != TRIGGER_INVALID) {
|
||||||
Game.triggers[c->trigger - 1](c->trigger, e2, e1, triggerType);
|
Game.triggers[c->trigger - 1](c->trigger, e2, e1, triggerType);
|
||||||
}
|
}
|
||||||
@@ -349,7 +311,102 @@ void game_raycast(struct LocalRay *rays, size_t count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void game_character_controller_raycast_handler(void *data, dGeomID g1, dGeomID g2) {
|
||||||
|
if(dGeomGetClass(g1) != dRayClass && dGeomGetClass(g2) != dRayClass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t e1 = (uintptr_t) dGeomGetData(g1);
|
||||||
|
uint16_t e2 = (uintptr_t) dGeomGetData(g2);
|
||||||
|
|
||||||
|
if(e1 == e2) {
|
||||||
|
// This means the ray is hitting the entity casting it.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dContact contact[1];
|
||||||
|
memset(contact, 0, sizeof(contact));
|
||||||
|
|
||||||
|
int numc = dCollide(g1, g2, 1, &contact[0].geom, sizeof(dContact));
|
||||||
|
|
||||||
|
if(numc) {
|
||||||
|
|
||||||
|
vec3 n = {0, -1, 0};
|
||||||
|
|
||||||
|
struct CPhysics *cp1 = game_getcomponent(e1, physics);
|
||||||
|
struct CPhysics *cp2 = game_getcomponent(e2, physics);
|
||||||
|
|
||||||
|
if((cp2 && (cp2->dynamics & CPHYSICS_GHOST)) || (cp1 && (cp1->dynamics & CPHYSICS_GHOST))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dGeomGetClass(g1) == dRayClass) {
|
||||||
|
dBodyID bid = dGeomGetBody(cp1->geom);
|
||||||
|
|
||||||
|
struct CMovement *cm = game_getcomponent(e1, movement);
|
||||||
|
|
||||||
|
cm->groundDepth = dGeomRayGetLength(g1) - contact[0].geom.depth;
|
||||||
|
|
||||||
|
if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7 && cm->groundDepth > SUBFEET(cp1)) {
|
||||||
|
cm->canJump = 1;
|
||||||
|
glm_vec3_scale(contact[0].geom.normal, -1, cm->groundNormal);
|
||||||
|
}
|
||||||
|
} else if(dGeomGetClass(g2) == dRayClass) {
|
||||||
|
dBodyID bid = dGeomGetBody(cp2->geom);
|
||||||
|
|
||||||
|
struct CMovement *cm = game_getcomponent(e2, movement);
|
||||||
|
|
||||||
|
cm->groundDepth = dGeomRayGetLength(g2) - contact[0].geom.depth;
|
||||||
|
|
||||||
|
if(glm_vec3_dot(contact[0].geom.normal, n) >= +0.7 && cm->groundDepth > SUBFEET(cp2)) {
|
||||||
|
cm->canJump = 1;
|
||||||
|
glm_vec3_scale(contact[0].geom.normal, +1, cm->groundNormal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void game_character_controller_raycast() {
|
||||||
|
dGeomID rayGeoms[Game.entities.movementCount];
|
||||||
|
|
||||||
|
for(size_t i = 0; i < Game.entities.movementCount; i++) {
|
||||||
|
Game.entities.movement[i].canJump = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < Game.entities.movementCount; i++) {
|
||||||
|
struct CPhysics *cp = game_getcomponent(Game.entities.movement[i].entity, physics);
|
||||||
|
|
||||||
|
if(!cp || !cp->geom || cp->type != CPHYSICS_CAPSULE) {
|
||||||
|
rayGeoms[i] = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rayGeoms[i] = dCreateRay(Game.space, cp->capsule.length / 2 + cp->capsule.radius + SUBFEET(cp));
|
||||||
|
|
||||||
|
dGeomSetData(rayGeoms[i], (void*) (uintptr_t) Game.entities.movement[i].entity);
|
||||||
|
|
||||||
|
dGeomSetCategoryBits(rayGeoms[i], CATEGORY_RAY);
|
||||||
|
dGeomSetCollideBits(rayGeoms[i], CATEGORY_STATIC | CATEGORY_ENTITY);
|
||||||
|
|
||||||
|
dBodyID bid = dGeomGetBody(cp->geom);
|
||||||
|
|
||||||
|
const float *position = dBodyGetPosition(bid);
|
||||||
|
|
||||||
|
dGeomRaySet(rayGeoms[i], position[0], position[1], position[2], 0, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dSpaceCollide(Game.space, NULL, game_character_controller_raycast_handler);
|
||||||
|
|
||||||
|
for(int i = 0; i < Game.entities.movementCount; i++) {
|
||||||
|
if(rayGeoms[i]) {
|
||||||
|
dGeomDestroy(rayGeoms[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void game_update() {
|
void game_update() {
|
||||||
|
game_character_controller_raycast();
|
||||||
|
|
||||||
for(size_t i = 0; i < Game.entities.playerctrlCount; i++) {
|
for(size_t i = 0; i < Game.entities.playerctrlCount; i++) {
|
||||||
struct CPlayerCtrl *cc = &Game.entities.playerctrl[i];
|
struct CPlayerCtrl *cc = &Game.entities.playerctrl[i];
|
||||||
|
|
||||||
@@ -395,9 +452,18 @@ void game_update() {
|
|||||||
if(cp && cp->geom) {
|
if(cp && cp->geom) {
|
||||||
dBodyID bid = dGeomGetBody(cp->geom);
|
dBodyID bid = dGeomGetBody(cp->geom);
|
||||||
if(Game.entities.movement[i].canJump) {
|
if(Game.entities.movement[i].canJump) {
|
||||||
dBodySetLinearVel(bid, 0, 0, 0);
|
if(dBodyGetLinearVel(bid)[1] <= 0) {
|
||||||
|
Game.entities.movement[i].isJumping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Game.entities.movement[i].isJumping) {
|
||||||
|
const float *pos = dBodyGetPosition(bid);
|
||||||
|
dBodySetPosition(bid, pos[0], pos[1] + Game.entities.movement[i].groundDepth - cp->capsule.radius / 2 - SUBFEET(cp), pos[2]);
|
||||||
|
|
||||||
|
dBodySetLinearVel(bid, 0, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dBodySetGravityMode(bid, !Game.entities.movement[i].canJump);
|
dBodySetGravityMode(bid, Game.entities.movement[i].canJump && !Game.entities.movement[i].isJumping ? 0 : 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,14 +499,21 @@ void game_update() {
|
|||||||
Game.entities.physics[i].box.l);
|
Game.entities.physics[i].box.l);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CPHYSICS_CAPSULE:
|
case CPHYSICS_CAPSULE: {
|
||||||
Game.entities.physics[i].geom = dCreateCapsule(Game.space,
|
dGeomID top = dCreateCapsule(Game.space,
|
||||||
Game.entities.physics[i].capsule.radius,
|
Game.entities.physics[i].capsule.radius,
|
||||||
Game.entities.physics[i].capsule.length);
|
Game.entities.physics[i].capsule.length - Game.entities.physics[i].capsule.radius);
|
||||||
|
|
||||||
|
dGeomID feet = dCreateSphere(Game.space,
|
||||||
|
Game.entities.physics[i].capsule.radius);
|
||||||
|
|
||||||
|
Game.entities.physics[i].geom = top;
|
||||||
|
Game.entities.physics[i].geom2 = feet;
|
||||||
|
|
||||||
dMassSetCapsuleTotal(&mass, Game.entities.physics[i].mass, 2, Game.entities.physics[i].capsule.radius, Game.entities.physics[i].capsule.length);
|
dMassSetCapsuleTotal(&mass, Game.entities.physics[i].mass, 2, Game.entities.physics[i].capsule.radius, Game.entities.physics[i].capsule.length);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CPHYSICS_SPHERE:
|
case CPHYSICS_SPHERE:
|
||||||
Game.entities.physics[i].geom = dCreateSphere(Game.space,
|
Game.entities.physics[i].geom = dCreateSphere(Game.space,
|
||||||
Game.entities.physics[i].sphere.radius);
|
Game.entities.physics[i].sphere.radius);
|
||||||
@@ -454,6 +527,12 @@ void game_update() {
|
|||||||
dGeomSetCollideBits(Game.entities.physics[i].geom, Game.entities.physics[i].collide);
|
dGeomSetCollideBits(Game.entities.physics[i].geom, Game.entities.physics[i].collide);
|
||||||
dGeomSetData(Game.entities.physics[i].geom, (void*) Game.entities.physics[i].entity);
|
dGeomSetData(Game.entities.physics[i].geom, (void*) Game.entities.physics[i].entity);
|
||||||
|
|
||||||
|
if(Game.entities.physics[i].type == CPHYSICS_CAPSULE) {
|
||||||
|
dGeomSetCategoryBits(Game.entities.physics[i].geom2, CATEGORY_ENTITY | CATEGORY_GHOST);
|
||||||
|
dGeomSetCollideBits(Game.entities.physics[i].geom2, Game.entities.physics[i].collide);
|
||||||
|
dGeomSetData(Game.entities.physics[i].geom2, (void*) Game.entities.physics[i].entity);
|
||||||
|
}
|
||||||
|
|
||||||
if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) != CPHYSICS_STATIC) {
|
if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) != CPHYSICS_STATIC) {
|
||||||
dBodyID body = dBodyCreate(Game.phys);
|
dBodyID body = dBodyCreate(Game.phys);
|
||||||
|
|
||||||
@@ -464,10 +543,16 @@ void game_update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dGeomSetBody(Game.entities.physics[i].geom, body);
|
dGeomSetBody(Game.entities.physics[i].geom, body);
|
||||||
|
if(Game.entities.physics[i].geom2) {
|
||||||
|
dGeomSetBody(Game.entities.physics[i].geom2, body);
|
||||||
|
}
|
||||||
|
|
||||||
if(Game.entities.physics[i].type == CPHYSICS_CAPSULE) {
|
if(Game.entities.physics[i].type == CPHYSICS_CAPSULE) {
|
||||||
dBodySetMaxAngularSpeed(body, 0);
|
dBodySetMaxAngularSpeed(body, 0);
|
||||||
|
|
||||||
|
dGeomSetOffsetPosition(Game.entities.physics[i].geom, 0, Game.entities.physics[i].capsule.radius / 2, 0);
|
||||||
|
dGeomSetOffsetPosition(Game.entities.physics[i].geom2, 0, -Game.entities.physics[i].capsule.length / 2, 0);
|
||||||
|
|
||||||
// Rotate to Y-up
|
// Rotate to Y-up
|
||||||
dQuaternion q;
|
dQuaternion q;
|
||||||
dQFromAxisAndAngle(q, 1, 0, 0, M_PI * 0.5);
|
dQFromAxisAndAngle(q, 1, 0, 0, M_PI * 0.5);
|
||||||
@@ -528,6 +613,10 @@ void game_update() {
|
|||||||
if(glm_vec3_norm(wishvel) > 3) {
|
if(glm_vec3_norm(wishvel) > 3) {
|
||||||
glm_vec3_scale_as(wishvel, 3, wishvel);
|
glm_vec3_scale_as(wishvel, 3, wishvel);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// We project the movement vector onto the ground plane (set by game_character_controller_raycast_handler)
|
||||||
|
// to "slide" along the ground with minimal bouncing
|
||||||
|
vec3_project_to_plane(wishvel, Game.entities.movement[mi].groundNormal, wishvel);
|
||||||
}
|
}
|
||||||
|
|
||||||
float currentspeed = glm_vec3_dot(wishvel, dBodyGetLinearVel(bid));
|
float currentspeed = glm_vec3_dot(wishvel, dBodyGetLinearVel(bid));
|
||||||
@@ -550,23 +639,19 @@ void game_update() {
|
|||||||
dQFromAxisAndAngle(q, 0, 1, 0, Game.entities.movement[mi].pointing + M_PI);
|
dQFromAxisAndAngle(q, 0, 1, 0, Game.entities.movement[mi].pointing + M_PI);
|
||||||
dBodySetQuaternion(bid, q);
|
dBodySetQuaternion(bid, q);
|
||||||
|
|
||||||
if(Game.entities.movement[mi].jump && (0||Game.entities.movement[mi].canJump)) {
|
if(Game.entities.movement[mi].jump && Game.entities.movement[mi].canJump) {
|
||||||
Game.entities.movement[mi].canJump = 0;
|
dVector3 force = {};
|
||||||
|
dWorldImpulseToForce(Game.phys, 1.f / GAME_TPS, 0, 6.5, 0, force);
|
||||||
dVector3 force;
|
|
||||||
dWorldImpulseToForce(Game.phys, 1.f / GAME_TPS, 0, 5, 0, force);
|
|
||||||
|
|
||||||
if(bid) {
|
if(bid) {
|
||||||
dBodyAddForce(bid, force[0], force[1], force[2]);
|
dBodyAddForce(bid, force[0], force[1], force[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Game.entities.movement[mi].isJumping = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0; i < Game.entities.movementCount; i++) {
|
|
||||||
Game.entities.movement[i].canJump = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dSpaceCollide(Game.space, 0, &contact_callback);
|
dSpaceCollide(Game.space, 0, &contact_callback);
|
||||||
|
|
||||||
tick_pairs();
|
tick_pairs();
|
||||||
@@ -600,7 +685,7 @@ void game_update() {
|
|||||||
|
|
||||||
size_t boneCount = Game.entities.render[ci].cache ? k3MdlGetBoneCount(Game.entities.render[ci].cache) : 0;
|
size_t boneCount = Game.entities.render[ci].cache ? k3MdlGetBoneCount(Game.entities.render[ci].cache) : 0;
|
||||||
if(boneCount) {
|
if(boneCount) {
|
||||||
struct CBoned *cb = game_getcomponent(Game.entities.render[ci].entity, boned);
|
/*struct CBoned *cb = game_getcomponent(Game.entities.render[ci].entity, boned);
|
||||||
|
|
||||||
if(!cb) {
|
if(!cb) {
|
||||||
cb = game_ensurecomponent(Game.entities.render[ci].entity, boned);
|
cb = game_ensurecomponent(Game.entities.render[ci].entity, boned);
|
||||||
@@ -656,7 +741,7 @@ void game_update() {
|
|||||||
glm_decompose(cb->anim.cache.inter[m], cb->bones[m].translation, rot, scaleignore);
|
glm_decompose(cb->anim.cache.inter[m], cb->bones[m].translation, rot, scaleignore);
|
||||||
glm_mat4_quat(cb->anim.cache.inter[m], cb->bones[m].rotation);
|
glm_mat4_quat(cb->anim.cache.inter[m], cb->bones[m].rotation);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
dGeomID gid = cp->geom;
|
dGeomID gid = cp->geom;
|
||||||
@@ -691,7 +776,7 @@ void game_update() {
|
|||||||
|
|
||||||
for(size_t cm = 0; cm < Game.entities.movementCount; cm++) {
|
for(size_t cm = 0; cm < Game.entities.movementCount; cm++) {
|
||||||
struct CBoned *cb = game_getcomponent(Game.entities.movement[cm].entity, boned);
|
struct CBoned *cb = game_getcomponent(Game.entities.movement[cm].entity, boned);
|
||||||
if(cb && cb->anim.standard) {
|
/*if(cb && cb->anim.standard) {
|
||||||
struct CPhysics *cp = game_getcomponent(Game.entities.movement[cm].entity, physics);
|
struct CPhysics *cp = game_getcomponent(Game.entities.movement[cm].entity, physics);
|
||||||
if(cp && cp->geom) {
|
if(cp && cp->geom) {
|
||||||
dBodyID bid = dGeomGetBody(cp->geom);
|
dBodyID bid = dGeomGetBody(cp->geom);
|
||||||
@@ -704,7 +789,7 @@ void game_update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0; i < Game.conveyorCount; i++) {
|
for(size_t i = 0; i < Game.conveyorCount; i++) {
|
||||||
@@ -791,7 +876,6 @@ void game_update() {
|
|||||||
vec3 dif;
|
vec3 dif;
|
||||||
glm_vec3_sub(conveyor->points[nextPoint], conveyor->points[currentPoint], dif);
|
glm_vec3_sub(conveyor->points[nextPoint], conveyor->points[currentPoint], dif);
|
||||||
glm_vec3_scale_as(dif, conveyor->speed * (conveyor->active <= 0 ? -1 : 1), dif);
|
glm_vec3_scale_as(dif, conveyor->speed * (conveyor->active <= 0 ? -1 : 1), dif);
|
||||||
//printf("set %f %f %f\n", dif[0], dif[1], dif[2]);
|
|
||||||
dBodySetLinearVel(bid, dif[0], dif[1], dif[2]); // doesn't affect movement, but necessary for proper collision response
|
dBodySetLinearVel(bid, dif[0], dif[1], dif[2]); // doesn't affect movement, but necessary for proper collision response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -865,7 +949,7 @@ void game_cleanup() {
|
|||||||
Game.entities.renderCount = 0;
|
Game.entities.renderCount = 0;
|
||||||
|
|
||||||
for(size_t i = 0; i < Game.entities.bonedCount; i++) {
|
for(size_t i = 0; i < Game.entities.bonedCount; i++) {
|
||||||
free(Game.entities.boned[i].bones);
|
//free(Game.entities.boned[i].bones);
|
||||||
}
|
}
|
||||||
Game.entities.bonedCount = 0;
|
Game.entities.bonedCount = 0;
|
||||||
|
|
||||||
@@ -901,8 +985,8 @@ void game_cleanup() {
|
|||||||
Game.phys = dWorldCreate();
|
Game.phys = dWorldCreate();
|
||||||
dWorldSetGravity(Game.phys, 0, -15, 0);
|
dWorldSetGravity(Game.phys, 0, -15, 0);
|
||||||
|
|
||||||
dWorldSetCFM(Game.phys, 0.0001);
|
dWorldSetCFM(Game.phys, 0.00002);
|
||||||
dWorldSetERP(Game.phys, 0.5);
|
dWorldSetERP(Game.phys, 0.1);
|
||||||
|
|
||||||
Game.space = dHashSpaceCreate(NULL);
|
Game.space = dHashSpaceCreate(NULL);
|
||||||
|
|
||||||
@@ -916,10 +1000,14 @@ void game_killentity(uint16_t eid) {
|
|||||||
if(cp) {
|
if(cp) {
|
||||||
dBodyID bid = dGeomGetBody(cp->geom);
|
dBodyID bid = dGeomGetBody(cp->geom);
|
||||||
|
|
||||||
dGeomDestroy(cp->geom);
|
|
||||||
|
|
||||||
if(bid) {
|
if(bid) {
|
||||||
|
for(dGeomID gid = dBodyGetFirstGeom(bid); gid; gid = dBodyGetNextGeom(gid)) {
|
||||||
|
dGeomDestroy(gid);
|
||||||
|
}
|
||||||
|
|
||||||
dBodyDestroy(bid);
|
dBodyDestroy(bid);
|
||||||
|
} else {
|
||||||
|
dGeomDestroy(cp->geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
game_killcomponent_ptr(cp, physics);
|
game_killcomponent_ptr(cp, physics);
|
||||||
@@ -929,7 +1017,7 @@ void game_killentity(uint16_t eid) {
|
|||||||
if(cr) {
|
if(cr) {
|
||||||
if(cr->cache) {
|
if(cr->cache) {
|
||||||
if(resman_rev(cr->cache)) {
|
if(resman_rev(cr->cache)) {
|
||||||
resman_unref(RESMAN_MODEL, cr->cache);
|
resman_unref_ptr(RESMAN_MODEL, cr->cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
src/game.h
16
src/game.h
@@ -13,6 +13,7 @@
|
|||||||
#define CATEGORY_STATIC 1
|
#define CATEGORY_STATIC 1
|
||||||
#define CATEGORY_RAY 2
|
#define CATEGORY_RAY 2
|
||||||
#define CATEGORY_ENTITY 4
|
#define CATEGORY_ENTITY 4
|
||||||
|
#define CATEGORY_GHOST 8
|
||||||
|
|
||||||
#define TRIGGER_INVALID 0
|
#define TRIGGER_INVALID 0
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ struct TrimeshData {
|
|||||||
#define CPHYSICS_GHOST 128
|
#define CPHYSICS_GHOST 128
|
||||||
struct CPhysics {
|
struct CPhysics {
|
||||||
uint16_t entity;
|
uint16_t entity;
|
||||||
dGeomID geom;
|
dGeomID geom, geom2;
|
||||||
uint16_t trigger;
|
uint16_t trigger;
|
||||||
|
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -87,7 +88,9 @@ struct CMovement {
|
|||||||
uint16_t entity;
|
uint16_t entity;
|
||||||
vec3 dir;
|
vec3 dir;
|
||||||
float pointing;
|
float pointing;
|
||||||
char jump, canJump;
|
char jump, canJump, isJumping;
|
||||||
|
vec3 groundNormal;
|
||||||
|
float groundDepth;
|
||||||
uint16_t holding;
|
uint16_t holding;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,14 +118,7 @@ struct CPlayerCtrl {
|
|||||||
struct CBoned {
|
struct CBoned {
|
||||||
uint16_t entity;
|
uint16_t entity;
|
||||||
|
|
||||||
size_t size;
|
struct k3Animator animator;
|
||||||
struct k3AnimationBone *bones;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint16_t id;
|
|
||||||
struct k3Animator cache;
|
|
||||||
bool standard;
|
|
||||||
} anim;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CONVEYOR_TYPE_LOOP 0
|
#define CONVEYOR_TYPE_LOOP 0
|
||||||
|
|||||||
143
src/gl.h
143
src/gl.h
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* Loader generated by glad 2.0.8 on Fri May 9 09:20:04 2025
|
* Loader generated by glad 2.0.8 on Sun Oct 12 16:54:54 2025
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
|
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
|
||||||
*
|
*
|
||||||
* Generator: C/C++
|
* Generator: C/C++
|
||||||
* Specification: gl
|
* Specification: gl
|
||||||
* Extensions: 37
|
* Extensions: 40
|
||||||
*
|
*
|
||||||
* APIs:
|
* APIs:
|
||||||
* - gl:compatibility=4.6
|
* - gl:compatibility=4.6
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
* - ON_DEMAND = False
|
* - ON_DEMAND = False
|
||||||
*
|
*
|
||||||
* Commandline:
|
* Commandline:
|
||||||
* --api='gl:compatibility=4.6' --extensions='GL_ARB_compatibility,GL_ARB_debug_output,GL_ARB_fragment_program,GL_ARB_fragment_shader,GL_ARB_framebuffer_sRGB,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shading_language_100,GL_ARB_texture_compression_bptc,GL_ARB_texture_float,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_2_10_10_10_rev,GL_EXT_direct_state_access,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_shader4,GL_EXT_shader_image_load_store,GL_EXT_texture_array,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_integer,GL_EXT_texture_sRGB,GL_EXT_transform_feedback,GL_INTEL_conservative_rasterization,GL_KHR_texture_compression_astc_ldr,GL_NV_conservative_raster' c --header-only
|
* --api='gl:compatibility=4.6' --extensions='GL_ARB_compatibility,GL_ARB_debug_output,GL_ARB_direct_state_access,GL_ARB_fragment_program,GL_ARB_fragment_shader,GL_ARB_framebuffer_sRGB,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shading_language_100,GL_ARB_texture_compression_bptc,GL_ARB_texture_float,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_timer_query,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_2_10_10_10_rev,GL_EXT_direct_state_access,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_shader4,GL_EXT_shader_image_load_store,GL_EXT_texture_array,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_integer,GL_EXT_texture_sRGB,GL_EXT_transform_feedback,GL_INTEL_conservative_rasterization,GL_KHR_debug,GL_KHR_texture_compression_astc_ldr,GL_NV_conservative_raster' c --header-only
|
||||||
*
|
*
|
||||||
* Online:
|
* Online:
|
||||||
* http://glad.sh/#api=gl%3Acompatibility%3D4.6&extensions=GL_ARB_compatibility%2CGL_ARB_debug_output%2CGL_ARB_fragment_program%2CGL_ARB_fragment_shader%2CGL_ARB_framebuffer_sRGB%2CGL_ARB_shader_image_load_store%2CGL_ARB_shader_image_size%2CGL_ARB_shader_objects%2CGL_ARB_shader_storage_buffer_object%2CGL_ARB_shading_language_100%2CGL_ARB_texture_compression_bptc%2CGL_ARB_texture_float%2CGL_ARB_texture_rg%2CGL_ARB_texture_rgb10_a2ui%2CGL_ARB_vertex_buffer_object%2CGL_ARB_vertex_program%2CGL_ARB_vertex_shader%2CGL_ARB_vertex_type_2_10_10_10_rev%2CGL_EXT_direct_state_access%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_multisample%2CGL_EXT_framebuffer_multisample_blit_scaled%2CGL_EXT_framebuffer_object%2CGL_EXT_framebuffer_sRGB%2CGL_EXT_geometry_shader4%2CGL_EXT_gpu_shader4%2CGL_EXT_shader_image_load_store%2CGL_EXT_texture_array%2CGL_EXT_texture_compression_rgtc%2CGL_EXT_texture_compression_s3tc%2CGL_EXT_texture_filter_anisotropic%2CGL_EXT_texture_integer%2CGL_EXT_texture_sRGB%2CGL_EXT_transform_feedback%2CGL_INTEL_conservative_rasterization%2CGL_KHR_texture_compression_astc_ldr%2CGL_NV_conservative_raster&generator=c&options=HEADER_ONLY
|
* http://glad.sh/#api=gl%3Acompatibility%3D4.6&extensions=GL_ARB_compatibility%2CGL_ARB_debug_output%2CGL_ARB_direct_state_access%2CGL_ARB_fragment_program%2CGL_ARB_fragment_shader%2CGL_ARB_framebuffer_sRGB%2CGL_ARB_shader_image_load_store%2CGL_ARB_shader_image_size%2CGL_ARB_shader_objects%2CGL_ARB_shader_storage_buffer_object%2CGL_ARB_shading_language_100%2CGL_ARB_texture_compression_bptc%2CGL_ARB_texture_float%2CGL_ARB_texture_rg%2CGL_ARB_texture_rgb10_a2ui%2CGL_ARB_timer_query%2CGL_ARB_vertex_buffer_object%2CGL_ARB_vertex_program%2CGL_ARB_vertex_shader%2CGL_ARB_vertex_type_2_10_10_10_rev%2CGL_EXT_direct_state_access%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_multisample%2CGL_EXT_framebuffer_multisample_blit_scaled%2CGL_EXT_framebuffer_object%2CGL_EXT_framebuffer_sRGB%2CGL_EXT_geometry_shader4%2CGL_EXT_gpu_shader4%2CGL_EXT_shader_image_load_store%2CGL_EXT_texture_array%2CGL_EXT_texture_compression_rgtc%2CGL_EXT_texture_compression_s3tc%2CGL_EXT_texture_filter_anisotropic%2CGL_EXT_texture_integer%2CGL_EXT_texture_sRGB%2CGL_EXT_transform_feedback%2CGL_INTEL_conservative_rasterization%2CGL_KHR_debug%2CGL_KHR_texture_compression_astc_ldr%2CGL_NV_conservative_raster&generator=c&options=HEADER_ONLY
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2916,6 +2916,8 @@ GLAD_API_CALL int GLAD_GL_VERSION_4_6;
|
|||||||
GLAD_API_CALL int GLAD_GL_ARB_compatibility;
|
GLAD_API_CALL int GLAD_GL_ARB_compatibility;
|
||||||
#define GL_ARB_debug_output 1
|
#define GL_ARB_debug_output 1
|
||||||
GLAD_API_CALL int GLAD_GL_ARB_debug_output;
|
GLAD_API_CALL int GLAD_GL_ARB_debug_output;
|
||||||
|
#define GL_ARB_direct_state_access 1
|
||||||
|
GLAD_API_CALL int GLAD_GL_ARB_direct_state_access;
|
||||||
#define GL_ARB_fragment_program 1
|
#define GL_ARB_fragment_program 1
|
||||||
GLAD_API_CALL int GLAD_GL_ARB_fragment_program;
|
GLAD_API_CALL int GLAD_GL_ARB_fragment_program;
|
||||||
#define GL_ARB_fragment_shader 1
|
#define GL_ARB_fragment_shader 1
|
||||||
@@ -2940,6 +2942,8 @@ GLAD_API_CALL int GLAD_GL_ARB_texture_float;
|
|||||||
GLAD_API_CALL int GLAD_GL_ARB_texture_rg;
|
GLAD_API_CALL int GLAD_GL_ARB_texture_rg;
|
||||||
#define GL_ARB_texture_rgb10_a2ui 1
|
#define GL_ARB_texture_rgb10_a2ui 1
|
||||||
GLAD_API_CALL int GLAD_GL_ARB_texture_rgb10_a2ui;
|
GLAD_API_CALL int GLAD_GL_ARB_texture_rgb10_a2ui;
|
||||||
|
#define GL_ARB_timer_query 1
|
||||||
|
GLAD_API_CALL int GLAD_GL_ARB_timer_query;
|
||||||
#define GL_ARB_vertex_buffer_object 1
|
#define GL_ARB_vertex_buffer_object 1
|
||||||
GLAD_API_CALL int GLAD_GL_ARB_vertex_buffer_object;
|
GLAD_API_CALL int GLAD_GL_ARB_vertex_buffer_object;
|
||||||
#define GL_ARB_vertex_program 1
|
#define GL_ARB_vertex_program 1
|
||||||
@@ -2982,6 +2986,8 @@ GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB;
|
|||||||
GLAD_API_CALL int GLAD_GL_EXT_transform_feedback;
|
GLAD_API_CALL int GLAD_GL_EXT_transform_feedback;
|
||||||
#define GL_INTEL_conservative_rasterization 1
|
#define GL_INTEL_conservative_rasterization 1
|
||||||
GLAD_API_CALL int GLAD_GL_INTEL_conservative_rasterization;
|
GLAD_API_CALL int GLAD_GL_INTEL_conservative_rasterization;
|
||||||
|
#define GL_KHR_debug 1
|
||||||
|
GLAD_API_CALL int GLAD_GL_KHR_debug;
|
||||||
#define GL_KHR_texture_compression_astc_ldr 1
|
#define GL_KHR_texture_compression_astc_ldr 1
|
||||||
GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_ldr;
|
GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_ldr;
|
||||||
#define GL_NV_conservative_raster 1
|
#define GL_NV_conservative_raster 1
|
||||||
@@ -7530,6 +7536,7 @@ int GLAD_GL_VERSION_4_5 = 0;
|
|||||||
int GLAD_GL_VERSION_4_6 = 0;
|
int GLAD_GL_VERSION_4_6 = 0;
|
||||||
int GLAD_GL_ARB_compatibility = 0;
|
int GLAD_GL_ARB_compatibility = 0;
|
||||||
int GLAD_GL_ARB_debug_output = 0;
|
int GLAD_GL_ARB_debug_output = 0;
|
||||||
|
int GLAD_GL_ARB_direct_state_access = 0;
|
||||||
int GLAD_GL_ARB_fragment_program = 0;
|
int GLAD_GL_ARB_fragment_program = 0;
|
||||||
int GLAD_GL_ARB_fragment_shader = 0;
|
int GLAD_GL_ARB_fragment_shader = 0;
|
||||||
int GLAD_GL_ARB_framebuffer_sRGB = 0;
|
int GLAD_GL_ARB_framebuffer_sRGB = 0;
|
||||||
@@ -7542,6 +7549,7 @@ int GLAD_GL_ARB_texture_compression_bptc = 0;
|
|||||||
int GLAD_GL_ARB_texture_float = 0;
|
int GLAD_GL_ARB_texture_float = 0;
|
||||||
int GLAD_GL_ARB_texture_rg = 0;
|
int GLAD_GL_ARB_texture_rg = 0;
|
||||||
int GLAD_GL_ARB_texture_rgb10_a2ui = 0;
|
int GLAD_GL_ARB_texture_rgb10_a2ui = 0;
|
||||||
|
int GLAD_GL_ARB_timer_query = 0;
|
||||||
int GLAD_GL_ARB_vertex_buffer_object = 0;
|
int GLAD_GL_ARB_vertex_buffer_object = 0;
|
||||||
int GLAD_GL_ARB_vertex_program = 0;
|
int GLAD_GL_ARB_vertex_program = 0;
|
||||||
int GLAD_GL_ARB_vertex_shader = 0;
|
int GLAD_GL_ARB_vertex_shader = 0;
|
||||||
@@ -7563,6 +7571,7 @@ int GLAD_GL_EXT_texture_integer = 0;
|
|||||||
int GLAD_GL_EXT_texture_sRGB = 0;
|
int GLAD_GL_EXT_texture_sRGB = 0;
|
||||||
int GLAD_GL_EXT_transform_feedback = 0;
|
int GLAD_GL_EXT_transform_feedback = 0;
|
||||||
int GLAD_GL_INTEL_conservative_rasterization = 0;
|
int GLAD_GL_INTEL_conservative_rasterization = 0;
|
||||||
|
int GLAD_GL_KHR_debug = 0;
|
||||||
int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
|
int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
|
||||||
int GLAD_GL_NV_conservative_raster = 0;
|
int GLAD_GL_NV_conservative_raster = 0;
|
||||||
|
|
||||||
@@ -10179,6 +10188,106 @@ static void glad_gl_load_GL_ARB_debug_output( GLADuserptrloadfunc load, void* us
|
|||||||
glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load(userptr, "glDebugMessageInsertARB");
|
glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load(userptr, "glDebugMessageInsertARB");
|
||||||
glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load(userptr, "glGetDebugMessageLogARB");
|
glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load(userptr, "glGetDebugMessageLogARB");
|
||||||
}
|
}
|
||||||
|
static void glad_gl_load_GL_ARB_direct_state_access( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_GL_ARB_direct_state_access) return;
|
||||||
|
glad_glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC) load(userptr, "glBindTextureUnit");
|
||||||
|
glad_glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC) load(userptr, "glBlitNamedFramebuffer");
|
||||||
|
glad_glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckNamedFramebufferStatus");
|
||||||
|
glad_glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC) load(userptr, "glClearNamedBufferData");
|
||||||
|
glad_glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC) load(userptr, "glClearNamedBufferSubData");
|
||||||
|
glad_glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) load(userptr, "glClearNamedFramebufferfi");
|
||||||
|
glad_glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) load(userptr, "glClearNamedFramebufferfv");
|
||||||
|
glad_glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) load(userptr, "glClearNamedFramebufferiv");
|
||||||
|
glad_glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) load(userptr, "glClearNamedFramebufferuiv");
|
||||||
|
glad_glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) load(userptr, "glCompressedTextureSubImage1D");
|
||||||
|
glad_glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) load(userptr, "glCompressedTextureSubImage2D");
|
||||||
|
glad_glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) load(userptr, "glCompressedTextureSubImage3D");
|
||||||
|
glad_glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC) load(userptr, "glCopyNamedBufferSubData");
|
||||||
|
glad_glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC) load(userptr, "glCopyTextureSubImage1D");
|
||||||
|
glad_glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC) load(userptr, "glCopyTextureSubImage2D");
|
||||||
|
glad_glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC) load(userptr, "glCopyTextureSubImage3D");
|
||||||
|
glad_glCreateBuffers = (PFNGLCREATEBUFFERSPROC) load(userptr, "glCreateBuffers");
|
||||||
|
glad_glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC) load(userptr, "glCreateFramebuffers");
|
||||||
|
glad_glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC) load(userptr, "glCreateProgramPipelines");
|
||||||
|
glad_glCreateQueries = (PFNGLCREATEQUERIESPROC) load(userptr, "glCreateQueries");
|
||||||
|
glad_glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC) load(userptr, "glCreateRenderbuffers");
|
||||||
|
glad_glCreateSamplers = (PFNGLCREATESAMPLERSPROC) load(userptr, "glCreateSamplers");
|
||||||
|
glad_glCreateTextures = (PFNGLCREATETEXTURESPROC) load(userptr, "glCreateTextures");
|
||||||
|
glad_glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC) load(userptr, "glCreateTransformFeedbacks");
|
||||||
|
glad_glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC) load(userptr, "glCreateVertexArrays");
|
||||||
|
glad_glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC) load(userptr, "glDisableVertexArrayAttrib");
|
||||||
|
glad_glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC) load(userptr, "glEnableVertexArrayAttrib");
|
||||||
|
glad_glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) load(userptr, "glFlushMappedNamedBufferRange");
|
||||||
|
glad_glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC) load(userptr, "glGenerateTextureMipmap");
|
||||||
|
glad_glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) load(userptr, "glGetCompressedTextureImage");
|
||||||
|
glad_glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) load(userptr, "glGetNamedBufferParameteri64v");
|
||||||
|
glad_glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedBufferParameteriv");
|
||||||
|
glad_glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC) load(userptr, "glGetNamedBufferPointerv");
|
||||||
|
glad_glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC) load(userptr, "glGetNamedBufferSubData");
|
||||||
|
glad_glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferAttachmentParameteriv");
|
||||||
|
glad_glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferParameteriv");
|
||||||
|
glad_glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedRenderbufferParameteriv");
|
||||||
|
glad_glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC) load(userptr, "glGetQueryBufferObjecti64v");
|
||||||
|
glad_glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC) load(userptr, "glGetQueryBufferObjectiv");
|
||||||
|
glad_glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC) load(userptr, "glGetQueryBufferObjectui64v");
|
||||||
|
glad_glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC) load(userptr, "glGetQueryBufferObjectuiv");
|
||||||
|
glad_glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC) load(userptr, "glGetTextureImage");
|
||||||
|
glad_glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC) load(userptr, "glGetTextureLevelParameterfv");
|
||||||
|
glad_glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC) load(userptr, "glGetTextureLevelParameteriv");
|
||||||
|
glad_glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC) load(userptr, "glGetTextureParameterIiv");
|
||||||
|
glad_glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC) load(userptr, "glGetTextureParameterIuiv");
|
||||||
|
glad_glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC) load(userptr, "glGetTextureParameterfv");
|
||||||
|
glad_glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC) load(userptr, "glGetTextureParameteriv");
|
||||||
|
glad_glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC) load(userptr, "glGetTransformFeedbacki64_v");
|
||||||
|
glad_glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC) load(userptr, "glGetTransformFeedbacki_v");
|
||||||
|
glad_glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC) load(userptr, "glGetTransformFeedbackiv");
|
||||||
|
glad_glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC) load(userptr, "glGetVertexArrayIndexed64iv");
|
||||||
|
glad_glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC) load(userptr, "glGetVertexArrayIndexediv");
|
||||||
|
glad_glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC) load(userptr, "glGetVertexArrayiv");
|
||||||
|
glad_glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) load(userptr, "glInvalidateNamedFramebufferData");
|
||||||
|
glad_glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) load(userptr, "glInvalidateNamedFramebufferSubData");
|
||||||
|
glad_glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC) load(userptr, "glMapNamedBuffer");
|
||||||
|
glad_glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC) load(userptr, "glMapNamedBufferRange");
|
||||||
|
glad_glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC) load(userptr, "glNamedBufferData");
|
||||||
|
glad_glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC) load(userptr, "glNamedBufferStorage");
|
||||||
|
glad_glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC) load(userptr, "glNamedBufferSubData");
|
||||||
|
glad_glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) load(userptr, "glNamedFramebufferDrawBuffer");
|
||||||
|
glad_glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) load(userptr, "glNamedFramebufferDrawBuffers");
|
||||||
|
glad_glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) load(userptr, "glNamedFramebufferParameteri");
|
||||||
|
glad_glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) load(userptr, "glNamedFramebufferReadBuffer");
|
||||||
|
glad_glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glNamedFramebufferRenderbuffer");
|
||||||
|
glad_glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) load(userptr, "glNamedFramebufferTexture");
|
||||||
|
glad_glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glNamedFramebufferTextureLayer");
|
||||||
|
glad_glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC) load(userptr, "glNamedRenderbufferStorage");
|
||||||
|
glad_glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glNamedRenderbufferStorageMultisample");
|
||||||
|
glad_glTextureBuffer = (PFNGLTEXTUREBUFFERPROC) load(userptr, "glTextureBuffer");
|
||||||
|
glad_glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC) load(userptr, "glTextureBufferRange");
|
||||||
|
glad_glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC) load(userptr, "glTextureParameterIiv");
|
||||||
|
glad_glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC) load(userptr, "glTextureParameterIuiv");
|
||||||
|
glad_glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC) load(userptr, "glTextureParameterf");
|
||||||
|
glad_glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC) load(userptr, "glTextureParameterfv");
|
||||||
|
glad_glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC) load(userptr, "glTextureParameteri");
|
||||||
|
glad_glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC) load(userptr, "glTextureParameteriv");
|
||||||
|
glad_glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC) load(userptr, "glTextureStorage1D");
|
||||||
|
glad_glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC) load(userptr, "glTextureStorage2D");
|
||||||
|
glad_glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) load(userptr, "glTextureStorage2DMultisample");
|
||||||
|
glad_glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC) load(userptr, "glTextureStorage3D");
|
||||||
|
glad_glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) load(userptr, "glTextureStorage3DMultisample");
|
||||||
|
glad_glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC) load(userptr, "glTextureSubImage1D");
|
||||||
|
glad_glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC) load(userptr, "glTextureSubImage2D");
|
||||||
|
glad_glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC) load(userptr, "glTextureSubImage3D");
|
||||||
|
glad_glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) load(userptr, "glTransformFeedbackBufferBase");
|
||||||
|
glad_glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) load(userptr, "glTransformFeedbackBufferRange");
|
||||||
|
glad_glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC) load(userptr, "glUnmapNamedBuffer");
|
||||||
|
glad_glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC) load(userptr, "glVertexArrayAttribBinding");
|
||||||
|
glad_glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC) load(userptr, "glVertexArrayAttribFormat");
|
||||||
|
glad_glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC) load(userptr, "glVertexArrayAttribIFormat");
|
||||||
|
glad_glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC) load(userptr, "glVertexArrayAttribLFormat");
|
||||||
|
glad_glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC) load(userptr, "glVertexArrayBindingDivisor");
|
||||||
|
glad_glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC) load(userptr, "glVertexArrayElementBuffer");
|
||||||
|
glad_glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC) load(userptr, "glVertexArrayVertexBuffer");
|
||||||
|
glad_glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC) load(userptr, "glVertexArrayVertexBuffers");
|
||||||
|
}
|
||||||
static void glad_gl_load_GL_ARB_fragment_program( GLADuserptrloadfunc load, void* userptr) {
|
static void glad_gl_load_GL_ARB_fragment_program( GLADuserptrloadfunc load, void* userptr) {
|
||||||
if(!GLAD_GL_ARB_fragment_program) return;
|
if(!GLAD_GL_ARB_fragment_program) return;
|
||||||
glad_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB");
|
glad_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB");
|
||||||
@@ -10252,6 +10361,12 @@ static void glad_gl_load_GL_ARB_shader_storage_buffer_object( GLADuserptrloadfun
|
|||||||
if(!GLAD_GL_ARB_shader_storage_buffer_object) return;
|
if(!GLAD_GL_ARB_shader_storage_buffer_object) return;
|
||||||
glad_glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC) load(userptr, "glShaderStorageBlockBinding");
|
glad_glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC) load(userptr, "glShaderStorageBlockBinding");
|
||||||
}
|
}
|
||||||
|
static void glad_gl_load_GL_ARB_timer_query( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_GL_ARB_timer_query) return;
|
||||||
|
glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v");
|
||||||
|
glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v");
|
||||||
|
glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter");
|
||||||
|
}
|
||||||
static void glad_gl_load_GL_ARB_vertex_buffer_object( GLADuserptrloadfunc load, void* userptr) {
|
static void glad_gl_load_GL_ARB_vertex_buffer_object( GLADuserptrloadfunc load, void* userptr) {
|
||||||
if(!GLAD_GL_ARB_vertex_buffer_object) return;
|
if(!GLAD_GL_ARB_vertex_buffer_object) return;
|
||||||
glad_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) load(userptr, "glBindBufferARB");
|
glad_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) load(userptr, "glBindBufferARB");
|
||||||
@@ -10776,6 +10891,20 @@ static void glad_gl_load_GL_EXT_transform_feedback( GLADuserptrloadfunc load, vo
|
|||||||
glad_glGetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) load(userptr, "glGetTransformFeedbackVaryingEXT");
|
glad_glGetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) load(userptr, "glGetTransformFeedbackVaryingEXT");
|
||||||
glad_glTransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) load(userptr, "glTransformFeedbackVaryingsEXT");
|
glad_glTransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) load(userptr, "glTransformFeedbackVaryingsEXT");
|
||||||
}
|
}
|
||||||
|
static void glad_gl_load_GL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
|
||||||
|
if(!GLAD_GL_KHR_debug) return;
|
||||||
|
glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load(userptr, "glDebugMessageCallback");
|
||||||
|
glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load(userptr, "glDebugMessageControl");
|
||||||
|
glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load(userptr, "glDebugMessageInsert");
|
||||||
|
glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load(userptr, "glGetDebugMessageLog");
|
||||||
|
glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load(userptr, "glGetObjectLabel");
|
||||||
|
glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load(userptr, "glGetObjectPtrLabel");
|
||||||
|
glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv");
|
||||||
|
glad_glObjectLabel = (PFNGLOBJECTLABELPROC) load(userptr, "glObjectLabel");
|
||||||
|
glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load(userptr, "glObjectPtrLabel");
|
||||||
|
glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load(userptr, "glPopDebugGroup");
|
||||||
|
glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load(userptr, "glPushDebugGroup");
|
||||||
|
}
|
||||||
static void glad_gl_load_GL_NV_conservative_raster( GLADuserptrloadfunc load, void* userptr) {
|
static void glad_gl_load_GL_NV_conservative_raster( GLADuserptrloadfunc load, void* userptr) {
|
||||||
if(!GLAD_GL_NV_conservative_raster) return;
|
if(!GLAD_GL_NV_conservative_raster) return;
|
||||||
glad_glSubpixelPrecisionBiasNV = (PFNGLSUBPIXELPRECISIONBIASNVPROC) load(userptr, "glSubpixelPrecisionBiasNV");
|
glad_glSubpixelPrecisionBiasNV = (PFNGLSUBPIXELPRECISIONBIASNVPROC) load(userptr, "glSubpixelPrecisionBiasNV");
|
||||||
@@ -10877,6 +11006,7 @@ static int glad_gl_find_extensions_gl(void) {
|
|||||||
|
|
||||||
GLAD_GL_ARB_compatibility = glad_gl_has_extension(exts, exts_i, "GL_ARB_compatibility");
|
GLAD_GL_ARB_compatibility = glad_gl_has_extension(exts, exts_i, "GL_ARB_compatibility");
|
||||||
GLAD_GL_ARB_debug_output = glad_gl_has_extension(exts, exts_i, "GL_ARB_debug_output");
|
GLAD_GL_ARB_debug_output = glad_gl_has_extension(exts, exts_i, "GL_ARB_debug_output");
|
||||||
|
GLAD_GL_ARB_direct_state_access = glad_gl_has_extension(exts, exts_i, "GL_ARB_direct_state_access");
|
||||||
GLAD_GL_ARB_fragment_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_program");
|
GLAD_GL_ARB_fragment_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_program");
|
||||||
GLAD_GL_ARB_fragment_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_shader");
|
GLAD_GL_ARB_fragment_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_shader");
|
||||||
GLAD_GL_ARB_framebuffer_sRGB = glad_gl_has_extension(exts, exts_i, "GL_ARB_framebuffer_sRGB");
|
GLAD_GL_ARB_framebuffer_sRGB = glad_gl_has_extension(exts, exts_i, "GL_ARB_framebuffer_sRGB");
|
||||||
@@ -10889,6 +11019,7 @@ static int glad_gl_find_extensions_gl(void) {
|
|||||||
GLAD_GL_ARB_texture_float = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_float");
|
GLAD_GL_ARB_texture_float = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_float");
|
||||||
GLAD_GL_ARB_texture_rg = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rg");
|
GLAD_GL_ARB_texture_rg = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rg");
|
||||||
GLAD_GL_ARB_texture_rgb10_a2ui = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rgb10_a2ui");
|
GLAD_GL_ARB_texture_rgb10_a2ui = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rgb10_a2ui");
|
||||||
|
GLAD_GL_ARB_timer_query = glad_gl_has_extension(exts, exts_i, "GL_ARB_timer_query");
|
||||||
GLAD_GL_ARB_vertex_buffer_object = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_buffer_object");
|
GLAD_GL_ARB_vertex_buffer_object = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_buffer_object");
|
||||||
GLAD_GL_ARB_vertex_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_program");
|
GLAD_GL_ARB_vertex_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_program");
|
||||||
GLAD_GL_ARB_vertex_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_shader");
|
GLAD_GL_ARB_vertex_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_shader");
|
||||||
@@ -10910,6 +11041,7 @@ static int glad_gl_find_extensions_gl(void) {
|
|||||||
GLAD_GL_EXT_texture_sRGB = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_sRGB");
|
GLAD_GL_EXT_texture_sRGB = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_sRGB");
|
||||||
GLAD_GL_EXT_transform_feedback = glad_gl_has_extension(exts, exts_i, "GL_EXT_transform_feedback");
|
GLAD_GL_EXT_transform_feedback = glad_gl_has_extension(exts, exts_i, "GL_EXT_transform_feedback");
|
||||||
GLAD_GL_INTEL_conservative_rasterization = glad_gl_has_extension(exts, exts_i, "GL_INTEL_conservative_rasterization");
|
GLAD_GL_INTEL_conservative_rasterization = glad_gl_has_extension(exts, exts_i, "GL_INTEL_conservative_rasterization");
|
||||||
|
GLAD_GL_KHR_debug = glad_gl_has_extension(exts, exts_i, "GL_KHR_debug");
|
||||||
GLAD_GL_KHR_texture_compression_astc_ldr = glad_gl_has_extension(exts, exts_i, "GL_KHR_texture_compression_astc_ldr");
|
GLAD_GL_KHR_texture_compression_astc_ldr = glad_gl_has_extension(exts, exts_i, "GL_KHR_texture_compression_astc_ldr");
|
||||||
GLAD_GL_NV_conservative_raster = glad_gl_has_extension(exts, exts_i, "GL_NV_conservative_raster");
|
GLAD_GL_NV_conservative_raster = glad_gl_has_extension(exts, exts_i, "GL_NV_conservative_raster");
|
||||||
|
|
||||||
@@ -10994,10 +11126,12 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
|
|||||||
|
|
||||||
if (!glad_gl_find_extensions_gl()) return 0;
|
if (!glad_gl_find_extensions_gl()) return 0;
|
||||||
glad_gl_load_GL_ARB_debug_output(load, userptr);
|
glad_gl_load_GL_ARB_debug_output(load, userptr);
|
||||||
|
glad_gl_load_GL_ARB_direct_state_access(load, userptr);
|
||||||
glad_gl_load_GL_ARB_fragment_program(load, userptr);
|
glad_gl_load_GL_ARB_fragment_program(load, userptr);
|
||||||
glad_gl_load_GL_ARB_shader_image_load_store(load, userptr);
|
glad_gl_load_GL_ARB_shader_image_load_store(load, userptr);
|
||||||
glad_gl_load_GL_ARB_shader_objects(load, userptr);
|
glad_gl_load_GL_ARB_shader_objects(load, userptr);
|
||||||
glad_gl_load_GL_ARB_shader_storage_buffer_object(load, userptr);
|
glad_gl_load_GL_ARB_shader_storage_buffer_object(load, userptr);
|
||||||
|
glad_gl_load_GL_ARB_timer_query(load, userptr);
|
||||||
glad_gl_load_GL_ARB_vertex_buffer_object(load, userptr);
|
glad_gl_load_GL_ARB_vertex_buffer_object(load, userptr);
|
||||||
glad_gl_load_GL_ARB_vertex_program(load, userptr);
|
glad_gl_load_GL_ARB_vertex_program(load, userptr);
|
||||||
glad_gl_load_GL_ARB_vertex_shader(load, userptr);
|
glad_gl_load_GL_ARB_vertex_shader(load, userptr);
|
||||||
@@ -11012,6 +11146,7 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
|
|||||||
glad_gl_load_GL_EXT_texture_array(load, userptr);
|
glad_gl_load_GL_EXT_texture_array(load, userptr);
|
||||||
glad_gl_load_GL_EXT_texture_integer(load, userptr);
|
glad_gl_load_GL_EXT_texture_integer(load, userptr);
|
||||||
glad_gl_load_GL_EXT_transform_feedback(load, userptr);
|
glad_gl_load_GL_EXT_transform_feedback(load, userptr);
|
||||||
|
glad_gl_load_GL_KHR_debug(load, userptr);
|
||||||
glad_gl_load_GL_NV_conservative_raster(load, userptr);
|
glad_gl_load_GL_NV_conservative_raster(load, userptr);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
36
src/k3mix.c
36
src/k3mix.c
@@ -6,6 +6,11 @@
|
|||||||
#include<math.h>
|
#include<math.h>
|
||||||
#include<pthread.h>
|
#include<pthread.h>
|
||||||
#include<assert.h>
|
#include<assert.h>
|
||||||
|
#include"k3.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#endif
|
||||||
|
|
||||||
static uint32_t FinalSampleRate;
|
static uint32_t FinalSampleRate;
|
||||||
static uint8_t FinalChannels;
|
static uint8_t FinalChannels;
|
||||||
@@ -19,12 +24,22 @@ struct k3MixSource {
|
|||||||
char *filepath;
|
char *filepath;
|
||||||
OggVorbis_File vf;
|
OggVorbis_File vf;
|
||||||
int bitstream;
|
int bitstream;
|
||||||
|
size_t looppoint;
|
||||||
};
|
};
|
||||||
struct k3MixSource *k3MixSourceFile(const char *path) {
|
struct k3MixSource *k3MixSourceFile(const char *path) {
|
||||||
struct k3MixSource *ret = calloc(1, sizeof(*ret));
|
struct k3MixSource *ret = calloc(1, sizeof(*ret));
|
||||||
ret->filepath = strdup(path);
|
ret->filepath = strdup(path);
|
||||||
ov_fopen(path, &ret->vf);
|
ov_fopen(path, &ret->vf);
|
||||||
ret->bitstream = 0;
|
ret->bitstream = 0;
|
||||||
|
|
||||||
|
ret->looppoint = 0;
|
||||||
|
for(size_t ci = 0; ci < ret->vf.vc->comments; ci++) {
|
||||||
|
if(strncasecmp(ret->vf.vc->user_comments[ci], "looppoint=", 10) == 0) {
|
||||||
|
ret->looppoint = strtol(ret->vf.vc->user_comments[ci] + 10, NULL, 0);
|
||||||
|
k3Log(k3_DEBUG, "%s has loop point %lu", path, ret->looppoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
void k3MixSourceClose(struct k3MixSource *src) {
|
void k3MixSourceClose(struct k3MixSource *src) {
|
||||||
@@ -42,7 +57,7 @@ __attribute__((optimize("Ofast"))) static intmax_t ogg_read(struct k3MixWave *th
|
|||||||
long lastRead = ov_read_float(&od->vf, &ni, sampleCount, &od->bitstream);
|
long lastRead = ov_read_float(&od->vf, &ni, sampleCount, &od->bitstream);
|
||||||
|
|
||||||
if(this->loop && lastRead == 0) {
|
if(this->loop && lastRead == 0) {
|
||||||
ov_pcm_seek(&od->vf, 0);
|
ov_pcm_seek(&od->vf, od->looppoint);
|
||||||
continue;
|
continue;
|
||||||
} else if(lastRead <= 0) {
|
} else if(lastRead <= 0) {
|
||||||
this->end = true;
|
this->end = true;
|
||||||
@@ -161,12 +176,13 @@ static void queue_clone(struct k3MixWave *this, struct k3MixWave *new) {
|
|||||||
new->clone = queue_clone;
|
new->clone = queue_clone;
|
||||||
new->close = queue_close;
|
new->close = queue_close;
|
||||||
|
|
||||||
|
new->end = this->end;
|
||||||
new->loop = this->loop;
|
new->loop = this->loop;
|
||||||
new->dam = this->dam;
|
new->dam = this->dam;
|
||||||
new->volume = this->volume;
|
new->volume = this->volume;
|
||||||
}
|
}
|
||||||
struct k3MixWave *k3MixQueue() {
|
struct k3MixWave *k3MixQueue() {
|
||||||
struct k3MixWave *ret = malloc(sizeof(*ret));
|
struct k3MixWave *ret = calloc(1, sizeof(*ret));
|
||||||
ret->refs = 1;
|
ret->refs = 1;
|
||||||
ret->sampleRate = FinalSampleRate;
|
ret->sampleRate = FinalSampleRate;
|
||||||
ret->channels = FinalChannels;
|
ret->channels = FinalChannels;
|
||||||
@@ -182,6 +198,7 @@ struct k3MixWave *k3MixQueue() {
|
|||||||
ret->loop = 0;
|
ret->loop = 0;
|
||||||
ret->dam = 0;
|
ret->dam = 0;
|
||||||
ret->volume = 1;
|
ret->volume = 1;
|
||||||
|
ret->end = false;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -260,6 +277,7 @@ static void power_measurement_clone(struct k3MixWave *this, struct k3MixWave *ne
|
|||||||
new->clone = power_measurement_clone;
|
new->clone = power_measurement_clone;
|
||||||
new->close = power_measurement_close;
|
new->close = power_measurement_close;
|
||||||
|
|
||||||
|
new->end = this->end;
|
||||||
new->loop = this->loop;
|
new->loop = this->loop;
|
||||||
new->dam = this->dam;
|
new->dam = this->dam;
|
||||||
new->volume = this->volume;
|
new->volume = this->volume;
|
||||||
@@ -308,6 +326,10 @@ struct k3MixWave *k3MixPowerMeasurement(struct k3MixWave *child) {
|
|||||||
static size_t playingCount, playingCapacity;
|
static size_t playingCount, playingCapacity;
|
||||||
static struct k3MixWave **playings;
|
static struct k3MixWave **playings;
|
||||||
|
|
||||||
|
void k3MixStopSmooth(struct k3MixWave *wav) {
|
||||||
|
wav->fade = -0.01;
|
||||||
|
}
|
||||||
|
|
||||||
void k3MixStop(struct k3MixWave *wav) {
|
void k3MixStop(struct k3MixWave *wav) {
|
||||||
for(size_t i = 0; i < playingCount; i++) {
|
for(size_t i = 0; i < playingCount; i++) {
|
||||||
if(playings[i] == wav) {
|
if(playings[i] == wav) {
|
||||||
@@ -346,6 +368,16 @@ __attribute__((optimize("Ofast"))) static void k3MixDoYourThang(size_t sampleCou
|
|||||||
for(size_t i = 0; i < playingCount;) {
|
for(size_t i = 0; i < playingCount;) {
|
||||||
intmax_t read = playings[i]->read(playings[i], sampleCount, FinalData);
|
intmax_t read = playings[i]->read(playings[i], sampleCount, FinalData);
|
||||||
|
|
||||||
|
if(playings[i]->fade) {
|
||||||
|
playings[i]->volume += playings[i]->fade;
|
||||||
|
if(playings[i]->volume > 1) {
|
||||||
|
playings[i]->volume = 1;
|
||||||
|
playings[i]->fade = 0;
|
||||||
|
} else if(playings[i]->volume < 0) {
|
||||||
|
playings[i]->end = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(playings[i]->end) {
|
if(playings[i]->end) {
|
||||||
k3MixStop(playings[i]);
|
k3MixStop(playings[i]);
|
||||||
} else i++;
|
} else i++;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ struct k3MixWave {
|
|||||||
bool end;
|
bool end;
|
||||||
uint16_t dam;
|
uint16_t dam;
|
||||||
float volume;
|
float volume;
|
||||||
|
float fade;
|
||||||
};
|
};
|
||||||
|
|
||||||
void k3MixInit(uint32_t sampleRate, uint8_t channels);
|
void k3MixInit(uint32_t sampleRate, uint8_t channels);
|
||||||
@@ -44,6 +45,7 @@ struct k3MixWave *k3MixPowerMeasurement(struct k3MixWave *child);
|
|||||||
float k3MixPowerMeasurementGetRMS(struct k3MixWave*);
|
float k3MixPowerMeasurementGetRMS(struct k3MixWave*);
|
||||||
|
|
||||||
void k3MixStop(struct k3MixWave*);
|
void k3MixStop(struct k3MixWave*);
|
||||||
|
void k3MixStopSmooth(struct k3MixWave*);
|
||||||
struct k3MixWave *k3MixPlay(struct k3MixWave*);
|
struct k3MixWave *k3MixPlay(struct k3MixWave*);
|
||||||
void k3MixPlayDirect(struct k3MixWave*);
|
void k3MixPlayDirect(struct k3MixWave*);
|
||||||
|
|
||||||
|
|||||||
2
src/k4.h
2
src/k4.h
@@ -45,3 +45,5 @@ void k4_set_texture_reduction(int);
|
|||||||
|
|
||||||
void k4_set_clipboard_text(const char *str);
|
void k4_set_clipboard_text(const char *str);
|
||||||
const char *k4_get_clipboard_text();
|
const char *k4_get_clipboard_text();
|
||||||
|
|
||||||
|
void k4_set_ui_mode(bool yes);
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ static int mdlloader(void *ud, struct ResManRes *res) {
|
|||||||
} header;
|
} header;
|
||||||
fread(&header, 4, 4, f);
|
fread(&header, 4, 4, f);
|
||||||
|
|
||||||
|
// ' ' or '1'
|
||||||
|
char version = ((char*) &header.magic)[3];
|
||||||
|
|
||||||
int colorsEnabled = header.flags & 1;
|
int colorsEnabled = header.flags & 1;
|
||||||
|
|
||||||
mat4 *invBind = _mm_malloc(sizeof(*invBind) * header.boneCount, 16);
|
mat4 *invBind = _mm_malloc(sizeof(*invBind) * header.boneCount, 16);
|
||||||
@@ -33,6 +36,17 @@ static int mdlloader(void *ud, struct ResManRes *res) {
|
|||||||
uint8_t *boneParents = malloc(header.boneCount);
|
uint8_t *boneParents = malloc(header.boneCount);
|
||||||
fread(boneParents, 1, header.boneCount, f);
|
fread(boneParents, 1, header.boneCount, f);
|
||||||
|
|
||||||
|
char boneNames[1500] = {};
|
||||||
|
size_t boneNamesLen = 0;
|
||||||
|
for(size_t b = 0; b < header.boneCount; b++) {
|
||||||
|
while(1) {
|
||||||
|
fread(boneNames + boneNamesLen, 1, 1, f);
|
||||||
|
if(boneNames[boneNamesLen++] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vec3 *pos = malloc(sizeof(*pos) * header.vertCount);
|
vec3 *pos = malloc(sizeof(*pos) * header.vertCount);
|
||||||
fread(pos, sizeof(vec3), header.vertCount, f);
|
fread(pos, sizeof(vec3), header.vertCount, f);
|
||||||
|
|
||||||
@@ -59,6 +73,8 @@ static int mdlloader(void *ud, struct ResManRes *res) {
|
|||||||
|
|
||||||
struct k3Mdl *mdl = k3MdlCreate(header.vertCount, header.indCount, header.boneCount, pos, nrm, uvs, cols, boneIDs, boneWeights, inds, invBind, boneParents);
|
struct k3Mdl *mdl = k3MdlCreate(header.vertCount, header.indCount, header.boneCount, pos, nrm, uvs, cols, boneIDs, boneWeights, inds, invBind, boneParents);
|
||||||
|
|
||||||
|
k3MdlSetBoneNames(mdl, boneNames);
|
||||||
|
|
||||||
k3MdlSetDebugName(mdl, res->name);
|
k3MdlSetDebugName(mdl, res->name);
|
||||||
|
|
||||||
free(pos);
|
free(pos);
|
||||||
@@ -70,8 +86,11 @@ static int mdlloader(void *ud, struct ResManRes *res) {
|
|||||||
fread(&meshes, sizeof(uint16_t), 1, f);
|
fread(&meshes, sizeof(uint16_t), 1, f);
|
||||||
|
|
||||||
for(uint32_t i = 0; i < meshes; i++) {
|
for(uint32_t i = 0; i < meshes; i++) {
|
||||||
uint16_t startnum[2];
|
uint32_t start = 0;
|
||||||
fread(startnum, sizeof(uint16_t), 2, f);
|
uint32_t number = 0;
|
||||||
|
|
||||||
|
fread(&start, version == ' ' ? sizeof(uint16_t) : sizeof(uint32_t), 1, f);
|
||||||
|
fread(&number, version == ' ' ? sizeof(uint16_t) : sizeof(uint32_t), 1, f);
|
||||||
|
|
||||||
char buf[256] = {};
|
char buf[256] = {};
|
||||||
for(int c = 0; c < sizeof(buf) - 1; c++) {
|
for(int c = 0; c < sizeof(buf) - 1; c++) {
|
||||||
@@ -81,28 +100,25 @@ static int mdlloader(void *ud, struct ResManRes *res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
k3MdlAddMesh(mdl, resman_ref(RESMAN_MATERIAL, buf), startnum[0], startnum[1]);
|
k3MdlAddMesh(mdl, resman_ref(RESMAN_MATERIAL, buf), start, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0; i < header.animCount; i++) {
|
for(size_t i = 0; i < header.animCount; i++) {
|
||||||
struct {
|
struct {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
uint16_t frames;
|
uint16_t frameCount;
|
||||||
uint16_t fps;
|
uint16_t fps;
|
||||||
uint16_t zero;
|
uint16_t zero;
|
||||||
} info;
|
} info;
|
||||||
fread(&info, sizeof(info), 1, f);
|
fread(&info, sizeof(info), 1, f);
|
||||||
|
|
||||||
struct k3Animation *anim = malloc(sizeof(*anim));
|
struct k3AnimationFountain *anim = _mm_malloc(sizeof(*anim) + sizeof(*anim->frames) * info.frameCount * header.boneCount, 16);
|
||||||
anim->frames = _mm_malloc(sizeof(*anim->frames) * info.frames * header.boneCount, 16);
|
|
||||||
anim->boneParents = boneParents;
|
|
||||||
anim->invBind = invBind;
|
|
||||||
anim->id = info.id;
|
anim->id = info.id;
|
||||||
anim->fps = info.fps;
|
anim->fps = info.fps;
|
||||||
anim->frameCount = info.frames;
|
anim->frameCount = info.frameCount;
|
||||||
anim->boneCount = header.boneCount;
|
anim->bones = header.boneCount;
|
||||||
|
|
||||||
fread(anim->frames, sizeof(*anim->frames), info.frames * header.boneCount, f);
|
fread(anim->frames, sizeof(*anim->frames), info.frameCount * header.boneCount, f);
|
||||||
|
|
||||||
k3MdlAddAnim(mdl, anim);
|
k3MdlAddAnim(mdl, anim);
|
||||||
}
|
}
|
||||||
@@ -168,7 +184,7 @@ static int streamloader(void *ud, struct ResManRes *res) {
|
|||||||
snprintf(namebuf, sizeof(namebuf), "assets/aud/%s", res->name);
|
snprintf(namebuf, sizeof(namebuf), "assets/aud/%s", res->name);
|
||||||
|
|
||||||
res->thing = k3MixSourceFile(namebuf);
|
res->thing = k3MixSourceFile(namebuf);
|
||||||
return 1;
|
return !!res->thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int refresh_texture(struct ResManRes *res) {
|
static int refresh_texture(struct ResManRes *res) {
|
||||||
@@ -317,19 +333,11 @@ static int texloader(void *ud, struct ResManRes *res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int fontloader(void *ud, struct ResManRes *res) {
|
static int fontloader(void *ud, struct ResManRes *res) {
|
||||||
FILE *fntf = fopen(res->name, "rb");
|
char namebuf[256];
|
||||||
fseek(fntf, 0, SEEK_END);
|
snprintf(namebuf, sizeof(namebuf), "assets/%s", res->name);
|
||||||
size_t fntfsz = ftell(fntf);
|
|
||||||
fseek(fntf, 0, SEEK_SET);
|
|
||||||
char *fntbuf = malloc(fntfsz);
|
|
||||||
fread(fntbuf, 1, fntfsz, fntf);
|
|
||||||
|
|
||||||
struct k3Font *fnt = k3FontCreate();
|
struct k3Font *fnt = k3FontCreate();
|
||||||
struct k3Tex *fnttexldr(struct k3Font *fnt, const char *name) {
|
k3FontLoad(fnt, namebuf);
|
||||||
return resman_ref(RESMAN_TEXTURE, name);
|
|
||||||
}
|
|
||||||
k3FontLoad(fnt, fntbuf, fntfsz, fnttexldr);
|
|
||||||
|
|
||||||
res->thing = fnt;
|
res->thing = fnt;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
1222
src/luaapi.c
1222
src/luaapi.c
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,8 @@ extern int LuaapiFirstPerson;
|
|||||||
|
|
||||||
extern double LuaapiStartTime;
|
extern double LuaapiStartTime;
|
||||||
extern float LuaapiFov;
|
extern float LuaapiFov;
|
||||||
|
extern float LuaapiNear;
|
||||||
|
extern float LuaapiFar;
|
||||||
|
|
||||||
extern struct k3Tex *LuaapiSkybox;
|
extern struct k3Tex *LuaapiSkybox;
|
||||||
extern vec4 LuaapiSkyboxRotation;
|
extern vec4 LuaapiSkyboxRotation;
|
||||||
|
|||||||
100
src/main.c
100
src/main.c
@@ -28,6 +28,7 @@
|
|||||||
#include"k3font.h"
|
#include"k3font.h"
|
||||||
#include"k3menu.h"
|
#include"k3menu.h"
|
||||||
#include"k3bloom.h"
|
#include"k3bloom.h"
|
||||||
|
#include"k3batch.h"
|
||||||
|
|
||||||
#include"resman.h"
|
#include"resman.h"
|
||||||
|
|
||||||
@@ -37,10 +38,13 @@
|
|||||||
|
|
||||||
#include"net_server.h"
|
#include"net_server.h"
|
||||||
#include"net_client.h"
|
#include"net_client.h"
|
||||||
|
#include"net_hi.h"
|
||||||
|
|
||||||
#include<ctype.h>
|
#include<ctype.h>
|
||||||
|
|
||||||
GLFWwindow *GameWnd;
|
GLFWwindow *GameWnd;
|
||||||
|
uint16_t GameWndW;
|
||||||
|
uint16_t GameWndH;
|
||||||
|
|
||||||
static int TextureResolutionReduction = 0;
|
static int TextureResolutionReduction = 0;
|
||||||
|
|
||||||
@@ -58,7 +62,7 @@ static double LastTime;
|
|||||||
|
|
||||||
#include"loaders.inc"
|
#include"loaders.inc"
|
||||||
|
|
||||||
void set_ui_mode(int yes) {
|
void k4_set_ui_mode(bool yes) {
|
||||||
glfwSetInputMode(GameWnd, GLFW_CURSOR, yes ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
|
glfwSetInputMode(GameWnd, GLFW_CURSOR, yes ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,9 +74,6 @@ static double xposold, yposold;
|
|||||||
static void buttoncallback(GLFWwindow *GameWnd, int button, int action, int mods) {
|
static void buttoncallback(GLFWwindow *GameWnd, int button, int action, int mods) {
|
||||||
if(button == GLFW_MOUSE_BUTTON_LEFT) {
|
if(button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||||
if(UiActive) {
|
if(UiActive) {
|
||||||
int ww, wh;
|
|
||||||
glfwGetWindowSize(GameWnd, &ww, &wh);
|
|
||||||
|
|
||||||
struct k3MEvent ev = {
|
struct k3MEvent ev = {
|
||||||
.original = (void*) UiActive,
|
.original = (void*) UiActive,
|
||||||
.target = (void*) UiActive,
|
.target = (void*) UiActive,
|
||||||
@@ -80,8 +81,8 @@ static void buttoncallback(GLFWwindow *GameWnd, int button, int action, int mods
|
|||||||
.code = action == GLFW_PRESS ? k3M_EVENT_MOUSE_PRESS : k3M_EVENT_MOUSE_RELEASE,
|
.code = action == GLFW_PRESS ? k3M_EVENT_MOUSE_PRESS : k3M_EVENT_MOUSE_RELEASE,
|
||||||
.mouse = {
|
.mouse = {
|
||||||
.button = k3M_MOUSE_BUTTON_0,
|
.button = k3M_MOUSE_BUTTON_0,
|
||||||
.x = xposold * UiActive->w / ww,
|
.x = xposold * UiActive->w / GameWndW,
|
||||||
.y = (wh - yposold - 1) * UiActive->h / wh,
|
.y = yposold * UiActive->h / GameWndH,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,11 +111,8 @@ static void motioncallback(GLFWwindow *GameWnd, double xpos, double ypos) {
|
|||||||
first = 0;
|
first = 0;
|
||||||
|
|
||||||
if(UiActive) {
|
if(UiActive) {
|
||||||
int ww, wh;
|
uint16_t uix = xposold * UiActive->w / GameWndW;
|
||||||
glfwGetWindowSize(GameWnd, &ww, &wh);
|
uint16_t uiy = yposold * UiActive->h / GameWndH;
|
||||||
|
|
||||||
uint16_t uix = xposold * UiActive->w / ww;
|
|
||||||
uint16_t uiy = (wh - yposold - 1) * UiActive->h / wh;
|
|
||||||
|
|
||||||
struct k3MEvent ev = {
|
struct k3MEvent ev = {
|
||||||
.original = (void*) UiActive,
|
.original = (void*) UiActive,
|
||||||
@@ -134,7 +132,7 @@ static void motioncallback(GLFWwindow *GameWnd, double xpos, double ypos) {
|
|||||||
static void keycallback(GLFWwindow *GameWnd, int key, int scancode, int action, int mods) {
|
static void keycallback(GLFWwindow *GameWnd, int key, int scancode, int action, int mods) {
|
||||||
if(action == GLFW_RELEASE && key == GLFW_KEY_ESCAPE) {
|
if(action == GLFW_RELEASE && key == GLFW_KEY_ESCAPE) {
|
||||||
luaapi_escape();
|
luaapi_escape();
|
||||||
set_ui_mode(!!UiActive);
|
k4_set_ui_mode(!!UiActive);
|
||||||
} else {
|
} else {
|
||||||
if(UiActive) {
|
if(UiActive) {
|
||||||
struct k3MEvent ev = {
|
struct k3MEvent ev = {
|
||||||
@@ -172,8 +170,16 @@ static void charcallback(GLFWwindow *window, unsigned int codepoint) {
|
|||||||
|
|
||||||
static void fix_resol();
|
static void fix_resol();
|
||||||
static void resizecallback(GLFWwindow *window, int width, int height) {
|
static void resizecallback(GLFWwindow *window, int width, int height) {
|
||||||
k3Resize(width, height);
|
k3Resize(GameWndW = width, GameWndH = height);
|
||||||
fix_resol();
|
fix_resol();
|
||||||
|
|
||||||
|
if(UiActive) {
|
||||||
|
UiActive->w = UiActive->wDesired = GameWndW;
|
||||||
|
UiActive->h = UiActive->hDesired = GameWndH;
|
||||||
|
|
||||||
|
k3MMeasure(UiActive);
|
||||||
|
k3MArrange(UiActive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int argc;
|
static int argc;
|
||||||
@@ -189,7 +195,10 @@ const char *k4_get_arg(const char *name) {
|
|||||||
|
|
||||||
#include<signal.h>
|
#include<signal.h>
|
||||||
void k4k3LogCallback(enum k3LogLevel lvl, const char *str, size_t len) {
|
void k4k3LogCallback(enum k3LogLevel lvl, const char *str, size_t len) {
|
||||||
|
if(lvl == k3_TRACE) return;
|
||||||
|
|
||||||
static const char *prefixes[] = {
|
static const char *prefixes[] = {
|
||||||
|
[k3_TRACE] = "[\x1B[95mTRACE\x1B[0m]",
|
||||||
[k3_DEBUG] = "[\x1B[95mDEBUG\x1B[0m]",
|
[k3_DEBUG] = "[\x1B[95mDEBUG\x1B[0m]",
|
||||||
[k3_INFO] = "[\x1B[97mINFO\x1B[0m] ",
|
[k3_INFO] = "[\x1B[97mINFO\x1B[0m] ",
|
||||||
[k3_WARN] = "[\x1B[93mWARN\x1B[0m] ",
|
[k3_WARN] = "[\x1B[93mWARN\x1B[0m] ",
|
||||||
@@ -198,7 +207,7 @@ void k4k3LogCallback(enum k3LogLevel lvl, const char *str, size_t len) {
|
|||||||
|
|
||||||
//if(lvl == k3_ERR) raise(SIGINT);
|
//if(lvl == k3_ERR) raise(SIGINT);
|
||||||
|
|
||||||
fprintf(stderr, "%s : %s\n", prefixes[lvl], str);
|
fprintf(stdout, "%s : %s\n", prefixes[lvl], str);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k4Control {
|
struct k4Control {
|
||||||
@@ -217,22 +226,26 @@ static int eng_init() {
|
|||||||
#define START_WIDTH 960
|
#define START_WIDTH 960
|
||||||
#define START_HEIGHT 540
|
#define START_HEIGHT 540
|
||||||
#define START_TITLE "k4"
|
#define START_TITLE "k4"
|
||||||
|
|
||||||
|
GameWndW = START_WIDTH;
|
||||||
|
GameWndH = START_HEIGHT;
|
||||||
|
|
||||||
// Prefer core
|
// Prefer core
|
||||||
if(!k4_get_arg("core") || strcmp(k4_get_arg("core"), "0")) {
|
if(!k4_get_arg("core") || strcmp(k4_get_arg("core"), "0")) {
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL);
|
GameWnd = glfwCreateWindow(GameWndW, GameWndH, START_TITLE, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt compatibility
|
||||||
if(!GameWnd) {
|
if(!GameWnd) {
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL);
|
GameWnd = glfwCreateWindow(GameWndW, GameWndH, START_TITLE, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
k3MixInit(44100, 2);
|
k3MixInit(44100, 2);
|
||||||
@@ -266,8 +279,16 @@ static int eng_init() {
|
|||||||
GLAD_GL_ARB_framebuffer_sRGB = 0;
|
GLAD_GL_ARB_framebuffer_sRGB = 0;
|
||||||
GLAD_GL_EXT_framebuffer_object = 0;
|
GLAD_GL_EXT_framebuffer_object = 0;
|
||||||
}
|
}
|
||||||
|
if(k4_get_arg("dsa") && strtol(k4_get_arg("dsa"), NULL, 0) == 0) {
|
||||||
|
GLAD_GL_EXT_direct_state_access = 0;
|
||||||
|
GLAD_GL_ARB_direct_state_access = 0;
|
||||||
|
}
|
||||||
|
|
||||||
glfwSwapInterval(0);
|
if(k4_get_arg("vsync")) {
|
||||||
|
glfwSwapInterval(strtol(k4_get_arg("vsync"), NULL, 0));
|
||||||
|
} else {
|
||||||
|
glfwSwapInterval(0);
|
||||||
|
}
|
||||||
|
|
||||||
printf("GL version: %s\n", glGetString(GL_VERSION));
|
printf("GL version: %s\n", glGetString(GL_VERSION));
|
||||||
printf("GL renderer: %s\n", glGetString(GL_RENDERER));
|
printf("GL renderer: %s\n", glGetString(GL_RENDERER));
|
||||||
@@ -275,7 +296,9 @@ static int eng_init() {
|
|||||||
|
|
||||||
k3SetLogCallback(k4k3LogCallback);
|
k3SetLogCallback(k4k3LogCallback);
|
||||||
|
|
||||||
k3Init();
|
k3Init(
|
||||||
|
!k4_get_arg("tc") || strtol(k4_get_arg("tc"), NULL, 0) != 0,
|
||||||
|
!k4_get_arg("mipmap") || strtol(k4_get_arg("mipmap"), NULL, 0) != 0);
|
||||||
|
|
||||||
k3BatchInit();
|
k3BatchInit();
|
||||||
|
|
||||||
@@ -299,7 +322,7 @@ static void fix_resol() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void eng_ui_init() {
|
static void eng_ui_init() {
|
||||||
set_ui_mode(1);
|
k4_set_ui_mode(!!UiActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fps_counter_step(double newDT) {
|
static void fps_counter_step(double newDT) {
|
||||||
@@ -338,6 +361,7 @@ static int gr_shadowmap_init() {
|
|||||||
"!!ARBfp1.0\n"
|
"!!ARBfp1.0\n"
|
||||||
"TEMP col;\n"
|
"TEMP col;\n"
|
||||||
"TEX col, fragment.texcoord, texture[0], 2D;\n"
|
"TEX col, fragment.texcoord, texture[0], 2D;\n"
|
||||||
|
"MOV result.color, col;\n"
|
||||||
"MAD col.xyz, -col, 29.9, 30.1;\n"
|
"MAD col.xyz, -col, 29.9, 30.1;\n"
|
||||||
"RCP col.x, col.x;\n"
|
"RCP col.x, col.x;\n"
|
||||||
"RCP col.y, col.y;\n"
|
"RCP col.y, col.y;\n"
|
||||||
@@ -393,7 +417,6 @@ int main(int argc_, char **argv_) {
|
|||||||
argv = argv_;
|
argv = argv_;
|
||||||
|
|
||||||
eng_init();
|
eng_init();
|
||||||
eng_ui_init();
|
|
||||||
|
|
||||||
gr_shadowmap_init();
|
gr_shadowmap_init();
|
||||||
gr_bloom_init();
|
gr_bloom_init();
|
||||||
@@ -413,7 +436,7 @@ int main(int argc_, char **argv_) {
|
|||||||
luaapi_load(k4_get_arg("script") ? k4_get_arg("script") : "init");
|
luaapi_load(k4_get_arg("script") ? k4_get_arg("script") : "init");
|
||||||
//
|
//
|
||||||
|
|
||||||
LuaapiStartTime = glfwGetTime();
|
eng_ui_init();
|
||||||
|
|
||||||
LastTime = glfwGetTime();
|
LastTime = glfwGetTime();
|
||||||
|
|
||||||
@@ -432,6 +455,9 @@ int main(int argc_, char **argv_) {
|
|||||||
|
|
||||||
net_hi_update(CurrentTime);
|
net_hi_update(CurrentTime);
|
||||||
|
|
||||||
|
int windowW, windowH;
|
||||||
|
glfwGetWindowSize(GameWnd, &windowW, &windowH);
|
||||||
|
|
||||||
float alpha = fmodf(accumulator * GAME_TPS, 1.f);
|
float alpha = fmodf(accumulator * GAME_TPS, 1.f);
|
||||||
|
|
||||||
vec3 cameraForwardDir = {0, 0, -1};
|
vec3 cameraForwardDir = {0, 0, -1};
|
||||||
@@ -492,7 +518,7 @@ int main(int argc_, char **argv_) {
|
|||||||
glfwGetFramebufferSize(GameWnd, &width, &height);
|
glfwGetFramebufferSize(GameWnd, &width, &height);
|
||||||
|
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
glm_perspective(glm_rad(LuaapiFov), (float) width / height, 0.1f, 80.f, proj);
|
glm_perspective(glm_rad(LuaapiFov), (float) width / height, LuaapiNear, LuaapiFar, proj);
|
||||||
|
|
||||||
/* Third-person camera movement */
|
/* Third-person camera movement */
|
||||||
struct LocalRay camray = {};
|
struct LocalRay camray = {};
|
||||||
@@ -520,11 +546,16 @@ int main(int argc_, char **argv_) {
|
|||||||
InstantCamShift--;
|
InstantCamShift--;
|
||||||
}
|
}
|
||||||
if(LuaapiFirstPerson) {
|
if(LuaapiFirstPerson) {
|
||||||
struct CRender *c = game_getcomponent(Game.spectated, render);
|
struct CRender *cr = game_getcomponent(Game.spectated, render);
|
||||||
|
struct CPhysics *cp = game_getcomponent(Game.spectated, physics);
|
||||||
|
|
||||||
if(c) {
|
if(cr) {
|
||||||
vec3 p;
|
vec3 p;
|
||||||
glm_vec3_lerp(c->posLast, c->pos, alpha, p);
|
glm_vec3_lerp(cr->posLast, cr->pos, alpha, p);
|
||||||
|
|
||||||
|
if(cp && cp->type == CPHYSICS_CAPSULE) {
|
||||||
|
p[1] += cp->capsule.length / 2;
|
||||||
|
}
|
||||||
|
|
||||||
mat4 view;
|
mat4 view;
|
||||||
glm_look(p, cameraForwardDir, (vec3) {0, 1, 0}, view);
|
glm_look(p, cameraForwardDir, (vec3) {0, 1, 0}, view);
|
||||||
@@ -559,6 +590,7 @@ int main(int argc_, char **argv_) {
|
|||||||
|
|
||||||
glm_mat4_copy(cam, LuaapiCamMatrix);
|
glm_mat4_copy(cam, LuaapiCamMatrix);
|
||||||
|
|
||||||
|
k3Update();
|
||||||
k3SetTime(glfwGetTime());
|
k3SetTime(glfwGetTime());
|
||||||
|
|
||||||
size_t lightCount;
|
size_t lightCount;
|
||||||
@@ -584,12 +616,16 @@ int main(int argc_, char **argv_) {
|
|||||||
if(c->cache) {
|
if(c->cache) {
|
||||||
struct CBoned *b = game_getcomponent(c->entity, boned);
|
struct CBoned *b = game_getcomponent(c->entity, boned);
|
||||||
|
|
||||||
k3Batch(c->cache, transform, b ? b->bones : NULL);
|
if(b && b->animator.anim) {
|
||||||
|
k3AnimatorStep(&b->animator, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
k3Batch(c->cache, transform, b ? b->animator.bones : NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!IrregularShadows) {
|
if(!IrregularShadows) {
|
||||||
k3PassShadowmap(proj, cam, shadowmapOffscreen);
|
k3PassShadowmap(proj, cam, shadowmapOffscreen, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lowresOffscreen) {
|
if(lowresOffscreen) {
|
||||||
@@ -634,13 +670,7 @@ int main(int argc_, char **argv_) {
|
|||||||
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
if(!k3IsCore) {
|
k3BatchSetResolution(windowW, windowH);
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrtho(0, 3600, 0, 2025, -1, 1);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
}
|
|
||||||
|
|
||||||
luaapi_render2d();
|
luaapi_render2d();
|
||||||
|
|
||||||
|
|||||||
@@ -26,11 +26,7 @@ void net_client_init() {
|
|||||||
Game.isAuthority = 0;
|
Game.isAuthority = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool net_client_connect(const char *addr, uint16_t port) {
|
bool net_client_connect(ENetAddress eaddr) {
|
||||||
ENetAddress eaddr;
|
|
||||||
enet_address_set_host(&eaddr, addr);
|
|
||||||
eaddr.port = port;
|
|
||||||
|
|
||||||
peer = enet_host_connect(host, &eaddr, 1, 0);
|
peer = enet_host_connect(host, &eaddr, 1, 0);
|
||||||
|
|
||||||
ENetEvent ev;
|
ENetEvent ev;
|
||||||
@@ -118,7 +114,7 @@ static void interpret_pkt(ENetPacket *pkt) {
|
|||||||
c->holding = b_ru16(&b);
|
c->holding = b_ru16(&b);
|
||||||
} if(ctype == CMD_CTYPE_BONED) {
|
} if(ctype == CMD_CTYPE_BONED) {
|
||||||
struct CBoned *c = game_ensurecomponent(ent, boned);
|
struct CBoned *c = game_ensurecomponent(ent, boned);
|
||||||
c->anim.standard = b_ru8(&b);
|
/*c->anim.standard =*/ b_ru8(&b);
|
||||||
}
|
}
|
||||||
} else if(cmd == CMD_SC_POSUPDATE) {
|
} else if(cmd == CMD_SC_POSUPDATE) {
|
||||||
uint16_t lastOurTick = b_ru16(&b);
|
uint16_t lastOurTick = b_ru16(&b);
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include"enet.h"
|
||||||
|
|
||||||
void net_client_init();
|
void net_client_init();
|
||||||
bool net_client_connect(const char *addr, uint16_t port);
|
bool net_client_connect(ENetAddress addr);
|
||||||
void net_client_receive();
|
void net_client_receive();
|
||||||
void net_client_update();
|
void net_client_update();
|
||||||
void net_client_dejitter();
|
void net_client_dejitter();
|
||||||
|
|||||||
156
src/net_hi.c
156
src/net_hi.c
@@ -7,9 +7,15 @@
|
|||||||
#include"net_server.h"
|
#include"net_server.h"
|
||||||
#include"net_client.h"
|
#include"net_client.h"
|
||||||
#include<math.h>
|
#include<math.h>
|
||||||
|
#include"k3.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handles networking on a higher-level, combining hole punching with
|
||||||
|
* basic client & server interface
|
||||||
|
* */
|
||||||
|
|
||||||
static void *ReqPeercodeUD;
|
static void *ReqPeercodeUD;
|
||||||
static void(*ReqPeercodeCB)(void*, const char *peercode);
|
static void(*ReqPeercodeCB)(void*, struct StoonPeercode *peercode);
|
||||||
|
|
||||||
static struct Stoon stoon;
|
static struct Stoon stoon;
|
||||||
|
|
||||||
@@ -17,11 +23,11 @@ static bool inited = false;
|
|||||||
static bool isHost;
|
static bool isHost;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#define MASK_IPv4 1
|
ENetAddress pv4;
|
||||||
#define MASK_IPv6 2
|
ENetAddress pv6;
|
||||||
int mask;
|
|
||||||
ENetAddress v4;
|
ENetAddress lv4;
|
||||||
ENetAddress v6;
|
ENetAddress lv6;
|
||||||
} ToPunch;
|
} ToPunch;
|
||||||
static ToPunch *topunch = NULL;
|
static ToPunch *topunch = NULL;
|
||||||
static size_t topunchCount = 0;
|
static size_t topunchCount = 0;
|
||||||
@@ -30,13 +36,22 @@ static double Timeout = 0;
|
|||||||
|
|
||||||
static bool connected = false;
|
static bool connected = false;
|
||||||
|
|
||||||
bool net_hi_request_peercode(void *ud, void(*callback)(void*, const char *peercode)) {
|
static uint16_t servport = 0;
|
||||||
|
|
||||||
|
bool net_hi_request_peercode(void *ud, void(*callback)(void*, struct StoonPeercode *peercode)) {
|
||||||
if(inited) return false;
|
if(inited) return false;
|
||||||
|
|
||||||
ReqPeercodeUD = ud;
|
ReqPeercodeUD = ud;
|
||||||
ReqPeercodeCB = callback;
|
ReqPeercodeCB = callback;
|
||||||
|
|
||||||
stoon = stoon_init("stun.easybell.de", 3478, 26656);
|
for(size_t port = 25000; port <= 26656; port++) {
|
||||||
|
stoon = stoon_init("stun.easybell.de", 3478, port);
|
||||||
|
|
||||||
|
if(stoon.fd4 >= 0 || stoon.fd6 >= 0) {
|
||||||
|
servport = port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Timeout = 0;
|
Timeout = 0;
|
||||||
|
|
||||||
@@ -52,7 +67,7 @@ bool net_hi_setup(bool host) {
|
|||||||
isHost = host;
|
isHost = host;
|
||||||
|
|
||||||
if(host) {
|
if(host) {
|
||||||
net_server_init();
|
net_server_init(servport);
|
||||||
} else {
|
} else {
|
||||||
net_client_init();
|
net_client_init();
|
||||||
}
|
}
|
||||||
@@ -67,16 +82,17 @@ void net_hi_update(double now) {
|
|||||||
|
|
||||||
if(stoon_req(&stoon)) {
|
if(stoon_req(&stoon)) {
|
||||||
if(stoon_listen(&stoon)) {
|
if(stoon_listen(&stoon)) {
|
||||||
uint8_t peercode[STOON_CONN_INFO_SIZE] = {};
|
ReqPeercodeCB(ReqPeercodeUD, &stoon.peercode);
|
||||||
stoon_serialize(&stoon, peercode);
|
|
||||||
|
|
||||||
ReqPeercodeCB(ReqPeercodeUD, peercode);
|
|
||||||
|
|
||||||
ReqPeercodeCB = NULL;
|
ReqPeercodeCB = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
k3Log(k3_INFO, "stoon_listen failure");
|
||||||
|
|
||||||
Timeout = now + 1;
|
Timeout = now + 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
k3Log(k3_INFO, "stoon_req failure");
|
||||||
|
|
||||||
Timeout = now + 1;
|
Timeout = now + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,11 +113,11 @@ void net_hi_update(double now) {
|
|||||||
for(size_t tpi = 0; tpi < topunchCount; tpi++) {
|
for(size_t tpi = 0; tpi < topunchCount; tpi++) {
|
||||||
ToPunch *tp = &topunch[tpi];
|
ToPunch *tp = &topunch[tpi];
|
||||||
|
|
||||||
if(tp->mask & MASK_IPv4) {
|
if(tp->lv6.port) enet_socket_send(h->socket, &tp->lv6, &buf, 1);
|
||||||
enet_socket_send(h->socket, &tp->v4, &buf, 1);
|
if(tp->lv4.port) enet_socket_send(h->socket, &tp->lv4, &buf, 1);
|
||||||
} else if(tp->mask & MASK_IPv6) {
|
|
||||||
enet_socket_send(h->socket, &tp->v6, &buf, 1);
|
if(tp->pv6.port) enet_socket_send(h->socket, &tp->pv6, &buf, 1);
|
||||||
}
|
if(tp->pv4.port) enet_socket_send(h->socket, &tp->pv4, &buf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -111,55 +127,85 @@ void net_hi_update(double now) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stoonpeer_to_enets(const char *peercode, ENetAddress *v4, ENetAddress *v6, int *mask) {
|
static bool stoonpeer_to_enet4(uint8_t *publicV4, uint8_t *publicP4, ENetAddress *enet) {
|
||||||
memset(v4->host.__in6_u.__u6_addr8, 0, 16);
|
memset(enet, 0, sizeof(*enet));
|
||||||
v4->host.__in6_u.__u6_addr8[10] = 0xFF;
|
|
||||||
v4->host.__in6_u.__u6_addr8[11] = 0xFF;
|
|
||||||
v4->host.__in6_u.__u6_addr8[12] = peercode[0];
|
|
||||||
v4->host.__in6_u.__u6_addr8[13] = peercode[1];
|
|
||||||
v4->host.__in6_u.__u6_addr8[14] = peercode[2];
|
|
||||||
v4->host.__in6_u.__u6_addr8[15] = peercode[3];
|
|
||||||
v4->port = ntohs(*(uint16_t*) &peercode[4]);
|
|
||||||
|
|
||||||
memcpy(v6->host.__in6_u.__u6_addr8, peercode + 6, 16);
|
if(*(uint32_t*) publicV4 == 0 || *(uint16_t*) publicP4 == 0) {
|
||||||
v6->port = ntohs(*(uint16_t*) &peercode[22]);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*mask = 0;
|
uint8_t *addr8 = (uint8_t*) &enet->host;
|
||||||
if(v4->port) {
|
|
||||||
*mask |= MASK_IPv4;
|
memset(addr8, 0, 16);
|
||||||
}
|
addr8[10] = 0xFF;
|
||||||
if(v6->port) {
|
addr8[11] = 0xFF;
|
||||||
*mask |= MASK_IPv6;
|
addr8[12] = publicV4[0];
|
||||||
}
|
addr8[13] = publicV4[1];
|
||||||
|
addr8[14] = publicV4[2];
|
||||||
|
addr8[15] = publicV4[3];
|
||||||
|
enet->port = *(uint16_t*) publicP4;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_hi_add_punch(const char *peercode) {
|
static bool stoonpeer_to_enet6(uint8_t *publicV6, uint8_t *publicP6, ENetAddress *enet) {
|
||||||
int mask;
|
memset(enet, 0, sizeof(*enet));
|
||||||
ENetAddress v4 = {}, v6 = {};
|
|
||||||
stoonpeer_to_enets(peercode, &v4, &v6, &mask);
|
|
||||||
|
|
||||||
|
if(*(uint32_t*) publicV6 == 0 || *(uint16_t*) publicP6 == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *addr8 = (uint8_t*) &enet->host;
|
||||||
|
|
||||||
|
memcpy(addr8, publicV6, 16);
|
||||||
|
enet->port = *(uint16_t*) publicP6;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_hi_add_punch(struct StoonPeercode *peercode) {
|
||||||
topunch = realloc(topunch, sizeof(*topunch) * (++topunchCount));
|
topunch = realloc(topunch, sizeof(*topunch) * (++topunchCount));
|
||||||
topunch[topunchCount - 1] = (ToPunch) {
|
ToPunch *tp = &topunch[topunchCount - 1];
|
||||||
.v4 = v4,
|
|
||||||
.v6 = v6,
|
stoonpeer_to_enet4(peercode->publicV4, peercode->publicP4, &tp->pv4);
|
||||||
.mask = mask,
|
stoonpeer_to_enet6(peercode->publicV6, peercode->publicP6, &tp->pv6);
|
||||||
};
|
|
||||||
|
stoonpeer_to_enet4(peercode->localV4, peercode->localP4, &tp->lv4);
|
||||||
|
stoonpeer_to_enet6(peercode->localV6, peercode->localP6, &tp->lv6);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool net_hi_connect(const char *peercode) {
|
bool net_hi_connect(struct StoonPeercode *peercode) {
|
||||||
if(!inited) return false;
|
if(!inited) return false;
|
||||||
|
|
||||||
if(connected) return false;
|
if(connected) return false;
|
||||||
|
|
||||||
char ip[64];
|
ENetAddress pv4, pv6;
|
||||||
int port;
|
stoonpeer_to_enet4(peercode->publicV4, peercode->publicP4, &pv4);
|
||||||
if(*(uint16_t*) (peercode + 22) == 0) {
|
stoonpeer_to_enet6(peercode->publicV6, peercode->publicP6, &pv6);
|
||||||
inet_ntop(AF_INET, peercode, ip, sizeof(ip));
|
|
||||||
port = ntohs(*(uint16_t*) (peercode + 4));
|
ENetAddress lv4, lv6;
|
||||||
} else {
|
stoonpeer_to_enet4(peercode->localV4, peercode->localP4, &lv4);
|
||||||
inet_ntop(AF_INET6, peercode + 6, ip, sizeof(ip));
|
stoonpeer_to_enet6(peercode->localV6, peercode->localP6, &lv6);
|
||||||
port = ntohs(*(uint16_t*) (peercode + 22));
|
|
||||||
|
if(lv6.port && net_client_connect(lv6)) {
|
||||||
|
k3Log(k3_INFO, "Found local IPv6");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(lv4.port && net_client_connect(lv4)) {
|
||||||
|
k3Log(k3_INFO, "Found local IPv4");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return net_client_connect(ip, port);
|
if(pv6.port && net_client_connect(pv6)) {
|
||||||
|
k3Log(k3_INFO, "Found remote IPv6");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(pv4.port && net_client_connect(pv4)) {
|
||||||
|
k3Log(k3_INFO, "Found remote IPv4");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
k3Log(k3_INFO, "Failed to establish connection");
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
#include<stdbool.h>
|
#include<stdbool.h>
|
||||||
|
|
||||||
bool net_hi_request_peercode(void *ud, void(*callback)(void*, const char *peercode));
|
struct StoonPeercode;
|
||||||
|
|
||||||
|
bool net_hi_request_peercode(void *ud, void(*callback)(void*, struct StoonPeercode *peercode));
|
||||||
bool net_hi_setup(bool host);
|
bool net_hi_setup(bool host);
|
||||||
void net_hi_update(double now);
|
void net_hi_update(double now);
|
||||||
|
|
||||||
void net_hi_add_punch(const char *peercode);
|
void net_hi_add_punch(struct StoonPeercode *peercode);
|
||||||
|
|
||||||
bool net_hi_connect(const char *peercode);
|
bool net_hi_connect(struct StoonPeercode *peercode);
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ struct Conn {
|
|||||||
#define MAX_PLAYERS 64
|
#define MAX_PLAYERS 64
|
||||||
static struct Conn conns[MAX_PLAYERS];
|
static struct Conn conns[MAX_PLAYERS];
|
||||||
|
|
||||||
void net_server_init() {
|
void net_server_init(uint16_t port) {
|
||||||
host = enet_host_create(&(ENetAddress) {.host = ENET_HOST_ANY, .port = 26656}, 16, 1, 0, 0);
|
host = enet_host_create(&(ENetAddress) {.host = ENET_HOST_ANY, .port = port}, 16, 1, 0, 0);
|
||||||
|
|
||||||
Game.isMultiplayer = 1;
|
Game.isMultiplayer = 1;
|
||||||
Game.isAuthority = 1;
|
Game.isAuthority = 1;
|
||||||
@@ -121,7 +121,7 @@ static void send_full_state(ENetPeer **peers, size_t peerCount) {
|
|||||||
|
|
||||||
b_wu16(&b, c->entity);
|
b_wu16(&b, c->entity);
|
||||||
|
|
||||||
b_wu8(&b, c->anim.standard);
|
b_wu8(&b, 0/*c->anim.standard*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(peers) {
|
if(peers) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
struct _ENetPeer;
|
struct _ENetPeer;
|
||||||
struct bstr;
|
struct bstr;
|
||||||
|
|
||||||
void net_server_init();
|
void net_server_init(uint16_t port);
|
||||||
void net_server_receive();
|
void net_server_receive();
|
||||||
void net_server_update();
|
void net_server_update();
|
||||||
|
|
||||||
|
|||||||
144
src/stoon.c
144
src/stoon.c
@@ -4,11 +4,12 @@
|
|||||||
#include<winsock2.h>
|
#include<winsock2.h>
|
||||||
#include<ws2tcpip.h>
|
#include<ws2tcpip.h>
|
||||||
#include<ntsecapi.h>
|
#include<ntsecapi.h>
|
||||||
|
#include<iphlpapi.h>
|
||||||
#else
|
#else
|
||||||
#include<netdb.h>
|
#include<netdb.h>
|
||||||
#include<sys/socket.h>
|
#include<sys/socket.h>
|
||||||
#include<sys/random.h>
|
|
||||||
#include<arpa/inet.h>
|
#include<arpa/inet.h>
|
||||||
|
#include<ifaddrs.h>
|
||||||
#endif
|
#endif
|
||||||
#include<unistd.h>
|
#include<unistd.h>
|
||||||
#include<sys/types.h>
|
#include<sys/types.h>
|
||||||
@@ -34,6 +35,13 @@
|
|||||||
#define RAND(b, i) RtlGenRandom(b, i)
|
#define RAND(b, i) RtlGenRandom(b, i)
|
||||||
#else
|
#else
|
||||||
#define RAND(b, i) getrandom(b, i, 0)
|
#define RAND(b, i) getrandom(b, i, 0)
|
||||||
|
static void getrandom(void *buf, size_t amount, int flags) {
|
||||||
|
static FILE *f;
|
||||||
|
if(!f) {
|
||||||
|
f = fopen("/dev/urandom", "rb");
|
||||||
|
}
|
||||||
|
fread(buf, 1, amount, f);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct StunMsg {
|
struct StunMsg {
|
||||||
@@ -43,7 +51,7 @@ struct StunMsg {
|
|||||||
uint8_t id[12];
|
uint8_t id[12];
|
||||||
};
|
};
|
||||||
|
|
||||||
static int stoon_init_mini(struct addrinfo *serv, uint16_t myport) {
|
static int stoon_init_mini(struct Stoon *this, struct addrinfo *serv, uint16_t myport) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
errno = 0;
|
errno = 0;
|
||||||
int fd = socket(serv->ai_family, serv->ai_socktype, serv->ai_protocol);
|
int fd = socket(serv->ai_family, serv->ai_socktype, serv->ai_protocol);
|
||||||
@@ -59,16 +67,79 @@ static int stoon_init_mini(struct addrinfo *serv, uint16_t myport) {
|
|||||||
char p[6];
|
char p[6];
|
||||||
sprintf(p, "%u", myport);
|
sprintf(p, "%u", myport);
|
||||||
|
|
||||||
struct addrinfo *myaddr;
|
struct addrinfo *myaddrinfo;
|
||||||
if(getaddrinfo(NULL, p, &(struct addrinfo) {.ai_family = serv->ai_family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_flags = AI_PASSIVE}, &myaddr)) {
|
if(getaddrinfo(NULL, p, &(struct addrinfo) {.ai_family = serv->ai_family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_flags = AI_PASSIVE}, &myaddrinfo)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(bind(fd, myaddr->ai_addr, myaddr->ai_addrlen)) {
|
if(bind(fd, myaddrinfo->ai_addr, myaddrinfo->ai_addrlen)) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
freeaddrinfo(myaddr);
|
|
||||||
|
freeaddrinfo(myaddrinfo);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
size_t sz = 1024 * 64;
|
||||||
|
IP_ADAPTER_ADDRESSES *addrs = malloc(sz);
|
||||||
|
if(GetAdaptersAddresses(serv->ai_family, GAA_FLAG_SKIP_MULTICAST, NULL, addrs, &sz) == NO_ERROR) {
|
||||||
|
for(IP_ADAPTER_ADDRESSES *ifa = addrs; ifa; ifa = ifa->Next) {
|
||||||
|
if(!ifa->FirstUnicastAddress) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(serv->ai_family == AF_INET6) {
|
||||||
|
uint8_t *addr = (void*) &((struct sockaddr_in6*) ifa->FirstUnicastAddress->Address.lpSockaddr)->sin6_addr;
|
||||||
|
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 && addr[4] == 0 && addr[5] == 0 && addr[6] == 0 && addr[7] == 0 && addr[8] == 0 && addr[9] == 0 && addr[10] == 0 && addr[11] == 0 && addr[12] == 0 && addr[13] == 0 && addr[14] == 0 && (addr[15] == 0 || addr[15] == 1)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(this->peercode.localV6, addr, 16);
|
||||||
|
memcpy(this->peercode.localP6, &myport, 2);
|
||||||
|
} else {
|
||||||
|
uint8_t *addr = (void*) &((struct sockaddr_in*) ifa->FirstUnicastAddress->Address.lpSockaddr)->sin_addr;
|
||||||
|
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 || addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(this->peercode.localV4, addr, 4);
|
||||||
|
memcpy(this->peercode.localP4, &myport, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(addrs);
|
||||||
|
#else
|
||||||
|
struct ifaddrs *ifaddr;
|
||||||
|
if(getifaddrs(&ifaddr) >= 0) {
|
||||||
|
for(struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
||||||
|
if(!ifa->ifa_addr || ifa->ifa_addr->sa_family != serv->ai_family) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(serv->ai_family == AF_INET6) {
|
||||||
|
uint8_t *addr = (void*) &((struct sockaddr_in6*) ifa->ifa_addr)->sin6_addr;
|
||||||
|
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 && addr[4] == 0 && addr[5] == 0 && addr[6] == 0 && addr[7] == 0 && addr[8] == 0 && addr[9] == 0 && addr[10] == 0 && addr[11] == 0 && addr[12] == 0 && addr[13] == 0 && addr[14] == 0 && (addr[15] == 0 || addr[15] == 1)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(this->peercode.localV6, addr, 16);
|
||||||
|
memcpy(this->peercode.localP6, &myport, 2);
|
||||||
|
} else {
|
||||||
|
uint8_t *addr = (void*) &((struct sockaddr_in*) ifa->ifa_addr)->sin_addr;
|
||||||
|
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 || addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(this->peercode.localV4, addr, 4);
|
||||||
|
memcpy(this->peercode.localP4, &myport, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeifaddrs(ifaddr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -92,18 +163,16 @@ struct Stoon stoon_init(const char *stunhost, uint16_t stunport, uint16_t myport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Stoon ret;
|
struct Stoon ret = {};
|
||||||
|
|
||||||
memset(&ret.my4, 0, sizeof(ret.my4));
|
|
||||||
if(v4) {
|
if(v4) {
|
||||||
memcpy(&ret.stu4, v4->ai_addr, v4->ai_addrlen);
|
memcpy(&ret.stu4, v4->ai_addr, v4->ai_addrlen);
|
||||||
ret.fd4 = stoon_init_mini(v4, myport);
|
ret.fd4 = stoon_init_mini(&ret, v4, myport);
|
||||||
} else ret.fd4 = -1;
|
} else ret.fd4 = -1;
|
||||||
|
|
||||||
memset(&ret.my6, 0, sizeof(ret.my6));
|
|
||||||
if(v6) {
|
if(v6) {
|
||||||
memcpy(&ret.stu6, v6->ai_addr, v6->ai_addrlen);
|
memcpy(&ret.stu6, v6->ai_addr, v6->ai_addrlen);
|
||||||
ret.fd6 = stoon_init_mini(v6, myport);
|
ret.fd6 = stoon_init_mini(&ret, v6, myport);
|
||||||
} else ret.fd6 = -1;
|
} else ret.fd6 = -1;
|
||||||
|
|
||||||
ret.poonchstage = 0;
|
ret.poonchstage = 0;
|
||||||
@@ -121,12 +190,21 @@ static int stoon_req_mini(struct Stoon *this, int *fd, struct sockaddr *serv, in
|
|||||||
if(errno == ENETUNREACH) {
|
if(errno == ENETUNREACH) {
|
||||||
close(*fd);
|
close(*fd);
|
||||||
*fd = -1;
|
*fd = -1;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
int stoon_req(struct Stoon *this) {
|
int stoon_req(struct Stoon *this) {
|
||||||
if(this->fd4 >= 0) stoon_req_mini(this, &this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in));
|
if(this->fd4 >= 0) stoon_req_mini(this, &this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in));
|
||||||
if(this->fd6 >= 0) stoon_req_mini(this, &this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6));
|
if(this->fd6 >= 0) stoon_req_mini(this, &this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6));
|
||||||
|
|
||||||
|
if(this->fd4 < 0 && this->fd6 < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv, int servlen) {
|
static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv, int servlen) {
|
||||||
@@ -161,11 +239,10 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
|
|||||||
uint16_t netfam = ntohs(((uint16_t*) d)[2]);
|
uint16_t netfam = ntohs(((uint16_t*) d)[2]);
|
||||||
uint16_t publicPort = ntohs(((uint16_t*) d)[3]) ^ (STUN_MAGIC >> 16);
|
uint16_t publicPort = ntohs(((uint16_t*) d)[3]) ^ (STUN_MAGIC >> 16);
|
||||||
if(netfam == STUN_NETFAM_IPV4) {
|
if(netfam == STUN_NETFAM_IPV4) {
|
||||||
uint32_t publicIp = ntohl(((uint32_t*) d)[2]) ^ STUN_MAGIC;
|
uint32_t publicIp = htonl(ntohl(((uint32_t*) d)[2]) ^ STUN_MAGIC);
|
||||||
|
|
||||||
this->my4.sin_family = AF_INET;
|
memcpy(this->peercode.publicV4, &publicIp, 4);
|
||||||
memcpy(&this->my4.sin_addr, &publicIp, 4);
|
memcpy(this->peercode.publicP4, &publicPort, 2);
|
||||||
this->my4.sin_port = htons(publicPort);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} else if(netfam == STUN_NETFAM_IPV6) {
|
} else if(netfam == STUN_NETFAM_IPV6) {
|
||||||
@@ -175,9 +252,8 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
|
|||||||
publicIp[2] = ((uint32_t*) d)[4] ^ ((uint32_t*) res.base.id)[1];
|
publicIp[2] = ((uint32_t*) d)[4] ^ ((uint32_t*) res.base.id)[1];
|
||||||
publicIp[3] = ((uint32_t*) d)[5] ^ ((uint32_t*) res.base.id)[2];
|
publicIp[3] = ((uint32_t*) d)[5] ^ ((uint32_t*) res.base.id)[2];
|
||||||
|
|
||||||
this->my6.sin6_family = AF_INET6;
|
memcpy(this->peercode.publicV6, &publicIp, 16);
|
||||||
memcpy(&this->my6.sin6_addr, &publicIp, 16);
|
memcpy(this->peercode.publicP6, &publicPort, 2);
|
||||||
this->my6.sin6_port = htons(publicPort);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -188,12 +264,12 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
|
|||||||
d += 4 + attribLen;
|
d += 4 + attribLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
int stoon_listen(struct Stoon *this) {
|
int stoon_listen(struct Stoon *this) {
|
||||||
if(this->fd4 >= 0) if(stoon_listen_mini(this, this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in)) < 0) return 0;
|
if(this->fd4 >= 0) if(stoon_listen_mini(this, this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in)) < 0) return 0;
|
||||||
if(this->fd6 >= 0) if(stoon_listen_mini(this, this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6)) < 0) return 0;
|
if(this->fd6 >= 0) if(stoon_listen_mini(this, this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6)) < 0) return 0;
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stoon_keepalive(struct Stoon *this) {
|
void stoon_keepalive(struct Stoon *this) {
|
||||||
@@ -217,31 +293,7 @@ void stoon_kill(struct Stoon *this) {
|
|||||||
this->fd6 = -1;
|
this->fd6 = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int stoon_v4_available(struct Stoon *this) {
|
/*int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]) {
|
||||||
return this->fd4 >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stoon_v6_available(struct Stoon *this) {
|
|
||||||
return this->fd6 >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stoon_serialize(struct Stoon *this, uint8_t ret[static STOON_CONN_INFO_SIZE]) {
|
|
||||||
if(this->fd4 >= 0) {
|
|
||||||
memcpy(ret + 0, &this->my4.sin_addr, 4);
|
|
||||||
memcpy(ret + 4, &this->my4.sin_port, 2);
|
|
||||||
} else {
|
|
||||||
memset(ret, 0, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this->fd6 >= 0) {
|
|
||||||
memcpy(ret + 6, &this->my6.sin6_addr, 16);
|
|
||||||
memcpy(ret + 22, &this->my6.sin6_port, 2);
|
|
||||||
} else {
|
|
||||||
memset(ret + 6, 0, 18);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]) {
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t addr4;
|
uint32_t addr4;
|
||||||
uint16_t port4;
|
uint16_t port4;
|
||||||
@@ -303,7 +355,7 @@ int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_IN
|
|||||||
}
|
}
|
||||||
|
|
||||||
return STOON_POONCH_NO_KNOCK;
|
return STOON_POONCH_NO_KNOCK;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
#ifdef STOON_STANDALONE
|
#ifdef STOON_STANDALONE
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
29
src/stoon.h
29
src/stoon.h
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include<stddef.h>
|
#include<stddef.h>
|
||||||
#include<stdint.h>
|
#include<stdint.h>
|
||||||
|
#include<stdbool.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include<winsock2.h>
|
#include<winsock2.h>
|
||||||
@@ -16,8 +17,6 @@
|
|||||||
|
|
||||||
/* Standalone hole punching libary (IPv4 & IPv6 compatible) */
|
/* Standalone hole punching libary (IPv4 & IPv6 compatible) */
|
||||||
|
|
||||||
#define STOON_CONN_INFO_SIZE (4 + 2 + 16 + 2)
|
|
||||||
|
|
||||||
#define POONCH_MAGIC 0x504F4348
|
#define POONCH_MAGIC 0x504F4348
|
||||||
#define POONCH_STAGE_KNOCKING 0
|
#define POONCH_STAGE_KNOCKING 0
|
||||||
#define POONCH_STAGE_ACK 1
|
#define POONCH_STAGE_ACK 1
|
||||||
@@ -26,16 +25,30 @@ struct Poonch {
|
|||||||
uint32_t stage;
|
uint32_t stage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StoonPeercode {
|
||||||
|
uint8_t publicV4[4];
|
||||||
|
uint8_t publicP4[2];
|
||||||
|
|
||||||
|
uint8_t publicV6[16];
|
||||||
|
uint8_t publicP6[2];
|
||||||
|
|
||||||
|
uint8_t localV4[4];
|
||||||
|
uint8_t localP4[2];
|
||||||
|
|
||||||
|
uint8_t localV6[16];
|
||||||
|
uint8_t localP6[2];
|
||||||
|
};
|
||||||
|
|
||||||
struct Stoon {
|
struct Stoon {
|
||||||
struct sockaddr_in stu4;
|
struct sockaddr_in stu4;
|
||||||
struct sockaddr_in my4;
|
|
||||||
int fd4;
|
int fd4;
|
||||||
|
|
||||||
struct sockaddr_in6 stu6;
|
struct sockaddr_in6 stu6;
|
||||||
struct sockaddr_in6 my6;
|
|
||||||
int fd6;
|
int fd6;
|
||||||
|
|
||||||
uint8_t poonchstage;
|
uint8_t poonchstage;
|
||||||
|
|
||||||
|
struct StoonPeercode peercode;
|
||||||
};
|
};
|
||||||
|
|
||||||
// stunhost: Self-explanatory
|
// stunhost: Self-explanatory
|
||||||
@@ -53,12 +66,8 @@ void stoon_keepalive(struct Stoon*);
|
|||||||
|
|
||||||
void stoon_kill(struct Stoon*);
|
void stoon_kill(struct Stoon*);
|
||||||
|
|
||||||
int stoon_v4_available(struct Stoon*);
|
/*#define STOON_POONCH_INCOMPATIBLE_NETFAMS (-1)
|
||||||
int stoon_v6_available(struct Stoon*);
|
|
||||||
|
|
||||||
void stoon_serialize(struct Stoon*, uint8_t ret[static STOON_CONN_INFO_SIZE]);
|
|
||||||
|
|
||||||
#define STOON_POONCH_INCOMPATIBLE_NETFAMS (-1)
|
|
||||||
#define STOON_POONCH_NO_KNOCK 0
|
#define STOON_POONCH_NO_KNOCK 0
|
||||||
#define STOON_POONCH_ACKED 1
|
#define STOON_POONCH_ACKED 1
|
||||||
int stoon_poonch(struct Stoon*, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]);
|
int stoon_poonch(struct Stoon*, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]);
|
||||||
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user