Ptex: PtexUtils.cpp Source File

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
46 PTEX_NAMESPACE_BEGIN
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
77 const 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
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
97 const 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
667 ApplyConstFn
668applyConstFunctions[20] = {
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
685 String& 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
700 PTEX_NAMESPACE_END
PtexHalf.h
Half-precision floating-point type.
PtexPlatform.h
Platform-specific classes, functions, and includes.
faces
const FaceInfo * faces
Definition PtexUtils.cpp:540
EdgeFilterModeName
const char * EdgeFilterModeName(EdgeFilterMode m)
Definition PtexUtils.cpp:77
ConvertFromFloat
void ConvertFromFloat(void *dst, const float *src, DataType dt, int numChannels)
Definition PtexUtils.cpp:134
MetaDataTypeName
const char * MetaDataTypeName(MetaDataType mdt)
Definition PtexUtils.cpp:97
BorderModeName
const char * BorderModeName(BorderMode m)
Definition PtexUtils.cpp:68
EdgeIdName
const char * EdgeIdName(EdgeId eid)
Definition PtexUtils.cpp:87
MeshTypeName
PTEX_NAMESPACE_BEGIN const char * MeshTypeName(MeshType mt)
Definition PtexUtils.cpp:48
ConvertToFloat
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition PtexUtils.cpp:123
operator<<
std::ostream & operator<<(std::ostream &stream, const String &str)
Definition PtexUtils.cpp:692
DataTypeName
const char * DataTypeName(DataType dt)
Definition PtexUtils.cpp:58
PtexUtils.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Ptex::String
Memory-managed string.
Definition Ptexture.h:296
PTEX_NAMESPACE_BEGIN
Definition PtexSeparableKernel.cpp:42
PtexUtils
Definition PtexUtils.cpp:145
PtexUtils::clamp
T clamp(T x, T lo, T hi)
Definition PtexUtils.h:154
PtexUtils::genRfaceids
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition PtexUtils.cpp:630
PtexUtils::reduceu
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:333
PtexUtils::isConstant
bool isConstant(const void *data, int stride, int ures, int vres, int pixelSize)
Definition PtexUtils.cpp:147
PtexUtils::min
T min(T a, T b)
Definition PtexUtils.h:148
PtexUtils::divalpha
void divalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition PtexUtils.cpp:618
PtexUtils::encodeDifference
void encodeDifference(void *data, int size, DataType dt)
Definition PtexUtils.cpp:251
PtexUtils::reduce
void reduce(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:299
PtexUtils::deinterleave
void deinterleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:226
PtexUtils::quarter
T quarter(T val)
Definition PtexUtils.h:163
PtexUtils::blend
void blend(const void *src, float weight, void *dst, bool flip, int rowlen, DataType dt, int nchan)
Definition PtexUtils.cpp:480
PtexUtils::decodeDifference
void decodeDifference(void *data, int size, DataType dt)
Definition PtexUtils.cpp:271
PtexUtils::reducev
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:366
PtexUtils::fill
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition PtexUtils.cpp:422
PtexUtils::reduceTri
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:406
PtexUtils::halve
T halve(T val)
Definition PtexUtils.h:157
PtexUtils::copy
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition PtexUtils.cpp:438
PtexUtils::multalpha
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition PtexUtils.cpp:579
PtexUtils::interleave
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:189
PtexUtils::ApplyConstFn
void(* ApplyConstFn)(float weight, float *dst, void *data, int nChan)
Definition PtexUtils.h:277
PtexUtils::average
void average(const void *src, int sstride, int uw, int vw, void *dst, DataType dt, int nchan)
Definition PtexUtils.cpp:522
PtexUtils::applyConstFunctions
ApplyConstFn applyConstFunctions[20]
Definition PtexUtils.cpp:668
PtexHalf
Half-precision (16-bit) floating-point type.
Definition PtexHalf.h:72
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition Ptexture.h:229
Ptex::FaceInfo::res
Res res
Resolution of face.
Definition Ptexture.h:230
Ptex::FaceInfo::isConstant
bool isConstant() const
Determine if face is constant (by checking a flag).
Definition Ptexture.h:262
Ptex::Res::ulog2
int8_t ulog2
log base 2 of u resolution, in texels
Definition Ptexture.h:160
Ptex::Res::vlog2
int8_t vlog2
log base 2 of v resolution, in texels
Definition Ptexture.h:161