Path: blob/master/thirdparty/embree/kernels/subdiv/linear_bezier_patch.h
9913 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "bezier_curve.h"67namespace embree8{9namespace isa10{11template<typename V>12struct TensorLinearQuadraticBezierSurface13{14QuadraticBezierCurve<V> L;15QuadraticBezierCurve<V> R;1617__forceinline TensorLinearQuadraticBezierSurface() {}1819__forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<V>& curve)20: L(curve.L), R(curve.R) {}2122__forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {23L = other.L; R = other.R; return *this;24}2526__forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<V>& L, const QuadraticBezierCurve<V>& R)27: L(L), R(R) {}2829__forceinline BBox<V> bounds() const {30return merge(L.bounds(),R.bounds());31}32};3334#if !defined(__SYCL_DEVICE_ONLY__)35template<>36struct TensorLinearQuadraticBezierSurface<Vec2fa>37{38QuadraticBezierCurve<vfloat4> LR;3940__forceinline TensorLinearQuadraticBezierSurface() {}4142__forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<Vec2fa>& curve)43: LR(curve.LR) {}4445__forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {46LR = other.LR; return *this;47}4849__forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<vfloat4>& LR)50: LR(LR) {}5152__forceinline BBox<Vec2fa> bounds() const53{54const BBox<vfloat4> b = LR.bounds();55const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));56const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));57return merge(bl,br);58}59};60#endif6162template<typename V>63struct TensorLinearCubicBezierSurface64{65CubicBezierCurve<V> L;66CubicBezierCurve<V> R;6768__forceinline TensorLinearCubicBezierSurface() {}6970__forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)71: L(curve.L), R(curve.R) {}7273__forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {74L = other.L; R = other.R; return *this;75}7677__forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<V>& L, const CubicBezierCurve<V>& R)78: L(L), R(R) {}7980template<template<typename T> class SourceCurve>81__forceinline static TensorLinearCubicBezierSurface fromCenterAndNormalCurve(const SourceCurve<Vec3ff>& center, const SourceCurve<Vec3fa>& normal)82{83SourceCurve<Vec3ff> vcurve = center;84SourceCurve<Vec3fa> ncurve = normal;8586/* here we construct a patch which follows the curve l(t) =87* p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */8889const Vec3ff p0 = vcurve.eval(0.0f);90const Vec3ff dp0 = vcurve.eval_du(0.0f);91//const Vec3ff ddp0 = vcurve.eval_dudu(0.0f); // ddp0 is assumed to be 09293const Vec3fa n0 = ncurve.eval(0.0f);94const Vec3fa dn0 = ncurve.eval_du(0.0f);9596const Vec3ff p1 = vcurve.eval(1.0f);97const Vec3ff dp1 = vcurve.eval_du(1.0f);98//const Vec3ff ddp1 = vcurve.eval_dudu(1.0f); // ddp1 is assumed to be 099100const Vec3fa n1 = ncurve.eval(1.0f);101const Vec3fa dn1 = ncurve.eval_du(1.0f);102103const Vec3fa bt0 = cross(n0,dp0);104const Vec3fa dbt0 = cross(dn0,dp0);// + cross(n0,ddp0);105106const Vec3fa bt1 = cross(n1,dp1);107const Vec3fa dbt1 = cross(dn1,dp1);// + cross(n1,ddp1);108109const Vec3fa k0 = normalize(bt0);110const Vec3fa dk0 = dnormalize(bt0,dbt0);111112const Vec3fa k1 = normalize(bt1);113const Vec3fa dk1 = dnormalize(bt1,dbt1);114115const Vec3fa l0 = p0 - p0.w*k0;116const Vec3fa dl0 = dp0 - (dp0.w*k0 + p0.w*dk0);117118const Vec3fa r0 = p0 + p0.w*k0;119const Vec3fa dr0 = dp0 + (dp0.w*k0 + p0.w*dk0);120121const Vec3fa l1 = p1 - p1.w*k1;122const Vec3fa dl1 = dp1 - (dp1.w*k1 + p1.w*dk1);123124const Vec3fa r1 = p1 + p1.w*k1;125const Vec3fa dr1 = dp1 + (dp1.w*k1 + p1.w*dk1);126127const float scale = 1.0f/3.0f;128CubicBezierCurve<V> L(l0,l0+scale*dl0,l1-scale*dl1,l1);129CubicBezierCurve<V> R(r0,r0+scale*dr0,r1-scale*dr1,r1);130return TensorLinearCubicBezierSurface(L,R);131}132133__forceinline BBox<V> bounds() const {134return merge(L.bounds(),R.bounds());135}136137__forceinline BBox3fa accurateBounds() const {138return merge(L.accurateBounds(),R.accurateBounds());139}140141__forceinline CubicBezierCurve<Interval1f> reduce_v() const {142return merge(CubicBezierCurve<Interval<V>>(L),CubicBezierCurve<Interval<V>>(R));143}144145__forceinline LinearBezierCurve<Interval1f> reduce_u() const {146return LinearBezierCurve<Interval1f>(L.bounds(),R.bounds());147}148149__forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx) const {150return TensorLinearCubicBezierSurface<float>(L.xfm(dx),R.xfm(dx));151}152153template<int W>154__forceinline TensorLinearCubicBezierSurface<vfloat<W>> vxfm(const V& dx) const {155return TensorLinearCubicBezierSurface<vfloat<W>>(L.template vxfm<W>(dx),R.template vxfm<W>(dx));156}157158__forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx, const V& p) const {159return TensorLinearCubicBezierSurface<float>(L.xfm(dx,p),R.xfm(dx,p));160}161162__forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space) const {163return TensorLinearCubicBezierSurface(L.xfm(space),R.xfm(space));164}165166__forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const {167return TensorLinearCubicBezierSurface(L.xfm(space,p),R.xfm(space,p));168}169170__forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const {171return TensorLinearCubicBezierSurface(L.xfm(space,p,s),R.xfm(space,p,s));172}173174__forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {175return TensorLinearCubicBezierSurface(L.clip(u),R.clip(u));176}177178__forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const {179return TensorLinearCubicBezierSurface(clerp(L,R,V(v.lower)),clerp(L,R,V(v.upper)));180}181182__forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {183return clip_v(v).clip_u(u);184}185186__forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const187{188CubicBezierCurve<V> L0,L1; L.split(L0,L1,u);189CubicBezierCurve<V> R0,R1; R.split(R0,R1,u);190new (&left ) TensorLinearCubicBezierSurface(L0,R0);191new (&right) TensorLinearCubicBezierSurface(L1,R1);192}193194__forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {195valid = true; clear(valid,VSIZEX-1);196return TensorLinearCubicBezierSurface<Vec2vfx>(L.split(u),R.split(u));197}198199template<int W>200__forceinline TensorLinearCubicBezierSurface<Vec2vf<W>> vsplit_u(vbool<W>& valid, const BBox1f& u, int& i, int N) const201{202valid = true; clear(valid,W-1);203auto r = TensorLinearCubicBezierSurface<Vec2vf<W>>(L.template split<W>(u,i,N),R.template split<W>(u,i,N));204i += W-1;205return r;206}207208__forceinline V eval(const float u, const float v) const {209return clerp(L,R,V(v)).eval(u);210}211212__forceinline V eval_du(const float u, const float v) const {213return clerp(L,R,V(v)).eval_dt(u);214}215216__forceinline V eval_dv(const float u, const float v) const {217return (R-L).eval(u);218}219220__forceinline void eval(const float u, const float v, V& p, V& dpdu, V& dpdv) const221{222V p0, dp0du; L.eval(u,p0,dp0du);223V p1, dp1du; R.eval(u,p1,dp1du);224p = lerp(p0,p1,v);225dpdu = lerp(dp0du,dp1du,v);226dpdv = p1-p0;227}228229__forceinline TensorLinearQuadraticBezierSurface<V> derivative_u() const {230return TensorLinearQuadraticBezierSurface<V>(L.derivative(),R.derivative());231}232233__forceinline CubicBezierCurve<V> derivative_v() const {234return R-L;235}236237__forceinline V axis_u() const {238return (L.end()-L.begin())+(R.end()-R.begin());239}240241__forceinline V axis_v() const {242return (R.begin()-L.begin())+(R.end()-L.end());243}244245friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)246{247return cout << "TensorLinearCubicBezierSurface" << embree_endl248<< "{" << embree_endl249<< " L = " << a.L << ", " << embree_endl250<< " R = " << a.R << embree_endl251<< "}";252}253254friend __forceinline TensorLinearCubicBezierSurface clerp(const TensorLinearCubicBezierSurface& a, const TensorLinearCubicBezierSurface& b, const float t) {255return TensorLinearCubicBezierSurface(clerp(a.L,b.L,V(t)), clerp(a.R,b.R,V(t)));256}257};258259#if !defined(__SYCL_DEVICE_ONLY__)260261template<>262struct TensorLinearCubicBezierSurface<Vec2fa>263{264CubicBezierCurve<vfloat4> LR;265266__forceinline TensorLinearCubicBezierSurface() {}267268__forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)269: LR(curve.LR) {}270271__forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {272LR = other.LR; return *this;273}274275__forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<vfloat4>& LR)276: LR(LR) {}277278__forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<Vec2fa>& L, const CubicBezierCurve<Vec2fa>& R)279: LR(shuffle<0,1,0,1>(vfloat4(L.v0),vfloat4(R.v0)),shuffle<0,1,0,1>(vfloat4(L.v1),vfloat4(R.v1)),shuffle<0,1,0,1>(vfloat4(L.v2),vfloat4(R.v2)),shuffle<0,1,0,1>(vfloat4(L.v3),vfloat4(R.v3))) {}280281__forceinline CubicBezierCurve<Vec2fa> getL() const {282return CubicBezierCurve<Vec2fa>(Vec2fa(LR.v0),Vec2fa(LR.v1),Vec2fa(LR.v2),Vec2fa(LR.v3));283}284285__forceinline CubicBezierCurve<Vec2fa> getR() const {286return CubicBezierCurve<Vec2fa>(Vec2fa(shuffle<2,3,2,3>(LR.v0)),Vec2fa(shuffle<2,3,2,3>(LR.v1)),Vec2fa(shuffle<2,3,2,3>(LR.v2)),Vec2fa(shuffle<2,3,2,3>(LR.v3)));287}288289__forceinline BBox<Vec2fa> bounds() const290{291const BBox<vfloat4> b = LR.bounds();292const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));293const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));294return merge(bl,br);295}296297__forceinline BBox1f bounds(const Vec2fa& axis) const298{299const CubicBezierCurve<vfloat4> LRx = LR;300const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));301const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(axis)),LRx,shuffle<1>(vfloat4(axis))*LRy);302const BBox<vfloat4> Lb = LRa.bounds();303const BBox<vfloat4> Rb(shuffle<3>(Lb.lower),shuffle<3>(Lb.upper));304const BBox<vfloat4> b = merge(Lb,Rb);305return BBox1f(b.lower[0],b.upper[0]);306}307308__forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx) const309{310const CubicBezierCurve<vfloat4> LRx = LR;311const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));312const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);313return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),314CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));315}316317__forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx, const Vec2fa& p) const318{319const vfloat4 pxyxy = shuffle<0,1,0,1>(vfloat4(p));320const CubicBezierCurve<vfloat4> LRx = LR-pxyxy;321const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));322const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);323return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),324CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));325}326327__forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {328return TensorLinearCubicBezierSurface(LR.clip(u));329}330331__forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const332{333const CubicBezierCurve<vfloat4> LL(shuffle<0,1,0,1>(LR.v0),shuffle<0,1,0,1>(LR.v1),shuffle<0,1,0,1>(LR.v2),shuffle<0,1,0,1>(LR.v3));334const CubicBezierCurve<vfloat4> RR(shuffle<2,3,2,3>(LR.v0),shuffle<2,3,2,3>(LR.v1),shuffle<2,3,2,3>(LR.v2),shuffle<2,3,2,3>(LR.v3));335return TensorLinearCubicBezierSurface(clerp(LL,RR,vfloat4(v.lower,v.lower,v.upper,v.upper)));336}337338__forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {339return clip_v(v).clip_u(u);340}341342__forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const343{344CubicBezierCurve<vfloat4> LR0,LR1; LR.split(LR0,LR1,u);345new (&left ) TensorLinearCubicBezierSurface(LR0);346new (&right) TensorLinearCubicBezierSurface(LR1);347}348349__forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {350valid = true; clear(valid,VSIZEX-1);351return TensorLinearCubicBezierSurface<Vec2vfx>(getL().split(u),getR().split(u));352}353354template<int W>355__forceinline TensorLinearCubicBezierSurface<Vec2vf<W>> vsplit_u(vbool<W>& valid, const BBox1f& u, int& i, int N) const {356valid = true; clear(valid,W-1);357auto r = TensorLinearCubicBezierSurface<Vec2vf<W>>(getL().split<W>(u,i,N),getR().split<W>(u,i,N));358i += W-1;359return r;360}361362__forceinline Vec2fa eval(const float u, const float v) const363{364const vfloat4 p = LR.eval(u);365return Vec2fa(lerp(shuffle<0,1,0,1>(p),shuffle<2,3,2,3>(p),v));366}367368__forceinline Vec2fa eval_du(const float u, const float v) const369{370const vfloat4 dpdu = LR.eval_dt(u);371return Vec2fa(lerp(shuffle<0,1,0,1>(dpdu),shuffle<2,3,2,3>(dpdu),v));372}373374__forceinline Vec2fa eval_dv(const float u, const float v) const375{376const vfloat4 p = LR.eval(u);377return Vec2fa(shuffle<2,3,2,3>(p)-shuffle<0,1,0,1>(p));378}379380__forceinline void eval(const float u, const float v, Vec2fa& p, Vec2fa& dpdu, Vec2fa& dpdv) const381{382vfloat4 p0, dp0du; LR.eval(u,p0,dp0du);383p = Vec2fa(lerp(shuffle<0,1,0,1>(p0),shuffle<2,3,2,3>(p0),v));384dpdu = Vec2fa(lerp(shuffle<0,1,0,1>(dp0du),shuffle<2,3,2,3>(dp0du),v));385dpdv = Vec2fa(shuffle<2,3,2,3>(p0)-shuffle<0,1,0,1>(p0));386}387388__forceinline TensorLinearQuadraticBezierSurface<Vec2fa> derivative_u() const {389return TensorLinearQuadraticBezierSurface<Vec2fa>(LR.derivative());390}391392__forceinline CubicBezierCurve<Vec2fa> derivative_v() const {393return getR()-getL();394}395396__forceinline Vec2fa axis_u() const397{398const CubicBezierCurve<Vec2fa> L = getL();399const CubicBezierCurve<Vec2fa> R = getR();400return (L.end()-L.begin())+(R.end()-R.begin());401}402403__forceinline Vec2fa axis_v() const404{405const CubicBezierCurve<Vec2fa> L = getL();406const CubicBezierCurve<Vec2fa> R = getR();407return (R.begin()-L.begin())+(R.end()-L.end());408}409410friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)411{412return cout << "TensorLinearCubicBezierSurface" << embree_endl413<< "{" << embree_endl414<< " L = " << a.getL() << ", " << embree_endl415<< " R = " << a.getR() << embree_endl416<< "}";417}418};419420template<>421__forceinline TensorLinearCubicBezierSurface<Vec2f> TensorLinearCubicBezierSurface<Vec2fa>::vsplit_u<1>(bool& valid, const BBox1f& u, int& i, int N) const {422auto r = TensorLinearCubicBezierSurface<Vec2f>(getL().split1(u,i,N),getR().split1(u,i,N));423valid = true; i += 1;424return r;425}426427#else428429template<> template<>430__forceinline TensorLinearCubicBezierSurface<Vec2f> TensorLinearCubicBezierSurface<Vec2fa>::vsplit_u<1>(bool& valid, const BBox1f& u, int& i, int N) const {431auto r = TensorLinearCubicBezierSurface<Vec2f>(L.split1(u,i,N),R.split1(u,i,N));432valid = true; i += 1;433return r;434}435436#endif437438typedef TensorLinearCubicBezierSurface<float> TensorLinearCubicBezierSurface1f;439typedef TensorLinearCubicBezierSurface<Vec2fa> TensorLinearCubicBezierSurface2fa;440typedef TensorLinearCubicBezierSurface<Vec3fa> TensorLinearCubicBezierSurface3fa;441}442}443444445