main
Dominik Madarász 2023-12-04 09:07:11 +01:00
parent bc1ff71f74
commit 67f60ac798
11 changed files with 254 additions and 120 deletions

View File

@ -20146,6 +20146,27 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model)
for(int i = 0; i < (int)hdr->num_meshes; i++) { for(int i = 0; i < (int)hdr->num_meshes; i++) {
struct iqmmesh *m = &meshes[i]; struct iqmmesh *m = &meshes[i];
// reuse texture+material if already decoded
bool reused = 0;
for( int j = 0; !reused && j < model->num_textures; ++j ) {
if( !strcmpi(model->texture_names[j], &str[m->material])) {
*out++ = model->materials[j].layer[0].texture;
{
model->num_textures++;
array_push(model->texture_names, STRDUP(&str[m->material]));
array_push(model->materials, model->materials[j]);
array_back(model->materials)->name = STRDUP(&str[m->material]);
}
reused = true;
}
}
if( reused ) continue;
// decode texture+material
int flags = TEXTURE_MIPMAPS|TEXTURE_REPEAT; // LINEAR, NEAREST int flags = TEXTURE_MIPMAPS|TEXTURE_REPEAT; // LINEAR, NEAREST
int invalid = texture_checker().id; int invalid = texture_checker().id;
@ -20157,7 +20178,7 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model)
array(char) embedded_texture = base64_decode(material_embedded_texture, strlen(material_embedded_texture)); array(char) embedded_texture = base64_decode(material_embedded_texture, strlen(material_embedded_texture));
//printf("%s %d\n", material_embedded_texture, array_count(embedded_texture)); //printf("%s %d\n", material_embedded_texture, array_count(embedded_texture));
//hexdump(embedded_texture, array_count(embedded_texture)); //hexdump(embedded_texture, array_count(embedded_texture));
*out = texture_compressed_from_mem( embedded_texture, array_count(embedded_texture), 0 ).id; *out = texture_compressed_from_mem( embedded_texture, array_count(embedded_texture), flags ).id;
array_free(embedded_texture); array_free(embedded_texture);
} }
@ -20210,6 +20231,7 @@ bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model)
*out = texture_checker().id; // placeholder *out = texture_checker().id; // placeholder
} }
inscribe_tex:;
{ {
model->num_textures++; model->num_textures++;
array_push(model->texture_names, STRDUP(&str[m->material])); array_push(model->texture_names, STRDUP(&str[m->material]));
@ -20277,7 +20299,7 @@ model_t model_from_mem(const void *mem, int len, int flags) {
// if( shaderprog < 0 ) { // if( shaderprog < 0 ) {
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs, int shaderprog = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_texcoord2,att_bitangent","fragColor", "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
va("SHADING_PHONG,%s", (flags&MODEL_RIMLIGHT)?"RIM":"")); va("SHADING_PHONG,%s", (flags&MODEL_RIMLIGHT)?"RIM":""));
// } // }
// ASSERT(shaderprog > 0); // ASSERT(shaderprog > 0);
@ -20686,7 +20708,7 @@ lightmap_t lightmap(int hmsize, float cnear, float cfar, vec3 color, int passes,
const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM const char *symbols[] = { "{{include-shadowmap}}", vfs_read("shaders/fs_0_0_shadowmap_lit.glsl") }; // #define RIM
lm.shader = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs, lm.shader = shader(strlerp(1,symbols,vfs_read("shaders/vs_323444143_16_3322_model.glsl")), strlerp(1,symbols,vfs_read("shaders/fs_32_4_model.glsl")), //fs,
"att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_texcoord2,att_bitangent","fragColor", "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent,att_texcoord2","fragColor",
va("%s", "LIGHTMAP_BAKING")); va("%s", "LIGHTMAP_BAKING"));
return lm; return lm;
@ -20720,6 +20742,10 @@ void lightmap_bake(lightmap_t *lm, int bounces, void (*drawscene)(lightmap_t *lm
texture_destroy(&m->lightmap); texture_destroy(&m->lightmap);
} }
m->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR|TEXTURE_FLOAT); m->lightmap = texture_create(w, h, 4, 0, TEXTURE_LINEAR|TEXTURE_FLOAT);
glBindTexture(GL_TEXTURE_2D, m->lightmap.id);
unsigned char emissive[] = { 0, 0, 0, 255 };
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
glBindTexture(GL_TEXTURE_2D, 0);
} }
for (int b = 0; b < bounces; b++) { for (int b = 0; b < bounces; b++) {
@ -28758,42 +28784,6 @@ vec3 editor_pick(float mouse_x, float mouse_y) {
#endif #endif
} }
#if 0
int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate
int clicked = 0;
uint8_t copy = *enabled;
// @fixme: better way to retrieve widget width? nk_layout_row_dynamic() seems excessive
nk_layout_row_dynamic(ui_ctx, 1, 1);
struct nk_rect bounds = nk_widget_bounds(ui_ctx);
// actual widget: label + 8 checkboxes
enum { HEIGHT = 18, BITS = 8, SPAN = 118 }; // bits widget below needs at least 118px wide
nk_layout_row_begin(ui_ctx, NK_STATIC, HEIGHT, 1+BITS);
int offset = bounds.w > SPAN ? bounds.w - SPAN : 0;
nk_layout_row_push(ui_ctx, offset);
if( ui_label_(label, NK_TEXT_LEFT) ) clicked = 1<<31;
for( int i = 0; i < BITS; ++i ) {
nk_layout_row_push(ui_ctx, 10);
// bit
int val = (*enabled >> i) & 1;
int chg = nk_checkbox_label(ui_ctx, "", &val);
*enabled = (*enabled & ~(1 << i)) | ((!!val) << i);
// tooltip
struct nk_rect bb = { offset + 10 + i * 14, bounds.y, 14, HEIGHT }; // 10:padding,14:width
if (nk_input_is_mouse_hovering_rect(&ui_ctx->input, bb) && !ui_popups()) {
const char *tips[BITS] = {"Init","Tick","Draw","Quit","","","",""};
if(tips[i][0]) nk_tooltipf(ui_ctx, "%s", tips[i]);
}
}
nk_layout_row_end(ui_ctx);
return clicked | (copy ^ *enabled);
}
#endif
typedef union engine_var { typedef union engine_var {
int i; int i;

View File

@ -14,8 +14,11 @@ cp bin/libassimp.dylib ../libassimp.5.dylib
cp bin/libassimp.dylib ../libassimp.5.0.1.dylib cp bin/libassimp.dylib ../libassimp.5.0.1.dylib
cd .. cd ..
cc ass2iqe.c -o ass2iqe.linux -O2 -I assimp/include/ libassimp.so -lm cc ass2iqe.c -o ass2iqe.linux -O2 -I. -I ../engine/split -I assimp/include/ libassimp.so -lm
cc ass2iqe.c -o ass2iqe.osx -O2 -I assimp/include/ libassimp.dylib -lm cc ass2iqe.c -o ass2iqe.osx -O2 -I. -I ../engine/split -I assimp/include/ libassimp.dylib -lm
cc iqe2iqm.c -o iqe2iqm.linux -O2 -I. -I ../engine/split -lm
cc iqe2iqm.c -o iqe2iqm.osx -O2 -I. -I ../engine/split -lm
exit exit
@ -24,12 +27,19 @@ exit
@echo off @echo off
cd "%~dp0" cd "%~dp0"
if not exist assimp-vc14?-mt.lib (
if not exist "fart.exe" echo fart tool required && exit /b
git clone https://github.com/assimp/assimp && md assimp\.build && pushd assimp\.build && git checkout 05115b07 git clone https://github.com/assimp/assimp && md assimp\.build && pushd assimp\.build && git checkout 05115b07
cmake .. -DCMAKE_BUILD_TYPE=Release && (make || msbuild assimp.sln -m -p:Configuration=Release) cmake .. -DCMAKE_BUILD_TYPE=Release && (make || msbuild assimp.sln -m -p:Configuration=Release)
popd popd
xcopy /y assimp\.build\bin\release\*.dll xcopy /y assimp\.build\bin\release\*.dll
xcopy /y assimp\.build\lib\release\*.lib xcopy /y assimp\.build\lib\release\*.lib
copy /y assimp\include\assimp\config.h.in assimp\config.h && fart -- assimp\config.h "cmakedefine" "//#define" 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-vc14?-mt.lib /O2 /Oy /MT /DNDEBUG )
cl ass2iqe.c -I. -I ..\engine\split -I assimp\include assimp-vc14?-mt.lib /O2 /Oy /MT /DNDEBUG
cl iqe2iqm.cpp /O2 /Oy /MT /DNDEBUG

View File

@ -17,8 +17,20 @@ exit
@echo off @echo off
cd "%~dp0" cd "%~dp0"
git clone https://github.com/septag/glslcc && md glslcc\.build && pushd glslcc\.build if not exist glslcc (
cmake .. -B . -DCMAKE_BUILD_TYPE=Release && (make || msbuild glslcc.sln -m -p:Configuration=Release) git clone https://github.com/septag/glslcc
popd )
xcopy /y glslcc\.build\src\Release\glslcc.exe if "%1"=="debug" (
if not exist glslcc\.debug md glslcc\.debug
pushd glslcc\.debug
cmake .. -B . && (make || msbuild glslcc.sln)
popd
xcopy /y glslcc\.debug\src\Debug\glslcc.exe
) else (
if not exist glslcc\.build md glslcc\.build
pushd glslcc\.build
cmake .. -B . -DCMAKE_BUILD_TYPE=Release && (make || msbuild glslcc.sln -m -p:Configuration=Release)
popd
xcopy /y glslcc\.build\src\Release\glslcc.exe
)

View File

@ -231,7 +231,8 @@ int main(int argc, char* argv[]) {
return error ? fprintf(stderr, "%s\n", error), -1 : 0; return error ? fprintf(stderr, "%s\n", error), -1 : 0;
} }
// cl ase2ini.c -I ..\engine\split /DNDEBUG /O2 /Ox /MT
// cl ase2ini.c -I ..\engine\split /DNDEBUG /O2 /Ox /MT /LD
// tcc ase2ini.c -I ..\engine\split -DNDEBUG // tcc ase2ini.c -I ..\engine\split -DNDEBUG
// cl ase2ini.c -I ..\engine\split /DNDEBUG /O2 /Ox /MT /LD
// cl ase2ini.c -I ..\engine\split /DNDEBUG /O2 /Ox /MT
// cc ase2ini.c -I ../engine/split -lm -O3 -oase2ini.linux // cc ase2ini.c -I ../engine/split -lm -O3 -oase2ini.linux
// cc ase2ini.c -I ../engine/split -lm -O3 -oase2ini.osx

