348 lines
8.8 KiB
C++
348 lines
8.8 KiB
C++
static int matloader(void *ud, struct ResManRes *res) {
|
|
char namebuf[256] = {};
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%s.lua", res->name);
|
|
|
|
struct k3Mat *mat = _mm_malloc(sizeof(*mat), 16);
|
|
luaapi_fillmaterial(namebuf, mat);
|
|
|
|
res->thing = mat;
|
|
return 1;
|
|
}
|
|
|
|
static int mdlloader(void *ud, struct ResManRes *res) {
|
|
char buf[256];
|
|
snprintf(buf, sizeof(buf), "assets/mdl/%s.k3m", res->name);
|
|
|
|
FILE *f = fopen(buf, "rb");
|
|
|
|
struct {
|
|
uint32_t magic;
|
|
uint32_t vertCount;
|
|
uint32_t indCount;
|
|
uint8_t boneCount;
|
|
uint8_t flags;
|
|
uint16_t animCount;
|
|
} header;
|
|
fread(&header, 4, 4, f);
|
|
|
|
int colorsEnabled = header.flags & 1;
|
|
|
|
mat4 *invBind = _mm_malloc(sizeof(*invBind) * header.boneCount, 16);
|
|
fread(invBind, sizeof(*invBind), header.boneCount, f);
|
|
|
|
uint8_t *boneParents = malloc(header.boneCount);
|
|
fread(boneParents, 1, header.boneCount, f);
|
|
|
|
vec3 *pos = malloc(sizeof(*pos) * header.vertCount);
|
|
fread(pos, sizeof(vec3), header.vertCount, f);
|
|
|
|
uint8_t *nrm = malloc(3 * header.vertCount);
|
|
fread(nrm, 3, header.vertCount, f);
|
|
|
|
float *uvs = malloc(8 * header.vertCount);
|
|
fread(uvs, 8, header.vertCount, f);
|
|
|
|
uint8_t *boneIDs = malloc(4 * header.vertCount);
|
|
fread(boneIDs, 4, header.vertCount, f);
|
|
|
|
uint16_t *boneWeights = malloc(8 * header.vertCount);
|
|
fread(boneWeights, 8, header.vertCount, f);
|
|
|
|
uint8_t *cols = NULL;
|
|
if(colorsEnabled) {
|
|
cols = malloc(4 * header.vertCount);
|
|
fread(cols, 4, header.vertCount, f);
|
|
}
|
|
|
|
uint16_t *inds = malloc(sizeof(*inds) * header.indCount);
|
|
fread(inds, sizeof(uint16_t), header.indCount, f);
|
|
|
|
struct k3Mdl *mdl = k3MdlCreate(header.vertCount, header.indCount, header.boneCount, pos, nrm, uvs, cols, boneIDs, boneWeights, inds, invBind, boneParents);
|
|
|
|
k3MdlSetDebugName(mdl, res->name);
|
|
|
|
free(pos);
|
|
free(nrm);
|
|
free(uvs);
|
|
free(inds);
|
|
|
|
uint16_t meshes;
|
|
fread(&meshes, sizeof(uint16_t), 1, f);
|
|
|
|
for(uint32_t i = 0; i < meshes; i++) {
|
|
uint16_t startnum[2];
|
|
fread(startnum, sizeof(uint16_t), 2, f);
|
|
|
|
char buf[256] = {};
|
|
for(int c = 0; c < sizeof(buf) - 1; c++) {
|
|
fread(buf + c, 1, 1, f);
|
|
if(buf[c] == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
k3MdlAddMesh(mdl, resman_ref(RESMAN_MATERIAL, buf), startnum[0], startnum[1]);
|
|
}
|
|
|
|
for(size_t i = 0; i < header.animCount; i++) {
|
|
struct {
|
|
uint16_t id;
|
|
uint16_t frames;
|
|
uint16_t fps;
|
|
uint16_t zero;
|
|
} info;
|
|
fread(&info, sizeof(info), 1, f);
|
|
|
|
struct k3Animation *anim = malloc(sizeof(*anim));
|
|
anim->frames = _mm_malloc(sizeof(*anim->frames) * info.frames * header.boneCount, 16);
|
|
anim->boneParents = boneParents;
|
|
anim->invBind = invBind;
|
|
anim->id = info.id;
|
|
anim->fps = info.fps;
|
|
anim->frameCount = info.frames;
|
|
anim->boneCount = header.boneCount;
|
|
|
|
fread(anim->frames, sizeof(*anim->frames), info.frames * header.boneCount, f);
|
|
|
|
k3MdlAddAnim(mdl, anim);
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
res->thing = mdl;
|
|
return 1;
|
|
}
|
|
|
|
static int physloader(void *ud, struct ResManRes *res) {
|
|
char namebuf[256];
|
|
snprintf(namebuf, sizeof(namebuf), "assets/phys/%s.phys", res->name);
|
|
|
|
FILE *p = fopen(namebuf, "rb");
|
|
if(!p) return 0;
|
|
dTriMeshDataID trid = dGeomTriMeshDataCreate();
|
|
fseek(p, 0, SEEK_END);
|
|
size_t len = ftell(p);
|
|
assert(len % 36 == 0);
|
|
fseek(p, 0, SEEK_SET);
|
|
float *data = malloc(len);
|
|
fread(data, 1, len, p);
|
|
int *idxs = malloc(sizeof(*idxs) * (len / sizeof(vec3)));
|
|
for(int i = 0; i < len / sizeof(vec3); i++) idxs[i] = i;
|
|
dGeomTriMeshDataBuildSingle(trid, data, sizeof(vec3), len / sizeof(vec3), idxs, len / sizeof(vec3), 3 * sizeof(int));
|
|
fclose(p);
|
|
|
|
struct TrimeshData *ret = malloc(sizeof(*ret));
|
|
ret->vdata = data;
|
|
ret->idata = idxs;
|
|
ret->trid = trid;
|
|
|
|
res->thing = ret;
|
|
return 1;
|
|
}
|
|
|
|
static int binloader(void *ud, struct ResManRes *res) {
|
|
char namebuf[256];
|
|
snprintf(namebuf, sizeof(namebuf), "assets/%s", res->name);
|
|
|
|
FILE *f = fopen(namebuf, "rb");
|
|
if(!f) return 0;
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
size_t len = ftell(f);
|
|
struct ResManBin *data = malloc(sizeof(*data) + len + 1);
|
|
fseek(f, 0, SEEK_SET);
|
|
fread(data->data, 1, len, f);
|
|
data->data[len] = 0;
|
|
data->length = len;
|
|
fclose(f);
|
|
|
|
res->thing = data;
|
|
return 1;
|
|
}
|
|
static void binunloader(void *ud, const char *name, void *data) {
|
|
free(data);
|
|
}
|
|
|
|
static int streamloader(void *ud, struct ResManRes *res) {
|
|
char namebuf[256];
|
|
snprintf(namebuf, sizeof(namebuf), "assets/aud/%s", res->name);
|
|
|
|
res->thing = k3MixSourceFile(namebuf);
|
|
return 1;
|
|
}
|
|
|
|
static int refresh_texture(struct ResManRes *res) {
|
|
if(strlen(res->name) < 8) return 0;
|
|
|
|
const char *suffix = res->name + strlen(res->name) - 8;
|
|
|
|
if(!strcmp(suffix, ".cub.png")) {
|
|
char namebuf[256];
|
|
int w, h, origN;
|
|
unsigned char *data;
|
|
|
|
struct k3Tex *tex = res->thing;
|
|
|
|
if(!tex) {
|
|
tex = k3TexCreate(k3_CUBEMAP);
|
|
}
|
|
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.nx.png", suffix - res->name, res->name);
|
|
data = stbi_load(namebuf, &w, &h, &origN, 4);
|
|
k3TexUpdate(tex, k3_DIFFUSE, 1, w, h, data);
|
|
stbi_image_free(data);
|
|
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.px.png", suffix - res->name, res->name);
|
|
data = stbi_load(namebuf, &w, &h, &origN, 4);
|
|
k3TexUpdate(tex, k3_DIFFUSE, 0, w, h, data);
|
|
stbi_image_free(data);
|
|
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.py.png", suffix - res->name, res->name);
|
|
data = stbi_load(namebuf, &w, &h, &origN, 4);
|
|
k3TexUpdate(tex, k3_DIFFUSE, 2, w, h, data);
|
|
stbi_image_free(data);
|
|
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.ny.png", suffix - res->name, res->name);
|
|
data = stbi_load(namebuf, &w, &h, &origN, 4);
|
|
k3TexUpdate(tex, k3_DIFFUSE, 3, w, h, data);
|
|
stbi_image_free(data);
|
|
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.nz.png", suffix - res->name, res->name);
|
|
data = stbi_load(namebuf, &w, &h, &origN, 4);
|
|
k3TexUpdate(tex, k3_DIFFUSE, 5, w, h, data);
|
|
stbi_image_free(data);
|
|
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.pz.png", suffix - res->name, res->name);
|
|
data = stbi_load(namebuf, &w, &h, &origN, 4);
|
|
k3TexUpdate(tex, k3_DIFFUSE, 4, w, h, data);
|
|
stbi_image_free(data);
|
|
|
|
res->thing = tex;
|
|
} else {
|
|
enum k3TexType type;
|
|
int n, gamma;
|
|
|
|
if(!strcmp(suffix, ".alp.png")) {
|
|
type = k3_ALPHA;
|
|
n = 1;
|
|
gamma = 0;
|
|
} else if(!strcmp(suffix, ".nrm.png")) {
|
|
type = k3_NORMAL;
|
|
n = 4;
|
|
gamma = 1;
|
|
} else if(!strcmp(suffix, ".dsp.png")) {
|
|
type = k3_DISPLACEMENT;
|
|
n = 1;
|
|
gamma = 0;
|
|
} else if(!strcmp(suffix, ".emt.png")) {
|
|
type = k3_EMISSION;
|
|
n = 4;
|
|
gamma = 1;
|
|
} else if(!strcmp(suffix, ".rgh.png")) {
|
|
type = k3_ROUGHNESS;
|
|
n = 1;
|
|
gamma = 0;
|
|
} else if(!strcmp(suffix, ".dif.png")) {
|
|
type = k3_DIFFUSE;
|
|
n = 4;
|
|
gamma = 1;
|
|
} else return 0;
|
|
|
|
char namebuf[256];
|
|
snprintf(namebuf, sizeof(namebuf), "assets/mdl/%s", res->name);
|
|
|
|
int w, h, origN;
|
|
unsigned char *data = stbi_load(namebuf, &w, &h, &origN, n);
|
|
int stbifree = 1;
|
|
|
|
if(TextureResolutionReduction && data) {
|
|
int newW = w >> TextureResolutionReduction;
|
|
int newH = h >> TextureResolutionReduction;
|
|
|
|
if(newW <= 4) newW = 4;
|
|
if(newH <= 4) newH = 4;
|
|
|
|
unsigned char *data2 = malloc(newW * newH * n);
|
|
int success = stbir_resize_uint8_generic(data, w, h, 0, data2, newW, newH, 0, n, n == 4 ? 3 : -1, 0, STBIR_EDGE_WRAP, STBIR_FILTER_DEFAULT, gamma ? STBIR_COLORSPACE_SRGB : STBIR_COLORSPACE_LINEAR, NULL);
|
|
|
|
if(success) {
|
|
stbi_image_free(data);
|
|
|
|
w = newW;
|
|
h = newH;
|
|
data = data2;
|
|
stbifree = 0;
|
|
} else {
|
|
free(data2);
|
|
}
|
|
}
|
|
|
|
if(!res->thing) {
|
|
res->thing = k3TexCreate(type);
|
|
}
|
|
|
|
if(data) {
|
|
k3TexUpdate(res->thing, type, 0, w, h, data);
|
|
|
|
if(stbifree) {
|
|
stbi_image_free(data);
|
|
} else {
|
|
free(data);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int refresh_textures() {
|
|
for(int b = 0; b < RESMAN_BUCKETS; b++) {
|
|
for(struct ResManRes *r = ResMan.buckets[b]; r; r = r->next) {
|
|
if(r->type == RESMAN_TEXTURE) {
|
|
refresh_texture(r);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int texloader(void *ud, struct ResManRes *res) {
|
|
refresh_texture(res);
|
|
return 1;
|
|
}
|
|
|
|
static int fontloader(void *ud, struct ResManRes *res) {
|
|
FILE *fntf = fopen(res->name, "rb");
|
|
fseek(fntf, 0, SEEK_END);
|
|
size_t fntfsz = ftell(fntf);
|
|
fseek(fntf, 0, SEEK_SET);
|
|
char *fntbuf = malloc(fntfsz);
|
|
fread(fntbuf, 1, fntfsz, fntf);
|
|
|
|
struct k3Font *fnt = k3FontCreate();
|
|
struct k3Tex *fnttexldr(struct k3Font *fnt, const char *name) {
|
|
return resman_ref(RESMAN_TEXTURE, name);
|
|
}
|
|
k3FontLoad(fnt, fntbuf, fntfsz, fnttexldr);
|
|
|
|
res->thing = fnt;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void init_res_handlers() {
|
|
ResMan.handlers[RESMAN_MATERIAL].loader = matloader;
|
|
|
|
ResMan.handlers[RESMAN_MODEL].loader = mdlloader;
|
|
|
|
ResMan.handlers[RESMAN_PHYSICS].loader = physloader;
|
|
|
|
ResMan.handlers[RESMAN_BIN].loader = binloader;
|
|
ResMan.handlers[RESMAN_BIN].unloader = binunloader;
|
|
|
|
ResMan.handlers[RESMAN_STREAM].loader = streamloader;
|
|
|
|
ResMan.handlers[RESMAN_TEXTURE].loader = texloader;
|
|
|
|
ResMan.handlers[RESMAN_FONT].loader = fontloader;
|
|
}
|