<commit_before>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#pragma once

#include "catmullclark_patch.h"
#include "bspline_patch.h"
#include "gregory_patch.h"

namespace embree
{
  template<typename Vertex>
    struct FeatureAdaptivePointEval
  {
    typedef BSplinePatchTT<Vertex> BSplinePatch;
    typedef CatmullClarkPatchT<Vertex> CatmullClarkPatch;
    typedef GeneralCatmullClarkPatchT<Vertex> GeneralCatmullClarkPatch;

    const float u,v;
    Vertex dst;
        
    __forceinline FeatureAdaptivePointEval (const GeneralCatmullClarkPatch& patch, const float u, const float v)
      : u(u), v(v)
    {
      const float vv = clamp(v,0.0f,1.0f); // FIXME: remove clamps
      const float uu = clamp(u,0.0f,1.0f); 
      eval(patch,Vec2f(uu,vv),size_t(0));
    }
 
    __forceinline Vec2f map_tri_to_quad(const Vec2f& a, const Vec2f& ab, const Vec2f& abc, const Vec2f& ac, const Vec2f& uv)
    {
      const Vec2f A = a, B = ab-a, C = ac-a, D = a-ab-ac+abc;
      float uk = 0.5f, vk = 0.5f;
      const float AA = det(D,C), BB = det(D,A) + det(B,C) + det(uv,D), CC = det(B,A) + det(uv,B);
      const float vv = (-BB+sqrtf(BB*BB-4.0f*AA*CC))/(2.0f*AA);
      const float uu = (uv.x - A.x - vv*C.x)/(B.x + vv*D.x);
      return Vec2f(uu,vv);
    }

    __forceinline bool right_of_line(const Vec2f& A, const Vec2f& B, const Vec2f& P) {
      return det(A-P,B-P) <= 0.0f;
    }

    void eval(const GeneralCatmullClarkPatch& patch, Vec2f uv, const size_t depth) // FIXME: no recursion required
    {
      /* convert into standard quad patch if possible */
      if (likely(patch.isQuadPatch())) 
      {
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));
        CatmullClarkPatch qpatch; patch.init(qpatch);
	eval(qpatch,uv,srange,depth); 
	return;
      }

      /* subdivide patch */
      size_t N;
      array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches; 
      patch.subdivide(patches,N); // FIXME: only have to generate one of the patches