Binary file not shown.

View File

@ -16,8 +16,12 @@
#define FREE free #define FREE free
#define MALLOC malloc #define MALLOC malloc
#include "3rd_base64.h" #include "3rd_base64.h"
#define STB_IMAGE_IMPLEMENTATION //
#include "3rd_stb_image.h" #ifdef _MSC_VER
#define strcmpi _stricmp
#else
#define strcmpi strcasecmp
#endif
int verbose = 0; int verbose = 0;
int need_to_bake_skin = 0; int need_to_bake_skin = 0;
@ -37,6 +41,9 @@ int doaxis = 0; // flip bone axis from X to Y to match blender
int dounscale = 0; // remove scaling from bind pose int dounscale = 0; // remove scaling from bind pose
int dohips = 0; // reparent thighs to pelvis (see zo_hom_marche) int dohips = 0; // reparent thighs to pelvis (see zo_hom_marche)
char *output = NULL; // output filename
char *input = NULL; // input filename
char *only_one_node = NULL; char *only_one_node = NULL;
int list_all_meshes = 0; int list_all_meshes = 0;
int list_all_positions = 0; int list_all_positions = 0;
@ -1085,57 +1092,48 @@ void export_node(FILE *out, const struct aiScene *scene, const struct aiNode *no
// look for embedded textures. referenced like *1, *2, *3... where N is texture ID // look for embedded textures. referenced like *1, *2, *3... where N is texture ID
// note: mHeight can be zero, in this case texture->pcData is not RGB values but // note: mHeight can be zero, in this case texture->pcData is not RGB values but
// compressed JPEG/PNG/etc. data. Using stb_image to decode such image in that case. // compressed JPEG/PNG/etc. data. Could use stb_image to decode such image in that case.
if( !strchr(buffer, '*') ) { unsigned tex_id = ~0u;
for( int j = 0; j < scene->mNumTextures; ++j ) {
struct aiTexture *tex = scene->mTextures[j]; if( buffer[0] ) {
if( strstr(tex->mFilename.data, buffer + !isalpha(buffer[0])) ) { if( strchr(buffer, '*') ) {
snprintf(buffer, sizeof(buffer-1), "*%d", j); tex_id = atoi(buffer+1);
break; } else {
const char *fname = buffer + (buffer[0] == '+');
for( int j = 0; j < scene->mNumTextures; ++j ) {
struct aiTexture *tex = scene->mTextures[j];
const char *basename = tex->mFilename.data;
if( strrchr(basename, '/') ) basename = strrchr(basename, '/')+1;
if( strrchr(basename,'\\') ) basename = strrchr(basename,'\\')+1;
if( !strcmpi(basename, fname) ) {
tex_id = j;
break;
}
} }
} }
} }
if( strchr(buffer, '*') ) { if( tex_id < scene->mNumTextures ) {
int tex_id = atoi(buffer+1); struct aiTexture *tex = scene->mTextures[tex_id];
if( tex_id < scene->mNumTextures ) { const char *hint = tex->achFormatHint; // "rgba8888" or "png", "bmp", etc.
struct aiTexture *tex = scene->mTextures[tex_id];
struct aiTexel *data = tex->pcData;
const char *hint = tex->achFormatHint; // "rgba8888" or "png"
unsigned w = tex->mWidth + !tex->mWidth;
unsigned h = tex->mHeight + !tex->mHeight;
// stbi_uc *decoded = 0; if( !tex->mHeight )
if( !tex->mHeight ) {
{ embedded = base64_encode(tex->pcData, (int)tex->mWidth ); // @leak
int len = (int)w; }
embedded = base64_encode(data, len); // leak else
// int x = 0, y = 0, n = 0; {
// decoded = stbi_load_from_memory((const stbi_uc *)data, len, &x, &y, &n, 4); embedded = base64_encode(tex->pcData, (int)(tex->mWidth * tex->mHeight * sizeof(struct aiTexel))); // @leak
// w = x; h = y; data = (struct aiTexel *)decoded;
}
#if 1
if(!embedded)
embedded = base64_encode(data, w * h * sizeof(struct aiTexel)); // leak
#else
fprintf(stderr, "%dx%d (%s)\n", w,h,hint);
char name[260]; sprintf(name, "tex_%d.%s", tex_id, hint);
FILE *out = fopen(name, "wb");
for(unsigned y = 0; y < h; ++y)
for(unsigned x = 0; x < w; ++x)
fwrite(&data[x+y*w].b, 1, 4, out);
fclose(out);
#endif
// if( decoded ) stbi_image_free(decoded);
} }
} }
#endif #endif
aiGetMaterialString(material, AI_MATKEY_NAME, &str); aiGetMaterialString(material, AI_MATKEY_NAME, &str);
fprintf(out, "material \"%s%s%s%s%s\"\n", str.data, buffer, colorbuffer, embedded ? "+b64:":"", embedded ? embedded:""); fprintf(out, "material \"%s%s%s%s%s\"\n", buffer[0] == '*' ? "" : str.data, buffer, colorbuffer, embedded ? "+b64:":"", embedded ? embedded:"");
} }
struct vb *vb = (struct vb*) malloc(mesh->mNumVertices * sizeof(*vb)); struct vb *vb = (struct vb*) malloc(mesh->mNumVertices * sizeof(*vb));
@ -1348,8 +1346,6 @@ int main(int argc, char **argv)
char *p; char *p;
int c; int c;
char *output = NULL;
char *input = NULL;
int onlyanim = 0; int onlyanim = 0;
int onlymesh = 0; int onlymesh = 0;

