/* * R_FreeCinematic */ void R_FreeCinematic( unsigned int id ) { r_cinhandle_t *handle; handle = R_GetCinematicHandleById( id ); if( !handle ) { return; } ri.CIN_Close( handle->cin ); handle->cin = NULL; assert( handle->name ); R_Free( handle->name ); handle->name = NULL; assert( handle->uploadName ); R_Free( handle->uploadName ); handle->uploadName = NULL; // remove from linked active list handle->prev->next = handle->next; handle->next->prev = handle->prev; // insert into linked free list handle->next = r_free_cinematics; r_free_cinematics = handle; }
/* * SkinFile_FreeSkinFile */ static void SkinFile_FreeSkinFile( skinfile_t *skinfile ) { int i; if( skinfile->numpairs ) { for( i = 0; i < skinfile->numpairs; i++ ) R_Free( skinfile->pairs[i].meshname ); R_Free( skinfile->pairs ); } R_Free( skinfile->name ); memset( skinfile, 0, sizeof( skinfile_t ) ); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ permuto will return a vector of all permutations needed for bruvo's distance. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ SEXP permuto(SEXP perm) { int permutations; int i; int per; SEXP Rval; /* IMPORTANT: INITIALIZE THE COUNTER. THE POINTER IS NOT RELEASED FROM MEMORY OTHERWISE. */ perm_count = 0; perm = coerceVector(perm, INTSXP); per = INTEGER(perm)[0]; int *allele_array; allele_array = R_Calloc(per, int); permutations = fact(per)*per; for(i = 0; i < per; i++) { allele_array[i] = i; } PROTECT(Rval = allocVector(INTSXP, permutations)); permute(allele_array, 0, per-1, INTEGER(Rval)); UNPROTECT(1); R_Free(allele_array); return Rval; }
SEXP dotask(SEXP Sclient, SEXP Sfun, SEXP Swork, SEXP Suval, SEXP Sback, SEXP Shigh){ rgearman_client_t *client = (rgearman_client_t *)R_ExternalPtrAddr(Sclient); SEXP ret; const char *fun, *work, *uval; int back, high; fun = (Sfun != R_NilValue)? (const char *)CHAR(STRING_ELT(Sfun,0)) : NULL; work = (Swork != R_NilValue)? (const char *)CHAR(STRING_ELT(Swork,0)) : NULL; uval = (Suval != R_NilValue)? (const char *)CHAR(STRING_ELT(Suval,0)) : NULL; back = LOGICAL(Sback)[0]; high = (Shigh != R_NilValue) ? LOGICAL(Shigh)[0] : -1; if (back){ gearman_return_t (*gm_fun)(gearman_client_st *client, const char *function_name, const char *unique, const void *workload, size_t workload_size, gearman_job_handle_t job_handle); char *job = (char *)R_Calloc(1,gearman_job_handle_t); gm_fun = (high == -1)? gearman_client_do_background : (high)? gearman_client_do_high_background : gearman_client_do_low_background ; client->lastretcode = gm_fun(client->client,fun,uval,work,strlen(work),job); ret = PROTECT(allocVector(STRSXP,1)); SET_STRING_ELT(ret,0,mkChar(job)); R_Free(job); UNPROTECT(1); } else { void *(*gm_fun)(gearman_client_st *client, const char *function_name, const char *unique, const void *workload, size_t workload_size, size_t *result_size, gearman_return_t *ret_ptr); size_t resultsize; void *result; gm_fun = (high == -1)? gearman_client_do : (high)? gearman_client_do_high : gearman_client_do_low ; result = gm_fun(client->client,fun,uval,work,strlen(work),&resultsize,&client->lastretcode); ret = PROTECT(allocVector(STRSXP,1)); SET_STRING_ELT(ret,0,mkCharLen((char *)result,resultsize)); UNPROTECT(1); } return ret; }
qboolean RE_RegisterModels_LevelLoadEnd(qboolean bDeleteEverythingNotUsedThisLevel /* = qfalse */) { qboolean bAtLeastoneModelFreed = qfalse; if (gbInsideRegisterModel) { Com_DPrintf( "(Inside RE_RegisterModel (z_malloc recovery?), exiting...\n"); } else { int iLoadedModelBytes = GetModelDataAllocSize(); const int iMaxModelBytes= r_modelpoolmegs->integer * 1024 * 1024; for (CachedModels_t::iterator itModel = CachedModels->begin(); itModel != CachedModels->end() && ( bDeleteEverythingNotUsedThisLevel || iLoadedModelBytes > iMaxModelBytes ); ) { CachedEndianedModelBinary_t &CachedModel = (*itModel).second; qboolean bDeleteThis = qfalse; if (bDeleteEverythingNotUsedThisLevel) { bDeleteThis = (qboolean)(CachedModel.iLastLevelUsedOn != RE_RegisterMedia_GetLevel()); } else { bDeleteThis = (qboolean)(CachedModel.iLastLevelUsedOn < RE_RegisterMedia_GetLevel()); } // if it wasn't used on this level, dump it... // if (bDeleteThis) { #ifdef _DEBUG // LPCSTR psModelName = (*itModel).first.c_str(); // ri.Printf( PRINT_DEVELOPER, "Dumping \"%s\"", psModelName); // ri.Printf( PRINT_DEVELOPER, ", used on lvl %d\n",CachedModel.iLastLevelUsedOn); #endif if (CachedModel.pModelDiskImage) { R_Free(CachedModel.pModelDiskImage); //CachedModel.pModelDiskImage = NULL; // REM for reference, erase() call below negates the need for it. bAtLeastoneModelFreed = qtrue; } CachedModels->erase(itModel++); iLoadedModelBytes = GetModelDataAllocSize(); } else { ++itModel; } } } //ri.Printf( PRINT_DEVELOPER, "RE_RegisterModels_LevelLoadEnd(): Ok\n"); return bAtLeastoneModelFreed; }
// only called from devmapbsp, devmapall, or ... // void RE_AnimationCFGs_DeleteAll(void) { for (AnimationCFGs_t::iterator it = AnimationCFGs.begin(); it != AnimationCFGs.end(); ++it) { char *psText = (*it).second; R_Free(psText); } AnimationCFGs.clear(); }
/* * R_VBOElemBuffer */ static elem_t *R_VBOElemBuffer( unsigned numElems ) { if( numElems > r_vbo_numtempelems ) { if( r_vbo_numtempelems ) R_Free( r_vbo_tempelems ); r_vbo_numtempelems = numElems; r_vbo_tempelems = ( elem_t * )R_Malloc( sizeof( *r_vbo_tempelems ) * numElems ); } return r_vbo_tempelems; }
/* * R_VBOVertBuffer */ static void *R_VBOVertBuffer( unsigned numVerts, size_t vertSize ) { size_t size = numVerts * vertSize; if( size > r_vbo_tempvsoupsize ) { if( r_vbo_tempvsoup ) R_Free( r_vbo_tempvsoup ); r_vbo_tempvsoupsize = size; r_vbo_tempvsoup = ( float * )R_Malloc( size ); } return r_vbo_tempvsoup; }
SEXP finalizeclient(SEXP Sclient){ rgearman_client_t *client = (rgearman_client_t *)R_ExternalPtrAddr(Sclient); if (client){ gearman_client_free(client->client); R_Free(client); } else warning("GearmanClient::finalize called with NULL client"); return R_NilValue; }
/* * R_ShutdownCinematics */ void R_ShutdownCinematics( void ) { r_cinhandle_t *handle, *hnode, *next; hnode = &r_cinematics_headnode; for( handle = hnode->prev; handle != hnode; handle = next ) { next = handle->prev; R_FreeCinematic( handle->id ); } R_Free( r_cinematics ); }
// Compute Euclidean (L2)/Manhattan (L1) distance map of matrix _a // Input: numeric matrix _a, of size width*height, where 0 is background and everything else is foreground. _a shouldn't contain any NAs // Input: integer _metric. If 0, will compute Euclidean distance and Manhattan distance otherwise // Output: distance matrix of same size as _a SEXP distmap(SEXP _a, SEXP _metric) { SEXP res; int i,nprotect=0,nz; // check validity validImage(_a,0); // initialize width, height, dim width=INTEGER(GET_DIM(_a))[0]; height=INTEGER(GET_DIM(_a))[1]; nz=getNumberOfFrames(_a,0); // initialize vj, where (i,vj[i]) are the coordinates of the closest background pixel to a(i,j) with vj[i]>=j vj=(int *)R_Calloc(height,int); // initialize d, the output distance matrix PROTECT(res = allocVector(REALSXP, XLENGTH(_a)) ); nprotect++; DUPLICATE_ATTRIB(res, _a); d=REAL(res); for (i=0;i<height*width*nz;i++) d[i]=R_PosInf; // initialize dist, the distance type metric=INTEGER(_metric)[0]; // do the job int sizexy = height*width; int offset = 0; for (i=0; i<nz; i++, offset+=sizexy) { d = &(REAL(res)[offset]); switch (TYPEOF(_a)) { case LGLSXP: case INTSXP: _distmap<int>( &(INTEGER(_a)[offset]) ); break; case REALSXP: _distmap<double>( &(REAL(_a)[offset]) ); break; } } // final square root for Euclidean distance d=REAL(res); if (metric==0) for (i=0;i<height*width*nz;i++) d[i]=sqrt(d[i]); R_Free(vj); UNPROTECT (nprotect); return res; }
void RE_SaveJPG(const char * filename, int quality, int image_width, int image_height, byte *image_buffer, int padding) { byte *out; size_t bufSize; bufSize = image_width * image_height * 3; out = (byte *) R_Malloc( bufSize, TAG_TEMP_WORKSPACE, qfalse ); bufSize = RE_SaveJPGToBuffer(out, bufSize, quality, image_width, image_height, image_buffer, padding, false); ri.FS_WriteFile(filename, out, bufSize); R_Free(out); }
/* * R_FreeCinematic */ void R_FreeCinematic( unsigned int id ) { qmutex_t *lock; r_cinhandle_t *handle; handle = R_GetCinematicHandleById( id ); if( !handle ) { return; } lock = handle->lock; ri.Mutex_Lock( lock ); ri.CIN_Close( handle->cin ); handle->cin = NULL; handle->lock = NULL; assert( handle->name ); R_Free( handle->name ); handle->name = NULL; assert( handle->uploadName ); R_Free( handle->uploadName ); handle->uploadName = NULL; // remove from linked active list handle->prev->next = handle->next; handle->next->prev = handle->prev; // insert into linked free list handle->next = r_free_cinematics; r_free_cinematics = handle; ri.Mutex_Unlock( lock ); ri.Mutex_Destroy( &lock ); }
/* ================ R_MipMap2 Uses temp mem, but then copies back to input, quartering the size of the texture Proper linear filter ================ */ static void R_MipMap2( unsigned *in, int inWidth, int inHeight ) { int i, j, k; byte *outpix; int inWidthMask, inHeightMask; int total; int outWidth, outHeight; unsigned *temp; outWidth = inWidth >> 1; outHeight = inHeight >> 1; temp = (unsigned int *) R_Malloc( outWidth * outHeight * 4, TAG_TEMP_WORKSPACE, qfalse ); inWidthMask = inWidth - 1; inHeightMask = inHeight - 1; for ( i = 0 ; i < outHeight ; i++ ) { for ( j = 0 ; j < outWidth ; j++ ) { outpix = (byte *) ( temp + i * outWidth + j ); for ( k = 0 ; k < 4 ; k++ ) { total = 1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + 1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + 4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + 4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + 4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + 4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] + 1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] + 2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] + 1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k]; outpix[k] = total / 36; } } } memcpy( in, temp, outWidth * outHeight * 4 ); R_Free( temp ); }
// Compute Euclidean (L2)/Manhattan (L1) distance map of matrix _a // Input: numeric matrix _a, of size width*height, where 0 is background and everything else is foreground. _a shouldn't contain any NAs // Input: integer _metric. If 0, will compute Euclidean distance and Manhattan distance otherwise // Output: distance matrix of same size as _a SEXP distmap(SEXP _a, SEXP _metric) { SEXP res; int i,nprotect=0,nz; // check validity validImage(_a,0); // initialize width, height, dim width=INTEGER(GET_DIM(_a))[0]; height=INTEGER(GET_DIM(_a))[1]; nz=getNumberOfFrames(_a,0); // initialize vj, where (i,vj[i]) are the coordinates of the closest background pixel to a(i,j) with vj[i]>=j vj=(int *)R_Calloc(height,int); // initialize a a=REAL(_a); // initialize d, the output distance matrix PROTECT(res=Rf_duplicate(_a)); nprotect++; d=REAL(res); for (i=0;i<height*width*nz;i++) d[i]=R_PosInf; // initialize dist, the distance type metric=INTEGER(_metric)[0]; // do the job for (i=0;i<nz;i++) { distmap_onesided(1); distmap_onesided(0); a=a+height*width; d=d+height*width; } // final square root for Euclidean distance d=REAL(res); if (metric==0) for (i=0;i<height*width*nz;i++) d[i]=sqrt(d[i]); // free vj R_Free(vj); UNPROTECT (nprotect); return res; }
/* * R_ReserveDrawSurfaces */ static void R_ReserveDrawSurfaces( drawList_t *list, int minMeshes ) { int oldSize, newSize; sortedDrawSurf_t *newDs; sortedDrawSurf_t *ds = list->drawSurfs; int maxMeshes = list->maxDrawSurfs; oldSize = maxMeshes; newSize = max( minMeshes, oldSize * 2 ); newDs = R_Malloc( newSize * sizeof( sortedDrawSurf_t ) ); if( ds ) { memcpy( newDs, ds, oldSize * sizeof( sortedDrawSurf_t ) ); R_Free( ds ); } list->drawSurfs = newDs; list->maxDrawSurfs = newSize; }
static void RE_RegisterModels_DeleteAll(void) { if(!CachedModels) { return; //argh! } for (CachedModels_t::iterator itModel = CachedModels->begin(); itModel != CachedModels->end(); ) { CachedEndianedModelBinary_t &CachedModel = (*itModel).second; if (CachedModel.pModelDiskImage) { R_Free(CachedModel.pModelDiskImage); } CachedModels->erase(itModel++); } extern void RE_AnimationCFGs_DeleteAll(void); RE_AnimationCFGs_DeleteAll(); }
/* * R_ShutdownVBO */ void R_ShutdownVBO( void ) { mesh_vbo_t *vbo; vbohandle_t *vboh, *next, *hnode; if( !r_num_active_vbos ) { return; } hnode = &r_vbohandles_headnode; for( vboh = hnode->prev; vboh != hnode; vboh = next ) { next = vboh->prev; vbo = &r_mesh_vbo[vboh->index]; R_ReleaseMeshVBO( vbo ); } if( r_vbo_tempelems ) { R_Free( r_vbo_tempelems ); } r_vbo_numtempelems = 0; }
void do_free(SEXP x) { void* addr = R_ExternalPtrAddr(x); R_Free(addr); }
SEXP clahe (SEXP x, SEXP _uiNrX, SEXP _uiNrY, SEXP _uiNrBins, SEXP _fCliplimit, SEXP _keepRange) { int nx, ny, nz, i, j; unsigned int uiNrX, uiNrY, uiNrBins; float fCliplimit; int keepRange; double *src, *tgt; SEXP res; kz_pixel_t min = 0, max = uiNR_OF_GREY-1; kz_pixel_t *img; double maxPixelValue = uiNR_OF_GREY-1; PROTECT( res = allocVector(REALSXP, XLENGTH(x)) ); DUPLICATE_ATTRIB(res, x); nx = INTEGER(GET_DIM(x))[0]; ny = INTEGER(GET_DIM(x))[1]; nz = getNumberOfFrames(x, 0); uiNrX = INTEGER(_uiNrX)[0]; uiNrY = INTEGER(_uiNrY)[0]; uiNrBins = INTEGER(_uiNrBins)[0]; fCliplimit = REAL(_fCliplimit)[0]; keepRange = LOGICAL(_keepRange)[0]; img = R_Calloc(nx*ny, kz_pixel_t); // process channels separately for(j = 0; j < nz; j++) { src = &(REAL(x)[j*nx*ny]); tgt = &(REAL(res)[j*nx*ny]); if (keepRange) { min = uiNR_OF_GREY-1; max = 0; } // convert frame to CLAHE-compatible format for (i = 0; i < nx*ny; i++) { double el = src[i]; // clip if (el < 0.0) el = 0; else if (el > 1.0) el = 1.0; // convert to int kz_pixel_t nel = (kz_pixel_t) round(el * maxPixelValue); if (keepRange) { if (nel < min) min = nel; if (nel > max) max = nel; } img[i] = nel; } int val = CLAHE (img, (unsigned int) nx, (unsigned int) ny, min, max, uiNrX, uiNrY, uiNrBins, fCliplimit); // translate internal error codes switch (val) { case -1: error("# of regions x-direction too large"); break; case -2: error("# of regions y-direction too large"); break; case -3: error("x-resolution no multiple of 'nx'"); break; case -4: error("y-resolution no multiple of 'ny'"); break; case -5: error("maximum too large"); break; case -6: error("minimum equal or larger than maximum"); break; case -7: error("at least 4 contextual regions required"); break; case -8: error("not enough memory! (try reducing 'bins')"); break; } // convert back to [0:1] range for (i = 0; i < nx*ny; i++) { tgt[i] = (double) img[i] / maxPixelValue; } } R_Free(img); UNPROTECT(1); return res; }
/* * Mod_LoadSkeletalModel */ void Mod_LoadSkeletalModel( model_t *mod, const model_t *parent, void *buffer, bspFormatDesc_t *unused ) { unsigned int i, j, k; size_t filesize; qbyte *pbase; size_t memsize; qbyte *pmem; iqmheader_t *header; char *texts; iqmvertexarray_t *va; iqmjoint_t *joints; bonepose_t *baseposes; iqmpose_t *poses; unsigned short *framedata; const int *inelems; elem_t *outelems; iqmmesh_t *inmesh; iqmbounds_t *inbounds; float *vposition, *vtexcoord, *vnormal, *vtangent; qbyte *vblendindices_byte, *vblendweights_byte; int *vblendindexes_int; float *vblendweights_float; mskmodel_t *poutmodel; baseposes = NULL; header = ( iqmheader_t * )buffer; // check IQM magic if( memcmp( header->magic, "INTERQUAKEMODEL", 16 ) ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s is not an Inter-Quake Model\n", mod->name ); goto error; } // check header version header->version = LittleLong( header->version ); if( header->version != IQM_VERSION ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has wrong type number (%i should be %i)\n", mod->name, header->version, IQM_VERSION ); goto error; } // byteswap header #define H_SWAP(s) (header->s = LittleLong( header->s )) H_SWAP( filesize ); H_SWAP( flags ); H_SWAP( num_text ); H_SWAP( ofs_text ); H_SWAP( num_meshes ); H_SWAP( ofs_meshes ); H_SWAP( num_vertexarrays ); H_SWAP( num_vertexes ); H_SWAP( ofs_vertexarrays ); H_SWAP( num_triangles ); H_SWAP( ofs_triangles ); H_SWAP( ofs_adjacency ); H_SWAP( num_joints ); H_SWAP( ofs_joints ); H_SWAP( num_poses ); H_SWAP( ofs_poses ); H_SWAP( num_anims ); H_SWAP( ofs_anims ); H_SWAP( num_frames ); H_SWAP( num_framechannels ); H_SWAP( ofs_frames ); H_SWAP( ofs_bounds ); H_SWAP( num_comment ); H_SWAP( ofs_comment ); H_SWAP( num_extensions ); H_SWAP( ofs_extensions ); #undef H_SWAP if( header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1 ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has no geometry\n", mod->name ); goto error; } if( header->num_frames < 1 || header->num_anims < 1 ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has no animations\n", mod->name ); goto error; } if( header->num_joints != header->num_poses ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has an invalid number of poses: %i vs %i\n", mod->name, header->num_joints, header->num_poses ); goto error; } if( !header->ofs_bounds ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has no frame bounds\n", mod->name ); goto error; } pbase = ( qbyte * )buffer; filesize = header->filesize; // check data offsets against the filesize if( header->ofs_text + header->num_text > filesize || header->ofs_vertexarrays + header->num_vertexarrays * sizeof( iqmvertexarray_t ) > filesize || header->ofs_joints + header->num_joints * sizeof( iqmjoint_t ) > filesize || header->ofs_frames + header->num_frames * header->num_framechannels * sizeof( unsigned short ) > filesize || header->ofs_triangles + header->num_triangles * sizeof( int[3] ) > filesize || header->ofs_meshes + header->num_meshes * sizeof( iqmmesh_t ) > filesize || header->ofs_bounds + header->num_frames * sizeof( iqmbounds_t ) > filesize ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s has invalid size or offset information\n", mod->name ); goto error; } poutmodel = mod->extradata = Mod_Malloc( mod, sizeof( *poutmodel ) ); // load text texts = Mod_Malloc( mod, header->num_text + 1 ); if( header->ofs_text ) { memcpy( texts, (const char *)(pbase + header->ofs_text), header->num_text ); } texts[header->ofs_text] = '\0'; // load vertex arrays vposition = NULL; vtexcoord = NULL; vnormal = NULL; vtangent = NULL; vblendindices_byte = NULL; vblendindexes_int = NULL; vblendweights_byte = NULL; vblendweights_float = NULL; va = ( iqmvertexarray_t * )( pbase + header->ofs_vertexarrays ); for( i = 0; i < header->num_vertexarrays; i++ ) { size_t vsize; va[i].type = LittleLong( va[i].type ); va[i].flags = LittleLong( va[i].flags ); va[i].format = LittleLong( va[i].format ); va[i].size = LittleLong( va[i].size ); va[i].offset = LittleLong( va[i].offset ); vsize = header->num_vertexes*va[i].size; switch( va[i].format ) { case IQM_FLOAT: vsize *= sizeof( float ); break; case IQM_INT: case IQM_UINT: vsize *= sizeof( int ); break; case IQM_BYTE: case IQM_UBYTE: vsize *= sizeof( unsigned char ); break; default: continue; } if( va[i].offset + vsize > filesize ) { continue; } switch( va[i].type ) { case IQM_POSITION: if( va[i].format == IQM_FLOAT && va[i].size == 3 ) { vposition = ( float * )( pbase + va[i].offset ); } break; case IQM_TEXCOORD: if( va[i].format == IQM_FLOAT && va[i].size == 2 ) { vtexcoord = ( float * )( pbase + va[i].offset ); } break; case IQM_NORMAL: if( va[i].format == IQM_FLOAT && va[i].size == 3 ) { vnormal = ( float * )( pbase + va[i].offset ); } break; case IQM_TANGENT: if( va[i].format == IQM_FLOAT && va[i].size == 4 ) { vtangent = ( float * )( pbase + va[i].offset ); } break; case IQM_BLENDINDEXES: if( va[i].size != SKM_MAX_WEIGHTS ) break; if( va[i].format == IQM_BYTE || va[i].format == IQM_UBYTE ) { vblendindices_byte = ( qbyte * )( pbase + va[i].offset ); } else if( va[i].format == IQM_INT || va[i].format == IQM_UINT ) { vblendindexes_int = ( int * )( pbase + va[i].offset ); } break; case IQM_BLENDWEIGHTS: if( va[i].size != SKM_MAX_WEIGHTS ) break; if( va[i].format == IQM_UBYTE ) { vblendweights_byte = ( qbyte * )( pbase + va[i].offset ); } else if( va[i].format == IQM_FLOAT ) { vblendweights_float = ( float * )( pbase + va[i].offset ); } break; default: break; } } if( !vposition || !vtexcoord || !(vblendindices_byte || vblendindexes_int) || !(vblendweights_byte || vblendweights_float) ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s is missing vertex array data\n", mod->name ); goto error; } // load joints memsize = 0; memsize += sizeof( bonepose_t ) * header->num_joints; pmem = Mod_Malloc( mod, memsize ); baseposes = ( void * )pmem; pmem += sizeof( *baseposes ); memsize = 0; memsize += sizeof( mskbone_t ) * header->num_joints; memsize += sizeof( bonepose_t ) * header->num_joints; pmem = Mod_Malloc( mod, memsize ); poutmodel->numbones = header->num_joints; poutmodel->bones = ( void * )pmem; pmem += sizeof( *poutmodel->bones ) * poutmodel->numbones; poutmodel->invbaseposes = ( void * )pmem; pmem += sizeof( *poutmodel->invbaseposes ) * poutmodel->numbones; joints = ( iqmjoint_t * )( pbase + header->ofs_joints ); for( i = 0; i < poutmodel->numbones; i++ ) { joints[i].name = LittleLong( joints[i].name ); joints[i].parent = LittleLong( joints[i].parent ); for( j = 0; j < 3; j++ ) { joints[i].translate[j] = LittleFloat( joints[i].translate[j] ); joints[i].rotate[j] = LittleFloat( joints[i].rotate[j] ); joints[i].scale[j] = LittleFloat( joints[i].scale[j] ); } if( joints[i].parent >= (int)i ) { ri.Com_Printf( S_COLOR_RED "ERROR: %s bone[%i].parent(%i) >= %i\n", mod->name, i, joints[i].parent, i ); goto error; } poutmodel->bones[i].name = texts + joints[i].name; poutmodel->bones[i].parent = joints[i].parent; DualQuat_FromQuat3AndVector( joints[i].rotate, joints[i].translate, baseposes[i].dualquat ); // scale is unused // reconstruct invserse bone pose if( joints[i].parent >= 0 ) { bonepose_t bp, *pbp; bp = baseposes[i]; pbp = &baseposes[joints[i].parent]; DualQuat_Multiply( pbp->dualquat, bp.dualquat, baseposes[i].dualquat ); } DualQuat_Copy( baseposes[i].dualquat, poutmodel->invbaseposes[i].dualquat ); DualQuat_Invert( poutmodel->invbaseposes[i].dualquat ); } // load frames poses = ( iqmpose_t * )( pbase + header->ofs_poses ); for( i = 0; i < header->num_poses; i++ ) { poses[i].parent = LittleLong( poses[i].parent ); poses[i].mask = LittleLong( poses[i].mask ); for( j = 0; j < 10; j++ ) { poses[i].channeloffset[j] = LittleFloat( poses[i].channeloffset[j] ); poses[i].channelscale[j] = LittleFloat( poses[i].channelscale[j] ); } } memsize = 0; memsize += sizeof( mskframe_t ) * header->num_frames; memsize += sizeof( bonepose_t ) * header->num_joints * header->num_frames; pmem = Mod_Malloc( mod, memsize ); poutmodel->numframes = header->num_frames; poutmodel->frames = ( mskframe_t * )pmem; pmem += sizeof( mskframe_t ) * poutmodel->numframes; framedata = ( unsigned short * )( pbase + header->ofs_frames ); for( i = 0; i < header->num_frames; i++ ) { bonepose_t *pbp; vec3_t translate; quat_t rotate; poutmodel->frames[i].boneposes = ( bonepose_t * )pmem; pmem += sizeof( bonepose_t ) * poutmodel->numbones; for( j = 0, pbp = poutmodel->frames[i].boneposes; j < header->num_poses; j++, pbp++ ) { translate[0] = poses[j].channeloffset[0]; if( poses[j].mask & 0x01 ) translate[0] += *framedata++ * poses[j].channelscale[0]; translate[1] = poses[j].channeloffset[1]; if( poses[j].mask & 0x02 ) translate[1] += *framedata++ * poses[j].channelscale[1]; translate[2] = poses[j].channeloffset[2]; if( poses[j].mask & 0x04 ) translate[2] += *framedata++ * poses[j].channelscale[2]; rotate[0] = poses[j].channeloffset[3]; if( poses[j].mask & 0x08 ) rotate[0] += *framedata++ * poses[j].channelscale[3]; rotate[1] = poses[j].channeloffset[4]; if( poses[j].mask & 0x10 ) rotate[1] += *framedata++ * poses[j].channelscale[4]; rotate[2] = poses[j].channeloffset[5]; if( poses[j].mask & 0x20 ) rotate[2] += *framedata++ * poses[j].channelscale[5]; rotate[3] = poses[j].channeloffset[6]; if( poses[j].mask & 0x40 ) rotate[3] += *framedata++ * poses[j].channelscale[6]; if( rotate[3] > 0 ) { Vector4Inverse( rotate ); } Vector4Normalize( rotate ); // scale is unused if( poses[j].mask & 0x80 ) framedata++; if( poses[j].mask & 0x100 ) framedata++; if( poses[j].mask & 0x200 ) framedata++; DualQuat_FromQuatAndVector( rotate, translate, pbp->dualquat ); } } // load triangles memsize = 0; memsize += sizeof( *outelems ) * header->num_triangles * 3; pmem = Mod_Malloc( mod, memsize ); poutmodel->numtris = header->num_triangles; poutmodel->elems = ( elem_t * )pmem; pmem += sizeof( *outelems ) * header->num_triangles * 3; inelems = ( const int * )(pbase + header->ofs_triangles); outelems = poutmodel->elems; for( i = 0; i < header->num_triangles; i++ ) { for( j = 0; j < 3; j++ ) { outelems[j] = LittleLong( inelems[j] ); } inelems += 3; outelems += 3; } // load vertices memsize = 0; memsize += sizeof( *poutmodel->sVectorsArray ) * header->num_vertexes; // 16-bytes aligned memsize += sizeof( *poutmodel->xyzArray ) * header->num_vertexes; memsize += sizeof( *poutmodel->normalsArray ) * header->num_vertexes; memsize += sizeof( *poutmodel->stArray ) * header->num_vertexes; memsize += sizeof( *poutmodel->blendWeights ) * header->num_vertexes * SKM_MAX_WEIGHTS; memsize += sizeof( *poutmodel->blendIndices ) * header->num_vertexes * SKM_MAX_WEIGHTS; pmem = Mod_Malloc( mod, memsize ); poutmodel->numverts = header->num_vertexes; // S-vectors poutmodel->sVectorsArray = ( vec4_t * )pmem; pmem += sizeof( *poutmodel->sVectorsArray ) * header->num_vertexes; if( vtangent ) { for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 4; j++ ) { poutmodel->sVectorsArray[i][j] = LittleFloat( vtangent[j] ); } vtangent += 4; } } // XYZ positions poutmodel->xyzArray = ( vec4_t * )pmem; pmem += sizeof( *poutmodel->xyzArray ) * header->num_vertexes; for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 3; j++ ) { poutmodel->xyzArray[i][j] = LittleFloat( vposition[j] ); } poutmodel->xyzArray[i][3] = 1; vposition += 3; } // normals poutmodel->normalsArray = ( vec4_t * )pmem; pmem += sizeof( *poutmodel->normalsArray ) * header->num_vertexes; for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 3; j++ ) { poutmodel->normalsArray[i][j] = LittleFloat( vnormal[j] ); } poutmodel->normalsArray[i][3] = 0; vnormal += 3; } // texture coordinates poutmodel->stArray = ( vec2_t * )pmem; pmem += sizeof( *poutmodel->stArray ) * header->num_vertexes; for( i = 0; i < header->num_vertexes; i++ ) { for( j = 0; j < 2; j++ ) { poutmodel->stArray[i][j] = LittleFloat( vtexcoord[j] ); } vtexcoord += 2; } if( !vtangent ) { // if the loaded file is missing precomputed S-vectors, compute them now R_BuildTangentVectors( poutmodel->numverts, poutmodel->xyzArray, poutmodel->normalsArray, poutmodel->stArray, poutmodel->numtris, poutmodel->elems, poutmodel->sVectorsArray ); } // blend indices poutmodel->blendIndices = ( qbyte * )pmem; pmem += sizeof( *poutmodel->blendIndices ) * header->num_vertexes * SKM_MAX_WEIGHTS; if( vblendindices_byte ) { memcpy( poutmodel->blendIndices, vblendindices_byte, sizeof( qbyte ) * header->num_vertexes * SKM_MAX_WEIGHTS ); } else if( vblendindexes_int ) { for( j = 0; j < header->num_vertexes * SKM_MAX_WEIGHTS; j++ ) { poutmodel->blendIndices[j] = LittleLong( vblendindexes_int[j] ); } } // blend weights poutmodel->blendWeights = ( qbyte * )pmem; pmem += sizeof( *poutmodel->blendWeights ) * header->num_vertexes * SKM_MAX_WEIGHTS; if( vblendweights_byte ) { memcpy( poutmodel->blendWeights, vblendweights_byte, sizeof( qbyte ) * header->num_vertexes * SKM_MAX_WEIGHTS ); } else if( vblendweights_float ) { for( j = 0; j < header->num_vertexes * SKM_MAX_WEIGHTS; j++ ) { poutmodel->blendWeights[j] = LittleFloat( vblendweights_float[j] ) * 255.0f; } } // blends memsize = 0; memsize += poutmodel->numverts * ( sizeof( mskblend_t ) + sizeof( unsigned int ) ); pmem = Mod_Malloc( mod, memsize ); poutmodel->numblends = 0; poutmodel->blends = ( mskblend_t * )pmem; pmem += sizeof( *poutmodel->blends ) * poutmodel->numverts; poutmodel->vertexBlends = ( unsigned int * )pmem; vblendindices_byte = poutmodel->blendIndices; vblendweights_byte = poutmodel->blendWeights; for( i = 0; i < poutmodel->numverts; i++ ) { mskblend_t blend; for( j = 0; j < SKM_MAX_WEIGHTS; j++ ) { blend.indices[j] = vblendindices_byte[j]; blend.weights[j] = vblendweights_byte[j]; } poutmodel->vertexBlends[i] = Mod_SkeletalModel_AddBlend( poutmodel, &blend ); vblendindices_byte += SKM_MAX_WEIGHTS; vblendweights_byte += SKM_MAX_WEIGHTS; } // meshes memsize = 0; memsize += sizeof( mskmesh_t ) * header->num_meshes; memsize += sizeof( drawSurfaceSkeletal_t ) * header->num_meshes; pmem = Mod_Malloc( mod, memsize ); poutmodel->nummeshes = header->num_meshes; poutmodel->meshes = ( mskmesh_t * )pmem; pmem += sizeof( *poutmodel->meshes ) * header->num_meshes; inmesh = ( iqmmesh_t * )(pbase + header->ofs_meshes); for( i = 0; i < header->num_meshes; i++ ) { inmesh[i].name = LittleLong( inmesh[i].name ); inmesh[i].material = LittleLong( inmesh[i].material ); inmesh[i].first_vertex = LittleLong( inmesh[i].first_vertex ); inmesh[i].num_vertexes = LittleLong( inmesh[i].num_vertexes ); inmesh[i].first_triangle = LittleLong( inmesh[i].first_triangle ); inmesh[i].num_triangles = LittleLong( inmesh[i].num_triangles ); poutmodel->meshes[i].name = texts + inmesh[i].name; Mod_StripLODSuffix( poutmodel->meshes[i].name ); poutmodel->meshes[i].skin.name = texts + inmesh[i].material; poutmodel->meshes[i].skin.shader = R_RegisterSkin( poutmodel->meshes[i].skin.name ); poutmodel->meshes[i].elems = poutmodel->elems + inmesh[i].first_triangle * 3; poutmodel->meshes[i].numtris = inmesh[i].num_triangles; poutmodel->meshes[i].numverts = inmesh[i].num_vertexes; poutmodel->meshes[i].xyzArray = poutmodel->xyzArray + inmesh[i].first_vertex; poutmodel->meshes[i].normalsArray = poutmodel->normalsArray + inmesh[i].first_vertex; poutmodel->meshes[i].stArray = poutmodel->stArray + inmesh[i].first_vertex; poutmodel->meshes[i].sVectorsArray = poutmodel->sVectorsArray + inmesh[i].first_vertex; poutmodel->meshes[i].blendIndices = poutmodel->blendIndices + inmesh[i].first_vertex * SKM_MAX_WEIGHTS; poutmodel->meshes[i].blendWeights = poutmodel->blendWeights + inmesh[i].first_vertex * SKM_MAX_WEIGHTS; poutmodel->meshes[i].vertexBlends = poutmodel->vertexBlends + inmesh[i].first_vertex; // elements are always offset to start vertex 0 for each mesh outelems = poutmodel->meshes[i].elems; for( j = 0; j < poutmodel->meshes[i].numtris; j++ ) { outelems[0] -= inmesh[i].first_vertex; outelems[1] -= inmesh[i].first_vertex; outelems[2] -= inmesh[i].first_vertex; outelems += 3; } poutmodel->meshes[i].maxWeights = 1; vblendweights_byte = poutmodel->meshes[i].blendWeights; for( j = 0; j < poutmodel->meshes[i].numverts; j++ ) { for( k = 1; k < SKM_MAX_WEIGHTS && vblendweights_byte[k]; k++ ); if( k > poutmodel->meshes[i].maxWeights ) { poutmodel->meshes[i].maxWeights = k; if( k == SKM_MAX_WEIGHTS ) { break; } } vblendweights_byte += SKM_MAX_WEIGHTS; } // creating a VBO only makes sense if GLSL is present and the number of bones // we can handle on the GPU is sufficient if( glConfig.ext.vertex_buffer_object && poutmodel->numbones <= glConfig.maxGLSLBones ) { // build a static vertex buffer object for this mesh Mod_SkeletalBuildStaticVBOForMesh( &poutmodel->meshes[i] ); } } poutmodel->drawSurfs = ( drawSurfaceSkeletal_t * )pmem; pmem += sizeof( *poutmodel->drawSurfs ) * header->num_meshes; for( i = 0; i < header->num_meshes; i++ ) { poutmodel->drawSurfs[i].type = ST_SKELETAL; poutmodel->drawSurfs[i].model = mod; poutmodel->drawSurfs[i].mesh = poutmodel->meshes + i; } // bounds ClearBounds( mod->mins, mod->maxs ); inbounds = ( iqmbounds_t * )(pbase + header->ofs_bounds); for( i = 0; i < header->num_frames; i++ ) { for( j = 0; j < 3; j++ ) { inbounds[i].bbmin[j] = LittleFloat( inbounds[i].bbmin[j] ); inbounds[i].bbmax[j] = LittleFloat( inbounds[i].bbmax[j] ); } inbounds[i].radius = LittleFloat( inbounds[i].radius ); inbounds[i].xyradius = LittleFloat( inbounds[i].xyradius ); VectorCopy( inbounds[i].bbmin, poutmodel->frames[i].mins ); VectorCopy( inbounds[i].bbmax, poutmodel->frames[i].maxs ); poutmodel->frames[i].radius = inbounds[i].radius; AddPointToBounds( poutmodel->frames[i].mins, mod->mins, mod->maxs ); AddPointToBounds( poutmodel->frames[i].maxs, mod->mins, mod->maxs ); } mod->radius = RadiusFromBounds( mod->mins, mod->maxs ); mod->type = mod_skeletal; mod->registrationSequence = rsh.registrationSequence; mod->touch = &Mod_TouchSkeletalModel; R_Free( baseposes ); return; error: if( baseposes ) { R_Free( baseposes ); } mod->type = mod_bad; }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Bruvo's Distance implementing Addition, Loss, and Infinite models for imputation of missing data. NOTE: The input needs to be divided by the repeat length beforehand for this to work. in: a matrix of two individuals out: a double value that will be the output from bruvo's distance. n: number of individuals(2) nall: number of alleles perm: a vector from the permn function in R woo: p * p! loss: TRUE/FALSE: impute under genome loss model. add: TRUE/FALSE: impute under genome addition model. ==============================================================================*/ double bruvo_dist(int *in, int *nall, int *perm, int *woo, int *loss, int *add, int old_model) { // R_CheckUserInterrupt(); int i; int j; int counter = 0; // counter used for building arrays int n = 2; // number of individuals int p = *nall; // number of alleles int w = *woo; // number of permutations = p * p! int loss_indicator = *loss; // 1 if the genome loss model should be used int add_indicator = *add; // 1 if the genome addition model should be used int* genos; // array to store the genotypes genos = R_Calloc(2*p, int); int zerocatch[2]; // 2 element array to store the number of missing // alleles in each genotype. int** zero_ind; // array to store the indices of the missing data for // each genotype zero_ind = R_Calloc(2, int*); zero_ind[0] = R_Calloc(p, int); zero_ind[1] = R_Calloc(p, int); int zerodiff; // used to check the amount of missing data different // between the two genotypes double minn = 100; // The minimum distance // reconstruct the genotype table. zerocatch[0] = 0; zerocatch[1] = 0; for(i = 0; i < n; i++) { for(j = 0; j < p; j++) { // Catch missing data here. if (in[counter] == 0) { if (zerocatch[i] == p - 1) { goto finalsteps; } zerocatch[i] += 1; // Rprintf("[%d]", zerocatch[i] - 1); zero_ind[i][zerocatch[i] - 1] = j; } genos[i*p + j] = in[counter++]; // Rprintf("%d\t", genos[i*p + j]); } // Rprintf("\n"); } // Rprintf("\n"); zerodiff = abs(zerocatch[0] - zerocatch[1]); /*========================================================================== * Removing superfluous zeroes from the data. This is in the case that both * of the genotypes contain one or more zeroes. * * smaller and larger refer to the size of the genotypes. ==========================================================================*/ if (zerocatch[0] > 0 && zerocatch[1] > 0) { int smaller = 0; int larger = 1; int reduction = 0; int i; int j; int zero_counter; int *perm_array; int *new_geno; int *new_alleles; if (zerodiff == 0) { reduction = p - zerocatch[0]; } else { if (zerocatch[0] < zerocatch[1]) { smaller = 1; larger = 0; } reduction = p - (zerocatch[smaller] - zerodiff); } new_alleles = R_Calloc(reduction, int); for (i = 0; i < reduction; i++) { new_alleles[i] = i; } w = fact(reduction) * reduction; perm_array = R_Calloc(w, int); perm_count = 0; permute(new_alleles, 0, reduction - 1, perm_array); new_geno = R_Calloc(reduction*n, int); counter = 0; for (i=0; i < n; i++) { zero_counter = zerocatch[larger]; for (j = 0; j < p; j++) { if (genos[i*p + j] == 0 && zero_counter > 0) { zero_counter--; } else { new_geno[counter++] = genos[i*p + j]; } } } minn = bruvo_dist(new_geno, &reduction, perm_array, &w, &loss_indicator, &add_indicator, old_model); R_Free(perm_array); R_Free(new_geno); R_Free(new_alleles); goto finalsteps; }