Ptex

PtexTriangleFilter.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 "PtexTriangleFilter.h"
41 #include "PtexTriangleKernel.h"
42 #include "PtexUtils.h"
43
44 namespace {
45 inline float squared(float x) { return x*x; }
46 }
47
48 PTEX_NAMESPACE_BEGIN
49
50 void PtexTriangleFilter::eval(float* result, int firstChan, int nChannels,
51 int faceid, float u, float v,
52 float uw1, float vw1, float uw2, float vw2,
53 float width, float blur)
54 {
55 // init
56 if (!_tx || nChannels <= 0) return;
57 if (faceid < 0 || faceid >= _tx->numFaces()) return;
58 _ntxchan = _tx->numChannels();
59 _dt = _tx->dataType();
60 _firstChanOffset = firstChan*DataSize(_dt);
61 _nchan = PtexUtils::min(nChannels, _ntxchan-firstChan);
62
63 // get face info
64 const FaceInfo& f = _tx->getFaceInfo(faceid);
65
66 // if neighborhood is constant, just return constant value of face
67 if (f.isNeighborhoodConstant()) {
68 PtexPtr<PtexFaceData> data ( _tx->getData(faceid, 0) );
69 if (data) {
70 char* d = (char*) data->getData() + _firstChanOffset;
71 Ptex::ConvertToFloat(result, d, _dt, _nchan);
72 }
73 return;
74 }
75
76 // clamp u and v
77 u = PtexUtils::clamp(u, 0.0f, 1.0f);
78 v = PtexUtils::clamp(v, 0.0f, 1.0f);
79
80 // build kernel
81 PtexTriangleKernel k;
82 buildKernel(k, u, v, uw1, vw1, uw2, vw2, width, blur, f.res);
83
84 // accumulate the weight as we apply
85 _weight = 0;
86
87 // allocate temporary result
88 _result = (float*) alloca(sizeof(float)*_nchan);
89 memset(_result, 0, sizeof(float)*_nchan);
90
91 // apply to faces
92 splitAndApply(k, faceid, f);
93
94 // normalize (both for data type and cumulative kernel weight applied)
95 // and output result
96 float scale = 1.0f / (_weight * OneValue(_dt));
97 for (int i = 0; i < _nchan; i++) result[i] = float(_result[i] * scale);
98
99 // clear temp result
100 _result = 0;
101 }
102
103
104
105 void PtexTriangleFilter::buildKernel(PtexTriangleKernel& k, float u, float v,
106 float uw1, float vw1, float uw2, float vw2,
107 float width, float blur, Res faceRes)
108 {
109 const float sqrt3 = 1.7320508075688772f;
110
111 // compute ellipse coefficients, A*u^2 + B*u*v + C*v^2 == AC - B^2/4
112 float scaleAC = 0.25f * width*width;
113 float scaleB = -2.0f * scaleAC;
114 float A = (vw1*vw1 + vw2*vw2) * scaleAC;
115 float B = (uw1*vw1 + uw2*vw2) * scaleB;
116 float C = (uw1*uw1 + uw2*uw2) * scaleAC;
117
118 // convert to cartesian domain
119 float Ac = 0.75f * A;
120 float Bc = float(sqrt3/2) * (B-A);
121 float Cc = 0.25f * A - 0.5f * B + C;
122
123 // compute min blur for eccentricity clamping
124 const float maxEcc = 15.0f; // max eccentricity
125 const float eccRatio = (maxEcc*maxEcc + 1.0f) / (maxEcc*maxEcc - 1.0f);
126 float X = sqrtf(squared(Ac - Cc) + squared(Bc));
127 float b_e = 0.5f * (eccRatio * X - (Ac + Cc));
128
129 // compute min blur for texel clamping
130 // (ensure that ellipse is no smaller than a texel)
131 float b_t = squared(0.5f / (float)faceRes.u());
132
133 // add blur
134 float b_b = 0.25f * blur * blur;
135 float b = PtexUtils::max(b_b, PtexUtils::max(b_e, b_t));
136 Ac += b;
137 Cc += b;
138
139 // compute minor radius
140 float m = sqrtf(2.0f*(Ac*Cc - 0.25f*Bc*Bc) / (Ac + Cc + X));
141
142 // choose desired resolution
143 int reslog2 = PtexUtils::max(0, PtexUtils::calcResFromWidth(2.0f*m));
144
145 // convert back to triangular domain
146 A = float(4/3.0) * Ac;
147 B = float(2/sqrt3) * Bc + A;
148 C = -0.25f * A + 0.5f * B + Cc;
149
150 // scale by kernel width
151 float scale = PtexTriangleKernelWidth * PtexTriangleKernelWidth;
152 A *= scale;
153 B *= scale;
154 C *= scale;
155
156 // find u,v,w extents
157 float uw = PtexUtils::min(sqrtf(C), 1.0f);
158 float vw = PtexUtils::min(sqrtf(A), 1.0f);
159 float ww = PtexUtils::min(sqrtf(A-B+C), 1.0f);
160
161 // init kernel
162 float w = 1.0f - u - v;
163 k.set(Res((int8_t)reslog2, (int8_t)reslog2), u, v, u-uw, v-vw, w-ww, u+uw, v+vw, w+ww, A, B, C);
164 }
165
166
167 void PtexTriangleFilter::splitAndApply(PtexTriangleKernel& k, int faceid, const Ptex::FaceInfo& f)
168 {
169 // do we need to split? if so, split kernel and apply across edge(s)
170 if (k.u1 < 0 && f.adjface(2) >= 0) {
171 PtexTriangleKernel ka;
172 k.splitU(ka);
173 applyAcrossEdge(ka, f, 2);
174 }
175 if (k.v1 < 0 && f.adjface(0) >= 0) {
176 PtexTriangleKernel ka;
177 k.splitV(ka);
178 applyAcrossEdge(ka, f, 0);
179 }
180 if (k.w1 < 0 && f.adjface(1) >= 0) {
181 PtexTriangleKernel ka;
182 k.splitW(ka);
183 applyAcrossEdge(ka, f, 1);
184 }
185 // apply to local face
186 apply(k, faceid, f);
187 }
188
189
190 void PtexTriangleFilter::applyAcrossEdge(PtexTriangleKernel& k,
191 const Ptex::FaceInfo& f, int eid)
192 {
193 int afid = f.adjface(eid), aeid = f.adjedge(eid);
194 const Ptex::FaceInfo& af = _tx->getFaceInfo(afid);
195 k.reorient(eid, aeid);
196 splitAndApply(k, afid, af);
197 }
198
199
200 void PtexTriangleFilter::apply(PtexTriangleKernel& k, int faceid, const Ptex::FaceInfo& f)
201 {
202 // clamp kernel face (resolution and extent)
203 k.clampRes(f.res);
204 k.clampExtent();
205
206 // build kernel iterators
207 PtexTriangleKernelIter keven, kodd;
208 k.getIterators(keven, kodd);
209 if (!keven.valid && !kodd.valid) return;
210
211 // get face data, and apply
212 PtexPtr<PtexFaceData> dh ( _tx->getData(faceid, k.res) );
213 if (!dh) return;
214
215 if (keven.valid) applyIter(keven, dh);
216 if (kodd.valid) applyIter(kodd, dh);
217 }
218
219
220 void PtexTriangleFilter::applyIter(PtexTriangleKernelIter& k, PtexFaceData* dh)
221 {
222 if (dh->isConstant()) {
223 k.applyConst(_result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan);
224 _weight += k.weight;
225 }
226 else if (dh->isTiled()) {
227 Ptex::Res tileres = dh->tileRes();
228 PtexTriangleKernelIter kt = k;
229 int tileresu = tileres.u();
230 int tileresv = tileres.v();
231 kt.rowlen = tileresu;
232 int ntilesu = k.rowlen / kt.rowlen;
233 int wOffsetBase = k.rowlen - tileresu;
234 for (int tilev = k.v1 / tileresv, tilevEnd = (k.v2-1) / tileresv; tilev <= tilevEnd; tilev++) {
235 int vOffset = tilev * tileresv;
236 kt.v = k.v - (float)vOffset;
237 kt.v1 = PtexUtils::max(0, k.v1 - vOffset);
238 kt.v2 = PtexUtils::min(k.v2 - vOffset, tileresv);
239 for (int tileu = k.u1 / tileresu, tileuEnd = (k.u2-1) / tileresu; tileu <= tileuEnd; tileu++) {
240 int uOffset = tileu * tileresu;
241 int wOffset = wOffsetBase - uOffset - vOffset;
242 kt.u = k.u - (float)uOffset;
243 kt.u1 = PtexUtils::max(0, k.u1 - uOffset);
244 kt.u2 = PtexUtils::min(k.u2 - uOffset, tileresu);
245 kt.w1 = k.w1 - wOffset;
246 kt.w2 = k.w2 - wOffset;
247 PtexPtr<PtexFaceData> th ( dh->getTile(tilev * ntilesu + tileu) );
248 if (th) {
249 kt.weight = 0;
250 if (th->isConstant())
251 kt.applyConst(_result, (char*)th->getData()+_firstChanOffset, _dt, _nchan);
252 else
253 kt.apply(_result, (char*)th->getData()+_firstChanOffset, _dt, _nchan, _ntxchan);
254 _weight += kt.weight;
255 }
256 }
257 }
258 }
259 else {
260 k.apply(_result, (char*)dh->getData()+_firstChanOffset, _dt, _nchan, _ntxchan);
261 _weight += k.weight;
262 }
263 }
264
265 PTEX_NAMESPACE_END
Ptex::Res::v
int v() const
V resolution in texels.
Definition: Ptexture.h:189
PtexTriangleFilter::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: PtexTriangleFilter.cpp:50
PtexTriangleFilter::apply
void apply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexTriangleFilter.cpp:200
PtexTexture::numChannels
virtual int numChannels()=0
Number of channels stored in file.
PtexTriangleFilter::_ntxchan
int _ntxchan
Definition: PtexTriangleFilter.h:77
PtexTriangleKernel::w1
float w1
Definition: PtexTriangleKernel.h:86
PtexTriangleKernelIter::applyConst
void applyConst(float *dst, void *data, DataType dt, int nChan)
Definition: PtexTriangleKernel.cpp:153
PtexTriangleKernelIter::rowlen
int rowlen
Definition: PtexTriangleKernel.h:56
PtexTriangleKernel::splitU
void splitU(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:116
PtexTriangleFilter::_tx
PtexTexture * _tx
Definition: PtexTriangleFilter.h:71
PtexTriangleKernel.h
PtexTriangleKernelIter::apply
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
Definition: PtexTriangleKernel.h:65
PtexUtils::calcResFromWidth
int calcResFromWidth(float w)
Definition: PtexUtils.h:102
PtexTriangleKernelIter::weight
float weight
Definition: PtexTriangleKernel.h:63
PtexTriangleKernel::splitV
void splitV(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:123
PtexTriangleFilter::_weight
float _weight
Definition: PtexTriangleFilter.h:74
PtexTriangleFilter::buildKernel
void buildKernel(PtexTriangleKernel &k, float u, float v, float uw1, float vw1, float uw2, float vw2, float width, float blur, Res faceRes)
Definition: PtexTriangleFilter.cpp:105
PtexTriangleKernel::reorient
void reorient(int eid, int aeid)
Definition: PtexTriangleKernel.h:151
PtexTriangleKernelIter::valid
bool valid
Definition: PtexTriangleKernel.h:61
PtexUtils::clamp
T clamp(T x, T lo, T hi)
Definition: PtexUtils.h:153
PtexTriangleKernelIter::v
float v
Definition: PtexTriangleKernel.h:57
PtexTriangleFilter.h
PtexTriangleKernelIter
Triangle filter kernel iterator (in texel coords)
Definition: PtexTriangleKernel.h:54
PtexTriangleKernel::clampExtent
void clampExtent()
Definition: PtexTriangleKernel.h:178
PtexTriangleFilter::splitAndApply
void splitAndApply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexTriangleFilter.cpp:167
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:147
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexTriangleKernel::v1
float v1
Definition: PtexTriangleKernel.h:86
C
#define C(eid, aeid)
PtexTriangleKernelIter::v2
int v2
Definition: PtexTriangleKernel.h:59
PtexTriangleKernelIter::u2
int u2
Definition: PtexTriangleKernel.h:59
PtexFaceData
Per-face texture data accessor.
Definition: Ptexture.h:419
PtexTriangleKernelIter::w2
int w2
Definition: PtexTriangleKernel.h:59
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
Ptex::FaceInfo::adjface
int adjface(int eid) const
Access an adjacent face id. The eid value must be 0..3.
Definition: Ptexture.h:272
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
PtexTriangleKernel::res
Res res
Definition: PtexTriangleKernel.h:84
PtexTexture::getData
virtual void getData(int faceid, void *buffer, int stride)=0
Access texture data for a face at highest-resolution.
PtexTriangleFilter::_result
float * _result
Definition: PtexTriangleFilter.h:73
Ptex::Res::u
int u() const
U resolution in texels.
Definition: Ptexture.h:186
PtexTriangleKernelIter::u1
int u1
Definition: PtexTriangleKernel.h:58
PtexTriangleKernelIter::w1
int w1
Definition: PtexTriangleKernel.h:58
PtexTexture::numFaces
virtual int numFaces()=0
Number of faces stored in file.
PtexTriangleKernel
Triangle filter kernel (in normalized triangle coords)
Definition: PtexTriangleKernel.h:82
PtexTriangleKernel::set
void set(Res resVal, float uVal, float vVal, float u1Val, float v1Val, float w1Val, float u2Val, float v2Val, float w2Val, float AVal, float BVal, float CVal)
Definition: PtexTriangleKernel.h:90
PtexUtils::max
T max(T a, T b)
Definition: PtexUtils.h:150
PtexTriangleKernelIter::u
float u
Definition: PtexTriangleKernel.h:57
PtexTriangleKernel::u1
float u1
Definition: PtexTriangleKernel.h:86
PtexTexture::dataType
virtual Ptex::DataType dataType()=0
Type of data stored in file.
PtexTriangleKernel::getIterators
void getIterators(PtexTriangleKernelIter &ke, PtexTriangleKernelIter &ko)
Definition: PtexTriangleKernel.h:188
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1045
PtexFaceData::isTiled
virtual bool isTiled()=0
True if this data block is tiled.
PtexTriangleKernelWidth
PTEX_NAMESPACE_BEGIN const float PtexTriangleKernelWidth
Definition: PtexTriangleKernel.h:50
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexTriangleFilter::_firstChanOffset
int _firstChanOffset
Definition: PtexTriangleFilter.h:75
Ptex::Res
Pixel resolution of a given texture.
Definition: Ptexture.h:172
PtexTriangleFilter::applyAcrossEdge
void applyAcrossEdge(PtexTriangleKernel &k, const Ptex::FaceInfo &f, int eid)
Definition: PtexTriangleFilter.cpp:190
PtexTriangleFilter::_nchan
int _nchan
Definition: PtexTriangleFilter.h:76
Ptex::DataSize
int DataSize(DataType dt)
Look up size of given data type (in bytes).
Definition: Ptexture.h:143
Ptex::FaceInfo::res
Res res
Resolution of face.
Definition: Ptexture.h:243
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:242
PtexTexture::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)=0
Access resolution and adjacency information about a face.
PtexTriangleKernel::clampRes
void clampRes(Res fres)
Definition: PtexTriangleKernel.h:172
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexUtils.h
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_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexTriangleKernelIter::v1
int v1
Definition: PtexTriangleKernel.h:58
PtexTriangleFilter::_dt
DataType _dt
Definition: PtexTriangleFilter.h:78
PtexTriangleFilter::applyIter
void applyIter(PtexTriangleKernelIter &k, PtexFaceData *dh)
Definition: PtexTriangleFilter.cpp:220
PtexTriangleKernel::splitW
void splitW(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:130
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::FaceInfo::adjedge
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
Definition: Ptexture.h:269
PtexFaceData::tileRes
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.