1 | // Copyright 2009-2021 Intel Corporation |
---|---|
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "../common/geometry.h" |
7 | |
8 | namespace embree |
9 | { |
10 | static const size_t MAX_PATCH_VALENCE = 16; //!< maximum number of vertices of a patch |
11 | static const size_t MAX_RING_FACE_VALENCE = 64; //!< maximum number of faces per ring |
12 | static const size_t MAX_RING_EDGE_VALENCE = 2*64; //!< maximum number of edges per ring |
13 | |
14 | class CatmullClarkPrecomputedCoefficients |
15 | { |
16 | private: |
17 | |
18 | float table_cos_2PI_div_n[MAX_RING_FACE_VALENCE+1]; |
19 | |
20 | float* table_limittangent_a[MAX_RING_FACE_VALENCE+1]; |
21 | float* table_limittangent_b[MAX_RING_FACE_VALENCE+1]; |
22 | float table_limittangent_c[MAX_RING_FACE_VALENCE+1]; |
23 | |
24 | __forceinline float set_cos_2PI_div_n(const size_t n) { |
25 | if (unlikely(n == 0)) return 1.0f; |
26 | return cosf(2.0f*float(pi)/(float)n); |
27 | } |
28 | |
29 | __forceinline float set_limittangent_a(const size_t i, const size_t n) |
30 | { |
31 | if (unlikely(n == 0)) return 1.0f; |
32 | const float c0 = 1.0f/(float)n * 1.0f / sqrtf(4.0f + cosf(float(pi)/(float)n)*cosf(float(pi)/(float)n)); |
33 | const float c1 = (1.0f/(float)n + cosf(float(pi)/(float)n) * c0); |
34 | return cosf(2.0f*float(pi)*(float)i/(float)n) * c1; |
35 | } |
36 | |
37 | __forceinline float set_limittangent_b(const size_t i, const size_t n) |
38 | { |
39 | if (unlikely(n == 0)) return 1.0f; |
40 | const float c0 = 1.0f/(float)n * 1.0f / sqrtf(4.0f + cosf(float(pi)/(float)n)*cosf(float(pi)/(float)n)); |
41 | return cosf((2.0f*float(pi)*i+float(pi))/(float)n) * c0; |
42 | } |
43 | |
44 | __forceinline float set_limittangent_c(const size_t n) |
45 | { |
46 | if (unlikely(n == 0)) return 1.0f; |
47 | return 2.0f/16.0f * (5.0f + cosf(2.0f*float(pi)/(float)n) + cosf(float(pi)/(float)n) * sqrtf(18.0f+2.0f*cosf(2.0f*float(pi)/(float)n))); |
48 | } |
49 | |
50 | public: |
51 | |
52 | __forceinline float cos_2PI_div_n(const size_t n) |
53 | { |
54 | if (likely(n <= MAX_RING_FACE_VALENCE)) |
55 | return table_cos_2PI_div_n[n]; |
56 | else |
57 | return set_cos_2PI_div_n(n); |
58 | } |
59 | |
60 | __forceinline float limittangent_a(const size_t i, const size_t n) |
61 | { |
62 | assert(n <= MAX_RING_FACE_VALENCE); |
63 | assert(i < n); |
64 | return table_limittangent_a[n][i]; |
65 | } |
66 | |
67 | __forceinline float limittangent_b(const size_t i, const size_t n) |
68 | { |
69 | assert(n <= MAX_RING_FACE_VALENCE); |
70 | assert(i < n); |
71 | return table_limittangent_b[n][i]; |
72 | } |
73 | |
74 | __forceinline float limittangent_c(const size_t n) |
75 | { |
76 | assert(n <= MAX_RING_FACE_VALENCE); |
77 | return table_limittangent_c[n]; |
78 | } |
79 | |
80 | static CatmullClarkPrecomputedCoefficients table; |
81 | |
82 | CatmullClarkPrecomputedCoefficients(); |
83 | ~CatmullClarkPrecomputedCoefficients(); |
84 | }; |
85 | } |
86 |