| 1 | // Copyright 2009-2021 Intel Corporation |
| 2 | // SPDX-License-Identifier: Apache-2.0 |
| 3 | |
| 4 | #pragma once |
| 5 | |
| 6 | #include "bezier_curve.h" |
| 7 | |
| 8 | namespace embree |
| 9 | { |
| 10 | namespace isa |
| 11 | { |
| 12 | template<typename V> |
| 13 | struct TensorLinearQuadraticBezierSurface |
| 14 | { |
| 15 | QuadraticBezierCurve<V> L; |
| 16 | QuadraticBezierCurve<V> R; |
| 17 | |
| 18 | __forceinline TensorLinearQuadraticBezierSurface() {} |
| 19 | |
| 20 | __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<V>& curve) |
| 21 | : L(curve.L), R(curve.R) {} |
| 22 | |
| 23 | __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) { |
| 24 | L = other.L; R = other.R; return *this; |
| 25 | } |
| 26 | |
| 27 | __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<V>& L, const QuadraticBezierCurve<V>& R) |
| 28 | : L(L), R(R) {} |
| 29 | |
| 30 | __forceinline BBox<V> bounds() const { |
| 31 | return merge(L.bounds(),R.bounds()); |
| 32 | } |
| 33 | }; |
| 34 | |
| 35 | template<> |
| 36 | struct TensorLinearQuadraticBezierSurface<Vec2fa> |
| 37 | { |
| 38 | QuadraticBezierCurve<vfloat4> LR; |
| 39 | |
| 40 | __forceinline TensorLinearQuadraticBezierSurface() {} |
| 41 | |
| 42 | __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<Vec2fa>& curve) |
| 43 | : LR(curve.LR) {} |
| 44 | |
| 45 | __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) { |
| 46 | LR = other.LR; return *this; |
| 47 | } |
| 48 | |
| 49 | __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<vfloat4>& LR) |
| 50 | : LR(LR) {} |
| 51 | |
| 52 | __forceinline BBox<Vec2fa> bounds() const |
| 53 | { |
| 54 | const BBox<vfloat4> b = LR.bounds(); |
| 55 | const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper)); |
| 56 | const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper))); |
| 57 | return merge(bl,br); |
| 58 | } |
| 59 | }; |
| 60 | |
| 61 | template<typename V> |
| 62 | struct TensorLinearCubicBezierSurface |
| 63 | { |
| 64 | CubicBezierCurve<V> L; |
| 65 | CubicBezierCurve<V> R; |
| 66 | |
| 67 | __forceinline TensorLinearCubicBezierSurface() {} |
| 68 | |
| 69 | __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve) |
| 70 | : L(curve.L), R(curve.R) {} |
| 71 | |
| 72 | __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) { |
| 73 | L = other.L; R = other.R; return *this; |
| 74 | } |
| 75 | |
| 76 | __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<V>& L, const CubicBezierCurve<V>& R) |
| 77 | : L(L), R(R) {} |
| 78 | |
| 79 | template<template<typename T> class SourceCurve> |
| 80 | __forceinline static TensorLinearCubicBezierSurface fromCenterAndNormalCurve(const SourceCurve<Vec3ff>& center, const SourceCurve<Vec3fa>& normal) |
| 81 | { |
| 82 | SourceCurve<Vec3ff> vcurve = center; |
| 83 | SourceCurve<Vec3fa> ncurve = normal; |
| 84 | |
| 85 | /* here we construct a patch which follows the curve l(t) = |
| 86 | * p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */ |
| 87 | |
| 88 | const Vec3ff p0 = vcurve.eval(0.0f); |
| 89 | const Vec3ff dp0 = vcurve.eval_du(0.0f); |
| 90 | //const Vec3ff ddp0 = vcurve.eval_dudu(0.0f); // ddp0 is assumed to be 0 |
| 91 | |
| 92 | const Vec3fa n0 = ncurve.eval(0.0f); |
| 93 | const Vec3fa dn0 = ncurve.eval_du(0.0f); |
| 94 | |
| 95 | const Vec3ff p1 = vcurve.eval(1.0f); |
| 96 | const Vec3ff dp1 = vcurve.eval_du(1.0f); |
| 97 | //const Vec3ff ddp1 = vcurve.eval_dudu(1.0f); // ddp1 is assumed to be 0 |
| 98 | |
| 99 | const Vec3fa n1 = ncurve.eval(1.0f); |
| 100 | const Vec3fa dn1 = ncurve.eval_du(1.0f); |
| 101 | |
| 102 | const Vec3fa bt0 = cross(n0,dp0); |
| 103 | const Vec3fa dbt0 = cross(dn0,dp0);// + cross(n0,ddp0); |
| 104 | |
| 105 | const Vec3fa bt1 = cross(n1,dp1); |
| 106 | const Vec3fa dbt1 = cross(dn1,dp1);// + cross(n1,ddp1); |
| 107 | |
| 108 | const Vec3fa k0 = normalize(bt0); |
| 109 | const Vec3fa dk0 = dnormalize(bt0,dbt0); |
| 110 | |
| 111 | const Vec3fa k1 = normalize(bt1); |
| 112 | const Vec3fa dk1 = dnormalize(bt1,dbt1); |
| 113 | |
| 114 | const Vec3fa l0 = p0 - p0.w*k0; |
| 115 | const Vec3fa dl0 = dp0 - (dp0.w*k0 + p0.w*dk0); |
| 116 | |
| 117 | const Vec3fa r0 = p0 + p0.w*k0; |
| 118 | const Vec3fa dr0 = dp0 + (dp0.w*k0 + p0.w*dk0); |
| 119 | |
| 120 | const Vec3fa l1 = p1 - p1.w*k1; |
| 121 | const Vec3fa dl1 = dp1 - (dp1.w*k1 + p1.w*dk1); |
| 122 | |
| 123 | const Vec3fa r1 = p1 + p1.w*k1; |
| 124 | const Vec3fa dr1 = dp1 + (dp1.w*k1 + p1.w*dk1); |
| 125 | |
| 126 | const float scale = 1.0f/3.0f; |
| 127 | CubicBezierCurve<V> L(l0,l0+scale*dl0,l1-scale*dl1,l1); |
| 128 | CubicBezierCurve<V> R(r0,r0+scale*dr0,r1-scale*dr1,r1); |
| 129 | return TensorLinearCubicBezierSurface(L,R); |
| 130 | } |
| 131 | |
| 132 | __forceinline BBox<V> bounds() const { |
| 133 | return merge(L.bounds(),R.bounds()); |
| 134 | } |
| 135 | |
| 136 | __forceinline BBox3fa accurateBounds() const { |
| 137 | return merge(L.accurateBounds(),R.accurateBounds()); |
| 138 | } |
| 139 | |
| 140 | __forceinline CubicBezierCurve<Interval1f> reduce_v() const { |
| 141 | return merge(CubicBezierCurve<Interval<V>>(L),CubicBezierCurve<Interval<V>>(R)); |
| 142 | } |
| 143 | |
| 144 | __forceinline LinearBezierCurve<Interval1f> reduce_u() const { |
| 145 | return LinearBezierCurve<Interval1f>(L.bounds(),R.bounds()); |
| 146 | } |
| 147 | |
| 148 | __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx) const { |
| 149 | return TensorLinearCubicBezierSurface<float>(L.xfm(dx),R.xfm(dx)); |
| 150 | } |
| 151 | |
| 152 | __forceinline TensorLinearCubicBezierSurface<vfloatx> vxfm(const V& dx) const { |
| 153 | return TensorLinearCubicBezierSurface<vfloatx>(L.vxfm(dx),R.vxfm(dx)); |
| 154 | } |
| 155 | |
| 156 | __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx, const V& p) const { |
| 157 | return TensorLinearCubicBezierSurface<float>(L.xfm(dx,p),R.xfm(dx,p)); |
| 158 | } |
| 159 | |
| 160 | __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space) const { |
| 161 | return TensorLinearCubicBezierSurface(L.xfm(space),R.xfm(space)); |
| 162 | } |
| 163 | |
| 164 | __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const { |
| 165 | return TensorLinearCubicBezierSurface(L.xfm(space,p),R.xfm(space,p)); |
| 166 | } |
| 167 | |
| 168 | __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const { |
| 169 | return TensorLinearCubicBezierSurface(L.xfm(space,p,s),R.xfm(space,p,s)); |
| 170 | } |
| 171 | |
| 172 | __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const { |
| 173 | return TensorLinearCubicBezierSurface(L.clip(u),R.clip(u)); |
| 174 | } |
| 175 | |
| 176 | __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const { |
| 177 | return TensorLinearCubicBezierSurface(clerp(L,R,V(v.lower)),clerp(L,R,V(v.upper))); |
| 178 | } |
| 179 | |
| 180 | __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const { |
| 181 | return clip_v(v).clip_u(u); |
| 182 | } |
| 183 | |
| 184 | __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const |
| 185 | { |
| 186 | CubicBezierCurve<V> L0,L1; L.split(L0,L1,u); |
| 187 | CubicBezierCurve<V> R0,R1; R.split(R0,R1,u); |
| 188 | new (&left ) TensorLinearCubicBezierSurface(L0,R0); |
| 189 | new (&right) TensorLinearCubicBezierSurface(L1,R1); |
| 190 | } |
| 191 | |
| 192 | __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const { |
| 193 | valid = true; clear(valid,VSIZEX-1); |
| 194 | return TensorLinearCubicBezierSurface<Vec2vfx>(L.split(u),R.split(u)); |
| 195 | } |
| 196 | |
| 197 | __forceinline V eval(const float u, const float v) const { |
| 198 | return clerp(L,R,V(v)).eval(u); |
| 199 | } |
| 200 | |
| 201 | __forceinline V eval_du(const float u, const float v) const { |
| 202 | return clerp(L,R,V(v)).eval_dt(u); |
| 203 | } |
| 204 | |
| 205 | __forceinline V eval_dv(const float u, const float v) const { |
| 206 | return (R-L).eval(u); |
| 207 | } |
| 208 | |
| 209 | __forceinline void eval(const float u, const float v, V& p, V& dpdu, V& dpdv) const |
| 210 | { |
| 211 | V p0, dp0du; L.eval(u,p0,dp0du); |
| 212 | V p1, dp1du; R.eval(u,p1,dp1du); |
| 213 | p = lerp(p0,p1,v); |
| 214 | dpdu = lerp(dp0du,dp1du,v); |
| 215 | dpdv = p1-p0; |
| 216 | } |
| 217 | |
| 218 | __forceinline TensorLinearQuadraticBezierSurface<V> derivative_u() const { |
| 219 | return TensorLinearQuadraticBezierSurface<V>(L.derivative(),R.derivative()); |
| 220 | } |
| 221 | |
| 222 | __forceinline CubicBezierCurve<V> derivative_v() const { |
| 223 | return R-L; |
| 224 | } |
| 225 | |
| 226 | __forceinline V axis_u() const { |
| 227 | return (L.end()-L.begin())+(R.end()-R.begin()); |
| 228 | } |
| 229 | |
| 230 | __forceinline V axis_v() const { |
| 231 | return (R.begin()-L.begin())+(R.end()-L.end()); |
| 232 | } |
| 233 | |
| 234 | friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a) |
| 235 | { |
| 236 | return cout << "TensorLinearCubicBezierSurface" << embree_endl |
| 237 | << "{" << embree_endl |
| 238 | << " L = " << a.L << ", " << embree_endl |
| 239 | << " R = " << a.R << embree_endl |
| 240 | << "}" ; |
| 241 | } |
| 242 | |
| 243 | friend __forceinline TensorLinearCubicBezierSurface clerp(const TensorLinearCubicBezierSurface& a, const TensorLinearCubicBezierSurface& b, const float t) { |
| 244 | return TensorLinearCubicBezierSurface(clerp(a.L,b.L,V(t)), clerp(a.R,b.R,V(t))); |
| 245 | } |
| 246 | }; |
| 247 | |
| 248 | template<> |
| 249 | struct TensorLinearCubicBezierSurface<Vec2fa> |
| 250 | { |
| 251 | CubicBezierCurve<vfloat4> LR; |
| 252 | |
| 253 | __forceinline TensorLinearCubicBezierSurface() {} |
| 254 | |
| 255 | __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve) |
| 256 | : LR(curve.LR) {} |
| 257 | |
| 258 | __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) { |
| 259 | LR = other.LR; return *this; |
| 260 | } |
| 261 | |
| 262 | __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<vfloat4>& LR) |
| 263 | : LR(LR) {} |
| 264 | |
| 265 | __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<Vec2fa>& L, const CubicBezierCurve<Vec2fa>& R) |
| 266 | : 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))) {} |
| 267 | |
| 268 | __forceinline CubicBezierCurve<Vec2fa> getL() const { |
| 269 | return CubicBezierCurve<Vec2fa>(Vec2fa(LR.v0),Vec2fa(LR.v1),Vec2fa(LR.v2),Vec2fa(LR.v3)); |
| 270 | } |
| 271 | |
| 272 | __forceinline CubicBezierCurve<Vec2fa> getR() const { |
| 273 | return 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))); |
| 274 | } |
| 275 | |
| 276 | __forceinline BBox<Vec2fa> bounds() const |
| 277 | { |
| 278 | const BBox<vfloat4> b = LR.bounds(); |
| 279 | const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper)); |
| 280 | const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper))); |
| 281 | return merge(bl,br); |
| 282 | } |
| 283 | |
| 284 | __forceinline BBox1f bounds(const Vec2fa& axis) const |
| 285 | { |
| 286 | const CubicBezierCurve<vfloat4> LRx = LR; |
| 287 | const 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)); |
| 288 | const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(axis)),LRx,shuffle<1>(vfloat4(axis))*LRy); |
| 289 | const BBox<vfloat4> Lb = LRa.bounds(); |
| 290 | const BBox<vfloat4> Rb(shuffle<3>(Lb.lower),shuffle<3>(Lb.upper)); |
| 291 | const BBox<vfloat4> b = merge(Lb,Rb); |
| 292 | return BBox1f(b.lower[0],b.upper[0]); |
| 293 | } |
| 294 | |
| 295 | __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx) const |
| 296 | { |
| 297 | const CubicBezierCurve<vfloat4> LRx = LR; |
| 298 | const 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)); |
| 299 | const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy); |
| 300 | return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]), |
| 301 | CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2])); |
| 302 | } |
| 303 | |
| 304 | __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx, const Vec2fa& p) const |
| 305 | { |
| 306 | const vfloat4 pxyxy = shuffle<0,1,0,1>(vfloat4(p)); |
| 307 | const CubicBezierCurve<vfloat4> LRx = LR-pxyxy; |
| 308 | const 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)); |
| 309 | const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy); |
| 310 | return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]), |
| 311 | CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2])); |
| 312 | } |
| 313 | |
| 314 | __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const { |
| 315 | return TensorLinearCubicBezierSurface(LR.clip(u)); |
| 316 | } |
| 317 | |
| 318 | __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const |
| 319 | { |
| 320 | const 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)); |
| 321 | const 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)); |
| 322 | return TensorLinearCubicBezierSurface(clerp(LL,RR,vfloat4(v.lower,v.lower,v.upper,v.upper))); |
| 323 | } |
| 324 | |
| 325 | __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const { |
| 326 | return clip_v(v).clip_u(u); |
| 327 | } |
| 328 | |
| 329 | __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const |
| 330 | { |
| 331 | CubicBezierCurve<vfloat4> LR0,LR1; LR.split(LR0,LR1,u); |
| 332 | new (&left ) TensorLinearCubicBezierSurface(LR0); |
| 333 | new (&right) TensorLinearCubicBezierSurface(LR1); |
| 334 | } |
| 335 | |
| 336 | __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const { |
| 337 | valid = true; clear(valid,VSIZEX-1); |
| 338 | return TensorLinearCubicBezierSurface<Vec2vfx>(getL().split(u),getR().split(u)); |
| 339 | } |
| 340 | |
| 341 | __forceinline Vec2fa eval(const float u, const float v) const |
| 342 | { |
| 343 | const vfloat4 p = LR.eval(u); |
| 344 | return Vec2fa(lerp(shuffle<0,1,0,1>(p),shuffle<2,3,2,3>(p),v)); |
| 345 | } |
| 346 | |
| 347 | __forceinline Vec2fa eval_du(const float u, const float v) const |
| 348 | { |
| 349 | const vfloat4 dpdu = LR.eval_dt(u); |
| 350 | return Vec2fa(lerp(shuffle<0,1,0,1>(dpdu),shuffle<2,3,2,3>(dpdu),v)); |
| 351 | } |
| 352 | |
| 353 | __forceinline Vec2fa eval_dv(const float u, const float v) const |
| 354 | { |
| 355 | const vfloat4 p = LR.eval(u); |
| 356 | return Vec2fa(shuffle<2,3,2,3>(p)-shuffle<0,1,0,1>(p)); |
| 357 | } |
| 358 | |
| 359 | __forceinline void eval(const float u, const float v, Vec2fa& p, Vec2fa& dpdu, Vec2fa& dpdv) const |
| 360 | { |
| 361 | vfloat4 p0, dp0du; LR.eval(u,p0,dp0du); |
| 362 | p = Vec2fa(lerp(shuffle<0,1,0,1>(p0),shuffle<2,3,2,3>(p0),v)); |
| 363 | dpdu = Vec2fa(lerp(shuffle<0,1,0,1>(dp0du),shuffle<2,3,2,3>(dp0du),v)); |
| 364 | dpdv = Vec2fa(shuffle<2,3,2,3>(p0)-shuffle<0,1,0,1>(p0)); |
| 365 | } |
| 366 | |
| 367 | __forceinline TensorLinearQuadraticBezierSurface<Vec2fa> derivative_u() const { |
| 368 | return TensorLinearQuadraticBezierSurface<Vec2fa>(LR.derivative()); |
| 369 | } |
| 370 | |
| 371 | __forceinline CubicBezierCurve<Vec2fa> derivative_v() const { |
| 372 | return getR()-getL(); |
| 373 | } |
| 374 | |
| 375 | __forceinline Vec2fa axis_u() const |
| 376 | { |
| 377 | const CubicBezierCurve<Vec2fa> L = getL(); |
| 378 | const CubicBezierCurve<Vec2fa> R = getR(); |
| 379 | return (L.end()-L.begin())+(R.end()-R.begin()); |
| 380 | } |
| 381 | |
| 382 | __forceinline Vec2fa axis_v() const |
| 383 | { |
| 384 | const CubicBezierCurve<Vec2fa> L = getL(); |
| 385 | const CubicBezierCurve<Vec2fa> R = getR(); |
| 386 | return (R.begin()-L.begin())+(R.end()-L.end()); |
| 387 | } |
| 388 | |
| 389 | friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a) |
| 390 | { |
| 391 | return cout << "TensorLinearCubicBezierSurface" << embree_endl |
| 392 | << "{" << embree_endl |
| 393 | << " L = " << a.getL() << ", " << embree_endl |
| 394 | << " R = " << a.getR() << embree_endl |
| 395 | << "}" ; |
| 396 | } |
| 397 | }; |
| 398 | |
| 399 | typedef TensorLinearCubicBezierSurface<float> TensorLinearCubicBezierSurface1f; |
| 400 | typedef TensorLinearCubicBezierSurface<Vec2fa> TensorLinearCubicBezierSurface2fa; |
| 401 | typedef TensorLinearCubicBezierSurface<Vec3fa> TensorLinearCubicBezierSurface3fa; |
| 402 | } |
| 403 | } |
| 404 | |