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();