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
46 PTEX_NAMESPACE_BEGIN
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
74 const char* EdgeFilterModeName(EdgeFilterMode m)
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
92 const char* MetaDataTypeName(MetaDataType mdt)
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
661 ApplyConstFn
662 applyConstFunctions[20] = {
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
694 PTEX_NAMESPACE_END
PtexUtils::halve
T halve(T val)
Definition: PtexUtils.h:156
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:147
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
MeshTypeName
const PTEX_NAMESPACE_BEGIN char * MeshTypeName(MeshType mt)
Definition: PtexUtils.cpp:48
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:308
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