Ptex
PtexUtils.cpp
Go to the documentation of this file.
1/*
2PTEX SOFTWARE
3Copyright 2014 Disney Enterprises, Inc. All rights reserved
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
22Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33OF 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
48const 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
58const 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
68const 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
77const char* EdgeFilterModeName(EdgeFilterMode m)
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
87const 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
97const char* MetaDataTypeName(MetaDataType mdt)
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
107namespace {
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
123void 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
134void 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
145namespace PtexUtils {
146
147bool 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
166namespace {
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
189void 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
203namespace {
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
226void 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
241namespace {
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
251void 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
261namespace {
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
271void 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
281namespace {
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
299void 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
315namespace {
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
333void 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
349namespace {
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
366void 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
383namespace {
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
406void 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
422void 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
438void 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
458namespace {
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
480void 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
504namespace {
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
522void 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
538namespace {
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
554namespace {
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
579void 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
591namespace {
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
618void 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
630void 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
649namespace {
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
679String::~String()
680{
681 if (_str) free(_str);
682}
683
684
685String& String::operator=(const char* str)
686{
687 if (_str) free(_str);
688 _str = str ? strdup(str) : 0;
689 return *this;
690}
691
692std::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 FaceInfo * faces
const char * EdgeFilterModeName(EdgeFilterMode m)
Definition PtexUtils.cpp:77
void ConvertFromFloat(void *dst, const float *src, DataType dt, int numChannels)
const char * MetaDataTypeName(MetaDataType mdt)
Definition PtexUtils.cpp:97
const char * BorderModeName(BorderMode m)
Definition PtexUtils.cpp:68
const char * EdgeIdName(EdgeId eid)
Definition PtexUtils.cpp:87
PTEX_NAMESPACE_BEGIN const char * MeshTypeName(MeshType mt)
Definition PtexUtils.cpp:48
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
std::ostream & operator<<(std::ostream &stream, const String &str)
const char * DataTypeName(DataType dt)
Definition PtexUtils.cpp:58
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Memory-managed string.
Definition Ptexture.h:296
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)
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
bool isConstant(const void *data, int stride, int ures, int vres, int pixelSize)
T min(T a, T b)
Definition PtexUtils.h:148
void divalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
void encodeDifference(void *data, int size, DataType dt)
void reduce(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
void deinterleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
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)
void decodeDifference(void *data, int size, DataType dt)
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
T halve(T val)
Definition PtexUtils.h:157
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
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)
ApplyConstFn applyConstFunctions[20]
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