Fermat
oct.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2018, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
39 #pragma once
40 
41 #include <cugar/basic/numbers.h>
42 #include <cugar/linalg/vector.h>
43 #include <cugar/linalg/matrix.h>
44 
45 namespace cugar {
46 
55 CUGAR_API CUGAR_HOST_DEVICE float oct_basis(const int32 i, const Vector3f& d);
60 
65 CUGAR_API CUGAR_HOST_DEVICE float oct_smooth_basis(const int32 i, const Vector3f& omega);
66 
72 struct Oct_basis
73 {
74  static const int32 COEFFS = 8;
75 
80  CUGAR_HOST CUGAR_DEVICE static float eval(const int32 i, const Vector3f& d) { return oct_basis( i, d ); }
81 
88  CUGAR_API static void clamped_cosine(const Vector3f& normal, const float w, float* coeffs);
89 
94  static void constant(float k, float* coeffs)
95  {
96  for (int32 i = 0; i < 8; ++i)
97  coeffs[i] = k * sqrtf(M_PIf/2.0f);
98  }
99 
102  static float integral(const float* coeffs)
103  {
104  float r = 0.0f;
105  for (int32 i = 0; i < 8; ++i)
106  r += coeffs[i];
107  return r;
108  }
109 
112  template <typename Vector_type>
113  static float integral(const Vector_type& coeffs)
114  {
115  float r = 0.0f;
116  for (int32 i = 0; i < 8; ++i)
117  r += coeffs[i];
118  return r;
119  }
120 
124  static void solve(float* coeffs) {}
125 };
126 
133 {
134  static const int32 COEFFS = 8;
135 
140  CUGAR_HOST_DEVICE static float eval(const int32 i, const Vector3f& d) { return oct_smooth_basis( i, d ); }
141 
148  CUGAR_API static void clamped_cosine(const Vector3f& normal, const float w, float* coeffs);
149 
154  static void constant(float k, float* coeffs)
155  {
156  for (int32 i = 0; i < 8; ++i)
157  coeffs[i] = k * s_K[i];
158  }
159 
162  static float integral(const float* coeffs)
163  {
164  float r = 0.0f;
165  for (int32 i = 0; i < 8; ++i)
166  r += coeffs[i];
167  return r;
168  }
169 
172  template <typename Vector_type>
173  static float integral(const Vector_type& coeffs)
174  {
175  float r = 0.0f;
176  for (int32 i = 0; i < 8; ++i)
177  r += coeffs[i];
178  return r;
179  }
180 
185  static float G(const int32 i, const int32 j) { return s_G[i][j]; }
186 
190  CUGAR_API static void solve(float* coeffs);
191 
192 private:
193  struct Initializer { Initializer(); };
194 
195  friend Initializer;
196 
197  static Matrix<float,8,8> s_G;
198  static float s_K[8];
199  static Initializer s_I;
200 };
201 
202 static Vector3f s_oct_verts[6] = {
203  Vector3f(+1, 0, 0),
204  Vector3f(-1, 0, 0),
205  Vector3f( 0,+1, 0),
206  Vector3f( 0,-1, 0),
207  Vector3f( 0, 0,+1),
208  Vector3f( 0, 0,-1),
209 };
210 static int32 s_oct_faces[8][3] = {
211  {0,2,4},
212  {2,1,4},
213  {1,3,4},
214  {3,0,4},
215  {2,0,5},
216  {1,2,5},
217  {3,1,5},
218  {0,3,5},
219 };
220 
221 // evaluate the i-th octahedral basis
222 inline CUGAR_HOST CUGAR_DEVICE float oct_basis(const int32 i, const Vector3f& omega)
223 {
224  const float norm = sqrtf(2.0f/M_PIf); // sqrt(8) / sqrt(4*PI)
225 
226  // oct_basis
227  return
228  ((1 - 2*(((i+1)>>1)&1))*omega[0] > 0.0f ? 1.0f : 0.0f)*
229  ((1 - 2*((i>>1)&1) )*omega[1] > 0.0f ? 1.0f : 0.0f)*
230  ((1 - 2*(i>>2) )*omega[2] > 0.0f ? 1.0f : 0.0f) * norm;
231 /*
232  // the i-th basis is defined by all directions inside the spherical triangle {v1,v2,v3}
233  const Vector3f v1 = s_oct_verts[ s_oct_faces[i][0] ];
234  const Vector3f v2 = s_oct_verts[ s_oct_faces[i][1] ];
235  const Vector3f v3 = s_oct_verts[ s_oct_faces[i][2] ];
236 
237  //
238  // check whether omega intersects {v1,v2,v3}
239  //
240 
241  // equivalent to checking that all three dot products with omega are positive, but we can make it cheaper...
242 
243  // first, assume v3 is the north/south pole, and check whether omega.z is on the same side or not.
244  if (v3[2] * omega[2] < 0.0f)
245  return 0.0f;
246 
247  // second, project omega on the XY plane, and test whether it intersects the edge (v1,v2):
248  // in order for this to happen, both dot products of omega with v1 and v2 have to be positive.
249  if (dot(v1,omega) < 0.0f || dot(v2,omega) < 0.0f)
250  return 0.0f;
251 
252  return norm;
253  */
254 }
255 
256 // evaluate the i-th smooth octahedral basis
257 inline CUGAR_HOST_DEVICE float oct_smooth_basis(const int32 i, const Vector3f& omega)
258 {
259  const Vector3f c(
260  -0.66666666666666666666f * (((i+1)>>1) & 1) + 0.33333333333333333333f,
261  -0.66666666666666666666f * ((i>>1) & 1) + 0.33333333333333333333f,
262  -0.66666666666666666666f * (i>>2) + 0.33333333333333333333f );
263 
264  const float N = 2.0f;
265  const float norm = 2.170803763674771f; //sqrtf( (N + 1) / (2.0f * M_PIf) );
266 
267  const float d = max( dot( omega, c ), 0.0f );
268  return fast_pow( d, N ) * norm;
269 }
270 
274 } // namespace cugar
static float integral(const float *coeffs)
Definition: oct.h:102
static void solve(float *coeffs)
Definition: oct.h:124
static float integral(const float *coeffs)
Definition: oct.h:162
static void constant(float k, float *coeffs)
Definition: oct.h:154
static CUGAR_HOST_DEVICE float eval(const int32 i, const Vector3f &d)
Definition: oct.h:140
CUGAR_HOST static CUGAR_DEVICE float eval(const int32 i, const Vector3f &d)
Definition: oct.h:80
CUGAR_API CUGAR_HOST_DEVICE float oct_smooth_basis(const int32 i, const Vector3f &omega)
Definition: oct.h:257
static CUGAR_API void clamped_cosine(const Vector3f &normal, const float w, float *coeffs)
Definition: oct.cpp:84
Definition: oct.h:132
static float integral(const Vector_type &coeffs)
Definition: oct.h:173
CUGAR_API CUGAR_HOST_DEVICE float oct_basis(const int32 i, const Vector3f &d)
Definition: oct.h:222
static float integral(const Vector_type &coeffs)
Definition: oct.h:113
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
static void constant(float k, float *coeffs)
Definition: oct.h:94
Definition: oct.h:72
static float G(const int32 i, const int32 j)
Definition: oct.h:185