Ptex
PtexUtils.cpp
Go to the documentation of this file.
1 /*
2 PTEX SOFTWARE
3 Copyright 2009 Disney Enterprises, Inc. All rights reserved
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in
14  the documentation and/or other materials provided with the
15  distribution.
16 
17  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
18  Studios" or the names of its contributors may NOT be used to
19  endorse or promote products derived from this software without
20  specific prior written permission from Walt Disney Pictures.
21 
22 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 */
35 
36 #include "PtexPlatform.h"
37 #include <algorithm>
38 #include <vector>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "PtexHalf.h"
43 #include "PtexUtils.h"
44 
46 {
47  static const char* names[] = { "triangle", "quad" };
48  if (mt < 0 || mt >= int(sizeof(names)/sizeof(const char*)))
49  return "(invalid mesh type)";
50  return names[mt];
51 }
52 
53 
55 {
56  static const char* names[] = { "uint8", "uint16", "float16", "float32" };
57  if (dt < 0 || dt >= int(sizeof(names)/sizeof(const char*)))
58  return "(invalid data type)";
59  return names[dt];
60 }
61 
62 
64 {
65  static const char* names[] = { "clamp", "black", "periodic" };
66  if (m < 0 || m >= int(sizeof(names)/sizeof(const char*)))
67  return "(invalid border mode)";
68  return names[m];
69 }
70 
71 
72 const char* Ptex::EdgeIdName(EdgeId eid)
73 {
74  static const char* names[] = { "bottom", "right", "top", "left" };
75  if (eid < 0 || eid >= int(sizeof(names)/sizeof(const char*)))
76  return "(invalid edge id)";
77  return names[eid];
78 }
79 
80 
82 {
83  static const char* names[] = { "string", "int8", "int16", "int32", "float", "double" };
84  if (mdt < 0 || mdt >= int(sizeof(names)/sizeof(const char*)))
85  return "(invalid meta data type)";
86  return names[mdt];
87 }
88 
89 
90 
91 namespace {
92  template<typename DST, typename SRC>
93  void ConvertArrayClamped(DST* dst, SRC* src, int numChannels, float scale, float round=0)
94  {
95  for (int i = 0; i < numChannels; i++)
96  dst[i] = DST(PtexUtils::clamp(src[i], 0.0f, 1.0f) * scale + round);
97  }
98 
99  template<typename DST, typename SRC>
100  void ConvertArray(DST* dst, SRC* src, int numChannels, float scale, float round=0)
101  {
102  for (int i = 0; i < numChannels; i++)
103  dst[i] = DST((float)src[i] * scale + round);
104  }
105 }
106 
107 void Ptex::ConvertToFloat(float* dst, const void* src, Ptex::DataType dt, int numChannels)
108 {
109  switch (dt) {
110  case dt_uint8: ConvertArray(dst, (uint8_t*)src, numChannels, 1.f/255.f); break;
111  case dt_uint16: ConvertArray(dst, (uint16_t*)src, numChannels, 1.f/65535.f); break;
112  case dt_half: ConvertArray(dst, (PtexHalf*)src, numChannels, 1.f); break;
113  case dt_float: memcpy(dst, src, sizeof(float)*numChannels); break;
114  }
115 }
116 
117 
118 void Ptex::ConvertFromFloat(void* dst, const float* src, Ptex::DataType dt, int numChannels)
119 {
120  switch (dt) {
121  case dt_uint8: ConvertArrayClamped((uint8_t*)dst, src, numChannels, 255.0, 0.5); break;
122  case dt_uint16: ConvertArrayClamped((uint16_t*)dst, src, numChannels, 65535.0, 0.5); break;
123  case dt_half: ConvertArray((PtexHalf*)dst, src, numChannels, 1.0); break;
124  case dt_float: memcpy(dst, src, sizeof(float)*numChannels); break;
125  }
126 }
127 
128 
129 bool PtexUtils::isConstant(const void* data, int stride, int ures, int vres,
130  int pixelSize)
131 {
132  int rowlen = pixelSize * ures;
133  const char* p = (const char*) data + stride;
134 
135  // compare each row with the first
136  for (int i = 1; i < vres; i++, p += stride)
137  if (0 != memcmp(data, p, rowlen)) return 0;
138 
139  // make sure first row is constant
140  p = (const char*) data + pixelSize;
141  for (int i = 1; i < ures; i++, p += pixelSize)
142  if (0 != memcmp(data, p, pixelSize)) return 0;
143 
144  return 1;
145 }
146 
147 
148 namespace {
149  template<typename T>
150  inline void interleave(const T* src, int sstride, int uw, int vw,
151  T* dst, int dstride, int nchan)
152  {
153  sstride /= (int)sizeof(T);
154  dstride /= (int)sizeof(T);
155  // for each channel
156  for (T* dstend = dst + nchan; dst != dstend; dst++) {
157  // for each row
158  T* drow = dst;
159  for (const T* rowend = src + sstride*vw; src != rowend;
160  src += sstride, drow += dstride) {
161  // copy each pixel across the row
162  T* dp = drow;
163  for (const T* sp = src, * end = sp + uw; sp != end; dp += nchan)
164  *dp = *sp++;
165  }
166  }
167  }
168 }
169 
170 
171 void PtexUtils::interleave(const void* src, int sstride, int uw, int vw,
172  void* dst, int dstride, DataType dt, int nchan)
173 {
174  switch (dt) {
175  case dt_uint8: ::interleave((const uint8_t*) src, sstride, uw, vw,
176  (uint8_t*) dst, dstride, nchan); break;
177  case dt_half:
178  case dt_uint16: ::interleave((const uint16_t*) src, sstride, uw, vw,
179  (uint16_t*) dst, dstride, nchan); break;
180  case dt_float: ::interleave((const float*) src, sstride, uw, vw,
181  (float*) dst, dstride, nchan); break;
182  }
183 }
184 
185 namespace {
186  template<typename T>
187  inline void deinterleave(const T* src, int sstride, int uw, int vw,
188  T* dst, int dstride, int nchan)
189  {
190  sstride /= (int)sizeof(T);
191  dstride /= (int)sizeof(T);
192  // for each channel
193  for (const T* srcend = src + nchan; src != srcend; src++) {
194  // for each row
195  const T* srow = src;
196  for (const T* rowend = srow + sstride*vw; srow != rowend;
197  srow += sstride, dst += dstride) {
198  // copy each pixel across the row
199  const T* sp = srow;
200  for (T* dp = dst, * end = dp + uw; dp != end; sp += nchan)
201  *dp++ = *sp;
202  }
203  }
204  }
205 }
206 
207 
208 void PtexUtils::deinterleave(const void* src, int sstride, int uw, int vw,
209  void* dst, int dstride, DataType dt, int nchan)
210 {
211  switch (dt) {
212  case dt_uint8: ::deinterleave((const uint8_t*) src, sstride, uw, vw,
213  (uint8_t*) dst, dstride, nchan); break;
214  case dt_half:
215  case dt_uint16: ::deinterleave((const uint16_t*) src, sstride, uw, vw,
216  (uint16_t*) dst, dstride, nchan); break;
217  case dt_float: ::deinterleave((const float*) src, sstride, uw, vw,
218  (float*) dst, dstride, nchan); break;
219  }
220 }
221 
222 
223 namespace {
224  template<typename T>
225  void encodeDifference(T* data, int size)
226  {
227  size /= (int)sizeof(T);
228  T* p = (T*) data, * end = p + size, tmp, prev = 0;
229  while (p != end) { tmp = prev; prev = *p; *p = T(*p - tmp); p++; }
230  }
231 }
232 
233 void PtexUtils::encodeDifference(void* data, int size, DataType dt)
234 {
235  switch (dt) {
236  case dt_uint8: ::encodeDifference((uint8_t*) data, size); break;
237  case dt_uint16: ::encodeDifference((uint16_t*) data, size); break;
238  default: break; // skip other types
239  }
240 }
241 
242 
243 namespace {
244  template<typename T>
245  void decodeDifference(T* data, int size)
246  {
247  size /= (int)sizeof(T);
248  T* p = (T*) data, * end = p + size, prev = 0;
249  while (p != end) { *p = T(*p + prev); prev = *p++; }
250  }
251 }
252 
253 void PtexUtils::decodeDifference(void* data, int size, DataType dt)
254 {
255  switch (dt) {
256  case dt_uint8: ::decodeDifference((uint8_t*) data, size); break;
257  case dt_uint16: ::decodeDifference((uint16_t*) data, size); break;
258  default: break; // skip other types
259  }
260 }
261 
262 
263 namespace {
264  template<typename T>
265  inline void reduce(const T* src, int sstride, int uw, int vw,
266  T* dst, int dstride, int nchan)
267  {
268  sstride /= (int)sizeof(T);
269  dstride /= (int)sizeof(T);
270  int rowlen = uw*nchan;
271  int srowskip = 2*sstride - rowlen;
272  int drowskip = dstride - rowlen/2;
273  for (const T* end = src + vw*sstride; src != end;
274  src += srowskip, dst += drowskip)
275  for (const T* rowend = src + rowlen; src != rowend; src += nchan)
276  for (const T* pixend = src+nchan; src != pixend; src++)
277  *dst++ = T(0.25 * (src[0] + src[nchan] +
278  src[sstride] + src[sstride+nchan]));
279  }
280 }
281 
282 void PtexUtils::reduce(const void* src, int sstride, int uw, int vw,
283  void* dst, int dstride, DataType dt, int nchan)
284 {
285  switch (dt) {
286  case dt_uint8: ::reduce((const uint8_t*) src, sstride, uw, vw,
287  (uint8_t*) dst, dstride, nchan); break;
288  case dt_half: ::reduce((const PtexHalf*) src, sstride, uw, vw,
289  (PtexHalf*) dst, dstride, nchan); break;
290  case dt_uint16: ::reduce((const uint16_t*) src, sstride, uw, vw,
291  (uint16_t*) dst, dstride, nchan); break;
292  case dt_float: ::reduce((const float*) src, sstride, uw, vw,
293  (float*) dst, dstride, nchan); break;
294  }
295 }
296 
297 
298 namespace {
299  template<typename T>
300  inline void reduceu(const T* src, int sstride, int uw, int vw,
301  T* dst, int dstride, int nchan)
302  {
303  sstride /= (int)sizeof(T);
304  dstride /= (int)sizeof(T);
305  int rowlen = uw*nchan;
306  int srowskip = sstride - rowlen;
307  int drowskip = dstride - rowlen/2;
308  for (const T* end = src + vw*sstride; src != end;
309  src += srowskip, dst += drowskip)
310  for (const T* rowend = src + rowlen; src != rowend; src += nchan)
311  for (const T* pixend = src+nchan; src != pixend; src++)
312  *dst++ = T(0.5 * (src[0] + src[nchan]));
313  }
314 }
315 
316 void PtexUtils::reduceu(const void* src, int sstride, int uw, int vw,
317  void* dst, int dstride, DataType dt, int nchan)
318 {
319  switch (dt) {
320  case dt_uint8: ::reduceu((const uint8_t*) src, sstride, uw, vw,
321  (uint8_t*) dst, dstride, nchan); break;
322  case dt_half: ::reduceu((const PtexHalf*) src, sstride, uw, vw,
323  (PtexHalf*) dst, dstride, nchan); break;
324  case dt_uint16: ::reduceu((const uint16_t*) src, sstride, uw, vw,
325  (uint16_t*) dst, dstride, nchan); break;
326  case dt_float: ::reduceu((const float*) src, sstride, uw, vw,
327  (float*) dst, dstride, nchan); break;
328  }
329 }
330 
331 
332 namespace {
333  template<typename T>
334  inline void reducev(const T* src, int sstride, int uw, int vw,
335  T* dst, int dstride, int nchan)
336  {
337  sstride /= (int)sizeof(T);
338  dstride /= (int)sizeof(T);
339  int rowlen = uw*nchan;
340  int srowskip = 2*sstride - rowlen;
341  int drowskip = dstride - rowlen;
342  for (const T* end = src + vw*sstride; src != end;
343  src += srowskip, dst += drowskip)
344  for (const T* rowend = src + rowlen; src != rowend; src++)
345  *dst++ = T(0.5 * (src[0] + src[sstride]));
346  }
347 }
348 
349 void PtexUtils::reducev(const void* src, int sstride, int uw, int vw,
350  void* dst, int dstride, DataType dt, int nchan)
351 {
352  switch (dt) {
353  case dt_uint8: ::reducev((const uint8_t*) src, sstride, uw, vw,
354  (uint8_t*) dst, dstride, nchan); break;
355  case dt_half: ::reducev((const PtexHalf*) src, sstride, uw, vw,
356  (PtexHalf*) dst, dstride, nchan); break;
357  case dt_uint16: ::reducev((const uint16_t*) src, sstride, uw, vw,
358  (uint16_t*) dst, dstride, nchan); break;
359  case dt_float: ::reducev((const float*) src, sstride, uw, vw,
360  (float*) dst, dstride, nchan); break;
361  }
362 }
363 
364 
365 
366 namespace {
367  // generate a reduction of a packed-triangle texture
368  // note: this method won't work for tiled textures
369  template<typename T>
370  inline void reduceTri(const T* src, int sstride, int w, int /*vw*/,
371  T* dst, int dstride, int nchan)
372  {
373  sstride /= (int)sizeof(T);
374  dstride /= (int)sizeof(T);
375  int rowlen = w*nchan;
376  const T* src2 = src + (w-1) * sstride + rowlen - nchan;
377  int srowinc2 = -2*sstride - nchan;
378  int srowskip = 2*sstride - rowlen;
379  int srowskip2 = w*sstride - 2 * nchan;
380  int drowskip = dstride - rowlen/2;
381  for (const T* end = src + w*sstride; src != end;
382  src += srowskip, src2 += srowskip2, dst += drowskip)
383  for (const T* rowend = src + rowlen; src != rowend; src += nchan, src2 += srowinc2)
384  for (const T* pixend = src+nchan; src != pixend; src++, src2++)
385  *dst++ = T(0.25 * (src[0] + src[nchan] + src[sstride] + src2[0]));
386  }
387 }
388 
389 void PtexUtils::reduceTri(const void* src, int sstride, int w, int /*vw*/,
390  void* dst, int dstride, DataType dt, int nchan)
391 {
392  switch (dt) {
393  case dt_uint8: ::reduceTri((const uint8_t*) src, sstride, w, 0,
394  (uint8_t*) dst, dstride, nchan); break;
395  case dt_half: ::reduceTri((const PtexHalf*) src, sstride, w, 0,
396  (PtexHalf*) dst, dstride, nchan); break;
397  case dt_uint16: ::reduceTri((const uint16_t*) src, sstride, w, 0,
398  (uint16_t*) dst, dstride, nchan); break;
399  case dt_float: ::reduceTri((const float*) src, sstride, w, 0,
400  (float*) dst, dstride, nchan); break;
401  }
402 }
403 
404 
405 void PtexUtils::fill(const void* src, void* dst, int dstride,
406  int ures, int vres, int pixelsize)
407 {
408  // fill first row
409  int rowlen = ures*pixelsize;
410  char* ptr = (char*) dst;
411  char* end = ptr + rowlen;
412  for (; ptr != end; ptr += pixelsize) memcpy(ptr, src, pixelsize);
413 
414  // fill remaining rows from first row
415  ptr = (char*) dst + dstride;
416  end = (char*) dst + vres*dstride;
417  for (; ptr != end; ptr += dstride) memcpy(ptr, dst, rowlen);
418 }
419 
420 
421 void PtexUtils::copy(const void* src, int sstride, void* dst, int dstride,
422  int vres, int rowlen)
423 {
424  // regular non-tiled case
425  if (sstride == rowlen && dstride == rowlen) {
426  // packed case - copy in single block
427  memcpy(dst, src, vres*rowlen);
428  } else {
429  // copy a row at a time
430  char* sptr = (char*) src;
431  char* dptr = (char*) dst;
432  for (char* end = sptr + vres*sstride; sptr != end;) {
433  memcpy(dptr, sptr, rowlen);
434  dptr += dstride;
435  sptr += sstride;
436  }
437  }
438 }
439 
440 
441 namespace {
442  template<typename T>
443  inline void blend(const T* src, float weight, T* dst, int rowlen, int nchan)
444  {
445  for (const T* end = src + rowlen * nchan; src != end; dst++)
446  *dst = T(*dst + T(weight * (float)*src++));
447  }
448 
449  template<typename T>
450  inline void blendflip(const T* src, float weight, T* dst, int rowlen, int nchan)
451  {
452  dst += (rowlen-1) * nchan;
453  for (const T* end = src + rowlen * nchan; src != end;) {
454  for (int i = 0; i < nchan; i++, dst++) {
455  *dst = T(*dst + T(weight * (float)*src++));
456  }
457  dst -= nchan*2;
458  }
459  }
460 }
461 
462 
463 void PtexUtils::blend(const void* src, float weight, void* dst, bool flip,
464  int rowlen, DataType dt, int nchan)
465 {
466  switch ((dt<<1) | int(flip)) {
467  case (dt_uint8<<1): ::blend((const uint8_t*) src, weight,
468  (uint8_t*) dst, rowlen, nchan); break;
469  case (dt_uint8<<1 | 1): ::blendflip((const uint8_t*) src, weight,
470  (uint8_t*) dst, rowlen, nchan); break;
471  case (dt_half<<1): ::blend((const PtexHalf*) src, weight,
472  (PtexHalf*) dst, rowlen, nchan); break;
473  case (dt_half<<1 | 1): ::blendflip((const PtexHalf*) src, weight,
474  (PtexHalf*) dst, rowlen, nchan); break;
475  case (dt_uint16<<1): ::blend((const uint16_t*) src, weight,
476  (uint16_t*) dst, rowlen, nchan); break;
477  case (dt_uint16<<1 | 1): ::blendflip((const uint16_t*) src, weight,
478  (uint16_t*) dst, rowlen, nchan); break;
479  case (dt_float<<1): ::blend((const float*) src, weight,
480  (float*) dst, rowlen, nchan); break;
481  case (dt_float<<1 | 1): ::blendflip((const float*) src, weight,
482  (float*) dst, rowlen, nchan); break;
483  }
484 }
485 
486 
487 namespace {
488  template<typename T>
489  inline void average(const T* src, int sstride, int uw, int vw,
490  T* dst, int nchan)
491  {
492  float* buff = (float*) alloca(nchan*sizeof(float));
493  memset(buff, 0, nchan*sizeof(float));
494  sstride /= (int)sizeof(T);
495  int rowlen = uw*nchan;
496  int rowskip = sstride - rowlen;
497  for (const T* end = src + vw*sstride; src != end; src += rowskip)
498  for (const T* rowend = src + rowlen; src != rowend;)
499  for (int i = 0; i < nchan; i++) buff[i] += (float)*src++;
500  float scale = 1.0f/(float)(uw*vw);
501  for (int i = 0; i < nchan; i++) dst[i] = T(buff[i]*scale);
502  }
503 }
504 
505 void PtexUtils::average(const void* src, int sstride, int uw, int vw,
506  void* dst, DataType dt, int nchan)
507 {
508  switch (dt) {
509  case dt_uint8: ::average((const uint8_t*) src, sstride, uw, vw,
510  (uint8_t*) dst, nchan); break;
511  case dt_half: ::average((const PtexHalf*) src, sstride, uw, vw,
512  (PtexHalf*) dst, nchan); break;
513  case dt_uint16: ::average((const uint16_t*) src, sstride, uw, vw,
514  (uint16_t*) dst, nchan); break;
515  case dt_float: ::average((const float*) src, sstride, uw, vw,
516  (float*) dst, nchan); break;
517  }
518 }
519 
520 
521 namespace {
522  struct CompareRfaceIds {
523  const Ptex::FaceInfo* faces;
524  CompareRfaceIds(const Ptex::FaceInfo* faces) : faces(faces) {}
525  bool operator() (uint32_t faceid1, uint32_t faceid2)
526  {
527  const Ptex::FaceInfo& f1 = faces[faceid1];
528  const Ptex::FaceInfo& f2 = faces[faceid2];
529  int min1 = f1.isConstant() ? 1 : PtexUtils::min(f1.res.ulog2, f1.res.vlog2);
530  int min2 = f2.isConstant() ? 1 : PtexUtils::min(f2.res.ulog2, f2.res.vlog2);
531  return min1 > min2;
532  }
533  };
534 }
535 
536 
537 namespace {
538  template<typename T>
539  inline void multalpha(T* data, int npixels, int nchannels, int alphachan, float scale)
540  {
541  int alphaoffset; // offset to alpha chan from data ptr
542  int nchanmult; // number of channels to alpha-multiply
543  if (alphachan == 0) {
544  // first channel is alpha chan: mult the rest of the channels
545  data++;
546  alphaoffset = -1;
547  nchanmult = nchannels - 1;
548  }
549  else {
550  // mult all channels up to alpha chan
551  alphaoffset = alphachan;
552  nchanmult = alphachan;
553  }
554 
555  for (T* end = data + npixels*nchannels; data != end; data += nchannels) {
556  float aval = scale * (float)data[alphaoffset];
557  for (int i = 0; i < nchanmult; i++) data[i] = T((float)data[i] * aval);
558  }
559  }
560 }
561 
562 void PtexUtils::multalpha(void* data, int npixels, DataType dt, int nchannels, int alphachan)
563 {
564  float scale = OneValueInv(dt);
565  switch(dt) {
566  case dt_uint8: ::multalpha((uint8_t*) data, npixels, nchannels, alphachan, scale); break;
567  case dt_uint16: ::multalpha((uint16_t*) data, npixels, nchannels, alphachan, scale); break;
568  case dt_half: ::multalpha((PtexHalf*) data, npixels, nchannels, alphachan, scale); break;
569  case dt_float: ::multalpha((float*) data, npixels, nchannels, alphachan, scale); break;
570  }
571 }
572 
573 
574 namespace {
575  template<typename T>
576  inline void divalpha(T* data, int npixels, int nchannels, int alphachan, float scale)
577  {
578  int alphaoffset; // offset to alpha chan from data ptr
579  int nchandiv; // number of channels to alpha-divide
580  if (alphachan == 0) {
581  // first channel is alpha chan: div the rest of the channels
582  data++;
583  alphaoffset = -1;
584  nchandiv = nchannels - 1;
585  }
586  else {
587  // div all channels up to alpha chan
588  alphaoffset = alphachan;
589  nchandiv = alphachan;
590  }
591 
592  for (T* end = data + npixels*nchannels; data != end; data += nchannels) {
593  T alpha = data[alphaoffset];
594  if (!alpha) continue; // don't divide by zero!
595  float aval = scale / (float)alpha;
596  for (int i = 0; i < nchandiv; i++) data[i] = T((float)data[i] * aval);
597  }
598  }
599 }
600 
601 void PtexUtils::divalpha(void* data, int npixels, DataType dt, int nchannels, int alphachan)
602 {
603  float scale = OneValue(dt);
604  switch(dt) {
605  case dt_uint8: ::divalpha((uint8_t*) data, npixels, nchannels, alphachan, scale); break;
606  case dt_uint16: ::divalpha((uint16_t*) data, npixels, nchannels, alphachan, scale); break;
607  case dt_half: ::divalpha((PtexHalf*) data, npixels, nchannels, alphachan, scale); break;
608  case dt_float: ::divalpha((float*) data, npixels, nchannels, alphachan, scale); break;
609  }
610 }
611 
612 
613 void PtexUtils::genRfaceids(const FaceInfo* faces, int nfaces,
614  uint32_t* rfaceids, uint32_t* faceids)
615 {
616  // stable_sort faceids by smaller dimension (u or v) in descending order
617  // treat const faces as having res of 1
618 
619  // init faceids
620  for (int i = 0; i < nfaces; i++) faceids[i] = i;
621 
622  // sort faceids by rfaceid
623  std::stable_sort(faceids, faceids + nfaces, CompareRfaceIds(faces));
624 
625  // generate mapping from faceid to rfaceid
626  for (int i = 0; i < nfaces; i++) {
627  // note: i is the rfaceid
628  rfaceids[faceids[i]] = i;
629  }
630 }
631 
632 namespace {
633  // apply to 1..4 channels, unrolled
634  template<class T, int nChan>
635  void ApplyConst(float weight, float* dst, void* data, int /*nChan*/)
636  {
637  // dst[i] += data[i] * weight for i in {0..n-1}
638  PtexUtils::VecAccum<T,nChan>()(dst, (T*) data, weight);
639  }
640 
641  // apply to N channels (general case)
642  template<class T>
643  void ApplyConstN(float weight, float* dst, void* data, int nChan)
644  {
645  // dst[i] += data[i] * weight for i in {0..n-1}
646  PtexUtils::VecAccumN<T>()(dst, (T*) data, nChan, weight);
647  }
648 }
649 
652  ApplyConstN<uint8_t>, ApplyConstN<uint16_t>, ApplyConstN<PtexHalf>, ApplyConstN<float>,
653  ApplyConst<uint8_t,1>, ApplyConst<uint16_t,1>, ApplyConst<PtexHalf,1>, ApplyConst<float,1>,
654  ApplyConst<uint8_t,2>, ApplyConst<uint16_t,2>, ApplyConst<PtexHalf,2>, ApplyConst<float,2>,
655  ApplyConst<uint8_t,3>, ApplyConst<uint16_t,3>, ApplyConst<PtexHalf,3>, ApplyConst<float,3>,
656  ApplyConst<uint8_t,4>, ApplyConst<uint16_t,4>, ApplyConst<PtexHalf,4>, ApplyConst<float,4>,
657 };
658 
659 #ifndef PTEX_USE_STDSTRING
661 {
662  if (_str) free(_str);
663 }
664 
665 
667 {
668  if (_str) free(_str);
669  _str = str ? strdup(str) : 0;
670  return *this;
671 }
672 
673 std::ostream& operator << (std::ostream& stream, const Ptex::String& str)
674 {
675  stream << str.c_str();
676  return stream;
677 }
678 #endif
679 
static float OneValueInv(DataType dt)
Lookup up inverse value of given data type that corresponds to the normalized value of 1...
Definition: Ptexture.h:144
Unsigned, 8-bit integer.
Definition: Ptexture.h:84
static void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:562
bool isConstant() const
Determine if face is constant (by checking a flag).
Definition: Ptexture.h:270
Unsigned, 16-bit integer.
Definition: Ptexture.h:85
Memory-managed string.
Definition: Ptexture.h:303
static void reduceTri(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:389
Half-precision (16-bit) floating point.
Definition: Ptexture.h:86
DataType
Type of data stored in texture file.
Definition: Ptexture.h:83
static void blend(const void *src, float weight, void *dst, bool flip, int rowlen, DataType dt, int nchannels)
Definition: PtexUtils.cpp:463
void(* ApplyConstFn)(float weight, float *dst, void *data, int nChan)
Definition: PtexUtils.h:202
static void average(const void *src, int sstride, int ures, int vres, void *dst, DataType dt, int nchannels)
Definition: PtexUtils.cpp:505
static T min(T a, T b)
Definition: PtexUtils.h:116
String & operator=(const char *str)
Definition: PtexUtils.cpp:666
static void copy(const void *src, int sstride, void *dst, int dstride, int nrows, int rowlen)
Definition: PtexUtils.cpp:421
Platform-specific classes, functions, and includes.
MetaDataType
Type of meta data entry.
Definition: Ptexture.h:107
static float OneValue(DataType dt)
Look up value of given data type that corresponds to the normalized value of 1.0. ...
Definition: Ptexture.h:138
static const char * MeshTypeName(MeshType mt)
Look up name of given mesh type.
Definition: PtexUtils.cpp:45
static ApplyConstFn applyConstFunctions[20]
Definition: PtexUtils.h:203
BorderMode
How to handle mesh border when filtering.
Definition: Ptexture.h:91
int8_t vlog2
log base 2 of v resolution, in texels
Definition: Ptexture.h:163
static T clamp(T x, T lo, T hi)
Definition: PtexUtils.h:122
static void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:613
Single-precision (32-bit) floating point.
Definition: Ptexture.h:87
std::ostream & operator<<(std::ostream &stream, const Ptex::String &str)
Definition: PtexUtils.cpp:673
Half-precision (16-bit) floating-point type.
Definition: PtexHalf.h:84
static const char * DataTypeName(DataType dt)
Look up name of given data type.
Definition: PtexUtils.cpp:54
MeshType
Type of base mesh for which the textures are defined.
Definition: Ptexture.h:77
static void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:405
static void encodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:233
static const char * MetaDataTypeName(MetaDataType mdt)
Look up name of given meta data type.
Definition: PtexUtils.cpp:81
int8_t ulog2
log base 2 of u resolution, in texels
Definition: Ptexture.h:162
static const char * BorderModeName(BorderMode m)
Look up name of given border mode.
Definition: PtexUtils.cpp:63
static void divalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:601
static void deinterleave(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:208
static void reduceu(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:316
static void interleave(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:171
static void reducev(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:349
Res res
Resolution of face.
Definition: Ptexture.h:238
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:237
Half-precision floating-point type.
static void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:253
static void ConvertToFloat(float *dst, const void *src, Ptex::DataType dt, int numChannels)
Convert a number of data values from the given data type to float.
Definition: PtexUtils.cpp:107
static void reduce(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:282
static void ConvertFromFloat(void *dst, const float *src, Ptex::DataType dt, int numChannels)
Convert a number of data values from float to the given data type.
Definition: PtexUtils.cpp:118
const char * c_str() const
Definition: Ptexture.h:312
static bool isConstant(const void *data, int stride, int ures, int vres, int pixelSize)
Definition: PtexUtils.cpp:129
static const char * EdgeIdName(EdgeId eid)
Look up name of given edge ID.
Definition: PtexUtils.cpp:72
EdgeId
Edge IDs used in adjacency data in the Ptex::FaceInfo struct.
Definition: Ptexture.h:99