Ptex: PtexTriangleFilter.cpp Source File

Ptex

PtexTriangleFilter.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 <cmath>
38#include <assert.h>
39
40#include "PtexTriangleFilter.h"
41#include "PtexTriangleKernel.h"
42#include "PtexUtils.h"
43
44namespace {
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
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexTriangleFilter.h
PtexTriangleKernel.h
C
#define C(eid, aeid)
PtexTriangleKernelWidth
PTEX_NAMESPACE_BEGIN const float PtexTriangleKernelWidth
Definition: PtexTriangleKernel.h:50
PtexUtils.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexFaceData
Per-face texture data accessor.
Definition: Ptexture.h:406
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
PtexFaceData::isTiled
virtual bool isTiled()=0
True if this data block is tiled.
PtexFaceData::tileRes
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1032
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.
PtexTexture::dataType
virtual Ptex::DataType dataType()=0
Type of data stored in file.
PtexTexture::numChannels
virtual int numChannels()=0
Number of channels stored in file.
PtexTexture::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)=0
Access resolution and adjacency information about a face.
PtexTriangleFilter::_ntxchan
int _ntxchan
Definition: PtexTriangleFilter.h:77
PtexTriangleFilter::splitAndApply
void splitAndApply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexTriangleFilter.cpp:167
PtexTriangleFilter::_weight
float _weight
Definition: PtexTriangleFilter.h:74
PtexTriangleFilter::applyIter
void applyIter(PtexTriangleKernelIter &k, PtexFaceData *dh)
Definition: PtexTriangleFilter.cpp:220
PtexTriangleFilter::apply
void apply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
Definition: PtexTriangleFilter.cpp:200
PtexTriangleFilter::_result
float * _result
Definition: PtexTriangleFilter.h:73
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
PtexTriangleFilter::_firstChanOffset
int _firstChanOffset
Definition: PtexTriangleFilter.h:75
PtexTriangleFilter::applyAcrossEdge
void applyAcrossEdge(PtexTriangleKernel &k, const Ptex::FaceInfo &f, int eid)
Definition: PtexTriangleFilter.cpp:190
PtexTriangleFilter::_nchan
int _nchan
Definition: PtexTriangleFilter.h:76
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::_dt
DataType _dt
Definition: PtexTriangleFilter.h:78
PtexTriangleFilter::_tx
PtexTexture * _tx
Definition: PtexTriangleFilter.h:71
PtexTriangleKernelIter
Triangle filter kernel iterator (in texel coords)
Definition: PtexTriangleKernel.h:54
PtexTriangleKernelIter::v1
int v1
Definition: PtexTriangleKernel.h:58
PtexTriangleKernelIter::v2
int v2
Definition: PtexTriangleKernel.h:59
PtexTriangleKernelIter::rowlen
int rowlen
Definition: PtexTriangleKernel.h:56
PtexTriangleKernelIter::w1
int w1
Definition: PtexTriangleKernel.h:58
PtexTriangleKernelIter::u
float u
Definition: PtexTriangleKernel.h:57
PtexTriangleKernelIter::apply
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
Definition: PtexTriangleKernel.h:65
PtexTriangleKernelIter::w2
int w2
Definition: PtexTriangleKernel.h:59
PtexTriangleKernelIter::u1
int u1
Definition: PtexTriangleKernel.h:58
PtexTriangleKernelIter::weight
float weight
Definition: PtexTriangleKernel.h:63
PtexTriangleKernelIter::valid
bool valid
Definition: PtexTriangleKernel.h:61
PtexTriangleKernelIter::u2
int u2
Definition: PtexTriangleKernel.h:59
PtexTriangleKernelIter::applyConst
void applyConst(float *dst, void *data, DataType dt, int nChan)
Definition: PtexTriangleKernel.cpp:153
PtexTriangleKernelIter::v
float v
Definition: PtexTriangleKernel.h:57
PtexTriangleKernel
Triangle filter kernel (in normalized triangle coords)
Definition: PtexTriangleKernel.h:82
PtexTriangleKernel::reorient
void reorient(int eid, int aeid)
Definition: PtexTriangleKernel.h:151
PtexTriangleKernel::clampExtent
void clampExtent()
Definition: PtexTriangleKernel.h:178
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
PtexTriangleKernel::u1
float u1
Definition: PtexTriangleKernel.h:86
PtexTriangleKernel::splitW
void splitW(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:130
PtexTriangleKernel::v1
float v1
Definition: PtexTriangleKernel.h:86
PtexTriangleKernel::splitV
void splitV(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:123
PtexTriangleKernel::splitU
void splitU(PtexTriangleKernel &ka)
Definition: PtexTriangleKernel.h:116
PtexTriangleKernel::res
Res res
Definition: PtexTriangleKernel.h:84
PtexTriangleKernel::getIterators
void getIterators(PtexTriangleKernelIter &ke, PtexTriangleKernelIter &ko)
Definition: PtexTriangleKernel.h:188
PtexTriangleKernel::w1
float w1
Definition: PtexTriangleKernel.h:86
PtexTriangleKernel::clampRes
void clampRes(Res fres)
Definition: PtexTriangleKernel.h:172
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexUtils::clamp
T clamp(T x, T lo, T hi)
Definition: PtexUtils.h:154
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:148
PtexUtils::calcResFromWidth
int calcResFromWidth(float w)
Definition: PtexUtils.h:103
PtexUtils::max
T max(T a, T b)
Definition: PtexUtils.h:151
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
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:229
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