Path: blob/master/thirdparty/embree/kernels/subdiv/gregory_patch.h
9913 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "catmullclark_patch.h"6#include "bezier_patch.h"7#include "bezier_curve.h"8#include "catmullclark_coefficients.h"910namespace embree11{12template<typename Vertex, typename Vertex_t = Vertex>13class __aligned(64) GregoryPatchT14{15typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;16typedef GeneralCatmullClarkPatchT<Vertex,Vertex_t> GeneralCatmullClarkPatch;17typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;18typedef BezierCurveT<Vertex> BezierCurve;1920public:21Vertex v[4][4];22Vertex f[2][2];2324__forceinline GregoryPatchT() {}2526__forceinline GregoryPatchT(const CatmullClarkPatch& patch) {27init(patch);28}2930__forceinline GregoryPatchT(const CatmullClarkPatch& patch,31const BezierCurve* border0, const BezierCurve* border1, const BezierCurve* border2, const BezierCurve* border3)32{33init_crackfix(patch,border0,border1,border2,border3);34}3536__forceinline GregoryPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {37init(CatmullClarkPatch(edge,vertices,stride));38}3940__forceinline Vertex& p0() { return v[0][0]; }41__forceinline Vertex& p1() { return v[0][3]; }42__forceinline Vertex& p2() { return v[3][3]; }43__forceinline Vertex& p3() { return v[3][0]; }4445__forceinline Vertex& e0_p() { return v[0][1]; }46__forceinline Vertex& e0_m() { return v[1][0]; }47__forceinline Vertex& e1_p() { return v[1][3]; }48__forceinline Vertex& e1_m() { return v[0][2]; }49__forceinline Vertex& e2_p() { return v[3][2]; }50__forceinline Vertex& e2_m() { return v[2][3]; }51__forceinline Vertex& e3_p() { return v[2][0]; }52__forceinline Vertex& e3_m() { return v[3][1]; }5354__forceinline Vertex& f0_p() { return v[1][1]; }55__forceinline Vertex& f1_p() { return v[1][2]; }56__forceinline Vertex& f2_p() { return v[2][2]; }57__forceinline Vertex& f3_p() { return v[2][1]; }58__forceinline Vertex& f0_m() { return f[0][0]; }59__forceinline Vertex& f1_m() { return f[0][1]; }60__forceinline Vertex& f2_m() { return f[1][1]; }61__forceinline Vertex& f3_m() { return f[1][0]; }6263__forceinline const Vertex& p0() const { return v[0][0]; }64__forceinline const Vertex& p1() const { return v[0][3]; }65__forceinline const Vertex& p2() const { return v[3][3]; }66__forceinline const Vertex& p3() const { return v[3][0]; }6768__forceinline const Vertex& e0_p() const { return v[0][1]; }69__forceinline const Vertex& e0_m() const { return v[1][0]; }70__forceinline const Vertex& e1_p() const { return v[1][3]; }71__forceinline const Vertex& e1_m() const { return v[0][2]; }72__forceinline const Vertex& e2_p() const { return v[3][2]; }73__forceinline const Vertex& e2_m() const { return v[2][3]; }74__forceinline const Vertex& e3_p() const { return v[2][0]; }75__forceinline const Vertex& e3_m() const { return v[3][1]; }7677__forceinline const Vertex& f0_p() const { return v[1][1]; }78__forceinline const Vertex& f1_p() const { return v[1][2]; }79__forceinline const Vertex& f2_p() const { return v[2][2]; }80__forceinline const Vertex& f3_p() const { return v[2][1]; }81__forceinline const Vertex& f0_m() const { return f[0][0]; }82__forceinline const Vertex& f1_m() const { return f[0][1]; }83__forceinline const Vertex& f2_m() const { return f[1][1]; }84__forceinline const Vertex& f3_m() const { return f[1][0]; }8586__forceinline Vertex initCornerVertex(const CatmullClarkPatch& irreg_patch, const size_t index) {87return irreg_patch.ring[index].getLimitVertex();88}8990__forceinline Vertex initPositiveEdgeVertex(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx) {91return madd(1.0f/3.0f,irreg_patch.ring[index].getLimitTangent(),p_vtx);92}9394__forceinline Vertex initNegativeEdgeVertex(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx) {95return madd(1.0f/3.0f,irreg_patch.ring[index].getSecondLimitTangent(),p_vtx);96}9798__forceinline Vertex initPositiveEdgeVertex2(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx)99{100CatmullClark1Ring3fa r0,r1,r2;101irreg_patch.ring[index].subdivide(r0);102r0.subdivide(r1);103r1.subdivide(r2);104return madd(8.0f/3.0f,r2.getLimitTangent(),p_vtx);105}106107__forceinline Vertex initNegativeEdgeVertex2(const CatmullClarkPatch& irreg_patch, const size_t index, const Vertex& p_vtx)108{109CatmullClark1Ring3fa r0,r1,r2;110irreg_patch.ring[index].subdivide(r0);111r0.subdivide(r1);112r1.subdivide(r2);113return madd(8.0f/3.0f,r2.getSecondLimitTangent(),p_vtx);114}115116void initFaceVertex(const CatmullClarkPatch& irreg_patch,117const size_t index,118const Vertex& p_vtx,119const Vertex& e0_p_vtx,120const Vertex& e1_m_vtx,121const unsigned int face_valence_p1,122const Vertex& e0_m_vtx,123const Vertex& e3_p_vtx,124const unsigned int face_valence_p3,125Vertex& f_p_vtx,126Vertex& f_m_vtx)127{128const unsigned int face_valence = irreg_patch.ring[index].face_valence;129const unsigned int edge_valence = irreg_patch.ring[index].edge_valence;130const unsigned int border_index = irreg_patch.ring[index].border_index;131132const Vertex& vtx = irreg_patch.ring[index].vtx;133const Vertex e_i = irreg_patch.ring[index].getEdgeCenter(0);134const Vertex c_i_m_1 = irreg_patch.ring[index].getQuadCenter(0);135const Vertex e_i_m_1 = irreg_patch.ring[index].getEdgeCenter(1);136137Vertex c_i, e_i_p_1;138const bool hasHardEdge0 =139std::isinf(irreg_patch.ring[index].vertex_crease_weight) &&140std::isinf(irreg_patch.ring[index].crease_weight[0]);141142if (unlikely((border_index == edge_valence-2) || hasHardEdge0))143{144/* mirror quad center and edge mid-point */145c_i = madd(2.0f, e_i - c_i_m_1, c_i_m_1);146e_i_p_1 = madd(2.0f, vtx - e_i_m_1, e_i_m_1);147}148else149{150c_i = irreg_patch.ring[index].getQuadCenter( face_valence-1 );151e_i_p_1 = irreg_patch.ring[index].getEdgeCenter( face_valence-1 );152}153154Vertex c_i_m_2, e_i_m_2;155const bool hasHardEdge1 =156std::isinf(irreg_patch.ring[index].vertex_crease_weight) &&157std::isinf(irreg_patch.ring[index].crease_weight[1]);158159if (unlikely(border_index == 2 || hasHardEdge1))160{161/* mirror quad center and edge mid-point */162c_i_m_2 = madd(2.0f, e_i_m_1 - c_i_m_1, c_i_m_1);163e_i_m_2 = madd(2.0f, vtx - e_i, + e_i);164}165else166{167c_i_m_2 = irreg_patch.ring[index].getQuadCenter( 1 );168e_i_m_2 = irreg_patch.ring[index].getEdgeCenter( 2 );169}170171const float d = 3.0f;172//const float c = cosf(2.0f*M_PI/(float)face_valence);173//const float c_e_p = cosf(2.0f*M_PI/(float)face_valence_p1);174//const float c_e_m = cosf(2.0f*M_PI/(float)face_valence_p3);175176const float c = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence);177const float c_e_p = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p1);178const float c_e_m = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p3);179180const Vertex r_e_p = 1.0f/3.0f * (e_i_m_1 - e_i_p_1) + 2.0f/3.0f * (c_i_m_1 - c_i);181const Vertex r_e_m = 1.0f/3.0f * (e_i - e_i_m_2) + 2.0f/3.0f * (c_i_m_1 - c_i_m_2);182183f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);184f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);185}186187__noinline void init(const CatmullClarkPatch& patch)188{189assert( patch.ring[0].hasValidPositions() );190assert( patch.ring[1].hasValidPositions() );191assert( patch.ring[2].hasValidPositions() );192assert( patch.ring[3].hasValidPositions() );193194p0() = initCornerVertex(patch,0);195p1() = initCornerVertex(patch,1);196p2() = initCornerVertex(patch,2);197p3() = initCornerVertex(patch,3);198199e0_p() = initPositiveEdgeVertex(patch,0, p0());200e1_p() = initPositiveEdgeVertex(patch,1, p1());201e2_p() = initPositiveEdgeVertex(patch,2, p2());202e3_p() = initPositiveEdgeVertex(patch,3, p3());203204e0_m() = initNegativeEdgeVertex(patch,0, p0());205e1_m() = initNegativeEdgeVertex(patch,1, p1());206e2_m() = initNegativeEdgeVertex(patch,2, p2());207e3_m() = initNegativeEdgeVertex(patch,3, p3());208209const unsigned int face_valence_p0 = patch.ring[0].face_valence;210const unsigned int face_valence_p1 = patch.ring[1].face_valence;211const unsigned int face_valence_p2 = patch.ring[2].face_valence;212const unsigned int face_valence_p3 = patch.ring[3].face_valence;213214initFaceVertex(patch,0,p0(),e0_p(),e1_m(),face_valence_p1,e0_m(),e3_p(),face_valence_p3,f0_p(),f0_m() );215initFaceVertex(patch,1,p1(),e1_p(),e2_m(),face_valence_p2,e1_m(),e0_p(),face_valence_p0,f1_p(),f1_m() );216initFaceVertex(patch,2,p2(),e2_p(),e3_m(),face_valence_p3,e2_m(),e1_p(),face_valence_p1,f2_p(),f2_m() );217initFaceVertex(patch,3,p3(),e3_p(),e0_m(),face_valence_p0,e3_m(),e2_p(),face_valence_p3,f3_p(),f3_m() );218219}220221__noinline void init_crackfix(const CatmullClarkPatch& patch,222const BezierCurve* border0,223const BezierCurve* border1,224const BezierCurve* border2,225const BezierCurve* border3)226{227assert( patch.ring[0].hasValidPositions() );228assert( patch.ring[1].hasValidPositions() );229assert( patch.ring[2].hasValidPositions() );230assert( patch.ring[3].hasValidPositions() );231232p0() = initCornerVertex(patch,0);233p1() = initCornerVertex(patch,1);234p2() = initCornerVertex(patch,2);235p3() = initCornerVertex(patch,3);236237e0_p() = initPositiveEdgeVertex(patch,0, p0());238e1_p() = initPositiveEdgeVertex(patch,1, p1());239e2_p() = initPositiveEdgeVertex(patch,2, p2());240e3_p() = initPositiveEdgeVertex(patch,3, p3());241242e0_m() = initNegativeEdgeVertex(patch,0, p0());243e1_m() = initNegativeEdgeVertex(patch,1, p1());244e2_m() = initNegativeEdgeVertex(patch,2, p2());245e3_m() = initNegativeEdgeVertex(patch,3, p3());246247if (unlikely(border0 != nullptr))248{249p0() = border0->v0;250e0_p() = border0->v1;251e1_m() = border0->v2;252p1() = border0->v3;253}254255if (unlikely(border1 != nullptr))256{257p1() = border1->v0;258e1_p() = border1->v1;259e2_m() = border1->v2;260p2() = border1->v3;261}262263if (unlikely(border2 != nullptr))264{265p2() = border2->v0;266e2_p() = border2->v1;267e3_m() = border2->v2;268p3() = border2->v3;269}270271if (unlikely(border3 != nullptr))272{273p3() = border3->v0;274e3_p() = border3->v1;275e0_m() = border3->v2;276p0() = border3->v3;277}278279const unsigned int face_valence_p0 = patch.ring[0].face_valence;280const unsigned int face_valence_p1 = patch.ring[1].face_valence;281const unsigned int face_valence_p2 = patch.ring[2].face_valence;282const unsigned int face_valence_p3 = patch.ring[3].face_valence;283284initFaceVertex(patch,0,p0(),e0_p(),e1_m(),face_valence_p1,e0_m(),e3_p(),face_valence_p3,f0_p(),f0_m() );285initFaceVertex(patch,1,p1(),e1_p(),e2_m(),face_valence_p2,e1_m(),e0_p(),face_valence_p0,f1_p(),f1_m() );286initFaceVertex(patch,2,p2(),e2_p(),e3_m(),face_valence_p3,e2_m(),e1_p(),face_valence_p1,f2_p(),f2_m() );287initFaceVertex(patch,3,p3(),e3_p(),e0_m(),face_valence_p0,e3_m(),e2_p(),face_valence_p3,f3_p(),f3_m() );288}289290291void computeGregoryPatchFacePoints(const unsigned int face_valence,292const Vertex& r_e_p,293const Vertex& r_e_m,294const Vertex& p_vtx,295const Vertex& e0_p_vtx,296const Vertex& e1_m_vtx,297const unsigned int face_valence_p1,298const Vertex& e0_m_vtx,299const Vertex& e3_p_vtx,300const unsigned int face_valence_p3,301Vertex& f_p_vtx,302Vertex& f_m_vtx,303const float d = 3.0f)304{305//const float c = cosf(2.0*M_PI/(float)face_valence);306//const float c_e_p = cosf(2.0*M_PI/(float)face_valence_p1);307//const float c_e_m = cosf(2.0*M_PI/(float)face_valence_p3);308309const float c = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence);310const float c_e_p = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p1);311const float c_e_m = CatmullClarkPrecomputedCoefficients::table.cos_2PI_div_n(face_valence_p3);312313314f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);315f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);316f_p_vtx = 1.0f / d * (c_e_p * p_vtx + (d - 2.0f*c - c_e_p) * e0_p_vtx + 2.0f*c* e1_m_vtx + r_e_p);317f_m_vtx = 1.0f / d * (c_e_m * p_vtx + (d - 2.0f*c - c_e_m) * e0_m_vtx + 2.0f*c* e3_p_vtx + r_e_m);318}319320__noinline void init(const GeneralCatmullClarkPatch& patch)321{322assert(patch.size() == 4);323#if 0324CatmullClarkPatch qpatch; patch.init(qpatch);325init(qpatch);326#else327const float face_valence_p0 = patch.ring[0].face_valence;328const float face_valence_p1 = patch.ring[1].face_valence;329const float face_valence_p2 = patch.ring[2].face_valence;330const float face_valence_p3 = patch.ring[3].face_valence;331332Vertex p0_r_p, p0_r_m;333patch.ring[0].computeGregoryPatchEdgePoints( p0(), e0_p(), e0_m(), p0_r_p, p0_r_m );334335Vertex p1_r_p, p1_r_m;336patch.ring[1].computeGregoryPatchEdgePoints( p1(), e1_p(), e1_m(), p1_r_p, p1_r_m );337338Vertex p2_r_p, p2_r_m;339patch.ring[2].computeGregoryPatchEdgePoints( p2(), e2_p(), e2_m(), p2_r_p, p2_r_m );340341Vertex p3_r_p, p3_r_m;342patch.ring[3].computeGregoryPatchEdgePoints( p3(), e3_p(), e3_m(), p3_r_p, p3_r_m );343344computeGregoryPatchFacePoints(face_valence_p0, p0_r_p, p0_r_m, p0(), e0_p(), e1_m(), face_valence_p1, e0_m(), e3_p(), face_valence_p3, f0_p(), f0_m() );345computeGregoryPatchFacePoints(face_valence_p1, p1_r_p, p1_r_m, p1(), e1_p(), e2_m(), face_valence_p2, e1_m(), e0_p(), face_valence_p0, f1_p(), f1_m() );346computeGregoryPatchFacePoints(face_valence_p2, p2_r_p, p2_r_m, p2(), e2_p(), e3_m(), face_valence_p3, e2_m(), e1_p(), face_valence_p1, f2_p(), f2_m() );347computeGregoryPatchFacePoints(face_valence_p3, p3_r_p, p3_r_m, p3(), e3_p(), e0_m(), face_valence_p0, e3_m(), e2_p(), face_valence_p3, f3_p(), f3_m() );348349#endif350}351352353__forceinline void convert_to_bezier()354{355f0_p() = (f0_p() + f0_m()) * 0.5f;356f1_p() = (f1_p() + f1_m()) * 0.5f;357f2_p() = (f2_p() + f2_m()) * 0.5f;358f3_p() = (f3_p() + f3_m()) * 0.5f;359f0_m() = Vertex( zero );360f1_m() = Vertex( zero );361f2_m() = Vertex( zero );362f3_m() = Vertex( zero );363}364365static __forceinline void computeInnerVertices(const Vertex matrix[4][4], const Vertex f_m[2][2], const float uu, const float vv,366Vertex_t& matrix_11, Vertex_t& matrix_12, Vertex_t& matrix_22, Vertex_t& matrix_21)367{368if (unlikely(uu == 0.0f || uu == 1.0f || vv == 0.0f || vv == 1.0f))369{370matrix_11 = matrix[1][1];371matrix_12 = matrix[1][2];372matrix_22 = matrix[2][2];373matrix_21 = matrix[2][1];374}375else376{377const Vertex_t f0_p = matrix[1][1];378const Vertex_t f1_p = matrix[1][2];379const Vertex_t f2_p = matrix[2][2];380const Vertex_t f3_p = matrix[2][1];381382const Vertex_t f0_m = f_m[0][0];383const Vertex_t f1_m = f_m[0][1];384const Vertex_t f2_m = f_m[1][1];385const Vertex_t f3_m = f_m[1][0];386387matrix_11 = ( uu * f0_p + vv * f0_m)*rcp(uu+vv);388matrix_12 = ((1.0f-uu) * f1_m + vv * f1_p)*rcp(1.0f-uu+vv);389matrix_22 = ((1.0f-uu) * f2_p + (1.0f-vv) * f2_m)*rcp(2.0f-uu-vv);390matrix_21 = ( uu * f3_m + (1.0f-vv) * f3_p)*rcp(1.0f+uu-vv);391}392}393394template<typename vfloat>395static __forceinline void computeInnerVertices(const Vertex v[4][4], const Vertex f[2][2],396size_t i, const vfloat& uu, const vfloat& vv, vfloat& matrix_11, vfloat& matrix_12, vfloat& matrix_22, vfloat& matrix_21)397{398const auto m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);399400const vfloat f0_p = v[1][1][i];401const vfloat f1_p = v[1][2][i];402const vfloat f2_p = v[2][2][i];403const vfloat f3_p = v[2][1][i];404405const vfloat f0_m = f[0][0][i];406const vfloat f1_m = f[0][1][i];407const vfloat f2_m = f[1][1][i];408const vfloat f3_m = f[1][0][i];409410const vfloat one_minus_uu = vfloat(1.0f) - uu;411const vfloat one_minus_vv = vfloat(1.0f) - vv;412413const vfloat f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);414const vfloat f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);415const vfloat f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);416const vfloat f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);417418matrix_11 = select(m_border,f0_p,f0_i);419matrix_12 = select(m_border,f1_p,f1_i);420matrix_22 = select(m_border,f2_p,f2_i);421matrix_21 = select(m_border,f3_p,f3_i);422}423424static __forceinline Vertex eval(const Vertex matrix[4][4], const Vertex f[2][2], const float& uu, const float& vv)425{426Vertex_t v_11, v_12, v_22, v_21;427computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);428429const Vec4<float> Bu = BezierBasis::eval(uu);430const Vec4<float> Bv = BezierBasis::eval(vv);431432return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),433madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),434madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),435Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));436}437438static __forceinline Vertex eval_du(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative439{440Vertex_t v_11, v_12, v_22, v_21;441computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);442443const Vec4<float> Bu = BezierBasis::derivative(uu);444const Vec4<float> Bv = BezierBasis::eval(vv);445446return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),447madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),448madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),449Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));450}451452static __forceinline Vertex eval_dv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative453{454Vertex_t v_11, v_12, v_22, v_21;455computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);456457const Vec4<float> Bu = BezierBasis::eval(uu);458const Vec4<float> Bv = BezierBasis::derivative(vv);459460return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),461madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),462madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),463Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));464}465466static __forceinline Vertex eval_dudu(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative467{468Vertex_t v_11, v_12, v_22, v_21;469computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);470471const Vec4<float> Bu = BezierBasis::derivative2(uu);472const Vec4<float> Bv = BezierBasis::eval(vv);473474return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),475madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),476madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),477Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));478}479480static __forceinline Vertex eval_dvdv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative481{482Vertex_t v_11, v_12, v_22, v_21;483computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);484485const Vec4<float> Bu = BezierBasis::eval(uu);486const Vec4<float> Bv = BezierBasis::derivative2(vv);487488return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),489madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),490madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),491Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));492}493494static __forceinline Vertex eval_dudv(const Vertex matrix[4][4], const Vertex f[2][2], const float uu, const float vv) // approximative derivative495{496Vertex_t v_11, v_12, v_22, v_21;497computeInnerVertices(matrix,f,uu,vv,v_11, v_12, v_22, v_21);498499const Vec4<float> Bu = BezierBasis::derivative(uu);500const Vec4<float> Bv = BezierBasis::derivative(vv);501502return madd(Bv.x,madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3]))),503madd(Bv.y,madd(Bu.x,matrix[1][0],madd(Bu.y,v_11 ,madd(Bu.z,v_12 ,Bu.w * matrix[1][3]))),504madd(Bv.z,madd(Bu.x,matrix[2][0],madd(Bu.y,v_21 ,madd(Bu.z,v_22 ,Bu.w * matrix[2][3]))),505Bv.w*madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3]))))));506}507508__forceinline Vertex eval(const float uu, const float vv) const {509return eval(v,f,uu,vv);510}511512__forceinline Vertex eval_du( const float uu, const float vv) const {513return eval_du(v,f,uu,vv);514}515516__forceinline Vertex eval_dv( const float uu, const float vv) const {517return eval_dv(v,f,uu,vv);518}519520__forceinline Vertex eval_dudu( const float uu, const float vv) const {521return eval_dudu(v,f,uu,vv);522}523524__forceinline Vertex eval_dvdv( const float uu, const float vv) const {525return eval_dvdv(v,f,uu,vv);526}527528__forceinline Vertex eval_dudv( const float uu, const float vv) const {529return eval_dudv(v,f,uu,vv);530}531532static __forceinline Vertex normal(const Vertex matrix[4][4], const Vertex f_m[2][2], const float uu, const float vv) // FIXME: why not using basis functions533{534/* interpolate inner vertices */535Vertex_t matrix_11, matrix_12, matrix_22, matrix_21;536computeInnerVertices(matrix,f_m,uu,vv,matrix_11, matrix_12, matrix_22, matrix_21);537538/* tangentU */539const Vertex_t col0 = deCasteljau(vv, (Vertex_t)matrix[0][0], (Vertex_t)matrix[1][0], (Vertex_t)matrix[2][0], (Vertex_t)matrix[3][0]);540const Vertex_t col1 = deCasteljau(vv, (Vertex_t)matrix[0][1], (Vertex_t)matrix_11 , (Vertex_t)matrix_21 , (Vertex_t)matrix[3][1]);541const Vertex_t col2 = deCasteljau(vv, (Vertex_t)matrix[0][2], (Vertex_t)matrix_12 , (Vertex_t)matrix_22 , (Vertex_t)matrix[3][2]);542const Vertex_t col3 = deCasteljau(vv, (Vertex_t)matrix[0][3], (Vertex_t)matrix[1][3], (Vertex_t)matrix[2][3], (Vertex_t)matrix[3][3]);543544const Vertex_t tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);545546/* tangentV */547const Vertex_t row0 = deCasteljau(uu, (Vertex_t)matrix[0][0], (Vertex_t)matrix[0][1], (Vertex_t)matrix[0][2], (Vertex_t)matrix[0][3]);548const Vertex_t row1 = deCasteljau(uu, (Vertex_t)matrix[1][0], (Vertex_t)matrix_11 , (Vertex_t)matrix_12 , (Vertex_t)matrix[1][3]);549const Vertex_t row2 = deCasteljau(uu, (Vertex_t)matrix[2][0], (Vertex_t)matrix_21 , (Vertex_t)matrix_22 , (Vertex_t)matrix[2][3]);550const Vertex_t row3 = deCasteljau(uu, (Vertex_t)matrix[3][0], (Vertex_t)matrix[3][1], (Vertex_t)matrix[3][2], (Vertex_t)matrix[3][3]);551552const Vertex_t tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);553554/* normal = tangentU x tangentV */555const Vertex_t n = cross(tangentU,tangentV);556557return n;558}559560__forceinline Vertex normal( const float uu, const float vv) const {561return normal(v,f,uu,vv);562}563564__forceinline void eval(const float u, const float v,565Vertex* P, Vertex* dPdu, Vertex* dPdv,566Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,567const float dscale = 1.0f) const568{569if (P) {570*P = eval(u,v);571}572if (dPdu) {573assert(dPdu); *dPdu = eval_du(u,v)*dscale;574assert(dPdv); *dPdv = eval_dv(u,v)*dscale;575}576if (ddPdudu) {577assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);578assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);579assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);580}581}582583template<class vfloat>584static __forceinline vfloat eval(const Vertex v[4][4], const Vertex f[2][2],585const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n,586vfloat& matrix_11, vfloat& matrix_12, vfloat& matrix_22, vfloat& matrix_21)587{588const vfloat curve0_x = madd(v_n[0],vfloat(v[0][0][i]),madd(v_n[1],vfloat(v[1][0][i]),madd(v_n[2],vfloat(v[2][0][i]),v_n[3] * vfloat(v[3][0][i]))));589const vfloat curve1_x = madd(v_n[0],vfloat(v[0][1][i]),madd(v_n[1],vfloat(matrix_11 ),madd(v_n[2],vfloat(matrix_21 ),v_n[3] * vfloat(v[3][1][i]))));590const vfloat curve2_x = madd(v_n[0],vfloat(v[0][2][i]),madd(v_n[1],vfloat(matrix_12 ),madd(v_n[2],vfloat(matrix_22 ),v_n[3] * vfloat(v[3][2][i]))));591const vfloat curve3_x = madd(v_n[0],vfloat(v[0][3][i]),madd(v_n[1],vfloat(v[1][3][i]),madd(v_n[2],vfloat(v[2][3][i]),v_n[3] * vfloat(v[3][3][i]))));592return madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));593}594595template<typename vbool, typename vfloat>596static __forceinline void eval(const Vertex v[4][4], const Vertex f[2][2],597const vbool& valid, const vfloat& uu, const vfloat& vv,598float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,599const float dscale, const size_t dstride, const size_t N)600{601if (P) {602const Vec4<vfloat> u_n = BezierBasis::eval(uu);603const Vec4<vfloat> v_n = BezierBasis::eval(vv);604for (size_t i=0; i<N; i++) {605vfloat matrix_11, matrix_12, matrix_22, matrix_21;606computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times607vfloat::store(valid,P+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21));608}609}610if (dPdu)611{612{613assert(dPdu);614const Vec4<vfloat> u_n = BezierBasis::derivative(uu);615const Vec4<vfloat> v_n = BezierBasis::eval(vv);616for (size_t i=0; i<N; i++) {617vfloat matrix_11, matrix_12, matrix_22, matrix_21;618computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times619vfloat::store(valid,dPdu+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*dscale);620}621}622{623assert(dPdv);624const Vec4<vfloat> u_n = BezierBasis::eval(uu);625const Vec4<vfloat> v_n = BezierBasis::derivative(vv);626for (size_t i=0; i<N; i++) {627vfloat matrix_11, matrix_12, matrix_22, matrix_21;628computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times629vfloat::store(valid,dPdv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*dscale);630}631}632}633if (ddPdudu)634{635{636assert(ddPdudu);637const Vec4<vfloat> u_n = BezierBasis::derivative2(uu);638const Vec4<vfloat> v_n = BezierBasis::eval(vv);639for (size_t i=0; i<N; i++) {640vfloat matrix_11, matrix_12, matrix_22, matrix_21;641computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times642vfloat::store(valid,ddPdudu+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));643}644}645{646assert(ddPdvdv);647const Vec4<vfloat> u_n = BezierBasis::eval(uu);648const Vec4<vfloat> v_n = BezierBasis::derivative2(vv);649for (size_t i=0; i<N; i++) {650vfloat matrix_11, matrix_12, matrix_22, matrix_21;651computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times652vfloat::store(valid,ddPdvdv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));653}654}655{656assert(ddPdudv);657const Vec4<vfloat> u_n = BezierBasis::derivative(uu);658const Vec4<vfloat> v_n = BezierBasis::derivative(vv);659for (size_t i=0; i<N; i++) {660vfloat matrix_11, matrix_12, matrix_22, matrix_21;661computeInnerVertices(v,f,i,uu,vv,matrix_11,matrix_12,matrix_22,matrix_21); // FIXME: calculated multiple times662vfloat::store(valid,ddPdudv+i*dstride,eval(v,f,i,uu,vv,u_n,v_n,matrix_11,matrix_12,matrix_22,matrix_21)*sqr(dscale));663}664}665}666}667668template<typename vbool, typename vfloat>669__forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,670float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,671const float dscale, const size_t dstride, const size_t N) const {672eval(v,f,valid,uu,vv,P,dPdu,dPdv,ddPdudu,ddPdvdv,ddPdudv,dscale,dstride,N);673}674675template<class T>676static __forceinline Vec3<T> eval_t(const Vertex matrix[4][4], const Vec3<T> f[2][2], const T& uu, const T& vv)677{678typedef typename T::Bool M;679const M m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);680681const Vec3<T> f0_p = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);682const Vec3<T> f1_p = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);683const Vec3<T> f2_p = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);684const Vec3<T> f3_p = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);685686const Vec3<T> f0_m = f[0][0];687const Vec3<T> f1_m = f[0][1];688const Vec3<T> f2_m = f[1][1];689const Vec3<T> f3_m = f[1][0];690691const T one_minus_uu = T(1.0f) - uu;692const T one_minus_vv = T(1.0f) - vv;693694const Vec3<T> f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);695const Vec3<T> f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);696const Vec3<T> f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);697const Vec3<T> f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);698699const Vec3<T> F0( select(m_border,f0_p.x,f0_i.x), select(m_border,f0_p.y,f0_i.y), select(m_border,f0_p.z,f0_i.z) );700const Vec3<T> F1( select(m_border,f1_p.x,f1_i.x), select(m_border,f1_p.y,f1_i.y), select(m_border,f1_p.z,f1_i.z) );701const Vec3<T> F2( select(m_border,f2_p.x,f2_i.x), select(m_border,f2_p.y,f2_i.y), select(m_border,f2_p.z,f2_i.z) );702const Vec3<T> F3( select(m_border,f3_p.x,f3_i.x), select(m_border,f3_p.y,f3_i.y), select(m_border,f3_p.z,f3_i.z) );703704const T B0_u = one_minus_uu * one_minus_uu * one_minus_uu;705const T B0_v = one_minus_vv * one_minus_vv * one_minus_vv;706const T B1_u = 3.0f * (one_minus_uu * uu * one_minus_uu);707const T B1_v = 3.0f * (one_minus_vv * vv * one_minus_vv);708const T B2_u = 3.0f * (uu * one_minus_uu * uu);709const T B2_v = 3.0f * (vv * one_minus_vv * vv);710const T B3_u = uu * uu * uu;711const T B3_v = vv * vv * vv;712713const T x = madd(B0_v,madd(B0_u,matrix[0][0].x,madd(B1_u,matrix[0][1].x,madd(B2_u,matrix[0][2].x,B3_u * matrix[0][3].x))),714madd(B1_v,madd(B0_u,matrix[1][0].x,madd(B1_u,F0.x ,madd(B2_u,F1.x ,B3_u * matrix[1][3].x))),715madd(B2_v,madd(B0_u,matrix[2][0].x,madd(B1_u,F3.x ,madd(B2_u,F2.x ,B3_u * matrix[2][3].x))),716B3_v*madd(B0_u,matrix[3][0].x,madd(B1_u,matrix[3][1].x,madd(B2_u,matrix[3][2].x,B3_u * matrix[3][3].x))))));717718const T y = madd(B0_v,madd(B0_u,matrix[0][0].y,madd(B1_u,matrix[0][1].y,madd(B2_u,matrix[0][2].y,B3_u * matrix[0][3].y))),719madd(B1_v,madd(B0_u,matrix[1][0].y,madd(B1_u,F0.y ,madd(B2_u,F1.y ,B3_u * matrix[1][3].y))),720madd(B2_v,madd(B0_u,matrix[2][0].y,madd(B1_u,F3.y ,madd(B2_u,F2.y ,B3_u * matrix[2][3].y))),721B3_v*madd(B0_u,matrix[3][0].y,madd(B1_u,matrix[3][1].y,madd(B2_u,matrix[3][2].y,B3_u * matrix[3][3].y))))));722723const T z = madd(B0_v,madd(B0_u,matrix[0][0].z,madd(B1_u,matrix[0][1].z,madd(B2_u,matrix[0][2].z,B3_u * matrix[0][3].z))),724madd(B1_v,madd(B0_u,matrix[1][0].z,madd(B1_u,F0.z ,madd(B2_u,F1.z ,B3_u * matrix[1][3].z))),725madd(B2_v,madd(B0_u,matrix[2][0].z,madd(B1_u,F3.z ,madd(B2_u,F2.z ,B3_u * matrix[2][3].z))),726B3_v*madd(B0_u,matrix[3][0].z,madd(B1_u,matrix[3][1].z,madd(B2_u,matrix[3][2].z,B3_u * matrix[3][3].z))))));727728return Vec3<T>(x,y,z);729}730731template<class T>732__forceinline Vec3<T> eval(const T& uu, const T& vv) const733{734Vec3<T> ff[2][2];735ff[0][0] = Vec3<T>(f[0][0]);736ff[0][1] = Vec3<T>(f[0][1]);737ff[1][1] = Vec3<T>(f[1][1]);738ff[1][0] = Vec3<T>(f[1][0]);739return eval_t(v,ff,uu,vv);740}741742template<class T>743static __forceinline Vec3<T> normal_t(const Vertex matrix[4][4], const Vec3<T> f[2][2], const T& uu, const T& vv)744{745typedef typename T::Bool M;746747const Vec3<T> f0_p = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);748const Vec3<T> f1_p = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);749const Vec3<T> f2_p = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);750const Vec3<T> f3_p = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);751752const Vec3<T> f0_m = f[0][0];753const Vec3<T> f1_m = f[0][1];754const Vec3<T> f2_m = f[1][1];755const Vec3<T> f3_m = f[1][0];756757const T one_minus_uu = T(1.0f) - uu;758const T one_minus_vv = T(1.0f) - vv;759760const Vec3<T> f0_i = ( uu * f0_p + vv * f0_m) * rcp(uu+vv);761const Vec3<T> f1_i = (one_minus_uu * f1_m + vv * f1_p) * rcp(one_minus_uu+vv);762const Vec3<T> f2_i = (one_minus_uu * f2_p + one_minus_vv * f2_m) * rcp(one_minus_uu+one_minus_vv);763const Vec3<T> f3_i = ( uu * f3_m + one_minus_vv * f3_p) * rcp(uu+one_minus_vv);764765#if 1766const M m_corner0 = (uu == 0.0f) & (vv == 0.0f);767const M m_corner1 = (uu == 1.0f) & (vv == 0.0f);768const M m_corner2 = (uu == 1.0f) & (vv == 1.0f);769const M m_corner3 = (uu == 0.0f) & (vv == 1.0f);770const Vec3<T> matrix_11( select(m_corner0,f0_p.x,f0_i.x), select(m_corner0,f0_p.y,f0_i.y), select(m_corner0,f0_p.z,f0_i.z) );771const Vec3<T> matrix_12( select(m_corner1,f1_p.x,f1_i.x), select(m_corner1,f1_p.y,f1_i.y), select(m_corner1,f1_p.z,f1_i.z) );772const Vec3<T> matrix_22( select(m_corner2,f2_p.x,f2_i.x), select(m_corner2,f2_p.y,f2_i.y), select(m_corner2,f2_p.z,f2_i.z) );773const Vec3<T> matrix_21( select(m_corner3,f3_p.x,f3_i.x), select(m_corner3,f3_p.y,f3_i.y), select(m_corner3,f3_p.z,f3_i.z) );774#else775const M m_border = (uu == 0.0f) | (uu == 1.0f) | (vv == 0.0f) | (vv == 1.0f);776const Vec3<T> matrix_11( select(m_border,f0_p.x,f0_i.x), select(m_border,f0_p.y,f0_i.y), select(m_border,f0_p.z,f0_i.z) );777const Vec3<T> matrix_12( select(m_border,f1_p.x,f1_i.x), select(m_border,f1_p.y,f1_i.y), select(m_border,f1_p.z,f1_i.z) );778const Vec3<T> matrix_22( select(m_border,f2_p.x,f2_i.x), select(m_border,f2_p.y,f2_i.y), select(m_border,f2_p.z,f2_i.z) );779const Vec3<T> matrix_21( select(m_border,f3_p.x,f3_i.x), select(m_border,f3_p.y,f3_i.y), select(m_border,f3_p.z,f3_i.z) );780#endif781782const Vec3<T> matrix_00 = Vec3<T>(matrix[0][0].x,matrix[0][0].y,matrix[0][0].z);783const Vec3<T> matrix_10 = Vec3<T>(matrix[1][0].x,matrix[1][0].y,matrix[1][0].z);784const Vec3<T> matrix_20 = Vec3<T>(matrix[2][0].x,matrix[2][0].y,matrix[2][0].z);785const Vec3<T> matrix_30 = Vec3<T>(matrix[3][0].x,matrix[3][0].y,matrix[3][0].z);786787const Vec3<T> matrix_01 = Vec3<T>(matrix[0][1].x,matrix[0][1].y,matrix[0][1].z);788const Vec3<T> matrix_02 = Vec3<T>(matrix[0][2].x,matrix[0][2].y,matrix[0][2].z);789const Vec3<T> matrix_03 = Vec3<T>(matrix[0][3].x,matrix[0][3].y,matrix[0][3].z);790791const Vec3<T> matrix_31 = Vec3<T>(matrix[3][1].x,matrix[3][1].y,matrix[3][1].z);792const Vec3<T> matrix_32 = Vec3<T>(matrix[3][2].x,matrix[3][2].y,matrix[3][2].z);793const Vec3<T> matrix_33 = Vec3<T>(matrix[3][3].x,matrix[3][3].y,matrix[3][3].z);794795const Vec3<T> matrix_13 = Vec3<T>(matrix[1][3].x,matrix[1][3].y,matrix[1][3].z);796const Vec3<T> matrix_23 = Vec3<T>(matrix[2][3].x,matrix[2][3].y,matrix[2][3].z);797798/* tangentU */799const Vec3<T> col0 = deCasteljau(vv, matrix_00, matrix_10, matrix_20, matrix_30);800const Vec3<T> col1 = deCasteljau(vv, matrix_01, matrix_11, matrix_21, matrix_31);801const Vec3<T> col2 = deCasteljau(vv, matrix_02, matrix_12, matrix_22, matrix_32);802const Vec3<T> col3 = deCasteljau(vv, matrix_03, matrix_13, matrix_23, matrix_33);803804const Vec3<T> tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);805806/* tangentV */807const Vec3<T> row0 = deCasteljau(uu, matrix_00, matrix_01, matrix_02, matrix_03);808const Vec3<T> row1 = deCasteljau(uu, matrix_10, matrix_11, matrix_12, matrix_13);809const Vec3<T> row2 = deCasteljau(uu, matrix_20, matrix_21, matrix_22, matrix_23);810const Vec3<T> row3 = deCasteljau(uu, matrix_30, matrix_31, matrix_32, matrix_33);811812const Vec3<T> tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);813814/* normal = tangentU x tangentV */815const Vec3<T> n = cross(tangentU,tangentV);816return n;817}818819template<class T>820__forceinline Vec3<T> normal(const T& uu, const T& vv) const821{822Vec3<T> ff[2][2];823ff[0][0] = Vec3<T>(f[0][0]);824ff[0][1] = Vec3<T>(f[0][1]);825ff[1][1] = Vec3<T>(f[1][1]);826ff[1][0] = Vec3<T>(f[1][0]);827return normal_t(v,ff,uu,vv);828}829830__forceinline BBox<Vertex> bounds() const831{832const Vertex *const cv = &v[0][0];833BBox<Vertex> bounds (cv[0]);834for (size_t i=1; i<16; i++)835bounds.extend( cv[i] );836bounds.extend(f[0][0]);837bounds.extend(f[1][0]);838bounds.extend(f[1][1]);839bounds.extend(f[1][1]);840return bounds;841}842843friend embree_ostream operator<<(embree_ostream o, const GregoryPatchT& p)844{845for (size_t y=0; y<4; y++)846for (size_t x=0; x<4; x++)847o << "v[" << y << "][" << x << "] " << p.v[y][x] << embree_endl;848849for (size_t y=0; y<2; y++)850for (size_t x=0; x<2; x++)851o << "f[" << y << "][" << x << "] " << p.f[y][x] << embree_endl;852return o;853}854};855856typedef GregoryPatchT<Vec3fa,Vec3fa_t> GregoryPatch3fa;857858template<typename Vertex, typename Vertex_t>859__forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT (const HalfEdge* edge, const char* vertices, size_t stride)860{861CatmullClarkPatchT<Vertex,Vertex_t> patch(edge,vertices,stride);862GregoryPatchT<Vertex,Vertex_t> gpatch(patch);863gpatch.convert_to_bezier();864for (size_t y=0; y<4; y++)865for (size_t x=0; x<4; x++)866matrix[y][x] = (Vertex_t)gpatch.v[y][x];867}868869template<typename Vertex, typename Vertex_t>870__forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch)871{872GregoryPatchT<Vertex,Vertex_t> gpatch(patch);873gpatch.convert_to_bezier();874for (size_t y=0; y<4; y++)875for (size_t x=0; x<4; x++)876matrix[y][x] = (Vertex_t)gpatch.v[y][x];877}878879template<typename Vertex, typename Vertex_t>880__forceinline BezierPatchT<Vertex,Vertex_t>::BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch,881const BezierCurveT<Vertex>* border0,882const BezierCurveT<Vertex>* border1,883const BezierCurveT<Vertex>* border2,884const BezierCurveT<Vertex>* border3)885{886GregoryPatchT<Vertex,Vertex_t> gpatch(patch,border0,border1,border2,border3);887gpatch.convert_to_bezier();888for (size_t y=0; y<4; y++)889for (size_t x=0; x<4; x++)890matrix[y][x] = (Vertex_t)gpatch.v[y][x];891}892}893894895