Ptex

PtexSeparableFilter.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 <cmath>
38 #include <assert.h>
39
40 #include "PtexSeparableFilter.h"
41 #include "PtexSeparableKernel.h"
42 #include "PtexUtils.h"
43
44
45 PTEX_NAMESPACE_BEGIN
46
47 void PtexSeparableFilter::eval(float* result, int firstChan, int nChannels,
48 int faceid, float u, float v,
49 float uw1, float vw1, float uw2, float vw2,
50 float width, float blur)
51 {
52 // init
53 if (!_tx || nChannels <= 0) return;
54 if (faceid < 0 || faceid >= _tx->numFaces()) return;
55 _firstChanOffset = firstChan*DataSize(_dt);
56 _nchan = PtexUtils::min(nChannels, _ntxchan-firstChan);
57
58 // get face info
59 const FaceInfo& f = _tx->getFaceInfo(faceid);
60
61 // if neighborhood is constant, just return constant value of face
62 if (f.isNeighborhoodConstant()) {
63 PtexPtr<PtexFaceData> data ( _tx->getData(faceid, 0) );
64 if (data) {
65 char* d = (char*) data->getData() + _firstChanOffset;
66 Ptex::ConvertToFloat(result, d, _dt, _nchan);
67 }
68 return;
69 }
70
71 // find filter width as bounding box of vectors w1 and w2
72 float uw = PtexUtils::abs(uw1) + PtexUtils::abs(uw2), vw = PtexUtils::abs(vw1) + PtexUtils::abs(vw2);
73
74 // handle border modes
75 bool return_black = false;
76
77 switch (_uMode) {
78 case m_clamp: u = PtexUtils::clamp(u, 0.0f, 1.0f); break;
79 case m_periodic: u = u-PtexUtils::floor(u); break;
80 case m_black: if (u <= -1.0f || u >= 2.0f) return_black = true; break;
81 }
82
83 switch (_vMode) {
84 case m_clamp: v = PtexUtils::clamp(v, 0.0f, 1.0f); break;
85 case m_periodic: v = v-PtexUtils::floor(v); break;
86 case m_black: if (v <= -1.0f || v >= 2.0f) return_black = true; break;
87 }
88
89 if (return_black) {
90 memset(result, 0, sizeof(float)*_nchan);
91 return;
92 }
93
94 // build kernel
95 PtexSeparableKernel k;
96 if (f.isSubface()) {
97 // for a subface, build the kernel as if it were on a main face and then downres
98 uw = uw * width + blur * 2.0f;
99 vw = vw * width + blur * 2.0f;
100 buildKernel(k, u*.5f, v*.5f, uw*.5f, vw*.5f,
101 Ptex::Res((int8_t)(f.res.ulog2+1),(int8_t)(f.res.vlog2+1)));
102 if (k.res.ulog2 == 0) k.upresU();
103 if (k.res.vlog2 == 0) k.upresV();
104 k.res.ulog2--; k.res.vlog2--;
105 }
106 else {
107 uw = uw * width + blur;
108 vw = vw * width + blur;
109 buildKernel(k, u, v, uw, vw, f.res);
110 }
111 k.stripZeros();
112
113 // check kernel (debug only)
114 assert(k.uw > 0 && k.vw > 0);
115 assert(k.uw <= PtexSeparableKernel::kmax && k.vw <= PtexSeparableKernel::kmax);
116 _weight = k.weight();
117
118 // allocate temporary result
119 _result = (float*) alloca(sizeof(float)*_nchan);
120 memset(_result, 0, sizeof(float)*_nchan);
121
122 // apply to faces
123 splitAndApply(k, faceid, f);
124
125 // normalize (both for data type and cumulative kernel weight applied)
126 // and output result
127 float scale = 1.0f / (_weight * OneValue(_dt));
128 for (int i = 0; i < _nchan; i++) result[i] = float(_result[i] * scale);
129
130 // clear temp result
131 _result = 0;
132 }
133
134
135 void PtexSeparableFilter::splitAndApply(PtexSeparableKernel& k, int faceid, const Ptex::FaceInfo& f)
136 {
137 // do we need to split? (i.e. does kernel span an edge?)
138 bool splitR = (k.u+k.uw > k.res.u()), splitL = (k.u < 0);
139 bool splitT = (k.v+k.vw > k.res.v()), splitB = (k.v < 0);
140
141 if (_options.noedgeblend) {
142 if (splitR) k.mergeR(_uMode);
143 if (splitL) k.mergeL(_uMode);
144 if (splitT) k.mergeT(_vMode);
145 if (splitB) k.mergeB(_vMode);
146 apply(k, faceid, f);
147 return;
148 }
149
150 if (splitR || splitL || splitT || splitB) {
151 PtexSeparableKernel ka, kc;
152 if (splitR) {
153 if (f.adjface(e_right) >= 0) {
154 k.splitR(ka);
155 if (splitT) {
156 if (f.adjface(e_top) >= 0) {
157 ka.splitT(kc);
158 applyToCorner(kc, faceid, f, e_top);
159 }
160 else ka.mergeT(_vMode);
161 }
162 if (splitB) {
163 if (f.adjface(e_bottom) >= 0) {
164 ka.splitB(kc);
165 applyToCorner(kc, faceid, f, e_right);
166 }
167 else ka.mergeB(_vMode);
168 }
169 applyAcrossEdge(ka, faceid, f, e_right);
170 }
171 else k.mergeR(_uMode);
172 }
173 if (splitL) {
174 if (f.adjface(e_left) >= 0) {
175 k.splitL(ka);
176 if (splitT) {
177 if (f.adjface(e_top) >= 0) {
178 ka.splitT(kc);
179 applyToCorner(kc, faceid, f, e_left);
180 }
181 else ka.mergeT(_vMode);
182 }
183 if (splitB) {
184 if (f.adjface(e_bottom) >= 0) {
185 ka.splitB(kc);
186 applyToCorner(kc, faceid, f, e_bottom);
187 }
188 else ka.mergeB(_vMode);
189 }
190 applyAcrossEdge(ka, faceid, f, e_left);
191 }
192 else k.mergeL(_uMode);
193 }
194 if (splitT) {
195 if (f.adjface(e_top) >= 0) {
196 k.splitT(ka);
197 applyAcrossEdge(ka, faceid, f, e_top);
198 }
199 else k.mergeT(_vMode);
200 }
201 if (splitB) {
202 if (f.adjface(e_bottom) >= 0) {
203 k.splitB(ka);
204 applyAcrossEdge(ka, faceid, f, e_bottom);
205 }
206 else k.mergeB(_vMode);
207 }
208 }
209
210 // do local face
211 apply(k, faceid, f);
212 }
213
214
215 void PtexSeparableFilter::applyAcrossEdge(PtexSeparableKernel& k,
216 int faceid, const Ptex::FaceInfo& f, int eid)
217 {
218 int afid = f.adjface(eid), aeid = f.adjedge(eid);
219 const Ptex::FaceInfo* af = &_tx->getFaceInfo(afid);
220 int rot = eid - aeid + 2;
221
222 // adjust uv coord and res for face/subface boundary
223 bool fIsSubface = f.isSubface(), afIsSubface = af->isSubface();
224 if (fIsSubface != afIsSubface) {
225 if (afIsSubface) {
226 // main face to subface transition
227 // adjust res and offset uv coord for primary subface
228 bool primary = k.adjustMainToSubface(eid);
229 if (!primary) {
230 // advance ajacent face and edge id to secondary subface
231 int neid = (aeid + 3) % 4;
232 afid = af->adjface(neid);
233 aeid = af->adjedge(neid);
234 af = &_tx->getFaceInfo(afid);
235 rot += neid - aeid + 2;
236 }
237 }
238 else {
239 // subface to main face transition
240 // Note: the transform depends on which subface the kernel is
241 // coming from. The "primary" subface is the one the main
242 // face is pointing at. The secondary subface adjustment
243 // happens to be the same as for the primary subface for the
244 // next edge, so the cases can be combined.
245 bool primary = (af->adjface(aeid) == faceid);
246 k.adjustSubfaceToMain(eid - primary);
247 }
248 }
249
250 // rotate and apply (resplit if going to a subface)
251 k.rotate(rot);
252 if (afIsSubface) splitAndApply(k, afid, *af);
253 else apply(k, afid, *af);
254 }
255
256
257 void PtexSeparableFilter::applyToCorner(PtexSeparableKernel& k, int faceid,
258 const Ptex::FaceInfo& f, int eid)
259 {
260 // traverse clockwise around corner vertex and gather corner faces
261 int afid = faceid, aeid = eid;
262 const FaceInfo* af = &f;
263 bool prevIsSubface = af->isSubface();
264
265 const int MaxValence = 10;
266 int cfaceId[MaxValence];
267 int cedgeId[MaxValence];
268 const FaceInfo* cface[MaxValence];
269
270 int numCorners = 0;
271 for (int i = 0; i < MaxValence; i++) {
272 // advance to next face
273 int prevFace = afid;
274 afid = af->adjface(aeid);
275 aeid = (af->adjedge(aeid) + 1) % 4;
276
277 // we hit a boundary or reached starting face
278 // note: we need to check edge id too because we might have
279 // a periodic texture (w/ toroidal topology) where all 4 corners
280 // are from the same face
281 if (afid < 0 || (afid == faceid && aeid == eid)) {
282 numCorners = i - 2;
283 break;
284 }
285
286 // record face info
287 af = &_tx->getFaceInfo(afid);
288 cfaceId[i] = afid;
289 cedgeId[i] = aeid;
290 cface[i] = af;
291
292 // check to see if corner is a subface "tee"
293 bool isSubface = af->isSubface();
294 if (prevIsSubface && !isSubface && af->adjface((aeid+3)%4) == prevFace)
295 {
296 // adjust the eid depending on whether we started from
297 // the primary or secondary subface.
298 bool primary = (i==1);
299 k.adjustSubfaceToMain(eid + primary * 2);
300 k.rotate(eid - aeid + 3 - primary);
301 splitAndApply(k, afid, *af);
302 return;
303 }
304 prevIsSubface = isSubface;
305 }
306
307 if (numCorners == 1) {
308 // regular case (valence 4)
309 applyToCornerFace(k, f, eid, cfaceId[1], *cface[1], cedgeId[1]);
310 }
311 else if (numCorners > 1) {
312 // valence 5+, make kernel symmetric and apply equally to each face
313 // first, rotate to standard orientation, u=v=0
314 k.rotate(eid + 2);
315 float initialWeight = k.weight();
316 float newWeight = k.makeSymmetric(initialWeight);
317 for (int i = 1; i <= numCorners; i++) {
318 PtexSeparableKernel kc = k;
319 applyToCornerFace(kc, f, 2, cfaceId[i], *cface[i], cedgeId[i]);
320 }
321 // adjust weight for symmetrification and for additional corners
322 _weight += newWeight * (float)numCorners - initialWeight;
323 }
324 else {
325 // valence 2 or 3, ignore corner face (just adjust weight)
326 _weight -= k.weight();
327 }
328 }
329
330
331 void PtexSeparableFilter::applyToCornerFace(PtexSeparableKernel& k, const Ptex::FaceInfo& f, int eid,
332 int cfid, const Ptex::FaceInfo& cf, int ceid)
333 {
334 // adjust uv coord and res for face/subface boundary
335 bool fIsSubface = f.isSubface(), cfIsSubface = cf.isSubface();
336 if (fIsSubface != cfIsSubface) {
337 if (cfIsSubface) k.adjustMainToSubface(eid + 3);
338 else k.adjustSubfaceToMain(eid + 3);
339 }
340
341 // rotate and apply (resplit if going to a subface)
342 k.rotate(eid - ceid + 2);
343 if (cfIsSubface) splitAndApply(k, cfid, cf);
344 else apply(k, cfid, cf);
345 }
346
347
348 void PtexSeparableFilter::apply(PtexSeparableKernel& k, int faceid, const Ptex::FaceInfo& f)
349 {
350 assert(k.u >= 0 && k.u + k.uw <= k.res.u());
351 assert(k.v >= 0 && k.v + k.vw <= k.res.v());
352
353 if (k.uw <= 0 || k.vw <= 0) return;
354
355 // downres kernel if needed
356 while (k.res.u() > f.res.u()) k.downresU();
357 while (k.res.v() > f.res.v()) k.downresV();
358
359 // get face data, and apply
360 PtexPtr<PtexFaceData> dh ( _tx->getData(faceid, k.res) );
361 if (!dh) return;
362
363 if (dh->isConstant()) {
364 k.applyConst(_result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan);
365 return;
366 }
367
368 // allocate temporary result for tanvec mode (if needed)
369 bool tanvecMode = (_efm == efm_tanvec) && (_nchan >= 2) && (k.rot > 0);
370 float* result = tanvecMode ? (float*) alloca(sizeof(float)*_nchan) : _result;
371 if (tanvecMode) memset(result, 0, sizeof(float)*_nchan);
372
373 if (dh->isTiled()) {
374 Ptex::Res tileres = dh->tileRes();
375 PtexSeparableKernel kt;
376 kt.res = tileres;
377 int tileresu = tileres.u();
378 int tileresv = tileres.v();
379 int ntilesu = k.res.u() / tileresu;
380 for (int v = k.v, vw = k.vw; vw > 0; vw -= kt.vw, v += kt.vw) {
381 int tilev = v / tileresv;
382 kt.v = v % tileresv;
383 kt.vw = PtexUtils::min(vw, tileresv - kt.v);
384 kt.kv = k.kv + v - k.v;
385 for (int u = k.u, uw = k.uw; uw > 0; uw -= kt.uw, u += kt.uw) {
386 int tileu = u / tileresu;
387 kt.u = u % tileresu;
388 kt.uw = PtexUtils::min(uw, tileresu - kt.u);
389 kt.ku = k.ku + u - k.u;
390 PtexPtr<PtexFaceData> th ( dh->getTile(tilev * ntilesu + tileu) );
391 if (th) {
392 if (th->isConstant())
393 kt.applyConst(result, (char*)th->getData()+_firstChanOffset, _dt, _nchan);
394 else
395 kt.apply(result, (char*)th->getData()+_firstChanOffset, _dt, _nchan, _ntxchan);
396 }
397 }
398 }
399 }
400 else {
401 k.apply(result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan, _ntxchan);
402 }
403
404 if (tanvecMode) {
405 // rotate tangent-space vector data and update main result
406 switch (k.rot) {
407 case 0: // rot==0 included for completeness, but tanvecMode should be false in this case
408 _result[0] += result[0];
409 _result[1] += result[1];
410 break;
411 case 1:
412 _result[0] -= result[1];
413 _result[1] += result[0];
414 break;
415 case 2:
416 _result[0] -= result[0];
417 _result[1] -= result[1];
418 break;
419 case 3:
420 _result[0] += result[1];
421 _result[1] -= result[0];
422 break;
423 }
424 for (int i = 2; i < _nchan; i++) _result[i] += result[i];
425 }
426 }
427
428 PTEX_NAMESPACE_END
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexSeparableFilter.h
PtexSeparableKernel.h
PtexUtils.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1032
PtexSeparableFilter::splitAndApply
void splitAndApply(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexSeparableFilter.cpp:135
PtexSeparableFilter::applyToCornerFace
void applyToCornerFace(PtexSeparableKernel &k, const Ptex::FaceInfo &f, int eid, int cfaceid, const Ptex::FaceInfo &cf, int ceid)
Definition: PtexSeparableFilter.cpp:331
PtexSeparableFilter::eval
virtual void eval(float *result, int firstchan, int nchannels, int faceid, float u, float v, float uw1, float vw1, float uw2, float vw2, float width, float blur)
Apply filter to a ptex data file.
Definition: PtexSeparableFilter.cpp:47
PtexSeparableFilter::apply
void apply(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexSeparableFilter.cpp:348
PtexSeparableFilter::applyAcrossEdge
void applyAcrossEdge(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f, int eid)
Definition: PtexSeparableFilter.cpp:215
PtexSeparableFilter::_result
float * _result
Definition: PtexSeparableFilter.h:80
PtexSeparableFilter::_tx
PtexTexture * _tx
Definition: PtexSeparableFilter.h:78
PtexSeparableFilter::_options
Options _options
Definition: PtexSeparableFilter.h:79
PtexSeparableFilter::_uMode
BorderMode _uMode
Definition: PtexSeparableFilter.h:86
PtexSeparableFilter::applyToCorner
void applyToCorner(PtexSeparableKernel &k, int faceid, const Ptex::FaceInfo &f, int eid)
Definition: PtexSeparableFilter.cpp:257
PtexSeparableFilter::_ntxchan
int _ntxchan
Definition: PtexSeparableFilter.h:84
PtexSeparableFilter::_weight
float _weight
Definition: PtexSeparableFilter.h:81
PtexSeparableFilter::_firstChanOffset
int _firstChanOffset
Definition: PtexSeparableFilter.h:82
PtexSeparableFilter::_efm
EdgeFilterMode _efm
Definition: PtexSeparableFilter.h:87
PtexSeparableFilter::_dt
DataType _dt
Definition: PtexSeparableFilter.h:85
PtexSeparableFilter::_vMode
BorderMode _vMode
Definition: PtexSeparableFilter.h:86
PtexSeparableFilter::buildKernel
virtual void buildKernel(PtexSeparableKernel &k, float u, float v, float uw, float vw, Res faceRes)=0
PtexSeparableFilter::_nchan
int _nchan
Definition: PtexSeparableFilter.h:83
PtexSeparableKernel
Definition: PtexSeparableKernel.h:48
PtexSeparableKernel::mergeT
void mergeT(BorderMode mode)
Definition: PtexSeparableKernel.h:139
PtexSeparableKernel::mergeB
void mergeB(BorderMode mode)
Definition: PtexSeparableKernel.h:129
PtexSeparableKernel::stripZeros
void stripZeros()
Definition: PtexSeparableKernel.h:96
PtexSeparableKernel::apply
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
Definition: PtexSeparableKernel.h:457
PtexSeparableKernel::makeSymmetric
float makeSymmetric(float initialWeight)
Definition: PtexSeparableKernel.h:397
PtexSeparableKernel::u
int u
Definition: PtexSeparableKernel.h:51
PtexSeparableKernel::kv
float * kv
Definition: PtexSeparableKernel.h:54
PtexSeparableKernel::splitT
void splitT(PtexSeparableKernel &k)
Definition: PtexSeparableKernel.h:214
PtexSeparableKernel::rot
int rot
Definition: PtexSeparableKernel.h:58
PtexSeparableKernel::res
Res res
Definition: PtexSeparableKernel.h:50
PtexSeparableKernel::adjustSubfaceToMain
void adjustSubfaceToMain(int eid)
Definition: PtexSeparableKernel.h:302
PtexSeparableKernel::splitB
void splitB(PtexSeparableKernel &k)
Definition: PtexSeparableKernel.h:192
PtexSeparableKernel::vw
int vw
Definition: PtexSeparableKernel.h:52
PtexSeparableKernel::v
int v
Definition: PtexSeparableKernel.h:51
PtexSeparableKernel::splitL
void splitL(PtexSeparableKernel &k)
Definition: PtexSeparableKernel.h:148
PtexSeparableKernel::downresV
void downresV()
Definition: PtexSeparableKernel.h:342
PtexSeparableKernel::ku
float * ku
Definition: PtexSeparableKernel.h:53
PtexSeparableKernel::uw
int uw
Definition: PtexSeparableKernel.h:52
PtexSeparableKernel::mergeR
void mergeR(BorderMode mode)
Definition: PtexSeparableKernel.h:120
PtexSeparableKernel::applyConst
void applyConst(float *dst, void *data, DataType dt, int nChan)
Definition: PtexSeparableKernel.h:464
PtexSeparableKernel::adjustMainToSubface
bool adjustMainToSubface(int eid)
Definition: PtexSeparableKernel.h:266
PtexSeparableKernel::mergeL
void mergeL(BorderMode mode)
Definition: PtexSeparableKernel.h:110
PtexSeparableKernel::upresV
void upresV()
Definition: PtexSeparableKernel.h:384
PtexSeparableKernel::upresU
void upresU()
Definition: PtexSeparableKernel.h:371
PtexSeparableKernel::splitR
void splitR(PtexSeparableKernel &k)
Definition: PtexSeparableKernel.h:171
PtexSeparableKernel::kmax
static const int kmax
Definition: PtexSeparableKernel.h:55
PtexSeparableKernel::rotate
void rotate(int rotVal)
Definition: PtexSeparableKernel.h:254
PtexSeparableKernel::weight
float weight() const
Definition: PtexSeparableKernel.h:105
PtexSeparableKernel::downresU
void downresU()
Definition: PtexSeparableKernel.h:313
PtexTexture::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)=0
Access resolution and adjacency information about a face.
PtexTexture::getData
virtual void getData(int faceid, void *buffer, int stride)=0
Access texture data for a face at highest-resolution.
PtexTexture::numFaces
virtual int numFaces()=0
Number of faces stored in file.
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexUtils::clamp
T clamp(T x, T lo, T hi)
Definition: PtexUtils.h:154
PtexUtils::abs
T abs(T x)
Definition: PtexUtils.h:134
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:148
Ptex::DataSize
int DataSize(DataType dt)
Look up size of given data type (in bytes).
Definition: Ptexture.h:130
Ptex::e_right
@ e_right
Right edge, from UV (1,0) to (1,1)
Definition: Ptexture.h:96
Ptex::e_top
@ e_top
Top edge, from UV (1,1) to (0,1)
Definition: Ptexture.h:97
Ptex::e_left
@ e_left
Left edge, from UV (0,1) to (0,0)
Definition: Ptexture.h:98
Ptex::e_bottom
@ e_bottom
Bottom edge, from UV (0,0) to (1,0)
Definition: Ptexture.h:95
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:136
Ptex::m_black
@ m_black
texel beyond border are assumed to be black
Definition: Ptexture.h:88
Ptex::m_clamp
@ m_clamp
texel access is clamped to border
Definition: Ptexture.h:87
Ptex::m_periodic
@ m_periodic
texel access wraps to other side of face
Definition: Ptexture.h:89
Ptex::ConvertToFloat
void ConvertToFloat(float *dst, const void *src, Ptex::DataType dt, int numChannels)
Convert a number of data values from the given data type to float.
Ptex::efm_tanvec
@ efm_tanvec
Values are vectors in tangent space; rotate values.
Definition: Ptexture.h:82
PtexFilter::Options::noedgeblend
bool noedgeblend
Disable cross-face filtering. Useful for debugging or rendering on polys.
Definition: Ptexture.h:961
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:229
Ptex::FaceInfo::isSubface
bool isSubface() const
Determine if face is a subface (by checking a flag).
Definition: Ptexture.h:271
Ptex::FaceInfo::res
Res res
Resolution of face.
Definition: Ptexture.h:230
Ptex::FaceInfo::adjedge
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
Definition: Ptexture.h:256
Ptex::FaceInfo::adjface
int adjface(int eid) const
Access an adjacent face id. The eid value must be 0..3.
Definition: Ptexture.h:259
Ptex::Res
Pixel resolution of a given texture.
Definition: Ptexture.h:159
Ptex::Res::v
int v() const
V resolution in texels.
Definition: Ptexture.h:176
Ptex::Res::u
int u() const
U resolution in texels.
Definition: Ptexture.h:173