      /* parametrization for triangles */
      if (N == 3) 
      {
        const Vec2f a(0.0f,0.0f), b(1.0f,0.0f), c(0.0f,1.0f);
        const Vec2f ab = 0.5f*(a+b), ac = 0.5f*(a+c), bc = 0.5f*(b+c), abc = (1.0f/3.0f)*(a+b+c);
        const bool ab_abc = right_of_line(ab,abc,uv);
        const bool ac_abc = right_of_line(ac,abc,uv);
        const bool bc_abc = right_of_line(bc,abc,uv);
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));

        const float u = uv.x, v = uv.y, w = 1.0f-u-v;
        if      (!ab_abc &&  ac_abc) eval(patches[0],map_tri_to_quad(a,ab,abc,ac,Vec2f(u,v)),srange,depth+1);
        else if ( ab_abc && !bc_abc) eval(patches[1],map_tri_to_quad(a,ab,abc,ac,Vec2f(v,w)),srange,depth+1);
        else                         eval(patches[2],map_tri_to_quad(a,ab,abc,ac,Vec2f(w,u)),srange,depth+1);
      } 

      /* parametrization for quads */
      else if (N == 4) 
      {
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));
        const Vec2f c = srange.center();
        if (uv.y < c.y) {
          if (uv.x < c.x) eval(patches[0],uv,BBox2f(srange.lower,c),depth+1);
          else            eval(patches[1],uv,BBox2f(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y)),depth+1);
        } else {
          if (uv.x > c.x) eval(patches[2],uv,BBox2f(c,srange.upper),depth+1);
          else            eval(patches[3],uv,BBox2f(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y)),depth+1);
        }
      }

      /* parametrization for arbitrary polygons */
      else 
      {
        const unsigned i = trunc(uv.x); assert(i<N);
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));
        eval(patches[i],Vec2f(floorf(uv.x),uv.y),srange,depth+1); // FIXME: uv encoding creates issues as uv=(1,0) will refer to second quad
      }
    }

    void eval(const CatmullClarkPatch& patch, const Vec2f& uv, const BBox2f& srange, size_t depth)
    {
      if (patch.isRegularOrFinal2(depth)) 
      {
        if (patch.isRegular()) 
        {
          BSplinePatch bspline; bspline.init(patch);
          const float fx = (uv.x-srange.lower.x)*rcp(srange.upper.x-srange.lower.x);
          const float fy = (uv.y-srange.lower.y)*rcp(srange.upper.y-srange.lower.y);
          dst = bspline.eval(fx,fy);
        }
        else 
        {
          const float sx1 = (uv.x-srange.lower.x)*rcp(srange.upper.x-srange.lower.x), sx0 = 1.0f-sx1;
          const float sy1 = (uv.y-srange.lower.y)*rcp(srange.upper.y-srange.lower.y), sy0 = 1.0f-sy1;
          const Vertex P0 = patch.ring[0].getLimitVertex();
          const Vertex P1 = patch.ring[1].getLimitVertex();
          const Vertex P2 = patch.ring[2].getLimitVertex();
          const Vertex P3 = patch.ring[3].getLimitVertex();
          dst = sy0*(sx0*P0+sx1*P1) + sy1*(sx0*P3+sx1*P2);
        }
        return;
      }

      array_t<CatmullClarkPatch,4> patches; 
      patch.subdivide(patches); // FIXME: only have to generate one of the patches

      const Vec2f c = srange.center();
      if (uv.y < c.y) {
        if (uv.x < c.x) eval(patches[0],uv,BBox2f(srange.lower,c),depth+1);
        else            eval(patches[1],uv,BBox2f(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y)),depth+1);
      } else {
        if (uv.x > c.x) eval(patches[2],uv,BBox2f(c,srange.upper),depth+1);
        else            eval(patches[3],uv,BBox2f(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y)),depth+1);
      }
    }
  };

  template<typename Vertex>
    __forceinline Vertex feature_adaptive_point_eval (const GeneralCatmullClarkPatchT<Vertex>& patch, const float u, const float v) {
    FeatureAdaptivePointEval<Vertex> eval(patch,u,v); return eval.dst;
  }

  struct FeatureAdaptiveEval
  {
    const size_t x0,x1;
    const size_t y0,y1;
    const size_t swidth,sheight;
    Vec3fa* const P;
    Vec3fa* const Ng;
    const size_t dwidth,dheight;
    
    __forceinline FeatureAdaptiveEval (const CatmullClarkPatch3fa& patch, 
				       const size_t x0, const size_t x1, const size_t y0, const size_t y1, const size_t swidth, const size_t sheight, 
				       Vec3fa* P, Vec3fa* Ng, const size_t dwidth, const size_t dheight)
      : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), P(P), Ng(Ng), dwidth(dwidth), dheight(dheight)
    {
      assert(swidth < (2<<20) && sheight < (2<<20));
      const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(swidth-1,sheight-1));
      const BBox2f erange(Vec2f(x0,y0),Vec2f(x1,y1));
      eval(patch, srange, erange, 0);
    }

    void dice(const CatmullClarkPatch3fa& patch, const BBox2f& srange, const BBox2f& erange)
    {<commit_msg>removed recursion from FeatureAdaptivePointEval<commit_after>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#pragma once

#include "catmullclark_patch.h"
#include "bspline_patch.h"
#include "gregory_patch.h"

namespace embree
{
  template<typename Vertex>
    struct FeatureAdaptivePointEval
  {
    typedef BSplinePatchTT<Vertex> BSplinePatch;
    typedef CatmullClarkPatchT<Vertex> CatmullClarkPatch;
    typedef GeneralCatmullClarkPatchT<Vertex> GeneralCatmullClarkPatch;

    const float u,v;
    Vertex dst;
        
    __forceinline FeatureAdaptivePointEval (const GeneralCatmullClarkPatch& patch, const float u, const float v)
      : u(u), v(v)
    {
      const float vv = clamp(v,0.0f,1.0f); // FIXME: remove clamps
      const float uu = clamp(u,0.0f,1.0f); 
      eval(patch,Vec2f(uu,vv),size_t(0));
    }
 
    __forceinline Vec2f map_tri_to_quad(const Vec2f& a, const Vec2f& ab, const Vec2f& abc, const Vec2f& ac, const Vec2f& uv)
    {
      const Vec2f A = a, B = ab-a, C = ac-a, D = a-ab-ac+abc;
      float uk = 0.5f, vk = 0.5f;
      const float AA = det(D,C), BB = det(D,A) + det(B,C) + det(uv,D), CC = det(B,A) + det(uv,B);
      const float vv = (-BB+sqrtf(BB*BB-4.0f*AA*CC))/(2.0f*AA);
      const float uu = (uv.x - A.x - vv*C.x)/(B.x + vv*D.x);
      return Vec2f(uu,vv);
    }

    __forceinline bool right_of_line(const Vec2f& A, const Vec2f& B, const Vec2f& P) {
      return det(A-P,B-P) <= 0.0f;
    }

    void eval(const GeneralCatmullClarkPatch& patch, Vec2f uv, const size_t depth) // FIXME: no recursion required
    {
      /* convert into standard quad patch if possible */
      if (likely(patch.isQuadPatch())) 
      {
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));
        CatmullClarkPatch qpatch; patch.init(qpatch);
	eval(qpatch,uv,srange,depth); 
	return;
      }

      /* subdivide patch */
      size_t N;
      array_t<CatmullClarkPatch,GeneralCatmullClarkPatch::SIZE> patches; 
      patch.subdivide(patches,N); // FIXME: only have to generate one of the patches

      /* parametrization for triangles */
      if (N == 3) 
      {
        const Vec2f a(0.0f,0.0f), b(1.0f,0.0f), c(0.0f,1.0f);
        const Vec2f ab = 0.5f*(a+b), ac = 0.5f*(a+c), bc = 0.5f*(b+c), abc = (1.0f/3.0f)*(a+b+c);
        const bool ab_abc = right_of_line(ab,abc,uv);
        const bool ac_abc = right_of_line(ac,abc,uv);
        const bool bc_abc = right_of_line(bc,abc,uv);
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));

        const float u = uv.x, v = uv.y, w = 1.0f-u-v;
        if      (!ab_abc &&  ac_abc) eval(patches[0],map_tri_to_quad(a,ab,abc,ac,Vec2f(u,v)),srange,depth+1);
        else if ( ab_abc && !bc_abc) eval(patches[1],map_tri_to_quad(a,ab,abc,ac,Vec2f(v,w)),srange,depth+1);
        else                         eval(patches[2],map_tri_to_quad(a,ab,abc,ac,Vec2f(w,u)),srange,depth+1);
      } 

      /* parametrization for quads */
      else if (N == 4) 
      {
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));
        const Vec2f c = srange.center();
        if (uv.y < c.y) {
          if (uv.x < c.x) eval(patches[0],uv,BBox2f(srange.lower,c),depth+1);
          else            eval(patches[1],uv,BBox2f(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y)),depth+1);
        } else {
          if (uv.x > c.x) eval(patches[2],uv,BBox2f(c,srange.upper),depth+1);
          else            eval(patches[3],uv,BBox2f(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y)),depth+1);
        }
      }

      /* parametrization for arbitrary polygons */
      else 
      {
        const unsigned i = trunc(uv.x); assert(i<N);
        const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(1.0f,1.0f));
        eval(patches[i],Vec2f(floorf(uv.x),uv.y),srange,depth+1); // FIXME: uv encoding creates issues as uv=(1,0) will refer to second quad
      }
    }

    void eval(CatmullClarkPatch& patch, const Vec2f& uv, BBox2f srange, size_t depth)
    {
      /*! recursively subdivide */
      while (!patch.isRegularOrFinal2(depth)) 
      {
        array_t<CatmullClarkPatch,4> patches; 
        patch.subdivide(patches); // FIXME: only have to generate one of the patches
        
        const Vec2f c = srange.center();
        if (uv.y < c.y) {
          if (uv.x < c.x) { patch = patches[0]; srange = BBox2f(srange.lower,c); }
          else            { patch = patches[1]; srange = BBox2f(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y)); }
        } else {
          if (uv.x > c.x) { patch = patches[2]; srange = BBox2f(c,srange.upper); }
          else            { patch = patches[3]; srange = BBox2f(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y)); }
        }
        depth++;
      }

      /*! use either B-spline or bilinear patch to interpolate */
      if (patch.isRegular()) 
      {
        BSplinePatch bspline; bspline.init(patch);
        const float fx = (uv.x-srange.lower.x)*rcp(srange.upper.x-srange.lower.x);
        const float fy = (uv.y-srange.lower.y)*rcp(srange.upper.y-srange.lower.y);
        dst = bspline.eval(fx,fy);
      }
      else 
      {
        const float sx1 = (uv.x-srange.lower.x)*rcp(srange.upper.x-srange.lower.x), sx0 = 1.0f-sx1;
        const float sy1 = (uv.y-srange.lower.y)*rcp(srange.upper.y-srange.lower.y), sy0 = 1.0f-sy1;
        const Vertex P0 = patch.ring[0].getLimitVertex();
        const Vertex P1 = patch.ring[1].getLimitVertex();
        const Vertex P2 = patch.ring[2].getLimitVertex();
        const Vertex P3 = patch.ring[3].getLimitVertex();
        dst = sy0*(sx0*P0+sx1*P1) + sy1*(sx0*P3+sx1*P2);
      }
    }
  };

  template<typename Vertex>
    __forceinline Vertex feature_adaptive_point_eval (const GeneralCatmullClarkPatchT<Vertex>& patch, const float u, const float v) {
    FeatureAdaptivePointEval<Vertex> eval(patch,u,v); return eval.dst;
  }

  struct FeatureAdaptiveEval
  {
    const size_t x0,x1;
    const size_t y0,y1;
    const size_t swidth,sheight;
    Vec3fa* const P;
    Vec3fa* const Ng;
    const size_t dwidth,dheight;
    
    __forceinline FeatureAdaptiveEval (const CatmullClarkPatch3fa& patch, 
				       const size_t x0, const size_t x1, const size_t y0, const size_t y1, const size_t swidth, const size_t sheight, 
				       Vec3fa* P, Vec3fa* Ng, const size_t dwidth, const size_t dheight)
      : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), P(P), Ng(Ng), dwidth(dwidth), dheight(dheight)
    {
      assert(swidth < (2<<20) && sheight < (2<<20));
      const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(swidth-1,sheight-1));
      const BBox2f erange(Vec2f(x0,y0),Vec2f(x1,y1));
      eval(patch, srange, erange, 0);
    }

    void dice(const CatmullClarkPatch3fa& patch, const BBox2f& srange, const BBox2f& erange)
    {
{'fraction_non_alphanumeric': 0.15795534514746337, 'fraction_numerical': 0.030708208048109528, 'mean_word_length': 2.3252499468198256, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6710719', 'n_tokens_mistral': 5904, 'n_tokens_neox': 5698, 'n_words': 1147}