Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/manifold/src/utils.h
9903 views
1
// Copyright 2020 The Manifold Authors, Jared Hoberock and Nathan Bell of
2
// NVIDIA Research
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License");
5
// you may not use this file except in compliance with the License.
6
// You may obtain a copy of the License at
7
//
8
// http://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing, software
11
// distributed under the License is distributed on an "AS IS" BASIS,
12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
// See the License for the specific language governing permissions and
14
// limitations under the License.
15
16
#pragma once
17
#include <atomic>
18
#include <memory>
19
#include <mutex>
20
21
#include "manifold/common.h"
22
#include "vec.h"
23
24
#ifndef MANIFOLD_PAR
25
#error "MANIFOLD_PAR must be defined to either 1 (parallel) or -1 (series)"
26
#else
27
#if (MANIFOLD_PAR != 1) && (MANIFOLD_PAR != -1)
28
#define XSTR(x) STR(x)
29
#define STR(x) #x
30
#pragma message "Current value of MANIFOLD_PAR is: " XSTR(MANIFOLD_PAR)
31
#error "MANIFOLD_PAR must be defined to either 1 (parallel) or -1 (series)"
32
#endif
33
#endif
34
35
#include "parallel.h"
36
37
#if __has_include(<tracy/Tracy.hpp>)
38
#include <tracy/Tracy.hpp>
39
#else
40
#define FrameMarkStart(x)
41
#define FrameMarkEnd(x)
42
// putting ZoneScoped in a function will instrument the function execution when
43
// TRACY_ENABLE is set, which allows the profiler to record more accurate
44
// timing.
45
#define ZoneScoped
46
#define ZoneScopedN(name)
47
#endif
48
49
namespace manifold {
50
51
/**
52
* Stand-in for C++23's operator""uz (P0330R8)[https://wg21.link/P0330R8].
53
*/
54
[[nodiscard]] constexpr std::size_t operator""_uz(
55
unsigned long long n) noexcept {
56
return n;
57
}
58
59
constexpr double kPrecision = 1e-12;
60
61
inline int Next3(int i) {
62
constexpr ivec3 next3(1, 2, 0);
63
return next3[i];
64
}
65
66
inline int Prev3(int i) {
67
constexpr ivec3 prev3(2, 0, 1);
68
return prev3[i];
69
}
70
71
template <typename T, typename T1>
72
void Permute(Vec<T>& inOut, const Vec<T1>& new2Old) {
73
Vec<T> tmp(std::move(inOut));
74
inOut.resize_nofill(new2Old.size());
75
gather(new2Old.begin(), new2Old.end(), tmp.begin(), inOut.begin());
76
}
77
78
template <typename T, typename T1>
79
void Permute(std::vector<T>& inOut, const Vec<T1>& new2Old) {
80
std::vector<T> tmp(std::move(inOut));
81
inOut.resize(new2Old.size());
82
gather(new2Old.begin(), new2Old.end(), tmp.begin(), inOut.begin());
83
}
84
85
template <typename T>
86
T AtomicAdd(T& target, T add) {
87
std::atomic<T>& tar = reinterpret_cast<std::atomic<T>&>(target);
88
T old_val = tar.load();
89
while (!tar.compare_exchange_weak(old_val, old_val + add,
90
std::memory_order_seq_cst)) {
91
}
92
return old_val;
93
}
94
95
template <>
96
inline int AtomicAdd(int& target, int add) {
97
std::atomic<int>& tar = reinterpret_cast<std::atomic<int>&>(target);
98
int old_val = tar.fetch_add(add, std::memory_order_seq_cst);
99
return old_val;
100
}
101
102
template <typename T>
103
class ConcurrentSharedPtr {
104
public:
105
ConcurrentSharedPtr(T value) : impl(std::make_shared<T>(value)) {}
106
ConcurrentSharedPtr(const ConcurrentSharedPtr<T>& other)
107
: impl(other.impl), mutex(other.mutex) {}
108
ConcurrentSharedPtr& operator=(const ConcurrentSharedPtr<T>& other) {
109
if (this == &other) return *this;
110
impl = other.impl;
111
mutex = other.mutex;
112
return *this;
113
}
114
class SharedPtrGuard {
115
public:
116
SharedPtrGuard(std::recursive_mutex* mutex, T* content)
117
: mutex(mutex), content(content) {
118
mutex->lock();
119
}
120
~SharedPtrGuard() { mutex->unlock(); }
121
122
T& operator*() { return *content; }
123
T* operator->() { return content; }
124
125
private:
126
std::recursive_mutex* mutex;
127
T* content;
128
};
129
SharedPtrGuard GetGuard() { return SharedPtrGuard(mutex.get(), impl.get()); };
130
unsigned int UseCount() { return impl.use_count(); };
131
132
private:
133
std::shared_ptr<T> impl;
134
std::shared_ptr<std::recursive_mutex> mutex =
135
std::make_shared<std::recursive_mutex>();
136
};
137
138
template <typename T>
139
struct Identity {
140
T operator()(T v) const { return v; }
141
};
142
143
template <typename T>
144
struct Negate {
145
T operator()(T v) const { return -v; }
146
};
147
148
/**
149
* Determines if the three points are wound counter-clockwise, clockwise, or
150
* colinear within the specified tolerance.
151
*
152
* @param p0 First point
153
* @param p1 Second point
154
* @param p2 Third point
155
* @param tol Tolerance value for colinearity
156
* @return int, like Signum, this returns 1 for CCW, -1 for CW, and 0 if within
157
* tol of colinear.
158
*/
159
inline int CCW(vec2 p0, vec2 p1, vec2 p2, double tol) {
160
vec2 v1 = p1 - p0;
161
vec2 v2 = p2 - p0;
162
double area = v1.x * v2.y - v1.y * v2.x;
163
double base2 = la::max(la::dot(v1, v1), la::dot(v2, v2));
164
if (area * area * 4 <= base2 * tol * tol)
165
return 0;
166
else
167
return area > 0 ? 1 : -1;
168
}
169
170
inline mat4 Mat4(mat3x4 a) {
171
return mat4({a[0], 0}, {a[1], 0}, {a[2], 0}, {a[3], 1});
172
}
173
inline mat3 Mat3(mat2x3 a) { return mat3({a[0], 0}, {a[1], 0}, {a[2], 1}); }
174
175
// https://stackoverflow.com/questions/664014/what-integer-hash-function-are-good-that-accepts-an-integer-hash-key
176
constexpr uint64_t hash64bit(uint64_t x) {
177
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ull;
178
x = (x ^ (x >> 27)) * 0x94d049bb133111ebull;
179
x = x ^ (x >> 31);
180
return x;
181
}
182
} // namespace manifold
183
184