├── Core ├── Memory.cpp ├── Memory.h ├── Slice.cpp ├── Slice.h ├── Utils.cpp ├── Utils.h └── Vector.h ├── MC.cpp ├── Math ├── Mat.cpp ├── Mat.h ├── Noise.cpp ├── Noise.h ├── Plane.cpp ├── Plane.h ├── Quat.cpp ├── Quat.h ├── Rect.h ├── Sphere.cpp ├── Sphere.h ├── Transform.cpp ├── Transform.h ├── Utils.h └── Vec.h ├── README └── compile.bash /Core/Memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Core/Memory.h" 5 | #include "Core/Utils.h" 6 | 7 | void *xmalloc(int n) 8 | { 9 | void *mem = malloc(n); 10 | if (!mem) 11 | die("nextgame: out of memory"); 12 | return mem; 13 | } 14 | 15 | void xfree(void *ptr) 16 | { 17 | free(ptr); 18 | } 19 | 20 | int xcopy(void *dst, const void *src, int n) 21 | { 22 | memmove(dst, src, n); 23 | return n; 24 | } 25 | 26 | void xclear(void *dst, int n) 27 | { 28 | memset(dst, 0, n); 29 | } 30 | 31 | void *operator new(size_t size, const OrDie_t &) 32 | { 33 | void *mem = operator new(size, std::nothrow); 34 | if (!mem) 35 | die("nextgame: out of memory"); 36 | return mem; 37 | } 38 | 39 | void *operator new[](size_t size, const OrDie_t &) 40 | { 41 | void *mem = operator new[](size, std::nothrow); 42 | if (!mem) 43 | die("nextgame: out of memory"); 44 | return mem; 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /Core/Memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void *xmalloc(int n); 9 | void xfree(void *ptr); 10 | int xcopy(void *dst, const void *src, int n); 11 | void xclear(void *dst, int n); 12 | 13 | struct OrDie_t {}; 14 | const OrDie_t OrDie = {}; 15 | 16 | void *operator new(size_t size, const OrDie_t&); 17 | void *operator new[](size_t size, const OrDie_t&); 18 | 19 | template 20 | T *allocate_memory(int n = 1) 21 | { 22 | return (T*)xmalloc(sizeof(T) * n); 23 | } 24 | 25 | template 26 | T &allocate_memory(T *&ptr) 27 | { 28 | ptr = (T*)xmalloc(sizeof(T)); 29 | return *ptr; 30 | } 31 | 32 | template 33 | void free_memory(T *ptr) 34 | { 35 | if (ptr) xfree(ptr); 36 | } 37 | 38 | template 39 | int copy_memory(T *dst, const T *src, int n = 1) 40 | { 41 | return xcopy(dst, src, sizeof(T) * n); 42 | } 43 | 44 | template 45 | void clear_memory(T *dst, int n = 1) 46 | { 47 | xclear(dst, sizeof(T)*n); 48 | } 49 | -------------------------------------------------------------------------------- /Core/Slice.cpp: -------------------------------------------------------------------------------- 1 | #include "Core/Slice.h" 2 | 3 | #define _SLICE_CONST_CHAR_OPERATOR(op) \ 4 | bool operator op(Slice lhs, Slice rhs) { \ 5 | return operator op(lhs, rhs); \ 6 | } 7 | 8 | _SLICE_CONST_CHAR_OPERATOR(==) 9 | _SLICE_CONST_CHAR_OPERATOR(<) 10 | _SLICE_CONST_CHAR_OPERATOR(!=) 11 | _SLICE_CONST_CHAR_OPERATOR(>=) 12 | _SLICE_CONST_CHAR_OPERATOR(<=) 13 | _SLICE_CONST_CHAR_OPERATOR(>) 14 | 15 | #undef _SLICE_CONST_CHAR_OPERATOR 16 | 17 | int compute_hash(Slice s) 18 | { 19 | constexpr unsigned M0 = 2860486313U; 20 | constexpr unsigned M1 = 3267000013U; 21 | unsigned hash = M0; 22 | for (const auto &b : s) 23 | hash = (hash ^ b) * M1; 24 | return hash; 25 | } 26 | 27 | int compute_hash(const char *s) 28 | { 29 | return compute_hash(Slice(s)); 30 | } 31 | 32 | int compute_hash(int i) 33 | { 34 | return compute_hash(slice_cast(Slice(&i, 1))); 35 | } 36 | -------------------------------------------------------------------------------- /Core/Slice.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Core/Utils.h" 7 | 8 | #define _COMMON_SLICE_PART_CONST(T) \ 9 | const T *data; \ 10 | int length; \ 11 | \ 12 | Slice() = default; \ 13 | Slice(std::initializer_list r): data(r.begin()), length(r.size()) {} \ 14 | template \ 15 | Slice(const T (&array)[N]): data(array), length(N) {} \ 16 | Slice(const T *data, int len): data(data), length(len) {} \ 17 | Slice(const Slice &r): data(r.data), length(r.length) {} \ 18 | explicit operator bool() const { return length != 0; } \ 19 | int byte_length() const { return length * sizeof(T); } \ 20 | const T &first() const { NG_ASSERT(length != 0); return data[0]; } \ 21 | const T &last() const { NG_ASSERT(length != 0); return data[length-1]; }\ 22 | Slice sub() const \ 23 | { \ 24 | return {data, length}; \ 25 | } \ 26 | Slice sub(int begin) const \ 27 | { \ 28 | NG_SLICE_BOUNDS_CHECK(begin, length); \ 29 | return {data + begin, length - begin}; \ 30 | } \ 31 | Slice sub(int begin, int end) const \ 32 | { \ 33 | NG_ASSERT(begin <= end); \ 34 | NG_SLICE_BOUNDS_CHECK(begin, length); \ 35 | NG_SLICE_BOUNDS_CHECK(end, length); \ 36 | return {data + begin, end - begin}; \ 37 | } \ 38 | const T &operator[](int idx) const \ 39 | { \ 40 | NG_IDX_BOUNDS_CHECK(idx, length); \ 41 | return data[idx]; \ 42 | } 43 | 44 | template 45 | struct Slice { 46 | T *data; 47 | int length; 48 | 49 | Slice() = default; 50 | 51 | template 52 | Slice(T (&array)[N]): data(array), length(N) {} 53 | Slice(T *data, int length): data(data), length(length) {} 54 | explicit operator bool() const { return length != 0; } 55 | 56 | T &operator[](int idx) 57 | { 58 | NG_IDX_BOUNDS_CHECK(idx, length); 59 | return data[idx]; 60 | } 61 | 62 | const T &operator[](int idx) const 63 | { 64 | NG_IDX_BOUNDS_CHECK(idx, length); 65 | return data[idx]; 66 | } 67 | 68 | // for consistency with Vector, but feel free to use length directly 69 | int byte_length() const { return length * sizeof(T); } 70 | 71 | T &first() { NG_ASSERT(length != 0); return data[0]; } 72 | const T &first() const { NG_ASSERT(length != 0); return data[0]; } 73 | T &last() { NG_ASSERT(length != 0); return data[length-1]; } 74 | const T &last() const { NG_ASSERT(length != 0); return data[length-1]; } 75 | 76 | Slice sub() 77 | { 78 | return {data, length}; 79 | } 80 | Slice sub(int begin) 81 | { 82 | NG_SLICE_BOUNDS_CHECK(begin, length); 83 | return {data + begin, length - begin}; 84 | } 85 | Slice sub(int begin, int end) 86 | { 87 | NG_ASSERT(begin <= end); 88 | NG_SLICE_BOUNDS_CHECK(begin, length); 89 | NG_SLICE_BOUNDS_CHECK(end, length); 90 | return {data + begin, end - begin}; 91 | } 92 | Slice sub() const 93 | { 94 | return {data, length}; 95 | } 96 | Slice sub(int begin) const 97 | { 98 | NG_SLICE_BOUNDS_CHECK(begin, length); 99 | return {data + begin, length - begin}; 100 | } 101 | Slice sub(int begin, int end) const 102 | { 103 | NG_ASSERT(begin <= end); 104 | NG_SLICE_BOUNDS_CHECK(begin, length); 105 | NG_SLICE_BOUNDS_CHECK(end, length); 106 | return {data + begin, end - begin}; 107 | } 108 | }; 109 | 110 | template 111 | struct Slice { 112 | _COMMON_SLICE_PART_CONST(T) 113 | }; 114 | 115 | template <> 116 | struct Slice { 117 | _COMMON_SLICE_PART_CONST(char) 118 | Slice(const char *str): data(str), length(str != nullptr ? strlen(str) : 0) {} 119 | }; 120 | 121 | #undef _COMMON_SLICE_PART_CONST 122 | 123 | template 124 | bool operator==(Slice lhs, Slice rhs) 125 | { 126 | if (lhs.length != rhs.length) 127 | return false; 128 | for (int i = 0; i < lhs.length; i++) { 129 | if (!(lhs.data[i] == rhs.data[i])) 130 | return false; 131 | } 132 | return true; 133 | } 134 | 135 | template 136 | bool operator<(Slice lhs, Slice rhs) 137 | { 138 | for (int i = 0; i < rhs.length; i++) { 139 | if (i == lhs.length) { 140 | // lhs.len() < rhs.len(), but the common part is == 141 | return true; 142 | } 143 | if (lhs.data[i] < rhs.data[i]) { 144 | return true; 145 | } 146 | if (rhs.data[i] < lhs.data[i]) { 147 | return false; 148 | } 149 | } 150 | return false; 151 | } 152 | 153 | template 154 | bool operator!=(Slice lhs, Slice rhs) 155 | { 156 | return !operator==(lhs, rhs); 157 | } 158 | 159 | template 160 | bool operator>=(Slice lhs, Slice rhs) 161 | { 162 | return !operator<(lhs, rhs); 163 | } 164 | 165 | template 166 | bool operator<=(Slice lhs, Slice rhs) 167 | { 168 | return !operator<(rhs, lhs); 169 | } 170 | 171 | template 172 | bool operator>(Slice lhs, Slice rhs) 173 | { 174 | return operator<(rhs, lhs); 175 | } 176 | 177 | bool operator==(Slice lhs, Slice rhs); 178 | bool operator<(Slice lhs, Slice rhs); 179 | bool operator!=(Slice lhs, Slice rhs); 180 | bool operator>=(Slice lhs, Slice rhs); 181 | bool operator<=(Slice lhs, Slice rhs); 182 | bool operator>(Slice lhs, Slice rhs); 183 | 184 | template 185 | const T *begin(Slice s) { return s.data; } 186 | template 187 | const T *end(Slice s) { return s.data + s.length; } 188 | template 189 | T *begin(Slice s) { return s.data; } 190 | template 191 | T *end(Slice s) { return s.data + s.length; } 192 | 193 | template 194 | int copy(Slice dst, Slice src) 195 | { 196 | const int n = std::min(dst.length, src.length); 197 | if (n == 0) { 198 | return 0; 199 | } 200 | 201 | const T *srcp = src.data; 202 | T *dstp = dst.data; 203 | if (srcp == dstp) { 204 | return n; 205 | } 206 | 207 | if (srcp < dstp) { 208 | for (int i = n-1; i >= 0; i--) { 209 | dstp[i] = srcp[i]; 210 | } 211 | } else { 212 | for (int i = 0; i < n; i++) { 213 | dstp[i] = srcp[i]; 214 | } 215 | } 216 | return n; 217 | } 218 | 219 | template 220 | Slice slice_cast(Slice s) 221 | { 222 | const double ratio = (double)sizeof(U) / (double)sizeof(T); 223 | return Slice((T*)s.data, s.length * ratio); 224 | } 225 | 226 | int compute_hash(Slice s); 227 | int compute_hash(const char *s); 228 | int compute_hash(int i); 229 | 230 | template 231 | static inline int compute_hash(Slice s) 232 | { 233 | return compute_hash(slice_cast(s)); 234 | } 235 | 236 | template 237 | void sort(Slice s) 238 | { 239 | std::sort(s.data, s.data + s.length); 240 | } 241 | 242 | template 243 | void sort(Slice s, F &&f) 244 | { 245 | std::sort(s.data, s.data + s.length, std::forward(f)); 246 | } 247 | 248 | template 249 | void reverse(Slice s) 250 | { 251 | const int len1 = s.length - 1; 252 | const int mid = s.length / 2; 253 | for (int i = 0; i < mid; i++) { 254 | std::swap(s[i], s[len1-i]); 255 | } 256 | } 257 | 258 | template 259 | void fill(Slice s, const T &v) 260 | { 261 | for (int i = 0; i < s.length; i++) 262 | s.data[i] = v; 263 | } 264 | 265 | template 266 | int linear_find(Slice s, const U &v) 267 | { 268 | for (int i = 0; i < s.length; i++) { 269 | if (s.data[i] == v) 270 | return i; 271 | } 272 | return -1; 273 | } 274 | 275 | template 276 | int linear_find_if(Slice s, F &&f) 277 | { 278 | for (int i = 0; i < s.length; i++) 279 | if (f(s.data[i])) 280 | return i; 281 | return -1; 282 | } 283 | 284 | template 285 | int binary_find(Slice s, const U &v) 286 | { 287 | int imax = s.length-1; 288 | int imin = 0; 289 | 290 | while (imin < imax) { 291 | // believe it or not, nobody really cares about overflows here 292 | const int imid = (imin + imax) / 2; 293 | if (s.data[imid] < v) 294 | imin = imid+1; 295 | else 296 | imax = imid; 297 | } 298 | if (imax == imin && s.data[imin] == v) 299 | return imin; 300 | return -1; 301 | } 302 | -------------------------------------------------------------------------------- /Core/Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Core/Utils.h" 2 | #include 3 | #include 4 | #include 5 | 6 | void assertion_abort(const char *assertion, const char *file, 7 | int line, const char *func) 8 | { 9 | fprintf(stderr, "%s:%d: %s: assertion `%s` failed\n", 10 | file, line, func, assertion); 11 | abort(); 12 | } 13 | 14 | void die(const char *msg, ...) 15 | { 16 | va_list va; 17 | va_start(va, msg); 18 | vfprintf(stderr, msg, va); 19 | va_end(va); 20 | fprintf(stderr, "\n"); 21 | abort(); 22 | } 23 | 24 | void warn(const char *msg, ...) 25 | { 26 | va_list va; 27 | va_start(va, msg); 28 | vfprintf(stderr, msg, va); 29 | va_end(va); 30 | fprintf(stderr, "\n"); 31 | } 32 | -------------------------------------------------------------------------------- /Core/Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //---------------------------------------------------------------------- 4 | // Configuration 5 | //---------------------------------------------------------------------- 6 | 7 | #define NG_ASSERTION_ENABLED 8 | 9 | //---------------------------------------------------------------------- 10 | //---------------------------------------------------------------------- 11 | 12 | void assertion_abort(const char *assertion, const char *file, 13 | int line, const char *func); 14 | 15 | #ifdef NG_ASSERTION_ENABLED 16 | #define NG_ASSERT(expr) \ 17 | do { \ 18 | if (!(expr)) { \ 19 | assertion_abort(#expr, \ 20 | __FILE__, __LINE__, \ 21 | __PRETTY_FUNCTION__); \ 22 | } \ 23 | } while (0) 24 | #else 25 | #define NG_ASSERT(expr) ((void)0) 26 | #endif 27 | 28 | #define NG_SLICE_BOUNDS_CHECK(index, length) \ 29 | NG_ASSERT((unsigned)(index) <= (unsigned)(length)) 30 | 31 | #define NG_IDX_BOUNDS_CHECK(index, length) \ 32 | NG_ASSERT((unsigned)(index) < (unsigned)(length)) 33 | 34 | void die(const char *msg, ...); 35 | void warn(const char *msg, ...); 36 | 37 | #define NG_DELETE_COPY(Type) \ 38 | Type(const Type&) = delete; \ 39 | Type &operator=(const Type&) = delete 40 | 41 | #define NG_DELETE_MOVE(Type) \ 42 | Type(Type&&) = delete; \ 43 | Type &operator=(Type&&) = delete 44 | 45 | #define NG_DELETE_COPY_AND_MOVE(Type) \ 46 | NG_DELETE_COPY(Type); \ 47 | NG_DELETE_MOVE(Type) 48 | 49 | #ifdef _WIN32 50 | #define NG_LUA_API extern "C" __declspec(dllexport) 51 | #else 52 | #define NG_LUA_API extern "C" 53 | #endif 54 | 55 | #define NG_ENABLE_SINGLETON(globalptr) \ 56 | do { \ 57 | if (globalptr) { \ 58 | die("There can only be one " #globalptr); \ 59 | } \ 60 | globalptr = this; \ 61 | } while (0) 62 | 63 | #define NG_DISABLE_SINGLETON(globalptr) \ 64 | do { \ 65 | globalptr = nullptr; \ 66 | } while (0) 67 | 68 | -------------------------------------------------------------------------------- /Core/Vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Core/Utils.h" 4 | #include "Core/Memory.h" 5 | #include "Core/Slice.h" 6 | 7 | template 8 | struct Vector { 9 | T *m_data = nullptr; 10 | int m_len = 0; 11 | int m_cap = 0; 12 | 13 | int _new_size(int requested) const 14 | { 15 | int newcap = m_cap * 2; 16 | return newcap < requested ? requested : newcap; 17 | } 18 | 19 | void _ensure_capacity(int n) 20 | { 21 | if (m_len + n > m_cap) 22 | reserve(_new_size(m_len + n)); 23 | } 24 | 25 | // expects: idx < _len, idx >= 0, offset > 0 26 | void _move_forward(int idx, int offset) 27 | { 28 | const int last = m_len-1; 29 | int src = last; 30 | int dst = last+offset; 31 | while (src >= idx) { 32 | new (&m_data[dst]) T(std::move(m_data[src])); 33 | m_data[src].~T(); 34 | src--; 35 | dst--; 36 | } 37 | } 38 | 39 | // expects: idx < _len, idx >= 0, offset < 0 40 | void _move_backward(int idx, int offset) 41 | { 42 | int src = idx; 43 | int dst = idx+offset; 44 | while (src < m_len) { 45 | new (&m_data[dst]) T(std::move(m_data[src])); 46 | m_data[src].~T(); 47 | src++; 48 | dst++; 49 | } 50 | } 51 | 52 | void _self_insert(int idx, Slice s) 53 | { 54 | int sidx = s.data - m_data; 55 | _ensure_capacity(s.length); 56 | 57 | // restore the slice after possible realloc 58 | s = Slice(m_data + sidx, s.length); 59 | 60 | // shorcut case, append 61 | if (idx == m_len) { 62 | for (int i = 0; i < s.length; i++) 63 | new (m_data + idx + i) T(s.data[i]); 64 | m_len += s.length; 65 | return; 66 | } 67 | 68 | // move tail further towards the end so that there is a free space for 69 | // data insertion 70 | _move_forward(idx, s.length); 71 | m_len += s.length; 72 | 73 | // adjust slice so that it points to the right data and if we're 74 | // splitting the slice, insert first half of it right away 75 | if (idx <= sidx) { 76 | s = Slice(s.data + s.length, s.length); 77 | } else { 78 | const int lhslen = idx - sidx; 79 | copy_memory(m_data + idx, m_data + sidx, lhslen); 80 | for (int i = 0; i < lhslen; i++) 81 | new (m_data + idx + i) T(m_data[sidx+i]); 82 | idx += lhslen; 83 | s = Slice(s.data + s.length + lhslen, s.length - lhslen); 84 | } 85 | for (int i = 0; i < s.length; i++) 86 | new (m_data + idx + i) T(s.data[i]); 87 | } 88 | 89 | void _nullify() 90 | { 91 | m_data = nullptr; 92 | m_len = 0; 93 | m_cap = 0; 94 | } 95 | 96 | Vector() = default; 97 | 98 | explicit Vector(int n): m_len(n), m_cap(n) 99 | { 100 | NG_ASSERT(n >= 0); 101 | if (m_len == 0) 102 | return; 103 | m_data = allocate_memory(m_len); 104 | for (int i = 0; i < m_len; i++) 105 | new (m_data + i) T; 106 | } 107 | 108 | Vector(int n, const T &elem): m_len(n), m_cap(n) 109 | { 110 | NG_ASSERT(n >= 0); 111 | if (m_len == 0) 112 | return; 113 | m_data = allocate_memory(m_len); 114 | for (int i = 0; i < m_len; i++) 115 | new (m_data + i) T(elem); 116 | } 117 | 118 | Vector(Slice s): m_len(s.length), m_cap(s.length) 119 | { 120 | if (m_len == 0) 121 | return; 122 | m_data = allocate_memory(m_len); 123 | for (int i = 0; i < m_len; i++) 124 | new (m_data + i) T(s.data[i]); 125 | } 126 | 127 | Vector(Slice s): Vector(Slice(s)) 128 | { 129 | } 130 | 131 | Vector(std::initializer_list r): Vector(Slice(r)) 132 | { 133 | } 134 | 135 | Vector(const Vector &r) = delete; 136 | 137 | Vector(Vector &&r): m_data(r.m_data), m_len(r.m_len), m_cap(r.m_cap) 138 | { 139 | r._nullify(); 140 | } 141 | 142 | Vector &operator=(Slice r) 143 | { 144 | if (m_data == r.data && m_len == r.length) { 145 | // self copy shortcut (a = a) 146 | return *this; 147 | } 148 | if (m_cap < r.length) { 149 | // slice is bigger than we are, realloc needed, also it 150 | // means slice cannot point to ourselves and it is save 151 | // to destroy ourselves 152 | for (int i = 0; i < m_len; i++) 153 | m_data[i].~T(); 154 | free_memory(m_data); 155 | m_cap = m_len = r.length; 156 | m_data = allocate_memory(m_len); 157 | for (int i = 0; i < m_len; i++) 158 | new (m_data + i) T(r.data[i]); 159 | } else { 160 | // slice can be a subset of ourselves 161 | int i = copy(sub(), r); 162 | for (; i < m_len; i++) { 163 | // destroy the rest if any 164 | m_data[i].~T(); 165 | } 166 | for (; i < r.length; i++) { 167 | // construct the new if any 168 | new (m_data + i) T(r.data[i]); 169 | } 170 | m_len = r.length; 171 | } 172 | return *this; 173 | } 174 | 175 | Vector &operator=(Slice r) 176 | { 177 | return operator=(Slice(r)); 178 | } 179 | 180 | Vector &operator=(const Vector &r) = delete; 181 | 182 | Vector &operator=(Vector &&r) 183 | { 184 | for (int i = 0; i < m_len; i++) 185 | m_data[i].~T(); 186 | free_memory(m_data); 187 | 188 | m_data = r.m_data; 189 | m_len = r.m_len; 190 | m_cap = r.m_cap; 191 | r._nullify(); 192 | return *this; 193 | } 194 | 195 | Vector &operator=(std::initializer_list r) 196 | { 197 | return operator=(Slice(r)); 198 | } 199 | 200 | ~Vector() 201 | { 202 | for (int i = 0; i < m_len; i++) 203 | m_data[i].~T(); 204 | free_memory(m_data); 205 | } 206 | 207 | int length() const { return m_len; } 208 | int byte_length() const { return m_len * sizeof(T); } 209 | int capacity() const { return m_cap; } 210 | T *data() { return m_data; } 211 | const T *data() const { return m_data; } 212 | 213 | void clear() 214 | { 215 | for (int i = 0; i < m_len; i++) 216 | m_data[i].~T(); 217 | m_len = 0; 218 | } 219 | 220 | void reserve(int n) 221 | { 222 | if (m_cap >= n) 223 | return; 224 | 225 | T *old_data = m_data; 226 | m_cap = n; 227 | m_data = allocate_memory(m_cap); 228 | for (int i = 0; i < m_len; i++) { 229 | new (m_data + i) T(std::move(old_data[i])); 230 | old_data[i].~T(); 231 | } 232 | free_memory(old_data); 233 | } 234 | 235 | void shrink() 236 | { 237 | if (m_cap == m_len) 238 | return; 239 | 240 | T *old_data = m_data; 241 | m_cap = m_len; 242 | if (m_len > 0) { 243 | m_data = allocate_memory(m_len); 244 | for (int i = 0; i < m_len; i++) { 245 | new (m_data + i) T(std::move(old_data[i])); 246 | old_data[i].~T(); 247 | } 248 | } else { 249 | m_data = nullptr; 250 | } 251 | free_memory(old_data); 252 | } 253 | 254 | void resize(int n) 255 | { 256 | NG_ASSERT(n >= 0); 257 | 258 | if (m_len == n) 259 | return; 260 | 261 | if (m_len > n) { 262 | for (int i = n; i < m_len; i++) 263 | m_data[i].~T(); 264 | m_len = n; 265 | return; 266 | } 267 | 268 | reserve(n); 269 | for (int i = m_len; i < n; i++) 270 | new (m_data + i) T; 271 | m_len = n; 272 | } 273 | 274 | void resize(int n, const T &elem) 275 | { 276 | NG_ASSERT(n >= 0); 277 | 278 | if (m_len == n) 279 | return; 280 | 281 | if (m_len > n) { 282 | for (int i = n; i < m_len; i++) 283 | m_data[i].~T(); 284 | m_len = n; 285 | return; 286 | } 287 | 288 | reserve(n); 289 | for (int i = m_len; i < n; i++) 290 | new (m_data + i) T(elem); 291 | m_len = n; 292 | } 293 | 294 | void quick_remove(int idx) 295 | { 296 | NG_IDX_BOUNDS_CHECK(idx, m_len); 297 | if (idx != m_len-1) 298 | std::swap(m_data[idx], m_data[m_len-1]); 299 | m_data[--m_len].~T(); 300 | } 301 | 302 | void remove(int idx) 303 | { 304 | NG_IDX_BOUNDS_CHECK(idx, m_len); 305 | if (idx == m_len - 1) { 306 | m_data[--m_len].~T(); 307 | return; 308 | } 309 | 310 | m_data[idx].~T(); 311 | _move_backward(idx+1, -1); 312 | m_len--; 313 | } 314 | 315 | void remove(int begin, int end) 316 | { 317 | NG_ASSERT(begin <= end); 318 | NG_SLICE_BOUNDS_CHECK(begin, m_len); 319 | NG_SLICE_BOUNDS_CHECK(end, m_len); 320 | const int len = end - begin; 321 | if (len == 0) 322 | return; 323 | for (int i = begin; i < end; i++) 324 | m_data[i].~T(); 325 | if (end < m_len) 326 | _move_backward(begin+len, -len); 327 | m_len -= len; 328 | } 329 | 330 | template 331 | void pinsert(int idx, Args &&...args) 332 | { 333 | NG_SLICE_BOUNDS_CHECK(idx, m_len); 334 | _ensure_capacity(1); 335 | if (idx < m_len) { 336 | _move_forward(idx, 1); 337 | } 338 | new (m_data + idx) T(std::forward(args)...); 339 | m_len++; 340 | } 341 | 342 | void insert(int idx, const T &elem) 343 | { 344 | pinsert(idx, elem); 345 | } 346 | 347 | void insert (int idx, T &&elem) 348 | { 349 | pinsert(idx, std::move(elem)); 350 | } 351 | 352 | void insert(int idx, Slice s) 353 | { 354 | NG_SLICE_BOUNDS_CHECK(idx, m_len); 355 | if (s.length == 0) { 356 | return; 357 | } 358 | if (s.data >= m_data && s.data < m_data + m_len) { 359 | _self_insert(idx, s); 360 | return; 361 | } 362 | _ensure_capacity(s.length); 363 | if (idx < m_len) 364 | _move_forward(idx, s.length); 365 | for (int i = 0; i < s.length; i++) 366 | new (m_data + idx + i) T(s.data[i]); 367 | m_len += s.length; 368 | } 369 | 370 | template 371 | void pappend(Args &&...args) 372 | { 373 | _ensure_capacity(1); 374 | new (m_data + m_len++) T(std::forward(args)...); 375 | } 376 | 377 | T *append() 378 | { 379 | _ensure_capacity(1); 380 | return new (m_data + m_len++) T; 381 | } 382 | 383 | void append(const T &elem) 384 | { 385 | NG_ASSERT(&elem < m_data || &elem >= m_data + m_len); 386 | pappend(elem); 387 | } 388 | 389 | void append(T &&elem) 390 | { 391 | NG_ASSERT(&elem < m_data || &elem >= m_data + m_len); 392 | pappend(std::move(elem)); 393 | } 394 | 395 | void append(Slice s) 396 | { 397 | insert(m_len, s); 398 | } 399 | 400 | T &operator[](int idx) 401 | { 402 | NG_IDX_BOUNDS_CHECK(idx, m_len); 403 | return m_data[idx]; 404 | } 405 | 406 | const T &operator[](int idx) const 407 | { 408 | NG_IDX_BOUNDS_CHECK(idx, m_len); 409 | return m_data[idx]; 410 | } 411 | 412 | T &first() { NG_ASSERT(m_len != 0); return m_data[0]; } 413 | const T &first() const { NG_ASSERT(m_len != 0); return m_data[0]; } 414 | T &last() { NG_ASSERT(m_len != 0); return m_data[m_len-1]; } 415 | const T &last() const { NG_ASSERT(m_len != 0); return m_data[m_len-1]; } 416 | 417 | Slice sub() 418 | { 419 | return {m_data, m_len}; 420 | } 421 | Slice sub(int begin) 422 | { 423 | NG_SLICE_BOUNDS_CHECK(begin, m_len); 424 | return {m_data + begin, m_len - begin}; 425 | } 426 | Slice sub(int begin, int end) 427 | { 428 | NG_ASSERT(begin <= end); 429 | NG_SLICE_BOUNDS_CHECK(begin, m_len); 430 | NG_SLICE_BOUNDS_CHECK(end, m_len); 431 | return {m_data + begin, end - begin}; 432 | } 433 | Slice sub() const 434 | { 435 | return {m_data, m_len}; 436 | } 437 | Slice sub(int begin) const 438 | { 439 | NG_SLICE_BOUNDS_CHECK(begin, m_len); 440 | return {m_data + begin, m_len - begin}; 441 | } 442 | Slice sub(int begin, int end) const 443 | { 444 | NG_ASSERT(begin <= end); 445 | NG_SLICE_BOUNDS_CHECK(begin, m_len); 446 | NG_SLICE_BOUNDS_CHECK(end, m_len); 447 | return {m_data + begin, end - begin}; 448 | } 449 | 450 | operator Slice() { return {m_data, m_len}; } 451 | operator Slice() const { return {m_data, m_len}; } 452 | }; 453 | 454 | template 455 | const T *begin(const Vector &v) { return v.data(); } 456 | template 457 | const T *end(const Vector &v) { return v.data()+v.length(); } 458 | template 459 | T *begin(Vector &v) { return v.data(); } 460 | template 461 | T *end(Vector &v) { return v.data()+v.length(); } 462 | -------------------------------------------------------------------------------- /MC.cpp: -------------------------------------------------------------------------------- 1 | /*********************************************************** 2 | * A Template for building OpenGL applications using GLUT 3 | * 4 | * Author: Perspective @ cprogramming.com 5 | * Date : Jan, 2005 6 | * 7 | * Description: 8 | * This code initializes an OpenGL ready window 9 | * using GLUT. Some of the most common callbacks 10 | * are registered to empty or minimal functions. 11 | * 12 | * This code is intended to be a quick starting point 13 | * when building GLUT applications. 14 | * 15 | ***********************************************************/ 16 | 17 | #include 18 | #include 19 | #include "Math/Transform.h" 20 | #include "Math/Noise.h" 21 | #include "Core/Utils.h" 22 | #include "Core/Vector.h" 23 | 24 | #ifdef __APPLE__ 25 | #include 26 | #include 27 | #include 28 | #else 29 | #include 30 | #endif 31 | 32 | 33 | //---------------------------------------------------------------------------- 34 | // Geometry 35 | //---------------------------------------------------------------------------- 36 | 37 | struct Vertex { 38 | Vec3f position; 39 | Vec3f normal; 40 | }; 41 | 42 | static Vector voxels(65*65*65); 43 | static Vector vertices; 44 | static Vector indices; 45 | 46 | static inline int offset_3d(const Vec3i &p, const Vec3i &size) 47 | { 48 | return (p.z * size.y + p.y) * size.x + p.x; 49 | } 50 | 51 | static inline int offset_3d_slab(const Vec3i &p, const Vec3i &size) 52 | { 53 | return size.x * size.y * (p.z % 2) + p.y * size.x + p.x; 54 | } 55 | 56 | static void generate_voxels() 57 | { 58 | Noise2D n2d(0); 59 | for (int z = 0; z < 65; z++) { 60 | for (int y = 0; y < 65; y++) { 61 | for (int x = 0; x < 65; x++) { 62 | const float fy = (float)y / 65.0f; 63 | const int offset = offset_3d({x, y, z}, Vec3i(65)); 64 | const float v = n2d.get(x / 16.0f, z / 16.0f) * 0.25f; 65 | voxels[offset] = fy - 0.25f - v; 66 | }}} 67 | } 68 | 69 | static const uint64_t marching_cube_tris[256] = { 70 | 0ULL, 33793ULL, 36945ULL, 159668546ULL, 71 | 18961ULL, 144771090ULL, 5851666ULL, 595283255635ULL, 72 | 20913ULL, 67640146ULL, 193993474ULL, 655980856339ULL, 73 | 88782242ULL, 736732689667ULL, 797430812739ULL, 194554754ULL, 74 | 26657ULL, 104867330ULL, 136709522ULL, 298069416227ULL, 75 | 109224258ULL, 8877909667ULL, 318136408323ULL, 1567994331701604ULL, 76 | 189884450ULL, 350847647843ULL, 559958167731ULL, 3256298596865604ULL, 77 | 447393122899ULL, 651646838401572ULL, 2538311371089956ULL, 737032694307ULL, 78 | 29329ULL, 43484162ULL, 91358498ULL, 374810899075ULL, 79 | 158485010ULL, 178117478419ULL, 88675058979ULL, 433581536604804ULL, 80 | 158486962ULL, 649105605635ULL, 4866906995ULL, 3220959471609924ULL, 81 | 649165714851ULL, 3184943915608436ULL, 570691368417972ULL, 595804498035ULL, 82 | 124295042ULL, 431498018963ULL, 508238522371ULL, 91518530ULL, 83 | 318240155763ULL, 291789778348404ULL, 1830001131721892ULL, 375363605923ULL, 84 | 777781811075ULL, 1136111028516116ULL, 3097834205243396ULL, 508001629971ULL, 85 | 2663607373704004ULL, 680242583802939237ULL, 333380770766129845ULL, 179746658ULL, 86 | 42545ULL, 138437538ULL, 93365810ULL, 713842853011ULL, 87 | 73602098ULL, 69575510115ULL, 23964357683ULL, 868078761575828ULL, 88 | 28681778ULL, 713778574611ULL, 250912709379ULL, 2323825233181284ULL, 89 | 302080811955ULL, 3184439127991172ULL, 1694042660682596ULL, 796909779811ULL, 90 | 176306722ULL, 150327278147ULL, 619854856867ULL, 1005252473234484ULL, 91 | 211025400963ULL, 36712706ULL, 360743481544788ULL, 150627258963ULL, 92 | 117482600995ULL, 1024968212107700ULL, 2535169275963444ULL, 4734473194086550421ULL, 93 | 628107696687956ULL, 9399128243ULL, 5198438490361643573ULL, 194220594ULL, 94 | 104474994ULL, 566996932387ULL, 427920028243ULL, 2014821863433780ULL, 95 | 492093858627ULL, 147361150235284ULL, 2005882975110676ULL, 9671606099636618005ULL, 96 | 777701008947ULL, 3185463219618820ULL, 482784926917540ULL, 2900953068249785909ULL, 97 | 1754182023747364ULL, 4274848857537943333ULL, 13198752741767688709ULL, 2015093490989156ULL, 98 | 591272318771ULL, 2659758091419812ULL, 1531044293118596ULL, 298306479155ULL, 99 | 408509245114388ULL, 210504348563ULL, 9248164405801223541ULL, 91321106ULL, 100 | 2660352816454484ULL, 680170263324308757ULL, 8333659837799955077ULL, 482966828984116ULL, 101 | 4274926723105633605ULL, 3184439197724820ULL, 192104450ULL, 15217ULL, 102 | 45937ULL, 129205250ULL, 129208402ULL, 529245952323ULL, 103 | 169097138ULL, 770695537027ULL, 382310500883ULL, 2838550742137652ULL, 104 | 122763026ULL, 277045793139ULL, 81608128403ULL, 1991870397907988ULL, 105 | 362778151475ULL, 2059003085103236ULL, 2132572377842852ULL, 655681091891ULL, 106 | 58419234ULL, 239280858627ULL, 529092143139ULL, 1568257451898804ULL, 107 | 447235128115ULL, 679678845236084ULL, 2167161349491220ULL, 1554184567314086709ULL, 108 | 165479003923ULL, 1428768988226596ULL, 977710670185060ULL, 10550024711307499077ULL, 109 | 1305410032576132ULL, 11779770265620358997ULL, 333446212255967269ULL, 978168444447012ULL, 110 | 162736434ULL, 35596216627ULL, 138295313843ULL, 891861543990356ULL, 111 | 692616541075ULL, 3151866750863876ULL, 100103641866564ULL, 6572336607016932133ULL, 112 | 215036012883ULL, 726936420696196ULL, 52433666ULL, 82160664963ULL, 113 | 2588613720361524ULL, 5802089162353039525ULL, 214799000387ULL, 144876322ULL, 114 | 668013605731ULL, 110616894681956ULL, 1601657732871812ULL, 430945547955ULL, 115 | 3156382366321172ULL, 7644494644932993285ULL, 3928124806469601813ULL, 3155990846772900ULL, 116 | 339991010498708ULL, 10743689387941597493ULL, 5103845475ULL, 105070898ULL, 117 | 3928064910068824213ULL, 156265010ULL, 1305138421793636ULL, 27185ULL, 118 | 195459938ULL, 567044449971ULL, 382447549283ULL, 2175279159592324ULL, 119 | 443529919251ULL, 195059004769796ULL, 2165424908404116ULL, 1554158691063110021ULL, 120 | 504228368803ULL, 1436350466655236ULL, 27584723588724ULL, 1900945754488837749ULL, 121 | 122971970ULL, 443829749251ULL, 302601798803ULL, 108558722ULL, 122 | 724700725875ULL, 43570095105972ULL, 2295263717447940ULL, 2860446751369014181ULL, 123 | 2165106202149444ULL, 69275726195ULL, 2860543885641537797ULL, 2165106320445780ULL, 124 | 2280890014640004ULL, 11820349930268368933ULL, 8721082628082003989ULL, 127050770ULL, 125 | 503707084675ULL, 122834978ULL, 2538193642857604ULL, 10129ULL, 126 | 801441490467ULL, 2923200302876740ULL, 1443359556281892ULL, 2901063790822564949ULL, 127 | 2728339631923524ULL, 7103874718248233397ULL, 12775311047932294245ULL, 95520290ULL, 128 | 2623783208098404ULL, 1900908618382410757ULL, 137742672547ULL, 2323440239468964ULL, 129 | 362478212387ULL, 727199575803140ULL, 73425410ULL, 34337ULL, 130 | 163101314ULL, 668566030659ULL, 801204361987ULL, 73030562ULL, 131 | 591509145619ULL, 162574594ULL, 100608342969108ULL, 5553ULL, 132 | 724147968595ULL, 1436604830452292ULL, 176259090ULL, 42001ULL, 133 | 143955266ULL, 2385ULL, 18433ULL, 0ULL, 134 | }; 135 | 136 | static void triangle(int a, int b, int c) 137 | { 138 | Vertex &va = vertices[a]; 139 | Vertex &vb = vertices[b]; 140 | Vertex &vc = vertices[c]; 141 | const Vec3f ab = va.position - vb.position; 142 | const Vec3f cb = vc.position - vb.position; 143 | const Vec3f n = cross(cb, ab); 144 | va.normal += n; 145 | vb.normal += n; 146 | vc.normal += n; 147 | } 148 | 149 | static void generate_geometry() 150 | { 151 | for (int z = 0; z < 64; z++) { 152 | for (int y = 0; y < 64; y++) { 153 | for (int x = 0; x < 64; x++) { 154 | const float vs[8] = { 155 | voxels[offset_3d({x, y, z}, Vec3i(65))], 156 | voxels[offset_3d({x+1, y, z}, Vec3i(65))], 157 | voxels[offset_3d({x, y+1, z}, Vec3i(65))], 158 | voxels[offset_3d({x+1, y+1, z}, Vec3i(65))], 159 | voxels[offset_3d({x, y, z+1}, Vec3i(65))], 160 | voxels[offset_3d({x+1, y, z+1}, Vec3i(65))], 161 | voxels[offset_3d({x, y+1, z+1}, Vec3i(65))], 162 | voxels[offset_3d({x+1, y+1, z+1}, Vec3i(65))], 163 | }; 164 | 165 | const int config_n = 166 | ((vs[0] < 0.0f) << 0) | 167 | ((vs[1] < 0.0f) << 1) | 168 | ((vs[2] < 0.0f) << 2) | 169 | ((vs[3] < 0.0f) << 3) | 170 | ((vs[4] < 0.0f) << 4) | 171 | ((vs[5] < 0.0f) << 5) | 172 | ((vs[6] < 0.0f) << 6) | 173 | ((vs[7] < 0.0f) << 7); 174 | 175 | if (config_n == 0 || config_n == 255) 176 | continue; 177 | 178 | int edge_indices[12]; 179 | auto do_edge = [&](int n_edge, float va, float vb, int axis, const Vec3f &base) { 180 | if ((va < 0.0) == (vb < 0.0)) 181 | return; 182 | 183 | Vec3f v = base; 184 | v[axis] += va / (va - vb); 185 | edge_indices[n_edge] = vertices.length(); 186 | vertices.append({v, Vec3f(0)}); 187 | }; 188 | 189 | do_edge(0, vs[0], vs[1], 0, Vec3f(x, y, z)); 190 | do_edge(1, vs[2], vs[3], 0, Vec3f(x, y+1, z)); 191 | do_edge(2, vs[4], vs[5], 0, Vec3f(x, y, z+1)); 192 | do_edge(3, vs[6], vs[7], 0, Vec3f(x, y+1, z+1)); 193 | 194 | do_edge(4, vs[0], vs[2], 1, Vec3f(x, y, z)); 195 | do_edge(5, vs[1], vs[3], 1, Vec3f(x+1, y, z)); 196 | do_edge(6, vs[4], vs[6], 1, Vec3f(x, y, z+1)); 197 | do_edge(7, vs[5], vs[7], 1, Vec3f(x+1, y, z+1)); 198 | 199 | do_edge(8, vs[0], vs[4], 2, Vec3f(x, y, z)); 200 | do_edge(9, vs[1], vs[5], 2, Vec3f(x+1, y, z)); 201 | do_edge(10, vs[2], vs[6], 2, Vec3f(x, y+1, z)); 202 | do_edge(11, vs[3], vs[7], 2, Vec3f(x+1, y+1, z)); 203 | 204 | const uint64_t config = marching_cube_tris[config_n]; 205 | const int n_triangles = config & 0xF; 206 | const int n_indices = n_triangles * 3; 207 | const int index_base = indices.length(); 208 | 209 | int offset = 4; 210 | for (int i = 0; i < n_indices; i++) { 211 | const int edge = (config >> offset) & 0xF; 212 | indices.append(edge_indices[edge]); 213 | offset += 4; 214 | } 215 | for (int i = 0; i < n_triangles; i++) { 216 | triangle( 217 | indices[index_base+i*3+0], 218 | indices[index_base+i*3+1], 219 | indices[index_base+i*3+2]); 220 | } 221 | }}} 222 | for (Vertex &v : vertices) 223 | v.normal = normalize(v.normal); 224 | } 225 | 226 | 227 | static void generate_geometry_smooth() 228 | { 229 | static Vector slab_inds(65*65*2); 230 | 231 | for (int z = 0; z < 64; z++) { 232 | for (int y = 0; y < 64; y++) { 233 | for (int x = 0; x < 64; x++) { 234 | const Vec3i p(x, y, z); 235 | const float vs[8] = { 236 | voxels[offset_3d({x, y, z}, Vec3i(65))], 237 | voxels[offset_3d({x+1, y, z}, Vec3i(65))], 238 | voxels[offset_3d({x, y+1, z}, Vec3i(65))], 239 | voxels[offset_3d({x+1, y+1, z}, Vec3i(65))], 240 | voxels[offset_3d({x, y, z+1}, Vec3i(65))], 241 | voxels[offset_3d({x+1, y, z+1}, Vec3i(65))], 242 | voxels[offset_3d({x, y+1, z+1}, Vec3i(65))], 243 | voxels[offset_3d({x+1, y+1, z+1}, Vec3i(65))], 244 | }; 245 | 246 | const int config_n = 247 | ((vs[0] < 0.0f) << 0) | 248 | ((vs[1] < 0.0f) << 1) | 249 | ((vs[2] < 0.0f) << 2) | 250 | ((vs[3] < 0.0f) << 3) | 251 | ((vs[4] < 0.0f) << 4) | 252 | ((vs[5] < 0.0f) << 5) | 253 | ((vs[6] < 0.0f) << 6) | 254 | ((vs[7] < 0.0f) << 7); 255 | 256 | if (config_n == 0 || config_n == 255) 257 | continue; 258 | 259 | auto do_edge = [&](int n_edge, float va, float vb, int axis, const Vec3i &p) { 260 | if ((va < 0.0) == (vb < 0.0)) 261 | return; 262 | 263 | Vec3f v = ToVec3f(p); 264 | v[axis] += va / (va - vb); 265 | slab_inds[offset_3d_slab(p, Vec3i(65))][axis] = vertices.length(); 266 | vertices.append({v, Vec3f(0)}); 267 | }; 268 | 269 | if (p.y == 0 && p.z == 0) 270 | do_edge(0, vs[0], vs[1], 0, Vec3i(x, y, z)); 271 | if (p.z == 0) 272 | do_edge(1, vs[2], vs[3], 0, Vec3i(x, y+1, z)); 273 | if (p.y == 0) 274 | do_edge(2, vs[4], vs[5], 0, Vec3i(x, y, z+1)); 275 | do_edge(3, vs[6], vs[7], 0, Vec3i(x, y+1, z+1)); 276 | 277 | if (p.x == 0 && p.z == 0) 278 | do_edge(4, vs[0], vs[2], 1, Vec3i(x, y, z)); 279 | if (p.z == 0) 280 | do_edge(5, vs[1], vs[3], 1, Vec3i(x+1, y, z)); 281 | if (p.x == 0) 282 | do_edge(6, vs[4], vs[6], 1, Vec3i(x, y, z+1)); 283 | do_edge(7, vs[5], vs[7], 1, Vec3i(x+1, y, z+1)); 284 | 285 | if (p.x == 0 && p.y == 0) 286 | do_edge(8, vs[0], vs[4], 2, Vec3i(x, y, z)); 287 | if (p.y == 0) 288 | do_edge(9, vs[1], vs[5], 2, Vec3i(x+1, y, z)); 289 | if (p.x == 0) 290 | do_edge(10, vs[2], vs[6], 2, Vec3i(x, y+1, z)); 291 | do_edge(11, vs[3], vs[7], 2, Vec3i(x+1, y+1, z)); 292 | 293 | int edge_indices[12]; 294 | edge_indices[0] = slab_inds[offset_3d_slab({p.x, p.y, p.z }, Vec3i(65))].x; 295 | edge_indices[1] = slab_inds[offset_3d_slab({p.x, p.y+1, p.z }, Vec3i(65))].x; 296 | edge_indices[2] = slab_inds[offset_3d_slab({p.x, p.y, p.z+1}, Vec3i(65))].x; 297 | edge_indices[3] = slab_inds[offset_3d_slab({p.x, p.y+1, p.z+1}, Vec3i(65))].x; 298 | edge_indices[4] = slab_inds[offset_3d_slab({p.x, p.y, p.z }, Vec3i(65))].y; 299 | edge_indices[5] = slab_inds[offset_3d_slab({p.x+1, p.y, p.z }, Vec3i(65))].y; 300 | edge_indices[6] = slab_inds[offset_3d_slab({p.x, p.y, p.z+1}, Vec3i(65))].y; 301 | edge_indices[7] = slab_inds[offset_3d_slab({p.x+1, p.y, p.z+1}, Vec3i(65))].y; 302 | edge_indices[8] = slab_inds[offset_3d_slab({p.x, p.y, p.z}, Vec3i(65))].z; 303 | edge_indices[9] = slab_inds[offset_3d_slab({p.x+1, p.y, p.z}, Vec3i(65))].z; 304 | edge_indices[10] = slab_inds[offset_3d_slab({p.x, p.y+1, p.z}, Vec3i(65))].z; 305 | edge_indices[11] = slab_inds[offset_3d_slab({p.x+1, p.y+1, p.z}, Vec3i(65))].z; 306 | 307 | const uint64_t config = marching_cube_tris[config_n]; 308 | const int n_triangles = config & 0xF; 309 | const int n_indices = n_triangles * 3; 310 | const int index_base = indices.length(); 311 | 312 | int offset = 4; 313 | for (int i = 0; i < n_indices; i++) { 314 | const int edge = (config >> offset) & 0xF; 315 | indices.append(edge_indices[edge]); 316 | offset += 4; 317 | } 318 | for (int i = 0; i < n_triangles; i++) { 319 | triangle( 320 | indices[index_base+i*3+0], 321 | indices[index_base+i*3+1], 322 | indices[index_base+i*3+2]); 323 | } 324 | }}} 325 | for (Vertex &v : vertices) 326 | v.normal = normalize(v.normal); 327 | } 328 | 329 | static void quad(bool flip, int ia, int ib, int ic, int id) 330 | { 331 | if (flip) 332 | std::swap(ib, id); 333 | 334 | Vertex &va = vertices[ia]; 335 | Vertex &vb = vertices[ib]; 336 | Vertex &vc = vertices[ic]; 337 | Vertex &vd = vertices[id]; 338 | 339 | const Vec3f ab = va.position - vb.position; 340 | const Vec3f cb = vc.position - vb.position; 341 | const Vec3f n1 = cross(cb, ab); 342 | va.normal += n1; 343 | vb.normal += n1; 344 | vc.normal += n1; 345 | 346 | const Vec3f ac = va.position - vc.position; 347 | const Vec3f dc = vd.position - vc.position; 348 | const Vec3f n2 = cross(dc, ac); 349 | va.normal += n2; 350 | vc.normal += n2; 351 | vd.normal += n2; 352 | 353 | indices.append(ia); 354 | indices.append(ib); 355 | indices.append(ic); 356 | 357 | indices.append(ia); 358 | indices.append(ic); 359 | indices.append(id); 360 | } 361 | 362 | 363 | static void generate_geometry_naive_surface_nets() 364 | { 365 | static Vector inds(65*65*2); 366 | 367 | for (int z = 0; z < 64; z++) { 368 | for (int y = 0; y < 64; y++) { 369 | for (int x = 0; x < 64; x++) { 370 | const Vec3i p(x, y, z); 371 | const float vs[8] = { 372 | voxels[offset_3d({x, y, z}, Vec3i(65))], 373 | voxels[offset_3d({x+1, y, z}, Vec3i(65))], 374 | voxels[offset_3d({x, y+1, z}, Vec3i(65))], 375 | voxels[offset_3d({x+1, y+1, z}, Vec3i(65))], 376 | voxels[offset_3d({x, y, z+1}, Vec3i(65))], 377 | voxels[offset_3d({x+1, y, z+1}, Vec3i(65))], 378 | voxels[offset_3d({x, y+1, z+1}, Vec3i(65))], 379 | voxels[offset_3d({x+1, y+1, z+1}, Vec3i(65))], 380 | }; 381 | 382 | const int config_n = 383 | ((vs[0] < 0.0f) << 0) | 384 | ((vs[1] < 0.0f) << 1) | 385 | ((vs[2] < 0.0f) << 2) | 386 | ((vs[3] < 0.0f) << 3) | 387 | ((vs[4] < 0.0f) << 4) | 388 | ((vs[5] < 0.0f) << 5) | 389 | ((vs[6] < 0.0f) << 6) | 390 | ((vs[7] < 0.0f) << 7); 391 | 392 | if (config_n == 0 || config_n == 255) 393 | continue; 394 | 395 | Vec3f average(0); 396 | int average_n = 0; 397 | auto do_edge = [&](float va, float vb, int axis, const Vec3i &p) { 398 | if ((va < 0.0) == (vb < 0.0)) 399 | return; 400 | 401 | Vec3f v = ToVec3f(p); 402 | v[axis] += va / (va - vb); 403 | average += v; 404 | average_n++; 405 | }; 406 | 407 | do_edge(vs[0], vs[1], 0, Vec3i(x, y, z)); 408 | do_edge(vs[2], vs[3], 0, Vec3i(x, y+1, z)); 409 | do_edge(vs[4], vs[5], 0, Vec3i(x, y, z+1)); 410 | do_edge(vs[6], vs[7], 0, Vec3i(x, y+1, z+1)); 411 | do_edge(vs[0], vs[2], 1, Vec3i(x, y, z)); 412 | do_edge(vs[1], vs[3], 1, Vec3i(x+1, y, z)); 413 | do_edge(vs[4], vs[6], 1, Vec3i(x, y, z+1)); 414 | do_edge(vs[5], vs[7], 1, Vec3i(x+1, y, z+1)); 415 | do_edge(vs[0], vs[4], 2, Vec3i(x, y, z)); 416 | do_edge(vs[1], vs[5], 2, Vec3i(x+1, y, z)); 417 | do_edge(vs[2], vs[6], 2, Vec3i(x, y+1, z)); 418 | do_edge(vs[3], vs[7], 2, Vec3i(x+1, y+1, z)); 419 | 420 | const Vec3f v = average / Vec3f(average_n); 421 | inds[offset_3d_slab(p, Vec3i(65))] = vertices.length(); 422 | vertices.append({v, Vec3f(0)}); 423 | 424 | const bool flip = vs[0] < 0.0f; 425 | if (p.y > 0 && p.z > 0 && (vs[0] < 0.0f) != (vs[1] < 0.0f)) { 426 | quad(flip, 427 | inds[offset_3d_slab(Vec3i(p.x, p.y, p.z), Vec3i(65))], 428 | inds[offset_3d_slab(Vec3i(p.x, p.y, p.z-1), Vec3i(65))], 429 | inds[offset_3d_slab(Vec3i(p.x, p.y-1, p.z-1), Vec3i(65))], 430 | inds[offset_3d_slab(Vec3i(p.x, p.y-1, p.z), Vec3i(65))] 431 | ); 432 | } 433 | if (p.x > 0 && p.z > 0 && (vs[0] < 0.0f) != (vs[2] < 0.0f)) { 434 | quad(flip, 435 | inds[offset_3d_slab(Vec3i(p.x, p.y, p.z), Vec3i(65))], 436 | inds[offset_3d_slab(Vec3i(p.x-1, p.y, p.z), Vec3i(65))], 437 | inds[offset_3d_slab(Vec3i(p.x-1, p.y, p.z-1), Vec3i(65))], 438 | inds[offset_3d_slab(Vec3i(p.x, p.y, p.z-1), Vec3i(65))] 439 | ); 440 | } 441 | if (p.x > 0 && p.y > 0 && (vs[0] < 0.0f) != (vs[4] < 0.0f)) { 442 | quad(flip, 443 | inds[offset_3d_slab(Vec3i(p.x, p.y, p.z), Vec3i(65))], 444 | inds[offset_3d_slab(Vec3i(p.x, p.y-1, p.z), Vec3i(65))], 445 | inds[offset_3d_slab(Vec3i(p.x-1, p.y-1, p.z), Vec3i(65))], 446 | inds[offset_3d_slab(Vec3i(p.x-1, p.y, p.z), Vec3i(65))] 447 | ); 448 | } 449 | }}} 450 | for (Vertex &v : vertices) 451 | v.normal = normalize(v.normal); 452 | } 453 | 454 | //---------------------------------------------------------------------------- 455 | // Camera 456 | //---------------------------------------------------------------------------- 457 | 458 | enum PlayerCameraState { 459 | PCS_MOVING_FORWARD = 1 << 0, 460 | PCS_MOVING_BACKWARD = 1 << 1, 461 | PCS_MOVING_LEFT = 1 << 2, 462 | PCS_MOVING_RIGHT = 1 << 3, 463 | }; 464 | 465 | static unsigned camera_state = 0; 466 | static Transform camera( 467 | Vec3f(33.755638, 49.220379, 72.422722), 468 | Quat(-0.362434, 0.002032, 0.000791, 0.931997)); 469 | static bool rotating_camera = false; 470 | 471 | static Quat mouse_rotate(const Quat &in, float x, float y, float sensitivity) 472 | { 473 | const Quat xq(Vec3f_Y(), -x * sensitivity); 474 | const Quat yq(Vec3f_X(), -y * sensitivity); 475 | return xq * (in * yq); 476 | } 477 | 478 | static void get_camera_vectors(Vec3f *look_dir, Vec3f *up, Vec3f *right, const Quat &orient) 479 | { 480 | NG_ASSERT(look_dir != nullptr); 481 | NG_ASSERT(up != nullptr); 482 | NG_ASSERT(right != nullptr); 483 | const Mat4 m = to_mat4(inverse(orient)); 484 | *right = { m[0], m[4], m[8]}; 485 | *up = { m[1], m[5], m[9]}; 486 | *look_dir = {-m[2], -m[6], -m[10]}; 487 | } 488 | 489 | static Vec3f get_walk_direction() 490 | { 491 | constexpr float sincos_45 = 0.7071067f; 492 | 493 | Vec3f look_dir, up, right; 494 | get_camera_vectors(&look_dir, &up, &right, camera.orientation); 495 | 496 | float fb_move = 0.0f; 497 | float lr_move = 0.0f; 498 | if (camera_state & PCS_MOVING_FORWARD) 499 | fb_move += 1.0f; 500 | if (camera_state & PCS_MOVING_BACKWARD) 501 | fb_move -= 1.0f; 502 | if (camera_state & PCS_MOVING_LEFT) 503 | lr_move -= 1.0f; 504 | if (camera_state & PCS_MOVING_RIGHT) 505 | lr_move += 1.0f; 506 | 507 | if (camera_state & (PCS_MOVING_FORWARD | PCS_MOVING_BACKWARD) && 508 | camera_state & (PCS_MOVING_LEFT | PCS_MOVING_RIGHT)) 509 | { 510 | fb_move *= sincos_45; 511 | lr_move *= sincos_45; 512 | } 513 | 514 | return look_dir * Vec3f(fb_move) + right * Vec3f(lr_move); 515 | } 516 | 517 | //---------------------------------------------------------------------------- 518 | // GLUT 519 | //---------------------------------------------------------------------------- 520 | 521 | static void keyboardDown(unsigned char key, int x, int y) { 522 | Vec3f look_dir, up, right; 523 | 524 | switch (key) { 525 | case 'Q': 526 | case 'q': 527 | case 27: 528 | exit(0); 529 | break; 530 | case 'w': 531 | camera_state |= PCS_MOVING_FORWARD; 532 | break; 533 | case 'a': 534 | camera_state |= PCS_MOVING_LEFT; 535 | break; 536 | case 's': 537 | camera_state |= PCS_MOVING_BACKWARD; 538 | break; 539 | case 'd': 540 | camera_state |= PCS_MOVING_RIGHT; 541 | break; 542 | case 'p': 543 | printf("pos: %f %f %f\n", VEC3(camera.translation)); 544 | printf("orient %f %f %f %f\n", VEC4(camera.orientation)); 545 | break; 546 | } 547 | } 548 | 549 | static void keyboardUp(unsigned char key, int x, int y) { 550 | switch (key) { 551 | case 'w': 552 | camera_state &= ~PCS_MOVING_FORWARD; 553 | break; 554 | case 'a': 555 | camera_state &= ~PCS_MOVING_LEFT; 556 | break; 557 | case 's': 558 | camera_state &= ~PCS_MOVING_BACKWARD; 559 | break; 560 | case 'd': 561 | camera_state &= ~PCS_MOVING_RIGHT; 562 | break; 563 | } 564 | } 565 | 566 | static void keyboardSpecialDown(int k, int x, int y) { 567 | } 568 | 569 | static void keyboardSpecialUp(int k, int x, int y) { 570 | } 571 | 572 | static void reshape(int width, int height) 573 | { 574 | GLfloat fieldOfView = 90.0f; 575 | glViewport(0, 0, width, height); 576 | 577 | glMatrixMode(GL_PROJECTION); 578 | glLoadIdentity(); 579 | gluPerspective(fieldOfView, (GLfloat)width/height, 0.1, 500.0); 580 | 581 | glMatrixMode(GL_MODELVIEW); 582 | glLoadIdentity(); 583 | } 584 | 585 | static void mouseClick(int button, int state, int x, int y) 586 | { 587 | rotating_camera = state == GLUT_DOWN; 588 | } 589 | 590 | static void mouseMotion(int x, int y) 591 | { 592 | static int last_x = 0, last_y = 0; 593 | const int dx = x - last_x; 594 | const int dy = y - last_y; 595 | last_x = x; 596 | last_y = y; 597 | 598 | if (rotating_camera) 599 | camera.orientation = mouse_rotate(camera.orientation, dx, dy, 0.25); 600 | } 601 | 602 | static void draw() 603 | { 604 | static int last_time = 0; 605 | const int current_time = glutGet(GLUT_ELAPSED_TIME); 606 | const float delta = float(current_time - last_time) / 1000.0f; 607 | camera.translation += get_walk_direction() * Vec3f(delta) * Vec3f(0.05); 608 | 609 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 610 | glMatrixMode(GL_MODELVIEW); 611 | glLoadIdentity(); 612 | glLoadMatrixf(to_mat4(inverse(camera)).data); 613 | 614 | // LIGHT SETUP HERE 615 | const Vec3f tmp = normalize(Vec3f(1, 1, 0)); 616 | const Vec4f light_dir(tmp.x, tmp.y, tmp.z, 0); 617 | const Vec4f ambient(0.4, 0.4, 0.4, 1); 618 | const Vec4f diffuse(1, 1, 1, 1); 619 | glLightfv(GL_LIGHT0, GL_AMBIENT, ambient.data); 620 | glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse.data); 621 | glLightfv(GL_LIGHT0, GL_POSITION, light_dir.data); 622 | 623 | // RENDER HERE 624 | glBegin(GL_TRIANGLES); 625 | for (int idx : indices) { 626 | const Vertex &v = vertices[idx]; 627 | glNormal3fv(v.normal.data); 628 | glVertex3fv(v.position.data); 629 | } 630 | glEnd(); 631 | 632 | glutSwapBuffers(); 633 | glutPostRedisplay(); 634 | } 635 | 636 | static void idle() 637 | { 638 | } 639 | 640 | /* initialize OpenGL settings */ 641 | static void initGL(int width, int height) 642 | { 643 | reshape(width, height); 644 | 645 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 646 | glClearDepth(1.0f); 647 | 648 | glEnable(GL_DEPTH_TEST); 649 | glDepthFunc(GL_LEQUAL); 650 | 651 | glEnable(GL_LIGHTING); 652 | glEnable(GL_LIGHT0); 653 | } 654 | 655 | static void menu(int choice) 656 | { 657 | static bool wireframe = false; 658 | 659 | switch (choice) { 660 | case 'f': 661 | vertices.clear(); 662 | indices.clear(); 663 | generate_geometry(); 664 | break; 665 | case 's': 666 | vertices.clear(); 667 | indices.clear(); 668 | generate_geometry_smooth(); 669 | break; 670 | case 'n': 671 | vertices.clear(); 672 | indices.clear(); 673 | generate_geometry_naive_surface_nets(); 674 | break; 675 | case 'w': 676 | if (!wireframe) { 677 | // enable 678 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 679 | } else { 680 | // disable 681 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 682 | } 683 | wireframe = !wireframe; 684 | break; 685 | } 686 | } 687 | 688 | int main(int argc, char** argv) 689 | { 690 | generate_voxels(); 691 | generate_geometry(); 692 | 693 | glutInit(&argc, argv); 694 | 695 | glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 696 | glutInitWindowSize(800, 600); 697 | glutInitWindowPosition(100, 100); 698 | glutCreateWindow("Perspective's GLUT Template"); 699 | 700 | // register glut call backs 701 | glutKeyboardFunc(keyboardDown); 702 | glutKeyboardUpFunc(keyboardUp); 703 | glutSpecialFunc(keyboardSpecialDown); 704 | glutSpecialUpFunc(keyboardSpecialUp); 705 | glutMouseFunc(mouseClick); 706 | glutMotionFunc(mouseMotion); 707 | glutPassiveMotionFunc(mouseMotion); 708 | glutReshapeFunc(reshape); 709 | glutDisplayFunc(draw); 710 | glutIdleFunc(idle); 711 | glutIgnoreKeyRepeat(true); // ignore keys held down 712 | 713 | glutCreateMenu(menu); 714 | glutAddMenuEntry("Marching Cubes (flat shading)", 'f'); 715 | glutAddMenuEntry("Marching Cubes (smooth shading)", 's'); 716 | glutAddMenuEntry("Naive Surface Nets (smooth shading)", 'n'); 717 | glutAddMenuEntry("Toggle Wireframe", 'w'); 718 | glutAttachMenu(GLUT_RIGHT_BUTTON); 719 | 720 | initGL(800, 600); 721 | 722 | glutMainLoop(); 723 | return 0; 724 | } 725 | -------------------------------------------------------------------------------- /Math/Mat.cpp: -------------------------------------------------------------------------------- 1 | #include "Math/Mat.h" 2 | #include 3 | #include 4 | 5 | void Mat4::dump() const 6 | { 7 | printf("[%f %f %f %f\n", data[0], data[4], data[8], data[12]); 8 | printf(" %f %f %f %f\n", data[1], data[5], data[9], data[13]); 9 | printf(" %f %f %f %f\n", data[2], data[6], data[10], data[14]); 10 | printf(" %f %f %f %f]\n", data[3], data[7], data[11], data[15]); 11 | } 12 | 13 | bool operator==(const Mat4 &l, const Mat4 &r) 14 | { 15 | return ( 16 | l[0] == r[0] && 17 | l[1] == r[1] && 18 | l[2] == r[2] && 19 | l[3] == r[3] && 20 | l[4] == r[4] && 21 | l[5] == r[5] && 22 | l[6] == r[6] && 23 | l[7] == r[7] && 24 | l[8] == r[8] && 25 | l[9] == r[9] && 26 | l[10] == r[10] && 27 | l[11] == r[11] && 28 | l[12] == r[12] && 29 | l[13] == r[13] && 30 | l[14] == r[14] && 31 | l[15] == r[15] 32 | ); 33 | } 34 | 35 | bool operator!=(const Mat4 &lhs, const Mat4 &rhs) 36 | { 37 | return !operator==(lhs, rhs); 38 | } 39 | 40 | Mat4 operator*(const Mat4 &l, const Mat4 &r) 41 | { 42 | Mat4 out; 43 | out[0] = l[0] * r[0] + l[4] * r[1] + l[8] * r[2] + l[12] * r[3]; 44 | out[1] = l[1] * r[0] + l[5] * r[1] + l[9] * r[2] + l[13] * r[3]; 45 | out[2] = l[2] * r[0] + l[6] * r[1] + l[10] * r[2] + l[14] * r[3]; 46 | out[3] = l[3] * r[0] + l[7] * r[1] + l[11] * r[2] + l[15] * r[3]; 47 | 48 | out[4] = l[0] * r[4] + l[4] * r[5] + l[8] * r[6] + l[12] * r[7]; 49 | out[5] = l[1] * r[4] + l[5] * r[5] + l[9] * r[6] + l[13] * r[7]; 50 | out[6] = l[2] * r[4] + l[6] * r[5] + l[10] * r[6] + l[14] * r[7]; 51 | out[7] = l[3] * r[4] + l[7] * r[5] + l[11] * r[6] + l[15] * r[7]; 52 | 53 | out[8] = l[0] * r[8] + l[4] * r[9] + l[8] * r[10] + l[12] * r[11]; 54 | out[9] = l[1] * r[8] + l[5] * r[9] + l[9] * r[10] + l[13] * r[11]; 55 | out[10] = l[2] * r[8] + l[6] * r[9] + l[10] * r[10] + l[14] * r[11]; 56 | out[11] = l[3] * r[8] + l[7] * r[9] + l[11] * r[10] + l[15] * r[11]; 57 | 58 | out[12] = l[0] * r[12] + l[4] * r[13] + l[8] * r[14] + l[12] * r[15]; 59 | out[13] = l[1] * r[12] + l[5] * r[13] + l[9] * r[14] + l[13] * r[15]; 60 | out[14] = l[2] * r[12] + l[6] * r[13] + l[10] * r[14] + l[14] * r[15]; 61 | out[15] = l[3] * r[12] + l[7] * r[13] + l[11] * r[14] + l[15] * r[15]; 62 | return out; 63 | } 64 | 65 | Mat4 operator+(const Mat4 &lhs, const Mat4 &rhs) 66 | { 67 | Mat4 out; 68 | out[0] = lhs[0] + rhs[0]; 69 | out[1] = lhs[1] + rhs[1]; 70 | out[2] = lhs[2] + rhs[2]; 71 | out[3] = lhs[3] + rhs[3]; 72 | out[4] = lhs[4] + rhs[4]; 73 | out[5] = lhs[5] + rhs[5]; 74 | out[6] = lhs[6] + rhs[6]; 75 | out[7] = lhs[7] + rhs[7]; 76 | out[8] = lhs[8] + rhs[8]; 77 | out[9] = lhs[9] + rhs[9]; 78 | out[10] = lhs[10] + rhs[10]; 79 | out[11] = lhs[11] + rhs[11]; 80 | out[12] = lhs[12] + rhs[12]; 81 | out[13] = lhs[13] + rhs[13]; 82 | out[14] = lhs[14] + rhs[14]; 83 | out[15] = lhs[15] + rhs[15]; 84 | return out; 85 | } 86 | 87 | Vec3f operator*(const Mat4 &l, const Vec3f &r) 88 | { 89 | return { 90 | l[0] * r[0] + l[4] * r[1] + l[8] * r[2] + l[12], 91 | l[1] * r[0] + l[5] * r[1] + l[9] * r[2] + l[13], 92 | l[2] * r[0] + l[6] * r[1] + l[10] * r[2] + l[14] 93 | }; 94 | } 95 | 96 | Vec3f operator*(const Vec3f &l, const Mat4 &r) 97 | { 98 | return { 99 | l[0] * r[0] + l[1] * r[1] + l[2] * r[2] + r[3], 100 | l[0] * r[4] + l[1] * r[5] + l[2] * r[6] + r[7], 101 | l[0] * r[8] + l[1] * r[9] + l[2] * r[10] + r[11], 102 | }; 103 | } 104 | 105 | // matrix l by column-vector r 106 | Vec4f operator*(const Mat4 &l, const Vec4f &r) 107 | { 108 | return { 109 | l[0] * r[0] + l[4] * r[1] + l[8] * r[2] + l[12] * r[3], 110 | l[1] * r[0] + l[5] * r[1] + l[9] * r[2] + l[13] * r[3], 111 | l[2] * r[0] + l[6] * r[1] + l[10] * r[2] + l[14] * r[3], 112 | l[3] * r[0] + l[7] * r[1] + l[11] * r[2] + l[15] * r[3] 113 | }; 114 | } 115 | 116 | // row-vector by matrix r 117 | Vec4f operator*(const Vec4f &l, const Mat4 &r) 118 | { 119 | return { 120 | l[0] * r[0] + l[1] * r[1] + l[2] * r[2] + l[3] * r[3], 121 | l[0] * r[4] + l[1] * r[5] + l[2] * r[6] + l[3] * r[7], 122 | l[0] * r[8] + l[1] * r[9] + l[2] * r[10] + l[3] * r[11], 123 | l[0] * r[12] + l[1] * r[13] + l[2] * r[14] + l[3] * r[15] 124 | }; 125 | } 126 | 127 | Mat4 Mat4_Rotate(const Vec3f &axis, float angle) 128 | { 129 | Mat4 m; 130 | float rad = angle * MATH_DEG_TO_RAD; 131 | float c = cosf(rad); 132 | float s = sinf(rad); 133 | Vec3f v = normalize(axis); 134 | float xx = v.x * v.x; 135 | float yy = v.y * v.y; 136 | float zz = v.z * v.z; 137 | float xy = v.x * v.y; 138 | float yz = v.y * v.z; 139 | float zx = v.z * v.x; 140 | float xs = v.x * s; 141 | float ys = v.y * s; 142 | float zs = v.z * s; 143 | m[0] = (1.0f - c) * xx + c; m[4] = (1.0f - c) * xy - zs; m[8] = (1.0f - c) * zx + ys; m[12] = 0.0f; 144 | m[1] = (1.0f - c) * xy + zs; m[5] = (1.0f - c) * yy + c; m[9] = (1.0f - c) * yz - xs; m[13] = 0.0f; 145 | m[2] = (1.0f - c) * zx - ys; m[6] = (1.0f - c) * yz + xs; m[10] = (1.0f - c) * zz + c; m[14] = 0.0f; 146 | m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f; 147 | 148 | return m; 149 | } 150 | 151 | Mat4 Mat4_RotateX(float angle) 152 | { 153 | Mat4 m; 154 | float rad = angle * MATH_DEG_TO_RAD; 155 | float c = cosf(rad); 156 | float s = sinf(rad); 157 | m[0] = 1.0f; m[4] = 0.0f; m[8] = 0.0f; m[12] = 0.0f; 158 | m[1] = 0.0f; m[5] = c; m[9] = -s; m[13] = 0.0f; 159 | m[2] = 0.0f; m[6] = s; m[10] = c; m[14] = 0.0f; 160 | m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f; 161 | 162 | return m; 163 | } 164 | 165 | Mat4 Mat4_RotateY(float angle) 166 | { 167 | Mat4 m; 168 | float rad = angle * MATH_DEG_TO_RAD; 169 | float c = cosf(rad); 170 | float s = sinf(rad); 171 | m[0] = c; m[4] = 0.0f; m[8] = s; m[12] = 0.0f; 172 | m[1] = 0.0f; m[5] = 1.0f; m[9] = 0.0f; m[13] = 0.0f; 173 | m[2] = -s; m[6] = 0.0f; m[10] = c; m[14] = 0.0f; 174 | m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f; 175 | 176 | return m; 177 | } 178 | 179 | Mat4 Mat4_RotateZ(float angle) 180 | { 181 | Mat4 m; 182 | float rad = angle * MATH_DEG_TO_RAD; 183 | float c = cosf(rad); 184 | float s = sinf(rad); 185 | m[0] = c; m[4] = -s; m[8] = 0.0f; m[12] = 0.0f; 186 | m[1] = s; m[5] = c; m[9] = 0.0f; m[13] = 0.0f; 187 | m[2] = 0.0f; m[6] = 0.0f; m[10] = 1.0f; m[14] = 0.0f; 188 | m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f; 189 | 190 | return m; 191 | } 192 | 193 | Mat4 Mat4_Scale(const Vec3f &v) 194 | { 195 | Mat4 m; 196 | m[0] = v.x; m[4] = 0.0f; m[8] = 0.0f; m[12] = 0.0f; 197 | m[1] = 0.0f; m[5] = v.y; m[9] = 0.0f; m[13] = 0.0f; 198 | m[2] = 0.0f; m[6] = 0.0f; m[10] = v.z; m[14] = 0.0f; 199 | m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f; 200 | 201 | return m; 202 | } 203 | 204 | Mat4 Mat4_Scale(float f) 205 | { 206 | return Mat4_Scale(Vec3f(f)); 207 | } 208 | 209 | Mat4 Mat4_Translate(const Vec3f &v) 210 | { 211 | Mat4 m; 212 | m[0] = 1.0f; m[4] = 0.0f; m[8] = 0.0f; m[12] = v.x; 213 | m[1] = 0.0f; m[5] = 1.0f; m[9] = 0.0f; m[13] = v.y; 214 | m[2] = 0.0f; m[6] = 0.0f; m[10] = 1.0f; m[14] = v.z; 215 | m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f; 216 | 217 | return m; 218 | } 219 | 220 | Mat4 Mat4_Perspective(float fov, float aspect, float znear, float zfar) 221 | { 222 | Mat4 m; 223 | float y = std::tan(fov * MATH_DEG_TO_RAD / 2); 224 | float x = y * aspect; 225 | 226 | m[0] = 1.0f / x; 227 | m[1] = 0.0f; 228 | m[2] = 0.0f; 229 | m[3] = 0.0f; 230 | 231 | m[4] = 0.0f; 232 | m[5] = 1.0f / y; 233 | m[6] = 0.0f; 234 | m[7] = 0.0f; 235 | 236 | m[8] = 0.0f; 237 | m[9] = 0.0f; 238 | m[10] = -(zfar + znear) / (zfar - znear); 239 | m[11] = -1.0f; 240 | 241 | m[12] = 0.0f; 242 | m[13] = 0.0f; 243 | m[14] = -(2.0f * zfar * znear) / (zfar - znear); 244 | m[15] = 0.0f; 245 | 246 | return m; 247 | } 248 | 249 | Mat4 Mat4_Ortho(float left, float right, float bottom, float top, float znear, float zfar) 250 | { 251 | Mat4 m; 252 | float x = 2.0f / (right - left); 253 | float y = 2.0f / (top - bottom); 254 | float z = -2.0f / (zfar - znear); 255 | float tx = - ((right + left) / (right - left)); 256 | float ty = - ((top + bottom) / (top - bottom)); 257 | float tz = - ((zfar + znear) / (zfar - znear)); 258 | 259 | m[0] = x; 260 | m[1] = 0.0f; 261 | m[2] = 0.0f; 262 | m[3] = 0.0f; 263 | 264 | m[4] = 0.0f; 265 | m[5] = y; 266 | m[6] = 0.0f; 267 | m[7] = 0.0f; 268 | 269 | m[8] = 0.0f; 270 | m[9] = 0.0f; 271 | m[10] = z; 272 | m[11] = 0.0f; 273 | 274 | m[12] = tx; 275 | m[13] = ty; 276 | m[14] = tz; 277 | m[15] = 1.0f; 278 | 279 | return m; 280 | } 281 | 282 | Mat4 Mat4_LookAt(const Vec3f &eye, const Vec3f ¢er, const Vec3f &up) 283 | { 284 | Mat4 m; 285 | Vec3f n,u,s; 286 | n = normalize(eye - center); 287 | s = normalize(cross(up, n)); 288 | u = normalize(cross(n, s)); 289 | 290 | m[0] = s.x; m[4] = s.y; m[8] = s.z; m[12] = 0.0f; 291 | m[1] = u.x; m[5] = u.y; m[9] = u.z; m[13] = 0.0f; 292 | m[2] = n.x; m[6] = n.y; m[10] = n.z; m[14] = 0.0f; 293 | m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f; 294 | return m * Mat4_Translate(-eye); 295 | } 296 | 297 | Mat4 transpose(const Mat4 &m) 298 | { 299 | Mat4 r; 300 | r[0] = m[0]; r[4] = m[1]; r[8] = m[2]; r[12] = m[3]; 301 | r[1] = m[4]; r[5] = m[5]; r[9] = m[6]; r[13] = m[7]; 302 | r[2] = m[8]; r[6] = m[9]; r[10] = m[10]; r[14] = m[11]; 303 | r[3] = m[12]; r[7] = m[13]; r[11] = m[14]; r[15] = m[15]; 304 | return r; 305 | } 306 | 307 | float determinant(const Mat4 &m) 308 | { 309 | float d; 310 | d = m[0] * (m[5] * (m[10] * m[15] - m[14] * m[11]) - m[9] * (m[6] * m[15] - m[14] * m[7]) + m[13] * (m[6] * m[11] - m[10] * m[7])); 311 | d -= m[4] * (m[1] * (m[10] * m[15] - m[14] * m[11]) - m[9] * (m[2] * m[15] - m[14] * m[3]) + m[13] * (m[2] * m[11] - m[10] * m[3])); 312 | d += m[8] * (m[1] * (m[6] * m[15] - m[14] * m[7]) - m[5] * (m[2] * m[15] - m[14] * m[3]) + m[13] * (m[2] * m[7] - m[6] * m[3])); 313 | d -= m[12] * (m[1] * (m[6] * m[11] - m[10] * m[7]) - m[5] * (m[2] * m[11] - m[10] * m[3]) + m[9] * (m[2] * m[7] - m[6] * m[3])); 314 | return d; 315 | } 316 | 317 | Mat4 inverse(const Mat4 &m, bool *inversed) 318 | { 319 | Mat4 r; 320 | float d = determinant(m); 321 | if (d < MATH_EPSILON) { 322 | if (inversed) 323 | *inversed = false; 324 | return r; 325 | } 326 | float id = 1.0f / d; 327 | r[0] = (m[5] * (m[10] * m[15] - m[14] * m[11]) - m[9] * (m[6] * m[15] - m[14] * m[7]) + m[13] * (m[6] * m[11] - m[10] * m[7])) * id; 328 | r[1] = -(m[1] * (m[10] * m[15] - m[14] * m[11]) - m[9] * (m[2] * m[15] - m[14] * m[3]) + m[13] * (m[2] * m[11] - m[10] * m[3])) * id; 329 | r[2] = (m[1] * (m[6] * m[15] - m[14] * m[7]) - m[5] * (m[2] * m[15] - m[14] * m[3]) + m[13] * (m[2] * m[7] - m[6] * m[3])) * id; 330 | r[3] = -(m[1] * (m[6] * m[11] - m[10] * m[7]) - m[5] * (m[2] * m[11] - m[10] * m[3]) + m[9] * (m[2] * m[7] - m[6] * m[3])) * id; 331 | r[4] = -(m[4] * (m[10] * m[15] - m[14] * m[11]) - m[8] * (m[6] * m[15] - m[14] * m[7]) + m[12] * (m[6] * m[11] - m[10] * m[7])) * id; 332 | r[5] = (m[0] * (m[10] * m[15] - m[14] * m[11]) - m[8] * (m[2] * m[15] - m[14] * m[3]) + m[12] * (m[2] * m[11] - m[10] * m[3])) * id; 333 | r[6] = -(m[0] * (m[6] * m[15] - m[14] * m[7]) - m[4] * (m[2] * m[15] - m[14] * m[3]) + m[12] * (m[2] * m[7] - m[6] * m[3])) * id; 334 | r[7] = (m[0] * (m[6] * m[11] - m[10] * m[7]) - m[4] * (m[2] * m[11] - m[10] * m[3]) + m[8] * (m[2] * m[7] - m[6] * m[3])) * id; 335 | r[8] = (m[4] * (m[9] * m[15] - m[13] * m[11]) - m[8] * (m[5] * m[15] - m[13] * m[7]) + m[12] * (m[5] * m[11] - m[9] * m[7])) * id; 336 | r[9] = -(m[0] * (m[9] * m[15] - m[13] * m[11]) - m[8] * (m[1] * m[15] - m[13] * m[3]) + m[12] * (m[1] * m[11] - m[9] * m[3])) * id; 337 | r[10] = (m[0] * (m[5] * m[15] - m[13] * m[7]) - m[4] * (m[1] * m[15] - m[13] * m[3]) + m[12] * (m[1] * m[7] - m[5] * m[3])) * id; 338 | r[11] = -(m[0] * (m[5] * m[11] - m[9] * m[7]) - m[4] * (m[1] * m[11] - m[9] * m[3]) + m[8] * (m[1] * m[7] - m[5] * m[3])) * id; 339 | r[12] = -(m[4] * (m[9] * m[14] - m[13] * m[10]) - m[8] * (m[5] * m[14] - m[13] * m[6]) + m[12] * (m[5] * m[10] - m[9] * m[6])) * id; 340 | r[13] = (m[0] * (m[9] * m[14] - m[13] * m[10]) - m[8] * (m[1] * m[14] - m[13] * m[2]) + m[12] * (m[1] * m[10] - m[9] * m[2])) * id; 341 | r[14] = -(m[0] * (m[5] * m[14] - m[13] * m[6]) - m[4] * (m[1] * m[14] - m[13] * m[2]) + m[12] * (m[1] * m[6] - m[5] * m[2])) * id; 342 | r[15] = (m[0] * (m[5] * m[10] - m[9] * m[6]) - m[4] * (m[1] * m[10] - m[9] * m[2]) + m[8] * (m[1] * m[6] - m[5] * m[2])) * id; 343 | if (inversed) 344 | *inversed = true; 345 | return r; 346 | } 347 | 348 | Vec4f Vec4_MiniOrtho2D(float left, float right, float bottom, float top, const Vec2f &offset) 349 | { 350 | float x = 2.0f / (right - left); 351 | float y = 2.0f / (top - bottom); 352 | float tx = -((right + left) / (right - left)) + offset.x * x; 353 | float ty = -((top + bottom) / (top - bottom)) + offset.y * y; 354 | return {x, y, tx, ty}; 355 | } 356 | 357 | Vec4f mini_ortho_translate(const Vec4f &miniortho, const Vec2f &offset) 358 | { 359 | return { 360 | miniortho.x, 361 | miniortho.y, 362 | miniortho.z + miniortho.x * offset.x, 363 | miniortho.w + miniortho.y * offset.y 364 | }; 365 | } 366 | 367 | Vec4f Vec4_MiniPerspective3D(float vfov, float aspect, float znear, float zfar) 368 | { 369 | float v = std::tan(vfov * MATH_DEG_TO_RAD); 370 | float h = v * aspect; 371 | return { 372 | 1.0f / v, 373 | 1.0f / h, 374 | -(zfar + znear) / (zfar - znear), 375 | -(2.0f * zfar * znear) / (zfar - znear) 376 | }; 377 | } 378 | 379 | Mat4 to_mat4(const Mat3 &m) 380 | { 381 | return Mat4( 382 | m[0], m[1], m[2], 0, 383 | m[3], m[4], m[5], 0, 384 | m[6], m[7], m[8], 0, 385 | 0, 0, 0, 1 386 | ); 387 | } 388 | 389 | Mat3 to_mat3(const Mat4 &m) 390 | { 391 | return Mat3( 392 | m[0], m[1], m[2], 393 | m[4], m[5], m[6], 394 | m[8], m[9], m[10] 395 | ); 396 | } 397 | -------------------------------------------------------------------------------- /Math/Mat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/Vec.h" 4 | 5 | //------------------------------------------------------------------------------ 6 | // Mat3 (column-major OpenGL-style) 7 | //------------------------------------------------------------------------------ 8 | 9 | struct Mat3 { 10 | // m[row][column] 11 | union { 12 | struct { 13 | float m11, m21, m31; // first column 14 | float m12, m22, m32; // second column 15 | float m13, m23, m33; // third column 16 | }; 17 | float data[9]; 18 | }; 19 | 20 | Mat3() = default; 21 | 22 | Mat3( 23 | float a11, float a21, float a31, 24 | float a12, float a22, float a32, 25 | float a13, float a23, float a33 26 | ): 27 | m11(a11), m21(a21), m31(a31), 28 | m12(a12), m22(a22), m32(a32), 29 | m13(a13), m23(a23), m33(a33) 30 | {} 31 | 32 | explicit Mat3(const float *n): 33 | m11(n[0]), m21(n[1]), m31(n[2]), 34 | m12(n[3]), m22(n[4]), m32(n[5]), 35 | m13(n[6]), m23(n[7]), m33(n[8]) 36 | {} 37 | 38 | float &operator[](int i) { return data[i]; } 39 | float operator[](int i) const { return data[i]; } 40 | }; 41 | 42 | //------------------------------------------------------------------------------ 43 | // Mat4 (column-major OpenGL-style) 44 | //------------------------------------------------------------------------------ 45 | 46 | struct Mat4 { 47 | // m[row][column] 48 | // translation is stored at m14 m24 m34 or m[12] m[13] m[14] 49 | 50 | union { 51 | struct { 52 | float m11, m21, m31, m41; // first column 53 | float m12, m22, m32, m42; // second column 54 | float m13, m23, m33, m43; // third column 55 | float m14, m24, m34, m44; // fourth column 56 | }; 57 | float data[16]; 58 | }; 59 | 60 | Mat4() = default; 61 | 62 | Mat4( 63 | float a11, float a21, float a31, float a41, 64 | float a12, float a22, float a32, float a42, 65 | float a13, float a23, float a33, float a43, 66 | float a14, float a24, float a34, float a44 67 | ): 68 | m11(a11), m21(a21), m31(a31), m41(a41), 69 | m12(a12), m22(a22), m32(a32), m42(a42), 70 | m13(a13), m23(a23), m33(a33), m43(a43), 71 | m14(a14), m24(a24), m34(a34), m44(a44) 72 | {} 73 | 74 | explicit Mat4(const float *n): 75 | m11(n[0]), m21(n[1]), m31(n[2]), m41(n[3]), 76 | m12(n[4]), m22(n[5]), m32(n[6]), m42(n[7]), 77 | m13(n[8]), m23(n[9]), m33(n[10]), m43(n[11]), 78 | m14(n[12]), m24(n[13]), m34(n[14]), m44(n[15]) 79 | {} 80 | 81 | float &operator[](int i) { return data[i]; } 82 | float operator[](int i) const { return data[i]; } 83 | 84 | void dump() const; 85 | }; 86 | 87 | static inline Mat4 Mat4_Identity() 88 | { 89 | return { 90 | 1, 0, 0, 0, 91 | 0, 1, 0, 0, 92 | 0, 0, 1, 0, 93 | 0, 0, 0, 1 94 | }; 95 | } 96 | 97 | static inline Mat4 Mat4_Zero() 98 | { 99 | return { 100 | 0, 0, 0, 0, 101 | 0, 0, 0, 0, 102 | 0, 0, 0, 0, 103 | 0, 0, 0, 0 104 | }; 105 | } 106 | 107 | static inline Mat4 Mat4_YZSwap() 108 | { 109 | return { 110 | 1, 0, 0, 0, 111 | 0, 0, -1, 0, 112 | 0, 1, 0, 0, 113 | 0, 0, 0, 1 114 | }; 115 | } 116 | 117 | bool operator==(const Mat4 &lhs, const Mat4 &rhs); 118 | bool operator!=(const Mat4 &lhs, const Mat4 &rhs); 119 | Mat4 operator*(const Mat4 &lhs, const Mat4 &rhs); 120 | Mat4 operator+(const Mat4 &lhs, const Mat4 &rhs); 121 | Vec3f operator*(const Mat4 &lhs, const Vec3f &rhs); 122 | Vec3f operator*(const Vec3f &lhs, const Mat4 &rhs); 123 | Vec4f operator*(const Mat4 &lhs, const Vec4f &rhs); 124 | Vec4f operator*(const Vec4f &lhs, const Mat4 &rhs); 125 | 126 | Mat4 Mat4_Rotate(const Vec3f &axis, float angle); 127 | Mat4 Mat4_RotateX(float angle); 128 | Mat4 Mat4_RotateY(float angle); 129 | Mat4 Mat4_RotateZ(float angle); 130 | Mat4 Mat4_Scale(const Vec3f &v); 131 | Mat4 Mat4_Scale(float f); 132 | Mat4 Mat4_Translate(const Vec3f &v); 133 | Mat4 Mat4_Perspective(float fov, float aspect, float znear, float zfar); 134 | Mat4 Mat4_Ortho(float left, float right, float bottom, float top, 135 | float znear = -1.0f, float zfar = 1.0f); 136 | Mat4 Mat4_LookAt(const Vec3f &eye, const Vec3f ¢er, const Vec3f &up); 137 | 138 | Mat4 transpose(const Mat4 &m); 139 | float determinant(const Mat4 &m); 140 | Mat4 inverse(const Mat4 &m, bool *inversed = nullptr); 141 | 142 | // MiniOrtho2D contains scale components at xy and translation at zw, to 143 | // transform the vertex do this: v * m.xy + m.zw. 144 | Vec4f Vec4_MiniOrtho2D(float left, float right, float bottom, float top, 145 | const Vec2f &offset = Vec2f(0)); 146 | Vec4f mini_ortho_translate(const Vec4f &miniortho, const Vec2f &offset); 147 | 148 | // MiniPerspective3D contains scale in xyz and z-offset in w, to transform the 149 | // vertex do this: Vec4(v.xy * m.xy, v.z * m.z + m.w, -v.z) 150 | Vec4f Vec4_MiniPerspective3D(float vfov, float aspect, float znear, float zfar); 151 | 152 | Mat4 to_mat4(const Mat3 &m); 153 | Mat3 to_mat3(const Mat4 &m); 154 | -------------------------------------------------------------------------------- /Math/Noise.cpp: -------------------------------------------------------------------------------- 1 | #include "Math/Noise.h" 2 | #include 3 | 4 | static inline float lerp(float a, float b, float v) 5 | { 6 | return a * (1 - v) + b * v; 7 | } 8 | 9 | static inline float Smooth(float v) 10 | { 11 | return v * v * (3 - 2 * v); 12 | } 13 | 14 | static inline float Gradient(const Vec3f &orig, const Vec3f &grad, const Vec3f &p) 15 | { 16 | return dot(grad, p - orig); 17 | } 18 | 19 | static inline float Gradient(const Vec2f &orig, const Vec2f &grad, const Vec2f &p) 20 | { 21 | return dot(grad, p - orig); 22 | } 23 | 24 | template 25 | static inline Vec3f RandomGradient3D(Rnd &g) 26 | { 27 | std::uniform_real_distribution _2pi(0.0f, MATH_PI * 2.0f); 28 | const float x = _2pi(g); 29 | const float angle = _2pi(g); 30 | return {cosf(angle) * cosf(x), sinf(angle) * cosf(x), sinf(x)}; 31 | } 32 | 33 | template 34 | static inline Vec2f RandomGradient2D(Rnd &g) 35 | { 36 | std::uniform_real_distribution _2pi(0.0f, MATH_PI * 2.0f); 37 | const float angle = _2pi(g); 38 | return {cosf(angle), sinf(angle)}; 39 | } 40 | 41 | Noise3D::Noise3D(int seed) 42 | { 43 | std::default_random_engine rnd(seed); 44 | for (auto &g : m_gradients) { 45 | g = RandomGradient3D(rnd); 46 | } 47 | 48 | for (int i = 0; i < 256; i++) { 49 | int j = std::uniform_int_distribution(0, i)(rnd); 50 | m_permutations[i] = m_permutations[j]; 51 | m_permutations[j] = i; 52 | } 53 | } 54 | 55 | Vec3f Noise3D::get_gradient(int x, int y, int z) const 56 | { 57 | int idx = 58 | m_permutations[x & 255] + 59 | m_permutations[y & 255] + 60 | m_permutations[z & 255]; 61 | return m_gradients[idx & 255]; 62 | } 63 | 64 | void Noise3D::get_gradients(Vec3f *origins, Vec3f *grads, 65 | float x, float y, float z) const 66 | { 67 | float x0f = std::floor(x); 68 | float y0f = std::floor(y); 69 | float z0f = std::floor(z); 70 | int x0 = x0f; 71 | int y0 = y0f; 72 | int z0 = z0f; 73 | int x1 = x0 + 1; 74 | int y1 = y0 + 1; 75 | int z1 = z0 + 1; 76 | 77 | grads[0] = get_gradient(x0, y0, z0); 78 | grads[1] = get_gradient(x0, y0, z1); 79 | grads[2] = get_gradient(x0, y1, z0); 80 | grads[3] = get_gradient(x0, y1, z1); 81 | grads[4] = get_gradient(x1, y0, z0); 82 | grads[5] = get_gradient(x1, y0, z1); 83 | grads[6] = get_gradient(x1, y1, z0); 84 | grads[7] = get_gradient(x1, y1, z1); 85 | 86 | origins[0] = {x0f + 0.0f, y0f + 0.0f, z0f + 0.0f}; 87 | origins[1] = {x0f + 0.0f, y0f + 0.0f, z0f + 1.0f}; 88 | origins[2] = {x0f + 0.0f, y0f + 1.0f, z0f + 0.0f}; 89 | origins[3] = {x0f + 0.0f, y0f + 1.0f, z0f + 1.0f}; 90 | origins[4] = {x0f + 1.0f, y0f + 0.0f, z0f + 0.0f}; 91 | origins[5] = {x0f + 1.0f, y0f + 0.0f, z0f + 1.0f}; 92 | origins[6] = {x0f + 1.0f, y0f + 1.0f, z0f + 0.0f}; 93 | origins[7] = {x0f + 1.0f, y0f + 1.0f, z0f + 1.0f}; 94 | } 95 | 96 | float Noise3D::get(float x, float y, float z) const 97 | { 98 | Vec3f origins[8]; 99 | Vec3f grads[8]; 100 | 101 | get_gradients(origins, grads, x, y, z); 102 | float vals[] = { 103 | Gradient(origins[0], grads[0], {x, y, z}), 104 | Gradient(origins[1], grads[1], {x, y, z}), 105 | Gradient(origins[2], grads[2], {x, y, z}), 106 | Gradient(origins[3], grads[3], {x, y, z}), 107 | Gradient(origins[4], grads[4], {x, y, z}), 108 | Gradient(origins[5], grads[5], {x, y, z}), 109 | Gradient(origins[6], grads[6], {x, y, z}), 110 | Gradient(origins[7], grads[7], {x, y, z}), 111 | }; 112 | 113 | float fz = Smooth(z - origins[0].z); 114 | float vz0 = lerp(vals[0], vals[1], fz); 115 | float vz1 = lerp(vals[2], vals[3], fz); 116 | float vz2 = lerp(vals[4], vals[5], fz); 117 | float vz3 = lerp(vals[6], vals[7], fz); 118 | 119 | float fy = Smooth(y - origins[0].y); 120 | float vy0 = lerp(vz0, vz1, fy); 121 | float vy1 = lerp(vz2, vz3, fy); 122 | 123 | float fx = Smooth(x - origins[0].x); 124 | return lerp(vy0, vy1, fx); 125 | } 126 | 127 | Noise2D::Noise2D(int seed) 128 | { 129 | std::default_random_engine rnd(seed); 130 | for (auto &g : m_gradients) { 131 | g = RandomGradient2D(rnd); 132 | } 133 | 134 | for (int i = 0; i < 256; i++) { 135 | int j = std::uniform_int_distribution(0, i)(rnd); 136 | m_permutations[i] = m_permutations[j]; 137 | m_permutations[j] = i; 138 | } 139 | } 140 | 141 | Vec2f Noise2D::get_gradient(int x, int y) const 142 | { 143 | int idx = 144 | m_permutations[x & 255] + 145 | m_permutations[y & 255]; 146 | return m_gradients[idx & 255]; 147 | } 148 | 149 | void Noise2D::get_gradients(Vec2f *origins, Vec2f *grads, float x, float y) const 150 | { 151 | float x0f = floorf(x); 152 | float y0f = floorf(y); 153 | int x0 = x0f; 154 | int y0 = y0f; 155 | int x1 = x0 + 1; 156 | int y1 = y0 + 1; 157 | 158 | grads[0] = get_gradient(x0, y0); 159 | grads[1] = get_gradient(x1, y0); 160 | grads[2] = get_gradient(x0, y1); 161 | grads[3] = get_gradient(x1, y1); 162 | 163 | origins[0] = {x0f + 0.0f, y0f + 0.0f}; 164 | origins[1] = {x0f + 1.0f, y0f + 0.0f}; 165 | origins[2] = {x0f + 0.0f, y0f + 1.0f}; 166 | origins[3] = {x0f + 1.0f, y0f + 1.0f}; 167 | } 168 | 169 | float Noise2D::get(float x, float y) const 170 | { 171 | Vec2f origins[4]; 172 | Vec2f grads[4]; 173 | 174 | get_gradients(origins, grads, x, y); 175 | float vals[] = { 176 | Gradient(origins[0], grads[0], {x, y}), 177 | Gradient(origins[1], grads[1], {x, y}), 178 | Gradient(origins[2], grads[2], {x, y}), 179 | Gradient(origins[3], grads[3], {x, y}), 180 | }; 181 | 182 | float fx = Smooth(x - origins[0].x); 183 | float vx0 = lerp(vals[0], vals[1], fx); 184 | float vx1 = lerp(vals[2], vals[3], fx); 185 | float fy = Smooth(y - origins[0].y); 186 | return lerp(vx0, vx1, fy); 187 | } 188 | -------------------------------------------------------------------------------- /Math/Noise.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/Vec.h" 4 | 5 | struct Noise3D { 6 | Vec3f m_gradients[256]; 7 | int m_permutations[256]; 8 | 9 | explicit Noise3D(int seed); 10 | Vec3f get_gradient(int x, int y, int z) const; 11 | void get_gradients(Vec3f *origins, Vec3f *grads, 12 | float x, float y, float z) const; 13 | 14 | float get(float x, float y, float z) const; 15 | }; 16 | 17 | struct Noise2D { 18 | Vec2f m_gradients[256]; 19 | int m_permutations[256]; 20 | 21 | explicit Noise2D(int seed); 22 | Vec2f get_gradient(int x, int y) const; 23 | void get_gradients(Vec2f *origins, Vec2f *grads, float x, float y) const; 24 | float get(float x, float y) const; 25 | }; 26 | -------------------------------------------------------------------------------- /Math/Plane.cpp: -------------------------------------------------------------------------------- 1 | #include "Math/Plane.h" 2 | 3 | PlaneSide Plane::side(const Vec3f &point) const 4 | { 5 | if ((dot(n, point) + d) >= 0.0f) 6 | return PS_FRONT; 7 | 8 | return PS_BACK; 9 | } 10 | 11 | PlaneSide Plane::side(const Vec3f &min, const Vec3f &max) const 12 | { 13 | Vec3f near(max); 14 | Vec3f far(min); 15 | 16 | if (n.x > 0) { 17 | near.x = min.x; 18 | far.x = max.x; 19 | } 20 | 21 | if (n.y > 0) { 22 | near.y = min.y; 23 | far.y = max.y; 24 | } 25 | 26 | if (n.z > 0) { 27 | near.z = min.z; 28 | far.z = max.z; 29 | } 30 | 31 | if (dot(n, near) + d > 0) 32 | return PS_FRONT; 33 | 34 | if (dot(n, far) + d > 0) 35 | return PS_BOTH; 36 | 37 | return PS_BACK; 38 | } 39 | -------------------------------------------------------------------------------- /Math/Plane.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/Vec.h" 4 | 5 | enum PlaneSide { 6 | PS_FRONT, 7 | PS_BACK, 8 | PS_BOTH, 9 | }; 10 | 11 | struct Plane { 12 | Plane() = default; 13 | 14 | // the normal should be normalized 15 | Plane(const Vec3f &origin, const Vec3f &normal): n(normal), d(-dot(n, origin)) {} 16 | Plane(const Vec3f &v1, const Vec3f &v2, const Vec3f &v3) 17 | { 18 | n = normalize(cross(v2 - v1, v3 - v1)); 19 | d = -dot(n, v1); 20 | } 21 | 22 | bool operator==(const Plane &r) const { return n == r.n && d == r.d; } 23 | bool operator!=(const Plane &r) const { return n != r.n || d != r.d; } 24 | 25 | PlaneSide side(const Vec3f &point) const; 26 | PlaneSide side(const Vec3f &min, const Vec3f &max) const; 27 | 28 | Vec3f n; 29 | float d; 30 | }; 31 | -------------------------------------------------------------------------------- /Math/Quat.cpp: -------------------------------------------------------------------------------- 1 | #include "Math/Quat.h" 2 | 3 | Quat::Quat(const Vec3f &dir, float angle) 4 | { 5 | const float halfangle = angle * MATH_DEG_TO_RAD / 2.0f; 6 | const float sinangle = sinf(halfangle); 7 | x = dir.x * sinangle; 8 | y = dir.y * sinangle; 9 | z = dir.z * sinangle; 10 | w = cosf(halfangle); 11 | } 12 | 13 | Quat::Quat(const Vec3f &u, const Vec3f &v) 14 | { 15 | Vec3f w = cross(u, v); 16 | float len2 = length2(w); 17 | float real = dot(u, v); 18 | if (len2 < MATH_EPSILON && real < 0) { 19 | w = std::abs(u.x) > std::abs(u.z) ? 20 | Vec3f(-u.y, u.x, 0) / Vec3f(length(u.XY())) : 21 | Vec3f(0, -u.z, u.y) / Vec3f(length(u.YZ())); 22 | this->x = w.x; 23 | this->y = w.y; 24 | this->z = w.z; 25 | this->w = 0; 26 | return; 27 | } 28 | 29 | real += std::sqrt(real * real + len2); 30 | float ilen = 1 / std::sqrt(real * real + len2); 31 | this->x = w.x * ilen; 32 | this->y = w.y * ilen; 33 | this->z = w.z * ilen; 34 | this->w = real * ilen; 35 | } 36 | 37 | Vec3f Quat::rotate(const Vec3f &v) const 38 | { 39 | /* 40 | // Alternative implementation, don't know which one is faster. 41 | // TODO: measure both 42 | const Vec3 xyz(x, y, z); 43 | const Vec3 t = Vec3(2) * Cross(xyz, v); 44 | return v + Vec3(w) * t + Cross(xyz, t); 45 | */ 46 | const Vec3f xyz(x, y, z); 47 | return v + Vec3f(2) * cross(xyz, cross(xyz, v) + Vec3f(w) * v); 48 | } 49 | 50 | Quat normalize(const Quat &q) 51 | { 52 | float il = 1.0f / (q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 53 | return {q.x * il, q.y * il, q.z * il, q.w * il}; 54 | } 55 | 56 | Quat slerp(const Quat &q0, const Quat &q1, float t) 57 | { 58 | float k0, k1, cosomega = q0.x * q1.x + q0.y * q1.y + q0.z * q1.z + q0.w * q1.w; 59 | Quat q; 60 | if (cosomega < 0.0f) { 61 | cosomega = -cosomega; 62 | q.x = -q1.x; 63 | q.y = -q1.y; 64 | q.z = -q1.z; 65 | q.w = -q1.w; 66 | } else { 67 | q.x = q1.x; 68 | q.y = q1.y; 69 | q.z = q1.z; 70 | q.w = q1.w; 71 | } 72 | if (1.0f - cosomega > MATH_EPSILON) { 73 | float omega = acosf(cosomega); 74 | float sinomega = sinf(omega); 75 | k0 = sinf((1.0f - t) * omega) / sinomega; 76 | k1 = sinf(t * omega) / sinomega; 77 | } else { 78 | k0 = 1.0f - t; 79 | k1 = t; 80 | } 81 | 82 | return { 83 | q0.x * k0 + q.x * k1, 84 | q0.y * k0 + q.y * k1, 85 | q0.z * k0 + q.z * k1, 86 | q0.w * k0 + q.w * k1 87 | }; 88 | } 89 | 90 | Quat to_quat(const Mat4 &m) 91 | { 92 | Quat q; 93 | float trace = m[0] + m[5] + m[10]; 94 | if (trace > 0.0f) { 95 | float s = sqrtf(trace + 1.0f); 96 | q[3] = 0.5f * s; 97 | s = 0.5f / s; 98 | q[0] = (m[6] - m[9]) * s; 99 | q[1] = (m[8] - m[2]) * s; 100 | q[2] = (m[1] - m[4]) * s; 101 | } else { 102 | static const int next[3] = { 1, 2, 0 }; 103 | int i = 0; 104 | if (m[5] > m[0]) i = 1; 105 | if (m[10] > m[4 * i + i]) i = 2; 106 | int j = next[i]; 107 | int k = next[j]; 108 | float s = sqrtf(m[4 * i + i] - m[4 * j + j] - m[4 * k + k] + 1.0f); 109 | q[i] = 0.5f * s; 110 | if (s != 0) s = 0.5f / s; 111 | q[3] = (m[4 * j + k] - m[4 * k + j]) * s; 112 | q[j] = (m[4 * i + j] + m[4 * j + i]) * s; 113 | q[k] = (m[4 * i + k] + m[4 * k + i]) * s; 114 | } 115 | return q; 116 | } 117 | 118 | Mat3 to_mat3(const Quat &q) 119 | { 120 | Mat3 r; 121 | const float x2 = q.x + q.x; 122 | const float y2 = q.y + q.y; 123 | const float z2 = q.z + q.z; 124 | const float xx = q.x * x2; 125 | const float yy = q.y * y2; 126 | const float zz = q.z * z2; 127 | const float xy = q.x * y2; 128 | const float yz = q.y * z2; 129 | const float xz = q.z * x2; 130 | const float wx = q.w * x2; 131 | const float wy = q.w * y2; 132 | const float wz = q.w * z2; 133 | r[0] = 1.0f - (yy + zz); r[3] = xy - wz; r[6] = xz + wy; 134 | r[1] = xy + wz; r[4] = 1.0f - (xx + zz); r[7] = yz - wx; 135 | r[2] = xz - wy; r[5] = yz + wx; r[8] = 1.0f - (xx + yy); 136 | return r; 137 | } 138 | 139 | Mat4 to_mat4(const Quat &q) 140 | { 141 | return to_mat4(to_mat3(q)); 142 | } 143 | 144 | Quat Quat_LookAt(const Vec3f &v) 145 | { 146 | const Vec3f unit = -Vec3f_Z(); 147 | const Vec3f around_y = normalize(Vec3f(v.x, 0, v.z)); 148 | const Quat xq(unit, around_y); 149 | const Quat yq(around_y, v); 150 | return yq * xq; 151 | } 152 | -------------------------------------------------------------------------------- /Math/Quat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/Vec.h" 4 | #include "Math/Mat.h" 5 | 6 | //------------------------------------------------------------------------------ 7 | // Quat 8 | //------------------------------------------------------------------------------ 9 | 10 | struct Quat { 11 | union { 12 | struct { 13 | float x, y, z, w; 14 | }; 15 | float data[4]; 16 | }; 17 | 18 | Quat() = default; 19 | Quat(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {} 20 | 21 | // dir should be normalized, angle is in degrees 22 | Quat(const Vec3f &dir, float angle); 23 | 24 | // both u and v should be normalized 25 | Quat(const Vec3f &u, const Vec3f &v); 26 | 27 | // rotates the vector 'v' by quaternion 28 | Vec3f rotate(const Vec3f &v) const; 29 | 30 | float &operator[](int i) { return data[i]; } 31 | float operator[](int i) const { return data[i]; } 32 | }; 33 | 34 | static inline bool operator==(const Quat &l, const Quat &r) 35 | { 36 | return l.x == r.x && l.y == r.y && l.z == r.z && l.w == r.w; 37 | } 38 | 39 | static inline bool operator!=(const Quat &l, const Quat &r) 40 | { 41 | return l.x != r.x || l.y != r.y || l.z != r.z || l.w != r.w; 42 | } 43 | 44 | // Multiplying l with r applies the rotation r to l 45 | static inline Quat operator*(const Quat &l, const Quat &r) 46 | { 47 | return { 48 | l.w * r.x + l.x * r.w + l.y * r.z - l.z * r.y, 49 | l.w * r.y + l.y * r.w + l.z * r.x - l.x * r.z, 50 | l.w * r.z + l.z * r.w + l.x * r.y - l.y * r.x, 51 | l.w * r.w - l.x * r.x - l.y * r.y - l.z * r.z 52 | }; 53 | } 54 | 55 | Quat normalize(const Quat &q); 56 | Quat slerp(const Quat &q0, const Quat &q1, float t); 57 | 58 | Quat to_quat(const Mat4 &m); 59 | Mat3 to_mat3(const Quat &q); 60 | Mat4 to_mat4(const Quat &q); 61 | 62 | static inline Quat inverse(const Quat &q) { return {-q.x, -q.y, -q.z, q.w}; } 63 | 64 | static inline Quat Quat_Identity() { return {0, 0, 0, 1}; } 65 | Quat Quat_LookAt(const Vec3f &dir); 66 | -------------------------------------------------------------------------------- /Math/Rect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/Vec.h" 4 | 5 | struct Rect { 6 | Vec2i min, max; 7 | 8 | Rect() = default; 9 | Rect(const Vec2i &min, const Vec2i &max): min(min), max(max) {} 10 | Rect(int x0, int y0, int x1, int y1): min(x0, y0), max(x1, y1) {} 11 | 12 | int width() const { return max.x - min.x + 1; } 13 | int height() const { return max.y - min.y + 1; } 14 | Vec2i size() const { return Vec2i(width(), height()); } 15 | 16 | int top() const { return min.y; } 17 | int bottom() const { return max.y; } 18 | int left() const { return min.x; } 19 | int right() const { return max.x; } 20 | 21 | Vec2i top_left() const { return Vec2i(min.x, min.y); } 22 | Vec2i top_right() const { return Vec2i(max.x, min.y); } 23 | Vec2i bottom_left() const { return Vec2i(min.x, max.y); } 24 | Vec2i bottom_right() const { return Vec2i(max.x, max.y); } 25 | 26 | void set_top(int v) { min.y = v; } 27 | void set_bottom(int v) { max.y = v; } 28 | void set_left(int v) { min.x = v; } 29 | void set_right(int v) { max.x = v; } 30 | 31 | void set_top_left(const Vec2i &v) { min.x = v.x; min.y = v.y; } 32 | void set_top_right(const Vec2i &v) { max.x = v.x; min.y = v.y; } 33 | void set_bottom_left(const Vec2i &v) { min.x = v.x; max.y = v.y; } 34 | void set_bottom_right(const Vec2i &v) { max.x = v.x; max.y = v.y; } 35 | 36 | bool valid() const { return min <= max; } 37 | }; 38 | 39 | static inline bool operator==(const Rect &l, const Rect &r) { return l.min == r.min && l.max == r.max; } 40 | static inline bool operator!=(const Rect &l, const Rect &r) { return l.min != r.min || l.max != r.max; } 41 | 42 | static inline Rect Rect_WH(const Vec2i &p, const Vec2i &size) { return Rect(p, p+size-Vec2i(1)); } 43 | static inline Rect Rect_WH(int x, int y, int w, int h) { return Rect_WH(Vec2i(x, y), Vec2i(w, h)); } 44 | static inline Rect Rect_Intersection(const Rect &r1, const Rect &r2) { return Rect(max(r1.min, r2.min), min(r1.max, r2.max)); } 45 | static inline Rect Rect_Valid(const Rect &r) 46 | { 47 | if (!r.valid()) 48 | return Rect(r.min, r.min); 49 | return r; 50 | } 51 | 52 | static inline bool contains(const Rect &r, const Vec2i &p) { return r.min <= p && p <= r.max; } 53 | static inline bool intersects(const Rect &r1, const Rect &r2) 54 | { 55 | return !( 56 | r1.max.x < r2.min.x || 57 | r1.max.y < r2.min.y || 58 | r1.min.x > r2.max.x || 59 | r1.min.y > r2.max.y 60 | ); 61 | } 62 | static inline bool contains(const Rect &r1, const Rect &r2) 63 | { 64 | return Rect_Intersection(r1, r2) == r2; 65 | } 66 | 67 | #define RECT(r) (r).min.x, (r).min.y, (r).max.x, (r).max.y 68 | -------------------------------------------------------------------------------- /Math/Sphere.cpp: -------------------------------------------------------------------------------- 1 | #include "Math/Sphere.h" 2 | 3 | Sphere transform(const Sphere &in, const Transform &tr) 4 | { 5 | Sphere out = in; 6 | out.center = transform(in.center, tr); 7 | return out; 8 | } 9 | -------------------------------------------------------------------------------- /Math/Sphere.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/Vec.h" 4 | #include "Math/Transform.h" 5 | 6 | struct Sphere { 7 | Vec3f center; 8 | float radius; 9 | 10 | Sphere() = default; 11 | Sphere(const Vec3f ¢er, float radius): center(center), radius(radius) {} 12 | 13 | float diameter() const { return 2 * radius; } 14 | }; 15 | 16 | Sphere transform(const Sphere &in, const Transform &tr); 17 | -------------------------------------------------------------------------------- /Math/Transform.cpp: -------------------------------------------------------------------------------- 1 | #include "Math/Transform.h" 2 | 3 | Mat4 to_mat4(const Transform &tf) 4 | { 5 | return to_mat4(tf.orientation) * Mat4_Translate(tf.translation); 6 | } 7 | 8 | Transform inverse(const Transform &tf) 9 | { 10 | return {-tf.translation, inverse(tf.orientation)}; 11 | } 12 | 13 | Vec3f transform(const Vec3f &in, const Transform &tr) 14 | { 15 | return tr.translation + tr.orientation.rotate(in); 16 | } 17 | -------------------------------------------------------------------------------- /Math/Transform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Math/Vec.h" 4 | #include "Math/Quat.h" 5 | 6 | struct Transform { 7 | Vec3f translation = Vec3f(0); 8 | Quat orientation = Quat_Identity(); 9 | 10 | Transform() = default; 11 | Transform(const Vec3f &translation, const Quat &orientation): 12 | translation(translation), orientation(orientation) 13 | { 14 | } 15 | 16 | explicit Transform(const Quat &orientation): orientation(orientation) {} 17 | explicit Transform(const Vec3f &translation): translation(translation) {} 18 | }; 19 | 20 | Transform inverse(const Transform &tf); 21 | Mat4 to_mat4(const Transform &tf); 22 | 23 | Vec3f transform(const Vec3f &in, const Transform &tr); 24 | -------------------------------------------------------------------------------- /Math/Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------------ 4 | // Utility functions 5 | //------------------------------------------------------------------------------ 6 | 7 | template 8 | static inline T lerp(const T &a, const T &b, float v) 9 | { 10 | return a * (1 - v) + b * v; 11 | } 12 | 13 | template 14 | static inline T clamp(const T &value, const T &min, const T &max) 15 | { 16 | if (value > max) 17 | return max; 18 | if (value < min) 19 | return min; 20 | return value; 21 | } 22 | 23 | template 24 | static inline const T &max(const T &v1, const T &v2) 25 | { 26 | return (v1 > v2) ? v1 : v2; 27 | } 28 | 29 | // returns 0 if v1 > v2 or 1 otherwise 30 | template 31 | static inline int max_i(const T &v1, const T &v2) 32 | { 33 | return (v1 > v2) ? 0 : 1; 34 | } 35 | 36 | template 37 | static inline const T &min(const T &v1, const T &v2) 38 | { 39 | return (v1 < v2) ? v1 : v2; 40 | } 41 | 42 | // returns 0 if v1 < v2 or 1 otherwise 43 | template 44 | static inline int min_i(const T &v1, const T &v2) 45 | { 46 | return (v1 < v2) ? 0 : 1; 47 | } 48 | 49 | template 50 | static inline const T &min3(const T &v1, const T &v2, const T &v3) 51 | { 52 | return min(v1, min(v2, v3)); 53 | } 54 | 55 | template 56 | static inline const T &max3(const T &v1, const T &v2, const T &v3) 57 | { 58 | return max(v1, max(v2, v3)); 59 | } 60 | 61 | template 62 | static inline int min3_i(const T &v1, const T &v2, const T &v3) 63 | { 64 | const T *vs[] = {&v1, &v2, &v3}; 65 | int min = 0; 66 | for (int i = 1; i < 3; i++) { 67 | if (*vs[i] < *vs[min]) 68 | min = i; 69 | } 70 | return min; 71 | } 72 | 73 | template 74 | static inline int max3_i(const T &v1, const T &v2, const T &v3) 75 | { 76 | const T *vs[] = {&v1, &v2, &v3}; 77 | int max = 0; 78 | for (int i = 1; i < 3; i++) { 79 | if (*vs[i] > *vs[max]) 80 | max = i; 81 | } 82 | return max; 83 | } 84 | 85 | static inline int next_power_of_2(int v) 86 | { 87 | v -= 1; 88 | v |= v >> 1; 89 | v |= v >> 2; 90 | v |= v >> 4; 91 | v |= v >> 8; 92 | v |= v >> 16; 93 | return v + 1; 94 | } 95 | 96 | static inline int floor_div(int a, int b) 97 | { 98 | int q = a / b; 99 | int r = a % b; 100 | if (r != 0 && ((r < 0) != (b < 0))) q--; 101 | return q; 102 | } 103 | 104 | //------------------------------------------------------------------------------ 105 | // Constants 106 | //------------------------------------------------------------------------------ 107 | 108 | const float MATH_PI = 3.14159265359f; 109 | const float MATH_2PI = MATH_PI * 2.0f; 110 | const float MATH_HALF_PI = MATH_PI / 2.0f; 111 | const float MATH_DEG_TO_RAD = MATH_PI / 180.0f; 112 | const float MATH_RAD_TO_DEG = 180.0f / MATH_PI; 113 | const float MATH_EPSILON = 1e-6f; 114 | -------------------------------------------------------------------------------- /Math/Vec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Math/Utils.h" 7 | 8 | //------------------------------------------------------------------------------ 9 | // Vec2 10 | //------------------------------------------------------------------------------ 11 | 12 | 13 | #define _DEFINE_VEC2_NO_FUNCTIONS(type, Vec2) 14 | #define _DEFINE_VEC2_NO_MEMBERS(type, Vec2) 15 | 16 | 17 | #define _DEFINE_VEC2_INT_MEMBERS(type, Vec2) \ 18 | Vec2 &operator|=(const Vec2 &r) { x|=r.x; y|=r.y; return *this; } \ 19 | Vec2 &operator&=(const Vec2 &r) { x&=r.x; y&=r.y; return *this; } \ 20 | Vec2 &operator^=(const Vec2 &r) { x^=r.x; y^=r.y; return *this; } \ 21 | Vec2 &operator%=(const Vec2 &r) { x%=r.x; y%=r.y; return *this; } \ 22 | 23 | 24 | #define _DEFINE_VEC2_INT_FUNCTIONS(type, Vec2) \ 25 | static inline Vec2 floor_div(const Vec2 &a, const Vec2 &b) { return Vec2(floor_div(a.x, b.x), floor_div(a.y, b.y)); } \ 26 | static inline Vec2 operator&(const Vec2 &l, const Vec2 &r) { return Vec2(l.x & r.x, l.y & r.y); } \ 27 | static inline Vec2 operator|(const Vec2 &l, const Vec2 &r) { return Vec2(l.x | r.x, l.y | r.y); } \ 28 | static inline Vec2 operator^(const Vec2 &l, const Vec2 &r) { return Vec2(l.x ^ r.x, l.y ^ r.y); } \ 29 | static inline Vec2 operator%(const Vec2 &l, const Vec2 &r) { return Vec2(l.x % r.x, l.y % r.y); } \ 30 | 31 | 32 | #define _DEFINE_VEC2_FLOAT_FUNCTIONS(type, Vec2) \ 33 | static inline type length(const Vec2 &v) { return std::sqrt(length2(v)); } \ 34 | static inline Vec2 normalize(const Vec2 &v) { return v / Vec2(length(v)); } \ 35 | static inline type distance(const Vec2 &v1, const Vec2 &v2) { return length(v2-v1); } \ 36 | 37 | 38 | #define _DEFINE_VEC2(type, Vec2, ADDITIONAL_MEMBERS, ADDITIONAL_FUNCTIONS) \ 39 | struct Vec2 { \ 40 | union { \ 41 | struct { \ 42 | type x, y; \ 43 | }; \ 44 | type data[2]; \ 45 | }; \ 46 | \ 47 | Vec2() = default; \ 48 | Vec2(type ax, type ay): x(ax), y(ay) {} \ 49 | explicit Vec2(type v): x(v), y(v) {} \ 50 | \ 51 | Vec2 &operator+=(const Vec2 &r) { x+=r.x; y+=r.y; return *this; } \ 52 | Vec2 &operator-=(const Vec2 &r) { x-=r.x; y-=r.y; return *this; } \ 53 | Vec2 &operator*=(const Vec2 &r) { x*=r.x; y*=r.y; return *this; } \ 54 | Vec2 &operator/=(const Vec2 &r) { x/=r.x; y/=r.y; return *this; } \ 55 | ADDITIONAL_MEMBERS(type, Vec2) \ 56 | \ 57 | type &operator[](int i) { return data[i]; } \ 58 | type operator[](int i) const { return data[i]; } \ 59 | }; \ 60 | \ 61 | static inline Vec2 Vec2##_X(type v = 1) { return {v, 0}; } \ 62 | static inline Vec2 Vec2##_Y(type v = 1) { return {0, v}; } \ 63 | \ 64 | static inline bool operator==(const Vec2 &l, const Vec2 &r) { return l.x == r.x && l.y == r.y; } \ 65 | static inline bool operator!=(const Vec2 &l, const Vec2 &r) { return l.x != r.x || l.y != r.y; } \ 66 | static inline bool operator<(const Vec2 &l, const Vec2 &r) { return l.x < r.x && l.y < r.y; } \ 67 | static inline bool operator>(const Vec2 &l, const Vec2 &r) { return l.x > r.x && l.y > r.y; } \ 68 | static inline bool operator<=(const Vec2 &l, const Vec2 &r) { return l.x <= r.x && l.y <= r.y; } \ 69 | static inline bool operator>=(const Vec2 &l, const Vec2 &r) { return l.x >= r.x && l.y >= r.y; } \ 70 | \ 71 | static inline Vec2 operator-(const Vec2 &v) { return Vec2(-v.x, -v.y); } \ 72 | static inline Vec2 operator+(const Vec2 &l, const Vec2 &r) { return Vec2(l.x + r.x, l.y + r.y); } \ 73 | static inline Vec2 operator-(const Vec2 &l, const Vec2 &r) { return Vec2(l.x - r.x, l.y - r.y); } \ 74 | static inline Vec2 operator*(const Vec2 &l, const Vec2 &r) { return Vec2(l.x * r.x, l.y * r.y); } \ 75 | static inline Vec2 operator/(const Vec2 &l, const Vec2 &r) { return Vec2(l.x / r.x, l.y / r.y); } \ 76 | \ 77 | static inline type area(const Vec2 &v) { return v.x * v.y; } \ 78 | static inline type length2(const Vec2 &v) { return v.x*v.x + v.y*v.y; } \ 79 | static inline type dot(const Vec2 &v1, const Vec2 &v2) { return v1.x*v2.x + v1.y*v2.y; } \ 80 | static inline type distance2(const Vec2 &v1, const Vec2 &v2) { return length2(v2-v1); } \ 81 | static inline Vec2 min(const Vec2 &v1, const Vec2 &v2) { return {min(v1.x, v2.x), min(v1.y, v2.y)}; } \ 82 | static inline Vec2 max(const Vec2 &v1, const Vec2 &v2) { return {max(v1.x, v2.x), max(v1.y, v2.y)}; } \ 83 | ADDITIONAL_FUNCTIONS(type, Vec2) \ 84 | 85 | 86 | _DEFINE_VEC2(float, Vec2f, _DEFINE_VEC2_NO_MEMBERS, _DEFINE_VEC2_FLOAT_FUNCTIONS) 87 | _DEFINE_VEC2(double, Vec2d, _DEFINE_VEC2_NO_MEMBERS, _DEFINE_VEC2_FLOAT_FUNCTIONS) 88 | _DEFINE_VEC2(int32_t, Vec2i, _DEFINE_VEC2_INT_MEMBERS, _DEFINE_VEC2_INT_FUNCTIONS) 89 | _DEFINE_VEC2(int16_t, Vec2s, _DEFINE_VEC2_INT_MEMBERS, _DEFINE_VEC2_INT_FUNCTIONS) 90 | _DEFINE_VEC2(int8_t, Vec2b, _DEFINE_VEC2_INT_MEMBERS, _DEFINE_VEC2_INT_FUNCTIONS) 91 | 92 | _DEFINE_VEC2(uint16_t, Vec2us, _DEFINE_VEC2_INT_MEMBERS, _DEFINE_VEC2_INT_FUNCTIONS) 93 | 94 | static inline Vec2f ToVec2f(const Vec2i &v) { return Vec2f(v.x, v.y); } 95 | static inline Vec2i ToVec2i(const Vec2f &v) { return Vec2i(v.x, v.y); } 96 | 97 | //------------------------------------------------------------------------------ 98 | // Vec3 99 | //------------------------------------------------------------------------------ 100 | 101 | #define _DEFINE_VEC3_NO_FUNCTIONS(type, Vec3) 102 | #define _DEFINE_VEC3_NO_MEMBERS(type, Vec3) 103 | 104 | 105 | #define _DEFINE_VEC3_INT_MEMBERS(type, Vec3) \ 106 | Vec3 &operator&=(const Vec3 &r) { x&=r.x; y&=r.y; z&=r.z; return *this; } \ 107 | Vec3 &operator|=(const Vec3 &r) { x|=r.x; y|=r.y; z|=r.z; return *this; } \ 108 | Vec3 &operator^=(const Vec3 &r) { x^=r.x; y^=r.y; z^=r.z; return *this; } \ 109 | Vec3 &operator%=(const Vec3 &r) { x%=r.x; y%=r.y; z%=r.z; return *this; } \ 110 | 111 | 112 | #define _DEFINE_VEC3_INT_FUNCTIONS(type, Vec3) \ 113 | static inline Vec3 floor_div(const Vec3 &a, const Vec3 &b) { return Vec3(floor_div(a.x, b.x), floor_div(a.y, b.y), floor_div(a.z, b.z)); } \ 114 | static inline Vec3 operator^(const Vec3 &l, const Vec3 &r) { return Vec3(l.x ^ r.x, l.y ^ r.y, l.z ^ r.z); } \ 115 | static inline Vec3 operator%(const Vec3 &l, const Vec3 &r) { return Vec3(l.x % r.x, l.y % r.y, l.z % r.z); } \ 116 | static inline Vec3 operator&(const Vec3 &l, const Vec3 &r) { return Vec3(l.x & r.x, l.y & r.y, l.z & r.z); } \ 117 | static inline Vec3 operator|(const Vec3 &l, const Vec3 &r) { return Vec3(l.x | r.x, l.y | r.y, l.z | r.z); } \ 118 | static inline Vec3 operator~(const Vec3 &v) { return Vec3(~v.x, ~v.y, ~v.z); } \ 119 | 120 | 121 | #define _DEFINE_VEC3_FLOAT_FUNCTIONS(type, Vec3) \ 122 | static inline Vec3 abs(const Vec3 &v) { return Vec3(std::abs(v.x), std::abs(v.y), std::abs(v.z)); } \ 123 | static inline type length(const Vec3 &v) { return std::sqrt(length2(v)); } \ 124 | static inline Vec3 normalize(const Vec3 &v) { return v / Vec3(length(v)); } \ 125 | static inline bool is_nan(const Vec3 &v) { return std::isnan(v.x) || std::isnan(v.y) || std::isnan(v.z); } \ 126 | static inline type distance(const Vec3 &v1, const Vec3 &v2) { return length(v2-v1); } \ 127 | static inline Vec3 lerp(const Vec3 &a, const Vec3 &b, float v) { return a * Vec3(1 - v) + b * Vec3(v); } \ 128 | static inline Vec3 mod(const Vec3 &a, const Vec3 &b) { return Vec3(std::fmod(a.x, b.x), std::fmod(a.y, b.y), std::fmod(a.z, b.z)); } \ 129 | static inline Vec3 pow(const Vec3 &v1, const Vec3 &v2) { return Vec3(std::pow(v1.x, v2.x), std::pow(v1.y, v2.y), std::pow(v1.z, v2.z)); } \ 130 | 131 | 132 | #define _DEFINE_VEC3(type, Vec3, Vec2, ADDITIONAL_MEMBERS, ADDITIONAL_FUNCTIONS) \ 133 | struct Vec3 { \ 134 | union { \ 135 | struct { \ 136 | type x, y, z; \ 137 | }; \ 138 | type data[3]; \ 139 | }; \ 140 | \ 141 | Vec3() = default; \ 142 | Vec3(type ax, type ay, type az): x(ax), y(ay), z(az) {} \ 143 | explicit Vec3(type v): x(v), y(v), z(v) {} \ 144 | \ 145 | Vec3 &operator+=(const Vec3 &r) { x+=r.x; y+=r.y; z+=r.z; return *this; } \ 146 | Vec3 &operator-=(const Vec3 &r) { x-=r.x; y-=r.y; z-=r.z; return *this; } \ 147 | Vec3 &operator*=(const Vec3 &r) { x*=r.x; y*=r.y; z*=r.z; return *this; } \ 148 | Vec3 &operator/=(const Vec3 &r) { x/=r.x; y/=r.y; z/=r.z; return *this; } \ 149 | ADDITIONAL_MEMBERS(type, Vec3) \ 150 | \ 151 | type &operator[](int i) { return data[i]; } \ 152 | type operator[](int i) const { return data[i]; } \ 153 | \ 154 | Vec2 XY() const { return {x, y}; } \ 155 | Vec2 XZ() const { return {x, z}; } \ 156 | Vec2 YZ() const { return {y, z}; } \ 157 | }; \ 158 | \ 159 | static inline Vec3 Vec3##_X(type v = 1) { return {v, 0, 0}; } \ 160 | static inline Vec3 Vec3##_Y(type v = 1) { return {0, v, 0}; } \ 161 | static inline Vec3 Vec3##_Z(type v = 1) { return {0, 0, v}; } \ 162 | static inline Vec3 Vec3##_XY(const Vec2 &v) { return {v.x, v.y, 0}; } \ 163 | static inline Vec3 Vec3##_XZ(const Vec2 &v) { return {v.x, 0, v.y}; } \ 164 | static inline Vec3 Vec3##_YZ(const Vec2 &v) { return {0, v.x, v.y}; } \ 165 | \ 166 | static inline bool operator==(const Vec3 &l, const Vec3 &r) { return l.x == r.x && l.y == r.y && l.z == r.z; } \ 167 | static inline bool operator!=(const Vec3 &l, const Vec3 &r) { return l.x != r.x || l.y != r.y || l.z != r.z; } \ 168 | static inline bool operator<(const Vec3 &l, const Vec3 &r) { return l.x < r.x && l.y < r.y && l.z < r.z; } \ 169 | static inline bool operator>(const Vec3 &l, const Vec3 &r) { return l.x > r.x && l.y > r.y && l.z > r.z; } \ 170 | static inline bool operator<=(const Vec3 &l, const Vec3 &r) { return l.x <= r.x && l.y <= r.y && l.z <= r.z; } \ 171 | static inline bool operator>=(const Vec3 &l, const Vec3 &r) { return l.x >= r.x && l.y >= r.y && l.z >= r.z; } \ 172 | static inline Vec3 operator+(const Vec3 &l, const Vec3 &r) { return Vec3(l.x + r.x, l.y + r.y, l.z + r.z); } \ 173 | static inline Vec3 operator-(const Vec3 &l, const Vec3 &r) { return Vec3(l.x - r.x, l.y - r.y, l.z - r.z); } \ 174 | static inline Vec3 operator*(const Vec3 &l, const Vec3 &r) { return Vec3(l.x * r.x, l.y * r.y, l.z * r.z); } \ 175 | static inline Vec3 operator/(const Vec3 &l, const Vec3 &r) { return Vec3(l.x / r.x, l.y / r.y, l.z / r.z); } \ 176 | static inline Vec3 operator-(const Vec3 &v) { return Vec3(-v.x, -v.y, -v.z); } \ 177 | \ 178 | static inline type length2(const Vec3 &v) { return v.x*v.x + v.y*v.y + v.z*v.z; } \ 179 | static inline type dot(const Vec3 &v1, const Vec3 &v2) { return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; } \ 180 | static inline type volume(const Vec3 &v) { return v.x * v.y * v.z; } \ 181 | static inline Vec3 cross(const Vec3 &v1, const Vec3 &v2) { return Vec3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } \ 182 | static inline type distance2(const Vec3 &v1, const Vec3 &v2) { return length2(v2-v1); } \ 183 | static inline Vec3 min(const Vec3 &v1, const Vec3 &v2) { return {min(v1.x, v2.x), min(v1.y, v2.y), min(v1.z, v2.z)}; } \ 184 | static inline Vec3 max(const Vec3 &v1, const Vec3 &v2) { return {max(v1.x, v2.x), max(v1.y, v2.y), max(v1.z, v2.z)}; } \ 185 | ADDITIONAL_FUNCTIONS(type, Vec3) \ 186 | 187 | 188 | _DEFINE_VEC3(float, Vec3f, Vec2f, _DEFINE_VEC3_NO_MEMBERS, _DEFINE_VEC3_FLOAT_FUNCTIONS) 189 | _DEFINE_VEC3(double, Vec3d, Vec2d, _DEFINE_VEC3_NO_MEMBERS, _DEFINE_VEC3_FLOAT_FUNCTIONS) 190 | _DEFINE_VEC3(int32_t, Vec3i, Vec2i, _DEFINE_VEC3_INT_MEMBERS, _DEFINE_VEC3_INT_FUNCTIONS) 191 | _DEFINE_VEC3(int16_t, Vec3s, Vec2s, _DEFINE_VEC3_INT_MEMBERS, _DEFINE_VEC3_INT_FUNCTIONS) 192 | _DEFINE_VEC3(int8_t, Vec3b, Vec2b, _DEFINE_VEC3_INT_MEMBERS, _DEFINE_VEC3_INT_FUNCTIONS) 193 | 194 | _DEFINE_VEC3(uint16_t, Vec3us, Vec2us, _DEFINE_VEC3_INT_MEMBERS, _DEFINE_VEC3_INT_FUNCTIONS) 195 | 196 | 197 | static inline Vec3f ToVec3f(const Vec3i &v) { return Vec3f(v.x, v.y, v.z); } 198 | static inline Vec3f ToVec3f(const Vec3d &v) { return Vec3f(v.x, v.y, v.z); } 199 | static inline Vec3d ToVec3d(const Vec3i &v) { return Vec3d(v.x, v.y, v.z); } 200 | static inline Vec3d ToVec3d(const Vec3f &v) { return Vec3d(v.x, v.y, v.z); } 201 | static inline Vec3i ToVec3i(const Vec3f &v) { return Vec3i(v.x, v.y, v.z); } 202 | static inline Vec3i ToVec3i(const Vec3d &v) { return Vec3i(v.x, v.y, v.z); } 203 | 204 | static inline Vec3i floor(const Vec3f &v) { return Vec3i(std::floor(v.x), std::floor(v.y), std::floor(v.z)); } 205 | static inline Vec3i floor(const Vec3d &v) { return Vec3i(std::floor(v.x), std::floor(v.y), std::floor(v.z)); } 206 | 207 | static inline bool axes_equal(const Vec3i &a, const Vec3i &b, const Vec2i &axes) 208 | { 209 | return a[axes[0]] == b[axes[0]] && a[axes[1]] == b[axes[1]]; 210 | } 211 | 212 | static inline bool aabb_aabb_intersection(const Vec3i &amin, const Vec3i &amax, 213 | const Vec3i &bmin, const Vec3i &bmax) 214 | { 215 | return !( 216 | amax.x < bmin.x || 217 | amax.y < bmin.y || 218 | amax.z < bmin.z || 219 | amin.x > bmax.x || 220 | amin.y > bmax.y || 221 | amin.z > bmax.z 222 | ); 223 | } 224 | 225 | //------------------------------------------------------------------------------ 226 | // Vec4 227 | //------------------------------------------------------------------------------ 228 | 229 | struct Vec4f { 230 | union { 231 | struct { 232 | float x, y, z, w; 233 | }; 234 | float data[4]; 235 | }; 236 | 237 | Vec4f() = default; 238 | Vec4f(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {} 239 | explicit Vec4f(float v): x(v), y(v), z(v), w(v) {} 240 | 241 | Vec4f &operator+=(const Vec4f &r) { x+=r.x; y+=r.y; z+=r.z; w+=r.w; return *this; } 242 | Vec4f &operator-=(const Vec4f &r) { x-=r.x; y-=r.y; z-=r.z; w-=r.w; return *this; } 243 | Vec4f &operator*=(const Vec4f &r) { x*=r.x; y*=r.y; z*=r.z; w*=r.w; return *this; } 244 | Vec4f &operator/=(const Vec4f &r) { x/=r.x; y/=r.y; z/=r.z; w/=r.w; return *this; } 245 | 246 | float &operator[](int i) { return data[i]; } 247 | float operator[](int i) const { return data[i]; } 248 | }; 249 | 250 | static inline Vec4f operator+(const Vec4f &l, const Vec4f &r) { return {l.x + r.x, l.y + r.y, l.z + r.z, l.w + r.w}; } 251 | static inline Vec4f operator-(const Vec4f &l, const Vec4f &r) { return {l.x - r.x, l.y - r.y, l.z - r.z, l.w - r.w}; } 252 | static inline Vec4f operator*(const Vec4f &l, const Vec4f &r) { return {l.x * r.x, l.y * r.y, l.z * r.z, l.w * r.w}; } 253 | static inline Vec4f operator/(const Vec4f &l, const Vec4f &r) { return {l.x / r.x, l.y / r.y, l.z / r.z, l.w / r.w}; } 254 | 255 | static inline float dot(const Vec4f &v1, const Vec4f &v2) { return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w; } 256 | 257 | static inline Vec3f ToVec3(const Vec4f &v) { return Vec3f(v.x, v.y, v.z); } 258 | static inline Vec4f ToVec4(const Vec3f &v) { return Vec4f(v.x, v.y, v.z, 1); } 259 | 260 | //------------------------------------------------------------------------------ 261 | // Vec4i 262 | //------------------------------------------------------------------------------ 263 | 264 | struct Vec4i { 265 | union { 266 | struct { 267 | int x, y, z, w; 268 | }; 269 | int data[4]; 270 | }; 271 | 272 | Vec4i() = default; 273 | Vec4i(int x, int y, int z, int w): x(x), y(y), z(z), w(w) {} 274 | explicit Vec4i(int v): x(v), y(v), z(v), w(v) {} 275 | 276 | Vec4i &operator+=(const Vec4i &r) { x+=r.x; y+=r.y; z+=r.z; w+=r.w; return *this; } 277 | Vec4i &operator-=(const Vec4i &r) { x-=r.x; y-=r.y; z-=r.z; w-=r.w; return *this; } 278 | Vec4i &operator*=(const Vec4i &r) { x*=r.x; y*=r.y; z*=r.z; w*=r.w; return *this; } 279 | Vec4i &operator/=(const Vec4i &r) { x/=r.x; y/=r.y; z/=r.z; w/=r.w; return *this; } 280 | 281 | int &operator[](int i) { return data[i]; } 282 | int operator[](int i) const { return data[i]; } 283 | }; 284 | 285 | static inline Vec4i operator+(const Vec4i &l, const Vec4i &r) { return {l.x + r.x, l.y + r.y, l.z + r.z, l.w + r.w}; } 286 | static inline Vec4i operator-(const Vec4i &l, const Vec4i &r) { return {l.x - r.x, l.y - r.y, l.z - r.z, l.w - r.w}; } 287 | static inline Vec4i operator*(const Vec4i &l, const Vec4i &r) { return {l.x * r.x, l.y * r.y, l.z * r.z, l.w * r.w}; } 288 | static inline Vec4i operator/(const Vec4i &l, const Vec4i &r) { return {l.x / r.x, l.y / r.y, l.z / r.z, l.w / r.w}; } 289 | 290 | static inline Vec4f ToVec4(const Vec4i &v) { return Vec4f(v.x, v.y, v.z, v.w); } 291 | static inline Vec4i ToVec4i(const Vec4f &v) { return Vec4i(v.x, v.y, v.z, v.w); } 292 | 293 | //------------------------------------------------------------------------------ 294 | // Macro Utils 295 | //------------------------------------------------------------------------------ 296 | 297 | #define VEC2(v) (v).x, (v).y 298 | #define VEC3(v) (v).x, (v).y, (v).z 299 | #define VEC4(v) (v).x, (v).y, (v).z, (v).w 300 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Very simple marching cubes/naive surface nets example. 2 | 3 | Depends on GLUT, GL, GLU and a C++11 compiler. 4 | 5 | Run ./compile.bash, enjoy! 6 | 7 | - LMB and drag mouse to rotate the camera, WASD to move the camera. 8 | - RMB to open a menu with various options: 9 | - Marching Cubes (flat shading) 10 | - Marching Cubes (smooth shading) 11 | - Naive Surface Nets (smooth shading) 12 | - Toggle Wireframe 13 | 14 | 15 | Public domain. -------------------------------------------------------------------------------- /compile.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | case "$OSTYPE" in 4 | darwin*) g++ -std=c++11 -o MC MC.cpp Core/*.cpp Math/*.cpp -I. -framework OpenGL -framework GLUT ;; 5 | *) g++ -std=c++11 -o MC MC.cpp Core/*.cpp Math/*.cpp -I. -lglut -lGL -lGLU ;; 6 | esac 7 | 8 | --------------------------------------------------------------------------------