Binary file not shown.

View File

@ -30,9 +30,9 @@ int main(int argc, const char **argv) {
/* /*
compiled with: compiled with:
cc -ObjC cook.c -I../engine -o cook.osx -framework Cocoa -framework IOKit -framework audiotoolbox -O3 cc -ObjC cook.c -I../engine -o cook.osx -framework Cocoa -framework IOKit -framework audiotoolbox -framework coreaudio -O3
cc cook.c -I../engine -o cook.linux -lm -lpthread -ldl -lX11 -O3 cc cook.c -I../engine -o cook.linux -lm -lpthread -ldl -lX11 -O3
tcc cook.c -I..\engine tcc cook.c -I..\engine
cl cook.c -I..\engine /openmp /Os /Ox /O2 /Oy /MT /DNDEBUG /GL /GF /Gw /arch:AVX2 /link /OPT:ICF /LTCG cl cook.c -I..\engine /openmp /Os /Ox /O2 /Oy /MT /DNDEBUG /GL /GF /Gw /arch:AVX2 /link /OPT:ICF /LTCG
del cook.o & del cook.obj & del cook.lib & del cook.exp del *.o & del *.obj & del *.lib & del *.exp & del *.pdb
*/ */

Binary file not shown.

View File

@ -17,6 +17,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
// - So, I increased the vector growsize & removed all deallocations to "fix" random crashes // - So, I increased the vector growsize & removed all deallocations to "fix" random crashes
// - Not quite sure still, so I also removed custom allocators // - Not quite sure still, so I also removed custom allocators
// - Also, switched string hashing to fnv1a, hoping to distribute hashmap buckets more uniformly // - Also, switched string hashing to fnv1a, hoping to distribute hashmap buckets more uniformly
// - Note: crashes behaves worse on x64. x86 seems to be more predictable.
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
@ -29,11 +30,108 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#include <vector> #include <vector>
#include <stdint.h> #include <stdint.h>
#define _CRT_SECURE_NO_WARNINGS 1 #define _CRT_SECURE_NO_WARNINGS 1
//#define ASSERT assert #define ASSERT(x) do{ if(!(x)) exit(-fprintf(stderr, "assertion failed: `" #x "` %s:%d\n%s\n", __FILE__, __LINE__, callstack(+16))); } while(0) // assert(x)
#define ASSERT(x) do{}while(0) //#define ASSERT(x) do{}while(0) // hack
#define delete_array (0),(void) // hac #define delete_array (0),(void) // hack to minimize crashes
//#define delete_array delete[] //#define delete_array delete[]
#ifdef _WIN32 // && !defined __TINYC__
#define SYS_MEM_REALLOC realloc
#define __thread __declspec(thread)
#define concat(a,b) conc4t(a,b)
#define conc4t(a,b) a##b ///-
#define macro(name) concat(name, __LINE__)
#define do_once static int macro(init) = 1; for(;macro(init);macro(init) = 0)
#include <winsock2.h> // windows.h alternative
#include <dbghelp.h>
#pragma comment(lib, "DbgHelp")
#pragma comment(lib, "Kernel32")
static int backtrace( void **addr, int maxtraces ) {
static bool init = 0;
do_once SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES);
do_once init = SymInitialize(GetCurrentProcess(), NULL, TRUE);
if(!init) return 0; // error: cannot initialize DbgHelp.lib
typedef USHORT (WINAPI *pFN)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG); // _MSC_VER
static pFN rtlCaptureStackBackTrace = 0;
if( !rtlCaptureStackBackTrace ) {
rtlCaptureStackBackTrace = (pFN)GetProcAddress(LoadLibraryA("kernel32.dll"), "RtlCaptureStackBackTrace");
}
if( !rtlCaptureStackBackTrace ) {
return 0;
}
return rtlCaptureStackBackTrace(1, maxtraces, (PVOID *)addr, (DWORD *) 0);
}
static char **backtrace_symbols(void *const *list,int size) {
HANDLE process = GetCurrentProcess();
struct symbol_t {
SYMBOL_INFO info;
TCHAR symbolname[256], terminator;
} si = { {0} };
si.info.SizeOfStruct = sizeof(SYMBOL_INFO);
si.info.MaxNameLen = sizeof(si.symbolname) / sizeof(TCHAR); // number of chars, not bytes
IMAGEHLP_LINE l64 = { 0 };
l64.SizeOfStruct = sizeof(IMAGEHLP_LINE);
static __thread char **symbols = 0; //[32][64] = {0};
if( !symbols ) {
symbols = (char**)SYS_MEM_REALLOC(0, 128 * sizeof(char*));
for( int i = 0; i < 128; ++i) symbols[i] = (char*)SYS_MEM_REALLOC(0, 128 * sizeof(char));
}
if(size > 128) size = 128;
for( int i = 0; i < size; ++i ) {
char *ptr = symbols[i];
*ptr = '\0';
if (SymFromAddr(process, (DWORD64)(uintptr_t)list[i], 0, &si.info)) {
//char undecorated[1024];
//UnDecorateSymbolName(si.info.Name, undecorated, sizeof(undecorated)-1, UNDNAME_COMPLETE);
char* undecorated = (char*)si.info.Name;
ptr += snprintf(ptr, 128, "%s", undecorated);
} else {
ptr += snprintf(ptr, 128, "%s", "(?""?)");
}
DWORD dw = 0;
if (SymGetLineFromAddr(process, (DWORD64)(uintptr_t)list[i], &dw, &l64)) {
ptr += snprintf(ptr, 128 - (ptr - symbols[i]), " (%s:%u)", l64.FileName, (unsigned)l64.LineNumber);
}
}
return symbols;
}
char *callstack( int traces ) {
static __thread char *output = 0;
if(!output ) output = (char*)SYS_MEM_REALLOC( 0, 128 * (64+2) );
if( output ) output[0] = '\0';
char *ptr = output;
enum { skip = 1 }; /* exclude 1 trace from stack (this function) */
enum { maxtraces = 128 };
int inc = 1;
if( traces < 0 ) traces = -traces, inc = -1;
if( traces == 0 ) return "";
if( traces > maxtraces ) traces = maxtraces;
void* stacks[maxtraces/* + 1*/]; // = { 0 };
traces = backtrace( stacks, traces );
char **symbols = backtrace_symbols( stacks, traces ); // @todo: optimization: map(void*,char*) cache; and retrieve only symbols not in cache
char demangled[1024] = "??";
int L = 0, B = inc>0 ? skip - 1 : traces, E = inc>0 ? traces : skip - 1;
for( int i = B; ( i += inc ) != E; ) {
ptr += sprintf(ptr, "%03d: %#016llx %s\n", ++L, (unsigned long long)(uintptr_t)stacks[i], symbols[i]); // format gymnastics because %p is not standard when printing pointers
}
return output ? output : "";
}
#endif
#ifndef __IQM_H__ #ifndef __IQM_H__
#define __IQM_H__ #define __IQM_H__
@ -308,7 +406,9 @@ template <class T> struct vector : public std::vector<T>
{ {
static const int MINSIZE = 8; static const int MINSIZE = 8;
mutable //< @r-lyeh
T *buf; T *buf;
mutable //< @r-lyeh
int alen, ulen; int alen, ulen;
vector() : buf(NULL), alen(0), ulen(0) vector() : buf(NULL), alen(0), ulen(0)
@ -327,6 +427,9 @@ template <class T> struct vector : public std::vector<T>
setsize(0); setsize(0);
if(v.length() > alen) growbuf(v.length()); if(v.length() > alen) growbuf(v.length());
loopv(v) add(v[i]); loopv(v) add(v[i]);
if(ulen==alen) growbuf(ulen+1); //< @r-lyeh
return *this; return *this;
} }
@ -361,8 +464,14 @@ template <class T> struct vector : public std::vector<T>
bool empty() const { return ulen==0; } bool empty() const { return ulen==0; }
int capacity() const { return alen; } int capacity() const { return alen; }
int length() const { return ulen; } int length() const { return ulen; }
T &operator[](int i) { ASSERT(i>=0 && i<ulen); return buf[i]; } T &operator[](int i) {
const T &operator[](int i) const { ASSERT(i >= 0 && i<ulen); return buf[i]; } if(i<ulen) reserve(i+1); //< @r-lyeh
//ASSERT(i>=0 && i<ulen);
return buf[i]; }
const T &operator[](int i) const {
if(i<ulen) reserve(i+1); //< @r-lyeh
//ASSERT(i >= 0 && i<ulen);
return buf[i]; }
void setsize(int i) { ASSERT(i <= ulen); ulen = i; } void setsize(int i) { ASSERT(i <= ulen); ulen = i; }
@ -378,6 +487,7 @@ template <class T> struct vector : public std::vector<T>
bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; } bool inbuf(const T *e) const { return e >= buf && e < &buf[ulen]; }
void growbuf(int sz) void growbuf(int sz)
const //< @r-lyeh
{ {
int olen = alen; int olen = alen;
if(!alen) alen = max(MINSIZE, sz); if(!alen) alen = max(MINSIZE, sz);
@ -393,6 +503,7 @@ template <class T> struct vector : public std::vector<T>
} }
T *reserve(int sz) T *reserve(int sz)
const //< @r-lyeh
{ {
if(ulen+sz > alen) growbuf(ulen+sz); if(ulen+sz > alen) growbuf(ulen+sz);
return &buf[ulen]; return &buf[ulen];
@ -487,7 +598,7 @@ template <class K, class T> struct hashtable
typedef T value; typedef T value;
typedef const T const_value; typedef const T const_value;
enum { CHUNKSIZE = 64, MAXLOADFACTOR = 75, RESIZEFACTOR = 4, MAXSIZE = 64<<20 }; enum { CHUNKSIZE = 64, MAXLOADFACTOR = 75, RESIZERATIO = 4, MAXSIZE = 128<<20 };
struct chain { T data; K key; chain *next; }; struct chain { T data; K key; chain *next; };
struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; }; struct chainchunk { chain chains[CHUNKSIZE]; chainchunk *next; };
@ -517,7 +628,12 @@ template <class K, class T> struct hashtable
chain *insert(const K &key, uint h) chain *insert(const K &key, uint h)
{ {
if(size <= MAXSIZE / RESIZEFACTOR && numelems * 100 > size * MAXLOADFACTOR) { rehash(); h = hthash(key)&(size-1); } if(size*RESIZERATIO < MAXSIZE && float(++numelems) / size * 100.0 > MAXLOADFACTOR) { rehash(); h = hthash(key)&(size-1); }
return insert(unused, chunks, table, key, h);
}
static chain *insert(chain *&unused, chainchunk *&chunks, chain **&table, const K& key, uint h)
{
if(!unused) if(!unused)
{ {
chainchunk *chunk = new chainchunk; chainchunk *chunk = new chainchunk;
@ -532,7 +648,6 @@ template <class K, class T> struct hashtable
c->key = key; c->key = key;
c->next = table[h]; c->next = table[h];
table[h] = c; table[h] = c;
numelems++;
return c; return c;
} }
@ -612,23 +727,27 @@ template <class K, class T> struct hashtable
void rehash() void rehash()
{ {
int oldsize = size; int newsize = size*RESIZERATIO;
chain **oldtable = table; chain **newtable = new chain* [newsize];
loopi(newsize) newtable[i] = NULL;
size *= RESIZEFACTOR; chainchunk *newchunks = NULL;
table = new chain*[size]; chain *newunused = NULL;
loopi(size) table[i] = NULL; loopi(size) for (chain *c = table[i]; c;)
loopi(oldsize) for (chain *c = oldtable[i]; c;)
{ {
chain *p = c; const K& k = c->key;
uint h = hthash(k)&(newsize-1);
insert(newunused, newchunks, newtable, k, h)->data = c->data;
c = c->next; c = c->next;
uint h = hthash(p->key)&(size-1);
p->next = table[h];
table[h] = p;
} }
delete_array oldtable; delete[] table;
deletechunks();
size = newsize;
table = newtable;
chunks = newchunks;
unused = newunused;
} }
}; };
@ -2552,13 +2671,16 @@ struct filespec
bool parseiqe(stream *f) bool parseiqe(stream *f)
{ {
enum { sizeof_tex = (8*1024) * (8*1024) * (4) }; // max cap: 8K texture, RGBA8888,
const unsigned sizeof_buf = ceil(sizeof_tex / 3) * 4; // then, max capacity encoded as base64
static char *buf = new char [sizeof_buf];
const char *curmesh = getnamekey(""), *curmaterial = getnamekey(""); const char *curmesh = getnamekey(""), *curmaterial = getnamekey("");
bool needmesh = true; bool needmesh = true;
int fmoffset = 0; int fmoffset = 0;
char buf[512]; if(!f->getline(buf, sizeof_buf)) return false;
if(!f->getline(buf, sizeof(buf))) return false;
if(!strchr(buf, '#') || strstr(buf, "# Inter-Quake Export") != strchr(buf, '#')) return false; if(!strchr(buf, '#') || strstr(buf, "# Inter-Quake Export") != strchr(buf, '#')) return false;
while(f->getline(buf, sizeof(buf))) while(f->getline(buf, sizeof_buf))
{ {
char *c = buf; char *c = buf;
while(isspace(*c)) ++c; while(isspace(*c)) ++c;
@ -3339,3 +3461,6 @@ int main(int argc, char **argv)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
// cl iqe2iqm.cpp /DDEBUG /MT /Zi /fsanitize=address
// cl iqe2iqm.cpp /O2 /Oy /MT /DNDEBUG

Binary file not shown.