summaryrefslogtreecommitdiff
path: root/thirdparty/embree/kernels/subdiv/subdivpatch1base.h
blob: c3069dadee79dc8e681d160faed8391a4db7688f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "../geometry/primitive.h"
#include "bspline_patch.h"
#include "bezier_patch.h"
#include "gregory_patch.h"
#include "gregory_patch_dense.h"
#include "tessellation.h"
#include "tessellation_cache.h"
#include "gridrange.h"
#include "patch_eval_grid.h"
#include "feature_adaptive_eval_grid.h"
#include "../common/scene_subdiv_mesh.h"

namespace embree
{
  struct __aligned(64) SubdivPatch1Base
  {
  public:

    enum Type {
      INVALID_PATCH          = 0,
      BSPLINE_PATCH          = 1,  
      BEZIER_PATCH           = 2,  
      GREGORY_PATCH          = 3,
      EVAL_PATCH             = 5,
      BILINEAR_PATCH         = 6,
    };

    enum Flags {
      TRANSITION_PATCH       = 16, 
    };

    /*! Default constructor. */
    __forceinline SubdivPatch1Base () {}

    SubdivPatch1Base (const unsigned int gID,
                      const unsigned int pID,
                      const unsigned int subPatch,
                      const SubdivMesh *const mesh,
                      const size_t time,
                      const Vec2f uv[4],
                      const float edge_level[4],
                      const int subdiv[4],
                      const int simd_width);

    __forceinline bool needsStitching() const {
      return flags & TRANSITION_PATCH;      
    }

    __forceinline Vec2f getUV(const size_t i) const {
      return Vec2f((float)u[i],(float)v[i]) * (8.0f/0x10000);
    }

    static void computeEdgeLevels(const float edge_level[4], const int subdiv[4], float level[4]);
    static Vec2i computeGridSize(const float level[4]);
    bool updateEdgeLevels(const float edge_level[4], const int subdiv[4], const SubdivMesh *const mesh, const int simd_width);

  public:

    __forceinline size_t getGridBytes() const {
      const size_t grid_size_xyzuv = (grid_size_simd_blocks * VSIZEX) * 4;
      return 64*((grid_size_xyzuv+15) / 16);
    }

    __forceinline void write_lock()     { mtx.lock();   }
    __forceinline void write_unlock()   { mtx.unlock(); }
    __forceinline bool try_write_lock() { return mtx.try_lock(); }
    //__forceinline bool try_read_lock()  { return mtx.try_read_lock(); }

    __forceinline void resetRootRef() {
      //assert( mtx.hasInitialState() );
      root_ref = SharedLazyTessellationCache::Tag();
    }

    __forceinline SharedLazyTessellationCache::CacheEntry& entry() {
      return (SharedLazyTessellationCache::CacheEntry&) root_ref;
    }

  public:    
    __forceinline unsigned int geomID() const  {
      return geom;
    } 

    __forceinline unsigned int primID() const  {
      return prim;
    } 

  public:
    SharedLazyTessellationCache::Tag root_ref;
    SpinLock mtx;

    unsigned short u[4];                        //!< 16bit discretized u,v coordinates
    unsigned short v[4];
    float level[4];

    unsigned char flags;
    unsigned char type;
    unsigned short grid_u_res;
    unsigned int geom;                          //!< geometry ID of the subdivision mesh this patch belongs to
    unsigned int prim;                          //!< primitive ID of this subdivision patch
    unsigned short grid_v_res;

    unsigned short grid_size_simd_blocks;
    unsigned int time_;

    struct PatchHalfEdge {
      const HalfEdge* edge;
      unsigned subPatch;
    };

    Vec3fa patch_v[4][4];

    const HalfEdge *edge() const { return ((PatchHalfEdge*)patch_v)->edge; }
    unsigned time() const { return time_; }
    unsigned subPatch() const { return ((PatchHalfEdge*)patch_v)->subPatch; }

    void set_edge(const HalfEdge *h) const { ((PatchHalfEdge*)patch_v)->edge = h; }
    void set_subPatch(const unsigned s) const { ((PatchHalfEdge*)patch_v)->subPatch = s; }
  };

  namespace isa
  {
    Vec3fa patchEval(const SubdivPatch1Base& patch, const float uu, const float vv);
    Vec3fa patchNormal(const SubdivPatch1Base& patch, const float uu, const float vv);
    
    template<typename simdf>
      Vec3<simdf> patchEval(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv); 

    template<typename simdf>
      Vec3<simdf> patchNormal(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv); 
   

    /* eval grid over patch and stich edges when required */      
    void evalGrid(const SubdivPatch1Base& patch,
                  const unsigned x0, const unsigned x1,
                  const unsigned y0, const unsigned y1,
                  const unsigned swidth, const unsigned sheight,
                  float *__restrict__ const grid_x,
                  float *__restrict__ const grid_y,
                  float *__restrict__ const grid_z,
                  float *__restrict__ const grid_u,
                  float *__restrict__ const grid_v,
                  const SubdivMesh* const geom);

    /* eval grid over patch and stich edges when required */      
    BBox3fa evalGridBounds(const SubdivPatch1Base& patch,
                           const unsigned x0, const unsigned x1,
                           const unsigned y0, const unsigned y1,
                           const unsigned swidth, const unsigned sheight,
                           const SubdivMesh* const geom);
  }
}