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
49
50void 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();
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
Platform-specific classes, functions, and includes.
#define C(eid, aeid)
PTEX_NAMESPACE_BEGIN const float PtexTriangleKernelWidth
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Per-face texture data accessor.
Definition Ptexture.h:406
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
virtual bool isTiled()=0
True if this data block is tiled.
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.
virtual bool isConstant()=0
True if this data block is constant.
virtual void * getData()=0
Access the data from this data block.
Smart-pointer for acquiring and releasing API objects.
Definition Ptexture.h:1032
virtual void getData(int faceid, void *buffer, int stride)=0
Access texture data for a face at highest-resolution.
virtual int numFaces()=0
Number of faces stored in file.
virtual Ptex::DataType dataType()=0
Type of data stored in file.
virtual int numChannels()=0
Number of channels stored in file.
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)=0
Access resolution and adjacency information about a face.
void splitAndApply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
void applyIter(PtexTriangleKernelIter &k, PtexFaceData *dh)
void apply(PtexTriangleKernel &k, int faceid, const Ptex::FaceInfo &f)
void buildKernel(PtexTriangleKernel &k, float u, float v, float uw1, float vw1, float uw2, float vw2, float width, float blur, Res faceRes)
void applyAcrossEdge(PtexTriangleKernel &k, const Ptex::FaceInfo &f, int eid)
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.
Triangle filter kernel iterator (in texel coords)
void apply(float *dst, void *data, DataType dt, int nChan, int nTxChan)
void applyConst(float *dst, void *data, DataType dt, int nChan)
Triangle filter kernel (in normalized triangle coords)
void reorient(int eid, int aeid)
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)
void splitW(PtexTriangleKernel &ka)
void splitV(PtexTriangleKernel &ka)
void splitU(PtexTriangleKernel &ka)
void getIterators(PtexTriangleKernelIter &ke, PtexTriangleKernelIter &ko)
T clamp(T x, T lo, T hi)
Definition PtexUtils.h:154
T min(T a, T b)
Definition PtexUtils.h:148
int calcResFromWidth(float w)
Definition PtexUtils.h:103
T max(T a, T b)
Definition PtexUtils.h:151
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.
Information about a face, as stored in the Ptex file header.
Definition Ptexture.h:229
Res res
Resolution of face.
Definition Ptexture.h:230
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
Definition Ptexture.h:256
int adjface(int eid) const
Access an adjacent face id. The eid value must be 0..3.
Definition Ptexture.h:259
Pixel resolution of a given texture.
Definition Ptexture.h:159
int v() const
V resolution in texels.
Definition Ptexture.h:176
int u() const
U resolution in texels.
Definition Ptexture.h:173