50     static const char* names[] = { 
"triangle", 
"quad" };
 
   51     if (mt < 0 || mt >= 
int(
sizeof(names)/
sizeof(
const char*)))
 
   52         return "(invalid mesh type)";
 
   59     static const char* names[] = { 
"uint8", 
"uint16", 
"float16", 
"float32" };
 
   60     if (dt < 0 || dt >= 
int(
sizeof(names)/
sizeof(
const char*)))
 
   61         return "(invalid data type)";
 
   68     static const char* names[] = { 
"clamp", 
"black", 
"periodic" };
 
   69     if (m < 0 || m >= 
int(
sizeof(names)/
sizeof(
const char*)))
 
   70         return "(invalid border mode)";
 
   76     static const char* names[] = { 
"none", 
"tanvec" };
 
   77     if (m < 0 || m >= 
int(
sizeof(names)/
sizeof(
const char*)))
 
   78         return "(invalid edge filter mode)";
 
   85     static const char* names[] = { 
"bottom", 
"right", 
"top", 
"left" };
 
   86     if (eid < 0 || eid >= 
int(
sizeof(names)/
sizeof(
const char*)))
 
   87         return "(invalid edge id)";
 
   94     static const char* names[] = { 
"string", 
"int8", 
"int16", 
"int32", 
"float", 
"double" };
 
   95     if (mdt < 0 || mdt >= 
int(
sizeof(names)/
sizeof(
const char*)))
 
   96         return "(invalid meta data type)";
 
  102     template<
typename DST, 
typename SRC>
 
  103     void ConvertArrayClamped(DST* dst, SRC* src, 
int numChannels, 
float scale, 
float round=0)
 
  105         for (
int i = 0; i < numChannels; i++)
 
  109     template<
typename DST, 
typename SRC>
 
  110     void ConvertArray(DST* dst, SRC* src, 
int numChannels, 
float scale, 
float round=0)
 
  112         for (
int i = 0; i < numChannels; i++)
 
  113                 dst[i] = DST((
float)src[i] * scale + round);
 
  120     case dt_uint8:  ConvertArray(dst, 
static_cast<const uint8_t*
>(src),  numChannels, 1.f/255.f); 
break;
 
  121     case dt_uint16: ConvertArray(dst, 
static_cast<const uint16_t*
>(src), numChannels, 1.f/65535.f); 
break;
 
  122     case dt_half:   ConvertArray(dst, 
static_cast<const PtexHalf*
>(src), numChannels, 1.f); 
break;
 
  123     case dt_float:  memcpy(dst, src, 
sizeof(
float)*numChannels); 
break;
 
  131     case dt_uint8:  ConvertArrayClamped(
static_cast<uint8_t*
>(dst),  src, numChannels, 255.0, 0.5); 
break;
 
  132     case dt_uint16: ConvertArrayClamped(
static_cast<uint16_t*
>(dst), src, numChannels, 65535.0, 0.5); 
break;
 
  133     case dt_half:   ConvertArray(
static_cast<PtexHalf*
>(dst), src, numChannels, 1.0); 
break;
 
  134     case dt_float:  memcpy(dst, src, 
sizeof(
float)*numChannels); 
break;
 
  141 bool isConstant(
const void* data, 
int stride, 
int ures, 
int vres,
 
  144     int rowlen = pixelSize * ures;
 
  145     const char* p = (
const char*) data + stride;
 
  148     for (
int i = 1; i < vres; i++, p += stride)
 
  149         if (0 != memcmp(data, p, rowlen)) 
return 0;
 
  152     p = (
const char*) data + pixelSize;
 
  153     for (
int i = 1; i < ures; i++, p += pixelSize)
 
  154         if (0 != memcmp(data, p, pixelSize)) 
return 0;
 
  162     inline void interleave(
const T* src, 
int sstride, 
int uw, 
int vw,
 
  163                            T* dst, 
int dstride, 
int nchan)
 
  165         sstride /= (int)
sizeof(T);
 
  166         dstride /= (int)
sizeof(T);
 
  168         for (T* dstend = dst + nchan; dst != dstend; dst++) {
 
  171             for (
const T* rowend = src + sstride*vw; src != rowend;
 
  172                  src += sstride, drow += dstride) {
 
  175                 for (
const T* sp = src, * end = sp + uw; sp != end; dp += nchan)
 
  183 void interleave(
const void* src, 
int sstride, 
int uw, 
int vw,
 
  184                 void* dst, 
int dstride, 
DataType dt, 
int nchan)
 
  188                                   (uint8_t*) dst, dstride, nchan); 
break;
 
  191                                   (uint16_t*) dst, dstride, nchan); 
break;
 
  193                                   (
float*) dst, dstride, nchan); 
break;
 
  199     inline void deinterleave(
const T* src, 
int sstride, 
int uw, 
int vw,
 
  200                              T* dst, 
int dstride, 
int nchan)
 
  202         sstride /= (int)
