| 1 | // Copyright 2009-2021 Intel Corporation | 
| 2 | // SPDX-License-Identifier: Apache-2.0 | 
| 3 |  | 
| 4 | #pragma once | 
| 5 |  | 
| 6 | #include "../geometry/primitive.h" | 
| 7 | #include "bspline_patch.h" | 
| 8 | #include "bezier_patch.h" | 
| 9 | #include "gregory_patch.h" | 
| 10 | #include "gregory_patch_dense.h" | 
| 11 | #include "tessellation.h" | 
| 12 | #include "tessellation_cache.h" | 
| 13 | #include "gridrange.h" | 
| 14 | #include "patch_eval_grid.h" | 
| 15 | #include "feature_adaptive_eval_grid.h" | 
| 16 | #include "../common/scene_subdiv_mesh.h" | 
| 17 |  | 
| 18 | namespace embree | 
| 19 | { | 
| 20 |   struct __aligned(64) SubdivPatch1Base | 
| 21 |   { | 
| 22 |   public: | 
| 23 |  | 
| 24 |     enum Type { | 
| 25 |       INVALID_PATCH          = 0, | 
| 26 |       BSPLINE_PATCH          = 1,   | 
| 27 |       BEZIER_PATCH           = 2,   | 
| 28 |       GREGORY_PATCH          = 3, | 
| 29 |       EVAL_PATCH             = 5, | 
| 30 |       BILINEAR_PATCH         = 6, | 
| 31 |     }; | 
| 32 |  | 
| 33 |     enum Flags { | 
| 34 |       TRANSITION_PATCH       = 16,  | 
| 35 |     }; | 
| 36 |  | 
| 37 |     /*! Default constructor. */ | 
| 38 |     __forceinline SubdivPatch1Base () {} | 
| 39 |  | 
| 40 |     SubdivPatch1Base (const unsigned int gID, | 
| 41 |                       const unsigned int pID, | 
| 42 |                       const unsigned int subPatch, | 
| 43 |                       const SubdivMesh *const mesh, | 
| 44 |                       const size_t time, | 
| 45 |                       const Vec2f uv[4], | 
| 46 |                       const float edge_level[4], | 
| 47 |                       const int subdiv[4], | 
| 48 |                       const int simd_width); | 
| 49 |  | 
| 50 |     __forceinline bool needsStitching() const { | 
| 51 |       return flags & TRANSITION_PATCH;       | 
| 52 |     } | 
| 53 |  | 
| 54 |     __forceinline Vec2f getUV(const size_t i) const { | 
| 55 |       return Vec2f((float)u[i],(float)v[i]) * (8.0f/0x10000); | 
| 56 |     } | 
| 57 |  | 
| 58 |     static void computeEdgeLevels(const float edge_level[4], const int subdiv[4], float level[4]); | 
| 59 |     static Vec2i computeGridSize(const float level[4]); | 
| 60 |     bool updateEdgeLevels(const float edge_level[4], const int subdiv[4], const SubdivMesh *const mesh, const int simd_width); | 
| 61 |  | 
| 62 |   public: | 
| 63 |  | 
| 64 |     __forceinline size_t getGridBytes() const { | 
| 65 |       const size_t grid_size_xyzuv = (grid_size_simd_blocks * VSIZEX) * 4; | 
| 66 |       return 64*((grid_size_xyzuv+15) / 16); | 
| 67 |     } | 
| 68 |  | 
| 69 |     __forceinline void write_lock()     { mtx.lock();   } | 
| 70 |     __forceinline void write_unlock()   { mtx.unlock(); } | 
| 71 |     __forceinline bool try_write_lock() { return mtx.try_lock(); } | 
| 72 |     //__forceinline bool try_read_lock()  { return mtx.try_read_lock(); } | 
| 73 |  | 
| 74 |     __forceinline void resetRootRef() { | 
| 75 |       //assert( mtx.hasInitialState() ); | 
| 76 |       root_ref = SharedLazyTessellationCache::Tag(); | 
| 77 |     } | 
| 78 |  | 
| 79 |     __forceinline SharedLazyTessellationCache::CacheEntry& entry() { | 
| 80 |       return (SharedLazyTessellationCache::CacheEntry&) root_ref; | 
| 81 |     } | 
| 82 |  | 
| 83 |   public:     | 
| 84 |     __forceinline unsigned int geomID() const  { | 
| 85 |       return geom; | 
| 86 |     }  | 
| 87 |  | 
| 88 |     __forceinline unsigned int primID() const  { | 
| 89 |       return prim; | 
| 90 |     }  | 
| 91 |  | 
| 92 |   public: | 
| 93 |     SharedLazyTessellationCache::Tag root_ref; | 
| 94 |     SpinLock mtx; | 
| 95 |  | 
| 96 |     unsigned short u[4];                        //!< 16bit discretized u,v coordinates | 
| 97 |     unsigned short v[4]; | 
| 98 |     float level[4]; | 
| 99 |  | 
| 100 |     unsigned char flags; | 
| 101 |     unsigned char type; | 
| 102 |     unsigned short grid_u_res; | 
| 103 |     unsigned int geom;                          //!< geometry ID of the subdivision mesh this patch belongs to | 
| 104 |     unsigned int prim;                          //!< primitive ID of this subdivision patch | 
| 105 |     unsigned short grid_v_res; | 
| 106 |  | 
| 107 |     unsigned short grid_size_simd_blocks; | 
| 108 |     unsigned int time_; | 
| 109 |  | 
| 110 |     struct PatchHalfEdge { | 
| 111 |       const HalfEdge* edge; | 
| 112 |       unsigned subPatch; | 
| 113 |     }; | 
| 114 |  | 
| 115 |     Vec3fa patch_v[4][4]; | 
| 116 |  | 
| 117 |     const HalfEdge *edge() const { return ((PatchHalfEdge*)patch_v)->edge; } | 
| 118 |     unsigned time() const { return time_; } | 
| 119 |     unsigned subPatch() const { return ((PatchHalfEdge*)patch_v)->subPatch; } | 
| 120 |  | 
| 121 |     void set_edge(const HalfEdge *h) const { ((PatchHalfEdge*)patch_v)->edge = h; } | 
| 122 |     void set_subPatch(const unsigned s) const { ((PatchHalfEdge*)patch_v)->subPatch = s; } | 
| 123 |   }; | 
| 124 |  | 
| 125 |   namespace isa | 
| 126 |   { | 
| 127 |     Vec3fa patchEval(const SubdivPatch1Base& patch, const float uu, const float vv); | 
| 128 |     Vec3fa patchNormal(const SubdivPatch1Base& patch, const float uu, const float vv); | 
| 129 |      | 
| 130 |     template<typename simdf> | 
| 131 |       Vec3<simdf> patchEval(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv);  | 
| 132 |  | 
| 133 |     template<typename simdf> | 
| 134 |       Vec3<simdf> patchNormal(const SubdivPatch1Base& patch, const simdf& uu, const simdf& vv);  | 
| 135 |     | 
| 136 |  | 
| 137 |     /* eval grid over patch and stich edges when required */       | 
| 138 |     void evalGrid(const SubdivPatch1Base& patch, | 
| 139 |                   const unsigned x0, const unsigned x1, | 
| 140 |                   const unsigned y0, const unsigned y1, | 
| 141 |                   const unsigned swidth, const unsigned sheight, | 
| 142 |                   float *__restrict__ const grid_x, | 
| 143 |                   float *__restrict__ const grid_y, | 
| 144 |                   float *__restrict__ const grid_z, | 
| 145 |                   float *__restrict__ const grid_u, | 
| 146 |                   float *__restrict__ const grid_v, | 
| 147 |                   const SubdivMesh* const geom); | 
| 148 |  | 
| 149 |     /* eval grid over patch and stich edges when required */       | 
| 150 |     BBox3fa evalGridBounds(const SubdivPatch1Base& patch, | 
| 151 |                            const unsigned x0, const unsigned x1, | 
| 152 |                            const unsigned y0, const unsigned y1, | 
| 153 |                            const unsigned swidth, const unsigned sheight, | 
| 154 |                            const SubdivMesh* const geom); | 
| 155 |   } | 
| 156 | } | 
| 157 |  |