Path: blob/master/thirdparty/embree/kernels/subdiv/feature_adaptive_eval.h
9913 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "patch.h"67namespace embree8{9namespace isa10{11template<typename Vertex, typename Vertex_t = Vertex>12struct FeatureAdaptiveEval13{14public:1516typedef PatchT<Vertex,Vertex_t> Patch;17typedef typename Patch::Ref Ref;18typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;19typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;20typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;21typedef BSplinePatchT<Vertex,Vertex_t> BSplinePatch;22typedef BezierPatchT<Vertex,Vertex_t> BezierPatch;23typedef GregoryPatchT<Vertex,Vertex_t> GregoryPatch;24typedef BilinearPatchT<Vertex,Vertex_t> BilinearPatch;25typedef BezierCurveT<Vertex> BezierCurve;2627public:2829FeatureAdaptiveEval (const HalfEdge* edge, const char* vertices, size_t stride, const float u, const float v,30Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)31: P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)32{33switch (edge->patch_type) {34case HalfEdge::BILINEAR_PATCH: BilinearPatch(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;35case HalfEdge::REGULAR_QUAD_PATCH: RegularPatchT(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;36#if PATCH_USE_GREGORY == 237case HalfEdge::IRREGULAR_QUAD_PATCH: GregoryPatch(edge,vertices,stride).eval(u,v,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,1.0f); break;38#endif39default: {40GeneralCatmullClarkPatch patch(edge,vertices,stride);41eval(patch,Vec2f(u,v),0);42break;43}44}45}4647FeatureAdaptiveEval (CatmullClarkPatch& patch, const float u, const float v, float dscale, size_t depth,48Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv)49: P(P), dPdu(dPdu), dPdv(dPdv), ddPdudu(ddPdudu), ddPdvdv(ddPdvdv), ddPdudv(ddPdudv)50{51eval(patch,Vec2f(u,v),dscale,depth);52}5354void eval_general_quad(const GeneralCatmullClarkPatch& patch, array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE>& patches, const Vec2f& uv, size_t depth)55{56float u = uv.x, v = uv.y;57if (v < 0.5f) {58if (u < 0.5f) {59#if PATCH_USE_GREGORY == 260BezierCurve borders[2]; patch.getLimitBorder(borders,0);61BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);62BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);63eval(patches[0],Vec2f(2.0f*u,2.0f*v),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);64#else65eval(patches[0],Vec2f(2.0f*u,2.0f*v),2.0f,depth+1);66#endif67if (dPdu && dPdv) {68const Vertex dpdx = *dPdu, dpdy = *dPdv;69*dPdu = dpdx; *dPdv = dpdy;70}71}72else {73#if PATCH_USE_GREGORY == 274BezierCurve borders[2]; patch.getLimitBorder(borders,1);75BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);76BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);77eval(patches[1],Vec2f(2.0f*v,2.0f-2.0f*u),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);78#else79eval(patches[1],Vec2f(2.0f*v,2.0f-2.0f*u),2.0f,depth+1);80#endif81if (dPdu && dPdv) {82const Vertex dpdx = *dPdu, dpdy = *dPdv;83*dPdu = -dpdy; *dPdv = dpdx;84}85}86} else {87if (u > 0.5f) {88#if PATCH_USE_GREGORY == 289BezierCurve borders[2]; patch.getLimitBorder(borders,2);90BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);91BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);92eval(patches[2],Vec2f(2.0f-2.0f*u,2.0f-2.0f*v),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);93#else94eval(patches[2],Vec2f(2.0f-2.0f*u,2.0f-2.0f*v),2.0f,depth+1);95#endif96if (dPdu && dPdv) {97const Vertex dpdx = *dPdu, dpdy = *dPdv;98*dPdu = -dpdx; *dPdv = -dpdy;99}100}101else {102#if PATCH_USE_GREGORY == 2103BezierCurve borders[2]; patch.getLimitBorder(borders,3);104BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);105BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);106eval(patches[3],Vec2f(2.0f-2.0f*v,2.0f*u),2.0f,depth+1, &border0l, nullptr, nullptr, &border2r);107#else108eval(patches[3],Vec2f(2.0f-2.0f*v,2.0f*u),2.0f,depth+1);109#endif110if (dPdu && dPdv) {111const Vertex dpdx = *dPdu, dpdy = *dPdv;112*dPdu = dpdy; *dPdv = -dpdx;113}114}115}116}117118__forceinline bool final(const CatmullClarkPatch& patch, const typename CatmullClarkRing::Type type, size_t depth)119{120const int max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;121//#if PATCH_MIN_RESOLUTION122// return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=(size_t)max_eval_depth;123//#else124return depth>=(size_t)max_eval_depth;125//#endif126}127128void eval(CatmullClarkPatch& patch, Vec2f uv, float dscale, size_t depth,129BezierCurve* border0 = nullptr, BezierCurve* border1 = nullptr, BezierCurve* border2 = nullptr, BezierCurve* border3 = nullptr)130{131while (true)132{133typename CatmullClarkPatch::Type ty = patch.type();134135if (unlikely(final(patch,ty,depth)))136{137if (ty & CatmullClarkRing::TYPE_REGULAR) {138RegularPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);139PATCH_DEBUG_SUBDIVISION(234423,c,c,-1);140return;141} else {142IrregularFillPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);143PATCH_DEBUG_SUBDIVISION(34534,c,-1,c);144return;145}146}147else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {148assert(depth > 0);149RegularPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);150PATCH_DEBUG_SUBDIVISION(43524,c,c,-1);151return;152}153#if PATCH_USE_GREGORY == 2154else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {155assert(depth > 0);156GregoryPatch(patch,border0,border1,border2,border3).eval(uv.x,uv.y,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale);157PATCH_DEBUG_SUBDIVISION(23498,c,-1,c);158return;159}160#endif161else162{163array_t<CatmullClarkPatch,4> patches;164patch.subdivide(patches); // FIXME: only have to generate one of the patches165166const float u = uv.x, v = uv.y;167if (v < 0.5f) {168if (u < 0.5f) { patch = patches[0]; uv = Vec2f(2.0f*u,2.0f*v); dscale *= 2.0f; }169else { patch = patches[1]; uv = Vec2f(2.0f*u-1.0f,2.0f*v); dscale *= 2.0f; }170} else {171if (u > 0.5f) { patch = patches[2]; uv = Vec2f(2.0f*u-1.0f,2.0f*v-1.0f); dscale *= 2.0f; }172else { patch = patches[3]; uv = Vec2f(2.0f*u,2.0f*v-1.0f); dscale *= 2.0f; }173}174depth++;175}176}177}178179void eval(const GeneralCatmullClarkPatch& patch, const Vec2f& uv, const size_t depth)180{181/* convert into standard quad patch if possible */182if (likely(patch.isQuadPatch()))183{184CatmullClarkPatch qpatch; patch.init(qpatch);185return eval(qpatch,uv,1.0f,depth);186}187188/* subdivide patch */189unsigned N;190array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches;191patch.subdivide(patches,N); // FIXME: only have to generate one of the patches192193/* parametrization for quads */194if (N == 4)195eval_general_quad(patch,patches,uv,depth);196197/* parametrization for arbitrary polygons */198else199{200const unsigned l = (unsigned) floor(0.5f*uv.x); const float u = 2.0f*frac(0.5f*uv.x)-0.5f;201const unsigned h = (unsigned) floor(0.5f*uv.y); const float v = 2.0f*frac(0.5f*uv.y)-0.5f;202const unsigned i = 4*h+l; assert(i<N);203if (i >= N) return;204205#if PATCH_USE_GREGORY == 2206BezierCurve borders[2]; patch.getLimitBorder(borders,i);207BezierCurve border0l,border0r; borders[0].subdivide(border0l,border0r);208BezierCurve border2l,border2r; borders[1].subdivide(border2l,border2r);209eval(patches[i],Vec2f(u,v),1.0f,depth+1, &border0l, nullptr, nullptr, &border2r);210#else211eval(patches[i],Vec2f(u,v),1.0f,depth+1);212#endif213}214}215216private:217Vertex* const P;218Vertex* const dPdu;219Vertex* const dPdv;220Vertex* const ddPdudu;221Vertex* const ddPdvdv;222Vertex* const ddPdudv;223};224}225}226227228