Ptex
PtexUtils.cpp
Go to the documentation of this file.
1 /*
2 PTEX SOFTWARE
3 Copyright 2014 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 
45 
47 
48 const char* MeshTypeName(MeshType mt)
49 {
50  static const char* names[] = { "triangle", "quad" };
51  if (mt < 0 || mt >= int(sizeof(names)/sizeof(const char*)))
52  return "(invalid mesh type)";
53  return names[mt];
54 }
55 
56 
57 const char* DataTypeName(DataType dt)
58 {
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)";
62  return names[dt];
63 }
64 
65 
66 const char* BorderModeName(BorderMode m)
67 {
68  static const char* names[] = { "clamp", "black", "periodic" };
69  if (m < 0 || m >= int(sizeof(names)/sizeof(const char*)))
70  return "(invalid border mode)";
71  return names[m];
72 }
73 
75 {
76  static const char* names[] = { "none", "tanvec" };
77  if (m < 0 || m >= int(sizeof(names)/sizeof(const char*)))
78  return "(invalid edge filter mode)";
79  return names[m];
80 }
81 
82 
83 const char* EdgeIdName(EdgeId eid)
84 {
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)";
88  return names[eid];
89 }
90 
91 
93 {
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)";
97  return names[mdt];
98 }
99 
100 
101 namespace {
102  template<typename DST, typename SRC>
103  void ConvertArrayClamped(DST* dst, SRC* src, int numChannels, float scale, float round=0)
104  {
105  for (int i = 0; i < numChannels; i++)
106  dst[i] = DST(PtexUtils::clamp(src[i], 0.0f, 1.0f) * scale + round);
107  }
108 
109  template<typename DST, typename SRC>
110  void ConvertArray(DST* dst, SRC* src, int numChannels, float scale, float round=0)
111  {
112  for (int i = 0; i < numChannels; i++)
113  dst[i] = DST((float)src[i] * scale + round);
114  }
115 }
116 
117 void ConvertToFloat(float* dst, const void* src, DataType dt, int numChannels)
118 {
119  switch (dt) {
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;
124  }
125 }
126 
127 
128 void ConvertFromFloat(void* dst, const float* src, DataType dt, int numChannels)
129 {
130  switch (dt) {
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;
135  }
136 }
137 
138 
139 namespace PtexUtils {
140 
141 bool isConstant(const void* data, int stride, int ures, int vres,
142  int pixelSize)
143 {
144  int rowlen = pixelSize * ures;
145  const char* p = (const char*) data + stride;
146 
147  // compare each row with the first
148  for (int i = 1; i < vres; i++, p += stride)
149  if (0 != memcmp(data, p, rowlen)) return 0;
150 
151  // make sure first row is constant
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;
155 
156  return 1;
157 }
158 
159 
160 namespace {
161  template<typename T>
162  inline void interleave(const T* src, int sstride, int uw, int vw,
163  T* dst, int dstride, int nchan)
164  {
165  sstride /= (int)sizeof(T);
166  dstride /= (int)sizeof(T);
167  // for each channel
168  for (T* dstend = dst + nchan; dst != dstend; dst++) {
169  // for each row
170  T* drow = dst;
171  for (const T* rowend = src + sstride*vw; src != rowend;
172  src += sstride, drow += dstride) {
173  // copy each pixel across the row
174  T* dp = drow;
175  for (const T* sp = src, * end = sp + uw; sp != end; dp += nchan)
176  *dp = *sp++;
177  }
178  }
179  }
180 }
181 
182 
183 void interleave(const void* src, int sstride, int uw, int vw,
184  void* dst, int dstride, DataType dt, int nchan)
185 {
186  switch (dt) {
187  case dt_uint8: interleave((const uint8_t*) src, sstride, uw, vw,
188  (uint8_t*) dst, dstride, nchan); break;
189  case dt_half:
190  case dt_uint16: interleave((const uint16_t*) src, sstride, uw, vw,
191  (uint16_t*) dst, dstride, nchan); break;
192  case dt_float: interleave((const float*) src, sstride, uw, vw,
193  (float*) dst, dstride, nchan); break;
194  }
195 }
196 
197 namespace {
198  template<typename T>
199  inline void deinterleave(const T* src, int sstride, int uw, int vw,
200  T* dst, int dstride, int nchan)
201  {
202  sstride /= (int)sizeof(T);
203  dstride /= (int)sizeof(T);
204  // for each channel
205  for (const T* srcend = src + nchan; src != srcend; src++) {
206  // for each row
207  const T* srow = src;
208  for (const T* rowend = srow + sstride*vw; srow != rowend;
209  srow += sstride, dst += dstride) {
210  // copy each pixel across the row
211  const T* sp = srow;
212  for (T* dp = dst, * end = dp + uw; dp != end; sp += nchan)
213  *dp++ = *sp;
214  }
215  }
216  }
217 }
218 
219 
220 void deinterleave(const void* src, int sstride, int uw, int vw,
221  void* dst, int dstride, DataType dt, int nchan)
222 {
223  switch (dt) {
224  case dt_uint8: deinterleave((const uint8_t*) src, sstride, uw, vw,
225  (uint8_t*) dst, dstride, nchan); break;
226  case dt_half:
227  case dt_uint16: deinterleave((const uint16_t*) src, sstride, uw, vw,
228  (uint16_t*) dst, dstride, nchan); break;
229  case dt_float: deinterleave((const float*) src, sstride, uw, vw,
230  (float*) dst, dstride, nchan); break;
231  }
232 }
233 
234 
235 namespace {
236  template<typename T>
237  void encodeDifference(T* data, int size)
238  {
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++; }
242  }
243 }
244 
245 void encodeDifference(void* data, int size, DataType dt)
246 {
247  switch (dt) {
248  case dt_uint8: encodeDifference(static_cast<uint8_t*>(data), size); break;
249  case dt_uint16: encodeDifference(static_cast<uint16_t*>(data), size); break;
250  default: break; // skip other types
251  }
252 }
253 
254 
255 namespace {
256  template<typename T>
257  void decodeDifference(T* data, int size)
258  {
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++; }
262  }
263 }
264 
265 void decodeDifference(void* data, int size, DataType dt)
266 {
267  switch (dt) {
268  case dt_uint8: decodeDifference(static_cast<uint8_t*>(data), size); break;
269  case dt_uint16: decodeDifference(static_cast<uint16_t*>(data), size); break;
270  default: break; // skip other types
271  }
272 }
273 
274 
275 namespace {
276  template<typename T>
277  inline void reduce(const T* src, int sstride, int uw, int vw,
278  T* dst, int dstride, int nchan)
279  {
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]));
290  }
291 }
292 
293 void reduce(const void* src, int sstride, int uw, int vw,
294  void* dst, int dstride, DataType dt, int nchan)
295 {
296  switch (dt) {
297  case dt_uint8: reduce(static_cast<const uint8_t*>(src), sstride, uw, vw,
298  static_cast<uint8_t*>(dst), dstride, nchan); break;
299  case dt_half: reduce(static_cast<const PtexHalf*>(src), sstride, uw, vw,
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;
305  }
306 }
307 
308 
309 namespace {
310  template<typename T>
311  inline void reduceu(const T* src, int sstride, int uw, int vw,
312  T* dst, int dstride, int nchan)
313  {
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]));
324  }
325 }
326 
327 void reduceu(const void* src, int sstride, int uw, int vw,
328  void* dst, int dstride, DataType dt, int nchan)
329 {
330  switch (dt) {
331  case dt_uint8: reduceu(static_cast<const uint8_t*>(src), sstride, uw, vw,
332  static_cast<uint8_t*>(dst), dstride, nchan); break;
333  case dt_half: reduceu(static_cast<const PtexHalf*>(src), sstride, uw, vw,
334  static_cast<PtexHalf*>(dst), dstride, nchan); break;
335  case dt_uint16: reduceu(static_cast<const uint16_t*>(src), sstride, uw, vw,
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;
339  }
340 }
341 
342 
343 namespace {
344  template<typename T>
345  inline void reducev(const T* src, int sstride, int uw, int vw,
346  T* dst, int dstride, int nchan)
347  {
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]));
357  }
358 }
359 
360 void reducev(const void* src, int sstride, int uw, int vw,
361  void* dst, int dstride, DataType dt, int nchan)
362 {
363  switch (dt) {
364  case dt_uint8: reducev(static_cast<const uint8_t*>(src), sstride, uw, vw,
365  static_cast<uint8_t*>(dst), dstride, nchan); break;
366  case dt_half: reducev(static_cast<const PtexHalf*>(src), sstride, uw, vw,
367  static_cast<PtexHalf*>(dst), dstride, nchan); break;
368  case dt_uint16: reducev(static_cast<const uint16_t*>(src), sstride, uw, vw,
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;
372  }
373 }
374 
375 
376 
377 namespace {
378  // generate a reduction of a packed-triangle texture
379  // note: this method won't work for tiled textures
380  template<typename T>
381  inline void reduceTri(const T* src, int sstride, int w, int /*vw*/,
382  T* dst, int dstride, int nchan)
383  {
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]));
397  }
398 }
399 
400 void reduceTri(const void* src, int sstride, int w, int /*vw*/,
401  void* dst, int dstride, DataType dt, int nchan)
402 {
403  switch (dt) {
404  case dt_uint8: reduceTri(static_cast<const uint8_t*>(src), sstride, w, 0,
405  static_cast<uint8_t*>(dst), dstride, nchan); break;
406  case dt_half: reduceTri(static_cast<const PtexHalf*>(src), sstride, w, 0,
407  static_cast<PtexHalf*>(dst), dstride, nchan); break;
408  case dt_uint16: reduceTri(static_cast<const uint16_t*>(src), sstride, w, 0,
409  static_cast<uint16_t*>(dst), dstride, nchan); break;
410  case dt_float: reduceTri(static_cast<const float*>(src), sstride, w, 0,
411  static_cast<float*>(dst), dstride, nchan); break;
412  }
413 }
414 
415 
416 void fill(const void* src, void* dst, int dstride,
417  int ures, int vres, int pixelsize)
418 {
419  // fill first row
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);
424 
425  // fill remaining rows from first row
426  ptr = (char*) dst + dstride;
427  end = (char*) dst + vres*dstride;
428  for (; ptr != end; ptr += dstride) memcpy(ptr, dst, rowlen);
429 }
430 
431 
432 void copy(const void* src, int sstride, void* dst, int dstride,
433  int vres, int rowlen)
434 {
435  // regular non-tiled case
436  if (sstride == rowlen && dstride == rowlen) {
437  // packed case - copy in single block
438  memcpy(dst, src, vres*rowlen);
439  } else {
440  // copy a row at a time
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);
445  dptr += dstride;
446  sptr += sstride;
447  }
448  }
449 }
450 
451 
452 namespace {
453  template<typename T>
454  inline void blend(const T* src, float weight, T* dst, int rowlen, int nchan)
455  {
456  for (const T* end = src + rowlen * nchan; src != end; dst++)
457  *dst = T(*dst + T(weight * (float)*src++));
458  }
459 
460  template<typename T>
461  inline void blendflip(const T* src, float weight, T* dst, int rowlen, int nchan)
462  {
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++));
467  }
468  dst -= nchan*2;
469  }
470  }
471 }
472 
473 
474 void blend(const void* src, float weight, void* dst, bool flip,
475  int rowlen, DataType dt, int nchan)
476 {
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;
482  case (dt_half<<1): blend(static_cast<const PtexHalf*>(src), weight,
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;
494  }
495 }
496 
497 
498 namespace {
499  template<typename T>
500  inline void average(const T* src, int sstride, int uw, int vw,
501  T* dst, int nchan)
502  {
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);
513  }
514 }
515 
516 void average(const void* src, int sstride, int uw, int vw,
517  void* dst, DataType dt, int nchan)
518 {
519  switch (dt) {
520  case dt_uint8: average(static_cast<const uint8_t*>(src), sstride, uw, vw,
521  static_cast<uint8_t*>(dst), nchan); break;
522  case dt_half: average(static_cast<const PtexHalf*>(src), sstride, uw, vw,
523  static_cast<PtexHalf*>(dst), nchan); break;
524  case dt_uint16: average(static_cast<const uint16_t*>(src), sstride, uw, vw,
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;
528  }
529 }
530 
531 
532 namespace {
533  struct CompareRfaceIds {
534  const FaceInfo* faces;
535  CompareRfaceIds(const FaceInfo* facesArg) : faces(facesArg) {}
536  bool operator() (uint32_t faceid1, uint32_t faceid2)
537  {
538  const Ptex::FaceInfo& f1 = faces[faceid1];
539  const Ptex::FaceInfo& f2 = faces[faceid2];
540  int min1 = f1.isConstant() ? 1 : PtexUtils::min(f1.res.ulog2, f1.res.vlog2);
541  int min2 = f2.isConstant() ? 1 : PtexUtils::min(f2.res.ulog2, f2.res.vlog2);
542  return min1 > min2;
543  }
544  };
545 }
546 
547 
548 namespace {
549  template<typename T>
550  inline void multalpha(T* data, int npixels, int nchannels, int alphachan, float scale)
551  {
552  int alphaoffset; // offset to alpha chan from data ptr
553  int nchanmult; // number of channels to alpha-multiply
554  if (alphachan == 0) {
555  // first channel is alpha chan: mult the rest of the channels
556  data++;
557  alphaoffset = -1;
558  nchanmult = nchannels - 1;
559  }
560  else {
561  // mult all channels up to alpha chan
562  alphaoffset = alphachan;
563  nchanmult = alphachan;
564  }
565 
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);
569  }
570  }
571 }
572 
573 void multalpha(void* data, int npixels, DataType dt, int nchannels, int alphachan)
574 {
575  float scale = OneValueInv(dt);
576  switch(dt) {
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;
579  case dt_half: multalpha(static_cast<PtexHalf*>(data), npixels, nchannels, alphachan, scale); break;
580  case dt_float: multalpha(static_cast<float*>(data), npixels, nchannels, alphachan, scale); break;
581  }
582 }
583 
584 
585 namespace {
586  template<typename T>
587  inline void divalpha(T* data, int npixels, int nchannels, int alphachan, float scale)
588  {
589  int alphaoffset; // offset to alpha chan from data ptr
590  int nchandiv; // number of channels to alpha-divide
591  if (alphachan == 0) {
592  // first channel is alpha chan: div the rest of the channels
593  data++;
594  alphaoffset = -1;
595  nchandiv = nchannels - 1;
596  }
597  else {
598  // div all channels up to alpha chan
599  alphaoffset = alphachan;
600  nchandiv = alphachan;
601  }
602 
603  for (T* end = data + npixels*nchannels; data != end; data += nchannels) {
604  T alpha = data[alphaoffset];
605  if (!alpha) continue; // don't divide by zero!
606  float aval = scale / (float)alpha;
607  for (int i = 0; i < nchandiv; i++) data[i] = T((float)data[i] * aval);
608  }
609  }
610 }
611 
612 void divalpha(void* data, int npixels, DataType dt, int nchannels, int alphachan)
613 {
614  float scale = OneValue(dt);
615  switch(dt) {
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;
618  case dt_half: divalpha(static_cast<PtexHalf*>(data), npixels, nchannels, alphachan, scale); break;
619  case dt_float: divalpha(static_cast<float*>(data), npixels, nchannels, alphachan, scale); break;
620  }
621 }
622 
623 
624 void genRfaceids(const FaceInfo* faces, int nfaces,
625  uint32_t* rfaceids, uint32_t* faceids)
626 {
627  // stable_sort faceids by smaller dimension (u or v) in descending order
628  // treat const faces as having res of 1
629 
630  // init faceids
631  for (int i = 0; i < nfaces; i++) faceids[i] = i;
632 
633  // sort faceids by rfaceid
634  std::stable_sort(faceids, faceids + nfaces, CompareRfaceIds(faces));
635 
636  // generate mapping from faceid to rfaceid
637  for (int i = 0; i < nfaces; i++) {
638  // note: i is the rfaceid
639  rfaceids[faceids[i]] = i;
640  }
641 }
642 
643 namespace {
644  // apply to 1..4 channels, unrolled
645  template<class T, int nChan>
646  void ApplyConst(float weight, float* dst, void* data, int /*nChan*/)
647  {
648  // dst[i] += data[i] * weight for i in {0..n-1}
649  VecAccum<T,nChan>()(dst, static_cast<T*>(data), weight);
650  }
651 
652  // apply to N channels (general case)
653  template<class T>
654  void ApplyConstN(float weight, float* dst, void* data, int nChan)
655  {
656  // dst[i] += data[i] * weight for i in {0..n-1}
657  VecAccumN<T>()(dst, static_cast<T*>(data), nChan, weight);
658  }
659 }
660 
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>,
668 };
669 
670 } // namespace PtexUtils end
671 
672 #ifndef PTEX_USE_STDSTRING
673 String::~String()
674 {
675  if (_str) free(_str);
676 }
677 
678 
679 String& String::operator=(const char* str)
680 {
681  if (_str) free(_str);
682  _str = str ? strdup(str) : 0;
683  return *this;
684 }
685 
686 std::ostream& operator << (std::ostream& stream, const String& str)
687 {
688  stream << str.c_str();
689  return stream;
690 }
691 
692 #endif
693 
PtexUtils::halve
T halve(T val)
Definition: PtexUtils.h:156
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:147
MeshTypeName
PTEX_NAMESPACE_BEGIN const char * MeshTypeName(MeshType mt)
Definition: PtexUtils.cpp:48
PtexUtils::clamp
T clamp(T x, T lo, T hi)
Definition: PtexUtils.h:153
EdgeIdName
const char * EdgeIdName(EdgeId eid)
Definition: PtexUtils.cpp:83
Ptex::dt_half
@ dt_half
Half-precision (16-bit) floating point.
Definition: Ptexture.h:88
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexUtils::deinterleave
void deinterleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:220
PtexUtils::divalpha
void divalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:612
Ptex::OneValueInv
float OneValueInv(DataType dt)
Lookup up inverse value of given data type that corresponds to the normalized value of 1....
Definition: Ptexture.h:155
Ptex::dt_float
@ dt_float
Single-precision (32-bit) floating point.
Definition: Ptexture.h:89
ConvertFromFloat
void ConvertFromFloat(void *dst, const float *src, DataType dt, int numChannels)
Definition: PtexUtils.cpp:128
Ptex::Res::ulog2
int8_t ulog2
log base 2 of u resolution, in texels
Definition: Ptexture.h:173
PtexUtils.h
PtexUtils::fill
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:416
Ptex::Res::vlog2
int8_t vlog2
log base 2 of v resolution, in texels
Definition: Ptexture.h:174
Ptex::DataType
DataType
Type of data stored in texture file.
Definition: Ptexture.h:85
EdgeFilterModeName
const char * EdgeFilterModeName(EdgeFilterMode m)
Definition: PtexUtils.cpp:74
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:242
PtexHalf
Half-precision (16-bit) floating-point type.
Definition: PtexHalf.h:88
PtexUtils::copy
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition: PtexUtils.cpp:432
Ptex::String::operator<<
std::ostream & operator<<(std::ostream &stream, const Ptex::String &str)
std::stream output operator.
PtexUtils::reducev
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:360
PtexUtils::blend
void blend(const void *src, float weight, void *dst, bool flip, int rowlen, DataType dt, int nchan)
Definition: PtexUtils.cpp:474
Ptex::dt_uint16
@ dt_uint16
Unsigned, 16-bit integer.
Definition: Ptexture.h:87
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
Ptex::FaceInfo::isConstant
bool isConstant() const
Determine if face is constant (by checking a flag).
Definition: Ptexture.h:275
PtexUtils::interleave
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:183
Ptex::dt_uint8
@ dt_uint8
Unsigned, 8-bit integer.
Definition: Ptexture.h:86
PtexUtils::applyConstFunctions
ApplyConstFn applyConstFunctions[20]
Definition: PtexUtils.cpp:662
PtexUtils
Definition: PtexUtils.cpp:139
PtexUtils::ApplyConstFn
void(* ApplyConstFn)(float weight, float *dst, void *data, int nChan)
Definition: PtexUtils.h:244
Ptex::OneValue
float OneValue(DataType dt)
Look up value of given data type that corresponds to the normalized value of 1.0.
Definition: Ptexture.h:149
Ptex::String
Memory-managed string.
Definition: Ptexture.h:309
Ptex::MetaDataType
MetaDataType
Type of meta data entry.
Definition: Ptexture.h:115
PtexUtils::quarter
T quarter(T val)
Definition: PtexUtils.h:162
PtexUtils::decodeDifference
void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:265
Ptex::EdgeFilterMode
EdgeFilterMode
How to handle transformation across edges when filtering.
Definition: Ptexture.h:93
PtexUtils::reduceu
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:327
ConvertToFloat
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition: PtexUtils.cpp:117
BorderModeName
const char * BorderModeName(BorderMode m)
Definition: PtexUtils.cpp:66
DataTypeName
const char * DataTypeName(DataType dt)
Definition: PtexUtils.cpp:57
PtexUtils::isConstant
bool isConstant(const void *data, int stride, int ures, int vres, int pixelSize)
Definition: PtexUtils.cpp:141
PtexUtils::genRfaceids
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:624
faces
const FaceInfo * faces
Definition: PtexUtils.cpp:534
PtexUtils::average
void average(const void *src, int sstride, int uw, int vw, void *dst, DataType dt, int nchan)
Definition: PtexUtils.cpp:516
Ptex::FaceInfo::res
Res res
Resolution of face.
Definition: Ptexture.h:243
PtexUtils::multalpha
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:573
Ptex::BorderMode
BorderMode
How to handle mesh border when filtering.
Definition: Ptexture.h:99
MetaDataTypeName
const char * MetaDataTypeName(MetaDataType mdt)
Definition: PtexUtils.cpp:92
Ptex::MeshType
MeshType
Type of base mesh for which the textures are defined.
Definition: Ptexture.h:79
PtexUtils::reduceTri
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:400
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexHalf.h
Half-precision floating-point type.
Ptex::EdgeId
EdgeId
Edge IDs used in adjacency data in the Ptex::FaceInfo struct.
Definition: Ptexture.h:107
PtexUtils::reduce
void reduce(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:293
PtexUtils::encodeDifference
void encodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:245