sizeof(T);
 
  203         dstride /= (int)
sizeof(T);
 
  205         for (
const T* srcend = src + nchan; src != srcend; src++) {
 
  208             for (
const T* rowend = srow + sstride*vw; srow != rowend;
 
  209                  srow += sstride, dst += dstride) {
 
  212                 for (T* dp = dst, * end = dp + uw; dp != end; sp += nchan)
 
  221                   void* dst, 
int dstride, 
DataType dt, 
int nchan)
 
  225                                     (uint8_t*) dst, dstride, nchan); 
break;
 
  228                                     (uint16_t*) dst, dstride, nchan); 
break;
 
  230                                     (
float*) dst, dstride, nchan); 
break;
 
  239         size /= (int)
sizeof(T);
 
  240         T* p = 
static_cast<T*
>(data), * end = p + size, tmp, prev = 0;
 
  241         while (p != end) { tmp = prev; prev = *p; *p = T(*p - tmp); p++; }
 
  259         size /= (int)
sizeof(T);
 
  260         T* p = 
static_cast<T*
>(data), * end = p + size, prev = 0;
 
  261         while (p != end) { *p = T(*p + prev); prev = *p++; }
 
  277     inline void reduce(
const T* src, 
int sstride, 
int uw, 
int vw,
 
  278                        T* dst, 
int dstride, 
int nchan)
 
  280         sstride /= (int)
sizeof(T);
 
  281         dstride /= (int)
sizeof(T);
 
  282         int rowlen = uw*nchan;
 
  283         int srowskip = 2*sstride - rowlen;
 
  284         int drowskip = dstride - rowlen/2;
 
  285         for (
const T* end = src + vw*sstride; src != end;
 
  286              src += srowskip, dst += drowskip)
 
  287             for (
const T* rowend = src + rowlen; src != rowend; src += nchan)
 
  288                 for (
const T* pixend = src+nchan; src != pixend; src++)
 
  289                     *dst++ = T(
quarter(src[0] + src[nchan] + src[sstride] + src[sstride+nchan]));
 
  293 void reduce(
const void* src, 
int sstride, 
int uw, 
int vw,
 
  294             void* dst, 
int dstride, 
DataType dt, 
int nchan)
 
  297     case dt_uint8:     
reduce(
static_cast<const uint8_t*
>(src), sstride, uw, vw,
 
  298                               static_cast<uint8_t*
>(dst), dstride, nchan); 
break;
 
  300                               static_cast<PtexHalf*
>(dst), dstride, nchan); 
break;
 
  301     case dt_uint16:    
reduce(
static_cast<const uint16_t*
>(src), sstride, uw, vw,
 
  302                               static_cast<uint16_t*
>(dst), dstride, nchan); 
break;
 
  303     case dt_float:     
reduce(
static_cast<const float*
>(src), sstride, uw, vw,
 
  304                               static_cast<float*
>(dst), dstride, nchan); 
break;
 
  311     inline void reduceu(
const T* src, 
int sstride, 
int uw, 
int vw,
 
  312                         T* dst, 
int dstride, 
int nchan)
 
  314         sstride /= (int)
sizeof(T);
 
  315         dstride /= (int)
sizeof(T);
 
  316         int rowlen = uw*nchan;
 
  317         int srowskip = sstride - rowlen;
 
  318         int drowskip = dstride - rowlen/2;
 
  319         for (
const T* end = src + vw*sstride; src != end;
 
  320              src += srowskip, dst += drowskip)
 
  321             for (
const T* rowend = src + rowlen; src != rowend; src += nchan)
 
  322                 for (
const T* pixend = src+nchan; src != pixend; src++)
 
  323                     *dst++ = T(
halve(src[0] + src[nchan]));
 
  327 void reduceu(
const void* src, 
int sstride, 
int uw, 
int vw,
 
  328              void* dst, 
int dstride, 
DataType dt, 
int nchan)
 
  331     case dt_uint8:     
