ass2iqe: animlist support + sample anim file

main
Dominik Madarász 2023-08-14 18:30:52 +02:00
parent fb2f7ee532
commit 8b6f07e5c5
37 changed files with 274 additions and 772 deletions

View File

@ -10,36 +10,6 @@
#include "v4k.h"
typedef struct anims_t {
int inuse; // animation number in use
float speed; // x1.00
array(anim_t) anims; // [begin,end,flags] frames of every animation in set
array(mat44) M; // instanced transforms
} anims_t;
anims_t animations(const char *pathfile, int flags) {
anims_t a = {0};
char *anim_file = vfs_read(pathfile);
for each_substring(anim_file, "\r\n", anim) {
int from, to;
char anim_name[128] = {0};
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
array_push(a.anims, !!strstri(anim_name, "loop") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
array_back(a.anims)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", "");
}
array_resize(a.M, 32*32);
for(int z = 0, i = 0; z < 32; ++z) {
for(int x = 0; x < 32; ++x, ++i) {
vec3 p = vec3(-x*3,0,-z*3);
vec3 r = vec3(0,0,0);
vec3 s = vec3(2,2,2);
compose44(a.M[i], p, eulerq(r), s);
}
}
a.speed = 1.0;
return a;
}
int main() {
bool do_showaabb = 0;
bool do_showbones = 0;
@ -52,8 +22,10 @@ int main() {
camera_t cam = camera();
skybox_t sky = skybox("cubemaps/stardust", 0);
model_t mdl = model("kgirls01.fbx", 0);
anims_t a = animations("kgirl/animlist.txt", 0);
model_t mdl = model("Stan.fbx", 0);
anims_t a = animations("Stan.anim", 0);
// load all postfx files in all subdirs
fx_load("fx**.fs");
@ -111,7 +83,7 @@ int main() {
}
if( do_showgizmo ) {
static vec3 p = {0,0,0}, r = {0,0,0}, s = {2,2,2};
static vec3 p = {0,0,0}, r = {0,-90,0}, s = {1,1,1};
gizmo(&p, &r, &s);
compose44(a.M[0], p, eulerq(r), s);
}

Binary file not shown.

View File

@ -1,716 +0,0 @@
// high-level, socket-less networking api. inspired by Quake, MPI and RenderBuckets theories.
// - rlyeh, public domain
//
// Usage:
// 1. configure networked memory buffers with flags (world, player1, player2, etc). network_buffer();
// 2. then during game loop:
// - modify your buffers as much as needed.
// - sync buffers at least once per frame. network_sync();
// - render your world
// 3. optionally, monitor network status & variables. network_get();
//
// @todo: maybe network_send(msg) + msg *network_recv(); instead of event queue of network_sync() ?
//enum { NETWORK_HANDSHAKE, NETWORK_ENCRYPT, NETWORK_VERSIONED, NETWORK_CHECKSUM }; // negotiation
//enum { NETWORK_TCP, NETWORK_UDP, NETWORK_KCP, NETWORK_ENET, NETWORK_WEBSOCKET }; // transport, where
enum { NETWORK_BIND = 2, NETWORK_CONNECT = 4, NETWORK_NOFAIL = 8 };
enum { MAX_CLIENTS = 32 };
API void network_create(const char *ip, const char *port, unsigned flags); // both ip and port can be null
//enum { NETWORK_LOSSY, NETWORK_COMPRESS }; // post-processes
//enum { NETWORK_UNRELIABLE, NETWORK_UNORDERED, NETWORK_PRIORITY }; // how
//enum { NETWORK_PREDICT, NETWORK_RECONCILE, NETWORK_INTERPOLATE, NETWORK_COMPENSATE }; // time authority, when
//enum { NETWORK_LAGS, NETWORK_DROPS, NETWORK_THROTTLES, NETWORK_DUPES }; // quality sim, how much
//enum { NETWORK_CONST = 1, NETWORK_64,NETWORK_32,NETWORK_16,NETWORK_8, NETWORK_FLT, NETWORK_STR, NETWORK_BLOB }; // type, what
enum { NETWORK_SEND = 2, NETWORK_RECV = 4 };
API void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank); // configures a shared/networked buffer
API char** network_sync(unsigned timeout_ms); // syncs all buffers & returns null-terminated list of network events
enum { NETWORK_RANK = 0 }; // [0..N] where 0 is server
enum { NETWORK_PING = 1 }; // NETWORK_BANDWIDTH, NETWORK_QUALITY };
enum { NETWORK_PORT = 2, NETWORK_IP, NETWORK_LIVE };
//enum { NETWORK_USERID, NETWORK_SALT, NETWORK_COUNT/*N users*/ /*...*/,
API int64_t network_get(uint64_t key);
API int64_t network_put(uint64_t key, int64_t value);
API void network_rpc(const char *signature, void *function);
API void network_rpc_send_to(int64_t rank, unsigned id, const char *cmdline);
API void network_rpc_send(unsigned id, const char *cmdline);
// -----------------------------------------------------------------------------
// low-level api (sockets based)
API bool server_bind(int max_clients, int port);
API void server_poll();
API void server_broadcast_bin(const void *ptr, int len);
API void server_broadcast(const char *msg);
API void server_terminate();
API void server_send(int64_t handle, const char *msg);
API void server_send_bin(int64_t handle, const void *ptr, int len);
API void server_drop(int64_t handle);
API int64_t client_join(const char *ip, int port);
#define client_send(msg) server_broadcast(msg)
#define client_send_bin(ptr,len) server_broadcast_bin(ptr, len)
#define client_terminate() server_terminate()
#define ANYHOST_IPV4 "0.0.0.0"
#define ANYHOST_IPV6 "::0"
#define LOCALHOST_IPV4 "127.0.0.1"
#define LOCALHOST_IPV6 "::1"
// -----------------------------------------------------------------------------
// implementation
typedef void* (*rpc_function)();
typedef struct rpc_call {
char *method;
rpc_function function;
uint64_t function_hash;
} rpc_call;
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a) // printf("%llx\n, HASH_STR("int(int,int,int)"));
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5) // printf("%llx\n, HASH_STR("int(int,int)"));
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12) // printf("%llx\n, HASH_STR("char*(char*)"));
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80) // printf("%llx\n, HASH_STR("char*(void)"));
static
rpc_call rpc_new_call(const char *signature, rpc_function function) {
if( signature && function ) {
array(char*)tokens = strsplit(signature, "(,)");
if( array_count(tokens) >= 1 ) {
char *method = strrchr(tokens[0], ' ')+1;
char *rettype = va("%.*s", (int)(method - tokens[0] - 1), tokens[0]);
int num_args = array_count(tokens) - 1;
char* hash_sig = va("%s(%s)", rettype, num_args ? (array_pop_front(tokens), strjoin(tokens, ",")) : "void");
uint64_t hash = hash_str(hash_sig);
method = va("%s%d", method, num_args );
#if RPC_DEBUG
printf("%p %p %s `%s` %s(", function, (void*)hash, rettype, hash_sig, method); for(int i = 0, end = array_count(tokens); i < end; ++i) printf("%s%s", tokens[i], i == (end-1)? "":", "); puts(");");
#endif
return (rpc_call) { strdup(method), function, hash }; // LEAK
}
}
return (rpc_call) {0};
}
static map(char*, rpc_call) rpc_calls = 0;
static
void rpc_insert(const char *signature, void *function ) {
rpc_call call = rpc_new_call(signature, function);
if( call.method ) {
if( !rpc_calls ) map_init(rpc_calls, less_str, hash_str);
if( map_find(rpc_calls, call.method)) {
map_erase(rpc_calls, call.method);
}
map_insert(rpc_calls, call.method, call);
}
}
static
char *rpc_full(unsigned id, const char* method, unsigned num_args, char *args[]) {
#if RPC_DEBUG
printf("id:%x method:%s args:", id, method );
for( int i = 0; i < num_args; ++i ) printf("%s,", args[i]); puts("");
#endif
method = va("%s%d", method, num_args);
rpc_call *found = map_find(rpc_calls, (char*)method);
if( found ) {
switch(found->function_hash) {
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1])) );
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
default: break;
}
}
return va("%d -1", id);
}
static
array(char*) rpc_parse_args( const char *cmdline, bool quote_whitespaces ) { // parse cmdline arguments. must array_free() after use
// - supports quotes: "abc" "abc def" "abc \"def\"" "abc \"def\"""ghi" etc.
// - #comments removed
array(char*) args = 0; // LEAK
for( int i = 0; cmdline[i]; ) {
char buf[256] = {0}, *ptr = buf;
while(cmdline[i] && isspace(cmdline[i])) ++i;
bool quoted = cmdline[i] == '\"';
if( quoted ) {
while(cmdline[++i]) {
char ch = cmdline[i];
/**/ if (ch == '\\' && cmdline[i + 1] == '\"') *ptr++ = '\"', ++i;
else if (ch == '\"' && cmdline[i + 1] == '\"') ++i;
else if (ch == '\"' && (!cmdline[i + 1] || isspace(cmdline[i + 1]))) {
++i; break;
}
else *ptr++ = ch;
}
} else {
while(cmdline[i] && !isspace(cmdline[i])) *ptr++ = cmdline[i++];
}
if (buf[0] && buf[0] != '#') { // exclude empty args + comments
if( quote_whitespaces && quoted )
array_push(args, va("\"%s\"",buf));
else
array_push(args, va("%s",buf));
}
}
return args;
}
static
char* rpc(unsigned id, const char* cmdline) {
array(char*) args = rpc_parse_args(cmdline, false);
int num_args = array_count(args);
char *ret = num_args ? rpc_full(id, args[0], num_args - 1, &args[1]) : rpc_full(id, "", 0, NULL);
array_free(args);
return ret;
}
static void enet_quit(void) {
do_once {
// enet_deinitialize();
}
}
static void enet_init() {
do_once {
if( enet_initialize() != 0 ) {
PANIC("cannot initialize enet");
}
atexit( enet_quit );
}
}
static ENetHost *Server;
static map(ENetPeer *, int64_t) clients;
static map(int64_t, ENetPeer *) peers;
static int64_t next_client_id = 1; // assumes ID 0 is server
enum { MSG_INIT, MSG_BUF, MSG_RPC, MSG_RPC_RESP };
bool server_bind(int max_clients, int port) {
map_init(clients, less_64, hash_64);
map_init(peers, less_64, hash_64);
assert(port == 0 || (port > 1024 && port < 65500));
ENetAddress address = {0};
address.host = ENET_HOST_ANY;
address.port = port;
Server = enet_host_create(&address, max_clients, 2 /*channels*/, 0 /*in bandwidth*/, 0 /*out bandwidth*/);
return Server != NULL;
}
static
void server_drop_client(int64_t handle) {
map_erase(clients, *(ENetPeer **)map_find(peers, handle));
map_erase(peers, *(int64_t *)handle);
}
static
void server_drop_client_peer(ENetPeer *peer) {
map_erase(peers, *(int64_t *)map_find(clients, peer));
map_erase(clients, peer);
}
void server_poll() {
ENetEvent event;
while( enet_host_service(Server, &event, 2 /*timeout,ms*/) > 0 ) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:;
char ip[128]; enet_peer_get_ip(event.peer, ip, 128);
PRINTF( "A new client connected from ::%s:%u.\n", ip, event.peer->address.port );
/* Store any relevant client information here. */
event.peer->data = "Client information";
int64_t client_id = next_client_id++;
map_find_or_add(clients, event.peer, client_id);
map_find_or_add(peers, client_id, event.peer);
break;
case ENET_EVENT_TYPE_RECEIVE:
PRINTF( "A packet of length %zu containing %s was received from %s on channel %u.\n",
event.packet->dataLength,
event.packet->data,
(char *)event.peer->data,
event.channelID );
char *dbg = (char *)event.peer->data;
char *ptr = event.packet->data;
unsigned sz = event.packet->dataLength;
uint32_t mid = *(uint32_t*)ptr;
ptr += 4;
// @todo: propagate event to user
switch (mid) {
case MSG_INIT: {
uint64_t *cid = map_find(clients, event.peer);
if (cid) {
char init_msg[12];
*(uint32_t*)&init_msg[0] = MSG_INIT;
*(uint64_t*)&init_msg[4] = *cid;
ENetPacket *packet = enet_packet_create(init_msg, 12, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, packet);
} else {
PRINTF("ignoring unk MSG_INIT client packet.\n");
}
} break;
case MSG_RPC:
case MSG_RPC_RESP:
// @todo: process and send a response back
break;
default:
PRINTF("recving unk %d sz %d from peer %s\n", mid, sz, dbg);
}
/* Clean up the packet now that we're done using it. */
enet_packet_destroy( event.packet );
break;
case ENET_EVENT_TYPE_DISCONNECT:
PRINTF( "%s disconnected.\n", (char *)event.peer->data );
/* Reset the peer's client information. */
event.peer->data = NULL;
server_drop_client_peer(event.peer);
break;
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
PRINTF( "%s timeout.\n", (char *)event.peer->data );
event.peer->data = NULL;
server_drop_client_peer(event.peer);
break;
case ENET_EVENT_TYPE_NONE: break;
}
}
}
void client_poll() {
ENetEvent event;
while( enet_host_service(Server, &event, 2 /*timeout,ms*/) > 0 ) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:;
break;
case ENET_EVENT_TYPE_RECEIVE:
PRINTF( "A packet of length %zu containing %s was received from %s on channel %u.\n",
event.packet->dataLength,
event.packet->data,
(char *)event.peer->data,
event.channelID );
char *dbg = (char *)event.peer->data;
char *ptr = event.packet->data;
unsigned sz = event.packet->dataLength;
uint32_t mid = *(uint32_t*)ptr;
ptr += 4;
// @todo: propagate event to user
switch (mid) {
case MSG_INIT:
/* handled during client_join */
break;
case MSG_RPC:
case MSG_RPC_RESP:
// @todo: process and send a response back
break;
default:
PRINTF("recving unk %d sz %d from peer %s\n", mid, sz, dbg);
}
/* Clean up the packet now that we're done using it. */
enet_packet_destroy( event.packet );
break;
case ENET_EVENT_TYPE_DISCONNECT:
PRINTF( "%s disconnected.\n", (char *)event.peer->data );
/* Reset the peer's client information. */
event.peer->data = NULL;
server_drop_client_peer(event.peer);
break;
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
PRINTF( "%s timeout.\n", (char *)event.peer->data );
event.peer->data = NULL;
server_drop_client_peer(event.peer);
break;
case ENET_EVENT_TYPE_NONE: break;
}
}
}
void server_broadcast_bin(const void *msg, int len) {
ENetPacket *packet = enet_packet_create(msg, len, ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(Server, 0, packet);
//enet_host_flush(Server); // flush if needed
}
void server_broadcast(const char *msg) {
server_broadcast_bin(msg, strlen(msg)+1);
}
void server_terminate() {
enet_host_destroy(Server);
Server = 0;
}
volatile int client_join_connected = 0;
static int client_join_threaded(void *userdata) {
ENetHost *host = (ENetHost *)userdata;
ENetPacket *packet = enet_packet_create("", 1, ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(Server, 0, packet);
/* Wait up to 5 seconds for the connection attempt to succeed. */
ENetEvent event;
client_join_connected = 0;
client_join_connected = enet_host_service(host, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT;
return 0;
}
int64_t client_join(const char *ip, int port) {
assert(port > 1024 && port < 65500);
ENetAddress address = {0};
// address.host = ENET_HOST_ANY;
enet_address_set_host(&address, !strcmp(ip, "localhost") ? "127.0.0.1" : ip);
address.port = port;
ENetHost *host = enet_host_create(NULL, 1 /*outgoing connections*/, 2 /*channels*/, 0 /*in bandwidth*/, 0 /*out bandwidth*/);
if(!host) return -1;
ENetPeer *peer = enet_host_connect(host, &address, 2, 0);
if(!peer) return -1;
Server = host;
#if 1
#if 0
// sync wait (not working in localhost, unless threaded)
thread_ptr_t th = thread_init(client_join_threaded, host, "client_join_threaded()", 0 );
thread_join( th );
thread_destroy( th );
#else
ENetEvent event;
bool client_join_connected = enet_host_service(host, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT;
#endif
if(!client_join_connected) { enet_peer_reset(peer); return -1; }
#endif
// ask for server slot
char init_msg[4]; *(uint32_t*)init_msg = MSG_INIT;
server_broadcast_bin(init_msg, sizeof(init_msg));
// wait for the response
bool msg_received = enet_host_service(host, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_RECEIVE;
if (!msg_received) { enet_peer_reset(peer); return -1; }
char *ptr = (char *)event.packet->data;
int64_t cid = -1;
// decapsulate incoming packet.
uint32_t mid = *(uint32_t*)(ptr + 0);
ptr += 4;
switch (mid) {
case MSG_INIT:
cid = *(int64_t*)ptr;
break;
default:
enet_peer_reset(peer);
return -1;
}
/* Clean up the packet now that we're done using it. */
enet_packet_destroy( event.packet );
return cid;
}
void server_drop(int64_t handle) {
enet_peer_disconnect_now(*(ENetPeer **)map_find(peers, handle), 0);
server_drop_client(handle);
}
void server_send_bin(int64_t handle, const void *ptr, int len) {
ENetPacket *packet = enet_packet_create(ptr, len, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(*(ENetPeer **)map_find(peers, handle), 0, packet);
}
void server_send(int64_t handle, const char *msg) {
server_send_bin(handle, msg, strlen(msg)+1);
}
// ---
typedef struct netbuffer_t {
int64_t owner;
void *ptr;
unsigned sz;
unsigned flags;
} netbuffer_t;
static array(char*) events; // @todo: make event 128 bytes max?
static array(int64_t) values; // @todo: map<key,values> instead?
static map( int64_t, array(netbuffer_t) ) buffers; // map<client,array<netbuffer>>
void network_create(const char *ip, const char *port_, unsigned flags) {
if (buffers) map_clear(buffers);
do_once {
array_resize(values, 128);
map_init(buffers, less_64, hash_64);
enet_init();
}
ip = ip ? ip : "0.0.0.0";
int port = atoi(port_ ? port_ : "1234");
// network_put(NETWORK_IP, 0x7F000001); // 127.0.0.1
network_put(NETWORK_PORT, port);
network_put(NETWORK_LIVE, -1);
if( !(flags&NETWORK_CONNECT) || flags&NETWORK_BIND ) {
// server, else client
PRINTF("Trying to bind server, else we connect as a client...\n");
network_put(NETWORK_RANK, 0);
if( server_bind(MAX_CLIENTS, port) ) {
network_put(NETWORK_LIVE, 1);
PRINTF("Server bound\n");
} else {
network_put(NETWORK_RANK, -1); /* unassigned until we connect successfully */
int64_t socket = client_join(ip, port);
if( socket >= 0 ) {
PRINTF("Client connected, id %lld\n", socket);
network_put(NETWORK_LIVE, 1);
network_put(NETWORK_RANK, socket);
} else {
PRINTF("!Client conn failed\n");
network_put(NETWORK_LIVE, 0);
if (!(flags&NETWORK_NOFAIL))
PANIC("cannot neither connect to %s:%d, nor create a server", ip, port);
}
}
} else {
// client only
PRINTF("Connecting to server...\n");
network_put(NETWORK_RANK, -1); /* unassigned until we connect successfully */
int64_t socket = client_join(ip, port);
if( socket > 0 ) {
PRINTF("Client connected, id %lld\n", socket);
network_put(NETWORK_LIVE, 1);
network_put(NETWORK_RANK, socket);
} else {
PRINTF("!Client conn failed\n");
network_put(NETWORK_LIVE, 0);
if (!(flags&NETWORK_NOFAIL))
PANIC("cannot connect to server %s:%d", ip, port);
}
}
PRINTF("Network rank:%lld ip:%s port:%lld\n", network_get(NETWORK_RANK), ip, network_get(NETWORK_PORT));
}
int64_t network_put(uint64_t key, int64_t value) {
int64_t *found = key < array_count(values) ? &values[key] : NULL;
if(found) *found = value;
return value;
}
int64_t network_get(uint64_t key) {
int64_t *found = key < array_count(values) ? &values[key] : NULL;
return found ? *found : 0;
}
void* network_buffer(void *ptr, unsigned sz, unsigned flags, int64_t rank) {
assert(flags);
array(netbuffer_t) *found = map_find_or_add(buffers, rank, NULL);
netbuffer_t nb;
nb.owner = rank;
nb.ptr = ptr;
nb.sz = sz;
nb.flags = flags;
array_push(*found, nb);
return ptr;
}
char** network_sync(unsigned timeout_ms) {
array_clear(events);
int64_t whoami = network_get(NETWORK_RANK);
bool is_server = whoami == 0;
bool is_client = !is_server;
if(timeout_ms < 2) timeout_ms = 2;
// sleep_ms(timeout_ms); // @fixme. server only?
// Split buffers into clients @todo
// clients need to do this before network polling; servers should do this after polling.
map_foreach(buffers, int64_t, rank, array(netbuffer_t), list) {
for(int i = 0, end = array_count(list); i < end; ++i) {
netbuffer_t *nb = &list[i];
if (!is_server && !(nb->flags & NETWORK_SEND))
continue;
static array(char) encapsulate;
array_resize(encapsulate, nb->sz + 28);
uint32_t *mid = (uint32_t*)&encapsulate[0]; *mid = MSG_BUF;
uint64_t *st = (uint64_t*)&encapsulate[4]; *st = nb->flags;
uint32_t *idx = (uint32_t*)&encapsulate[12]; *idx = i;
uint32_t *len = (uint32_t*)&encapsulate[16]; *len = nb->sz;
uint64_t *who = (uint64_t*)&encapsulate[20]; *who = nb->owner;
// PRINTF("sending %llx %u %lld %u\n", *st, *idx, *who, *len);
memcpy(&encapsulate[28], nb->ptr, nb->sz);
server_broadcast_bin(&encapsulate[0], nb->sz + 28);
}
}
// network poll
for( ENetEvent event; Server && enet_host_service(Server, &event, timeout_ms) > 0; ) {
char *msg = 0;
char ip[128]; enet_peer_get_ip(event.peer, ip, 128);
switch (event.type) {
default: // case ENET_EVENT_TYPE_NONE:
break;
case ENET_EVENT_TYPE_CONNECT:;
msg = va( "A new client connected from ::%s:%u", ip, event.peer->address.port );
/* Store any relevant client information here. */
event.peer->data = "Client information";
/* ensure we have free slot for client */
if (map_count(clients) >= MAX_CLIENTS) {
msg = va("%s\n", "Server is at maximum capacity, disconnecting the peer...");
enet_peer_disconnect_now(event.peer, 1);
break;
}
int64_t client_id = next_client_id++;
map_find_or_add(clients, event.peer, client_id);
map_find_or_add(peers, client_id, event.peer);
break;
case ENET_EVENT_TYPE_RECEIVE:;
/*
msg = va( "A packet of length %u containing %s was received from %s on channel %u",
(unsigned)event.packet->dataLength,
event.packet->data,
(char *)event.peer->data,
event.channelID );
*/
char *dbg = (char *)event.peer->data;
char *ptr = (char *)event.packet->data;
unsigned sz = (unsigned)event.packet->dataLength;
unsigned id = (unsigned)event.channelID;
// debug
// puts(dbg);
// hexdump(ptr, sz);
// decapsulate incoming packet.
uint32_t mid = *(uint32_t*)(ptr + 0);
ptr += 4;
switch (mid) {
case MSG_INIT:
if (is_server) {
uint64_t *cid = map_find(clients, event.peer);
if (cid) {
char init_msg[12];
*(uint32_t*)&init_msg[0] = MSG_INIT;
*(int64_t*)&init_msg[4] = *cid;
ENetPacket *packet = enet_packet_create(init_msg, 12, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, packet);
PRINTF("Client req id %lld for peer ::%s:%u\n", *cid, ip, event.peer->address.port);
} else {
PRINTF("!Ignoring unk MSG_INIT client packet.\n");
}
}
break;
case MSG_BUF: {
uint64_t *flags = (uint64_t*)(ptr + 0);
uint32_t *idx = (uint32_t*)(ptr + 8);
uint32_t *len = (uint32_t*)(ptr + 12);
uint64_t *who = (uint64_t*)(ptr + 16);
// PRINTF("recving %d %llx %u %u %lld\n", mid, *flags, *idx, *len, *who);
ptr += 24;
// validate if peer owns the buffer
uint8_t client_valid = 0;
if (is_server) {
int64_t *cid = map_find(clients, event.peer);
client_valid = cid ? *cid == *who : 0;
}
// apply incoming packet.
if( is_client ? *who != whoami : client_valid ) { // clients merge always foreign packets. servers merge foreign packets.
array(netbuffer_t) *list = map_find(buffers, *who);
assert( list );
assert( *idx < array_count(*list) );
netbuffer_t *nb = &(*list)[*idx];
assert( *len == nb->sz );
memcpy(nb->ptr, ptr, *len);
}
} break;
case MSG_RPC: {
unsigned id = *(uint32_t*)ptr; ptr += 4;
char *cmdline = ptr;
char *resp = rpc(id, cmdline);
char *resp_msg = va("%*.s%s", 4, "", resp);
*(uint32_t*)&resp_msg[0] = MSG_RPC_RESP;
ENetPacket *packet = enet_packet_create(resp_msg, 4 + strlen(resp), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, 0, packet);
} break;
case MSG_RPC_RESP: {
// @todo: react on response?
msg = ptr;
} break;
default:
// PRINTF("!Receiving unk %d sz %d from peer ::%s:%u\n", mid, sz, ip, event.peer->address.port);
break;
}
/* Clean up the packet now that we're done using it. */
enet_packet_destroy( event.packet );
break;
case ENET_EVENT_TYPE_DISCONNECT:
msg = va( "%s disconnected", (char *)event.peer->data );
/* Reset the peer's client information. */
event.peer->data = NULL;
if (is_server) server_drop_client_peer(event.peer);
else {network_put(NETWORK_RANK, -1); network_put(NETWORK_LIVE, 0);}
break;
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
msg = va( "%s timeout", (char *)event.peer->data );
event.peer->data = NULL;
if (is_server) server_drop_client_peer(event.peer);
else {network_put(NETWORK_RANK, -1); network_put(NETWORK_LIVE, 0);}
break;
}
if(msg) array_push(events, va("%d %s", event.type, msg));
// if(msg) server_broadcast(msg);
}
array_push(events, NULL);
return events;
}
void network_rpc(const char *signature, void *function) {
rpc_insert(signature, function);
}
void network_rpc_send_to(int64_t rank, unsigned id, const char *cmdline) {
assert(network_get(NETWORK_RANK) == 0); /* must be a host */
char *msg = va("%*.s%s", 8, "", cmdline);
*(uint32_t*)&msg[0] = MSG_RPC;
*(uint32_t*)&msg[4] = id;
server_send_bin(rank, msg, 8 + strlen(cmdline));
}
void network_rpc_send(unsigned id, const char *cmdline) {
char *msg = va("%*.s%s", 8, "", cmdline);
*(uint32_t*)&msg[0] = MSG_RPC;
*(uint32_t*)&msg[4] = id;
server_broadcast_bin(msg, 8 + strlen(cmdline));
}

View File

@ -12,8 +12,9 @@ camera_t cam;
void game_loop(void *userdata) {
// key handler
if (input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen()^1 );
if (input_down(KEY_ESC) ) window_loop_exit(); // @todo: break -> window_close()
// if (input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen()^1 );
// if (input_down(KEY_ESC) ) window_loop_exit(); // @todo: break -> window_close()
window_resize();
// animation
static float dx = 0, dy = 0;

View File

@ -100,6 +100,13 @@
},
canvas: (function() {
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
})
return canvas;
})(),
setStatus: function(text) {

View File

@ -2458,6 +2458,13 @@ unsigned num_instances;
bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out);
void model_destroy(model_t);
vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe);
typedef struct anims_t {
int inuse;
float speed;
anim_t* anims;
mat44* M;
} anims_t;
anims_t animations(const char *pathfile, int flags);
typedef struct skybox_t {
handle program;
mesh_t geometry;
@ -2803,6 +2810,7 @@ WINDOW_VSYNC_DISABLED =8192,
int window_swap();
void window_loop(void (*function)(void* loopArg), void* loopArg );
void window_loop_exit();
void window_resize();
void window_title(const char *title);
void window_icon(const char *file_icon);
void window_color(unsigned color);

View File

@ -16619,6 +16619,18 @@ API void model_destroy(model_t);
API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe);
// -----------------------------------------------------------------------------
// model animations
typedef struct anims_t {
int inuse; // animation number in use
float speed; // x1.00
array(anim_t) anims; // [begin,end,flags] frames of every animation in set
array(mat44) M; // instanced transforms
} anims_t;
API anims_t animations(const char *pathfile, int flags);
// -----------------------------------------------------------------------------
// skyboxes
@ -17165,6 +17177,7 @@ API int window_swap(); // single function that combines above functions (de
API void window_loop(void (*function)(void* loopArg), void* loopArg ); // run main loop function continuously (emscripten only)
API void window_loop_exit(); // exit from main loop function (emscripten only)
API void window_resize(); // resize if canvas size has changed (emscripten only)
API void window_title(const char *title);
API void window_icon(const char *file_icon);
@ -343986,6 +343999,29 @@ void model_destroy(model_t m) {
#undef buf
#undef bounds
#undef colormaps
anims_t animations(const char *pathfile, int flags) {
anims_t a = {0};
char *anim_file = vfs_read(pathfile);
for each_substring(anim_file, "\r\n", anim) {
int from, to;
char anim_name[128] = {0};
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
array_push(a.anims, !!strstri(anim_name, "loop") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
array_back(a.anims)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", "");
}
array_resize(a.M, 32*32);
for(int z = 0, i = 0; z < 32; ++z) {
for(int x = 0; x < 32; ++x, ++i) {
vec3 p = vec3(-x*3,0,-z*3);
vec3 r = vec3(0,0,0);
vec3 s = vec3(2,2,2);
compose44(a.M[i], p, eulerq(r), s);
}
}
a.speed = 1.0;
return a;
}
#line 0
#line 1 "v4k_renderdd.c"
@ -349762,8 +349798,8 @@ void window_loop_exit() {
vec2 window_canvas() {
#if is(ems)
int width = EM_ASM_INT_V(return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
int height = EM_ASM_INT_V(return window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight);
int width = EM_ASM_INT_V(return canvas.width || window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
int height = EM_ASM_INT_V(return canvas.height || window.innerHeight || document.documentElement.clientHeight|| document.body.clientHeight);
return vec2(width, height);
#else
glfw_init();
@ -349773,6 +349809,23 @@ vec2 window_canvas() {
#endif /* __EMSCRIPTEN__ */
}
static vec2 last_canvas_size;
void window_resize() {
#if is(ems)
vec2 size = window_canvas();
do_once last_canvas_size = size;
if (size.x != last_canvas_size.x || size.y != last_canvas_size.y) {
w = size.x;
h = size.y;
g->width = w;
g->height = h;
glfwSetWindowSize(g->window, w, h);
// emscripten_set_canvas_size(w, h);
}
#endif /* __EMSCRIPTEN__ */
}
int window_width() {
return w;
}

View File

@ -4218,3 +4218,26 @@ void model_destroy(model_t m) {
#undef buf
#undef bounds
#undef colormaps
anims_t animations(const char *pathfile, int flags) {
anims_t a = {0};
char *anim_file = vfs_read(pathfile);
for each_substring(anim_file, "\r\n", anim) {
int from, to;
char anim_name[128] = {0};
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
array_push(a.anims, !!strstri(anim_name, "loop") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
array_back(a.anims)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", "");
}
array_resize(a.M, 32*32);
for(int z = 0, i = 0; z < 32; ++z) {
for(int x = 0; x < 32; ++x, ++i) {
vec3 p = vec3(-x*3,0,-z*3);
vec3 r = vec3(0,0,0);
vec3 s = vec3(2,2,2);
compose44(a.M[i], p, eulerq(r), s);
}
}
a.speed = 1.0;
return a;
}

View File

@ -486,6 +486,18 @@ API void model_destroy(model_t);
API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe);
// -----------------------------------------------------------------------------
// model animations
typedef struct anims_t {
int inuse; // animation number in use
float speed; // x1.00
array(anim_t) anims; // [begin,end,flags] frames of every animation in set
array(mat44) M; // instanced transforms
} anims_t;
API anims_t animations(const char *pathfile, int flags);
// -----------------------------------------------------------------------------
// skyboxes

View File

@ -615,8 +615,8 @@ void window_loop_exit() {
vec2 window_canvas() {
#if is(ems)
int width = EM_ASM_INT_V(return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
int height = EM_ASM_INT_V(return window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight);
int width = EM_ASM_INT_V(return canvas.width || window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
int height = EM_ASM_INT_V(return canvas.height || window.innerHeight || document.documentElement.clientHeight|| document.body.clientHeight);
return vec2(width, height);
#else
glfw_init();
@ -626,6 +626,23 @@ vec2 window_canvas() {
#endif /* __EMSCRIPTEN__ */
}
static vec2 last_canvas_size;
void window_resize() {
#if is(ems)
vec2 size = window_canvas();
do_once last_canvas_size = size;
if (size.x != last_canvas_size.x || size.y != last_canvas_size.y) {
w = size.x;
h = size.y;
g->width = w;
g->height = h;
glfwSetWindowSize(g->window, w, h);
// emscripten_set_canvas_size(w, h);
}
#endif /* __EMSCRIPTEN__ */
}
int window_width() {
return w;
}

View File

@ -33,6 +33,7 @@ API int window_swap(); // single function that combines above functions (de
API void window_loop(void (*function)(void* loopArg), void* loopArg ); // run main loop function continuously (emscripten only)
API void window_loop_exit(); // exit from main loop function (emscripten only)
API void window_resize(); // resize if canvas size has changed (emscripten only)
API void window_title(const char *title);
API void window_icon(const char *file_icon);

View File

@ -15056,6 +15056,29 @@ void model_destroy(model_t m) {
#undef buf
#undef bounds
#undef colormaps
anims_t animations(const char *pathfile, int flags) {
anims_t a = {0};
char *anim_file = vfs_read(pathfile);
for each_substring(anim_file, "\r\n", anim) {
int from, to;
char anim_name[128] = {0};
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
array_push(a.anims, !!strstri(anim_name, "loop") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
array_back(a.anims)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", "");
}
array_resize(a.M, 32*32);
for(int z = 0, i = 0; z < 32; ++z) {
for(int x = 0; x < 32; ++x, ++i) {
vec3 p = vec3(-x*3,0,-z*3);
vec3 r = vec3(0,0,0);
vec3 s = vec3(2,2,2);
compose44(a.M[i], p, eulerq(r), s);
}
}
a.speed = 1.0;
return a;
}
#line 0
#line 1 "v4k_renderdd.c"
@ -20832,8 +20855,8 @@ void window_loop_exit() {
vec2 window_canvas() {
#if is(ems)
int width = EM_ASM_INT_V(return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
int height = EM_ASM_INT_V(return window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight);
int width = EM_ASM_INT_V(return canvas.width || window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
int height = EM_ASM_INT_V(return canvas.height || window.innerHeight || document.documentElement.clientHeight|| document.body.clientHeight);
return vec2(width, height);
#else
glfw_init();
@ -20843,6 +20866,23 @@ vec2 window_canvas() {
#endif /* __EMSCRIPTEN__ */
}
static vec2 last_canvas_size;
void window_resize() {
#if is(ems)
vec2 size = window_canvas();
do_once last_canvas_size = size;
if (size.x != last_canvas_size.x || size.y != last_canvas_size.y) {
w = size.x;
h = size.y;
g->width = w;
g->height = h;
glfwSetWindowSize(g->window, w, h);
// emscripten_set_canvas_size(w, h);
}
#endif /* __EMSCRIPTEN__ */
}
int window_width() {
return w;
}

View File

@ -2702,6 +2702,18 @@ API void model_destroy(model_t);
API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe);
// -----------------------------------------------------------------------------
// model animations
typedef struct anims_t {
int inuse; // animation number in use
float speed; // x1.00
array(anim_t) anims; // [begin,end,flags] frames of every animation in set
array(mat44) M; // instanced transforms
} anims_t;
API anims_t animations(const char *pathfile, int flags);
// -----------------------------------------------------------------------------
// skyboxes
@ -3248,6 +3260,7 @@ API int window_swap(); // single function that combines above functions (de
API void window_loop(void (*function)(void* loopArg), void* loopArg ); // run main loop function continuously (emscripten only)
API void window_loop_exit(); // exit from main loop function (emscripten only)
API void window_resize(); // resize if canvas size has changed (emscripten only)
API void window_title(const char *title);
API void window_icon(const char *file_icon);

File diff suppressed because one or more lines are too long

BIN
tools/7zr.exe 100644

Binary file not shown.

View File

@ -26,6 +26,7 @@ int doanim = 0; // export animations
int dobone = 0; // export skeleton
int doflip = 1; // export flipped (quake-style clockwise winding) triangles
int doflipUV = 0; // export flipped UVs
int doanimlist = 0; // generate list of animations with properties
int doaxis = 0; // flip bone axis from X to Y to match blender
int dounscale = 0; // remove scaling from bind pose
@ -853,6 +854,23 @@ void export_animations(FILE *out, const struct aiScene *scene)
export_static_animation(out, scene);
}
void export_animlist(FILE *out, const struct aiScene *scene)
{
int i, offset=0, len;
for (i = 0; i < scene->mNumAnimations; i++) {
const struct aiAnimation *anim = scene->mAnimations[i];
len = animation_length(anim)-1;
fprintf(stderr, "frame: %d-%d %s\n", offset, offset+len, anim->mName.data);
fprintf(out, "frame: %d-%d %s\n", offset, offset+len, anim->mName.data);
offset += len+1;
}
if (scene->mNumAnimations == 0)
fprintf(out, "frame: %s\n", "0-0 Idle");
}
/*
* For multi-mesh models, sometimes each mesh has its own inv_bind_matrix set
* for each bone. To export to IQE we must have only one inv_bind_matrix per
@ -1248,6 +1266,7 @@ void usage()
fprintf(stderr, "\t-U -- flip UVs\n");
fprintf(stderr, "\t-n mesh -- export only the named mesh\n");
fprintf(stderr, "\t-a -- only export animations\n");
fprintf(stderr, "\t-L -- export only animation list\n");
fprintf(stderr, "\t-m -- only export mesh\n");
fprintf(stderr, "\t-b -- bake mesh to bind pose / initial frame\n");
fprintf(stderr, "\t-f -- export counter-clockwise winding triangles\n");
@ -1301,7 +1320,7 @@ int main(int argc, char **argv)
int onlyanim = 0;
int onlymesh = 0;
while ((c = getopt(argc, argv, "AHMPSUabflmn:o:rvxsu:")) != -1) {
while ((c = getopt(argc, argv, "AHLMPSUabflmn:o:rvxsu:")) != -1) {
switch (c) {
case 'A': save_all_bones++; break;
case 'H': dohips = 1; break;
@ -1317,6 +1336,7 @@ case 'U': doflipUV = 1; puts("using flipUV"); break;
case 'f': doflip = 0; break;
case 'r': dorigid = 1; break;
case 'l': dolowprec = 1; break;
case 'L': doanimlist = 1; break;
case 'v': verbose++; break;
case 'x': doaxis = 1; break;
case 's': dounscale = 1; break;
@ -1436,6 +1456,17 @@ flags |= (doflipUV ? aiProcess_FlipUVs : 0);
if (onlymesh) { domesh = 1; doanim = 0; }
if (onlyanim) { domesh = 0; doanim = 1; }
if (doanimlist) {
fprintf(stderr, "exporting animation list for %s ...\n", basename);
file = fopen(output, "w");
if (!file) {
fprintf(stderr, "cannot open output file: '%s'\n", output);
exit(1);
}
export_animlist(file, scene);
return 0;
}
if (getenv("DOANIM")) doanim = 1;
// Convert to Z-UP coordinate system

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -19,7 +19,7 @@ exit
@echo off
cd "%~dp0"
git clone https://github.com/assimp/assimp && md assimp\.build && pushd assimp\.build
git clone https://github.com/assimp/assimp && pushd assimp && git checkout 05115b07 && popd && md assimp\.build && pushd assimp\.build
rem fart -- ..\CMakeLists.txt assimp-${ASSIMP_MSVC_VERSION}-mt.dll assimp.dll
rem fart -- ..\CMakeLists.txt assimp-${ASSIMP_MSVC_VERSION}-mt.lib assimp.lib
rem cmake .. -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 14 2015" && msbuild assimp.sln -m -p:Configuration=Release -p:PlatformToolset=140
@ -30,7 +30,7 @@ xcopy /y assimp\.build\bin\release\*.dll
xcopy /y assimp\.build\lib\release\*.lib
copy /y assimp\include\assimp\config.h.in assimp\config.h && fart -- assimp\config.h "cmakedefine" "//#define"
cl ass2iqe.c -I . -I assimp\include assimp-vc142-mt.lib /O2 /Oy /MT /DNDEBUG
cl ass2iqe.c -I . -I assimp\include assimp-vc143-mt.lib /O2 /Oy /MT /DNDEBUG
rem xcopy assimp\.build\bin\release\*.dll x64\ /s
rem xcopy assimp\.build\lib\release\*.lib x64\ /s

BIN
tools/bspinfo.exe 100644

Binary file not shown.

BIN
tools/bsputil.exe 100644

Binary file not shown.

View File

@ -39,6 +39,7 @@ icons=ico
image=jpg,png,bmp,psd,pic,pnm,hdr
texture=pvr,ktx,ktx2,dds,astc,basis,tga
model=iqm,iqe,gltf,gltf2,glb,fbx,obj,dae,blend,md3,md5,ms3d,smd,x,3ds,bvh,dxf,lwo
anims=anim
audio=wav,flac,ogg,mp1,mp3,mid,sfxr ; ,mod,xm
audio-modules=mod,xm,s3m,it
audio-furnace=fur
@ -67,7 +68,7 @@ TOOLS/ffmpeg.EXE -hide_banner -nostdin -loglevel fatal -y -i INPUT -f ogg -b:a 3
; cook midis as wavs here
[cook audio && mid]
SOUNDBANK=AweROMGM.sf3
SOUNDBANK=AweROMGM.sf3 ; note: GeneralUser_GS_v1_471.sf3 or FluidR3.sf3 likely to produce better results
TOOLS/mid2wav.EXE INPUT OUTPUT TOOLS/SOUNDBANK -> wav
; and furs as wavs...
@ -163,12 +164,16 @@ TOOLS/cuttlefish.EXE -q -m -i INPUT -o OUTPUT -f BC1_RGBA -> ktx
; ------------------------------------------------------------------------------
; finally, let's cook all models. the logic here is:
; 1. cook all models into iqe (ass2iqe), then into iqm (iqe2iqm): any -> iqe -> iqm
; 2. unless input is iqe. these models will run iqe2iqm only (no ass2iqe): iqe -> iqm.
; 3. unless input is iqm. these models will not run any conversion at all: iqm.
; 4. also, dae models need to flip their UVs coordinates (see -U flag below).
; 1. export animation list from models using ass2iqe -L
; 2. cook all models into iqe (ass2iqe), then into iqm (iqe2iqm): any -> iqe -> iqm
; 3. unless input is iqe. these models will run iqe2iqm only (no ass2iqe): iqe -> iqm.
; 4. unless input is iqm. these models will not run any conversion at all: iqm.
; 5. also, dae models need to flip their UVs coordinates (see -U flag below).
[cook model && dae] ; pass dae, reject iqm,iqe or any other model
[cook anims] ; process all models to extract animlist
TOOLS/ass2iqe.EXE -L -o OUTPUT INPUT 2> NUL
[cook model && dae &&] ; pass dae, reject iqm,iqe or any other model
FLAGS=
TOOLS/ass2iqe.EXE FLAGS -o OUTPUT INPUT -U 2> NUL -> iqe
@ -199,5 +204,5 @@ TOOLS/iqe2iqm.EXE OUTPUT INPUT > NUL -> iqm
; hint: use plain `0` to exclude those files we would like to directly stream within the final zipfile (flac,mp3,adpcm wav,...)
[compress]
0|ULZ=texture,image,model,audio,font,text,shader,script
0=video,flac,ogg,wav,mp1,mp3,jpg,png
0|ULZ=texture,image,model,audio,font,text,shader,script,animlist
0=video,flac,ogg,wav,mp1,mp3,jpg,png

BIN
tools/embree.dll 100644

Binary file not shown.

BIN
tools/freeglut.dll 100644

Binary file not shown.

Binary file not shown.

BIN
tools/libintl-8.dll 100644

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tools/light.exe 100644

Binary file not shown.

BIN
tools/qbsp.exe 100644

Binary file not shown.

BIN
tools/tbb.dll 100644

Binary file not shown.

BIN
tools/tbbmalloc.dll 100644

Binary file not shown.

BIN
tools/vis.exe 100644

Binary file not shown.

BIN
tools/zlib1.dll 100644

Binary file not shown.

View File

@ -3,7 +3,7 @@
[
{
"path": ".",
"file_exclude_patterns": ["*.zip"],
"file_exclude_patterns": ["*.zip", "*.ilk", "*.exp"],
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/v4k.h", "engine/v4k.c"]
}
],