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 
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;
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
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 
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
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 
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) {
172  k.splitU(ka);
173  applyAcrossEdge(ka, f, 2);
174  }
175  if (k.v1 < 0 && f.adjface(0) >= 0) {
177  k.splitV(ka);
178  applyAcrossEdge(ka, f, 0);
179  }
180  if (k.w1 < 0 && f.adjface(1) >= 0) {
182  k.splitW(ka);
183  applyAcrossEdge(ka, f, 1);
184  }
185  // apply to local face
186  apply(k, faceid, f);
187 }
188 
189 
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 
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 
221 {
222  if (dh->isConstant()) {
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 {
261  _weight += k.weight;
262  }
263 }
264 
PtexTriangleFilter::_result
float * _result
Definition: PtexTriangleFilter.h:73
PtexTriangleKernel::clampExtent
void clampExtent()
Definition: PtexTriangleKernel.h:178
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
Ptex::Res
Pixel resolution of a given texture.
Definition: Ptexture.h:172
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:147
PtexFaceData::isTiled
virtual bool isTiled()=0
True if this data block is tiled.
PtexTriangleKernelIter::apply
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
Definition: PtexTriangleKernel.h:65
PtexTriangleKernel::splitU
void splitU(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:116
PtexUtils::clamp
T clamp(T x, T lo, T hi)
Definition: PtexUtils.h:153
PtexTexture::numChannels
virtual int numChannels()=0
Number of channels stored in file.
PtexTriangleKernelIter::weight
float weight
Definition: PtexTriangleKernel.h:63
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexTriangleKernelIter::v2
int v2
Definition: PtexTriangleKernel.h:59
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexFaceData::tileRes
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.
PtexTriangleFilter::_ntxchan
int _ntxchan
Definition: PtexTriangleFilter.h:77
PtexUtils.h
Ptex::DataSize
int DataSize(DataType dt)
Look up size of given data type (in bytes).
Definition: Ptexture.h:143
PtexTriangleFilter::applyAcrossEdge
void applyAcrossEdge(PtexTriangleKernel &k, const Ptex::FaceInfo &f, int eid)
Definition: PtexTriangleFilter.cpp:190
PtexTriangleKernelWidth
PTEX_NAMESPACE_BEGIN const float PtexTriangleKernelWidth
Definition: PtexTriangleKernel.h:50
Ptex::FaceInfo::adjface
int adjface(int eid) const
Access an adjacent face id. The eid value must be 0..3.
Definition: Ptexture.h:272
PtexTriangleKernelIter::applyConst
void applyConst(float *dst, void *data, DataType dt, int nChan)
Definition: PtexTriangleKernel.cpp:153
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:242
PtexTriangleFilter::_weight
float _weight
Definition: PtexTriangleFilter.h:74
PtexTriangleFilter::applyIter
void applyIter(PtexTriangleKernelIter &k, PtexFaceData *dh)
Definition: PtexTriangleFilter.cpp:220
PtexTriangleKernel
Triangle filter kernel (in normalized triangle coords)
Definition: PtexTriangleKernel.h:82
PtexTexture::numFaces
virtual int numFaces()=0
Number of faces stored in file.
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
PtexTexture::getData
virtual void getData(int faceid, void *buffer, int stride)=0
Access texture data for a face at highest-resolution.
PtexTriangleFilter::_dt
DataType _dt
Definition: PtexTriangleFilter.h:78
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexTriangleKernelIter::u1
int u1
Definition: PtexTriangleKernel.h:58
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.
PtexTriangleKernelIter::rowlen
int rowlen
Definition: PtexTriangleKernel.h:56
PtexTriangleKernelIter::u
float u
Definition: PtexTriangleKernel.h:57
PtexTriangleFilter::apply
void apply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexTriangleFilter.cpp:200
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
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
PtexFaceData
Per-face texture data accessor.
Definition: Ptexture.h:419
PtexTriangleFilter::_nchan
int _nchan
Definition: PtexTriangleFilter.h:76
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1045
PtexTriangleKernel::res
Res res
Definition: PtexTriangleKernel.h:84
PtexTriangleKernelIter::u2
int u2
Definition: PtexTriangleKernel.h:59
PtexTriangleKernel::splitW
void splitW(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:130
PtexTriangleKernelIter
Triangle filter kernel iterator (in texel coords)
Definition: PtexTriangleKernel.h:54
PtexUtils::calcResFromWidth
int calcResFromWidth(float w)
Definition: PtexUtils.h:102
PtexTriangleKernelIter::v
float v
Definition: PtexTriangleKernel.h:57
PtexTriangleKernelIter::w1
int w1
Definition: PtexTriangleKernel.h:58
Ptex::Res::u
int u() const
U resolution in texels.
Definition: Ptexture.h:186
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
PtexUtils::max
T max(T a, T b)
Definition: PtexUtils.h:150
PtexTriangleKernel::v1
float v1
Definition: PtexTriangleKernel.h:86
PtexTriangleKernelIter::v1
int v1
Definition: PtexTriangleKernel.h:58
PtexTexture::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)=0
Access resolution and adjacency information about a face.
PtexTriangleKernel::u1
float u1
Definition: PtexTriangleKernel.h:86
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
C
#define C(eid, aeid)
PtexTriangleFilter::splitAndApply
void splitAndApply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexTriangleFilter.cpp:167
Ptex::Res::v
int v() const
V resolution in texels.
Definition: Ptexture.h:189
PtexTriangleKernelIter::w2
int w2
Definition: PtexTriangleKernel.h:59
Ptex::FaceInfo::adjedge
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
Definition: Ptexture.h:269
PtexTriangleKernel::getIterators
void getIterators(PtexTriangleKernelIter &ke, PtexTriangleKernelIter &ko)
Definition: PtexTriangleKernel.h:188
PtexTexture::dataType
virtual Ptex::DataType dataType()=0
Type of data stored in file.
PtexTriangleKernel::w1
float w1
Definition: PtexTriangleKernel.h:86
Ptex::FaceInfo::res
Res res
Resolution of face.
Definition: Ptexture.h:243
PtexTriangleFilter::_tx
PtexTexture * _tx
Definition: PtexTriangleFilter.h:71
PtexTriangleFilter::_firstChanOffset
int _firstChanOffset
Definition: PtexTriangleFilter.h:75
PtexTriangleKernel.h
PtexTriangleKernel::clampRes
void clampRes(Res fres)
Definition: PtexTriangleKernel.h:172
PtexTriangleKernel::splitV
void splitV(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:123
PtexTriangleKernel::reorient
void reorient(int eid, int aeid)
Definition: PtexTriangleKernel.h:151
PtexTriangleFilter.h
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexTriangleKernelIter::valid
bool valid
Definition: PtexTriangleKernel.h:61