SCM Library
Spherical Cube Map rendering library
 All Classes Files Functions Variables Friends Pages
scm-index.hpp
1 // Copyright (C) 2011-2012 Robert Kooima
2 //
3 // LIBSCM is free software; you can redistribute it and/or modify it under the
4 // terms of the GNU General Public License as published by the Free Software
5 // Foundation; either version 2 of the License, or (at your option) any later
6 // version.
7 //
8 // This program is distributed in the hope that it will be useful, but WITH-
9 // OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 // more details.
12 
13 #ifndef SCM_INDEX_HPP
14 #define SCM_INDEX_HPP
15 
16 // The following functions compute SCM page index relationships. There is quite
17 // a bit of redundant computation in their implementation, and it is expected
18 // that the compiler will aggressively inline and reduce common sub-expressions.
19 
20 // These calculations are performed using 64-bit signed indices. They're 64-bit
21 // because 31-bit indices have already been found in the wild, and increasing
22 // data set sizes are expected. The sign is useful for exception signaling.
23 
24 // Calculate the integer binary log of n. --------------------------------------
25 
26 static inline long long log2(long long n)
27 {
28  unsigned long long v = (unsigned long long) n;
29  unsigned long long r;
30  unsigned long long s;
31 
32  r = (v > 0xFFFFFFFFULL) << 5; v >>= r;
33  s = (v > 0xFFFFULL ) << 4; v >>= s; r |= s;
34  s = (v > 0xFFULL ) << 3; v >>= s; r |= s;
35  s = (v > 0xFULL ) << 2; v >>= s; r |= s;
36  s = (v > 0x3ULL ) << 1; v >>= s; r |= s;
37 
38  return (long long) (r | (v >> 1));
39 }
40 
41 // Calculate the number of pages in an SCM of depth d. -------------------------
42 
43 static inline long long scm_page_count(long long d)
44 {
45  return (1LL << (2 * d + 3)) - 2;
46 }
47 
48 // Calculate the subdivision level at which page i appears. --------------------
49 
50 static inline long long scm_page_level(long long i)
51 {
52  return (log2(i + 2) - 1) / 2;
53 }
54 
55 // Calculate the root page in the ancestry of page i. --------------------------
56 
57 static inline long long scm_page_root(long long i)
58 {
59  long long n = 1LL << (2 * scm_page_level(i));
60  return (i - 2 * (n - 1)) / n;
61 }
62 
63 // Calculate the tile number (face index) of page i. ---------------------------
64 
65 static inline long long scm_page_tile(long long i)
66 {
67  long long n = 1LL << (2 * scm_page_level(i));
68  return (i - 2 * (n - 1)) % n;
69 }
70 
71 // Calculate the tile row of page i. -------------------------------------------
72 
73 static inline long long scm_page_row(long long i)
74 {
75  return scm_page_tile(i) / (1LL << scm_page_level(i));
76 }
77 
78 // Calculate the tile column of page i. ----------------------------------------
79 
80 static inline long long scm_page_col(long long i)
81 {
82  return scm_page_tile(i) % (1LL << scm_page_level(i));
83 }
84 
85 // Calculate the index of the page on root a at level l, row r, column c. -----
86 
87 static inline long long scm_page_index(long long a, long long l,
88  long long r, long long c)
89 {
90  return scm_page_count(l - 1) + (a << (2 * l)) + (r << l) + c;
91 }
92 
93 // Calculate the parent page of page i. ----------------------------------------
94 
95 static inline long long scm_page_parent(long long i)
96 {
97  return scm_page_index(scm_page_root(i), scm_page_level(i) - 1,
98  scm_page_row (i) / 2,
99  scm_page_col (i) / 2);
100 }
101 
102 // Calculate child page k of page i. -------------------------------------------
103 
104 static inline long long scm_page_child(long long i, long long k)
105 {
106  return scm_page_index(scm_page_root(i), scm_page_level(i) + 1,
107  scm_page_row (i) * 2 + k / 2,
108  scm_page_col (i) * 2 + k % 2);
109 }
110 
111 // Calculate the order (child index) of page i. --------------------------------
112 
113 static inline long long scm_page_order(long long i)
114 {
115  return 2 * (scm_page_row(i) % 2)
116  + (scm_page_col(i) % 2);
117 }
118 
119 //------------------------------------------------------------------------------
120 
121 void scm_locate(long long *, double *, double *, const double *);
122 void scm_vector(long long, double, double, double *);
123 
124 long long scm_page_north(long long);
125 long long scm_page_south(long long);
126 long long scm_page_west (long long);
127 long long scm_page_east (long long);
128 
129 void scm_page_corners(long long, double *);
130 void scm_page_center (long long, double *);
131 
132 //------------------------------------------------------------------------------
133 
134 #endif