reduceu(
static_cast<const uint8_t*
>(src), sstride, uw, vw,
 
  332                                static_cast<uint8_t*
>(dst), dstride, nchan); 
break;
 
  334                                static_cast<PtexHalf*
>(dst), dstride, nchan); 
break;
 
  336                                static_cast<uint16_t*
>(dst), dstride, nchan); 
break;
 
  337     case dt_float:     
reduceu(
static_cast<const float*
>(src), sstride, uw, vw,
 
  338                                static_cast<float*
>(dst), dstride, nchan); 
break;
 
  345     inline void reducev(
const T* src, 
int sstride, 
int uw, 
int vw,
 
  346                         T* dst, 
int dstride, 
int nchan)
 
  348         sstride /= (int)
sizeof(T);
 
  349         dstride /= (int)
sizeof(T);
 
  350         int rowlen = uw*nchan;
 
  351         int srowskip = 2*sstride - rowlen;
 
  352         int drowskip = dstride - rowlen;
 
  353         for (
const T* end = src + vw*sstride; src != end;
 
  354              src += srowskip, dst += drowskip)
 
  355             for (
const T* rowend = src + rowlen; src != rowend; src++)
 
  356                 *dst++ = T(
halve(src[0] + src[sstride]));
 
  360 void reducev(
const void* src, 
int sstride, 
int uw, 
int vw,
 
  361              void* dst, 
int dstride, 
DataType dt, 
int nchan)
 
  364     case dt_uint8:     
reducev(
static_cast<const uint8_t*
>(src), sstride, uw, vw,
 
  365                                static_cast<uint8_t*
>(dst), dstride, nchan); 
break;
 
  367                                static_cast<PtexHalf*
>(dst), dstride, nchan); 
break;
 
  369                                static_cast<uint16_t*
>(dst), dstride, nchan); 
break;
 
  370     case dt_float:     
reducev(
static_cast<const float*
>(src), sstride, uw, vw,
 
  371                                static_cast<float*
>(dst), dstride, nchan); 
break;
 
  381     inline void reduceTri(
const T* src, 
int sstride, 
int w, 
int ,
 
  382                           T* dst, 
int dstride, 
int nchan)
 
  384         sstride /= (int)
sizeof(T);
 
  385         dstride /= (int)
sizeof(T);
 
  386         int rowlen = w*nchan;
 
  387         const T* src2 = src + (w-1) * sstride + rowlen - nchan;
 
  388         int srowinc2 = -2*sstride - nchan;
 
  389         int srowskip = 2*sstride - rowlen;
 
  390         int srowskip2 = w*sstride - 2 * nchan;
 
  391         int drowskip = dstride - rowlen/2;
 
  392         for (
const T* end = src + w*sstride; src != end;
 
  393              src += srowskip, src2 += srowskip2, dst += drowskip)
 
  394             for (
const T* rowend = src + rowlen; src != rowend; src += nchan, src2 += srowinc2)
 
  395                 for (
const T* pixend = src+nchan; src != pixend; src++, src2++)
 
  396                     *dst++ = T(
quarter(src[0] + src[nchan] + src[sstride] + src2[0]));
 
  400 void reduceTri(
const void* src, 
int sstride, 
int w, 
int ,
 
  401                void* dst, 
int dstride, 
DataType dt, 
int nchan)
 
  405                                  static_cast<uint8_t*
>(dst), dstride, nchan); 
break;
 
  407                                  static_cast<PtexHalf*
>(dst), dstride, nchan); 
break;
 
  409                                  static_cast<uint16_t*
>(dst), dstride, nchan); 
break;
 
  411                                  static_cast<float*
