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