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 if (mt < 0 || mt >= int(sizeof(names)/sizeof(const char*)))
52 return "(invalid mesh type)";
53 return names[mt];
54}
55
56
57const 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
66const 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
74const 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
83const 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
92const 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
101namespace {
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
117void 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
128void 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
139namespace PtexUtils {
140
141bool 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
160namespace {
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
183void 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
197namespace {
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
220void 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
235namespace {
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
245void 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
255namespace {
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
265void 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
275namespace {
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
293void 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
309namespace {
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
327void 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
343namespace {
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
360void 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
377namespace {
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
400void 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
416void 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
432void 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
452namespace {
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
474void 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
498namespace {
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
516void 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
532namespace {
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
548namespace {
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
573void 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
585namespace {
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
612void 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
624void 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
643namespace {
644 // apply to 1..4 channels, unrolled
645 template<class T, int nChan>
646 void ApplyConst(float weight, float* dst, void* data, int /*nChan*/)
647 {
648 // dst[i] += data[i] * weight for i in {0..n-1}
649 VecAccum<T,nChan>()(dst, static_cast<T*>(data), weight);
650 }
651
652 // apply to N channels (general case)
653 template<class T>
654 void ApplyConstN(float weight, float* dst, void* data, int nChan)
655 {
656 // dst[i] += data[i] * weight for i in {0..n-1}
657 VecAccumN<T>()(dst, static_cast<T*>(data), nChan, weight);
658 }
659}
660
663 ApplyConstN<uint8_t>, ApplyConstN<uint16_t>, ApplyConstN<PtexHalf>, ApplyConstN<float>,
664 ApplyConst<uint8_t,1>, ApplyConst<uint16_t,1>, ApplyConst<PtexHalf,1>, ApplyConst<float,1>,
665 ApplyConst<uint8_t,2>, ApplyConst<uint16_t,2>, ApplyConst<PtexHalf,2>, ApplyConst<float,2>,
666 ApplyConst<uint8_t,3>, ApplyConst<uint16_t,3>, ApplyConst<PtexHalf,3>, ApplyConst<float,3>,
667 ApplyConst<uint8_t,4>, ApplyConst<uint16_t,4>, ApplyConst<PtexHalf,4>, ApplyConst<float,4>,
668};
669
670} // namespace PtexUtils end
671
672#ifndef PTEX_USE_STDSTRING
673String::~String()
674{
675 if (_str) free(_str);
676}
677
678
679String& String::operator=(const char* str)
680{
681 if (_str) free(_str);
682 _str = str ? strdup(str) : 0;
683 return *this;
684}
685
686std::ostream& operator << (std::ostream& stream, const String& str)
687{
688 stream << str.c_str();
689 return stream;
690}
691
692#endif
693
Half-precision floating-point type.
Platform-specific classes, functions, and includes.
const FaceInfo * faces
Definition: PtexUtils.cpp:534
const char * EdgeFilterModeName(EdgeFilterMode m)
Definition: PtexUtils.cpp:74
void ConvertFromFloat(void *dst, const float *src, DataType dt, int numChannels)
Definition: PtexUtils.cpp:128
const char * MetaDataTypeName(MetaDataType mdt)
Definition: PtexUtils.cpp:92
const char * BorderModeName(BorderMode m)
Definition: PtexUtils.cpp:66
const char * EdgeIdName(EdgeId eid)
Definition: PtexUtils.cpp:83
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:117
std::ostream & operator<<(std::ostream &stream, const String &str)
Definition: PtexUtils.cpp:686
const char * DataTypeName(DataType dt)
Definition: PtexUtils.cpp:57
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
Memory-managed string.
Definition: Ptexture.h:309
T clamp(T x, T lo, T hi)
Definition: PtexUtils.h:153
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:624
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:327
bool isConstant(const void *data, int stride, int ures, int vres, int pixelSize)
Definition: PtexUtils.cpp:141
T min(T a, T b)
Definition: PtexUtils.h:147
void divalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:612
void encodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:245
void reduce(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:293
void deinterleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:220
T quarter(T val)
Definition: PtexUtils.h:162
void blend(const void *src, float weight, void *dst, bool flip, int rowlen, DataType dt, int nchan)
Definition: PtexUtils.cpp:474
void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:265
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:360
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:416
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:400
T halve(T val)
Definition: PtexUtils.h:156
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition: PtexUtils.cpp:432
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:573
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:183
void(* ApplyConstFn)(float weight, float *dst, void *data, int nChan)
Definition: PtexUtils.h:244
void average(const void *src, int sstride, int uw, int vw, void *dst, DataType dt, int nchan)
Definition: PtexUtils.cpp:516
ApplyConstFn applyConstFunctions[20]
Definition: PtexUtils.cpp:662
Half-precision (16-bit) floating-point type.
Definition: PtexHalf.h:88
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:242
Res res
Resolution of face.
Definition: Ptexture.h:243
bool isConstant() const
Determine if face is constant (by checking a flag).
Definition: Ptexture.h:275
int8_t ulog2
log base 2 of u resolution, in texels
Definition: Ptexture.h:173
int8_t vlog2
log base 2 of v resolution, in texels
Definition: Ptexture.h:174