>(dst), dstride, nchan); 
break;
 
  416 void fill(
const void* src, 
void* dst, 
int dstride,
 
  417           int ures, 
int vres, 
int pixelsize)
 
  420     int rowlen = ures*pixelsize;
 
  421     char* ptr = (
char*) dst;
 
  422     char* end = ptr + rowlen;
 
  423     for (; ptr != end; ptr += pixelsize) memcpy(ptr, src, pixelsize);
 
  426     ptr = (
char*) dst + dstride;
 
  427     end = (
char*) dst + vres*dstride;
 
  428     for (; ptr != end; ptr += dstride) memcpy(ptr, dst, rowlen);
 
  432 void copy(
const void* src, 
int sstride, 
void* dst, 
int dstride,
 
  433           int vres, 
int rowlen)
 
  436     if (sstride == rowlen && dstride == rowlen) {
 
  438         memcpy(dst, src, vres*rowlen);
 
  441         const char* sptr = (
const char*) src;
 
  442         char* dptr = (
char*) dst;
 
  443         for (
const char* end = sptr + vres*sstride; sptr != end;) {
 
  444             memcpy(dptr, sptr, rowlen);
 
  454     inline void blend(
const T* src, 
float weight, T* dst, 
int rowlen, 
int nchan)
 
  456         for (
const T* end = src + rowlen * nchan; src != end; dst++)
 
  457             *dst = T(*dst + T(weight * (
float)*src++));
 
  461     inline void blendflip(
const T* src, 
float weight, T* dst, 
int rowlen, 
int nchan)
 
  463         dst += (rowlen-1) * nchan;
 
  464         for (
const T* end = src + rowlen * nchan; src != end;) {
 
  465             for (
int i = 0; i < nchan; i++, dst++) {
 
  466                 *dst = T(*dst + T(weight * (
float)*src++));
 
  474 void blend(
const void* src, 
float weight, 
void* dst, 
bool flip,
 
  477     switch ((dt<<1) | 
int(flip)) {
 
  478     case (
dt_uint8<<1):        
blend(
static_cast<const uint8_t*
>(src), weight,
 
  479                                      static_cast<uint8_t*
>(dst), rowlen, nchan); 
break;
 
  480     case (
dt_uint8<<1 | 1):    blendflip(
static_cast<const uint8_t*
>(src), weight,
 
  481                                          static_cast<uint8_t*
>(dst), rowlen, nchan); 
break;
 
  483                                      static_cast<PtexHalf*
>(dst), rowlen, nchan); 
break;
 
  484     case (
dt_half<<1 | 1):     blendflip(
static_cast<const PtexHalf*
>(src), weight,
 
  485                                          static_cast<PtexHalf*
>(dst), rowlen, nchan); 
break;
 
  486     case (
dt_uint16<<1):       
blend(
static_cast<const uint16_t*
>(src), weight,
 
  487                                      static_cast<uint16_t*
>(dst), rowlen, nchan); 
break;
 
  488     case (
dt_uint16<<1 | 1):   blendflip(
static_cast<const uint16_t*
>(src), weight,
 
  489                                          static_cast<uint16_t*
>(dst), rowlen, nchan); 
break;
 
  490     case (
dt_float<<1):        
blend(
static_cast<const float*
>(src), weight,
 
  491                                      static_cast<float*
>(dst), rowlen, nchan); 
break;
 
  492     case (
dt_float<<1 | 1):    blendflip(
static_cast<const float*
>(src), weight,
 
  493                                          static_cast<float*
>(dst), rowlen, nchan); 
break;
 
  500     inline void average(
const T* src, 
int sstride, 
int uw, 
int vw,
 
  503         float* buff = (
float*) alloca(nchan*
sizeof(
float));
 
  504         memset(buff, 0, nchan*
sizeof(
float));
 
  505         sstride /= (int)
sizeof(T);
 
  506         int rowlen = uw*nchan;
 
  507         int rowskip = sstride - rowlen;
 
  508         for (
const T* end = src + vw*sstride; src != end; src += rowskip)
 
  509             for (
const T* rowend = src + rowlen; src != rowend;)
 
  510                 for (
int i = 0; i < nchan; i++) buff[i] += (
float)*src++;
 
  511         float scale = 1.0f/(float)(uw*vw);
 
  512         for (
int i = 0; i < nchan; i++) dst[i] = T(buff[i]*scale);
 
  516 void average(
const void* src, 
int sstride, 
int uw, 
int vw,
 
  520     case dt_uint8:     
average(
static_cast<const uint8_t*
>(src), sstride, uw, vw,
 
  521                                static_cast<uint8_t*
>(dst), nchan); 
break;
 
  523                                static_cast<PtexHalf*
>(dst), nchan); 
break;
 
  525                                static_cast<uint16_t*
>(dst), nchan); 
break;
 
  526     case dt_float:     
average(
static_cast<const float*
>(src), sstride, uw, vw,
 
  527                                static_cast<float*
>(dst), nchan); 
break;
 
  533     struct CompareRfaceIds {
 
  535         CompareRfaceIds(
const FaceInfo* facesArg) : 
faces(facesArg) {}
 
  536         bool operator() (uint32_t faceid1, uint32_t faceid2)
 
  550     inline void multalpha(T* data, 
int npixels, 
int nchannels, 
int alphachan, 
float scale)
 
  554         if (alphachan == 0) {
 
  558             nchanmult = nchannels - 1;
 
  562             alphaoffset = alphachan;
 
  563             nchanmult = alphachan;
 
  566         for (T* end = data + npixels*nchannels; data != end; data += nchannels) {
 
  567             float aval = scale * (float)data[alphaoffset];
 
  568             for (
int i = 0; i < nchanmult; i++) data[i] = T((
float)data[i] * aval);
 
  577     case dt_uint8:    
multalpha(
static_cast<uint8_t*
>(data), npixels, nchannels, alphachan, scale); 
break;
 
  578     case dt_uint16:   
multalpha(
static_cast<uint16_t*
>(data), npixels, nchannels, alphachan, scale); 
break;
 
  580     case dt_float:    
multalpha(
static_cast<float*
>(data), npixels, nchannels, alphachan, scale); 
break;
 
  587     inline void divalpha(T* data, 
int npixels, 
int nchannels, 
int alphachan, 
float scale)
 
  591         if (alphachan == 0) {
 
  595             nchandiv = nchannels - 1;
 
  599             alphaoffset = alphachan;
 
  600             nchandiv = alphachan;
 
  603         for (T* end = data + npixels*nchannels; data != end; data += nchannels) {
 
  604             T alpha = data[alphaoffset];
 
  605             if (!alpha) 
continue; 
 
  606             float aval = scale / (float)alpha;
 
  607             for (
int i = 0; i < nchandiv; i++)  data[i] = T((
float)data[i] * aval);
 
  616     case dt_uint8:    
divalpha(
static_cast<uint8_t*
>(data), npixels, nchannels, alphachan, scale); 
break;
 
  617     case dt_uint16:   
divalpha(
static_cast<uint16_t*
>(data), npixels, nchannels, alphachan, scale); 
break;
 
  619     case dt_float:    
divalpha(
static_cast<float*
>(data), npixels, nchannels, alphachan, scale); 
break;
 
  625                  uint32_t* rfaceids, uint32_t* faceids)
 
  631     for (
int i = 0; i < nfaces; i++) faceids[i] = i;
 
  634     std::stable_sort(faceids, faceids + nfaces, CompareRfaceIds(
faces));
 
  637     for (
int i = 0; i < nfaces; i++) {
 
  639         rfaceids[faceids[i]] = i;
 
  645     template<
class T, 
int nChan>
 
  646     void ApplyConst(
float weight, 
float* dst, 
void* data, 
int )
 
  649         VecAccum<T,nChan>()(dst, 
static_cast<T*
>(data), weight);
 
  654     void ApplyConstN(
float weight, 
float* dst, 
void* data, 
int nChan)
 
  657         VecAccumN<T>()(dst, 
static_cast<T*
>(data), nChan, weight);
 
  663     ApplyConstN<uint8_t>,  ApplyConstN<uint16_t>,  ApplyConstN<PtexHalf>,  ApplyConstN<float>,
 
  664     ApplyConst<uint8_t,1>, ApplyConst<uint16_t,1>, ApplyConst<PtexHalf,1>, ApplyConst<float,1>,
 
  665     ApplyConst<uint8_t,2>, ApplyConst<uint16_t,2>, ApplyConst<PtexHalf,2>, ApplyConst<float,2>,
 
  666     ApplyConst<uint8_t,3>, ApplyConst<uint16_t,3>, ApplyConst<PtexHalf,3>, ApplyConst<float,3>,
 
  667     ApplyConst<uint8_t,4>, ApplyConst<uint16_t,4>, ApplyConst<PtexHalf,4>, ApplyConst<float,4>,
 
  672 #ifndef PTEX_USE_STDSTRING 
  675     if (_str) free(_str);
 
  679 String& String::operator=(
const char* str)
 
  681     if (_str) free(_str);
 
  682     _str = str ? strdup(str) : 0;
 
  686 std::ostream& 
operator << (std::ostream& stream, 
const String& str)
 
  688     stream << str.c_str();