mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-04 00:41:05 +00:00
346 lines
11 KiB
C++
346 lines
11 KiB
C++
//
|
|
// Copyright 2013 Pixar
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
// with the following modification; you may not use this file except in
|
|
// compliance with the Apache License and the following modification to it:
|
|
// Section 6. Trademarks. is deleted and replaced with:
|
|
//
|
|
// 6. Trademarks. This License does not grant permission to use the trade
|
|
// names, trademarks, service marks, or product names of the Licensor
|
|
// and its affiliates, except as required to comply with Section 4(c) of
|
|
// the License and to reproduce the content of the NOTICE file.
|
|
//
|
|
// You may obtain a copy of the Apache License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the Apache License with the above modification is
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the Apache License for the specific
|
|
// language governing permissions and limitations under the Apache License.
|
|
//
|
|
|
|
#ifndef FAR_INTERPOLATE_H
|
|
#define FAR_INTERPOLATE_H
|
|
|
|
#include "../version.h"
|
|
|
|
#include "../far/patchParam.h"
|
|
#include "../far/stencilTables.h"
|
|
|
|
namespace OpenSubdiv {
|
|
namespace OPENSUBDIV_VERSION {
|
|
|
|
namespace Far {
|
|
|
|
// XXXX
|
|
//
|
|
// Note 1 : interpolation functions will eventually need to be augmented to
|
|
// handle second order derivatives
|
|
//
|
|
// Note 2 : evaluation of derivatives need to be ptional (passing NULL to
|
|
// dQ1 and dQ2 to the weights functions will do this)
|
|
|
|
void GetBilinearWeights(PatchParam::BitField bits,
|
|
float s, float t, float point[4], float deriv1[4], float deriv2[4]);
|
|
|
|
void GetBezierWeights(PatchParam::BitField bits,
|
|
float s, float t, float point[16], float deriv1[16], float deriv2[16]);
|
|
|
|
void GetBSplineWeights(PatchParam::BitField bits,
|
|
float s, float t, float point[16], float deriv1[16], float deriv2[16]);
|
|
|
|
|
|
/// \brief Interpolate the (s,t) parametric location of a bilinear (quad)
|
|
/// patch
|
|
///
|
|
/// @param cvs Array of 16 control vertex indices
|
|
///
|
|
/// @param Q Array of 16 bicubic weights for the control vertices
|
|
///
|
|
/// @param Qd1 Array of 16 bicubic 's' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param Qd2 Array of 16 bicubic 't' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param src Source primvar buffer (control vertices data)
|
|
///
|
|
/// @param dst Destination primvar buffer (limit surface data)
|
|
///
|
|
template <class T, class U>
|
|
inline void
|
|
InterpolateBilinearPatch(Index const * cvs,
|
|
float const * Q, float const *Qd1, float const *Qd2,
|
|
T const & src, U & dst) {
|
|
|
|
//
|
|
// v0 -- v1
|
|
// |.....|
|
|
// |.....|
|
|
// v3 -- v2
|
|
//
|
|
for (int k=0; k<4; ++k) {
|
|
dst.AddWithWeight(src[cvs[k]], Q[k], Qd1[k], Qd2[k]);
|
|
}
|
|
}
|
|
|
|
/// \brief Interpolate the (s,t) parametric location of a regular bicubic
|
|
/// patch
|
|
///
|
|
/// @param cvs Array of 16 control vertex indices
|
|
///
|
|
/// @param Q Array of 16 bicubic weights for the control vertices
|
|
///
|
|
/// @param Qd1 Array of 16 bicubic 's' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param Qd2 Array of 16 bicubic 't' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param src Source primvar buffer (control vertices data)
|
|
///
|
|
/// @param dst Destination primvar buffer (limit surface data)
|
|
///
|
|
template <class T, class U>
|
|
inline void
|
|
InterpolateRegularPatch(Index const * cvs,
|
|
float const * Q, float const *Qd1, float const *Qd2,
|
|
T const & src, U & dst) {
|
|
|
|
//
|
|
// v0 -- v1 -- v2 -- v3
|
|
// |.....|.....|.....|
|
|
// |.....|.....|.....|
|
|
// v4 -- v5 -- v6 -- v7
|
|
// |.....|.....|.....|
|
|
// |.....|.....|.....|
|
|
// v8 -- v9 -- v10-- v11
|
|
// |.....|.....|.....|
|
|
// |.....|.....|.....|
|
|
// v12-- v13-- v14-- v15
|
|
//
|
|
for (int k=0; k<16; ++k) {
|
|
dst.AddWithWeight(src[cvs[k]], Q[k], Qd1[k], Qd2[k]);
|
|
}
|
|
}
|
|
|
|
/// \brief Interpolate the (s,t) parametric location of a boundary bicubic
|
|
/// patch
|
|
///
|
|
/// @param cvs Array of 12 control vertex indices
|
|
///
|
|
/// @param Q Array of 12 bicubic weights for the control vertices
|
|
///
|
|
/// @param Qd1 Array of 12 bicubic 's' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param Qd2 Array of 12 bicubic 't' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param src Source primvar buffer (control vertices data)
|
|
///
|
|
/// @param dst Destination primvar buffer (limit surface data)
|
|
///
|
|
template <class T, class U>
|
|
inline void
|
|
InterpolateBoundaryPatch(Index const * cvs,
|
|
float const * Q, float const *Qd1, float const *Qd2,
|
|
T const & src, U & dst) {
|
|
|
|
// mirror the missing vertices (M)
|
|
//
|
|
// M0 -- M1 -- M2 -- M3 (corner)
|
|
// | | | |
|
|
// | | | |
|
|
// v0 -- v1 -- v2 -- v3 M : mirrored
|
|
// |.....|.....|.....|
|
|
// |.....|.....|.....|
|
|
// v4 -- v5 -- v6 -- v7 v : original Cv
|
|
// |.....|.....|.....|
|
|
// |.....|.....|.....|
|
|
// v8 -- v9 -- v10-- v11
|
|
//
|
|
for (int k=0; k<4; ++k) { // M0 - M3
|
|
dst.AddWithWeight(src[cvs[k]], 2.0f*Q[k], 2.0f*Qd1[k], 2.0f*Qd2[k]);
|
|
dst.AddWithWeight(src[cvs[k+4]], -1.0f*Q[k], -1.0f*Qd1[k], -1.0f*Qd2[k]);
|
|
}
|
|
for (int k=0; k<12; ++k) {
|
|
dst.AddWithWeight(src[cvs[k]], Q[k+4], Qd1[k+4], Qd2[k+4]);
|
|
}
|
|
}
|
|
|
|
/// \brief Interpolate the (s,t) parametric location of a corner bicubic
|
|
/// patch
|
|
///
|
|
/// @param cvs Array of 9 control vertex indices
|
|
///
|
|
/// @param Q Array of 9 bicubic weights for the control vertices
|
|
///
|
|
/// @param Qd1 Array of 9 bicubic 's' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param Qd2 Array of 9 bicubic 't' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param src Source primvar buffer (control vertices data)
|
|
///
|
|
/// @param dst Destination primvar buffer (limit surface data)
|
|
///
|
|
template <class T, class U>
|
|
inline void
|
|
InterpolateCornerPatch(Index const * cvs,
|
|
float const * Q, float const *Qd1, float const *Qd2,
|
|
T const & src, U & dst) {
|
|
|
|
// mirror the missing vertices (M)
|
|
//
|
|
// M0 -- M1 -- M2 -- M3 (corner)
|
|
// | | | |
|
|
// | | | |
|
|
// v0 -- v1 -- v2 -- M4 M : mirrored
|
|
// |.....|.....| |
|
|
// |.....|.....| |
|
|
// v3.--.v4.--.v5 -- M5 v : original Cv
|
|
// |.....|.....| |
|
|
// |.....|.....| |
|
|
// v6 -- v7 -- v8 -- M6
|
|
//
|
|
for (int k=0; k<3; ++k) { // M0 - M2
|
|
dst.AddWithWeight(src[cvs[k ]], 2.0f*Q[k], 2.0f*Qd1[k], 2.0f*Qd2[k]);
|
|
dst.AddWithWeight(src[cvs[k+3]], -1.0f*Q[k], -1.0f*Qd1[k], -1.0f*Qd2[k]);
|
|
}
|
|
for (int k=0; k<3; ++k) { // M4 - M6
|
|
int idx = (k+1)*4 + 3;
|
|
dst.AddWithWeight(src[cvs[k*3+2]], 2.0f*Q[idx], 2.0f*Qd1[idx], 2.0f*Qd2[idx]);
|
|
dst.AddWithWeight(src[cvs[k*3+1]], -1.0f*Q[idx], -1.0f*Qd1[idx], -1.0f*Qd2[idx]);
|
|
}
|
|
// M3 = -2.v1 + 4.v2 + v4 - 2.v5
|
|
dst.AddWithWeight(src[cvs[1]], -2.0f*Q[3], -2.0f*Qd1[3], -2.0f*Qd2[3]);
|
|
dst.AddWithWeight(src[cvs[2]], 4.0f*Q[3], 4.0f*Qd1[3], 4.0f*Qd2[3]);
|
|
dst.AddWithWeight(src[cvs[4]], 1.0f*Q[3], 1.0f*Qd1[3], 1.0f*Qd2[3]);
|
|
dst.AddWithWeight(src[cvs[5]], -2.0f*Q[3], -2.0f*Qd1[3], -2.0f*Qd2[3]);
|
|
for (int y=0; y<3; ++y) { // v0 - v8
|
|
for (int x=0; x<3; ++x) {
|
|
int idx = y*4+x+4;
|
|
dst.AddWithWeight(src[cvs[y*3+x]], Q[idx], Qd1[idx], Qd2[idx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// \brief Interpolate the (s,t) parametric location of a Gregory bicubic
|
|
/// patch
|
|
///
|
|
/// @param cvs Array of 20 control vertex indices
|
|
///
|
|
/// @param s Patch coordinate (in coarse face normalized space)
|
|
///
|
|
/// @param t Patch coordinate (in coarse face normalized space)
|
|
///
|
|
/// @param Q Array of 9 bicubic weights for the control vertices
|
|
///
|
|
/// @param Qd1 Array of 9 bicubic 's' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param Qd2 Array of 9 bicubic 't' tangent weights for the control
|
|
/// vertices
|
|
///
|
|
/// @param src Source primvar buffer (control vertices data)
|
|
///
|
|
/// @param dst Destination primvar buffer (limit surface data)
|
|
///
|
|
template <class T, class U>
|
|
inline void
|
|
InterpolateGregoryPatch(Index const *cvs, float s, float t,
|
|
float const * Q, float const *Qd1, float const *Qd2,
|
|
T const & src, U & dst) {
|
|
|
|
float ss = 1-s,
|
|
tt = 1-t;
|
|
// remark #1572: floating-point equality and inequality comparisons are unreliable
|
|
#ifdef __INTEL_COMPILER
|
|
#pragma warning disable 1572
|
|
#endif
|
|
float d11 = s+t; if(s+t==0.0f) d11 = 1.0f;
|
|
float d12 = ss+t; if(ss+t==0.0f) d12 = 1.0f;
|
|
float d21 = s+tt; if(s+tt==0.0f) d21 = 1.0f;
|
|
float d22 = ss+tt; if(ss+tt==0.0f) d22 = 1.0f;
|
|
#ifdef __INTEL_COMPILER
|
|
#pragma warning enable 1572
|
|
#endif
|
|
|
|
float weights[4][2] = { { s/d11, t/d11 },
|
|
{ ss/d12, t/d12 },
|
|
{ s/d21, tt/d21 },
|
|
{ ss/d22, tt/d22 } };
|
|
|
|
//
|
|
// P3 e3- e2+ P2
|
|
// 15------17-------11--------10
|
|
// | | | |
|
|
// | | | |
|
|
// | | f3- | f2+ |
|
|
// | 19 13 |
|
|
// e3+ 16-----18 14-----12 e2-
|
|
// | f3+ f2- |
|
|
// | |
|
|
// | |
|
|
// | f0- f1+ |
|
|
// e0- 2------4 8------6 e1+
|
|
// | 3 9 |
|
|
// | | f0+ | f1- |
|
|
// | | | |
|
|
// | | | |
|
|
// O--------1--------7--------5
|
|
// P0 e0+ e1- P1
|
|
//
|
|
|
|
// gregory-to-bezier map
|
|
static int const permute[16] =
|
|
{ 0, 1, 7, 5, 2, -1, -2, 6, 16, -3, -4, 12, 15, 17, 11, 10 };
|
|
|
|
for (int k = 0; k < 16; ++k) {
|
|
|
|
int index = permute[k];
|
|
if (index >=0) {
|
|
dst.AddWithWeight(src[cvs[index]], Q[k], Qd1[k], Qd2[k]);
|
|
} else if (index == -1) {
|
|
// 3, 4
|
|
float w0 = weights[0][0];
|
|
float w1 = weights[0][1];
|
|
dst.AddWithWeight(src[cvs[3]], w0*Q[k], w0*Qd1[k], w0*Qd2[k]);
|
|
dst.AddWithWeight(src[cvs[4]], w1*Q[k], w1*Qd1[k], w1*Qd2[k]);
|
|
} else if (index == -2) {
|
|
// 8, 9
|
|
float w0 = weights[1][0];
|
|
float w1 = weights[1][1];
|
|
dst.AddWithWeight(src[cvs[9]], w0*Q[k], w0*Qd1[k], w0*Qd2[k]);
|
|
dst.AddWithWeight(src[cvs[8]], w1*Q[k], w1*Qd1[k], w1*Qd2[k]);
|
|
} else if (index == -3) {
|
|
// 18, 19
|
|
float w0 = weights[2][0];
|
|
float w1 = weights[2][1];
|
|
dst.AddWithWeight(src[cvs[19]], w0*Q[k], w0*Qd1[k], w0*Qd2[k]);
|
|
dst.AddWithWeight(src[cvs[18]], w1*Q[k], w1*Qd1[k], w1*Qd2[k]);
|
|
} else if (index == -4) {
|
|
// 13, 14
|
|
float w0 = weights[3][0];
|
|
float w1 = weights[3][1];
|
|
dst.AddWithWeight(src[cvs[13]], w0*Q[k], w0*Qd1[k], w0*Qd2[k]);
|
|
dst.AddWithWeight(src[cvs[14]], w1*Q[k], w1*Qd1[k], w1*Qd2[k]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} // end namespace Far
|
|
|
|
} // end namespace OPENSUBDIV_VERSION
|
|
using namespace OPENSUBDIV_VERSION;
|
|
|
|
} // end namespace OpenSubdiv
|
|
|
|
#endif /* FAR_INTERPOLATE_H */
|