void CImagePacker::GetMinimumDimensions( int *pReturnWidth, int *pReturnHeight ) { *pReturnWidth = CeilPow2( m_MaxLightmapWidth ); *pReturnHeight = CeilPow2( m_MinimumHeight ); int aspect = *pReturnWidth / *pReturnHeight; if (aspect > HardwareConfig()->MaxTextureAspectRatio()) { *pReturnHeight = *pReturnWidth / HardwareConfig()->MaxTextureAspectRatio(); } }
static void MXMLBufferAppend(MXMLBuffer * a_buffer, const char* a_string, int a_stringLength = 0) { unsigned int maxLength; char * buffer; if( !a_stringLength ) { a_stringLength = (unsigned int)strlen(a_string); } // Grow buffer by power of 2 if required unsigned int requiredSize = (unsigned int)(a_buffer->m_bufferSize + a_stringLength); if(requiredSize >= a_buffer->m_maxBufferSize) { if(requiredSize < MXML_BUFFER_INITIAL_SIZE) { maxLength = MXML_BUFFER_INITIAL_SIZE; } else { maxLength = CeilPow2(requiredSize); } buffer = (char*)a_buffer->m_Alloc(maxLength, a_buffer->m_memContext); memcpy(buffer, a_buffer->m_buffer, a_buffer->m_bufferSize); if( a_buffer->m_buffer ) { a_buffer->m_Free(a_buffer->m_buffer, a_buffer->m_memContext); } a_buffer->m_buffer = buffer; a_buffer->m_maxBufferSize = maxLength; } // Add characters memcpy(a_buffer->m_buffer + a_buffer->m_bufferSize, a_string, a_stringLength); a_buffer->m_bufferSize += a_stringLength; }
float CImagePacker::GetEfficiency( void ) { return ( float )m_AreaUsed / ( float )( m_MaxLightmapWidth * CeilPow2( m_MinimumHeight ) ); }
static double ApproxEarthMoversMetric( vector<double> &dd, int wi, int hi ) { // find powers of 2 that are big enough int w = CeilPow2( wi ), h = CeilPow2( hi ); vector<double> d( w*h, 0.0 ); CopyRaster( &d[0], w, &dd[0], wi, wi, hi ); UnnormHaarTf2D( d, w, h ); // PrintVectorAsMat( stdout, d, 8 ); vector<int> cdist( w, 1 ); vector<int> rdist( h, 1 ); int mask; mask = w >> 1; // only works for w = 2^n for( int x = 1; x < w; ++x ) { for( int tmp = x; !(tmp & mask); tmp <<= 1 ) cdist[x] <<= 1; } mask = h >> 1; // only works for h = 2^n for( int y = 1; y < h; ++y ) { for( int tmp = y; !(tmp & mask); tmp <<= 1 ) rdist[y] <<= 1; } // use of 1 as lower bound is right; // do not care about sums, only differences double approx = 0.0; // approximate Earth Mover's metric for( int x = 1; x < w; ++x ) { for( int y = 1; y < h; ++y ) { int dx = cdist[x]; int dy = rdist[y]; double dist = min( dx, dy ); if( dist < 0 ) { printf( "x %d, y %d, dx %d, dy %d, dist %f, d[x+w*y] %f\n", x, y, dx, dy, dist, d[x + w*y] ); } approx += dist * abs( d[x + w*y] ); } } // this should never happen if( approx < 0 ) { printf( "##Negative metric? wi=%d, hi=%d" "\nColumn dists: ", wi, hi ); for( int x = 1; x < w; ++x ) printf( "%d ", cdist[x] ); printf( "\nRow dists: " ); for( int y = 1; y < h; ++y ) printf( "%d ", rdist[y] ); printf( "\n" ); exit( 42 ); } // Normalize: // - divide by 2 deltas per move unit. // - divide by N pixels (per pixel cost). // - divide by Poisson noise on area N. int N = wi * hi; approx /= 2.0 * N * sqrt( N ); printf( "Approximate EM metric %f for %d points.\n", approx, N ); return approx; }
// For the input (pts) region and value lists {av, bv): // - Return images {i1, i2, diff} (and dims Nx, Ny). // - Optionally write image files. // static void MakeMetricImagesFFT( vector<double> &i1, vector<double> &i2, vector<double> &diff, int &Nx, int &Ny, const vector<Point> &pts, const vector<double> &av, const vector<double> &bv, bool write_images, const char *msg, FILE* flog ) { /* ---------- */ /* Initialize */ /* ---------- */ i1.clear(); i2.clear(); diff.clear(); Nx = 0; Ny = 0; /* -------------------- */ /* Set image dimensions */ /* -------------------- */ IBox B; BBoxFromPoints( B, pts ); Nx = CeilPow2( B.R - B.L + 1 ); Ny = CeilPow2( B.T - B.B + 1 ); int N2 = Nx * Ny; fprintf( flog, "MetricImages: Range x %d %d, y %d %d, use Nx=%d, Ny=%d\n", B.L, B.R, B.B, B.T, Nx, Ny ); /* ----------- */ /* Fill images */ /* ----------- */ i1.resize( N2, 0.0 ); i2.resize( N2, 0.0 ); diff.resize( N2 ); int np = pts.size(); for( int i = 0; i < np; ++i ) { double x = pts[i].x - B.L, y = pts[i].y - B.B; DistributePixel( x, y, av[i], i1, Nx, Ny ); DistributePixel( x, y, bv[i], i2, Nx, Ny ); } for( int i = 0; i < N2; ++i ) diff[i] = i1[i] - i2[i]; /* ------------ */ /* Write images */ /* ------------ */ if( write_images ) { char fname[32]; sprintf( fname, "fft%d-a.tif", FFTFileIdx ); VectorDblToTif8( fname, i1, Nx, Ny ); sprintf( fname, "fft%d-b.tif", FFTFileIdx ); VectorDblToTif8( fname, i2, Nx, Ny ); sprintf( fname, "fft%d-d.tif", FFTFileIdx ); VectorDblToTif8( fname, diff, Nx, Ny ); ++FFTFileIdx; double e1 = 0.0, e2 = 0.0, ed = 0.0; for( int i = 0; i < N2; ++i ) { e1 += i1[i]*i1[i]; e2 += i2[i]*i2[i]; ed += diff[i]*diff[i]; } fprintf( flog, "MetricImages: Energies (1,2,dif) %f %f %f\n", e1, e2, ed ); } }