summaryrefslogtreecommitdiff
path: root/thirdparty/xatlas/xatlas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/xatlas/xatlas.cpp')
-rw-r--r--thirdparty/xatlas/xatlas.cpp2340
1 files changed, 1336 insertions, 1004 deletions
diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp
index f6a9ce64dc..df5ef94dbb 100644
--- a/thirdparty/xatlas/xatlas.cpp
+++ b/thirdparty/xatlas/xatlas.cpp
@@ -1,5 +1,9 @@
// This code is in the public domain -- castanyo@yahoo.es
-#include "xatlas.h"
+#include <algorithm>
+#include <cmath>
+#include <memory>
+#include <unordered_map>
+#include <vector>
#include <assert.h>
#include <float.h>
#include <math.h>
@@ -8,29 +12,19 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
-#include <algorithm>
-#include <cmath>
-#include <memory>
-#include <unordered_map>
-#include <vector>
+#include "xatlas.h"
#undef min
#undef max
#ifndef xaAssert
-#define xaAssert(exp) \
- if (!(exp)) { \
- xaPrint("%s %s %s\n", #exp, __FILE__, __LINE__); \
- }
+#define xaAssert(exp) if (!(exp)) { xaPrint("%s %s %s\n", #exp, __FILE__, __LINE__); }
#endif
#ifndef xaDebugAssert
#define xaDebugAssert(exp) assert(exp)
#endif
#ifndef xaPrint
-#define xaPrint(...) \
- if (xatlas::internal::s_print) { \
- xatlas::internal::s_print(__VA_ARGS__); \
- }
+#define xaPrint(...) if (xatlas::internal::s_print) { xatlas::internal::s_print(__VA_ARGS__); }
#endif
#ifdef _MSC_VER
@@ -43,87 +37,101 @@
#define NV_FORCEINLINE __forceinline
#else
#define restrict __restrict__
-#define NV_FORCEINLINE __attribute__((always_inline)) inline
+#define NV_FORCEINLINE __attribute__((always_inline)) inline
#endif
-#define NV_UINT32_MAX 0xffffffff
-#define NV_FLOAT_MAX 3.402823466e+38F
+#define NV_UINT32_MAX 0xffffffff
+#define NV_FLOAT_MAX 3.402823466e+38F
#ifndef PI
-#define PI float(3.1415926535897932384626433833)
+#define PI float(3.1415926535897932384626433833)
#endif
-#define NV_EPSILON (0.0001f)
-#define NV_NORMAL_EPSILON (0.001f)
+#define NV_EPSILON (0.0001f)
+#define NV_NORMAL_EPSILON (0.001f)
namespace xatlas {
namespace internal {
static PrintFunc s_print = NULL;
-static int align(int x, int a) {
+static int align(int x, int a)
+{
return (x + a - 1) & ~(a - 1);
}
-static bool isAligned(int x, int a) {
+static bool isAligned(int x, int a)
+{
return (x & (a - 1)) == 0;
}
/// Return the maximum of the three arguments.
template <typename T>
-static T max3(const T &a, const T &b, const T &c) {
+static T max3(const T &a, const T &b, const T &c)
+{
return std::max(a, std::max(b, c));
}
/// Return the maximum of the three arguments.
template <typename T>
-static T min3(const T &a, const T &b, const T &c) {
+static T min3(const T &a, const T &b, const T &c)
+{
return std::min(a, std::min(b, c));
}
/// Clamp between two values.
template <typename T>
-static T clamp(const T &x, const T &a, const T &b) {
+static T clamp(const T &x, const T &a, const T &b)
+{
return std::min(std::max(x, a), b);
}
-static float saturate(float f) {
+static float saturate(float f)
+{
return clamp(f, 0.0f, 1.0f);
}
// Robust floating point comparisons:
// http://realtimecollisiondetection.net/blog/?p=89
-static bool equal(const float f0, const float f1, const float epsilon = NV_EPSILON) {
+static bool equal(const float f0, const float f1, const float epsilon = NV_EPSILON)
+{
//return fabs(f0-f1) <= epsilon;
return fabs(f0 - f1) <= epsilon * max3(1.0f, fabsf(f0), fabsf(f1));
}
-NV_FORCEINLINE static int ftoi_floor(float val) {
+NV_FORCEINLINE static int ftoi_floor(float val)
+{
return (int)val;
}
-NV_FORCEINLINE static int ftoi_ceil(float val) {
+NV_FORCEINLINE static int ftoi_ceil(float val)
+{
return (int)ceilf(val);
}
-NV_FORCEINLINE static int ftoi_round(float f) {
+NV_FORCEINLINE static int ftoi_round(float f)
+{
return int(floorf(f + 0.5f));
}
-static bool isZero(const float f, const float epsilon = NV_EPSILON) {
+static bool isZero(const float f, const float epsilon = NV_EPSILON)
+{
return fabs(f) <= epsilon;
}
-static float lerp(float f0, float f1, float t) {
+static float lerp(float f0, float f1, float t)
+{
const float s = 1.0f - t;
return f0 * s + f1 * t;
}
-static float square(float f) {
+static float square(float f)
+{
return f * f;
}
-static int square(int i) {
+static int square(int i)
+{
return i * i;
}
@@ -133,8 +141,9 @@ static int square(int i) {
* @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x
* @note nextPowerOfTwo(x) = 2 << log2(x-1)
*/
-static uint32_t nextPowerOfTwo(uint32_t x) {
- xaDebugAssert(x != 0);
+static uint32_t nextPowerOfTwo(uint32_t x)
+{
+ xaDebugAssert( x != 0 );
// On modern CPUs this is supposed to be as fast as using the bsr instruction.
x--;
x |= x >> 1;
@@ -145,7 +154,8 @@ static uint32_t nextPowerOfTwo(uint32_t x) {
return x + 1;
}
-static uint64_t nextPowerOfTwo(uint64_t x) {
+static uint64_t nextPowerOfTwo(uint64_t x)
+{
xaDebugAssert(x != 0);
uint32_t p = 1;
while (x > p) {
@@ -154,17 +164,19 @@ static uint64_t nextPowerOfTwo(uint64_t x) {
return p;
}
-static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381) {
- const uint8_t *data = (const uint8_t *)data_in;
+static uint32_t sdbmHash(const void *data_in, uint32_t size, uint32_t h = 5381)
+{
+ const uint8_t *data = (const uint8_t *) data_in;
uint32_t i = 0;
while (i < size) {
- h = (h << 16) + (h << 6) - h + (uint32_t)data[i++];
+ h = (h << 16) + (h << 6) - h + (uint32_t ) data[i++];
}
return h;
}
// Note that this hash does not handle NaN properly.
-static uint32_t sdbmFloatHash(const float *f, uint32_t count, uint32_t h = 5381) {
+static uint32_t sdbmFloatHash(const float *f, uint32_t count, uint32_t h = 5381)
+{
for (uint32_t i = 0; i < count; i++) {
union {
float f;
@@ -177,85 +189,93 @@ static uint32_t sdbmFloatHash(const float *f, uint32_t count, uint32_t h = 5381)
}
template <typename T>
-static uint32_t hash(const T &t, uint32_t h = 5381) {
+static uint32_t hash(const T &t, uint32_t h = 5381)
+{
return sdbmHash(&t, sizeof(T), h);
}
-static uint32_t hash(const float &f, uint32_t h) {
+static uint32_t hash(const float &f, uint32_t h)
+{
return sdbmFloatHash(&f, 1, h);
}
// Functors for hash table:
-template <typename Key>
-struct Hash {
+template <typename Key> struct Hash
+{
uint32_t operator()(const Key &k) const { return hash(k); }
};
-template <typename Key>
-struct Equal {
+template <typename Key> struct Equal
+{
bool operator()(const Key &k0, const Key &k1) const { return k0 == k1; }
};
-class Vector2 {
+class Vector2
+{
public:
typedef Vector2 const &Arg;
Vector2() {}
- explicit Vector2(float f) :
- x(f),
- y(f) {}
- Vector2(float x, float y) :
- x(x),
- y(y) {}
- Vector2(Vector2::Arg v) :
- x(v.x),
- y(v.y) {}
-
- const Vector2 &operator=(Vector2::Arg v) {
+ explicit Vector2(float f) : x(f), y(f) {}
+ Vector2(float x, float y): x(x), y(y) {}
+ Vector2(Vector2::Arg v) : x(v.x), y(v.y) {}
+
+ const Vector2 &operator=(Vector2::Arg v)
+ {
x = v.x;
y = v.y;
- return *this;
+ return
+ *this;
}
const float *ptr() const { return &x; }
- void set(float _x, float _y) {
+ void set(float _x, float _y)
+ {
x = _x;
y = _y;
}
- Vector2 operator-() const {
+ Vector2 operator-() const
+ {
return Vector2(-x, -y);
}
- void operator+=(Vector2::Arg v) {
+ void operator+=(Vector2::Arg v)
+ {
x += v.x;
y += v.y;
}
- void operator-=(Vector2::Arg v) {
+ void operator-=(Vector2::Arg v)
+ {
x -= v.x;
y -= v.y;
}
- void operator*=(float s) {
+ void operator*=(float s)
+ {
x *= s;
y *= s;
}
- void operator*=(Vector2::Arg v) {
+ void operator*=(Vector2::Arg v)
+ {
x *= v.x;
y *= v.y;
}
- friend bool operator==(Vector2::Arg a, Vector2::Arg b) {
+ friend bool operator==(Vector2::Arg a, Vector2::Arg b)
+ {
return a.x == b.x && a.y == b.y;
}
- friend bool operator!=(Vector2::Arg a, Vector2::Arg b) {
+ friend bool operator!=(Vector2::Arg a, Vector2::Arg b)
+ {
return a.x != b.x || a.y != b.y;
}
- union {
+ union
+ {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4201)
@@ -272,52 +292,64 @@ public:
};
};
-Vector2 operator+(Vector2::Arg a, Vector2::Arg b) {
+Vector2 operator+(Vector2::Arg a, Vector2::Arg b)
+{
return Vector2(a.x + b.x, a.y + b.y);
}
-Vector2 operator-(Vector2::Arg a, Vector2::Arg b) {
+Vector2 operator-(Vector2::Arg a, Vector2::Arg b)
+{
return Vector2(a.x - b.x, a.y - b.y);
}
-Vector2 operator*(Vector2::Arg v, float s) {
+Vector2 operator*(Vector2::Arg v, float s)
+{
return Vector2(v.x * s, v.y * s);
}
-Vector2 operator*(Vector2::Arg v1, Vector2::Arg v2) {
+Vector2 operator*(Vector2::Arg v1, Vector2::Arg v2)
+{
return Vector2(v1.x * v2.x, v1.y * v2.y);
}
-Vector2 operator/(Vector2::Arg v, float s) {
+Vector2 operator/(Vector2::Arg v, float s)
+{
return Vector2(v.x / s, v.y / s);
}
-Vector2 lerp(Vector2::Arg v1, Vector2::Arg v2, float t) {
+Vector2 lerp(Vector2::Arg v1, Vector2::Arg v2, float t)
+{
const float s = 1.0f - t;
return Vector2(v1.x * s + t * v2.x, v1.y * s + t * v2.y);
}
-float dot(Vector2::Arg a, Vector2::Arg b) {
+float dot(Vector2::Arg a, Vector2::Arg b)
+{
return a.x * b.x + a.y * b.y;
}
-float lengthSquared(Vector2::Arg v) {
+float lengthSquared(Vector2::Arg v)
+{
return v.x * v.x + v.y * v.y;
}
-float length(Vector2::Arg v) {
+float length(Vector2::Arg v)
+{
return sqrtf(lengthSquared(v));
}
-float distance(Vector2::Arg a, Vector2::Arg b) {
+float distance(Vector2::Arg a, Vector2::Arg b)
+{
return length(a - b);
}
-bool isNormalized(Vector2::Arg v, float epsilon = NV_NORMAL_EPSILON) {
+bool isNormalized(Vector2::Arg v, float epsilon = NV_NORMAL_EPSILON)
+{
return equal(length(v), 1, epsilon);
}
-Vector2 normalize(Vector2::Arg v, float epsilon = NV_EPSILON) {
+Vector2 normalize(Vector2::Arg v, float epsilon = NV_EPSILON)
+{
float l = length(v);
xaDebugAssert(!isZero(l, epsilon));
#ifdef NDEBUG
@@ -328,7 +360,8 @@ Vector2 normalize(Vector2::Arg v, float epsilon = NV_EPSILON) {
return n;
}
-Vector2 normalizeSafe(Vector2::Arg v, Vector2::Arg fallback, float epsilon = NV_EPSILON) {
+Vector2 normalizeSafe(Vector2::Arg v, Vector2::Arg fallback, float epsilon = NV_EPSILON)
+{
float l = length(v);
if (isZero(l, epsilon)) {
return fallback;
@@ -336,23 +369,28 @@ Vector2 normalizeSafe(Vector2::Arg v, Vector2::Arg fallback, float epsilon = NV_
return v * (1.0f / l);
}
-bool equal(Vector2::Arg v1, Vector2::Arg v2, float epsilon = NV_EPSILON) {
+bool equal(Vector2::Arg v1, Vector2::Arg v2, float epsilon = NV_EPSILON)
+{
return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon);
}
-Vector2 max(Vector2::Arg a, Vector2::Arg b) {
+Vector2 max(Vector2::Arg a, Vector2::Arg b)
+{
return Vector2(std::max(a.x, b.x), std::max(a.y, b.y));
}
-bool isFinite(Vector2::Arg v) {
+bool isFinite(Vector2::Arg v)
+{
return std::isfinite(v.x) && std::isfinite(v.y);
}
// Note, this is the area scaled by 2!
-float triangleArea(Vector2::Arg v0, Vector2::Arg v1) {
+float triangleArea(Vector2::Arg v0, Vector2::Arg v1)
+{
return (v0.x * v1.y - v0.y * v1.x); // * 0.5f;
}
-float triangleArea(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c) {
+float triangleArea(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c)
+{
// IC: While it may be appealing to use the following expression:
//return (c.x * a.y + a.x * b.y + b.x * c.y - b.x * a.y - c.x * b.y - a.x * c.y); // * 0.5f;
// That's actually a terrible idea. Small triangles far from the origin can end up producing fairly large floating point
@@ -364,105 +402,109 @@ float triangleArea(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c) {
return triangleArea(a - c, b - c);
}
-float triangleArea2(Vector2::Arg v1, Vector2::Arg v2, Vector2::Arg v3) {
+float triangleArea2(Vector2::Arg v1, Vector2::Arg v2, Vector2::Arg v3)
+{
return 0.5f * (v3.x * v1.y + v1.x * v2.y + v2.x * v3.y - v2.x * v1.y - v3.x * v2.y - v1.x * v3.y);
}
-static uint32_t hash(const Vector2 &v, uint32_t h) {
+static uint32_t hash(const Vector2 &v, uint32_t h)
+{
return sdbmFloatHash(v.component, 2, h);
}
-class Vector3 {
+class Vector3
+{
public:
typedef Vector3 const &Arg;
Vector3() {}
- explicit Vector3(float f) :
- x(f),
- y(f),
- z(f) {}
- Vector3(float x, float y, float z) :
- x(x),
- y(y),
- z(z) {}
- Vector3(Vector2::Arg v, float z) :
- x(v.x),
- y(v.y),
- z(z) {}
- Vector3(Vector3::Arg v) :
- x(v.x),
- y(v.y),
- z(v.z) {}
-
- const Vector3 &operator=(Vector3::Arg v) {
+ explicit Vector3(float f) : x(f), y(f), z(f) {}
+ Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
+ Vector3(Vector2::Arg v, float z) : x(v.x), y(v.y), z(z) {}
+ Vector3(Vector3::Arg v) : x(v.x), y(v.y), z(v.z) {}
+
+ const Vector3 &operator=(Vector3::Arg v)
+ {
x = v.x;
y = v.y;
z = v.z;
return *this;
}
- Vector2 xy() const {
+ Vector2 xy() const
+ {
return Vector2(x, y);
}
const float *ptr() const { return &x; }
- void set(float _x, float _y, float _z) {
+ void set(float _x, float _y, float _z)
+ {
x = _x;
y = _y;
z = _z;
}
- Vector3 operator-() const {
+ Vector3 operator-() const
+ {
return Vector3(-x, -y, -z);
}
- void operator+=(Vector3::Arg v) {
+ void operator+=(Vector3::Arg v)
+ {
x += v.x;
y += v.y;
z += v.z;
}
- void operator-=(Vector3::Arg v) {
+ void operator-=(Vector3::Arg v)
+ {
x -= v.x;
y -= v.y;
z -= v.z;
}
- void operator*=(float s) {
+ void operator*=(float s)
+ {
x *= s;
y *= s;
z *= s;
}
- void operator/=(float s) {
+ void operator/=(float s)
+ {
float is = 1.0f / s;
x *= is;
y *= is;
z *= is;
}
- void operator*=(Vector3::Arg v) {
+ void operator*=(Vector3::Arg v)
+ {
x *= v.x;
y *= v.y;
z *= v.z;
}
- void operator/=(Vector3::Arg v) {
+ void operator/=(Vector3::Arg v)
+ {
x /= v.x;
y /= v.y;
z /= v.z;
}
- friend bool operator==(Vector3::Arg a, Vector3::Arg b) {
+ friend bool operator==(Vector3::Arg a, Vector3::Arg b)
+ {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
- friend bool operator!=(Vector3::Arg a, Vector3::Arg b) {
+ friend bool operator!=(Vector3::Arg a, Vector3::Arg b)
+ {
return a.x != b.x || a.y != b.y || a.z != b.z;
}
- union {
+ union
+ {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4201)
@@ -479,85 +521,106 @@ public:
};
};
-Vector3 add(Vector3::Arg a, Vector3::Arg b) {
+Vector3 add(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
}
-Vector3 add(Vector3::Arg a, float b) {
+Vector3 add(Vector3::Arg a, float b)
+{
return Vector3(a.x + b, a.y + b, a.z + b);
}
-Vector3 operator+(Vector3::Arg a, Vector3::Arg b) {
+Vector3 operator+(Vector3::Arg a, Vector3::Arg b)
+{
return add(a, b);
}
-Vector3 operator+(Vector3::Arg a, float b) {
+Vector3 operator+(Vector3::Arg a, float b)
+{
return add(a, b);
}
-Vector3 sub(Vector3::Arg a, Vector3::Arg b) {
+Vector3 sub(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
}
-Vector3 sub(Vector3::Arg a, float b) {
+Vector3 sub(Vector3::Arg a, float b)
+{
return Vector3(a.x - b, a.y - b, a.z - b);
}
-Vector3 operator-(Vector3::Arg a, Vector3::Arg b) {
+Vector3 operator-(Vector3::Arg a, Vector3::Arg b)
+{
return sub(a, b);
}
-Vector3 operator-(Vector3::Arg a, float b) {
+Vector3 operator-(Vector3::Arg a, float b)
+{
return sub(a, b);
}
-Vector3 cross(Vector3::Arg a, Vector3::Arg b) {
+Vector3 cross(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
}
-Vector3 operator*(Vector3::Arg v, float s) {
+Vector3 operator*(Vector3::Arg v, float s)
+{
return Vector3(v.x * s, v.y * s, v.z * s);
}
-Vector3 operator*(float s, Vector3::Arg v) {
+Vector3 operator*(float s, Vector3::Arg v)
+{
return Vector3(v.x * s, v.y * s, v.z * s);
}
-Vector3 operator*(Vector3::Arg v, Vector3::Arg s) {
+Vector3 operator*(Vector3::Arg v, Vector3::Arg s)
+{
return Vector3(v.x * s.x, v.y * s.y, v.z * s.z);
}
-Vector3 operator/(Vector3::Arg v, float s) {
+Vector3 operator/(Vector3::Arg v, float s)
+{
return v * (1.0f / s);
}
-Vector3 lerp(Vector3::Arg v1, Vector3::Arg v2, float t) {
+Vector3 lerp(Vector3::Arg v1, Vector3::Arg v2, float t)
+{
const float s = 1.0f - t;
return Vector3(v1.x * s + t * v2.x, v1.y * s + t * v2.y, v1.z * s + t * v2.z);
}
-float dot(Vector3::Arg a, Vector3::Arg b) {
+float dot(Vector3::Arg a, Vector3::Arg b)
+{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
-float lengthSquared(Vector3::Arg v) {
+float lengthSquared(Vector3::Arg v)
+{
return v.x * v.x + v.y * v.y + v.z * v.z;
}
-float length(Vector3::Arg v) {
+float length(Vector3::Arg v)
+{
return sqrtf(lengthSquared(v));
}
-float distance(Vector3::Arg a, Vector3::Arg b) {
+float distance(Vector3::Arg a, Vector3::Arg b)
+{
return length(a - b);
}
-float distanceSquared(Vector3::Arg a, Vector3::Arg b) {
+float distanceSquared(Vector3::Arg a, Vector3::Arg b)
+{
return lengthSquared(a - b);
}
-bool isNormalized(Vector3::Arg v, float epsilon = NV_NORMAL_EPSILON) {
+bool isNormalized(Vector3::Arg v, float epsilon = NV_NORMAL_EPSILON)
+{
return equal(length(v), 1, epsilon);
}
-Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON) {
+Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON)
+{
float l = length(v);
xaDebugAssert(!isZero(l, epsilon));
#ifdef NDEBUG
@@ -568,7 +631,8 @@ Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON) {
return n;
}
-Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_EPSILON) {
+Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_EPSILON)
+{
float l = length(v);
if (isZero(l, epsilon)) {
return fallback;
@@ -576,49 +640,56 @@ Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_
return v * (1.0f / l);
}
-bool equal(Vector3::Arg v1, Vector3::Arg v2, float epsilon = NV_EPSILON) {
+bool equal(Vector3::Arg v1, Vector3::Arg v2, float epsilon = NV_EPSILON)
+{
return equal(v1.x, v2.x, epsilon) && equal(v1.y, v2.y, epsilon) && equal(v1.z, v2.z, epsilon);
}
-Vector3 min(Vector3::Arg a, Vector3::Arg b) {
+Vector3 min(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
}
-Vector3 max(Vector3::Arg a, Vector3::Arg b) {
+Vector3 max(Vector3::Arg a, Vector3::Arg b)
+{
return Vector3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
}
-Vector3 clamp(Vector3::Arg v, float min, float max) {
+Vector3 clamp(Vector3::Arg v, float min, float max)
+{
return Vector3(clamp(v.x, min, max), clamp(v.y, min, max), clamp(v.z, min, max));
}
-Vector3 saturate(Vector3::Arg v) {
+Vector3 saturate(Vector3::Arg v)
+{
return Vector3(saturate(v.x), saturate(v.y), saturate(v.z));
}
-Vector3 floor(Vector3::Arg v) {
+Vector3 floor(Vector3::Arg v)
+{
return Vector3(floorf(v.x), floorf(v.y), floorf(v.z));
}
-bool isFinite(Vector3::Arg v) {
+bool isFinite(Vector3::Arg v)
+{
return std::isfinite(v.x) && std::isfinite(v.y) && std::isfinite(v.z);
}
-static uint32_t hash(const Vector3 &v, uint32_t h) {
+static uint32_t hash(const Vector3 &v, uint32_t h)
+{
return sdbmFloatHash(v.component, 3, h);
}
/// Basis class to compute tangent space basis, ortogonalizations and to
/// transform vectors from one space to another.
-class Basis {
+class Basis
+{
public:
/// Create a null basis.
- Basis() :
- tangent(0, 0, 0),
- bitangent(0, 0, 0),
- normal(0, 0, 0) {}
+ Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {}
- void buildFrameForDirection(Vector3::Arg d, float angle = 0) {
+ void buildFrameForDirection(Vector3::Arg d, float angle = 0)
+ {
xaAssert(isNormalized(d));
normal = d;
// Choose minimum axis.
@@ -649,65 +720,76 @@ public:
};
// Simple bit array.
-class BitArray {
+class BitArray
+{
public:
- BitArray() :
- m_size(0) {}
- BitArray(uint32_t sz) {
+ BitArray() : m_size(0) {}
+ BitArray(uint32_t sz)
+ {
resize(sz);
}
- uint32_t size() const {
+ uint32_t size() const
+ {
return m_size;
}
- void clear() {
+ void clear()
+ {
resize(0);
}
- void resize(uint32_t new_size) {
+ void resize(uint32_t new_size)
+ {
m_size = new_size;
- m_wordArray.resize((m_size + 31) >> 5);
+ m_wordArray.resize( (m_size + 31) >> 5 );
}
/// Get bit.
- bool bitAt(uint32_t b) const {
- xaDebugAssert(b < m_size);
+ bool bitAt(uint32_t b) const
+ {
+ xaDebugAssert( b < m_size );
return (m_wordArray[b >> 5] & (1 << (b & 31))) != 0;
}
// Set a bit.
- void setBitAt(uint32_t idx) {
+ void setBitAt(uint32_t idx)
+ {
xaDebugAssert(idx < m_size);
- m_wordArray[idx >> 5] |= (1 << (idx & 31));
+ m_wordArray[idx >> 5] |= (1 << (idx & 31));
}
// Toggle a bit.
- void toggleBitAt(uint32_t idx) {
+ void toggleBitAt(uint32_t idx)
+ {
xaDebugAssert(idx < m_size);
m_wordArray[idx >> 5] ^= (1 << (idx & 31));
}
// Set a bit to the given value. @@ Rename modifyBitAt?
- void setBitAt(uint32_t idx, bool b) {
+ void setBitAt(uint32_t idx, bool b)
+ {
xaDebugAssert(idx < m_size);
m_wordArray[idx >> 5] = setBits(m_wordArray[idx >> 5], 1 << (idx & 31), b);
xaDebugAssert(bitAt(idx) == b);
}
// Clear all the bits.
- void clearAll() {
- memset(m_wordArray.data(), 0, m_wordArray.size() * sizeof(uint32_t));
+ void clearAll()
+ {
+ memset(m_wordArray.data(), 0, m_wordArray.size() * sizeof(uint32_t ));
}
// Set all the bits.
- void setAll() {
- memset(m_wordArray.data(), 0xFF, m_wordArray.size() * sizeof(uint32_t));
+ void setAll()
+ {
+ memset(m_wordArray.data(), 0xFF, m_wordArray.size() * sizeof(uint32_t ));
}
private:
// See "Conditionally set or clear bits without branching" at http://graphics.stanford.edu/~seander/bithacks.html
- uint32_t setBits(uint32_t w, uint32_t m, bool b) {
+ uint32_t setBits(uint32_t w, uint32_t m, bool b)
+ {
return (w & ~m) | (-int(b) & m);
}
@@ -719,29 +801,26 @@ private:
};
/// Bit map. This should probably be called BitImage.
-class BitMap {
+class BitMap
+{
public:
- BitMap() :
- m_width(0),
- m_height(0) {}
- BitMap(uint32_t w, uint32_t h) :
- m_width(w),
- m_height(h),
- m_bitArray(w * h) {}
-
- uint32_t width() const {
+ BitMap() : m_width(0), m_height(0) {}
+ BitMap(uint32_t w, uint32_t h) : m_width(w), m_height(h), m_bitArray(w * h) {}
+
+ uint32_t width() const
+ {
return m_width;
}
- uint32_t height() const {
+ uint32_t height() const
+ {
return m_height;
}
- void resize(uint32_t w, uint32_t h, bool initValue) {
+ void resize(uint32_t w, uint32_t h, bool initValue)
+ {
BitArray tmp(w * h);
- if (initValue)
- tmp.setAll();
- else
- tmp.clearAll();
+ if (initValue) tmp.setAll();
+ else tmp.clearAll();
// @@ Copying one bit at a time. This could be much faster.
for (uint32_t y = 0; y < m_height; y++) {
for (uint32_t x = 0; x < m_width; x++) {
@@ -754,17 +833,20 @@ public:
m_height = h;
}
- bool bitAt(uint32_t x, uint32_t y) const {
+ bool bitAt(uint32_t x, uint32_t y) const
+ {
xaDebugAssert(x < m_width && y < m_height);
return m_bitArray.bitAt(y * m_width + x);
}
- void setBitAt(uint32_t x, uint32_t y) {
+ void setBitAt(uint32_t x, uint32_t y)
+ {
xaDebugAssert(x < m_width && y < m_height);
m_bitArray.setBitAt(y * m_width + x);
}
- void clearAll() {
+ void clearAll()
+ {
m_bitArray.clearAll();
}
@@ -775,39 +857,41 @@ private:
};
// Axis Aligned Bounding Box.
-class Box {
+class Box
+{
public:
Box() {}
- Box(const Box &b) :
- minCorner(b.minCorner),
- maxCorner(b.maxCorner) {}
- Box(const Vector3 &mins, const Vector3 &maxs) :
- minCorner(mins),
- maxCorner(maxs) {}
-
- operator const float *() const {
+ Box(const Box &b) : minCorner(b.minCorner), maxCorner(b.maxCorner) {}
+ Box(const Vector3 &mins, const Vector3 &maxs) : minCorner(mins), maxCorner(maxs) {}
+
+ operator const float *() const
+ {
return reinterpret_cast<const float *>(this);
}
// Clear the bounds.
- void clearBounds() {
+ void clearBounds()
+ {
minCorner.set(FLT_MAX, FLT_MAX, FLT_MAX);
maxCorner.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
}
// Return extents of the box.
- Vector3 extents() const {
+ Vector3 extents() const
+ {
return (maxCorner - minCorner) * 0.5f;
}
// Add a point to this box.
- void addPointToBounds(const Vector3 &p) {
+ void addPointToBounds(const Vector3 &p)
+ {
minCorner = min(minCorner, p);
maxCorner = max(maxCorner, p);
}
// Get the volume of the box.
- float volume() const {
+ float volume() const
+ {
Vector3 d = extents();
return 8.0f * (d.x * d.y * d.z);
}
@@ -816,9 +900,11 @@ public:
Vector3 maxCorner;
};
-class Fit {
+class Fit
+{
public:
- static Vector3 computeCentroid(int n, const Vector3 *__restrict points) {
+ static Vector3 computeCentroid(int n, const Vector3 *__restrict points)
+ {
Vector3 centroid(0.0f);
for (int i = 0; i < n; i++) {
centroid += points[i];
@@ -827,7 +913,8 @@ public:
return centroid;
}
- static Vector3 computeCovariance(int n, const Vector3 *__restrict points, float *__restrict covariance) {
+ static Vector3 computeCovariance(int n, const Vector3 *__restrict points, float *__restrict covariance)
+ {
// compute the centroid
Vector3 centroid = computeCentroid(n, points);
// compute covariance matrix
@@ -846,7 +933,8 @@ public:
return centroid;
}
- static bool isPlanar(int n, const Vector3 *points, float epsilon = NV_EPSILON) {
+ static bool isPlanar(int n, const Vector3 *points, float epsilon = NV_EPSILON)
+ {
// compute the centroid and covariance
float matrix[6];
computeCovariance(n, points, matrix);
@@ -861,7 +949,8 @@ public:
// Tridiagonal solver from Charles Bloom.
// Householder transforms followed by QL decomposition.
// Seems to be based on the code from Numerical Recipes in C.
- static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3]) {
+ static bool eigenSolveSymmetric3(const float matrix[6], float eigenValues[3], Vector3 eigenVectors[3])
+ {
xaDebugAssert(matrix != NULL && eigenValues != NULL && eigenVectors != NULL);
float subd[3];
float diag[3];
@@ -886,7 +975,7 @@ public:
// eigenvectors are the columns; make them the rows :
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- eigenVectors[j].component[i] = (float)work[i][j];
+ eigenVectors[j].component[i] = (float) work[i][j];
}
}
// shuffle to sort by singular value :
@@ -908,7 +997,8 @@ public:
}
private:
- static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd) {
+ static void EigenSolver3_Tridiagonal(float mat[3][3], float *diag, float *subd)
+ {
// Householder reduction T = Q^t M Q
// Input:
// mat, symmetric 3x3 matrix M
@@ -960,7 +1050,8 @@ private:
}
}
- static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd) {
+ static bool EigenSolver3_QLAlgorithm(float mat[3][3], float *diag, float *subd)
+ {
// QL iteration with implicit shifting to reduce matrix from tridiagonal
// to diagonal
const int maxiter = 32;
@@ -970,21 +1061,21 @@ private:
int m;
for (m = ell; m <= 1; m++) {
float dd = fabsf(diag[m]) + fabsf(diag[m + 1]);
- if (fabsf(subd[m]) + dd == dd)
+ if ( fabsf(subd[m]) + dd == dd )
break;
}
- if (m == ell)
+ if ( m == ell )
break;
float g = (diag[ell + 1] - diag[ell]) / (2 * subd[ell]);
float r = sqrtf(g * g + 1);
- if (g < 0)
+ if ( g < 0 )
g = diag[m] - diag[ell] + subd[ell] / (g - r);
else
g = diag[m] - diag[ell] + subd[ell] / (g + r);
float s = 1, c = 1, p = 0;
for (int i = m - 1; i >= ell; i--) {
float f = s * subd[i], b = c * subd[i];
- if (fabsf(f) >= fabsf(g)) {
+ if ( fabsf(f) >= fabsf(g) ) {
c = g / f;
r = sqrtf(c * c + 1);
subd[i + 1] = f * r;
@@ -1010,7 +1101,7 @@ private:
subd[ell] = g;
subd[m] = 0;
}
- if (iter == maxiter)
+ if ( iter == maxiter )
// should not get here under normal circumstances
return false;
}
@@ -1019,30 +1110,33 @@ private:
};
/// Fixed size vector class.
-class FullVector {
+class FullVector
+{
public:
FullVector(uint32_t dim) { m_array.resize(dim); }
- FullVector(const FullVector &v) :
- m_array(v.m_array) {}
+ FullVector(const FullVector &v) : m_array(v.m_array) {}
- const FullVector &operator=(const FullVector &v) {
+ const FullVector &operator=(const FullVector &v)
+ {
xaAssert(dimension() == v.dimension());
m_array = v.m_array;
return *this;
}
uint32_t dimension() const { return m_array.size(); }
- const float &operator[](uint32_t index) const { return m_array[index]; }
- float &operator[](uint32_t index) { return m_array[index]; }
+ const float &operator[]( uint32_t index ) const { return m_array[index]; }
+ float &operator[] ( uint32_t index ) { return m_array[index]; }
- void fill(float f) {
+ void fill(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] = f;
}
}
- void operator+=(const FullVector &v) {
+ void operator+=(const FullVector &v)
+ {
xaDebugAssert(dimension() == v.dimension());
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -1050,7 +1144,8 @@ public:
}
}
- void operator-=(const FullVector &v) {
+ void operator-=(const FullVector &v)
+ {
xaDebugAssert(dimension() == v.dimension());
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -1058,7 +1153,8 @@ public:
}
}
- void operator*=(const FullVector &v) {
+ void operator*=(const FullVector &v)
+ {
xaDebugAssert(dimension() == v.dimension());
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -1066,21 +1162,24 @@ public:
}
}
- void operator+=(float f) {
+ void operator+=(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] += f;
}
}
- void operator-=(float f) {
+ void operator-=(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] -= f;
}
}
- void operator*=(float f) {
+ void operator*=(float f)
+ {
const uint32_t dim = dimension();
for (uint32_t i = 0; i < dim; i++) {
m_array[i] *= f;
@@ -1095,66 +1194,70 @@ namespace halfedge {
class Face;
class Vertex;
-class Edge {
+class Edge
+{
public:
uint32_t id;
Edge *next;
- Edge *prev; // This is not strictly half-edge, but makes algorithms easier and faster.
+ Edge *prev; // This is not strictly half-edge, but makes algorithms easier and faster.
Edge *pair;
Vertex *vertex;
Face *face;
// Default constructor.
- Edge(uint32_t id) :
- id(id),
- next(NULL),
- prev(NULL),
- pair(NULL),
- vertex(NULL),
- face(NULL) {}
+ Edge(uint32_t id) : id(id), next(NULL), prev(NULL), pair(NULL), vertex(NULL), face(NULL) {}
// Vertex queries.
- const Vertex *from() const {
+ const Vertex *from() const
+ {
return vertex;
}
- Vertex *from() {
+ Vertex *from()
+ {
return vertex;
}
- const Vertex *to() const {
- return pair->vertex; // This used to be 'next->vertex', but that changed often when the connectivity of the mesh changes.
+ const Vertex *to() const
+ {
+ return pair->vertex; // This used to be 'next->vertex', but that changed often when the connectivity of the mesh changes.
}
- Vertex *to() {
+ Vertex *to()
+ {
return pair->vertex;
}
// Edge queries.
- void setNext(Edge *e) {
+ void setNext(Edge *e)
+ {
next = e;
if (e != NULL) e->prev = this;
}
- void setPrev(Edge *e) {
+ void setPrev(Edge *e)
+ {
prev = e;
if (e != NULL) e->next = this;
}
// @@ It would be more simple to only check m_pair == NULL
// Face queries.
- bool isBoundary() const {
+ bool isBoundary() const
+ {
return !(face && pair->face);
}
// @@ This is not exactly accurate, we should compare the texture coordinates...
- bool isSeam() const {
+ bool isSeam() const
+ {
return vertex != pair->next->vertex || next->vertex != pair->vertex;
}
bool isNormalSeam() const;
bool isTextureSeam() const;
- bool isValid() const {
+ bool isValid() const
+ {
// null face is OK.
if (next == NULL || prev == NULL || pair == NULL || vertex == NULL) return false;
if (next->prev != this) return false;
@@ -1169,10 +1272,10 @@ public:
float angle() const;
};
-class Vertex {
+class Vertex
+{
public:
uint32_t id;
- uint32_t original_id;
Edge *edge;
Vertex *next;
Vertex *prev;
@@ -1180,36 +1283,35 @@ public:
Vector3 nor;
Vector2 tex;
- Vertex(uint32_t id) :
- id(id),
- original_id(id),
- edge(NULL),
- pos(0.0f),
- nor(0.0f),
- tex(0.0f) {
+ Vertex(uint32_t id) : id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f)
+ {
next = this;
prev = this;
}
// Set first edge of all colocals.
- void setEdge(Edge *e) {
+ void setEdge(Edge *e)
+ {
for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
it.current()->edge = e;
}
}
// Update position of all colocals.
- void setPos(const Vector3 &p) {
+ void setPos(const Vector3 &p)
+ {
for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
it.current()->pos = p;
}
}
- bool isFirstColocal() const {
+ bool isFirstColocal() const
+ {
return firstColocal() == this;
}
- const Vertex *firstColocal() const {
+ const Vertex *firstColocal() const
+ {
uint32_t firstId = id;
const Vertex *vertex = this;
for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) {
@@ -1221,7 +1323,8 @@ public:
return vertex;
}
- Vertex *firstColocal() {
+ Vertex *firstColocal()
+ {
Vertex *vertex = this;
uint32_t firstId = id;
for (VertexIterator it(colocals()); !it.isDone(); it.advance()) {
@@ -1233,7 +1336,8 @@ public:
return vertex;
}
- bool isColocal(const Vertex *v) const {
+ bool isColocal(const Vertex *v) const
+ {
if (this == v) return true;
if (pos != v->pos) return false;
for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) {
@@ -1244,13 +1348,15 @@ public:
return false;
}
- void linkColocal(Vertex *v) {
+ void linkColocal(Vertex *v)
+ {
next->prev = v;
v->next = next;
next = v;
v->prev = this;
}
- void unlinkColocal() {
+ void unlinkColocal()
+ {
next->prev = prev;
prev->next = next;
next = this;
@@ -1258,7 +1364,8 @@ public:
}
// @@ Note: This only works if linkBoundary has been called.
- bool isBoundary() const {
+ bool isBoundary() const
+ {
return (edge && !edge->face);
}
@@ -1266,23 +1373,25 @@ public:
class EdgeIterator //: public Iterator<Edge *>
{
public:
- EdgeIterator(Edge *e) :
- m_end(NULL),
- m_current(e) {}
+ EdgeIterator(Edge *e) : m_end(NULL), m_current(e) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->pair->next;
//m_current = m_current->prev->pair;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual Edge *current() const {
+ virtual Edge *current() const
+ {
return m_current;
}
- Vertex *vertex() const {
+ Vertex *vertex() const
+ {
return m_current->vertex;
}
@@ -1291,10 +1400,12 @@ public:
Edge *m_current;
};
- EdgeIterator edges() {
+ EdgeIterator edges()
+ {
return EdgeIterator(edge);
}
- EdgeIterator edges(Edge *e) {
+ EdgeIterator edges(Edge *e)
+ {
return EdgeIterator(e);
}
@@ -1302,26 +1413,26 @@ public:
class ConstEdgeIterator //: public Iterator<Edge *>
{
public:
- ConstEdgeIterator(const Edge *e) :
- m_end(NULL),
- m_current(e) {}
- ConstEdgeIterator(EdgeIterator it) :
- m_end(NULL),
- m_current(it.current()) {}
-
- virtual void advance() {
+ ConstEdgeIterator(const Edge *e) : m_end(NULL), m_current(e) { }
+ ConstEdgeIterator(EdgeIterator it) : m_end(NULL), m_current(it.current()) { }
+
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->pair->next;
//m_current = m_current->prev->pair;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual const Edge *current() const {
+ virtual const Edge *current() const
+ {
return m_current;
}
- const Vertex *vertex() const {
+ const Vertex *vertex() const
+ {
return m_current->to();
}
@@ -1330,10 +1441,12 @@ public:
const Edge *m_current;
};
- ConstEdgeIterator edges() const {
+ ConstEdgeIterator edges() const
+ {
return ConstEdgeIterator(edge);
}
- ConstEdgeIterator edges(const Edge *e) const {
+ ConstEdgeIterator edges(const Edge *e) const
+ {
return ConstEdgeIterator(e);
}
@@ -1341,19 +1454,20 @@ public:
class VertexIterator //: public Iterator<Edge *>
{
public:
- VertexIterator(Vertex *v) :
- m_end(NULL),
- m_current(v) {}
+ VertexIterator(Vertex *v) : m_end(NULL), m_current(v) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual Vertex *current() const {
+ virtual Vertex *current() const
+ {
return m_current;
}
@@ -1362,7 +1476,8 @@ public:
Vertex *m_current;
};
- VertexIterator colocals() {
+ VertexIterator colocals()
+ {
return VertexIterator(this);
}
@@ -1370,19 +1485,20 @@ public:
class ConstVertexIterator //: public Iterator<Edge *>
{
public:
- ConstVertexIterator(const Vertex *v) :
- m_end(NULL),
- m_current(v) {}
+ ConstVertexIterator(const Vertex *v) : m_end(NULL), m_current(v) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual const Vertex *current() const {
+ virtual const Vertex *current() const
+ {
return m_current;
}
@@ -1391,24 +1507,29 @@ public:
const Vertex *m_current;
};
- ConstVertexIterator colocals() const {
+ ConstVertexIterator colocals() const
+ {
return ConstVertexIterator(this);
}
};
-bool Edge::isNormalSeam() const {
+bool Edge::isNormalSeam() const
+{
return (vertex->nor != pair->next->vertex->nor || next->vertex->nor != pair->vertex->nor);
}
-bool Edge::isTextureSeam() const {
+bool Edge::isTextureSeam() const
+{
return (vertex->tex != pair->next->vertex->tex || next->vertex->tex != pair->vertex->tex);
}
-float Edge::length() const {
+float Edge::length() const
+{
return internal::length(to()->pos - from()->pos);
}
-float Edge::angle() const {
+float Edge::angle() const
+{
Vector3 p = vertex->pos;
Vector3 a = prev->vertex->pos;
Vector3 b = next->vertex->pos;
@@ -1417,20 +1538,18 @@ float Edge::angle() const {
return acosf(dot(v0, v1) / (internal::length(v0) * internal::length(v1)));
}
-class Face {
+class Face
+{
public:
uint32_t id;
uint16_t group;
uint16_t material;
Edge *edge;
- Face(uint32_t id) :
- id(id),
- group(uint16_t(~0)),
- material(uint16_t(~0)),
- edge(NULL) {}
+ Face(uint32_t id) : id(id), group(uint16_t(~0)), material(uint16_t(~0)), edge(NULL) {}
- float area() const {
+ float area() const
+ {
float area = 0;
const Vector3 &v0 = edge->from()->pos;
for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance()) {
@@ -1442,7 +1561,8 @@ public:
return area * 0.5f;
}
- float parametricArea() const {
+ float parametricArea() const
+ {
float area = 0;
const Vector2 &v0 = edge->from()->tex;
for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance()) {
@@ -1454,7 +1574,8 @@ public:
return area * 0.5f;
}
- Vector3 normal() const {
+ Vector3 normal() const
+ {
Vector3 n(0);
const Vertex *vertex0 = NULL;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
@@ -1476,7 +1597,8 @@ public:
return normalizeSafe(n, Vector3(0, 0, 1), 0.0f);
}
- Vector3 centroid() const {
+ Vector3 centroid() const
+ {
Vector3 sum(0.0f);
uint32_t count = 0;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
@@ -1488,7 +1610,8 @@ public:
}
// Unnormalized face normal assuming it's a triangle.
- Vector3 triangleNormal() const {
+ Vector3 triangleNormal() const
+ {
Vector3 p0 = edge->vertex->pos;
Vector3 p1 = edge->next->vertex->pos;
Vector3 p2 = edge->next->next->vertex->pos;
@@ -1497,7 +1620,8 @@ public:
return normalizeSafe(cross(e0, e1), Vector3(0), 0.0f);
}
- Vector3 triangleNormalAreaScaled() const {
+ Vector3 triangleNormalAreaScaled() const
+ {
Vector3 p0 = edge->vertex->pos;
Vector3 p1 = edge->next->vertex->pos;
Vector3 p2 = edge->next->next->vertex->pos;
@@ -1508,7 +1632,8 @@ public:
// Average of the edge midpoints weighted by the edge length.
// I want a point inside the triangle, but closer to the cirumcenter.
- Vector3 triangleCenter() const {
+ Vector3 triangleCenter() const
+ {
Vector3 p0 = edge->vertex->pos;
Vector3 p1 = edge->next->vertex->pos;
Vector3 p2 = edge->next->next->vertex->pos;
@@ -1521,7 +1646,8 @@ public:
return m0 + m1 + m2;
}
- bool isValid() const {
+ bool isValid() const
+ {
uint32_t count = 0;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
const Edge *e = it.current();
@@ -1534,14 +1660,16 @@ public:
return true;
}
- bool contains(const Edge *e) const {
+ bool contains(const Edge *e) const
+ {
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
if (it.current() == e) return true;
}
return false;
}
- uint32_t edgeCount() const {
+ uint32_t edgeCount() const
+ {
uint32_t count = 0;
for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) {
++count;
@@ -1553,22 +1681,24 @@ public:
class EdgeIterator //: public Iterator<Edge *>
{
public:
- EdgeIterator(Edge *e) :
- m_end(NULL),
- m_current(e) {}
+ EdgeIterator(Edge *e) : m_end(NULL), m_current(e) { }
- virtual void advance() {
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual Edge *current() const {
+ virtual Edge *current() const
+ {
return m_current;
}
- Vertex *vertex() const {
+ Vertex *vertex() const
+ {
return m_current->vertex;
}
@@ -1577,10 +1707,12 @@ public:
Edge *m_current;
};
- EdgeIterator edges() {
+ EdgeIterator edges()
+ {
return EdgeIterator(edge);
}
- EdgeIterator edges(Edge *e) {
+ EdgeIterator edges(Edge *e)
+ {
xaDebugAssert(contains(e));
return EdgeIterator(e);
}
@@ -1589,25 +1721,25 @@ public:
class ConstEdgeIterator //: public Iterator<const Edge *>
{
public:
- ConstEdgeIterator(const Edge *e) :
- m_end(NULL),
- m_current(e) {}
- ConstEdgeIterator(const EdgeIterator &it) :
- m_end(NULL),
- m_current(it.current()) {}
-
- virtual void advance() {
+ ConstEdgeIterator(const Edge *e) : m_end(NULL), m_current(e) { }
+ ConstEdgeIterator(const EdgeIterator &it) : m_end(NULL), m_current(it.current()) { }
+
+ virtual void advance()
+ {
if (m_end == NULL) m_end = m_current;
m_current = m_current->next;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_end == m_current;
}
- virtual const Edge *current() const {
+ virtual const Edge *current() const
+ {
return m_current;
}
- const Vertex *vertex() const {
+ const Vertex *vertex() const
+ {
return m_current->vertex;
}
@@ -1616,22 +1748,25 @@ public:
const Edge *m_current;
};
- ConstEdgeIterator edges() const {
+ ConstEdgeIterator edges() const
+ {
return ConstEdgeIterator(edge);
}
- ConstEdgeIterator edges(const Edge *e) const {
+ ConstEdgeIterator edges(const Edge *e) const
+ {
xaDebugAssert(contains(e));
return ConstEdgeIterator(e);
}
};
/// Simple half edge mesh designed for dynamic mesh manipulation.
-class Mesh {
+class Mesh
+{
public:
- Mesh() :
- m_colocalVertexCount(0) {}
+ Mesh() : m_colocalVertexCount(0) {}
- Mesh(const Mesh *mesh) {
+ Mesh(const Mesh *mesh)
+ {
// Copy mesh vertices.
const uint32_t vertexCount = mesh->vertexCount();
m_vertexArray.resize(vertexCount);
@@ -1659,11 +1794,13 @@ public:
}
}
- ~Mesh() {
+ ~Mesh()
+ {
clear();
}
- void clear() {
+ void clear()
+ {
for (size_t i = 0; i < m_vertexArray.size(); i++)
delete m_vertexArray[i];
m_vertexArray.clear();
@@ -1676,7 +1813,8 @@ public:
m_faceArray.clear();
}
- Vertex *addVertex(const Vector3 &pos) {
+ Vertex *addVertex(const Vector3 &pos)
+ {
xaDebugAssert(isFinite(pos));
Vertex *v = new Vertex(m_vertexArray.size());
v->pos = pos;
@@ -1685,7 +1823,8 @@ public:
}
/// Link colocal vertices based on geometric location only.
- void linkColocals() {
+ void linkColocals()
+ {
xaPrint("--- Linking colocals:\n");
const uint32_t vertexCount = this->vertexCount();
std::unordered_map<Vector3, Vertex *, Hash<Vector3>, Equal<Vector3> > vertexMap;
@@ -1704,7 +1843,8 @@ public:
// @@ Remove duplicated vertices? or just leave them as colocals?
}
- void linkColocalsWithCanonicalMap(const std::vector<uint32_t> &canonicalMap) {
+ void linkColocalsWithCanonicalMap(const std::vector<uint32_t> &canonicalMap)
+ {
xaPrint("--- Linking colocals:\n");
uint32_t vertexMapSize = 0;
for (uint32_t i = 0; i < canonicalMap.size(); i++) {
@@ -1728,13 +1868,15 @@ public:
xaPrint("--- %d vertex positions.\n", m_colocalVertexCount);
}
- Face *addFace() {
+ Face *addFace()
+ {
Face *f = new Face(m_faceArray.size());
m_faceArray.push_back(f);
return f;
}
- Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2) {
+ Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2)
+ {
uint32_t indexArray[3];
indexArray[0] = v0;
indexArray[1] = v1;
@@ -1742,63 +1884,8 @@ public:
return addFace(indexArray, 3, 0, 3);
}
- Face *addUniqueFace(uint32_t v0, uint32_t v1, uint32_t v2) {
-
- int base_vertex = m_vertexArray.size();
-
- uint32_t ids[3] = { v0, v1, v2 };
-
- Vector3 base[3] = {
- m_vertexArray[v0]->pos,
- m_vertexArray[v1]->pos,
- m_vertexArray[v2]->pos,
- };
-
- //make sure its not a degenerate
- bool degenerate = distanceSquared(base[0], base[1]) < NV_EPSILON || distanceSquared(base[0], base[2]) < NV_EPSILON || distanceSquared(base[1], base[2]) < NV_EPSILON;
- xaDebugAssert(!degenerate);
-
- float min_x = 0;
-
- for (int i = 0; i < 3; i++) {
- if (i == 0 || m_vertexArray[v0]->pos.x < min_x) {
- min_x = m_vertexArray[v0]->pos.x;
- }
- }
-
- float max_x = 0;
-
- for (int j = 0; j < m_vertexArray.size(); j++) {
- if (j == 0 || m_vertexArray[j]->pos.x > max_x) { //vertex already exists
- max_x = m_vertexArray[j]->pos.x;
- }
- }
-
- //separate from everything else, in x axis
- for (int i = 0; i < 3; i++) {
-
- base[i].x -= min_x;
- base[i].x += max_x + 10.0;
- }
-
- for (int i = 0; i < 3; i++) {
- Vertex *v = new Vertex(m_vertexArray.size());
- v->pos = base[i];
- v->nor = m_vertexArray[ids[i]]->nor,
- v->tex = m_vertexArray[ids[i]]->tex,
-
- v->original_id = ids[i];
- m_vertexArray.push_back(v);
- }
-
- uint32_t indexArray[3];
- indexArray[0] = base_vertex + 0;
- indexArray[1] = base_vertex + 1;
- indexArray[2] = base_vertex + 2;
- return addFace(indexArray, 3, 0, 3);
- }
-
- Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) {
+ Face *addFace(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3)
+ {
uint32_t indexArray[4];
indexArray[0] = v0;
indexArray[1] = v1;
@@ -1807,15 +1894,18 @@ public:
return addFace(indexArray, 4, 0, 4);
}
- Face *addFace(const std::vector<uint32_t> &indexArray) {
+ Face *addFace(const std::vector<uint32_t> &indexArray)
+ {
return addFace(indexArray, 0, indexArray.size());
}
- Face *addFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num) {
+ Face *addFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num)
+ {
return addFace(indexArray.data(), (uint32_t)indexArray.size(), first, num);
}
- Face *addFace(const uint32_t *indexArray, uint32_t indexCount, uint32_t first, uint32_t num) {
+ Face *addFace(const uint32_t *indexArray, uint32_t indexCount, uint32_t first, uint32_t num)
+ {
xaDebugAssert(first < indexCount);
xaDebugAssert(num <= indexCount - first);
xaDebugAssert(num > 2);
@@ -1830,10 +1920,8 @@ public:
current = addEdge(indexArray[first + i], indexArray[first + i + 1]);
xaAssert(current != NULL && current->face == NULL);
current->face = f;
- if (last != NULL)
- last->setNext(current);
- else
- firstEdge = current;
+ if (last != NULL) last->setNext(current);
+ else firstEdge = current;
last = current;
}
current = addEdge(indexArray[first + num - 1], indexArray[first]);
@@ -1849,7 +1937,8 @@ public:
// These functions disconnect the given element from the mesh and delete it.
// @@ We must always disconnect edge pairs simultaneously.
- void disconnect(Edge *edge) {
+ void disconnect(Edge *edge)
+ {
xaDebugAssert(edge != NULL);
// Remove from edge list.
if ((edge->id & 1) == 0) {
@@ -1905,13 +1994,15 @@ public:
}
}
- void remove(Edge *edge) {
+ void remove(Edge *edge)
+ {
xaDebugAssert(edge != NULL);
disconnect(edge);
delete edge;
}
- void remove(Vertex *vertex) {
+ void remove(Vertex *vertex)
+ {
xaDebugAssert(vertex != NULL);
// Remove from vertex list.
m_vertexArray[vertex->id] = NULL;
@@ -1929,7 +2020,8 @@ public:
delete vertex;
}
- void remove(Face *face) {
+ void remove(Face *face)
+ {
xaDebugAssert(face != NULL);
// Remove from face list.
m_faceArray[face->id] = NULL;
@@ -1943,7 +2035,8 @@ public:
}
// Triangulate in place.
- void triangulate() {
+ void triangulate()
+ {
bool all_triangles = true;
const uint32_t faceCount = m_faceArray.size();
for (uint32_t f = 0; f < faceCount; f++) {
@@ -1984,7 +2077,8 @@ public:
}
/// Link boundary edges once the mesh has been created.
- void linkBoundary() {
+ void linkBoundary()
+ {
xaPrint("--- Linking boundaries:\n");
int num = 0;
// Create boundary edges.
@@ -2058,7 +2152,7 @@ public:
if (t > 0.0f + NV_EPSILON && t < 1.0f - NV_EPSILON) {
xaDebugAssert(equal(lerp(x1, x2, t), x0));
Vertex *splitVertex = splitBoundaryEdge(edge, t, x0);
- vertex->linkColocal(splitVertex); // @@ Should we do this here?
+ vertex->linkColocal(splitVertex); // @@ Should we do this here?
splitCount++;
}
}
@@ -2071,59 +2165,70 @@ public:
}
// Vertices
- uint32_t vertexCount() const {
+ uint32_t vertexCount() const
+ {
return m_vertexArray.size();
}
- const Vertex *vertexAt(int i) const {
+ const Vertex *vertexAt(int i) const
+ {
return m_vertexArray[i];
}
- Vertex *vertexAt(int i) {
+ Vertex *vertexAt(int i)
+ {
return m_vertexArray[i];
}
- uint32_t colocalVertexCount() const {
+ uint32_t colocalVertexCount() const
+ {
return m_colocalVertexCount;
}
// Faces
- uint32_t faceCount() const {
+ uint32_t faceCount() const
+ {
return m_faceArray.size();
}
- const Face *faceAt(int i) const {
+ const Face *faceAt(int i) const
+ {
return m_faceArray[i];
}
- Face *faceAt(int i) {
+ Face *faceAt(int i)
+ {
return m_faceArray[i];
}
// Edges
- uint32_t edgeCount() const {
+ uint32_t edgeCount() const
+ {
return m_edgeArray.size();
}
- const Edge *edgeAt(int i) const {
+ const Edge *edgeAt(int i) const
+ {
return m_edgeArray[i];
}
- Edge *edgeAt(int i) {
+ Edge *edgeAt(int i)
+ {
return m_edgeArray[i];
}
class ConstVertexIterator;
- class VertexIterator {
+ class VertexIterator
+ {
friend class ConstVertexIterator;
-
public:
- VertexIterator(Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
+ VertexIterator(Mesh *mesh) : m_mesh(mesh), m_current(0) { }
- virtual void advance() {
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->vertexCount();
}
- virtual Vertex *current() const {
+ virtual Vertex *current() const
+ {
return m_mesh->vertexAt(m_current);
}
@@ -2131,26 +2236,27 @@ public:
halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- VertexIterator vertices() {
+ VertexIterator vertices()
+ {
return VertexIterator(this);
}
- class ConstVertexIterator {
+ class ConstVertexIterator
+ {
public:
- ConstVertexIterator(const Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
- ConstVertexIterator(class VertexIterator &it) :
- m_mesh(it.m_mesh),
- m_current(it.m_current) {}
-
- virtual void advance() {
+ ConstVertexIterator(const Mesh *mesh) : m_mesh(mesh), m_current(0) { }
+ ConstVertexIterator(class VertexIterator &it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
+
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->vertexCount();
}
- virtual const Vertex *current() const {
+ virtual const Vertex *current() const
+ {
return m_mesh->vertexAt(m_current);
}
@@ -2158,27 +2264,29 @@ public:
const halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- ConstVertexIterator vertices() const {
+ ConstVertexIterator vertices() const
+ {
return ConstVertexIterator(this);
}
class ConstFaceIterator;
- class FaceIterator {
+ class FaceIterator
+ {
friend class ConstFaceIterator;
-
public:
- FaceIterator(Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
+ FaceIterator(Mesh *mesh) : m_mesh(mesh), m_current(0) { }
- virtual void advance() {
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->faceCount();
}
- virtual Face *current() const {
+ virtual Face *current() const
+ {
return m_mesh->faceAt(m_current);
}
@@ -2186,26 +2294,27 @@ public:
halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- FaceIterator faces() {
+ FaceIterator faces()
+ {
return FaceIterator(this);
}
- class ConstFaceIterator {
+ class ConstFaceIterator
+ {
public:
- ConstFaceIterator(const Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
- ConstFaceIterator(const FaceIterator &it) :
- m_mesh(it.m_mesh),
- m_current(it.m_current) {}
-
- virtual void advance() {
+ ConstFaceIterator(const Mesh *mesh) : m_mesh(mesh), m_current(0) { }
+ ConstFaceIterator(const FaceIterator &it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
+
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->faceCount();
}
- virtual const Face *current() const {
+ virtual const Face *current() const
+ {
return m_mesh->faceAt(m_current);
}
@@ -2213,27 +2322,29 @@ public:
const halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- ConstFaceIterator faces() const {
+ ConstFaceIterator faces() const
+ {
return ConstFaceIterator(this);
}
class ConstEdgeIterator;
- class EdgeIterator {
+ class EdgeIterator
+ {
friend class ConstEdgeIterator;
-
public:
- EdgeIterator(Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
+ EdgeIterator(Mesh *mesh) : m_mesh(mesh), m_current(0) { }
- virtual void advance() {
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->edgeCount();
}
- virtual Edge *current() const {
+ virtual Edge *current() const
+ {
return m_mesh->edgeAt(m_current);
}
@@ -2241,26 +2352,27 @@ public:
halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- EdgeIterator edges() {
+ EdgeIterator edges()
+ {
return EdgeIterator(this);
}
- class ConstEdgeIterator {
+ class ConstEdgeIterator
+ {
public:
- ConstEdgeIterator(const Mesh *mesh) :
- m_mesh(mesh),
- m_current(0) {}
- ConstEdgeIterator(const EdgeIterator &it) :
- m_mesh(it.m_mesh),
- m_current(it.m_current) {}
-
- virtual void advance() {
+ ConstEdgeIterator(const Mesh *mesh) : m_mesh(mesh), m_current(0) { }
+ ConstEdgeIterator(const EdgeIterator &it) : m_mesh(it.m_mesh), m_current(it.m_current) { }
+
+ virtual void advance()
+ {
m_current++;
}
- virtual bool isDone() const {
+ virtual bool isDone() const
+ {
return m_current == m_mesh->edgeCount();
}
- virtual const Edge *current() const {
+ virtual const Edge *current() const
+ {
return m_mesh->edgeAt(m_current);
}
@@ -2268,13 +2380,15 @@ public:
const halfedge::Mesh *m_mesh;
uint32_t m_current;
};
- ConstEdgeIterator edges() const {
+ ConstEdgeIterator edges() const
+ {
return ConstEdgeIterator(this);
}
// @@ Add half-edge iterator.
- bool isValid() const {
+ bool isValid() const
+ {
// Make sure all edges are valid.
const uint32_t edgeCount = m_edgeArray.size();
for (uint32_t e = 0; e < edgeCount; e++) {
@@ -2300,9 +2414,11 @@ public:
}
// Error status:
-
- struct ErrorCode {
- enum Enum {
+
+ struct ErrorCode
+ {
+ enum Enum
+ {
AlreadyAddedEdge,
DegenerateColocalEdge,
DegenerateEdge,
@@ -2316,11 +2432,13 @@ public:
private:
// Return true if the face can be added to the manifold mesh.
- bool canAddFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num) const {
+ bool canAddFace(const std::vector<uint32_t> &indexArray, uint32_t first, uint32_t num) const
+ {
return canAddFace(indexArray.data(), first, num);
}
- bool canAddFace(const uint32_t *indexArray, uint32_t first, uint32_t num) const {
+ bool canAddFace(const uint32_t *indexArray, uint32_t first, uint32_t num) const
+ {
for (uint32_t j = num - 1, i = 0; i < num; j = i++) {
if (!canAddEdge(indexArray[first + j], indexArray[first + i])) {
errorIndex0 = indexArray[first + j];
@@ -2347,7 +2465,8 @@ private:
}
// Return true if the edge doesn't exist or doesn't have any adjacent face.
- bool canAddEdge(uint32_t i, uint32_t j) const {
+ bool canAddEdge(uint32_t i, uint32_t j) const
+ {
if (i == j) {
// Skip degenerate edges.
errorCode = ErrorCode::DegenerateEdge;
@@ -2373,7 +2492,8 @@ private:
return true;
}
- Edge *addEdge(uint32_t i, uint32_t j) {
+ Edge *addEdge(uint32_t i, uint32_t j)
+ {
xaAssert(i != j);
Edge *edge = findEdge(i, j);
if (edge != NULL) {
@@ -2406,7 +2526,8 @@ private:
}
/// Find edge, test all colocals.
- Edge *findEdge(uint32_t i, uint32_t j) const {
+ Edge *findEdge(uint32_t i, uint32_t j) const
+ {
Edge *edge = NULL;
const Vertex *v0 = vertexAt(i);
const Vertex *v1 = vertexAt(j);
@@ -2418,9 +2539,9 @@ private:
auto edgeIt = m_edgeMap.find(key);
if (edgeIt != m_edgeMap.end())
edge = (*edgeIt).second;
-#if !defined(_DEBUG)
+ #if !defined(_DEBUG)
if (edge != NULL) return edge;
-#endif
+ #endif
} else {
// Make sure that only one edge is found.
xaDebugAssert(m_edgeMap.find(key) == m_edgeMap.end());
@@ -2431,7 +2552,8 @@ private:
}
/// Link this boundary edge.
- void linkBoundaryEdge(Edge *edge) {
+ void linkBoundaryEdge(Edge *edge)
+ {
xaAssert(edge->face == NULL);
// Make sure next pointer has not been set. @@ We want to be able to relink boundary edges after mesh changes.
Edge *next = edge;
@@ -2451,7 +2573,8 @@ private:
}
}
- Vertex *splitBoundaryEdge(Edge *edge, float t, const Vector3 &pos) {
+ Vertex *splitBoundaryEdge(Edge *edge, float t, const Vector3 &pos)
+ {
/*
We want to go from this configuration:
@@ -2521,19 +2644,18 @@ private:
std::vector<Edge *> m_edgeArray;
std::vector<Face *> m_faceArray;
- struct Key {
+ struct Key
+ {
Key() {}
- Key(const Key &k) :
- p0(k.p0),
- p1(k.p1) {}
- Key(uint32_t v0, uint32_t v1) :
- p0(v0),
- p1(v1) {}
- void operator=(const Key &k) {
+ Key(const Key &k) : p0(k.p0), p1(k.p1) {}
+ Key(uint32_t v0, uint32_t v1) : p0(v0), p1(v1) {}
+ void operator=(const Key &k)
+ {
p0 = k.p0;
p1 = k.p1;
}
- bool operator==(const Key &k) const {
+ bool operator==(const Key &k) const
+ {
return p0 == k.p0 && p1 == k.p1;
}
@@ -2546,48 +2668,54 @@ private:
uint32_t m_colocalVertexCount;
};
-class MeshTopology {
+class MeshTopology
+{
public:
- MeshTopology(const Mesh *mesh) {
+ MeshTopology(const Mesh *mesh)
+ {
buildTopologyInfo(mesh);
}
/// Determine if the mesh is connected.
- bool isConnected() const {
+ bool isConnected() const
+ {
return m_connectedCount == 1;
}
/// Determine if the mesh is closed. (Each edge is shared by two faces)
- bool isClosed() const {
+ bool isClosed() const
+ {
return m_boundaryCount == 0;
}
/// Return true if the mesh has the topology of a disk.
- bool isDisk() const {
- return isConnected() && m_boundaryCount == 1 /* && m_eulerNumber == 1*/;
+ bool isDisk() const
+ {
+ return isConnected() && m_boundaryCount == 1/* && m_eulerNumber == 1*/;
}
private:
- void buildTopologyInfo(const Mesh *mesh) {
+ void buildTopologyInfo(const Mesh *mesh)
+ {
const uint32_t vertexCount = mesh->colocalVertexCount();
const uint32_t faceCount = mesh->faceCount();
const uint32_t edgeCount = mesh->edgeCount();
- xaPrint("--- Building mesh topology:\n");
+ xaPrint( "--- Building mesh topology:\n" );
std::vector<uint32_t> stack(faceCount);
BitArray bitFlags(faceCount);
bitFlags.clearAll();
// Compute connectivity.
- xaPrint("--- Computing connectivity.\n");
+ xaPrint( "--- Computing connectivity.\n" );
m_connectedCount = 0;
- for (uint32_t f = 0; f < faceCount; f++) {
- if (bitFlags.bitAt(f) == false) {
+ for (uint32_t f = 0; f < faceCount; f++ ) {
+ if ( bitFlags.bitAt(f) == false ) {
m_connectedCount++;
- stack.push_back(f);
- while (!stack.empty()) {
+ stack.push_back( f );
+ while ( !stack.empty() ) {
const uint32_t top = stack.back();
xaAssert(top != uint32_t(~0));
stack.pop_back();
- if (bitFlags.bitAt(top) == false) {
+ if ( bitFlags.bitAt(top) == false ) {
bitFlags.setBitAt(top);
const Face *face = mesh->faceAt(top);
const Edge *firstEdge = face->edge;
@@ -2604,9 +2732,9 @@ private:
}
}
xaAssert(stack.empty());
- xaPrint("--- %d connected components.\n", m_connectedCount);
+ xaPrint( "--- %d connected components.\n", m_connectedCount );
// Count boundary loops.
- xaPrint("--- Counting boundary loops.\n");
+ xaPrint( "--- Counting boundary loops.\n" );
m_boundaryCount = 0;
bitFlags.resize(edgeCount);
bitFlags.clearAll();
@@ -2625,13 +2753,13 @@ private:
} while (startEdge != edge);
}
}
- xaPrint("--- %d boundary loops found.\n", m_boundaryCount);
+ xaPrint("--- %d boundary loops found.\n", m_boundaryCount );
// Compute euler number.
m_eulerNumber = vertexCount - edgeCount + faceCount;
xaPrint("--- Euler number: %d.\n", m_eulerNumber);
// Compute genus. (only valid on closed connected surfaces)
m_genus = -1;
- if (isClosed() && isConnected()) {
+ if ( isClosed() && isConnected() ) {
m_genus = (2 - m_eulerNumber) / 2;
xaPrint("--- Genus: %d.\n", m_genus);
}
@@ -2651,7 +2779,8 @@ private:
int m_genus;
};
-float computeSurfaceArea(const halfedge::Mesh *mesh) {
+float computeSurfaceArea(const halfedge::Mesh *mesh)
+{
float area = 0;
for (halfedge::Mesh::ConstFaceIterator it(mesh->faces()); !it.isDone(); it.advance()) {
const halfedge::Face *face = it.current();
@@ -2661,7 +2790,8 @@ float computeSurfaceArea(const halfedge::Mesh *mesh) {
return area;
}
-float computeParametricArea(const halfedge::Mesh *mesh) {
+float computeParametricArea(const halfedge::Mesh *mesh)
+{
float area = 0;
for (halfedge::Mesh::ConstFaceIterator it(mesh->faces()); !it.isDone(); it.advance()) {
const halfedge::Face *face = it.current();
@@ -2670,7 +2800,8 @@ float computeParametricArea(const halfedge::Mesh *mesh) {
return area;
}
-uint32_t countMeshTriangles(const Mesh *mesh) {
+uint32_t countMeshTriangles(const Mesh *mesh)
+{
const uint32_t faceCount = mesh->faceCount();
uint32_t triangleCount = 0;
for (uint32_t f = 0; f < faceCount; f++) {
@@ -2682,7 +2813,8 @@ uint32_t countMeshTriangles(const Mesh *mesh) {
return triangleCount;
}
-Mesh *unifyVertices(const Mesh *inputMesh) {
+Mesh *unifyVertices(const Mesh *inputMesh)
+{
Mesh *mesh = new Mesh;
// Only add the first colocal.
const uint32_t vertexCount = inputMesh->vertexCount();
@@ -2709,15 +2841,17 @@ Mesh *unifyVertices(const Mesh *inputMesh) {
return mesh;
}
-static bool pointInTriangle(const Vector2 &p, const Vector2 &a, const Vector2 &b, const Vector2 &c) {
+static bool pointInTriangle(const Vector2 &p, const Vector2 &a, const Vector2 &b, const Vector2 &c)
+{
return triangleArea(a, b, p) >= 0.00001f &&
- triangleArea(b, c, p) >= 0.00001f &&
- triangleArea(c, a, p) >= 0.00001f;
+ triangleArea(b, c, p) >= 0.00001f &&
+ triangleArea(c, a, p) >= 0.00001f;
}
// This is doing a simple ear-clipping algorithm that skips invalid triangles. Ideally, we should
// also sort the ears by angle, start with the ones that have the smallest angle and proceed in order.
-Mesh *triangulate(const Mesh *inputMesh) {
+Mesh *triangulate(const Mesh *inputMesh)
+{
Mesh *mesh = new Mesh;
// Add all vertices.
const uint32_t vertexCount = inputMesh->vertexCount();
@@ -2781,12 +2915,6 @@ Mesh *triangulate(const Mesh *inputMesh) {
Vector2 p0 = polygonPoints[i0];
Vector2 p1 = polygonPoints[i1];
Vector2 p2 = polygonPoints[i2];
-
- bool degenerate = distance(p0, p1) < NV_EPSILON || distance(p0, p2) < NV_EPSILON || distance(p1, p2) < NV_EPSILON;
- if (degenerate) {
- continue;
- }
-
float d = clamp(dot(p0 - p1, p2 - p1) / (length(p0 - p1) * length(p2 - p1)), -1.0f, 1.0f);
float angle = acosf(d);
float area = triangleArea(p0, p1, p2);
@@ -2810,9 +2938,6 @@ Mesh *triangulate(const Mesh *inputMesh) {
}
}
}
- if (!bestIsValid)
- break;
-
xaDebugAssert(minAngle <= 2 * PI);
// Clip best ear:
uint32_t i0 = (bestEar + size - 1) % size;
@@ -2835,59 +2960,66 @@ Mesh *triangulate(const Mesh *inputMesh) {
} // namespace halfedge
/// Mersenne twister random number generator.
-class MTRand {
+class MTRand
+{
public:
enum time_e { Time };
- enum { N = 624 }; // length of state vector
+ enum { N = 624 }; // length of state vector
enum { M = 397 };
/// Constructor that uses the current time as the seed.
- MTRand(time_e) {
- seed((uint32_t)time(NULL));
+ MTRand( time_e )
+ {
+ seed((uint32_t )time(NULL));
}
/// Constructor that uses the given seed.
- MTRand(uint32_t s = 0) {
+ MTRand( uint32_t s = 0 )
+ {
seed(s);
}
/// Provide a new seed.
- void seed(uint32_t s) {
+ void seed( uint32_t s )
+ {
initialize(s);
reload();
}
/// Get a random number between 0 - 65536.
- uint32_t get() {
+ uint32_t get()
+ {
// Pull a 32-bit integer from the generator state
// Every other access function simply transforms the numbers extracted here
- if (left == 0) {
+ if ( left == 0 ) {
reload();
}
left--;
uint32_t s1;
s1 = *next++;
s1 ^= (s1 >> 11);
- s1 ^= (s1 << 7) & 0x9d2c5680U;
+ s1 ^= (s1 << 7) & 0x9d2c5680U;
s1 ^= (s1 << 15) & 0xefc60000U;
- return (s1 ^ (s1 >> 18));
+ return ( s1 ^ (s1 >> 18) );
};
/// Get a random number on [0, max] interval.
- uint32_t getRange(uint32_t max) {
+ uint32_t getRange( uint32_t max )
+ {
if (max == 0) return 0;
if (max == NV_UINT32_MAX) return get();
- const uint32_t np2 = nextPowerOfTwo(max + 1); // @@ This fails if max == NV_UINT32_MAX
+ const uint32_t np2 = nextPowerOfTwo( max + 1 ); // @@ This fails if max == NV_UINT32_MAX
const uint32_t mask = np2 - 1;
uint32_t n;
do {
n = get() & mask;
- } while (n > max);
+ } while ( n > max );
return n;
}
private:
- void initialize(uint32_t seed) {
+ void initialize( uint32_t seed )
+ {
// Initialize generator state with seed
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
// In previous versions, most significant bits (MSBs) of the seed affect
@@ -2896,44 +3028,50 @@ private:
uint32_t *r = state;
int i = 1;
*s++ = seed & 0xffffffffUL;
- for (; i < N; ++i) {
- *s++ = (1812433253UL * (*r ^ (*r >> 30)) + i) & 0xffffffffUL;
+ for ( ; i < N; ++i ) {
+ *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
r++;
}
}
- void reload() {
+ void reload()
+ {
// Generate N new values in state
// Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
uint32_t *p = state;
int i;
- for (i = N - M; i--; ++p)
- *p = twist(p[M], p[0], p[1]);
- for (i = M; --i; ++p)
- *p = twist(p[M - N], p[0], p[1]);
- *p = twist(p[M - N], p[0], state[0]);
+ for ( i = N - M; i--; ++p )
+ *p = twist( p[M], p[0], p[1] );
+ for ( i = M; --i; ++p )
+ *p = twist( p[M - N], p[0], p[1] );
+ *p = twist( p[M - N], p[0], state[0] );
left = N, next = state;
}
- uint32_t hiBit(uint32_t u) const {
+ uint32_t hiBit( uint32_t u ) const
+ {
return u & 0x80000000U;
}
- uint32_t loBit(uint32_t u) const {
+ uint32_t loBit( uint32_t u ) const
+ {
return u & 0x00000001U;
}
- uint32_t loBits(uint32_t u) const {
+ uint32_t loBits( uint32_t u ) const
+ {
return u & 0x7fffffffU;
}
- uint32_t mixBits(uint32_t u, uint32_t v) const {
+ uint32_t mixBits( uint32_t u, uint32_t v ) const
+ {
return hiBit(u) | loBits(v);
}
- uint32_t twist(uint32_t m, uint32_t s0, uint32_t s1) const {
+ uint32_t twist( uint32_t m, uint32_t s0, uint32_t s1 ) const
+ {
return m ^ (mixBits(s0, s1) >> 1) ^ ((~loBit(s1) + 1) & 0x9908b0dfU);
}
- uint32_t state[N]; // internal state
- uint32_t *next; // next value to get from state
- int left; // number of values left before reload needed
+ uint32_t state[N]; // internal state
+ uint32_t *next; // next value to get from state
+ int left; // number of values left before reload needed
};
namespace morton {
@@ -2941,50 +3079,59 @@ namespace morton {
// http://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
// Inverse of part1By1 - "delete" all odd-indexed bits
-uint32_t compact1By1(uint32_t x) {
- x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
- x = (x ^ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
- x = (x ^ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
- x = (x ^ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
- x = (x ^ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
+uint32_t compact1By1(uint32_t x)
+{
+ x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
+ x = (x ^ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
+ x = (x ^ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
+ x = (x ^ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
+ x = (x ^ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
return x;
}
// Inverse of part1By2 - "delete" all bits not at positions divisible by 3
-uint32_t compact1By2(uint32_t x) {
- x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
- x = (x ^ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
- x = (x ^ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
- x = (x ^ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
+uint32_t compact1By2(uint32_t x)
+{
+ x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0
+ x = (x ^ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10
+ x = (x ^ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210
+ x = (x ^ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210
x = (x ^ (x >> 16)) & 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210
return x;
}
-uint32_t decodeMorton2X(uint32_t code) {
+uint32_t decodeMorton2X(uint32_t code)
+{
return compact1By1(code >> 0);
}
-uint32_t decodeMorton2Y(uint32_t code) {
+uint32_t decodeMorton2Y(uint32_t code)
+{
return compact1By1(code >> 1);
}
-uint32_t decodeMorton3X(uint32_t code) {
+uint32_t decodeMorton3X(uint32_t code)
+{
return compact1By2(code >> 0);
}
-uint32_t decodeMorton3Y(uint32_t code) {
+uint32_t decodeMorton3Y(uint32_t code)
+{
return compact1By2(code >> 1);
}
-uint32_t decodeMorton3Z(uint32_t code) {
+uint32_t decodeMorton3Z(uint32_t code)
+{
return compact1By2(code >> 2);
}
} // namespace morton
// A simple, dynamic proximity grid based on Jon's code.
// Instead of storing pointers here I store indices.
-struct ProximityGrid {
- void init(const Box &box, uint32_t count) {
+struct ProximityGrid
+{
+ void init(const Box &box, uint32_t count)
+ {
cellArray.clear();
// Determine grid size.
float cellWidth;
@@ -3021,19 +3168,23 @@ struct ProximityGrid {
corner = box.minCorner; // @@ Align grid better?
}
- int index_x(float x) const {
- return clamp(ftoi_floor((x - corner.x) * invCellSize.x), 0, sx - 1);
+ int index_x(float x) const
+ {
+ return clamp(ftoi_floor((x - corner.x) * invCellSize.x), 0, sx - 1);
}
- int index_y(float y) const {
- return clamp(ftoi_floor((y - corner.y) * invCellSize.y), 0, sy - 1);
+ int index_y(float y) const
+ {
+ return clamp(ftoi_floor((y - corner.y) * invCellSize.y), 0, sy - 1);
}
- int index_z(float z) const {
- return clamp(ftoi_floor((z - corner.z) * invCellSize.z), 0, sz - 1);
+ int index_z(float z) const
+ {
+ return clamp(ftoi_floor((z - corner.z) * invCellSize.z), 0, sz - 1);
}
- int index(int x, int y, int z) const {
+ int index(int x, int y, int z) const
+ {
xaDebugAssert(x >= 0 && x < sx);
xaDebugAssert(y >= 0 && y < sy);
xaDebugAssert(z >= 0 && z < sz);
@@ -3042,7 +3193,8 @@ struct ProximityGrid {
return idx;
}
- uint32_t mortonCount() const {
+ uint32_t mortonCount() const
+ {
uint64_t s = uint64_t(max3(sx, sy, sz));
s = nextPowerOfTwo(s);
if (s > 1024) {
@@ -3051,7 +3203,8 @@ struct ProximityGrid {
return uint32_t(s * s * s);
}
- int mortonIndex(uint32_t code) const {
+ int mortonIndex(uint32_t code) const
+ {
uint32_t x, y, z;
uint32_t s = uint32_t(max3(sx, sy, sz));
if (s > 1024) {
@@ -3084,7 +3237,8 @@ struct ProximityGrid {
return index(x, y, z);
}
- void add(const Vector3 &pos, uint32_t key) {
+ void add(const Vector3 &pos, uint32_t key)
+ {
int x = index_x(pos.x);
int y = index_y(pos.y);
int z = index_z(pos.z);
@@ -3094,7 +3248,8 @@ struct ProximityGrid {
// Gather all points inside the given sphere.
// Radius is assumed to be small, so we don't bother culling the cells.
- void gather(const Vector3 &position, float radius, std::vector<uint32_t> &indexArray) {
+ void gather(const Vector3 &position, float radius, std::vector<uint32_t> &indexArray)
+ {
int x0 = index_x(position.x - radius);
int x1 = index_x(position.x + radius);
int y0 = index_y(position.y - radius);
@@ -3125,26 +3280,25 @@ struct ProximityGrid {
// Based on Pierre Terdiman's and Michael Herf's source code.
// http://www.codercorner.com/RadixSortRevisited.htm
// http://www.stereopsis.com/radix.html
-class RadixSort {
+class RadixSort
+{
public:
- RadixSort() :
- m_size(0),
- m_ranks(NULL),
- m_ranks2(NULL),
- m_validRanks(false) {}
- ~RadixSort() {
+ RadixSort() : m_size(0), m_ranks(NULL), m_ranks2(NULL), m_validRanks(false) {}
+ ~RadixSort()
+ {
// Release everything
free(m_ranks2);
free(m_ranks);
}
- RadixSort &sort(const float *input, uint32_t count) {
+ RadixSort &sort(const float *input, uint32_t count)
+ {
if (input == NULL || count == 0) return *this;
// Resize lists if needed
if (count != m_size) {
if (count > m_size) {
- m_ranks2 = (uint32_t *)realloc(m_ranks2, sizeof(uint32_t) * count);
- m_ranks = (uint32_t *)realloc(m_ranks, sizeof(uint32_t) * count);
+ m_ranks2 = (uint32_t *)realloc(m_ranks2, sizeof(uint32_t ) * count);
+ m_ranks = (uint32_t *)realloc(m_ranks, sizeof(uint32_t ) * count);
}
m_size = count;
m_validRanks = false;
@@ -3164,16 +3318,19 @@ public:
return *this;
}
- RadixSort &sort(const std::vector<float> &input) {
+ RadixSort &sort(const std::vector<float> &input)
+ {
return sort(input.data(), input.size());
}
// Access to results. m_ranks is a list of indices in sorted order, i.e. in the order you may further process your data
- const uint32_t *ranks() const {
+ const uint32_t *ranks() const
+ {
xaDebugAssert(m_validRanks);
return m_ranks;
}
- uint32_t *ranks() {
+ uint32_t *ranks()
+ {
xaDebugAssert(m_validRanks);
return m_ranks;
}
@@ -3184,18 +3341,21 @@ private:
uint32_t *m_ranks2;
bool m_validRanks;
- void FloatFlip(uint32_t &f) {
+ void FloatFlip(uint32_t &f)
+ {
int32_t mask = (int32_t(f) >> 31) | 0x80000000; // Warren Hunt, Manchor Ko.
f ^= mask;
}
- void IFloatFlip(uint32_t &f) {
+ void IFloatFlip(uint32_t &f)
+ {
uint32_t mask = ((f >> 31) - 1) | 0x80000000; // Michael Herf.
f ^= mask;
}
- template <typename T>
- void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram) {
+ template<typename T>
+ void createHistograms(const T *buffer, uint32_t count, uint32_t *histogram)
+ {
const uint32_t bucketCount = sizeof(T); // (8 * sizeof(T)) / log2(radix)
// Init bucket pointers.
uint32_t *h[bucketCount];
@@ -3203,10 +3363,10 @@ private:
h[i] = histogram + 256 * i;
}
// Clear histograms.
- memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t));
+ memset(histogram, 0, 256 * bucketCount * sizeof(uint32_t ));
// @@ Add support for signed integers.
// Build histograms.
- const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
+ const uint8_t *p = (const uint8_t *)buffer; // @@ Does this break aliasing rules?
const uint8_t *pe = p + count * sizeof(T);
while (p != pe) {
h[0][*p++]++, h[1][*p++]++, h[2][*p++]++, h[3][*p++]++;
@@ -3221,8 +3381,8 @@ private:
}
}
- template <typename T>
- void insertionSort(const T *input, uint32_t count) {
+ template <typename T> void insertionSort(const T *input, uint32_t count)
+ {
if (!m_validRanks) {
m_ranks[0] = 0;
for (uint32_t i = 1; i != count; ++i) {
@@ -3252,8 +3412,8 @@ private:
}
}
- template <typename T>
- void radixSort(const T *input, uint32_t count) {
+ template <typename T> void radixSort(const T *input, uint32_t count)
+ {
const uint32_t P = sizeof(T); // pass count
// Allocate histograms & offsets on the stack
uint32_t histogram[256 * P];
@@ -3271,8 +3431,7 @@ private:
}
// Create offsets
link[0] = m_ranks2;
- for (uint32_t i = 1; i < 256; i++)
- link[i] = link[i - 1] + h[i - 1];
+ for (uint32_t i = 1; i < 256; i++) link[i] = link[i - 1] + h[i - 1];
// Perform Radix Sort
if (!m_validRanks) {
for (uint32_t i = 0; i < count; i++) {
@@ -3299,9 +3458,11 @@ private:
};
namespace raster {
-class ClippedTriangle {
+class ClippedTriangle
+{
public:
- ClippedTriangle(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c) {
+ ClippedTriangle(Vector2::Arg a, Vector2::Arg b, Vector2::Arg c)
+ {
m_numVertices = 3;
m_activeVertexBuffer = 0;
m_verticesA[0] = a;
@@ -3311,27 +3472,30 @@ public:
m_vertexBuffers[1] = m_verticesB;
}
- uint32_t vertexCount() {
+ uint32_t vertexCount()
+ {
return m_numVertices;
}
- const Vector2 *vertices() {
+ const Vector2 *vertices()
+ {
return m_vertexBuffers[m_activeVertexBuffer];
}
- void clipHorizontalPlane(float offset, float clipdirection) {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipHorizontalPlane(float offset, float clipdirection)
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dy2, dy1 = offset - v[0].y;
- int dy2in, dy1in = clipdirection * dy1 >= 0;
- uint32_t p = 0;
+ float dy2, dy1 = offset - v[0].y;
+ int dy2in, dy1in = clipdirection * dy1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
- dy2 = offset - v[k + 1].y;
+ dy2 = offset - v[k + 1].y;
dy2in = clipdirection * dy2 >= 0;
if (dy1in) v2[p++] = v[k];
- if (dy1in + dy2in == 1) { // not both in/out
+ if ( dy1in + dy2in == 1 ) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(v[k].x + dy1 * (dx / dy), offset);
@@ -3343,19 +3507,20 @@ public:
//for (uint32_t k=0; k<m_numVertices; k++) printf("(%f, %f)\n", v2[k].x, v2[k].y); printf("\n");
}
- void clipVerticalPlane(float offset, float clipdirection) {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void clipVerticalPlane(float offset, float clipdirection )
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
m_activeVertexBuffer ^= 1;
Vector2 *v2 = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
- float dx2, dx1 = offset - v[0].x;
- int dx2in, dx1in = clipdirection * dx1 >= 0;
- uint32_t p = 0;
+ float dx2, dx1 = offset - v[0].x;
+ int dx2in, dx1in = clipdirection * dx1 >= 0;
+ uint32_t p = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
dx2 = offset - v[k + 1].x;
dx2in = clipdirection * dx2 >= 0;
if (dx1in) v2[p++] = v[k];
- if (dx1in + dx2in == 1) { // not both in/out
+ if ( dx1in + dx2in == 1 ) { // not both in/out
float dx = v[k + 1].x - v[k].x;
float dy = v[k + 1].y - v[k].y;
v2[p++] = Vector2(offset, v[k].y + dx1 * (dy / dx));
@@ -3366,8 +3531,9 @@ public:
m_numVertices = p;
}
- void computeAreaCentroid() {
- Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
+ void computeAreaCentroid()
+ {
+ Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
m_area = 0;
float centroidx = 0, centroidy = 0;
@@ -3386,19 +3552,22 @@ public:
}
}
- void clipAABox(float x0, float y0, float x1, float y1) {
- clipVerticalPlane(x0, -1);
- clipHorizontalPlane(y0, -1);
- clipVerticalPlane(x1, 1);
- clipHorizontalPlane(y1, 1);
+ void clipAABox(float x0, float y0, float x1, float y1)
+ {
+ clipVerticalPlane ( x0, -1);
+ clipHorizontalPlane( y0, -1);
+ clipVerticalPlane ( x1, 1);
+ clipHorizontalPlane( y1, 1);
computeAreaCentroid();
}
- Vector2 centroid() {
+ Vector2 centroid()
+ {
return m_centroid;
}
- float area() {
+ float area()
+ {
return m_area;
}
@@ -3406,18 +3575,20 @@ private:
Vector2 m_verticesA[7 + 1];
Vector2 m_verticesB[7 + 1];
Vector2 *m_vertexBuffers[2];
- uint32_t m_numVertices;
- uint32_t m_activeVertexBuffer;
- float m_area;
+ uint32_t m_numVertices;
+ uint32_t m_activeVertexBuffer;
+ float m_area;
Vector2 m_centroid;
};
/// A callback to sample the environment. Return false to terminate rasterization.
-typedef bool (*SamplingCallback)(void *param, int x, int y, Vector3::Arg bar, Vector3::Arg dx, Vector3::Arg dy, float coverage);
+typedef bool (* SamplingCallback)(void *param, int x, int y, Vector3::Arg bar, Vector3::Arg dx, Vector3::Arg dy, float coverage);
/// A triangle for rasterization.
-struct Triangle {
- Triangle(Vector2::Arg v0, Vector2::Arg v1, Vector2::Arg v2, Vector3::Arg t0, Vector3::Arg t1, Vector3::Arg t2) {
+struct Triangle
+{
+ Triangle(Vector2::Arg v0, Vector2::Arg v1, Vector2::Arg v2, Vector3::Arg t0, Vector3::Arg t1, Vector3::Arg t2)
+ {
// Init vertices.
this->v1 = v0;
this->v2 = v2;
@@ -3437,7 +3608,8 @@ struct Triangle {
/// This method takes two edge vectors that form a basis, determines the
/// coordinates of the canonic vectors in that basis, and computes the
/// texture gradient that corresponds to those vectors.
- bool computeDeltas() {
+ bool computeDeltas()
+ {
Vector2 e0 = v3 - v1;
Vector2 e1 = v2 - v1;
Vector3 de0 = t3 - t1;
@@ -3446,16 +3618,17 @@ struct Triangle {
if (!std::isfinite(denom)) {
return false;
}
- float lambda1 = -e1.y * denom;
+ float lambda1 = - e1.y * denom;
float lambda2 = e0.y * denom;
float lambda3 = e1.x * denom;
- float lambda4 = -e0.x * denom;
+ float lambda4 = - e0.x * denom;
dx = de0 * lambda1 + de1 * lambda2;
dy = de0 * lambda3 + de1 * lambda4;
return true;
}
- bool draw(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param) {
+ bool draw(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param)
+ {
// 28.4 fixed-point coordinates
const int Y1 = ftoi_round(16.0f * v1.y);
const int Y2 = ftoi_round(16.0f * v2.y);
@@ -3479,10 +3652,10 @@ struct Triangle {
const int FDY31 = DY31 << 4;
int minx, miny, maxx, maxy;
if (enableScissors) {
- int frustumX0 = 0 << 4;
- int frustumY0 = 0 << 4;
- int frustumX1 = (int)extents.x << 4;
- int frustumY1 = (int)extents.y << 4;
+ int frustumX0 = 0 << 4;
+ int frustumY0 = 0 << 4;
+ int frustumX1 = (int)extents.x << 4;
+ int frustumY1 = (int)extents.y << 4;
// Bounding rectangle
minx = (std::max(min3(X1, X2, X3), frustumX0) + 0xF) >> 4;
miny = (std::max(min3(Y1, Y2, Y3), frustumY0) + 0xF) >> 4;
@@ -3586,26 +3759,27 @@ struct Triangle {
}
// extents has to be multiple of BK_SIZE!!
- bool drawAA(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param) {
- const float PX_INSIDE = 1.0f / sqrt(2.0f);
- const float PX_OUTSIDE = -1.0f / sqrt(2.0f);
+ bool drawAA(const Vector2 &extents, bool enableScissors, SamplingCallback cb, void *param)
+ {
+ const float PX_INSIDE = 1.0f/sqrt(2.0f);
+ const float PX_OUTSIDE = -1.0f/sqrt(2.0f);
const float BK_SIZE = 8;
- const float BK_INSIDE = sqrt(BK_SIZE * BK_SIZE / 2.0f);
- const float BK_OUTSIDE = -sqrt(BK_SIZE * BK_SIZE / 2.0f);
+ const float BK_INSIDE = sqrt(BK_SIZE*BK_SIZE/2.0f);
+ const float BK_OUTSIDE = -sqrt(BK_SIZE*BK_SIZE/2.0f);
float minx, miny, maxx, maxy;
if (enableScissors) {
// Bounding rectangle
minx = floorf(std::max(min3(v1.x, v2.x, v3.x), 0.0f));
miny = floorf(std::max(min3(v1.y, v2.y, v3.y), 0.0f));
- maxx = ceilf(std::min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
- maxy = ceilf(std::min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
+ maxx = ceilf( std::min(max3(v1.x, v2.x, v3.x), extents.x - 1.0f));
+ maxy = ceilf( std::min(max3(v1.y, v2.y, v3.y), extents.y - 1.0f));
} else {
// Bounding rectangle
minx = floorf(min3(v1.x, v2.x, v3.x));
miny = floorf(min3(v1.y, v2.y, v3.y));
- maxx = ceilf(max3(v1.x, v2.x, v3.x));
- maxy = ceilf(max3(v1.y, v2.y, v3.y));
+ maxx = ceilf( max3(v1.x, v2.x, v3.x));
+ maxy = ceilf( max3(v1.y, v2.y, v3.y));
}
// There's no reason to align the blocks to the viewport, instead we align them to the origin of the triangle bounds.
minx = floorf(minx);
@@ -3631,9 +3805,9 @@ struct Triangle {
float bC = C2 + n2.x * xc + n2.y * yc;
float cC = C3 + n3.x * xc + n3.y * yc;
// Skip block when outside an edge
- if ((aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE)) continue;
+ if ( (aC <= BK_OUTSIDE) || (bC <= BK_OUTSIDE) || (cC <= BK_OUTSIDE) ) continue;
// Accept whole block when totally covered
- if ((aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE)) {
+ if ( (aC >= BK_INSIDE) && (bC >= BK_INSIDE) && (cC >= BK_INSIDE) ) {
Vector3 texRow = t1 + dy * (y0 - v1.y) + dx * (x0 - v1.x);
for (float y = y0; y < y0 + BK_SIZE; y++) {
Vector3 tex = texRow;
@@ -3695,9 +3869,10 @@ struct Triangle {
return true;
}
- void flipBackface() {
+ void flipBackface()
+ {
// check if triangle is backfacing, if so, swap two vertices
- if (((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0) {
+ if ( ((v3.x - v1.x) * (v2.y - v1.y) - (v3.y - v1.y) * (v2.x - v1.x)) < 0 ) {
Vector2 hv = v1;
v1 = v2;
v2 = hv; // swap pos
@@ -3708,7 +3883,8 @@ struct Triangle {
}
// compute unit inward normals for each edge.
- void computeUnitInwardNormals() {
+ void computeUnitInwardNormals()
+ {
n1 = v1 - v2;
n1 = Vector2(-n1.y, n1.x);
n1 = n1 * (1.0f / sqrtf(n1.x * n1.x + n1.y * n1.y));
@@ -3732,13 +3908,15 @@ struct Triangle {
bool valid;
};
-enum Mode {
+enum Mode
+{
Mode_Nearest,
Mode_Antialiased
};
// Process the given triangle. Returns false if rasterization was interrupted by the callback.
-static bool drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[3], SamplingCallback cb, void *param) {
+static bool drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[3], SamplingCallback cb, void *param)
+{
Triangle tri(v[0], v[1], v[2], Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1));
// @@ It would be nice to have a conservative drawing mode that enlarges the triangle extents by one texel and is able to handle degenerate triangles.
// @@ Maybe the simplest thing to do would be raster triangle edges.
@@ -3754,7 +3932,8 @@ static bool drawTriangle(Mode mode, Vector2::Arg extents, bool enableScissors, c
}
// Process the given quad. Returns false if rasterization was interrupted by the callback.
-static bool drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[4], SamplingCallback cb, void *param) {
+static bool drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const Vector2 v[4], SamplingCallback cb, void *param)
+{
bool sign0 = triangleArea2(v[0], v[1], v[2]) > 0.0f;
bool sign1 = triangleArea2(v[0], v[2], v[3]) > 0.0f;
// Divide the quad into two non overlapping triangles.
@@ -3786,7 +3965,8 @@ static bool drawQuad(Mode mode, Vector2::Arg extents, bool enableScissors, const
// Full and sparse vector and matrix classes. BLAS subset.
// Pseudo-BLAS interface.
namespace sparse {
-enum Transpose {
+enum Transpose
+{
NoTransposed = 0,
Transposed = 1
};
@@ -3799,22 +3979,22 @@ enum Transpose {
* elements for each row of the matrix. As with the FullVector the
* dimension of the matrix is constant.
**/
-class Matrix {
+class Matrix
+{
public:
// An element of the sparse array.
- struct Coefficient {
- uint32_t x; // column
+ struct Coefficient
+ {
+ uint32_t x; // column
float v; // value
};
- Matrix(uint32_t d) :
- m_width(d) { m_array.resize(d); }
- Matrix(uint32_t w, uint32_t h) :
- m_width(w) { m_array.resize(h); }
- Matrix(const Matrix &m) :
- m_width(m.m_width) { m_array = m.m_array; }
+ Matrix(uint32_t d) : m_width(d) { m_array.resize(d); }
+ Matrix(uint32_t w, uint32_t h) : m_width(w) { m_array.resize(h); }
+ Matrix(const Matrix &m) : m_width(m.m_width) { m_array = m.m_array; }
- const Matrix &operator=(const Matrix &m) {
+ const Matrix &operator=(const Matrix &m)
+ {
xaAssert(width() == m.width());
xaAssert(height() == m.height());
m_array = m.m_array;
@@ -3826,9 +4006,10 @@ public:
bool isSquare() const { return width() == height(); }
// x is column, y is row
- float getCoefficient(uint32_t x, uint32_t y) const {
- xaDebugAssert(x < width());
- xaDebugAssert(y < height());
+ float getCoefficient(uint32_t x, uint32_t y) const
+ {
+ xaDebugAssert( x < width() );
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
if (m_array[y][i].x == x) return m_array[y][i].v;
@@ -3836,9 +4017,10 @@ public:
return 0.0f;
}
- void setCoefficient(uint32_t x, uint32_t y, float f) {
- xaDebugAssert(x < width());
- xaDebugAssert(y < height());
+ void setCoefficient(uint32_t x, uint32_t y, float f)
+ {
+ xaDebugAssert( x < width() );
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
if (m_array[y][i].x == x) {
@@ -3848,12 +4030,13 @@ public:
}
if (f != 0.0f) {
Coefficient c = { x, f };
- m_array[y].push_back(c);
+ m_array[y].push_back( c );
}
}
- float dotRow(uint32_t y, const FullVector &v) const {
- xaDebugAssert(y < height());
+ float dotRow(uint32_t y, const FullVector &v) const
+ {
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
float sum = 0;
for (uint32_t i = 0; i < count; i++) {
@@ -3862,7 +4045,8 @@ public:
return sum;
}
- void madRow(uint32_t y, float alpha, FullVector &v) const {
+ void madRow(uint32_t y, float alpha, FullVector &v) const
+ {
xaDebugAssert(y < height());
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
@@ -3870,13 +4054,15 @@ public:
}
}
- void clearRow(uint32_t y) {
- xaDebugAssert(y < height());
+ void clearRow(uint32_t y)
+ {
+ xaDebugAssert( y < height() );
m_array[y].clear();
}
- void scaleRow(uint32_t y, float f) {
- xaDebugAssert(y < height());
+ void scaleRow(uint32_t y, float f)
+ {
+ xaDebugAssert( y < height() );
const uint32_t count = m_array[y].size();
for (uint32_t i = 0; i < count; i++) {
m_array[y][i].v *= f;
@@ -3890,11 +4076,12 @@ private:
const uint32_t m_width;
/// Array of matrix elements.
- std::vector<std::vector<Coefficient> > m_array;
+ std::vector< std::vector<Coefficient> > m_array;
};
// y = a * x + y
-static void saxpy(float a, const FullVector &x, FullVector &y) {
+static void saxpy(float a, const FullVector &x, FullVector &y)
+{
xaDebugAssert(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -3902,7 +4089,8 @@ static void saxpy(float a, const FullVector &x, FullVector &y) {
}
}
-static void copy(const FullVector &x, FullVector &y) {
+static void copy(const FullVector &x, FullVector &y)
+{
xaDebugAssert(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
@@ -3910,14 +4098,16 @@ static void copy(const FullVector &x, FullVector &y) {
}
}
-static void scal(float a, FullVector &x) {
+static void scal(float a, FullVector &x)
+{
const uint32_t dim = x.dimension();
for (uint32_t i = 0; i < dim; i++) {
x[i] *= a;
}
}
-static float dot(const FullVector &x, const FullVector &y) {
+static float dot(const FullVector &x, const FullVector &y)
+{
xaDebugAssert(x.dimension() == y.dimension());
const uint32_t dim = x.dimension();
float sum = 0;
@@ -3927,19 +4117,20 @@ static float dot(const FullVector &x, const FullVector &y) {
return sum;
}
-static void mult(Transpose TM, const Matrix &M, const FullVector &x, FullVector &y) {
+static void mult(Transpose TM, const Matrix &M, const FullVector &x, FullVector &y)
+{
const uint32_t w = M.width();
const uint32_t h = M.height();
if (TM == Transposed) {
- xaDebugAssert(h == x.dimension());
- xaDebugAssert(w == y.dimension());
+ xaDebugAssert( h == x.dimension() );
+ xaDebugAssert( w == y.dimension() );
y.fill(0.0f);
for (uint32_t i = 0; i < h; i++) {
M.madRow(i, x[i], y);
}
} else {
- xaDebugAssert(w == x.dimension());
- xaDebugAssert(h == y.dimension());
+ xaDebugAssert( w == x.dimension() );
+ xaDebugAssert( h == y.dimension() );
for (uint32_t i = 0; i < h; i++) {
y[i] = M.dotRow(i, x);
}
@@ -3947,22 +4138,24 @@ static void mult(Transpose TM, const Matrix &M, const FullVector &x, FullVector
}
// y = M * x
-static void mult(const Matrix &M, const FullVector &x, FullVector &y) {
+static void mult(const Matrix &M, const FullVector &x, FullVector &y)
+{
mult(NoTransposed, M, x, y);
}
-static void sgemv(float alpha, Transpose TA, const Matrix &A, const FullVector &x, float beta, FullVector &y) {
+static void sgemv(float alpha, Transpose TA, const Matrix &A, const FullVector &x, float beta, FullVector &y)
+{
const uint32_t w = A.width();
const uint32_t h = A.height();
if (TA == Transposed) {
- xaDebugAssert(h == x.dimension());
- xaDebugAssert(w == y.dimension());
+ xaDebugAssert( h == x.dimension() );
+ xaDebugAssert( w == y.dimension() );
for (uint32_t i = 0; i < h; i++) {
A.madRow(i, alpha * x[i], y);
}
} else {
- xaDebugAssert(w == x.dimension());
- xaDebugAssert(h == y.dimension());
+ xaDebugAssert( w == x.dimension() );
+ xaDebugAssert( h == y.dimension() );
for (uint32_t i = 0; i < h; i++) {
y[i] = alpha * A.dotRow(i, x) + beta * y[i];
}
@@ -3970,12 +4163,14 @@ static void sgemv(float alpha, Transpose TA, const Matrix &A, const FullVector &
}
// y = alpha*A*x + beta*y
-static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y) {
+static void sgemv(float alpha, const Matrix &A, const FullVector &x, float beta, FullVector &y)
+{
sgemv(alpha, NoTransposed, A, x, beta, y);
}
// dot y-row of A by x-column of B
-static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) {
+static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B)
+{
const std::vector<Matrix::Coefficient> &row = A.getRow(y);
const uint32_t count = row.size();
float sum = 0.0f;
@@ -3987,7 +4182,8 @@ static float dotRowColumn(int y, const Matrix &A, int x, const Matrix &B) {
}
// dot y-row of A by x-row of B
-static float dotRowRow(int y, const Matrix &A, int x, const Matrix &B) {
+static float dotRowRow(int y, const Matrix &A, int x, const Matrix &B)
+{
const std::vector<Matrix::Coefficient> &row = A.getRow(y);
const uint32_t count = row.size();
float sum = 0.0f;
@@ -3999,7 +4195,8 @@ static float dotRowRow(int y, const Matrix &A, int x, const Matrix &B) {
}
// dot y-column of A by x-column of B
-static float dotColumnColumn(int y, const Matrix &A, int x, const Matrix &B) {
+static float dotColumnColumn(int y, const Matrix &A, int x, const Matrix &B)
+{
xaDebugAssert(A.height() == B.height());
const uint32_t h = A.height();
float sum = 0.0f;
@@ -4009,7 +4206,8 @@ static float dotColumnColumn(int y, const Matrix &A, int x, const Matrix &B) {
return sum;
}
-static void transpose(const Matrix &A, Matrix &B) {
+static void transpose(const Matrix &A, Matrix &B)
+{
xaDebugAssert(A.width() == B.height());
xaDebugAssert(B.width() == A.height());
const uint32_t w = A.width();
@@ -4028,7 +4226,8 @@ static void transpose(const Matrix &A, Matrix &B) {
}
}
-static void sgemm(float alpha, Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, float beta, Matrix &C) {
+static void sgemm(float alpha, Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, float beta, Matrix &C)
+{
const uint32_t w = C.width();
const uint32_t h = C.height();
uint32_t aw = (TA == NoTransposed) ? A.width() : A.height();
@@ -4063,21 +4262,24 @@ static void sgemm(float alpha, Transpose TA, const Matrix &A, Transpose TB, cons
}
}
-static void mult(Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, Matrix &C) {
+static void mult(Transpose TA, const Matrix &A, Transpose TB, const Matrix &B, Matrix &C)
+{
sgemm(1.0f, TA, A, TB, B, 0.0f, C);
}
// C = A * B
-static void mult(const Matrix &A, const Matrix &B, Matrix &C) {
+static void mult(const Matrix &A, const Matrix &B, Matrix &C)
+{
mult(NoTransposed, A, NoTransposed, B, C);
}
} // namespace sparse
-class JacobiPreconditioner {
+class JacobiPreconditioner
+{
public:
- JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) :
- m_inverseDiagonal(M.width()) {
+ JacobiPreconditioner(const sparse::Matrix &M, bool symmetric) : m_inverseDiagonal(M.width())
+ {
xaAssert(M.isSquare());
for (uint32_t x = 0; x < M.width(); x++) {
float elem = M.getCoefficient(x, x);
@@ -4090,7 +4292,8 @@ public:
}
}
- void apply(const FullVector &x, FullVector &y) const {
+ void apply(const FullVector &x, FullVector &y) const
+ {
xaDebugAssert(x.dimension() == m_inverseDiagonal.dimension());
xaDebugAssert(y.dimension() == m_inverseDiagonal.dimension());
// @@ Wrap vector component-wise product into a separate function.
@@ -4105,10 +4308,12 @@ private:
};
// Linear solvers.
-class Solver {
+class Solver
+{
public:
// Solve the symmetric system: At·A·x = At·b
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
+ static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f)
+ {
xaDebugAssert(A.width() == x.dimension());
xaDebugAssert(A.height() == b.dimension());
xaDebugAssert(A.height() >= A.width()); // @@ If height == width we could solve it directly...
@@ -4123,7 +4328,8 @@ public:
}
// See section 10.4.3 in: Mesh Parameterization: Theory and Practice, Siggraph Course Notes, August 2007
- static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f) {
+ static bool LeastSquaresSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, const uint32_t *lockedParameters, uint32_t lockedCount, float epsilon = 1e-5f)
+ {
xaDebugAssert(A.width() == x.dimension());
xaDebugAssert(A.height() == b.dimension());
xaDebugAssert(A.height() >= A.width() - lockedCount);
@@ -4221,16 +4427,17 @@ private:
* Jonhathan Richard Shewchuk.
*
**/
- static bool ConjugateGradientSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) {
- xaDebugAssert(A.isSquare());
- xaDebugAssert(A.width() == b.dimension());
- xaDebugAssert(A.width() == x.dimension());
+ static bool ConjugateGradientSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon)
+ {
+ xaDebugAssert( A.isSquare() );
+ xaDebugAssert( A.width() == b.dimension() );
+ xaDebugAssert( A.width() == x.dimension() );
int i = 0;
const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
+ const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
+ FullVector r(D); // residual
+ FullVector p(D); // search direction
+ FullVector q(D); //
float delta_0;
float delta_old;
float delta_new;
@@ -4241,14 +4448,14 @@ private:
sparse::sgemv(-1, A, x, 1, r);
// p = r;
sparse::copy(r, p);
- delta_new = sparse::dot(r, r);
+ delta_new = sparse::dot( r, r );
delta_0 = delta_new;
while (i < i_max && delta_new > epsilon * epsilon * delta_0) {
i++;
// q = A·p
mult(A, p, q);
// alpha = delta_new / p·q
- alpha = delta_new / sparse::dot(p, q);
+ alpha = delta_new / sparse::dot( p, q );
// x = alfa·p + x
sparse::saxpy(alpha, p, x);
if ((i & 31) == 0) { // recompute r after 32 steps
@@ -4260,7 +4467,7 @@ private:
sparse::saxpy(-alpha, q, r);
}
delta_old = delta_new;
- delta_new = sparse::dot(r, r);
+ delta_new = sparse::dot( r, r );
beta = delta_new / delta_old;
// p = beta·p + r
sparse::scal(beta, p);
@@ -4269,18 +4476,20 @@ private:
return delta_new <= epsilon * epsilon * delta_0;
}
+
// Conjugate gradient with preconditioner.
- static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon) {
- xaDebugAssert(A.isSquare());
- xaDebugAssert(A.width() == b.dimension());
- xaDebugAssert(A.width() == x.dimension());
+ static bool ConjugateGradientSolver(const JacobiPreconditioner &preconditioner, const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon)
+ {
+ xaDebugAssert( A.isSquare() );
+ xaDebugAssert( A.width() == b.dimension() );
+ xaDebugAssert( A.width() == x.dimension() );
int i = 0;
const int D = A.width();
- const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
- FullVector r(D); // residual
- FullVector p(D); // search direction
- FullVector q(D); //
- FullVector s(D); // preconditioned
+ const int i_max = 4 * D; // Convergence should be linear, but in some cases, it's not.
+ FullVector r(D); // residual
+ FullVector p(D); // search direction
+ FullVector q(D); //
+ FullVector s(D); // preconditioned
float delta_0;
float delta_old;
float delta_new;
@@ -4312,7 +4521,7 @@ private:
// s = M^-1 · r
preconditioner.apply(r, s);
delta_old = delta_new;
- delta_new = sparse::dot(r, s);
+ delta_new = sparse::dot( r, s );
beta = delta_new / delta_old;
// p = s + beta·p
sparse::scal(beta, p);
@@ -4321,7 +4530,8 @@ private:
return delta_new <= epsilon * epsilon * delta_0;
}
- static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f) {
+ static bool SymmetricSolver(const sparse::Matrix &A, const FullVector &b, FullVector &x, float epsilon = 1e-5f)
+ {
xaDebugAssert(A.height() == A.width());
xaDebugAssert(A.height() == b.dimension());
xaDebugAssert(b.dimension() == x.dimension());
@@ -4335,7 +4545,8 @@ class Atlas;
class Chart;
// Fast sweep in 3 directions
-static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vertex **a, halfedge::Vertex **b) {
+static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vertex **a, halfedge::Vertex **b)
+{
xaDebugAssert(mesh != NULL);
xaDebugAssert(a != NULL);
xaDebugAssert(b != NULL);
@@ -4364,18 +4575,12 @@ static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vert
// Skip interior vertices.
continue;
}
- if (vertex->pos.x < minVertex[0]->pos.x)
- minVertex[0] = vertex;
- else if (vertex->pos.x > maxVertex[0]->pos.x)
- maxVertex[0] = vertex;
- if (vertex->pos.y < minVertex[1]->pos.y)
- minVertex[1] = vertex;
- else if (vertex->pos.y > maxVertex[1]->pos.y)
- maxVertex[1] = vertex;
- if (vertex->pos.z < minVertex[2]->pos.z)
- minVertex[2] = vertex;
- else if (vertex->pos.z > maxVertex[2]->pos.z)
- maxVertex[2] = vertex;
+ if (vertex->pos.x < minVertex[0]->pos.x) minVertex[0] = vertex;
+ else if (vertex->pos.x > maxVertex[0]->pos.x) maxVertex[0] = vertex;
+ if (vertex->pos.y < minVertex[1]->pos.y) minVertex[1] = vertex;
+ else if (vertex->pos.y > maxVertex[1]->pos.y) maxVertex[1] = vertex;
+ if (vertex->pos.z < minVertex[2]->pos.z) minVertex[2] = vertex;
+ else if (vertex->pos.z > maxVertex[2]->pos.z) maxVertex[2] = vertex;
}
float lengths[3];
for (int i = 0; i < 3; i++) {
@@ -4396,24 +4601,28 @@ static bool findApproximateDiameterVertices(halfedge::Mesh *mesh, halfedge::Vert
// Conformal relations from Brecht Van Lommel (based on ABF):
-static float vec_angle_cos(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3) {
+static float vec_angle_cos(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3)
+{
Vector3 d1 = v1 - v2;
Vector3 d2 = v3 - v2;
return clamp(dot(d1, d2) / (length(d1) * length(d2)), -1.0f, 1.0f);
}
-static float vec_angle(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3) {
+static float vec_angle(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3)
+{
float dot = vec_angle_cos(v1, v2, v3);
return acosf(dot);
}
-static void triangle_angles(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3, float *a1, float *a2, float *a3) {
+static void triangle_angles(Vector3::Arg v1, Vector3::Arg v2, Vector3::Arg v3, float *a1, float *a2, float *a3)
+{
*a1 = vec_angle(v3, v1, v2);
*a2 = vec_angle(v1, v2, v3);
*a3 = PI - *a2 - *a1;
}
-static void setup_abf_relations(sparse::Matrix &A, int row, const halfedge::Vertex *v0, const halfedge::Vertex *v1, const halfedge::Vertex *v2) {
+static void setup_abf_relations(sparse::Matrix &A, int row, const halfedge::Vertex *v0, const halfedge::Vertex *v1, const halfedge::Vertex *v2)
+{
int id0 = v0->id;
int id1 = v1->id;
int id2 = v2->id;
@@ -4469,7 +4678,8 @@ static void setup_abf_relations(sparse::Matrix &A, int row, const halfedge::Vert
A.setCoefficient(v2_id, 2 * row + 1, 1);
}
-bool computeLeastSquaresConformalMap(halfedge::Mesh *mesh) {
+bool computeLeastSquaresConformalMap(halfedge::Mesh *mesh)
+{
xaDebugAssert(mesh != NULL);
// For this to work properly, mesh should not have colocals that have the same
// attributes, unless you want the vertices to actually have different texcoords.
@@ -4542,7 +4752,8 @@ bool computeLeastSquaresConformalMap(halfedge::Mesh *mesh) {
return true;
}
-bool computeOrthogonalProjectionMap(halfedge::Mesh *mesh) {
+bool computeOrthogonalProjectionMap(halfedge::Mesh *mesh)
+{
Vector3 axis[2];
uint32_t vertexCount = mesh->vertexCount();
std::vector<Vector3> points(vertexCount);
@@ -4572,7 +4783,8 @@ bool computeOrthogonalProjectionMap(halfedge::Mesh *mesh) {
return true;
}
-void computeSingleFaceMap(halfedge::Mesh *mesh) {
+void computeSingleFaceMap(halfedge::Mesh *mesh)
+{
xaDebugAssert(mesh != NULL);
xaDebugAssert(mesh->faceCount() == 1);
halfedge::Face *face = mesh->faceAt(0);
@@ -4603,11 +4815,12 @@ void computeSingleFaceMap(halfedge::Mesh *mesh) {
// - Resorting is n*log(n)
// @@ Number of elements in the queue is usually small, and we'd have to rebalance often. I'm not sure it's worth implementing a heap.
// @@ Searcing at removal would remove the need for sorting when priorities change.
-struct PriorityQueue {
- PriorityQueue(uint32_t size = UINT_MAX) :
- maxSize(size) {}
+struct PriorityQueue
+{
+ PriorityQueue(uint32_t size = UINT_MAX) : maxSize(size) {}
- void push(float priority, uint32_t face) {
+ void push(float priority, uint32_t face)
+ {
uint32_t i = 0;
const uint32_t count = pairs.size();
for (; i < count; i++) {
@@ -4621,39 +4834,47 @@ struct PriorityQueue {
}
// push face out of order, to be sorted later.
- void push(uint32_t face) {
+ void push(uint32_t face)
+ {
Pair p = { 0.0f, face };
pairs.push_back(p);
}
- uint32_t pop() {
+ uint32_t pop()
+ {
uint32_t f = pairs.back().face;
pairs.pop_back();
return f;
}
- void sort() {
+ void sort()
+ {
//sort(pairs); // @@ My intro sort appears to be much slower than it should!
std::sort(pairs.begin(), pairs.end());
}
- void clear() {
+ void clear()
+ {
pairs.clear();
}
- uint32_t count() const {
+ uint32_t count() const
+ {
return pairs.size();
}
- float firstPriority() const {
+ float firstPriority() const
+ {
return pairs.back().priority;
}
const uint32_t maxSize;
- struct Pair {
- bool operator<(const Pair &p) const {
- return priority > p.priority; // !! Sort in inverse priority order!
+ struct Pair
+ {
+ bool operator <(const Pair &p) const
+ {
+ return priority > p.priority; // !! Sort in inverse priority order!
}
float priority;
@@ -4663,9 +4884,10 @@ struct PriorityQueue {
std::vector<Pair> pairs;
};
-struct ChartBuildData {
- ChartBuildData(int p_id) :
- id(p_id) {
+struct ChartBuildData
+{
+ ChartBuildData(int id) : id(id)
+ {
planeNormal = Vector3(0);
centroid = Vector3(0);
coneAxis = Vector3(0);
@@ -4689,15 +4911,15 @@ struct ChartBuildData {
Vector3 normalSum;
Vector3 centroidSum;
- std::vector<uint32_t> seeds; // @@ These could be a pointers to the halfedge faces directly.
+ std::vector<uint32_t> seeds; // @@ These could be a pointers to the halfedge faces directly.
std::vector<uint32_t> faces;
PriorityQueue candidates;
};
-struct AtlasBuilder {
- AtlasBuilder(const halfedge::Mesh *m) :
- mesh(m),
- facesLeft(m->faceCount()) {
+struct AtlasBuilder
+{
+ AtlasBuilder(const halfedge::Mesh *m) : mesh(m), facesLeft(m->faceCount())
+ {
const uint32_t faceCount = m->faceCount();
faceChartArray.resize(faceCount, -1);
faceCandidateArray.resize(faceCount, (uint32_t)-1);
@@ -4720,14 +4942,16 @@ struct AtlasBuilder {
}
}
- ~AtlasBuilder() {
+ ~AtlasBuilder()
+ {
const uint32_t chartCount = chartArray.size();
for (uint32_t i = 0; i < chartCount; i++) {
delete chartArray[i];
}
}
- void markUnchartedFaces(const std::vector<uint32_t> &unchartedFaces) {
+ void markUnchartedFaces(const std::vector<uint32_t> &unchartedFaces)
+ {
const uint32_t unchartedFaceCount = unchartedFaces.size();
for (uint32_t i = 0; i < unchartedFaceCount; i++) {
uint32_t f = unchartedFaces[i];
@@ -4739,7 +4963,8 @@ struct AtlasBuilder {
facesLeft -= unchartedFaceCount;
}
- void computeShortestPaths() {
+ void computeShortestPaths()
+ {
const uint32_t faceCount = mesh->faceCount();
shortestPaths.resize(faceCount * faceCount, FLT_MAX);
// Fill edges:
@@ -4767,7 +4992,8 @@ struct AtlasBuilder {
}
}
- void placeSeeds(float threshold, uint32_t maxSeedCount) {
+ void placeSeeds(float threshold, uint32_t maxSeedCount)
+ {
// Instead of using a predefiened number of seeds:
// - Add seeds one by one, growing chart until a certain treshold.
// - Undo charts and restart growing process.
@@ -4783,18 +5009,17 @@ struct AtlasBuilder {
}
}
- void createRandomChart(float threshold) {
+ void createRandomChart(float threshold)
+ {
ChartBuildData *chart = new ChartBuildData(chartArray.size());
chartArray.push_back(chart);
// Pick random face that is not used by any chart yet.
uint32_t randomFaceIdx = rand.getRange(facesLeft - 1);
uint32_t i = 0;
for (uint32_t f = 0; f != randomFaceIdx; f++, i++) {
- while (faceChartArray[i] != -1)
- i++;
+ while (faceChartArray[i] != -1) i++;
}
- while (faceChartArray[i] != -1)
- i++;
+ while (faceChartArray[i] != -1) i++;
chart->seeds.push_back(i);
addFaceToChart(chart, i, true);
// Grow the chart as much as possible within the given threshold.
@@ -4802,7 +5027,8 @@ struct AtlasBuilder {
//growCharts(threshold - threshold * 0.75f / chartCount(), facesLeft);
}
- void addFaceToChart(ChartBuildData *chart, uint32_t f, bool recomputeProxy = false) {
+ void addFaceToChart(ChartBuildData *chart, uint32_t f, bool recomputeProxy = false)
+ {
// Add face to chart.
chart->faces.push_back(f);
xaDebugAssert(faceChartArray[f] == -1);
@@ -4824,7 +5050,8 @@ struct AtlasBuilder {
}
// Returns true if any of the charts can grow more.
- bool growCharts(float threshold, uint32_t faceCount) {
+ bool growCharts(float threshold, uint32_t faceCount)
+ {
// Using one global list.
faceCount = std::min(faceCount, facesLeft);
for (uint32_t i = 0; i < faceCount; i++) {
@@ -4837,9 +5064,10 @@ struct AtlasBuilder {
return facesLeft != 0; // Can continue growing.
}
- bool growChart(ChartBuildData *chart, float threshold, uint32_t faceCount) {
+ bool growChart(ChartBuildData *chart, float threshold, uint32_t faceCount)
+ {
// Try to add faceCount faces within threshold to chart.
- for (uint32_t i = 0; i < faceCount;) {
+ for (uint32_t i = 0; i < faceCount; ) {
if (chart->candidates.count() == 0 || chart->candidates.firstPriority() > threshold) {
return false;
}
@@ -4855,7 +5083,8 @@ struct AtlasBuilder {
return true;
}
- void resetCharts() {
+ void resetCharts()
+ {
const uint32_t faceCount = mesh->faceCount();
for (uint32_t i = 0; i < faceCount; i++) {
faceChartArray[i] = -1;
@@ -4877,7 +5106,8 @@ struct AtlasBuilder {
}
}
- void updateCandidates(ChartBuildData *chart, uint32_t f) {
+ void updateCandidates(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
// Traverse neighboring faces, add the ones that do not belong to any chart yet.
for (halfedge::Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) {
@@ -4891,20 +5121,23 @@ struct AtlasBuilder {
}
}
- void updateProxies() {
+ void updateProxies()
+ {
const uint32_t chartCount = chartArray.size();
for (uint32_t i = 0; i < chartCount; i++) {
updateProxy(chartArray[i]);
}
}
- void updateProxy(ChartBuildData *chart) {
+ void updateProxy(ChartBuildData *chart)
+ {
//#pragma message(NV_FILE_LINE "TODO: Use best fit plane instead of average normal.")
chart->planeNormal = normalizeSafe(chart->normalSum, Vector3(0), 0.0f);
chart->centroid = chart->centroidSum / float(chart->faces.size());
}
- bool relocateSeeds() {
+ bool relocateSeeds()
+ {
bool anySeedChanged = false;
const uint32_t chartCount = chartArray.size();
for (uint32_t i = 0; i < chartCount; i++) {
@@ -4915,9 +5148,10 @@ struct AtlasBuilder {
return anySeedChanged;
}
- bool relocateSeed(ChartBuildData *chart) {
+ bool relocateSeed(ChartBuildData *chart)
+ {
Vector3 centroid = computeChartCentroid(chart);
- const uint32_t N = 10; // @@ Hardcoded to 10?
+ const uint32_t N = 10; // @@ Hardcoded to 10?
PriorityQueue bestTriangles(N);
// Find the first N triangles that fit the proxy best.
const uint32_t faceCount = chart->faces.size();
@@ -4953,7 +5187,8 @@ struct AtlasBuilder {
}
}
- void updatePriorities(ChartBuildData *chart) {
+ void updatePriorities(ChartBuildData *chart)
+ {
// Re-evaluate candidate priorities.
uint32_t candidateCount = chart->candidates.count();
for (uint32_t i = 0; i < candidateCount; i++) {
@@ -4967,7 +5202,8 @@ struct AtlasBuilder {
}
// Evaluate combined metric.
- float evaluatePriority(ChartBuildData *chart, uint32_t face) {
+ float evaluatePriority(ChartBuildData *chart, uint32_t face)
+ {
// Estimate boundary length and area:
float newBoundaryLength = evaluateBoundaryLength(chart, face);
float newChartArea = evaluateChartArea(chart, face);
@@ -4984,11 +5220,11 @@ struct AtlasBuilder {
// - Cause more impedance. Never cross 90 degree edges.
// -
float cost = float(
- options.proxyFitMetricWeight * F +
- options.roundnessMetricWeight * C +
- options.straightnessMetricWeight * P +
- options.normalSeamMetricWeight * N +
- options.textureSeamMetricWeight * T);
+ options.proxyFitMetricWeight * F +
+ options.roundnessMetricWeight * C +
+ options.straightnessMetricWeight * P +
+ options.normalSeamMetricWeight * N +
+ options.textureSeamMetricWeight * T);
// Enforce limits strictly:
if (newChartArea > options.maxChartArea) cost = FLT_MAX;
if (newBoundaryLength > options.maxBoundaryLength) cost = FLT_MAX;
@@ -4999,14 +5235,16 @@ struct AtlasBuilder {
}
// Returns a value in [0-1].
- float evaluateProxyFitMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateProxyFitMetric(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
Vector3 faceNormal = face->triangleNormal();
// Use plane fitting metric for now:
return 1 - dot(faceNormal, chart->planeNormal); // @@ normal deviations should be weighted by face area
}
- float evaluateRoundnessMetric(ChartBuildData *chart, uint32_t /*face*/, float newBoundaryLength, float newChartArea) {
+ float evaluateRoundnessMetric(ChartBuildData *chart, uint32_t /*face*/, float newBoundaryLength, float newChartArea)
+ {
float roundness = square(chart->boundaryLength) / chart->area;
float newRoundness = square(newBoundaryLength) / newChartArea;
if (newRoundness > roundness) {
@@ -5017,7 +5255,8 @@ struct AtlasBuilder {
}
}
- float evaluateStraightnessMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateStraightnessMetric(ChartBuildData *chart, uint32_t f)
+ {
float l_out = 0.0f;
float l_in = 0.0f;
const halfedge::Face *face = mesh->faceAt(f);
@@ -5040,7 +5279,8 @@ struct AtlasBuilder {
return std::min(ratio, 0.0f); // Only use the straightness metric to close gaps.
}
- float evaluateNormalSeamMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateNormalSeamMetric(ChartBuildData *chart, uint32_t f)
+ {
float seamFactor = 0.0f;
float totalLength = 0.0f;
const halfedge::Face *face = mesh->faceAt(f);
@@ -5071,7 +5311,8 @@ struct AtlasBuilder {
return seamFactor / totalLength;
}
- float evaluateTextureSeamMetric(ChartBuildData *chart, uint32_t f) {
+ float evaluateTextureSeamMetric(ChartBuildData *chart, uint32_t f)
+ {
float seamLength = 0.0f;
float totalLength = 0.0f;
const halfedge::Face *face = mesh->faceAt(f);
@@ -5101,12 +5342,14 @@ struct AtlasBuilder {
return seamLength / totalLength;
}
- float evaluateChartArea(ChartBuildData *chart, uint32_t f) {
+ float evaluateChartArea(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
return chart->area + faceAreas[face->id];
}
- float evaluateBoundaryLength(ChartBuildData *chart, uint32_t f) {
+ float evaluateBoundaryLength(ChartBuildData *chart, uint32_t f)
+ {
float boundaryLength = chart->boundaryLength;
// Add new edges, subtract edges shared with the chart.
const halfedge::Face *face = mesh->faceAt(f);
@@ -5125,20 +5368,23 @@ struct AtlasBuilder {
}
}
}
- return std::max(0.0f, boundaryLength); // @@ Hack!
+ return std::max(0.0f, boundaryLength); // @@ Hack!
}
- Vector3 evaluateChartNormalSum(ChartBuildData *chart, uint32_t f) {
+ Vector3 evaluateChartNormalSum(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
return chart->normalSum + face->triangleNormalAreaScaled();
}
- Vector3 evaluateChartCentroidSum(ChartBuildData *chart, uint32_t f) {
+ Vector3 evaluateChartCentroidSum(ChartBuildData *chart, uint32_t f)
+ {
const halfedge::Face *face = mesh->faceAt(f);
return chart->centroidSum + face->centroid();
}
- Vector3 computeChartCentroid(const ChartBuildData *chart) {
+ Vector3 computeChartCentroid(const ChartBuildData *chart)
+ {
Vector3 centroid(0);
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
@@ -5148,12 +5394,14 @@ struct AtlasBuilder {
return centroid / float(faceCount);
}
- void fillHoles(float threshold) {
+ void fillHoles(float threshold)
+ {
while (facesLeft > 0)
createRandomChart(threshold);
}
- void mergeCharts() {
+ void mergeCharts()
+ {
std::vector<float> sharedBoundaryLengths;
const uint32_t chartCount = chartArray.size();
for (int c = chartCount - 1; c >= 0; c--) {
@@ -5219,9 +5467,9 @@ struct AtlasBuilder {
// Update faceChartArray.
const uint32_t faceCount = faceChartArray.size();
for (uint32_t i = 0; i < faceCount; i++) {
- xaDebugAssert(faceChartArray[i] != -1);
- xaDebugAssert(faceChartArray[i] != c);
- xaDebugAssert(faceChartArray[i] <= int32_t(chartArray.size()));
+ xaDebugAssert (faceChartArray[i] != -1);
+ xaDebugAssert (faceChartArray[i] != c);
+ xaDebugAssert (faceChartArray[i] <= int32_t(chartArray.size()));
if (faceChartArray[i] > c) {
faceChartArray[i]--;
}
@@ -5241,7 +5489,8 @@ struct AtlasBuilder {
};
// @@ Get N best candidates in one pass.
- const Candidate &getBestCandidate() const {
+ const Candidate &getBestCandidate() const
+ {
uint32_t best = 0;
float bestCandidateMetric = FLT_MAX;
const uint32_t candidateCount = candidateArray.size();
@@ -5256,7 +5505,8 @@ struct AtlasBuilder {
return candidateArray[best];
}
- void removeCandidate(uint32_t f) {
+ void removeCandidate(uint32_t f)
+ {
int c = faceCandidateArray[f];
if (c != -1) {
faceCandidateArray[f] = (uint32_t)-1;
@@ -5271,7 +5521,8 @@ struct AtlasBuilder {
}
}
- void updateCandidate(ChartBuildData *chart, uint32_t f, float metric) {
+ void updateCandidate(ChartBuildData *chart, uint32_t f, float metric)
+ {
if (faceCandidateArray[f] == -1) {
const uint32_t index = candidateArray.size();
faceCandidateArray[f] = index;
@@ -5291,7 +5542,8 @@ struct AtlasBuilder {
}
}
- void mergeChart(ChartBuildData *owner, ChartBuildData *chart, float sharedBoundaryLength) {
+ void mergeChart(ChartBuildData *owner, ChartBuildData *chart, float sharedBoundaryLength)
+ {
const uint32_t faceCount = chart->faces.size();
for (uint32_t i = 0; i < faceCount; i++) {
uint32_t f = chart->faces[i];
@@ -5307,6 +5559,7 @@ struct AtlasBuilder {
updateProxy(owner);
}
+
uint32_t chartCount() const { return chartArray.size(); }
const std::vector<uint32_t> &chartFaces(uint32_t i) const { return chartArray[i]->faces; }
@@ -5324,13 +5577,13 @@ struct AtlasBuilder {
};
/// A chart is a connected set of faces with a certain topology (usually a disk).
-class Chart {
+class Chart
+{
public:
- Chart() :
- m_isDisk(false),
- m_isVertexMapped(false) {}
+ Chart() : m_isDisk(false), m_isVertexMapped(false) {}
- void build(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &faceArray) {
+ void build(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &faceArray)
+ {
// Copy face indices.
m_faceArray = faceArray;
const uint32_t meshVertexCount = originalMesh->vertexCount();
@@ -5353,7 +5606,7 @@ public:
}
if (chartMeshIndices[vertex->id] == ~0) {
chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
- m_chartToOriginalMap.push_back(vertex->original_id);
+ m_chartToOriginalMap.push_back(vertex->id);
m_chartToUnifiedMap.push_back(unifiedMeshIndices[unifiedVertex->id]);
halfedge::Vertex *v = m_chartMesh->addVertex(vertex->pos);
v->nor = vertex->nor;
@@ -5417,7 +5670,8 @@ public:
m_isDisk = topology.isDisk();
}
- void buildVertexMap(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &unchartedMaterialArray) {
+ void buildVertexMap(const halfedge::Mesh *originalMesh, const std::vector<uint32_t> &unchartedMaterialArray)
+ {
xaAssert(m_chartMesh.get() == NULL && m_unifiedMesh.get() == NULL);
m_isVertexMapped = true;
// Build face indices.
@@ -5445,7 +5699,7 @@ public:
const halfedge::Vertex *vertex = it.current()->vertex;
if (chartMeshIndices[vertex->id] == ~0) {
chartMeshIndices[vertex->id] = m_chartMesh->vertexCount();
- m_chartToOriginalMap.push_back(vertex->original_id);
+ m_chartToOriginalMap.push_back(vertex->id);
halfedge::Vertex *v = m_chartMesh->addVertex(vertex->pos);
v->nor = vertex->nor;
v->tex = vertex->tex; // @@ Not necessary.
@@ -5505,7 +5759,7 @@ public:
halfedge::Vertex *vertex = m_chartMesh->vertexAt(idx);
xaDebugAssert(vertexIndexArray[idx] == -1);
std::vector<uint32_t> neighbors;
- grid.gather(vertex->pos, positionThreshold, /*ref*/ neighbors);
+ grid.gather(vertex->pos, positionThreshold, /*ref*/neighbors);
// Compare against all nearby vertices, cluster greedily.
for (uint32_t j = 0; j < neighbors.size(); j++) {
uint32_t otherIdx = neighbors[j];
@@ -5528,7 +5782,7 @@ public:
xaDebugAssert(cellsVisited == grid.cellArray.size());
xaDebugAssert(verticesVisited == chartVertexCount);
vertexMapWidth = ftoi_ceil(sqrtf(float(texelCount)));
- vertexMapWidth = (vertexMapWidth + 3) & ~3; // Width aligned to 4.
+ vertexMapWidth = (vertexMapWidth + 3) & ~3; // Width aligned to 4.
vertexMapHeight = vertexMapWidth == 0 ? 0 : (texelCount + vertexMapWidth - 1) / vertexMapWidth;
//vertexMapHeight = (vertexMapHeight + 3) & ~3; // Height aligned to 4.
xaDebugAssert(vertexMapWidth >= vertexMapHeight);
@@ -5559,7 +5813,8 @@ public:
}
}
- bool closeHoles() {
+ bool closeHoles()
+ {
xaDebugAssert(!m_isVertexMapped);
std::vector<halfedge::Edge *> boundaryEdges;
getBoundaryEdges(m_unifiedMesh.get(), boundaryEdges);
@@ -5610,7 +5865,7 @@ public:
std::vector<halfedge::Edge *> edgeLoop;
halfedge::Edge *edge = startEdge;
do {
- halfedge::Vertex *vertex = edge->next->vertex; // edge->to()
+ halfedge::Vertex *vertex = edge->next->vertex; // edge->to()
uint32_t j;
for (j = 0; j < vertexLoop.size(); j++) {
if (vertex->isColocal(vertexLoop[j])) {
@@ -5619,8 +5874,8 @@ public:
}
bool isCrossing = (j != vertexLoop.size());
if (isCrossing) {
- halfedge::Edge *prev = edgeLoop[j]; // Previous edge before the loop.
- halfedge::Edge *next = edge->next; // Next edge after the loop.
+ halfedge::Edge *prev = edgeLoop[j]; // Previous edge before the loop.
+ halfedge::Edge *next = edge->next; // Next edge after the loop.
xaDebugAssert(prev->to()->isColocal(next->from()));
// Close loop.
edgeLoop.push_back(edge);
@@ -5646,55 +5901,69 @@ public:
return boundaryCount == 1;
}
- bool isDisk() const {
+ bool isDisk() const
+ {
return m_isDisk;
}
- bool isVertexMapped() const {
+ bool isVertexMapped() const
+ {
return m_isVertexMapped;
}
- uint32_t vertexCount() const {
+ uint32_t vertexCount() const
+ {
return m_chartMesh->vertexCount();
}
- uint32_t colocalVertexCount() const {
+ uint32_t colocalVertexCount() const
+ {
return m_unifiedMesh->vertexCount();
}
- uint32_t faceCount() const {
+ uint32_t faceCount() const
+ {
return m_faceArray.size();
}
- uint32_t faceAt(uint32_t i) const {
+ uint32_t faceAt(uint32_t i) const
+ {
return m_faceArray[i];
}
- const halfedge::Mesh *chartMesh() const {
+ const halfedge::Mesh *chartMesh() const
+ {
return m_chartMesh.get();
}
- halfedge::Mesh *chartMesh() {
+ halfedge::Mesh *chartMesh()
+ {
return m_chartMesh.get();
}
- const halfedge::Mesh *unifiedMesh() const {
+ const halfedge::Mesh *unifiedMesh() const
+ {
return m_unifiedMesh.get();
}
- halfedge::Mesh *unifiedMesh() {
+ halfedge::Mesh *unifiedMesh()
+ {
return m_unifiedMesh.get();
}
//uint32_t vertexIndex(uint32_t i) const { return m_vertexIndexArray[i]; }
- uint32_t mapChartVertexToOriginalVertex(uint32_t i) const {
+ uint32_t mapChartVertexToOriginalVertex(uint32_t i) const
+ {
return m_chartToOriginalMap[i];
}
- uint32_t mapChartVertexToUnifiedVertex(uint32_t i) const {
+ uint32_t mapChartVertexToUnifiedVertex(uint32_t i) const
+ {
return m_chartToUnifiedMap[i];
}
- const std::vector<uint32_t> &faceArray() const {
+ const std::vector<uint32_t> &faceArray() const
+ {
return m_faceArray;
}
// Transfer parameterization from unified mesh to chart mesh.
- void transferParameterization() {
+ void transferParameterization()
+ {
xaDebugAssert(!m_isVertexMapped);
uint32_t vertexCount = m_chartMesh->vertexCount();
for (uint32_t v = 0; v < vertexCount; v++) {
@@ -5704,18 +5973,21 @@ public:
}
}
- float computeSurfaceArea() const {
+ float computeSurfaceArea() const
+ {
return halfedge::computeSurfaceArea(m_chartMesh.get()) * scale;
}
- float computeParametricArea() const {
+ float computeParametricArea() const
+ {
// This only makes sense in parameterized meshes.
xaDebugAssert(m_isDisk);
xaDebugAssert(!m_isVertexMapped);
return halfedge::computeParametricArea(m_chartMesh.get());
}
- Vector2 computeParametricBounds() const {
+ Vector2 computeParametricBounds() const
+ {
// This only makes sense in parameterized meshes.
xaDebugAssert(m_isDisk);
xaDebugAssert(!m_isVertexMapped);
@@ -5735,7 +6007,8 @@ public:
bool blockAligned = true;
private:
- bool closeLoop(uint32_t start, const std::vector<halfedge::Edge *> &loop) {
+ bool closeLoop(uint32_t start, const std::vector<halfedge::Edge *> &loop)
+ {
const uint32_t vertexCount = loop.size() - start;
xaDebugAssert(vertexCount >= 3);
if (vertexCount < 3) return false;
@@ -5779,7 +6052,8 @@ private:
return true;
}
- static void getBoundaryEdges(halfedge::Mesh *mesh, std::vector<halfedge::Edge *> &boundaryEdges) {
+ static void getBoundaryEdges(halfedge::Mesh *mesh, std::vector<halfedge::Edge *> &boundaryEdges)
+ {
xaDebugAssert(mesh != NULL);
const uint32_t edgeCount = mesh->edgeCount();
BitArray bitFlags(edgeCount);
@@ -5810,7 +6084,7 @@ private:
std::auto_ptr<halfedge::Mesh> m_unifiedMesh;
bool m_isDisk;
bool m_isVertexMapped;
-
+
// List of faces of the original mesh that belong to this chart.
std::vector<uint32_t> m_faceArray;
@@ -5821,9 +6095,11 @@ private:
};
// Estimate quality of existing parameterization.
-class ParameterizationQuality {
+class ParameterizationQuality
+{
public:
- ParameterizationQuality() {
+ ParameterizationQuality()
+ {
m_totalTriangleCount = 0;
m_flippedTriangleCount = 0;
m_zeroAreaTriangleCount = 0;
@@ -5835,7 +6111,8 @@ public:
m_authalicMetric = 0.0f;
}
- ParameterizationQuality(const halfedge::Mesh *mesh) {
+ ParameterizationQuality(const halfedge::Mesh *mesh)
+ {
xaDebugAssert(mesh != NULL);
m_totalTriangleCount = 0;
m_flippedTriangleCount = 0;
@@ -5879,33 +6156,39 @@ public:
xaDebugAssert(std::isfinite(m_authalicMetric));
}
- bool isValid() const {
+ bool isValid() const
+ {
return m_flippedTriangleCount == 0; // @@ Does not test for self-overlaps.
}
- float rmsStretchMetric() const {
+ float rmsStretchMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
float normFactor = sqrtf(m_parametricArea / m_geometricArea);
return sqrtf(m_stretchMetric / m_geometricArea) * normFactor;
}
- float maxStretchMetric() const {
+ float maxStretchMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
float normFactor = sqrtf(m_parametricArea / m_geometricArea);
return m_maxStretchMetric * normFactor;
}
- float rmsConformalMetric() const {
+ float rmsConformalMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
return sqrtf(m_conformalMetric / m_geometricArea);
}
- float maxAuthalicMetric() const {
+ float maxAuthalicMetric() const
+ {
if (m_geometricArea == 0) return 0.0f;
return sqrtf(m_authalicMetric / m_geometricArea);
}
- void operator+=(const ParameterizationQuality &pq) {
+ void operator+=(const ParameterizationQuality &pq)
+ {
m_totalTriangleCount += pq.m_totalTriangleCount;
m_flippedTriangleCount += pq.m_flippedTriangleCount;
m_zeroAreaTriangleCount += pq.m_zeroAreaTriangleCount;
@@ -5918,7 +6201,8 @@ public:
}
private:
- void processTriangle(Vector3 q[3], Vector2 p[3]) {
+ void processTriangle(Vector3 q[3], Vector2 p[3])
+ {
m_totalTriangleCount++;
// Evaluate texture stretch metric. See:
// - "Texture Mapping Progressive Meshes", Sander, Snyder, Gortler & Hoppe
@@ -5983,32 +6267,38 @@ private:
};
// Set of charts corresponding to a single mesh.
-class MeshCharts {
+class MeshCharts
+{
public:
- MeshCharts(const halfedge::Mesh *mesh) :
- m_mesh(mesh) {}
+ MeshCharts(const halfedge::Mesh *mesh) : m_mesh(mesh) {}
- ~MeshCharts() {
+ ~MeshCharts()
+ {
for (size_t i = 0; i < m_chartArray.size(); i++)
delete m_chartArray[i];
}
- uint32_t chartCount() const {
+ uint32_t chartCount() const
+ {
return m_chartArray.size();
}
- uint32_t vertexCount() const {
+ uint32_t vertexCount () const
+ {
return m_totalVertexCount;
}
- const Chart *chartAt(uint32_t i) const {
+ const Chart *chartAt(uint32_t i) const
+ {
return m_chartArray[i];
}
- Chart *chartAt(uint32_t i) {
+ Chart *chartAt(uint32_t i)
+ {
return m_chartArray[i];
}
// Extract the charts of the input mesh.
- void extractCharts() {
+ void extractCharts()
+ {
const uint32_t faceCount = m_mesh->faceCount();
int first = 0;
std::vector<uint32_t> queue;
@@ -6108,7 +6398,8 @@ public:
- emphasize roundness metrics to prevent those cases.
- If interior self-overlaps: preserve boundary parameterization and use mean-value map.
*/
- void computeCharts(const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray) {
+ void computeCharts(const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray)
+ {
Chart *vertexMap = NULL;
if (unchartedMaterialArray.size() != 0) {
vertexMap = new Chart();
@@ -6141,7 +6432,7 @@ public:
xaPrint("### Placed %d seeds (max = %d)\n", builder.chartCount(), maxSeedCount);
builder.updateProxies();
builder.mergeCharts();
-#if 1
+ #if 1
xaPrint("### Relocating seeds\n");
builder.relocateSeeds();
xaPrint("### Reset charts\n");
@@ -6183,7 +6474,7 @@ public:
xaPrint("### Growing charts\n");
}
};
-#endif
+ #endif
// Make sure no holes are left!
xaDebugAssert(builder.facesLeft == 0);
const uint32_t chartCount = builder.chartArray.size();
@@ -6220,21 +6511,25 @@ public:
}
}
- void parameterizeCharts() {
+ void parameterizeCharts()
+ {
ParameterizationQuality globalParameterizationQuality;
// Parameterize the charts.
uint32_t diskCount = 0;
const uint32_t chartCount = m_chartArray.size();
- for (uint32_t i = 0; i < chartCount; i++) {
+ for (uint32_t i = 0; i < chartCount; i++)
+ {
Chart *chart = m_chartArray[i];
bool isValid = false;
- if (chart->isVertexMapped()) {
+ if (chart->isVertexMapped())
+ {
continue;
}
- if (chart->isDisk()) {
+ if (chart->isDisk())
+ {
diskCount++;
ParameterizationQuality chartParameterizationQuality;
if (chart->faceCount() == 1) {
@@ -6258,6 +6553,7 @@ public:
// Transfer parameterization from unified mesh to chart mesh.
chart->transferParameterization();
+
}
xaPrint(" Parameterized %d/%d charts.\n", diskCount, chartCount);
xaPrint(" RMS stretch metric: %f\n", globalParameterizationQuality.rmsStretchMetric());
@@ -6266,18 +6562,22 @@ public:
xaPrint(" RMS authalic metric: %f\n", globalParameterizationQuality.maxAuthalicMetric());
}
- uint32_t faceChartAt(uint32_t i) const {
+ uint32_t faceChartAt(uint32_t i) const
+ {
return m_faceChart[i];
}
- uint32_t faceIndexWithinChartAt(uint32_t i) const {
+ uint32_t faceIndexWithinChartAt(uint32_t i) const
+ {
return m_faceIndex[i];
}
- uint32_t vertexCountBeforeChartAt(uint32_t i) const {
+ uint32_t vertexCountBeforeChartAt(uint32_t i) const
+ {
return m_chartVertexCountPrefixSum[i];
}
private:
+
const halfedge::Mesh *m_mesh;
std::vector<Chart *> m_chartArray;
@@ -6290,26 +6590,32 @@ private:
};
/// An atlas is a set of charts.
-class Atlas {
+class Atlas
+{
public:
- ~Atlas() {
+ ~Atlas()
+ {
for (size_t i = 0; i < m_meshChartsArray.size(); i++)
delete m_meshChartsArray[i];
}
- uint32_t meshCount() const {
+ uint32_t meshCount() const
+ {
return m_meshChartsArray.size();
}
- const MeshCharts *meshAt(uint32_t i) const {
+ const MeshCharts *meshAt(uint32_t i) const
+ {
return m_meshChartsArray[i];
}
- MeshCharts *meshAt(uint32_t i) {
+ MeshCharts *meshAt(uint32_t i)
+ {
return m_meshChartsArray[i];
}
- uint32_t chartCount() const {
+ uint32_t chartCount() const
+ {
uint32_t count = 0;
for (uint32_t c = 0; c < m_meshChartsArray.size(); c++) {
count += m_meshChartsArray[c]->chartCount();
@@ -6317,7 +6623,8 @@ public:
return count;
}
- const Chart *chartAt(uint32_t i) const {
+ const Chart *chartAt(uint32_t i) const
+ {
for (uint32_t c = 0; c < m_meshChartsArray.size(); c++) {
uint32_t count = m_meshChartsArray[c]->chartCount();
if (i < count) {
@@ -6328,7 +6635,8 @@ public:
return NULL;
}
- Chart *chartAt(uint32_t i) {
+ Chart *chartAt(uint32_t i)
+ {
for (uint32_t c = 0; c < m_meshChartsArray.size(); c++) {
uint32_t count = m_meshChartsArray[c]->chartCount();
if (i < count) {
@@ -6341,23 +6649,27 @@ public:
// Add mesh charts and takes ownership.
// Extract the charts and add to this atlas.
- void addMeshCharts(MeshCharts *meshCharts) {
+ void addMeshCharts(MeshCharts *meshCharts)
+ {
m_meshChartsArray.push_back(meshCharts);
}
- void extractCharts(const halfedge::Mesh *mesh) {
+ void extractCharts(const halfedge::Mesh *mesh)
+ {
MeshCharts *meshCharts = new MeshCharts(mesh);
meshCharts->extractCharts();
addMeshCharts(meshCharts);
}
- void computeCharts(const halfedge::Mesh *mesh, const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray) {
+ void computeCharts(const halfedge::Mesh *mesh, const CharterOptions &options, const std::vector<uint32_t> &unchartedMaterialArray)
+ {
MeshCharts *meshCharts = new MeshCharts(mesh);
meshCharts->computeCharts(options, unchartedMaterialArray);
addMeshCharts(meshCharts);
}
- void parameterizeCharts() {
+ void parameterizeCharts()
+ {
for (uint32_t i = 0; i < m_meshChartsArray.size(); i++) {
m_meshChartsArray[i]->parameterizeCharts();
}
@@ -6367,11 +6679,10 @@ private:
std::vector<MeshCharts *> m_meshChartsArray;
};
-struct AtlasPacker {
- AtlasPacker(Atlas *atlas) :
- m_atlas(atlas),
- m_width(0),
- m_height(0) {
+struct AtlasPacker
+{
+ AtlasPacker(Atlas *atlas) : m_atlas(atlas), m_width(0), m_height(0)
+ {
// Save the original uvs.
m_originalChartUvs.resize(m_atlas->chartCount());
for (uint32_t i = 0; i < m_atlas->chartCount(); i++) {
@@ -6386,7 +6697,8 @@ struct AtlasPacker {
uint32_t getHeight() const { return m_height; }
// Pack charts in the smallest possible rectangle.
- void packCharts(const PackerOptions &options) {
+ void packCharts(const PackerOptions &options)
+ {
const uint32_t chartCount = m_atlas->chartCount();
if (chartCount == 0) return;
float texelsPerUnit = 1;
@@ -6415,7 +6727,7 @@ struct AtlasPacker {
meshArea += chartArea;
//chartOrderArray[c] = chartArea;
// Compute chart scale
- float parametricArea = fabsf(chart->computeParametricArea()); // @@ There doesn't seem to be anything preventing parametric area to be negative.
+ float parametricArea = fabsf(chart->computeParametricArea()); // @@ There doesn't seem to be anything preventing parametric area to be negative.
if (parametricArea < NV_EPSILON) {
// When the parametric area is too small we use a rough approximation to prevent divisions by very small numbers.
Vector2 bounds = chart->computeParametricBounds();
@@ -6564,18 +6876,18 @@ struct AtlasPacker {
// 0 1 2
if (options.conservative) {
// Init all bits to 0.
- chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1 + options.padding, ftoi_ceil(chartExtents[c].y) + 1 + options.padding, /*initValue=*/false); // + 2 to add padding on both sides.
+ chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1 + options.padding, ftoi_ceil(chartExtents[c].y) + 1 + options.padding, /*initValue=*/false); // + 2 to add padding on both sides.
// Rasterize chart and dilate.
drawChartBitmapDilate(chart, &chart_bitmap, options.padding);
} else {
// Init all bits to 0.
- chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1, ftoi_ceil(chartExtents[c].y) + 1, /*initValue=*/false); // Add half a texels on each side.
+ chart_bitmap.resize(ftoi_ceil(chartExtents[c].x) + 1, ftoi_ceil(chartExtents[c].y) + 1, /*initValue=*/false); // Add half a texels on each side.
// Rasterize chart and dilate.
drawChartBitmap(chart, &chart_bitmap, Vector2(1), Vector2(0.5));
}
}
int best_x, best_y;
- int best_cw, best_ch; // Includes padding now.
+ int best_cw, best_ch; // Includes padding now.
int best_r;
findChartLocation(options.quality, &chart_bitmap, chartExtents[c], w, h, &best_x, &best_y, &best_cw, &best_ch, &best_r, chart->blockAligned);
/*if (w < best_x + best_cw || h < best_y + best_ch)
@@ -6629,7 +6941,8 @@ struct AtlasPacker {
}
}
- float computeAtlasUtilization() const {
+ float computeAtlasUtilization() const
+ {
const uint32_t w = m_width;
const uint32_t h = m_height;
xaDebugAssert(w <= m_bitmap.width());
@@ -6644,7 +6957,8 @@ struct AtlasPacker {
}
private:
- void resetUvs() {
+ void resetUvs()
+ {
for (uint32_t i = 0; i < m_atlas->chartCount(); i++) {
halfedge::Mesh *mesh = m_atlas->chartAt(i)->chartMesh();
for (uint32_t j = 0; j < mesh->vertexCount(); j++)
@@ -6656,7 +6970,8 @@ private:
// is occupied at this point. At the end we have many small charts and a large atlas with sparse holes. Finding those holes randomly is slow. A better approach would be to
// start stacking large charts as if they were tetris pieces. Once charts get small try to place them randomly. It may be interesting to try a intermediate strategy, first try
// along one axis and then try exhaustively along that axis.
- void findChartLocation(int quality, const BitMap *bitmap, Vector2::Arg extents, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned) {
+ void findChartLocation(int quality, const BitMap *bitmap, Vector2::Arg extents, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned)
+ {
int attempts = 256;
if (quality == 1) attempts = 4096;
if (quality == 2) attempts = 2048;
@@ -6669,7 +6984,8 @@ private:
}
}
- void findChartLocation_bruteForce(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned) {
+ void findChartLocation_bruteForce(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, bool blockAligned)
+ {
const int BLOCK_SIZE = 4;
int best_metric = INT_MAX;
int step_size = blockAligned ? BLOCK_SIZE : 1;
@@ -6708,10 +7024,11 @@ private:
}
}
done:
- xaDebugAssert(best_metric != INT_MAX);
+ xaDebugAssert (best_metric != INT_MAX);
}
- void findChartLocation_random(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned) {
+ void findChartLocation_random(const BitMap *bitmap, Vector2::Arg /*extents*/, int w, int h, int *best_x, int *best_y, int *best_w, int *best_h, int *best_r, int minTrialCount, bool blockAligned)
+ {
const int BLOCK_SIZE = 4;
int best_metric = INT_MAX;
for (int i = 0; i < minTrialCount || best_metric == INT_MAX; i++) {
@@ -6752,7 +7069,8 @@ private:
}
}
- void drawChartBitmapDilate(const Chart *chart, BitMap *bitmap, int padding) {
+ void drawChartBitmapDilate(const Chart *chart, BitMap *bitmap, int padding)
+ {
const int w = bitmap->width();
const int h = bitmap->height();
const Vector2 extents = Vector2(float(w), float(h));
@@ -6802,7 +7120,8 @@ private:
}
}
- void drawChartBitmap(const Chart *chart, BitMap *bitmap, const Vector2 &scale, const Vector2 &offset) {
+ void drawChartBitmap(const Chart *chart, BitMap *bitmap, const Vector2 &scale, const Vector2 &offset)
+ {
const int w = bitmap->width();
const int h = bitmap->height();
const Vector2 extents = Vector2(float(w), float(h));
@@ -6863,7 +7182,8 @@ private:
std::swap(tmp, *bitmap);
}
- bool canAddChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) {
+ bool canAddChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r)
+ {
xaDebugAssert(r == 0 || r == 1);
// Check whether the two bitmaps overlap.
const int w = bitmap->width();
@@ -6904,7 +7224,8 @@ private:
return true;
}
- void addChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r) {
+ void addChart(const BitMap *bitmap, int atlas_w, int atlas_h, int offset_x, int offset_y, int r)
+ {
xaDebugAssert(r == 0 || r == 1);
// Check whether the two bitmaps overlap.
const int w = bitmap->width();
@@ -6946,8 +7267,9 @@ private:
}
}
- static bool setBitsCallback(void *param, int x, int y, Vector3::Arg, Vector3::Arg, Vector3::Arg, float area) {
- BitMap *bitmap = (BitMap *)param;
+ static bool setBitsCallback(void *param, int x, int y, Vector3::Arg, Vector3::Arg, Vector3::Arg, float area)
+ {
+ BitMap *bitmap = (BitMap * )param;
if (area > 0.0) {
bitmap->setBitAt(x, y);
}
@@ -6955,7 +7277,8 @@ private:
}
// Compute the convex hull using Graham Scan.
- static void convexHull(const std::vector<Vector2> &input, std::vector<Vector2> &output, float epsilon) {
+ static void convexHull(const std::vector<Vector2> &input, std::vector<Vector2> &output, float epsilon)
+ {
const uint32_t inputCount = input.size();
std::vector<float> coords(inputCount);
for (uint32_t i = 0; i < inputCount; i++) {
@@ -6984,7 +7307,7 @@ private:
output.clear();
output.push_back(top[0]);
output.push_back(top[1]);
- for (uint32_t i = 2; i < top.size();) {
+ for (uint32_t i = 2; i < top.size(); ) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = top[i];
@@ -7000,7 +7323,7 @@ private:
uint32_t top_count = output.size();
output.push_back(bottom[1]);
// Filter bottom list.
- for (uint32_t i = 2; i < bottom.size();) {
+ for (uint32_t i = 2; i < bottom.size(); ) {
Vector2 a = output[output.size() - 2];
Vector2 b = output[output.size() - 1];
Vector2 c = bottom[i];
@@ -7019,7 +7342,8 @@ private:
}
// This should compute convex hull and use rotating calipers to find the best box. Currently it uses a brute force method.
- static void computeBoundingBox(Chart *chart, Vector2 *majorAxis, Vector2 *minorAxis, Vector2 *minCorner, Vector2 *maxCorner) {
+ static void computeBoundingBox(Chart *chart, Vector2 *majorAxis, Vector2 *minorAxis, Vector2 *minCorner, Vector2 *maxCorner)
+ {
// Compute list of boundary points.
std::vector<Vector2> points;
points.reserve(16);
@@ -7096,7 +7420,8 @@ private:
} // namespace param
} // namespace internal
-struct Atlas {
+struct Atlas
+{
internal::param::Atlas atlas;
std::vector<internal::halfedge::Mesh *> heMeshes;
uint32_t width = 0;
@@ -7104,65 +7429,75 @@ struct Atlas {
OutputMesh **outputMeshes = NULL;
};
-void SetPrint(PrintFunc print) {
+void SetPrint(PrintFunc print)
+{
internal::s_print = print;
}
-Atlas *Create() {
+Atlas *Create()
+{
Atlas *atlas = new Atlas();
return atlas;
}
-void Destroy(Atlas *atlas) {
+void Destroy(Atlas *atlas)
+{
xaAssert(atlas);
for (int i = 0; i < (int)atlas->heMeshes.size(); i++) {
delete atlas->heMeshes[i];
if (atlas->outputMeshes) {
OutputMesh *outputMesh = atlas->outputMeshes[i];
for (uint32_t j = 0; j < outputMesh->chartCount; j++)
- delete[] outputMesh->chartArray[j].indexArray;
- delete[] outputMesh->chartArray;
- delete[] outputMesh->vertexArray;
- delete[] outputMesh->indexArray;
+ delete [] outputMesh->chartArray[j].indexArray;
+ delete [] outputMesh->chartArray;
+ delete [] outputMesh->vertexArray;
+ delete [] outputMesh->indexArray;
delete outputMesh;
}
}
- delete[] atlas->outputMeshes;
+ delete [] atlas->outputMeshes;
delete atlas;
}
-static internal::Vector3 DecodePosition(const InputMesh &mesh, uint32_t index) {
+static internal::Vector3 DecodePosition(const InputMesh &mesh, uint32_t index)
+{
xaAssert(mesh.vertexPositionData);
return *((const internal::Vector3 *)&((const uint8_t *)mesh.vertexPositionData)[mesh.vertexPositionStride * index]);
}
-static internal::Vector3 DecodeNormal(const InputMesh &mesh, uint32_t index) {
+static internal::Vector3 DecodeNormal(const InputMesh &mesh, uint32_t index)
+{
xaAssert(mesh.vertexNormalData);
return *((const internal::Vector3 *)&((const uint8_t *)mesh.vertexNormalData)[mesh.vertexNormalStride * index]);
}
-static internal::Vector2 DecodeUv(const InputMesh &mesh, uint32_t index) {
+static internal::Vector2 DecodeUv(const InputMesh &mesh, uint32_t index)
+{
xaAssert(mesh.vertexUvData);
return *((const internal::Vector2 *)&((const uint8_t *)mesh.vertexUvData)[mesh.vertexUvStride * index]);
}
-static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, uint32_t i) {
+static uint32_t DecodeIndex(IndexFormat::Enum format, const void *indexData, uint32_t i)
+{
if (format == IndexFormat::HalfFloat)
return (uint32_t)((const uint16_t *)indexData)[i];
return ((const uint32_t *)indexData)[i];
}
-static float EdgeLength(internal::Vector3 pos1, internal::Vector3 pos2) {
+static float EdgeLength(internal::Vector3 pos1, internal::Vector3 pos2)
+{
return internal::length(pos2 - pos1);
}
-AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertices) {
+AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertices)
+{
xaAssert(atlas);
AddMeshError error;
error.code = AddMeshErrorCode::Success;
error.face = error.index0 = error.index1 = UINT32_MAX;
// Expecting triangle faces.
- if ((mesh.indexCount % 3) != 0) {
+ if ((mesh.indexCount % 3) != 0)
+ {
error.code = AddMeshErrorCode::InvalidIndexCount;
return error;
}
@@ -7238,24 +7573,15 @@ AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertice
}
}
internal::halfedge::Face *face = heMesh->addFace(tri[0], tri[1], tri[2]);
-
- if (!face && heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge) {
- //there is still hope for this, no reason to not add, at least add as separate
- face = heMesh->addUniqueFace(tri[0], tri[1], tri[2]);
- }
-
if (!face) {
- //continue;
-
- if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge) {
+ if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::AlreadyAddedEdge)
error.code = AddMeshErrorCode::AlreadyAddedEdge;
- } else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateColocalEdge) {
+ else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateColocalEdge)
error.code = AddMeshErrorCode::DegenerateColocalEdge;
- } else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateEdge) {
+ else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DegenerateEdge)
error.code = AddMeshErrorCode::DegenerateEdge;
- } else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DuplicateEdge) {
+ else if (heMesh->errorCode == internal::halfedge::Mesh::ErrorCode::DuplicateEdge)
error.code = AddMeshErrorCode::DuplicateEdge;
- }
error.face = i;
error.index0 = heMesh->errorIndex0;
error.index1 = heMesh->errorIndex1;
@@ -7270,7 +7596,8 @@ AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertice
return error;
}
-void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerOptions) {
+void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerOptions)
+{
xaAssert(atlas);
xaAssert(packerOptions.texelArea > 0);
// Chart meshes.
@@ -7285,7 +7612,7 @@ void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerO
atlas->width = packer.getWidth();
atlas->height = packer.getHeight();
// Build output meshes.
- atlas->outputMeshes = new OutputMesh *[atlas->heMeshes.size()];
+ atlas->outputMeshes = new OutputMesh*[atlas->heMeshes.size()];
for (int i = 0; i < (int)atlas->heMeshes.size(); i++) {
const internal::halfedge::Mesh *heMesh = atlas->heMeshes[i];
OutputMesh *outputMesh = atlas->outputMeshes[i] = new OutputMesh;
@@ -7341,27 +7668,32 @@ void Generate(Atlas *atlas, CharterOptions charterOptions, PackerOptions packerO
}
}
-uint32_t GetWidth(const Atlas *atlas) {
+uint32_t GetWidth(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->width;
}
-uint32_t GetHeight(const Atlas *atlas) {
+uint32_t GetHeight(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->height;
}
-uint32_t GetNumCharts(const Atlas *atlas) {
+uint32_t GetNumCharts(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->atlas.chartCount();
}
-const OutputMesh *const *GetOutputMeshes(const Atlas *atlas) {
+const OutputMesh * const *GetOutputMeshes(const Atlas *atlas)
+{
xaAssert(atlas);
return atlas->outputMeshes;
}
-const char *StringForEnum(AddMeshErrorCode::Enum error) {
+const char *StringForEnum(AddMeshErrorCode::Enum error)
+{
if (error == AddMeshErrorCode::AlreadyAddedEdge)
return "already added edge";
if (error == AddMeshErrorCode::DegenerateColocalEdge)