static void init_qf (void) { Sys_Init (); Cvar_Get ("pr_debug", va ("%d", verbosity), 0, 0, ""); Cvar_Get ("pr_source_path", source_path, 0, 0, ""); PR_Init_Cvars (); PR_Init (); pr.edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.file_error = file_error; pr.load_file = load_file; pr.allocate_progs_mem = allocate_progs_mem; pr.free_progs_mem = free_progs_mem; func_tab = Hash_NewTable (1021, 0, 0, 0); Hash_SetHashCompare (func_tab, func_hash, func_compare); }
wad_t * wad_new (const char *name) { wad_t *wad = calloc (sizeof (*wad), 1); if (!wad) return 0; wad->filename = strdup (name); if (!wad->filename) { free (wad); return 0; } wad->lump_hash = Hash_NewTable (1021, 0, 0, 0); if (!wad->lump_hash) { free (wad->filename); free (wad); return 0; } Hash_SetHashCompare (wad->lump_hash, wad_get_hash, wad_compare); return wad; }
void opcode_init (void) { opcode_t *op, *mop; if (opcode_type_table) { Hash_FlushTable (opcode_void_table); Hash_FlushTable (opcode_type_table); } else { PR_Opcode_Init (); opcode_type_table = Hash_NewTable (1021, 0, opcode_free, 0); Hash_SetHashCompare (opcode_type_table, get_hash, compare); opcode_void_table = Hash_NewTable (1021, get_key, 0, 0); } for (op = pr_opcodes; op->name; op++) { if (op->min_version > options.code.progsversion) continue; mop = malloc (sizeof (opcode_t)); *mop = *op; if (options.code.progsversion == PROG_ID_VERSION) { // v6 progs have no concept of integer, but the QF engine // treats the operands of certain operands as integers // irrespective the progs version, so convert the engine's // view of the operands to the prog's view. if (mop->type_a == ev_integer) mop->type_a = ev_float; if (mop->type_b == ev_integer) mop->type_b = ev_float; if (mop->type_c == ev_integer) mop->type_c = ev_float; } Hash_AddElement (opcode_type_table, mop); if (mop->type_a == ev_void || mop->type_b == ev_void || mop->type_c == ev_void) Hash_Add (opcode_void_table, mop); } }
iqmblend_t * Mod_IQMBuildBlendPalette (iqm_t *iqm, int *size) { int i, j; iqmvertexarray *bindices = 0; iqmvertexarray *bweights = 0; iqmblend_t *blend_list; int num_blends; hashtab_t *blend_hash; for (i = 0; i < iqm->num_arrays; i++) { if (iqm->vertexarrays[i].type == IQM_BLENDINDEXES) bindices = &iqm->vertexarrays[i]; if (iqm->vertexarrays[i].type == IQM_BLENDWEIGHTS) bweights = &iqm->vertexarrays[i]; } if (!bindices || !bweights) { // Not necessarily an error: might be a static model with no bones // Either way, no need to make a blend palette Sys_MaskPrintf (SYS_MODEL, "bone index or weight array missing\n"); *size = 0; return 0; } blend_list = calloc (MAX_BLENDS, sizeof (iqmblend_t)); for (i = 0; i < iqm->num_joints; i++) { blend_list[i].indices[0] = i; blend_list[i].weights[0] = 255; } num_blends = iqm->num_joints; blend_hash = Hash_NewTable (1023, 0, 0, 0); Hash_SetHashCompare (blend_hash, blend_get_hash, blend_compare); for (i = 0; i < iqm->num_verts; i++) { byte *vert = iqm->vertices + i * iqm->stride; byte *bi = vert + bindices->offset; byte *bw = vert + bweights->offset; iqmblend_t blend; iqmblend_t *bl; // First, canonicalize vextex bone data: // bone indices are in increasing order // bone weight of zero is never followed by a non-zero weight // bone weight of zero has bone index of zero // if the weight is zero, ensure the index is also zero // also, ensure non-zero weights never follow zero weights for (j = 0; j < 4; j++) { if (!bw[j]) { bi[j] = 0; } else { if (j && !bw[j-1]) { swap_bones (bi, bw, j - 1, j); j = 0; // force a rescan } } } // sort the bones such that the indeces are increasing (unless the // weight is zero) for (j = 0; j < 3; j++) { if (!bw[j+1]) // zero weight == end of list break; if (bi[j] > bi[j+1]) { swap_bones (bi, bw, j, j + 1); j = -1; // force rescan } } // Now that the bone data is canonical, it can be hashed. // However, no need to check other combinations if the vertex has // only one influencing bone: the bone index will only change format. if (!bw[1]) { *(uint32_t *) bi = bi[0]; continue; } QuatCopy (bi, blend.indices); QuatCopy (bw, blend.weights); if ((bl = Hash_FindElement (blend_hash, &blend))) { *(uint32_t *) bi = (bl - blend_list); continue; } if (num_blends >= MAX_BLENDS) Sys_Error ("Too many blends. Tell taniwha to stop being lazy."); blend_list[num_blends] = blend; Hash_AddElement (blend_hash, &blend_list[num_blends]); *(uint32_t *) bi = num_blends; num_blends++; } Hash_DelTable (blend_hash); *size = num_blends; return realloc (blend_list, num_blends * sizeof (iqmblend_t)); }