From c3058070e50d9f2873c87fc53f85a06191ab414a Mon Sep 17 00:00:00 2001 From: MarcEricMartel Date: Mon, 18 Sep 2023 15:56:17 -0400 Subject: [PATCH] Projet server. --- SQCSim-common/SQCSim-common.vcxproj | 154 ++ SQCSim-common/SQCSim-common.vcxproj.filters | 72 + SQCSim-common/array2d.h | 61 + SQCSim-common/array3d.h | 55 + SQCSim-common/blockinfo.cpp | 42 + SQCSim-common/blockinfo.h | 32 + SQCSim-common/bullet.cpp | 32 + SQCSim-common/bullet.h | 23 + SQCSim-common/chunk.cpp | 111 + SQCSim-common/chunk.h | 31 + SQCSim-common/define.h | 49 + SQCSim-common/matrix4.h | 571 +++++ SQCSim-common/opensimplex.cpp | 2542 +++++++++++++++++++ SQCSim-common/opensimplex.h | 51 + SQCSim-common/player.cpp | 160 ++ SQCSim-common/player.h | 34 + SQCSim-common/vector3.h | 219 ++ SQCSim-common/world.cpp | 109 + SQCSim-common/world.h | 45 + SQCSim-srv/SQCSim-srv.vcxproj | 138 + SQCSim-srv/SQCSim-srv.vcxproj.filters | 17 + SQCSim2021/SQCSim2021.vcxproj | 8 +- SQCSim2021/define.h | 21 +- SQCSim2021/world.cpp | 36 +- SQCSim2023.sln | 24 +- 25 files changed, 4600 insertions(+), 37 deletions(-) create mode 100644 SQCSim-common/SQCSim-common.vcxproj create mode 100644 SQCSim-common/SQCSim-common.vcxproj.filters create mode 100644 SQCSim-common/array2d.h create mode 100644 SQCSim-common/array3d.h create mode 100644 SQCSim-common/blockinfo.cpp create mode 100644 SQCSim-common/blockinfo.h create mode 100644 SQCSim-common/bullet.cpp create mode 100644 SQCSim-common/bullet.h create mode 100644 SQCSim-common/chunk.cpp create mode 100644 SQCSim-common/chunk.h create mode 100644 SQCSim-common/define.h create mode 100644 SQCSim-common/matrix4.h create mode 100644 SQCSim-common/opensimplex.cpp create mode 100644 SQCSim-common/opensimplex.h create mode 100644 SQCSim-common/player.cpp create mode 100644 SQCSim-common/player.h create mode 100644 SQCSim-common/vector3.h create mode 100644 SQCSim-common/world.cpp create mode 100644 SQCSim-common/world.h create mode 100644 SQCSim-srv/SQCSim-srv.vcxproj create mode 100644 SQCSim-srv/SQCSim-srv.vcxproj.filters diff --git a/SQCSim-common/SQCSim-common.vcxproj b/SQCSim-common/SQCSim-common.vcxproj new file mode 100644 index 0000000..5db21d0 --- /dev/null +++ b/SQCSim-common/SQCSim-common.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {ee91ab12-4225-4a4d-931d-69d72f6d91fb} + SQCSimcommon + 10.0 + + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + true + Unicode + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SQCSim-common/SQCSim-common.vcxproj.filters b/SQCSim-common/SQCSim-common.vcxproj.filters new file mode 100644 index 0000000..af8b625 --- /dev/null +++ b/SQCSim-common/SQCSim-common.vcxproj.filters @@ -0,0 +1,72 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + + + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + Fichiers sources + + + \ No newline at end of file diff --git a/SQCSim-common/array2d.h b/SQCSim-common/array2d.h new file mode 100644 index 0000000..7451365 --- /dev/null +++ b/SQCSim-common/array2d.h @@ -0,0 +1,61 @@ +#ifndef ARRAY2D_H__ +#define ARRAY2D_H__ + +#include "define.h" + +template +class Array2d { + public: + Array2d(int x, int y); + ~Array2d(); + Array2d(const Array2d& array); + + void Set(int x, int y, T type); + T Get(int x, int y) const; + T Remove(int x, int y); + + void Reset(T type); + + private: + int m_x, m_y; + T* m_array; + + int To1dIndex(int x, int y) const; +}; + +template +Array2d::Array2d(int x, int y) : m_x(x), m_y(y) { m_array = new T[m_x * m_y]; } + +template +Array2d::~Array2d() { delete[] m_array; } + +template +Array2d::Array2d(const Array2d& array) : m_x(array.m_x), m_y(array.m_y) { + m_array = new T[m_x * m_y]; + for (int i = 0; i < m_x * m_y; ++i) + m_array[i] = array.m_array[i]; +} + +template +void Array2d::Set(int x, int y, T type) { m_array[To1dIndex(x, y)] = type; } + +template +T Array2d::Get(int x, int y) const { return m_array[To1dIndex(x, y)]; } + +template +T Array2d::Remove(int x, int y) { + T thing = std::move(m_array[To1dIndex(x, y)]); + m_array[To1dIndex(x, y)] = nullptr; + return thing; +} + +template +void Array2d::Reset(T type) { + for (int i = 0; i < m_x * m_y; ++i) + m_array[i] = type; +} + +template +int Array2d::To1dIndex(int x, int y) const { return x + (y * m_x); } + +#endif // ARRAY2D_H__ diff --git a/SQCSim-common/array3d.h b/SQCSim-common/array3d.h new file mode 100644 index 0000000..97603ef --- /dev/null +++ b/SQCSim-common/array3d.h @@ -0,0 +1,55 @@ +#ifndef ARRAY3D_H__ +#define ARRAY3D_H__ + +#include "define.h" + +template +class Array3d { + public: + Array3d(int x, int y, int z); + ~Array3d(); + Array3d(const Array3d& array); + + void Set(int x, int y, int z, T type); + T Get(int x, int y, int z) const; + + void Reset(T type); + + private: + int m_x, m_y, m_z; + T* m_array; + + int To1dIndex(int x, int y, int z) const; +}; + +template +Array3d::Array3d(int x, int y, int z) : m_x(x), m_y(y), m_z(z) { m_array = new T[m_x * m_y * m_z]; } + +template +Array3d::~Array3d() { delete[] m_array; } + +template +Array3d::Array3d(const Array3d& array) : m_x(array.m_x), m_y(array.m_y), m_z(array.m_z) { + m_array = new T[m_x * m_y * m_z]; + for (int i = 0; i < m_x * m_y * m_z; ++i) + m_array[i] = array.m_array[i]; +} + +template +void Array3d::Set(int x, int y, int z, T type) { + m_array[To1dIndex(x, y, z)] = type; +} + +template +T Array3d::Get(int x, int y, int z) const { return m_array[To1dIndex(x, y, z)]; } + +template +void Array3d::Reset(T type) { + for (int i = 0; i < m_x * m_y * m_z; ++i) + m_array[i] = type; +} + +template +int Array3d::To1dIndex(int x, int y, int z) const { return x + (z * m_x) + (y * m_z * m_x); } + +#endif // ARRAY3D_H__ diff --git a/SQCSim-common/blockinfo.cpp b/SQCSim-common/blockinfo.cpp new file mode 100644 index 0000000..1e42825 --- /dev/null +++ b/SQCSim-common/blockinfo.cpp @@ -0,0 +1,42 @@ +#include "blockinfo.h" +#include + +BlockInfo::BlockInfo(BlockType type, const std::string& name, float u, float v, float s, int dur) : m_type(type), m_name(name), m_u(u), m_v(v), m_s(s), m_durability(dur) +{ +} + +BlockInfo::~BlockInfo() +{ +} + +BlockType BlockInfo::GetType() const +{ + return m_type; +} + +void BlockInfo::SetDurability(int durability) +{ + m_durability = durability; +} + +int BlockInfo::GetDurability() const +{ + return m_durability; +} + +void BlockInfo::GetTexture(float& u, float& v, float& s) +{ + u = m_u; + v = m_v; + s = m_s; +} + +void BlockInfo::Show() const +{ + std::cout << "Type: " << m_type << std::endl; + std::cout << "Nom: " << m_name << std::endl; + std::cout << "Durabilite: " << m_durability << std::endl; + std::cout << "Coordonnees Texture: " << m_u << ", " << m_v << ", " << m_s << std::endl; +} + + diff --git a/SQCSim-common/blockinfo.h b/SQCSim-common/blockinfo.h new file mode 100644 index 0000000..8a2afe7 --- /dev/null +++ b/SQCSim-common/blockinfo.h @@ -0,0 +1,32 @@ +#ifndef BLOCKINFO_H__ +#define BLOCKINFO_H__ + +#include +#include "define.h" + +class BlockInfo +{ + public: + BlockInfo(BlockType type, const std::string& name, float u, float v, float s, int dur); + ~BlockInfo(); + + BlockType GetType() const; + + void SetDurability(int durability); + int GetDurability() const; + + void GetTexture(float& u, float& v, float& s); + + void Show() const; + + private: + BlockType m_type; + float m_u; + float m_v; + float m_s; + std::string m_name; + int m_durability; + +}; + +#endif // BLOCKINFO_H__ diff --git a/SQCSim-common/bullet.cpp b/SQCSim-common/bullet.cpp new file mode 100644 index 0000000..c06c9e7 --- /dev/null +++ b/SQCSim-common/bullet.cpp @@ -0,0 +1,32 @@ +#include "bullet.h" +#include "world.h" + +Bullet::Bullet(Player& player) { + m_startpos = m_currentpos = player.GetPOV() + player.GetDirection(); + m_velocity = player.GetDirection(); +} + +Bullet::~Bullet() {} + +bool Bullet::Update(World* world, float elapsedtime) { + for (int x = 0; x < 1000; ++x) { + m_currentpos += m_velocity * elapsedtime; + + if (!world->ChunkAt(m_currentpos)) + return true; + else if (world->BlockAt(m_currentpos) != BTYPE_AIR) { + world->ChangeBlockAtPosition(BTYPE_AIR, m_currentpos); + return true; + } + else if ((m_currentpos - m_startpos).Length() > VIEW_DISTANCE) return true; + } + + return false; +} + +void Bullet::Transpose(int& x, int& z) { + m_currentpos.x -= x * CHUNK_SIZE_X; + m_currentpos.z -= z * CHUNK_SIZE_Z; + m_startpos.x -= x * CHUNK_SIZE_X; + m_startpos.z -= z * CHUNK_SIZE_Z; +} diff --git a/SQCSim-common/bullet.h b/SQCSim-common/bullet.h new file mode 100644 index 0000000..de2e14c --- /dev/null +++ b/SQCSim-common/bullet.h @@ -0,0 +1,23 @@ +#ifndef BULLET_H__ +#define BULLET_H__ + +#include "player.h" + +class World; + +class Bullet { +public: + Bullet(Player& player); + ~Bullet(); + + bool Update(World* world, float elapsedtime); + void Transpose(int& x, int& z); + +private: + Vector3f m_startpos; + Vector3f m_currentpos; + Vector3f m_velocity; +}; + +#endif // BULLET_H__ + diff --git a/SQCSim-common/chunk.cpp b/SQCSim-common/chunk.cpp new file mode 100644 index 0000000..7bfc690 --- /dev/null +++ b/SQCSim-common/chunk.cpp @@ -0,0 +1,111 @@ +#include "chunk.h" +#include "world.h" + +Chunk::Chunk(unsigned int x, unsigned int y) : m_posX(x), m_posY(y) { + //std::ostringstream pos; // Vérifie l'existence d'un fichier .chunk avec sa position. + //pos << CHUNK_PATH << x << '_' << y << ".chunk"; + //std::ifstream input(pos.str(), std::fstream::binary); + + //if (input.fail()) { + OpenSimplexNoise::Noise simplex = OpenSimplexNoise::Noise(SEED); + m_blocks.Reset(BTYPE_AIR); + + for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // Montagnes + for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { + float xnoiz, ynoiz; + xnoiz = (double)(ix + x * CHUNK_SIZE_X) / 4096.; + ynoiz = (double)(iz + y * CHUNK_SIZE_Z) / 4096.; + double height = 0; + for (int x = 0; x < 39; ++x) { + height += simplex.eval(xnoiz, ynoiz); + height *= .79; + xnoiz *= 1.139; + ynoiz *= 1.139; + } + height = height * 2000. * simplex.eval((double)(ix + x * CHUNK_SIZE_X) / 512., (double)(iz + y * CHUNK_SIZE_Z) / 512.); + height /= (CHUNK_SIZE_Y / 1.9); + height += 15.; + for (int iy = 0; iy <= (int)height % CHUNK_SIZE_Y; ++iy) + SetBlock(ix, iy, iz, BTYPE_METAL, nullptr); + } + for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // Collines + for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { + float xnoiz, ynoiz; + xnoiz = (double)(ix + x * CHUNK_SIZE_X) / 512.; + ynoiz = (double)(iz + y * CHUNK_SIZE_Z) / 512.; + float height = simplex.eval(xnoiz, ynoiz) * 50.f;// +1.f; + for (int iy = 0; iy <= (int)height % CHUNK_SIZE_Y; ++iy) { + if (GetBlock(ix, iy, iz) == BTYPE_AIR) + SetBlock(ix, iy, iz, BTYPE_GRASS, nullptr); + } + } + for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // "Lacs" + for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { + for (int iy = 0; iy < 13; ++iy) { + if (GetBlock(ix, iy, iz) == BTYPE_AIR) + SetBlock(ix, iy, iz, BTYPE_ICE, nullptr); + } + } + //for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // "Arbres" + // for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { + // float xnoiz, ynoiz; + // xnoiz = (double)(iz * CHUNK_SIZE_Y + x * CHUNK_SIZE_X) / 256.; + // ynoiz = (double)(ix * CHUNK_SIZE_Y + y * CHUNK_SIZE_Z) / 256.; + // bool tree = (int)(abs(simplex.eval(xnoiz, ynoiz)) * 17933.f) % CHUNK_SIZE_Y > 126 ? true : false; + // for (int iy = 0; iy < CHUNK_SIZE_Y - 10; ++iy) + // if (GetBlock(ix, iy, iz) == BTYPE_AIR) + // if (GetBlock(ix, iy - 1, iz) == BTYPE_GRASS) + // if (tree) { + // for (int i = 0; i < (int)(abs(simplex.eval(xnoiz, ynoiz) * 4)) % 42 + 1; ++i) + // SetBlock(ix, iy + i, iz, BTYPE_DIRT, nullptr); + // break; + // } + // } + /* } + else { + input.seekg(0, std::ios_base::end); + int size = input.tellg(); + input.seekg(0, std::ios_base::beg); + + char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]; + input.read(data, size); + input.close(); + + for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) + for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) + for (int iy = 0; iy < CHUNK_SIZE_Y; ++iy) + m_blocks.Set(ix, iy, iz, data[ix + (iz * CHUNK_SIZE_X) + (iy * CHUNK_SIZE_Z * CHUNK_SIZE_X)]); + }*/ +} + +Chunk::~Chunk() { + /*if (m_isModified) { + char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]; + + for (int x = 0; x < CHUNK_SIZE_X; ++x) + for (int z = 0; z < CHUNK_SIZE_Z; ++z) + for (int y = 0; y < CHUNK_SIZE_Y; ++y) + data[x + (z * CHUNK_SIZE_X) + (y * CHUNK_SIZE_Z * CHUNK_SIZE_X)] = (char)GetBlock(x, y, z); + + std::ostringstream pos; + pos << CHUNK_PATH << m_posX << '_' << m_posY << ".chunk"; + + std::ofstream output(pos.str(), std::fstream::binary); + output.write(data, sizeof(data)); + output.close(); + }*/ +} + +void Chunk::RemoveBlock(int x, int y, int z, World* world) { + m_blocks.Set(x, y, z, BTYPE_AIR); +} + +void Chunk::SetBlock(int x, int y, int z, BlockType type, World* world) { + m_blocks.Set(x, y, z, type); +} + +BlockType Chunk::GetBlock(int x, int y, int z) { return m_blocks.Get(x, y, z); } + +void Chunk::GetPosition(unsigned int& x, unsigned int& y) const { x = m_posX; y = m_posY; } + +void Chunk::MakeModified() { m_isModified = true; } diff --git a/SQCSim-common/chunk.h b/SQCSim-common/chunk.h new file mode 100644 index 0000000..ec015ba --- /dev/null +++ b/SQCSim-common/chunk.h @@ -0,0 +1,31 @@ +#ifndef CHUNK_H__ +#define CHUNK_H__ +#include "define.h" +#include "array3d.h" +#include "array2d.h" +#include "blockinfo.h" +#include "opensimplex.h" + +class World; + +class Chunk { + protected: + Array3d m_blocks = Array3d(CHUNK_SIZE_X, CHUNK_SIZE_Y, CHUNK_SIZE_Z); + bool m_isModified = false; + + unsigned int m_posX; // Position du chunk dans l'array constituant le monde. + unsigned int m_posY; + + public: + Chunk(unsigned int x, unsigned int y); + ~Chunk(); + + void RemoveBlock(int x, int y, int z, World* world); + void SetBlock(int x, int y, int z, BlockType type, World* world); + BlockType GetBlock(int x, int y, int z); + void GetPosition(unsigned int& x, unsigned int& y) const; + + void MakeModified(); +}; + +#endif // CHUNK_H__ diff --git a/SQCSim-common/define.h b/SQCSim-common/define.h new file mode 100644 index 0000000..aea5ea2 --- /dev/null +++ b/SQCSim-common/define.h @@ -0,0 +1,49 @@ +#ifndef DEFINE_H__ +#define DEFINE_H__ + +#include + +#define CHUNK_SIZE_X 16 +#define CHUNK_SIZE_Y 128 +#define CHUNK_SIZE_Z 16 +#define MAX_SELECTION_DISTANCE 5 +#define SEED 12345 + +#ifdef _DEBUG +#define WORLD_SIZE_X 64 +#define WORLD_SIZE_Y 64 + +#define FRAMES_RENDER_CHUNKS 4 +#define FRAMES_UPDATE_CHUNKS 4 +#define FRAMES_DELETE_CHUNKS 4 + +#define THREADS_GENERATE_CHUNKS 1 +#define THREADS_UPDATE_CHUNKS 1 +#define THREADS_DELETE_CHUNKS 1 + +#define VIEW_DISTANCE 256 +#define TEXTURE_SIZE 128 +#define MAX_BULLETS 64 +#endif + +#ifdef NDEBUG +#define WORLD_SIZE_X 16 +#define WORLD_SIZE_Y 16 + +#define FRAMES_RENDER_CHUNKS 1 +#define FRAMES_UPDATE_CHUNKS 1 +#define FRAMES_DELETE_CHUNKS 1 + +#define THREADS_GENERATE_CHUNKS 12 +#define THREADS_UPDATE_CHUNKS 5 +#define THREADS_DELETE_CHUNKS 2 + +#define VIEW_DISTANCE 1024 +#define TEXTURE_SIZE 512 +#define MAX_BULLETS 512 +#endif + +typedef uint8_t BlockType; +enum BLOCK_TYPE { BTYPE_AIR, BTYPE_DIRT, BTYPE_GRASS, BTYPE_METAL, BTYPE_ICE, BTYPE_LAST }; + +#endif // DEFINE_H__ diff --git a/SQCSim-common/matrix4.h b/SQCSim-common/matrix4.h new file mode 100644 index 0000000..a0d911a --- /dev/null +++ b/SQCSim-common/matrix4.h @@ -0,0 +1,571 @@ +#ifndef MATRIX4_H__ +#define MATRIX4_H__ + +#include +#include +#include + +#include "define.h" +#include "vector3.h" + +#ifndef M_PI +#define M_PI 3.14159265f +#endif + +#define DEGTORAD(x) ((x * M_PI) / 180.f) +#define RADTODEG(x) ((180.f * x) / M_PI) + +template +class Matrix4 +{ + public: + typedef T Type; + + public: + static const Matrix4 ZERO; + static const Matrix4 IDENTITY; + + public: + Matrix4(); + Matrix4(const T& v); + Matrix4(const Matrix4& m); + Matrix4(const T& m_11, const T& m_12, const T& m_13, const T& m_14, + const T& m_21, const T& m_22, const T& m_23, const T& m_24, + const T& m_31, const T& m_32, const T& m_33, const T& m_34, + const T& m_41, const T& m_42, const T& m_43, const T& m_44); + + const T& Get11() const; + const T& Get12() const; + const T& Get13() const; + const T& Get14() const; + const T& Get21() const; + const T& Get22() const; + const T& Get23() const; + const T& Get24() const; + const T& Get31() const; + const T& Get32() const; + const T& Get33() const; + const T& Get34() const; + const T& Get41() const; + const T& Get42() const; + const T& Get43() const; + const T& Get44() const; + + Matrix4& operator=(const Matrix4& m); + + Matrix4 operator+(const Matrix4& m) const; + const Matrix4& operator+=(const Matrix4& m); + + Matrix4 operator-(const Matrix4& m) const; + Matrix4 operator-() const; + const Matrix4& operator-=(const Matrix4& m); + + Matrix4 operator*(const Matrix4& m) const; + Matrix4 operator*(const T& v) const; + const Matrix4& operator*=(const Matrix4& m); + const Matrix4& operator*=(const T& v); + + Matrix4 operator/(const T& v) const; + const Matrix4& operator/=(const T& v); + + bool operator==(const Matrix4& m) const; + bool operator!=(const Matrix4& m) const; + + void SetZero(); + void SetIdentity(); + void SetPerspectiveProjection(const T& fov, const T& aspect, const T& nearPlane, const T& farPlane); + void SetOrthographicProjection(const T& left, const T& right, const T& bottom, const T& top, const T& nearPlane, const T& farPlane); + + void SetLookAt(const Vector3& eyePosition, const Vector3& lookAtPosition, Vector3 upVector = Vector3(T(0), T(1), T(0))); + + bool IsZero() const; + bool IsIdentity() const; + + void ApplyTranslation(const T& x, const T& y, const T& z); + void ApplyRotation(const T& angle, const T& x, const T& y, const T& z); + void ApplyScale(const T& x, const T& y, const T& z); + + Vector3 GetTranslation() const; + + const T* GetInternalValues() const; + T* GetInternalValues(); + std::string ToString(const std::string& lineBegin = "|", const std::string& lineEnd = "|\n") const; + + private: + union { + // column-major matrix + struct + { + T m_11, m_21, m_31, m_41, m_12, m_22, m_32, m_42, m_13, m_23, m_33, m_43, m_14, m_24, m_34, m_44; + }; + T m_values[16]; + }; +}; + +typedef Matrix4 Matrix4i; +typedef Matrix4 Matrix4f; +typedef Matrix4 Matrix4d; + +template +const Matrix4 Matrix4::ZERO = Matrix4(0); + +template +const Matrix4 Matrix4::IDENTITY = Matrix4( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + + template +std::ostream& operator<<(std::ostream& out, const Matrix4& m) +{ + out << m.ToString(); + return out; +} + + template +Matrix4::Matrix4() +{ + // Leave matrix uninitialized +} + + template +Matrix4::Matrix4(const T& v) +{ + for(int i = 0; i < 16; ++i) + m_values[i] = v; +} + + template +Matrix4::Matrix4(const Matrix4& m) +{ + for(int i = 0; i < 16; ++i) + m_values[i] = m.m_values[i]; +} + + template +Matrix4::Matrix4(const T& m_11, const T& m_12, const T& m_13, const T& m_14, + const T& m_21, const T& m_22, const T& m_23, const T& m_24, + const T& m_31, const T& m_32, const T& m_33, const T& m_34, + const T& m_41, const T& m_42, const T& m_43, const T& m_44) +{ + this->m_11 = m_11; + this->m_12 = m_12; + this->m_13 = m_13; + this->m_14 = m_14; + this->m_21 = m_21; + this->m_22 = m_22; + this->m_23 = m_23; + this->m_24 = m_24; + this->m_31 = m_31; + this->m_32 = m_32; + this->m_33 = m_33; + this->m_34 = m_34; + this->m_41 = m_41; + this->m_42 = m_42; + this->m_43 = m_43; + this->m_44 = m_44; +} + +template +const T& Matrix4::Get11() const +{ + return m_11; +} + +template +const T& Matrix4::Get12() const +{ + return m_12; +} + +template +const T& Matrix4::Get13() const +{ + return m_13; +} + +template +const T& Matrix4::Get14() const +{ + return m_14; +} + +template +const T& Matrix4::Get21() const +{ + return m_21; +} + +template +const T& Matrix4::Get22() const +{ + return m_22; +} + +template +const T& Matrix4::Get23() const +{ + return m_23; +} + +template +const T& Matrix4::Get24() const +{ + return m_24; +} + +template +const T& Matrix4::Get31() const +{ + return m_31; +} + +template +const T& Matrix4::Get32() const +{ + return m_32; +} + +template +const T& Matrix4::Get33() const +{ + return m_33; +} + +template +const T& Matrix4::Get34() const +{ + return m_34; +} + +template +const T& Matrix4::Get41() const +{ + return m_41; +} + +template +const T& Matrix4::Get42() const +{ + return m_42; +} + +template +const T& Matrix4::Get43() const +{ + return m_43; +} + +template +const T& Matrix4::Get44() const +{ + return m_44; +} + + template +Matrix4& Matrix4::operator=(const Matrix4& m) +{ + if(this != &m) + { + for(int i = 0; i < 16; ++i) + m_values[i] = m.m_values[i]; + } + + return *this; +} + +template +Matrix4 Matrix4::operator+(const Matrix4& m) const +{ + return Matrix4( + m_11 + m.m_11, m_12 + m.m_12, m_13 + m.m_13, m_14 + m.m_14, + m_21 + m.m_21, m_22 + m.m_22, m_23 + m.m_23, m_24 + m.m_24, + m_31 + m.m_31, m_32 + m.m_32, m_33 + m.m_33, m_34 + m.m_34, + m_41 + m.m_41, m_42 + m.m_42, m_43 + m.m_43, m_44 + m.m_44); +} + + template +const Matrix4& Matrix4::operator+=(const Matrix4& m) +{ + *this = *this + m; + return *this; +} + +template +Matrix4 Matrix4::operator-(const Matrix4& m) const +{ + return Matrix4( + m_11 - m.m_11, m_12 - m.m_12, m_13 - m.m_13, m_14 - m.m_14, + m_21 - m.m_21, m_22 - m.m_22, m_23 - m.m_23, m_24 - m.m_24, + m_31 - m.m_31, m_32 - m.m_32, m_33 - m.m_33, m_34 - m.m_34, + m_41 - m.m_41, m_42 - m.m_42, m_43 - m.m_43, m_44 - m.m_44); +} + +template +Matrix4 Matrix4::operator-() const +{ + return Matrix4( + -m_11, -m_12, -m_13, -m_14, + -m_21, -m_22, -m_23, -m_24, + -m_31, -m_32, -m_33, -m_34, + -m_41, -m_42, -m_43, -m_44); +} + + template +const Matrix4& Matrix4::operator-=(const Matrix4& m) +{ + *this = *this - m; + return *this; +} + +template +Matrix4 Matrix4::operator*(const Matrix4& m) const +{ + return Matrix4( + m_11 * m.m_11 + m_12 * m.m_21 + m_13 * m.m_31 + m_14 * m.m_41, + m_11 * m.m_12 + m_12 * m.m_22 + m_13 * m.m_32 + m_14 * m.m_42, + m_11 * m.m_13 + m_12 * m.m_23 + m_13 * m.m_33 + m_14 * m.m_43, + m_11 * m.m_14 + m_12 * m.m_24 + m_13 * m.m_34 + m_14 * m.m_44, + + m_21 * m.m_11 + m_22 * m.m_21 + m_23 * m.m_31 + m_24 * m.m_41, + m_21 * m.m_12 + m_22 * m.m_22 + m_23 * m.m_32 + m_24 * m.m_42, + m_21 * m.m_13 + m_22 * m.m_23 + m_23 * m.m_33 + m_24 * m.m_43, + m_21 * m.m_14 + m_22 * m.m_24 + m_23 * m.m_34 + m_24 * m.m_44, + + m_31 * m.m_11 + m_32 * m.m_21 + m_33 * m.m_31 + m_34 * m.m_41, + m_31 * m.m_12 + m_32 * m.m_22 + m_33 * m.m_32 + m_34 * m.m_42, + m_31 * m.m_13 + m_32 * m.m_23 + m_33 * m.m_33 + m_34 * m.m_43, + m_31 * m.m_14 + m_32 * m.m_24 + m_33 * m.m_34 + m_34 * m.m_44, + + m_41 * m.m_11 + m_42 * m.m_21 + m_43 * m.m_31 + m_44 * m.m_41, + m_41 * m.m_12 + m_42 * m.m_22 + m_43 * m.m_32 + m_44 * m.m_42, + m_41 * m.m_13 + m_42 * m.m_23 + m_43 * m.m_33 + m_44 * m.m_43, + m_41 * m.m_14 + m_42 * m.m_24 + m_43 * m.m_34 + m_44 * m.m_44); +} + +template +Matrix4 Matrix4::operator*(const T& v) const +{ + return Matrix4( + m_11 * v, m_12 * v, m_13 * v, m_14 * v, + m_21 * v, m_22 * v, m_23 * v, m_24 * v, + m_31 * v, m_32 * v, m_33 * v, m_34 * v, + m_41 * v, m_42 * v, m_43 * v, m_44 * v); +} + + template +const Matrix4& Matrix4::operator*=(const Matrix4& m) +{ + *this = *this * m; + return *this; +} + + template +const Matrix4& Matrix4::operator*=(const T& v) +{ + *this = *this * v; + return *this; +} + +template +Matrix4 Matrix4::operator/(const T& v) const +{ + return Matrix4( + m_11 / v, m_12 / v, m_13 / v, m_14 / v, + m_21 / v, m_22 / v, m_23 / v, m_24 / v, + m_31 / v, m_32 / v, m_33 / v, m_34 / v, + m_41 / v, m_42 / v, m_43 / v, m_44 / v); +} + + template +const Matrix4& Matrix4::operator/=(const T& v) +{ + *this = *this / v; + return *this; +} + +template +bool Matrix4::operator==(const Matrix4& m) const +{ + for(int i = 0; i < 16; ++i) + if(m_values[i] != m.m_values[i]) + return false; + + return true; +} + +template +bool Matrix4::operator!=(const Matrix4& m) const +{ + return !(*this == m); +} + + template +void Matrix4::SetZero() +{ + *this = ZERO; +} + + template +void Matrix4::SetIdentity() +{ + *this = IDENTITY; +} + + template +void Matrix4::SetPerspectiveProjection(const T& fov, const T& aspect, const T& nearPlane, const T& farPlane) +{ + const float h = T(1) / tan(fov * T(M_PI / 360.f)); + T negDepth = nearPlane - farPlane; + + SetZero(); + + m_11 = h / aspect; + m_22 = h; + m_33 = (farPlane + nearPlane) / negDepth; + m_34 = T(2) * (nearPlane * farPlane) / negDepth; + m_43 = -T(1); +} + + template +void Matrix4::SetOrthographicProjection(const T& left, const T& right, const T& bottom, const T& top, const T& nearPlane, const T& farPlane) +{ + m_11 = T(2) / (right - left); + m_12 = T(0); + m_13 = T(0); + m_14 = -(right + left) / (right - left); + + m_21 = T(0); + m_22 = T(2) / (top - bottom); + m_23 = T(0); + m_24 = -(top + bottom) / (top - bottom); + + m_31 = T(0); + m_32 = T(0); + m_33 = -T(2) / (farPlane - nearPlane); + m_34 = -(farPlane + nearPlane) / (farPlane - nearPlane); + + m_41 = T(0); + m_42 = T(0); + m_43 = T(0); + m_44 = T(1); +} + + template +void Matrix4::SetLookAt(const Vector3& eyePosition, const Vector3& lookAtPosition, Vector3 upVector) +{ + Vector3f L = lookAtPosition - eyePosition; + L.Normalize(); + + upVector.Normalize(); + Vector3f S = L.Cross(upVector); + S.Normalize(); + + Vector3f U = S.Cross(L); + + Matrix4 M; + M.m_11 = S.x; + M.m_12 = S.y; + M.m_13 = S.z; + M.m_14 = 0; + + M.m_21 = U.x; + M.m_22 = U.y; + M.m_23 = U.z; + M.m_24 = 0; + + M.m_31 = -L.x; + M.m_32 = -L.y; + M.m_33 = -L.z; + M.m_34 = 0; + + M.m_41 = 0; + M.m_42 = 0; + M.m_43 = 0; + M.m_44 = 1.f; + + SetIdentity(); + *this *= M; + ApplyTranslation(-eyePosition.x, -eyePosition.y, -eyePosition.z); +} + + template +void Matrix4::ApplyTranslation(const T& x, const T& y, const T& z) +{ + Matrix4 tmp( + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1); + + *this *= tmp; +} + + template +void Matrix4::ApplyRotation(const T& angle, const T& x, const T& y, const T& z) +{ + // TODO axis (x, y, z) must be normalized... + + T s = sin(DEGTORAD(angle)); + T c = cos(DEGTORAD(angle)); + T ic = T(1) - c; + + Matrix4 tmp( + x * x * ic + c, y * x * ic + (z * s), z * x * ic - (y * s), 0, + x * y * ic - (z * s), y * y * ic + c, z * y * ic + (x * s), 0, + x * z * ic + (y * s), y * z * ic - (x * s), z * z * ic + c, 0, + 0, 0, 0, 1); + + *this *= tmp; +} + + template +void Matrix4::ApplyScale(const T& x, const T& y, const T& z) +{ + Matrix4 tmp( + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1); + + *this *= tmp; +} + +template +Vector3 Matrix4::GetTranslation() const +{ + // NOTE: Works only if the matrix doesn't contains scale information (only rotation and translation) + // Reference: http://www.gamedev.net/topic/397751-how-to-get-camera-position/ + T x = -(m_11 * m_14 + m_21 * m_24 + m_31 * m_34); + T y = -(m_12 * m_14 + m_22 * m_24 + m_32 * m_34); + T z = -(m_13 * m_14 + m_23 * m_24 + m_33 * m_34); + + return Vector3(x, y, z); +} + + template +T* Matrix4::GetInternalValues() +{ + return m_values; +} + +template +const T* Matrix4::GetInternalValues() const +{ + return m_values; +} + +template +std::string Matrix4::ToString(const std::string& lineBegin, const std::string& lineEnd) const +{ + std::ostringstream ss; + ss << lineBegin << m_11 << " " << m_12 << " " << m_13 << " " << m_14 << lineEnd; + ss << lineBegin << m_21 << " " << m_22 << " " << m_23 << " " << m_24 << lineEnd; + ss << lineBegin << m_31 << " " << m_32 << " " << m_33 << " " << m_34 << lineEnd; + ss << lineBegin << m_41 << " " << m_42 << " " << m_43 << " " << m_44 << lineEnd; + + return ss.str(); +} + +#endif // MATRIX4_H__ diff --git a/SQCSim-common/opensimplex.cpp b/SQCSim-common/opensimplex.cpp new file mode 100644 index 0000000..a64d31f --- /dev/null +++ b/SQCSim-common/opensimplex.cpp @@ -0,0 +1,2542 @@ +#include "opensimplex.h" + +#include +namespace OpenSimplexNoise +{ + using namespace std; + + Noise::Noise() + : m_stretch2d(-0.211324865405187) //(1/Math.sqrt(2+1)-1)/2; + , m_squish2d(0.366025403784439) //(Math.sqrt(2+1)-1)/2; + , m_stretch3d(-1.0 / 6) //(1/Math.sqrt(3+1)-1)/3; + , m_squish3d(1.0 / 3) //(Math.sqrt(3+1)-1)/3; + , m_stretch4d(-0.138196601125011) //(1/Math.sqrt(4+1)-1)/4; + , m_squish4d(0.309016994374947) //(Math.sqrt(4+1)-1)/4; + , m_norm2d(47) + , m_norm3d(103) + , m_norm4d(30) + , m_defaultSeed(0) + , m_perm{0} + , m_permGradIndex3d{0} + , m_gradients2d{ 5, 2, 2, 5, + -5, 2, -2, 5, + 5, -2, 2, -5, + -5, -2, -2, -5, } + , m_gradients3d{-11, 4, 4, -4, 11, 4, -4, 4, 11, + 11, 4, 4, 4, 11, 4, 4, 4, 11, + -11, -4, 4, -4, -11, 4, -4, -4, 11, + 11, -4, 4, 4, -11, 4, 4, -4, 11, + -11, 4, -4, -4, 11, -4, -4, 4, -11, + 11, 4, -4, 4, 11, -4, 4, 4, -11, + -11, -4, -4, -4, -11, -4, -4, -4, -11, + 11, -4, -4, 4, -11, -4, 4, -4, -11, } + , m_gradients4d{ 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, + -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, + 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, + -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, + 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, + -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, + 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, + -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, + 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, + -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, + 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, + -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, + 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, + -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, + 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, + -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, } + { + } + + Noise::Noise(int64_t seed) + : Noise() + { + short source[256]; + for (short i = 0; i < 256; i++) + { + source[i] = i; + } + seed = seed * 6364136223846793005l + 1442695040888963407l; + seed = seed * 6364136223846793005l + 1442695040888963407l; + seed = seed * 6364136223846793005l + 1442695040888963407l; + for (int i = 255; i >= 0; i--) + { + seed = seed * 6364136223846793005l + 1442695040888963407l; + int r = static_cast((seed + 31) % (i + 1)); + if (r < 0) + { + r += (i + 1); + } + m_perm[i] = source[r]; + m_permGradIndex3d[i] = static_cast((m_perm[i] % (m_gradients3d.size() / 3)) * 3); + source[r] = source[i]; + } + } + + double Noise::eval(double x, double y) const + { + //Place input coordinates onto grid. + double stretchOffset = (x + y) * m_stretch2d; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + + //Floor to get grid coordinates of rhombus (stretched square) super-cell origin. + int xsb = static_cast(floor(xs)); + int ysb = static_cast(floor(ys)); + + //Skew out to get actual coordinates of rhombus origin. We'll need these later. + double squishOffset = (xsb + ysb) * m_squish2d; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + + //Compute grid coordinates relative to rhombus origin. + double xins = xs - xsb; + double yins = ys - ysb; + + //Sum those together to get a value that determines which region we're in. + double inSum = xins + yins; + + //Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + + //We'll be defining these inside the next block and using them afterwards. + double dx_ext, dy_ext; + int xsv_ext, ysv_ext; + + double value = 0; + + //Contribution (1,0) + double dx1 = dx0 - 1 - m_squish2d; + double dy1 = dy0 - 0 - m_squish2d; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1); + } + + //Contribution (0,1) + double dx2 = dx0 - 0 - m_squish2d; + double dy2 = dy0 - 1 - m_squish2d; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2); + } + + if (inSum <= 1) + { //We're inside the triangle (2-Simplex) at (0,0) + double zins = 1 - inSum; + if (zins > xins || zins > yins) + { //(0,0) is one of the closest two triangular vertices + if (xins > yins) + { + xsv_ext = xsb + 1; + ysv_ext = ysb - 1; + dx_ext = dx0 - 1; + dy_ext = dy0 + 1; + } + else + { + xsv_ext = xsb - 1; + ysv_ext = ysb + 1; + dx_ext = dx0 + 1; + dy_ext = dy0 - 1; + } + } + else + { //(1,0) and (0,1) are the closest two vertices. + xsv_ext = xsb + 1; + ysv_ext = ysb + 1; + dx_ext = dx0 - 1 - 2 * m_squish2d; + dy_ext = dy0 - 1 - 2 * m_squish2d; + } + } + else + { //We're inside the triangle (2-Simplex) at (1,1) + double zins = 2 - inSum; + if (zins < xins || zins < yins) + { //(0,0) is one of the closest two triangular vertices + if (xins > yins) + { + xsv_ext = xsb + 2; + ysv_ext = ysb + 0; + dx_ext = dx0 - 2 - 2 * m_squish2d; + dy_ext = dy0 + 0 - 2 * m_squish2d; + } + else + { + xsv_ext = xsb + 0; + ysv_ext = ysb + 2; + dx_ext = dx0 + 0 - 2 * m_squish2d; + dy_ext = dy0 - 2 - 2 * m_squish2d; + } + } + else + { //(1,0) and (0,1) are the closest two vertices. + dx_ext = dx0; + dy_ext = dy0; + xsv_ext = xsb; + ysv_ext = ysb; + } + xsb += 1; + ysb += 1; + dx0 = dx0 - 1 - 2 * m_squish2d; + dy0 = dy0 - 1 - 2 * m_squish2d; + } + + //Contribution (0,0) or (1,1) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0; + if (attn0 > 0) + { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0); + } + + //Extra Vertex + double attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext; + if (attn_ext > 0) + { + attn_ext *= attn_ext; + value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext); + } + + return value / m_norm2d; + } + + double Noise::eval(double x, double y, double z) const + { + //Place input coordinates on simplectic honeycomb. + double stretchOffset = (x + y + z) * m_stretch3d; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + double zs = z + stretchOffset; + + //static_cast(floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin. + int xsb = static_cast(floor(xs)); + int ysb = static_cast(floor(ys)); + int zsb = static_cast(floor(zs)); + + //Skew out to get actual coordinates of rhombohedron origin. We'll need these later. + double squishOffset = (xsb + ysb + zsb) * m_squish3d; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + double zb = zsb + squishOffset; + + //Compute simplectic honeycomb coordinates relative to rhombohedral origin. + double xins = xs - xsb; + double yins = ys - ysb; + double zins = zs - zsb; + + //Sum those together to get a value that determines which region we're in. + double inSum = xins + yins + zins; + + //Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + double dz0 = z - zb; + + //We'll be defining these inside the next block and using them afterwards. + double dx_ext0, dy_ext0, dz_ext0; + double dx_ext1, dy_ext1, dz_ext1; + int xsv_ext0, ysv_ext0, zsv_ext0; + int xsv_ext1, ysv_ext1, zsv_ext1; + + double value = 0; + if (inSum <= 1) + { //We're inside the tetrahedron (3-Simplex) at (0,0,0) + +//Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest. + char aPoint = 0x01; + double aScore = xins; + char bPoint = 0x02; + double bScore = yins; + if (aScore >= bScore && zins > bScore) + { + bScore = zins; + bPoint = 0x04; + } + else if (aScore < bScore && zins > aScore) + { + aScore = zins; + aPoint = 0x04; + } + + //Now we determine the two lattice points not part of the tetrahedron that may contribute. + //This depends on the closest two tetrahedral vertices, including (0,0,0) + double wins = 1 - inSum; + if (wins > aScore || wins > bScore) + { //(0,0,0) is one of the closest two tetrahedral vertices. + char c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + + if ((c & 0x01) == 0) + { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1; + dx_ext1 = dx0; + } + else + { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1; + } + + if ((c & 0x02) == 0) + { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0; + if ((c & 0x01) == 0) + { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + else + { + ysv_ext0 -= 1; + dy_ext0 += 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1; + } + + if ((c & 0x04) == 0) + { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0; + dz_ext1 = dz0 + 1; + } + else + { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1; + } + } + else + { //(0,0,0) is not one of the closest two tetrahedral vertices. + char c = static_cast(aPoint | bPoint); //Our two extra vertices are determined by the closest two. + + if ((c & 0x01) == 0) + { + xsv_ext0 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 2 * m_squish3d; + dx_ext1 = dx0 + 1 - m_squish3d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 1 - 2 * m_squish3d; + dx_ext1 = dx0 - 1 - m_squish3d; + } + + if ((c & 0x02) == 0) + { + ysv_ext0 = ysb; + ysv_ext1 = ysb - 1; + dy_ext0 = dy0 - 2 * m_squish3d; + dy_ext1 = dy0 + 1 - m_squish3d; + } + else + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * m_squish3d; + dy_ext1 = dy0 - 1 - m_squish3d; + } + + if ((c & 0x04) == 0) + { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0 - 2 * m_squish3d; + dz_ext1 = dz0 + 1 - m_squish3d; + } + else + { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * m_squish3d; + dz_ext1 = dz0 - 1 - m_squish3d; + } + } + + //Contribution (0,0,0) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; + if (attn0 > 0) + { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0); + } + + //Contribution (1,0,0) + double dx1 = dx0 - 1 - m_squish3d; + double dy1 = dy0 - 0 - m_squish3d; + double dz1 = dz0 - 0 - m_squish3d; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); + } + + //Contribution (0,1,0) + double dx2 = dx0 - 0 - m_squish3d; + double dy2 = dy0 - 1 - m_squish3d; + double dz2 = dz1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); + } + + //Contribution (0,0,1) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - m_squish3d; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) + { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); + } + } + else if (inSum >= 2) + { //We're inside the tetrahedron (3-Simplex) at (1,1,1) + +//Determine which two tetrahedral vertices are the closest, out of (1,1,0), (1,0,1), (0,1,1) but not (1,1,1). + char aPoint = 0x06; + double aScore = xins; + char bPoint = 0x05; + double bScore = yins; + if (aScore <= bScore && zins < bScore) + { + bScore = zins; + bPoint = 0x03; + } + else if (aScore > bScore && zins < aScore) + { + aScore = zins; + aPoint = 0x03; + } + + //Now we determine the two lattice points not part of the tetrahedron that may contribute. + //This depends on the closest two tetrahedral vertices, including (1,1,1) + double wins = 3 - inSum; + if (wins < aScore || wins < bScore) + { //(1,1,1) is one of the closest two tetrahedral vertices. + char c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + + if ((c & 0x01) != 0) + { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * m_squish3d; + dx_ext1 = dx0 - 1 - 3 * m_squish3d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * m_squish3d; + } + + if ((c & 0x02) != 0) + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * m_squish3d; + if ((c & 0x01) != 0) + { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + else + { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * m_squish3d; + } + + if ((c & 0x04) != 0) + { + zsv_ext0 = zsb + 1; + zsv_ext1 = zsb + 2; + dz_ext0 = dz0 - 1 - 3 * m_squish3d; + dz_ext1 = dz0 - 2 - 3 * m_squish3d; + } + else + { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * m_squish3d; + } + } + else + { //(1,1,1) is not one of the closest two tetrahedral vertices. + char c = static_cast(aPoint & bPoint); //Our two extra vertices are determined by the closest two. + + if ((c & 0x01) != 0) + { + xsv_ext0 = xsb + 1; + xsv_ext1 = xsb + 2; + dx_ext0 = dx0 - 1 - m_squish3d; + dx_ext1 = dx0 - 2 - 2 * m_squish3d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx0 - m_squish3d; + dx_ext1 = dx0 - 2 * m_squish3d; + } + + if ((c & 0x02) != 0) + { + ysv_ext0 = ysb + 1; + ysv_ext1 = ysb + 2; + dy_ext0 = dy0 - 1 - m_squish3d; + dy_ext1 = dy0 - 2 - 2 * m_squish3d; + } + else + { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy0 - m_squish3d; + dy_ext1 = dy0 - 2 * m_squish3d; + } + + if ((c & 0x04) != 0) + { + zsv_ext0 = zsb + 1; + zsv_ext1 = zsb + 2; + dz_ext0 = dz0 - 1 - m_squish3d; + dz_ext1 = dz0 - 2 - 2 * m_squish3d; + } + else + { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz0 - m_squish3d; + dz_ext1 = dz0 - 2 * m_squish3d; + } + } + + //Contribution (1,1,0) + double dx3 = dx0 - 1 - 2 * m_squish3d; + double dy3 = dy0 - 1 - 2 * m_squish3d; + double dz3 = dz0 - 0 - 2 * m_squish3d; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) + { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3); + } + + //Contribution (1,0,1) + double dx2 = dx3; + double dy2 = dy0 - 0 - 2 * m_squish3d; + double dz2 = dz0 - 1 - 2 * m_squish3d; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2); + } + + //Contribution (0,1,1) + double dx1 = dx0 - 0 - 2 * m_squish3d; + double dy1 = dy3; + double dz1 = dz2; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1); + } + + //Contribution (1,1,1) + dx0 = dx0 - 1 - 3 * m_squish3d; + dy0 = dy0 - 1 - 3 * m_squish3d; + dz0 = dz0 - 1 - 3 * m_squish3d; + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; + if (attn0 > 0) + { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0); + } + } + else + { //We're inside the octahedron (Rectified 3-Simplex) in between. + double aScore; + char aPoint; + bool aIsFurtherSide; + double bScore; + char bPoint; + bool bIsFurtherSide; + + //Decide between point (0,0,1) and (1,1,0) as closest + double p1 = xins + yins; + if (p1 > 1) + { + aScore = p1 - 1; + aPoint = 0x03; + aIsFurtherSide = true; + } + else + { + aScore = 1 - p1; + aPoint = 0x04; + aIsFurtherSide = false; + } + + //Decide between point (0,1,0) and (1,0,1) as closest + double p2 = xins + zins; + if (p2 > 1) + { + bScore = p2 - 1; + bPoint = 0x05; + bIsFurtherSide = true; + } + else + { + bScore = 1 - p2; + bPoint = 0x02; + bIsFurtherSide = false; + } + + //The closest out of the two (1,0,0) and (0,1,1) will replace the furthest out of the two decided above, if closer. + double p3 = yins + zins; + if (p3 > 1) + { + double score = p3 - 1; + if (aScore <= bScore && aScore < score) + { + aScore = score; + aPoint = 0x06; + aIsFurtherSide = true; + } + else if (aScore > bScore && bScore < score) + { + bScore = score; + bPoint = 0x06; + bIsFurtherSide = true; + } + } + else + { + double score = 1 - p3; + if (aScore <= bScore && aScore < score) + { + aScore = score; + aPoint = 0x01; + aIsFurtherSide = false; + } + else if (aScore > bScore && bScore < score) + { + bScore = score; + bPoint = 0x01; + bIsFurtherSide = false; + } + } + + //Where each of the two closest points are determines how the extra two vertices are calculated. + if (aIsFurtherSide == bIsFurtherSide) + { + if (aIsFurtherSide) + { //Both closest points on (1,1,1) side + +//One of the two extra points is (1,1,1) + dx_ext0 = dx0 - 1 - 3 * m_squish3d; + dy_ext0 = dy0 - 1 - 3 * m_squish3d; + dz_ext0 = dz0 - 1 - 3 * m_squish3d; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb + 1; + + //Other extra point is based on the shared axis. + char c = static_cast(aPoint & bPoint); + if ((c & 0x01) != 0) + { + dx_ext1 = dx0 - 2 - 2 * m_squish3d; + dy_ext1 = dy0 - 2 * m_squish3d; + dz_ext1 = dz0 - 2 * m_squish3d; + xsv_ext1 = xsb + 2; + ysv_ext1 = ysb; + zsv_ext1 = zsb; + } + else if ((c & 0x02) != 0) + { + dx_ext1 = dx0 - 2 * m_squish3d; + dy_ext1 = dy0 - 2 - 2 * m_squish3d; + dz_ext1 = dz0 - 2 * m_squish3d; + xsv_ext1 = xsb; + ysv_ext1 = ysb + 2; + zsv_ext1 = zsb; + } + else + { + dx_ext1 = dx0 - 2 * m_squish3d; + dy_ext1 = dy0 - 2 * m_squish3d; + dz_ext1 = dz0 - 2 - 2 * m_squish3d; + xsv_ext1 = xsb; + ysv_ext1 = ysb; + zsv_ext1 = zsb + 2; + } + } + else + {//Both closest points on (0,0,0) side + + //One of the two extra points is (0,0,0) + dx_ext0 = dx0; + dy_ext0 = dy0; + dz_ext0 = dz0; + xsv_ext0 = xsb; + ysv_ext0 = ysb; + zsv_ext0 = zsb; + + //Other extra point is based on the omitted axis. + char c = static_cast(aPoint | bPoint); + if ((c & 0x01) == 0) + { + dx_ext1 = dx0 + 1 - m_squish3d; + dy_ext1 = dy0 - 1 - m_squish3d; + dz_ext1 = dz0 - 1 - m_squish3d; + xsv_ext1 = xsb - 1; + ysv_ext1 = ysb + 1; + zsv_ext1 = zsb + 1; + } + else if ((c & 0x02) == 0) + { + dx_ext1 = dx0 - 1 - m_squish3d; + dy_ext1 = dy0 + 1 - m_squish3d; + dz_ext1 = dz0 - 1 - m_squish3d; + xsv_ext1 = xsb + 1; + ysv_ext1 = ysb - 1; + zsv_ext1 = zsb + 1; + } + else + { + dx_ext1 = dx0 - 1 - m_squish3d; + dy_ext1 = dy0 - 1 - m_squish3d; + dz_ext1 = dz0 + 1 - m_squish3d; + xsv_ext1 = xsb + 1; + ysv_ext1 = ysb + 1; + zsv_ext1 = zsb - 1; + } + } + } + else + { //One point on (0,0,0) side, one point on (1,1,1) side + char c1, c2; + if (aIsFurtherSide) + { + c1 = aPoint; + c2 = bPoint; + } + else + { + c1 = bPoint; + c2 = aPoint; + } + + //One contribution is a permutation of (1,1,-1) + if ((c1 & 0x01) == 0) + { + dx_ext0 = dx0 + 1 - m_squish3d; + dy_ext0 = dy0 - 1 - m_squish3d; + dz_ext0 = dz0 - 1 - m_squish3d; + xsv_ext0 = xsb - 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb + 1; + } + else if ((c1 & 0x02) == 0) + { + dx_ext0 = dx0 - 1 - m_squish3d; + dy_ext0 = dy0 + 1 - m_squish3d; + dz_ext0 = dz0 - 1 - m_squish3d; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb - 1; + zsv_ext0 = zsb + 1; + } + else + { + dx_ext0 = dx0 - 1 - m_squish3d; + dy_ext0 = dy0 - 1 - m_squish3d; + dz_ext0 = dz0 + 1 - m_squish3d; + xsv_ext0 = xsb + 1; + ysv_ext0 = ysb + 1; + zsv_ext0 = zsb - 1; + } + + //One contribution is a permutation of (0,0,2) + dx_ext1 = dx0 - 2 * m_squish3d; + dy_ext1 = dy0 - 2 * m_squish3d; + dz_ext1 = dz0 - 2 * m_squish3d; + xsv_ext1 = xsb; + ysv_ext1 = ysb; + zsv_ext1 = zsb; + if ((c2 & 0x01) != 0) + { + dx_ext1 -= 2; + xsv_ext1 += 2; + } + else if ((c2 & 0x02) != 0) + { + dy_ext1 -= 2; + ysv_ext1 += 2; + } + else + { + dz_ext1 -= 2; + zsv_ext1 += 2; + } + } + + //Contribution (1,0,0) + double dx1 = dx0 - 1 - m_squish3d; + double dy1 = dy0 - 0 - m_squish3d; + double dz1 = dz0 - 0 - m_squish3d; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); + } + + //Contribution (0,1,0) + double dx2 = dx0 - 0 - m_squish3d; + double dy2 = dy0 - 1 - m_squish3d; + double dz2 = dz1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); + } + + //Contribution (0,0,1) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - m_squish3d; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; + if (attn3 > 0) + { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); + } + + //Contribution (1,1,0) + double dx4 = dx0 - 1 - 2 * m_squish3d; + double dy4 = dy0 - 1 - 2 * m_squish3d; + double dz4 = dz0 - 0 - 2 * m_squish3d; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4; + if (attn4 > 0) + { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4); + } + + //Contribution (1,0,1) + double dx5 = dx4; + double dy5 = dy0 - 0 - 2 * m_squish3d; + double dz5 = dz0 - 1 - 2 * m_squish3d; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5; + if (attn5 > 0) + { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5); + } + + //Contribution (0,1,1) + double dx6 = dx0 - 0 - 2 * m_squish3d; + double dy6 = dy4; + double dz6 = dz5; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6; + if (attn6 > 0) + { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6); + } + } + + //First extra vertex + double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0; + if (attn_ext0 > 0) + { + attn_ext0 *= attn_ext0; + value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0); + } + + //Second extra vertex + double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1; + if (attn_ext1 > 0) + { + attn_ext1 *= attn_ext1; + value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1); + } + + return value / m_norm3d; + } + + double Noise::eval(double x, double y, double z, double w) const + { + //Place input coordinates on simplectic honeycomb. + double stretchOffset = (x + y + z + w) * m_stretch4d; + double xs = x + stretchOffset; + double ys = y + stretchOffset; + double zs = z + stretchOffset; + double ws = w + stretchOffset; + + //static_cast(floor to get simplectic honeycomb coordinates of rhombo-hypercube super-cell origin. + int xsb = static_cast(floor(xs)); + int ysb = static_cast(floor(ys)); + int zsb = static_cast(floor(zs)); + int wsb = static_cast(floor(ws)); + + //Skew out to get actual coordinates of stretched rhombo-hypercube origin. We'll need these later. + double squishOffset = (xsb + ysb + zsb + wsb) * m_squish4d; + double xb = xsb + squishOffset; + double yb = ysb + squishOffset; + double zb = zsb + squishOffset; + double wb = wsb + squishOffset; + + //Compute simplectic honeycomb coordinates relative to rhombo-hypercube origin. + double xins = xs - xsb; + double yins = ys - ysb; + double zins = zs - zsb; + double wins = ws - wsb; + + //Sum those together to get a value that determines which region we're in. + double inSum = xins + yins + zins + wins; + + //Positions relative to origin point. + double dx0 = x - xb; + double dy0 = y - yb; + double dz0 = z - zb; + double dw0 = w - wb; + + //We'll be defining these inside the next block and using them afterwards. + double dx_ext0, dy_ext0, dz_ext0, dw_ext0; + double dx_ext1, dy_ext1, dz_ext1, dw_ext1; + double dx_ext2, dy_ext2, dz_ext2, dw_ext2; + int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0; + int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1; + int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2; + + double value = 0; + if (inSum <= 1) + { //We're inside the pentachoron (4-Simplex) at (0,0,0,0) + +//Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) are closest. + char aPoint = 0x01; + double aScore = xins; + char bPoint = 0x02; + double bScore = yins; + if (aScore >= bScore && zins > bScore) + { + bScore = zins; + bPoint = 0x04; + } + else if (aScore < bScore && zins > aScore) + { + aScore = zins; + aPoint = 0x04; + } + if (aScore >= bScore && wins > bScore) + { + bScore = wins; + bPoint = 0x08; + } + else if (aScore < bScore && wins > aScore) + { + aScore = wins; + aPoint = 0x08; + } + + //Now we determine the three lattice points not part of the pentachoron that may contribute. + //This depends on the closest two pentachoron vertices, including (0,0,0,0) + double uins = 1 - inSum; + if (uins > aScore || uins > bScore) + { //(0,0,0,0) is one of the closest two pentachoron vertices. + char c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + if ((c & 0x01) == 0) + { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx0 + 1; + dx_ext1 = dx_ext2 = dx0; + } + else + { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1; + } + + if ((c & 0x02) == 0) + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy_ext1 = dy_ext2 = dy0; + if ((c & 0x01) == 0x01) + { + ysv_ext0 -= 1; + dy_ext0 += 1; + } + else + { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1; + } + + if ((c & 0x04) == 0) + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz_ext1 = dz_ext2 = dz0; + if ((c & 0x03) != 0) + { + if ((c & 0x03) == 0x03) + { + zsv_ext0 -= 1; + dz_ext0 += 1; + } + else + { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } + else + { + zsv_ext2 -= 1; + dz_ext2 += 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1; + } + + if ((c & 0x08) == 0) + { + wsv_ext0 = wsv_ext1 = wsb; + wsv_ext2 = wsb - 1; + dw_ext0 = dw_ext1 = dw0; + dw_ext2 = dw0 + 1; + } + else + { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; + dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1; + } + } + else + { //(0,0,0,0) is not one of the closest two pentachoron vertices. + char c = static_cast(aPoint | bPoint); //Our three extra vertices are determined by the closest two. + + if ((c & 0x01) == 0) + { + xsv_ext0 = xsv_ext2 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 2 * m_squish4d; + dx_ext1 = dx0 + 1 - m_squish4d; + dx_ext2 = dx0 - m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx0 - 1 - 2 * m_squish4d; + dx_ext1 = dx_ext2 = dx0 - 1 - m_squish4d; + } + + if ((c & 0x02) == 0) + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy0 - 2 * m_squish4d; + dy_ext1 = dy_ext2 = dy0 - m_squish4d; + if ((c & 0x01) == 0x01) + { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + else + { + ysv_ext2 -= 1; + dy_ext2 += 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * m_squish4d; + dy_ext1 = dy_ext2 = dy0 - 1 - m_squish4d; + } + + if ((c & 0x04) == 0) + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz0 - 2 * m_squish4d; + dz_ext1 = dz_ext2 = dz0 - m_squish4d; + if ((c & 0x03) == 0x03) + { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + else + { + zsv_ext2 -= 1; + dz_ext2 += 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * m_squish4d; + dz_ext1 = dz_ext2 = dz0 - 1 - m_squish4d; + } + + if ((c & 0x08) == 0) + { + wsv_ext0 = wsv_ext1 = wsb; + wsv_ext2 = wsb - 1; + dw_ext0 = dw0 - 2 * m_squish4d; + dw_ext1 = dw0 - m_squish4d; + dw_ext2 = dw0 + 1 - m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; + dw_ext0 = dw0 - 1 - 2 * m_squish4d; + dw_ext1 = dw_ext2 = dw0 - 1 - m_squish4d; + } + } + + //Contribution (0,0,0,0) + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; + if (attn0 > 0) + { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0); + } + + //Contribution (1,0,0,0) + double dx1 = dx0 - 1 - m_squish4d; + double dy1 = dy0 - 0 - m_squish4d; + double dz1 = dz0 - 0 - m_squish4d; + double dw1 = dw0 - 0 - m_squish4d; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); + } + + //Contribution (0,1,0,0) + double dx2 = dx0 - 0 - m_squish4d; + double dy2 = dy0 - 1 - m_squish4d; + double dz2 = dz1; + double dw2 = dw1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); + } + + //Contribution (0,0,1,0) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - m_squish4d; + double dw3 = dw1; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) + { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); + } + + //Contribution (0,0,0,1) + double dx4 = dx2; + double dy4 = dy1; + double dz4 = dz1; + double dw4 = dw0 - 1 - m_squish4d; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) + { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); + } + } + else if (inSum >= 3) + { //We're inside the pentachoron (4-Simplex) at (1,1,1,1) +//Determine which two of (1,1,1,0), (1,1,0,1), (1,0,1,1), (0,1,1,1) are closest. + char aPoint = 0x0E; + double aScore = xins; + char bPoint = 0x0D; + double bScore = yins; + if (aScore <= bScore && zins < bScore) + { + bScore = zins; + bPoint = 0x0B; + } + else if (aScore > bScore && zins < aScore) + { + aScore = zins; + aPoint = 0x0B; + } + if (aScore <= bScore && wins < bScore) + { + bScore = wins; + bPoint = 0x07; + } + else if (aScore > bScore && wins < aScore) + { + aScore = wins; + aPoint = 0x07; + } + + //Now we determine the three lattice points not part of the pentachoron that may contribute. + //This depends on the closest two pentachoron vertices, including (0,0,0,0) + double uins = 4 - inSum; + if (uins < aScore || uins < bScore) + { //(1,1,1,1) is one of the closest two pentachoron vertices. + char c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. + + if ((c & 0x01) != 0) + { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsv_ext2 = xsb + 1; + dx_ext0 = dx0 - 2 - 4 * m_squish4d; + dx_ext1 = dx_ext2 = dx0 - 1 - 4 * m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * m_squish4d; + } + + if ((c & 0x02) != 0) + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * m_squish4d; + if ((c & 0x01) != 0) + { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + else + { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * m_squish4d; + } + + if ((c & 0x04) != 0) + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * m_squish4d; + if ((c & 0x03) != 0x03) + { + if ((c & 0x03) == 0) + { + zsv_ext0 += 1; + dz_ext0 -= 1; + } + else + { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } + else + { + zsv_ext2 += 1; + dz_ext2 -= 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * m_squish4d; + } + + if ((c & 0x08) != 0) + { + wsv_ext0 = wsv_ext1 = wsb + 1; + wsv_ext2 = wsb + 2; + dw_ext0 = dw_ext1 = dw0 - 1 - 4 * m_squish4d; + dw_ext2 = dw0 - 2 - 4 * m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; + dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * m_squish4d; + } + } + else + { //(1,1,1,1) is not one of the closest two pentachoron vertices. + char c = static_cast(aPoint & bPoint); //Our three extra vertices are determined by the closest two. + + if ((c & 0x01) != 0) + { + xsv_ext0 = xsv_ext2 = xsb + 1; + xsv_ext1 = xsb + 2; + dx_ext0 = dx0 - 1 - 2 * m_squish4d; + dx_ext1 = dx0 - 2 - 3 * m_squish4d; + dx_ext2 = dx0 - 1 - 3 * m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; + dx_ext0 = dx0 - 2 * m_squish4d; + dx_ext1 = dx_ext2 = dx0 - 3 * m_squish4d; + } + + if ((c & 0x02) != 0) + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; + dy_ext0 = dy0 - 1 - 2 * m_squish4d; + dy_ext1 = dy_ext2 = dy0 - 1 - 3 * m_squish4d; + if ((c & 0x01) != 0) + { + ysv_ext2 += 1; + dy_ext2 -= 1; + } + else + { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; + dy_ext0 = dy0 - 2 * m_squish4d; + dy_ext1 = dy_ext2 = dy0 - 3 * m_squish4d; + } + + if ((c & 0x04) != 0) + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; + dz_ext0 = dz0 - 1 - 2 * m_squish4d; + dz_ext1 = dz_ext2 = dz0 - 1 - 3 * m_squish4d; + if ((c & 0x03) != 0) + { + zsv_ext2 += 1; + dz_ext2 -= 1; + } + else + { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; + dz_ext0 = dz0 - 2 * m_squish4d; + dz_ext1 = dz_ext2 = dz0 - 3 * m_squish4d; + } + + if ((c & 0x08) != 0) + { + wsv_ext0 = wsv_ext1 = wsb + 1; + wsv_ext2 = wsb + 2; + dw_ext0 = dw0 - 1 - 2 * m_squish4d; + dw_ext1 = dw0 - 1 - 3 * m_squish4d; + dw_ext2 = dw0 - 2 - 3 * m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; + dw_ext0 = dw0 - 2 * m_squish4d; + dw_ext1 = dw_ext2 = dw0 - 3 * m_squish4d; + } + } + + //Contribution (1,1,1,0) + double dx4 = dx0 - 1 - 3 * m_squish4d; + double dy4 = dy0 - 1 - 3 * m_squish4d; + double dz4 = dz0 - 1 - 3 * m_squish4d; + double dw4 = dw0 - 3 * m_squish4d; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) + { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); + } + + //Contribution (1,1,0,1) + double dx3 = dx4; + double dy3 = dy4; + double dz3 = dz0 - 3 * m_squish4d; + double dw3 = dw0 - 1 - 3 * m_squish4d; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) + { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); + } + + //Contribution (1,0,1,1) + double dx2 = dx4; + double dy2 = dy0 - 3 * m_squish4d; + double dz2 = dz4; + double dw2 = dw3; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); + } + + //Contribution (0,1,1,1) + double dx1 = dx0 - 3 * m_squish4d; + double dz1 = dz4; + double dy1 = dy4; + double dw1 = dw3; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); + } + + //Contribution (1,1,1,1) + dx0 = dx0 - 1 - 4 * m_squish4d; + dy0 = dy0 - 1 - 4 * m_squish4d; + dz0 = dz0 - 1 - 4 * m_squish4d; + dw0 = dw0 - 1 - 4 * m_squish4d; + double attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; + if (attn0 > 0) + { + attn0 *= attn0; + value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0); + } + } + else if (inSum <= 2) + { //We're inside the first dispentachoron (Rectified 4-Simplex) + double aScore; + char aPoint; + bool aIsBiggerSide = true; + double bScore; + char bPoint; + bool bIsBiggerSide = true; + + //Decide between (1,1,0,0) and (0,0,1,1) + if (xins + yins > zins + wins) + { + aScore = xins + yins; + aPoint = 0x03; + } + else + { + aScore = zins + wins; + aPoint = 0x0C; + } + + //Decide between (1,0,1,0) and (0,1,0,1) + if (xins + zins > yins + wins) + { + bScore = xins + zins; + bPoint = 0x05; + } + else + { + bScore = yins + wins; + bPoint = 0x0A; + } + + //Closer between (1,0,0,1) and (0,1,1,0) will replace the further of a and b, if closer. + if (xins + wins > yins + zins) + { + double score = xins + wins; + if (aScore >= bScore && score > bScore) + { + bScore = score; + bPoint = 0x09; + } + else if (aScore < bScore && score > aScore) + { + aScore = score; + aPoint = 0x09; + } + } + else + { + double score = yins + zins; + if (aScore >= bScore && score > bScore) + { + bScore = score; + bPoint = 0x06; + } + else if (aScore < bScore && score > aScore) + { + aScore = score; + aPoint = 0x06; + } + } + + //Decide if (1,0,0,0) is closer. + double p1 = 2 - inSum + xins; + if (aScore >= bScore && p1 > bScore) + { + bScore = p1; + bPoint = 0x01; + bIsBiggerSide = false; + } + else if (aScore < bScore && p1 > aScore) + { + aScore = p1; + aPoint = 0x01; + aIsBiggerSide = false; + } + + //Decide if (0,1,0,0) is closer. + double p2 = 2 - inSum + yins; + if (aScore >= bScore && p2 > bScore) + { + bScore = p2; + bPoint = 0x02; + bIsBiggerSide = false; + } + else if (aScore < bScore && p2 > aScore) + { + aScore = p2; + aPoint = 0x02; + aIsBiggerSide = false; + } + + //Decide if (0,0,1,0) is closer. + double p3 = 2 - inSum + zins; + if (aScore >= bScore && p3 > bScore) + { + bScore = p3; + bPoint = 0x04; + bIsBiggerSide = false; + } + else if (aScore < bScore && p3 > aScore) + { + aScore = p3; + aPoint = 0x04; + aIsBiggerSide = false; + } + + //Decide if (0,0,0,1) is closer. + double p4 = 2 - inSum + wins; + if (aScore >= bScore && p4 > bScore) + { + bScore = p4; + bPoint = 0x08; + bIsBiggerSide = false; + } + else if (aScore < bScore && p4 > aScore) + { + aScore = p4; + aPoint = 0x08; + aIsBiggerSide = false; + } + + //Where each of the two closest points are determines how the extra three vertices are calculated. + if (aIsBiggerSide == bIsBiggerSide) + { + if (aIsBiggerSide) + { //Both closest points on the bigger side + char c1 = static_cast(aPoint | bPoint); + char c2 = static_cast(aPoint & bPoint); + if ((c1 & 0x01) == 0) + { + xsv_ext0 = xsb; + xsv_ext1 = xsb - 1; + dx_ext0 = dx0 - 3 * m_squish4d; + dx_ext1 = dx0 + 1 - 2 * m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 1 - 3 * m_squish4d; + dx_ext1 = dx0 - 1 - 2 * m_squish4d; + } + + if ((c1 & 0x02) == 0) + { + ysv_ext0 = ysb; + ysv_ext1 = ysb - 1; + dy_ext0 = dy0 - 3 * m_squish4d; + dy_ext1 = dy0 + 1 - 2 * m_squish4d; + } + else + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy0 - 1 - 3 * m_squish4d; + dy_ext1 = dy0 - 1 - 2 * m_squish4d; + } + + if ((c1 & 0x04) == 0) + { + zsv_ext0 = zsb; + zsv_ext1 = zsb - 1; + dz_ext0 = dz0 - 3 * m_squish4d; + dz_ext1 = dz0 + 1 - 2 * m_squish4d; + } + else + { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz0 - 1 - 3 * m_squish4d; + dz_ext1 = dz0 - 1 - 2 * m_squish4d; + } + + if ((c1 & 0x08) == 0) + { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - 3 * m_squish4d; + dw_ext1 = dw0 + 1 - 2 * m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw0 - 1 - 3 * m_squish4d; + dw_ext1 = dw0 - 1 - 2 * m_squish4d; + } + + //One combination is a permutation of (0,0,0,2) based on c2 + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0 - 2 * m_squish4d; + dy_ext2 = dy0 - 2 * m_squish4d; + dz_ext2 = dz0 - 2 * m_squish4d; + dw_ext2 = dw0 - 2 * m_squish4d; + if ((c2 & 0x01) != 0) + { + xsv_ext2 += 2; + dx_ext2 -= 2; + } + else if ((c2 & 0x02) != 0) + { + ysv_ext2 += 2; + dy_ext2 -= 2; + } + else if ((c2 & 0x04) != 0) + { + zsv_ext2 += 2; + dz_ext2 -= 2; + } + else + { + wsv_ext2 += 2; + dw_ext2 -= 2; + } + + } + else + { //Both closest points on the smaller side + //One of the two extra points is (0,0,0,0) + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0; + dy_ext2 = dy0; + dz_ext2 = dz0; + dw_ext2 = dw0; + + //Other two points are based on the omitted axes. + char c = static_cast(aPoint | bPoint); + + if ((c & 0x01) == 0) + { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1 - m_squish4d; + dx_ext1 = dx0 - m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1 - m_squish4d; + } + + if ((c & 0x02) == 0) + { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - m_squish4d; + if ((c & 0x01) == 0x01) + { + ysv_ext0 -= 1; + dy_ext0 += 1; + } + else + { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - m_squish4d; + } + + if ((c & 0x04) == 0) + { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - m_squish4d; + if ((c & 0x03) == 0x03) + { + zsv_ext0 -= 1; + dz_ext0 += 1; + } + else + { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - m_squish4d; + } + + if ((c & 0x08) == 0) + { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - m_squish4d; + dw_ext1 = dw0 + 1 - m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw_ext1 = dw0 - 1 - m_squish4d; + } + + } + } + else + { //One point on each "side" + char c1, c2; + if (aIsBiggerSide) + { + c1 = aPoint; + c2 = bPoint; + } + else + { + c1 = bPoint; + c2 = aPoint; + } + + //Two contributions are the bigger-sided point with each 0 replaced with -1. + if ((c1 & 0x01) == 0) + { + xsv_ext0 = xsb - 1; + xsv_ext1 = xsb; + dx_ext0 = dx0 + 1 - m_squish4d; + dx_ext1 = dx0 - m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb + 1; + dx_ext0 = dx_ext1 = dx0 - 1 - m_squish4d; + } + + if ((c1 & 0x02) == 0) + { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - m_squish4d; + if ((c1 & 0x01) == 0x01) + { + ysv_ext0 -= 1; + dy_ext0 += 1; + } + else + { + ysv_ext1 -= 1; + dy_ext1 += 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - m_squish4d; + } + + if ((c1 & 0x04) == 0) + { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - m_squish4d; + if ((c1 & 0x03) == 0x03) + { + zsv_ext0 -= 1; + dz_ext0 += 1; + } + else + { + zsv_ext1 -= 1; + dz_ext1 += 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - m_squish4d; + } + + if ((c1 & 0x08) == 0) + { + wsv_ext0 = wsb; + wsv_ext1 = wsb - 1; + dw_ext0 = dw0 - m_squish4d; + dw_ext1 = dw0 + 1 - m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsb + 1; + dw_ext0 = dw_ext1 = dw0 - 1 - m_squish4d; + } + + //One contribution is a permutation of (0,0,0,2) based on the smaller-sided point + xsv_ext2 = xsb; + ysv_ext2 = ysb; + zsv_ext2 = zsb; + wsv_ext2 = wsb; + dx_ext2 = dx0 - 2 * m_squish4d; + dy_ext2 = dy0 - 2 * m_squish4d; + dz_ext2 = dz0 - 2 * m_squish4d; + dw_ext2 = dw0 - 2 * m_squish4d; + if ((c2 & 0x01) != 0) + { + xsv_ext2 += 2; + dx_ext2 -= 2; + } + else if ((c2 & 0x02) != 0) + { + ysv_ext2 += 2; + dy_ext2 -= 2; + } + else if ((c2 & 0x04) != 0) + { + zsv_ext2 += 2; + dz_ext2 -= 2; + } + else + { + wsv_ext2 += 2; + dw_ext2 -= 2; + } + } + + //Contribution (1,0,0,0) + double dx1 = dx0 - 1 - m_squish4d; + double dy1 = dy0 - 0 - m_squish4d; + double dz1 = dz0 - 0 - m_squish4d; + double dw1 = dw0 - 0 - m_squish4d; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); + } + + //Contribution (0,1,0,0) + double dx2 = dx0 - 0 - m_squish4d; + double dy2 = dy0 - 1 - m_squish4d; + double dz2 = dz1; + double dw2 = dw1; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); + } + + //Contribution (0,0,1,0) + double dx3 = dx2; + double dy3 = dy1; + double dz3 = dz0 - 1 - m_squish4d; + double dw3 = dw1; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) + { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); + } + + //Contribution (0,0,0,1) + double dx4 = dx2; + double dy4 = dy1; + double dz4 = dz1; + double dw4 = dw0 - 1 - m_squish4d; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) + { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); + } + + //Contribution (1,1,0,0) + double dx5 = dx0 - 1 - 2 * m_squish4d; + double dy5 = dy0 - 1 - 2 * m_squish4d; + double dz5 = dz0 - 0 - 2 * m_squish4d; + double dw5 = dw0 - 0 - 2 * m_squish4d; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; + if (attn5 > 0) + { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); + } + + //Contribution (1,0,1,0) + double dx6 = dx0 - 1 - 2 * m_squish4d; + double dy6 = dy0 - 0 - 2 * m_squish4d; + double dz6 = dz0 - 1 - 2 * m_squish4d; + double dw6 = dw0 - 0 - 2 * m_squish4d; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; + if (attn6 > 0) + { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); + } + + //Contribution (1,0,0,1) + double dx7 = dx0 - 1 - 2 * m_squish4d; + double dy7 = dy0 - 0 - 2 * m_squish4d; + double dz7 = dz0 - 0 - 2 * m_squish4d; + double dw7 = dw0 - 1 - 2 * m_squish4d; + double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; + if (attn7 > 0) + { + attn7 *= attn7; + value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); + } + + //Contribution (0,1,1,0) + double dx8 = dx0 - 0 - 2 * m_squish4d; + double dy8 = dy0 - 1 - 2 * m_squish4d; + double dz8 = dz0 - 1 - 2 * m_squish4d; + double dw8 = dw0 - 0 - 2 * m_squish4d; + double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; + if (attn8 > 0) + { + attn8 *= attn8; + value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); + } + + //Contribution (0,1,0,1) + double dx9 = dx0 - 0 - 2 * m_squish4d; + double dy9 = dy0 - 1 - 2 * m_squish4d; + double dz9 = dz0 - 0 - 2 * m_squish4d; + double dw9 = dw0 - 1 - 2 * m_squish4d; + double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; + if (attn9 > 0) + { + attn9 *= attn9; + value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); + } + + //Contribution (0,0,1,1) + double dx10 = dx0 - 0 - 2 * m_squish4d; + double dy10 = dy0 - 0 - 2 * m_squish4d; + double dz10 = dz0 - 1 - 2 * m_squish4d; + double dw10 = dw0 - 1 - 2 * m_squish4d; + double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; + if (attn10 > 0) + { + attn10 *= attn10; + value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); + } + } + else + { //We're inside the second dispentachoron (Rectified 4-Simplex) + double aScore; + char aPoint; + bool aIsBiggerSide = true; + double bScore; + char bPoint; + bool bIsBiggerSide = true; + + //Decide between (0,0,1,1) and (1,1,0,0) + if (xins + yins < zins + wins) + { + aScore = xins + yins; + aPoint = 0x0C; + } + else + { + aScore = zins + wins; + aPoint = 0x03; + } + + //Decide between (0,1,0,1) and (1,0,1,0) + if (xins + zins < yins + wins) + { + bScore = xins + zins; + bPoint = 0x0A; + } + else + { + bScore = yins + wins; + bPoint = 0x05; + } + + //Closer between (0,1,1,0) and (1,0,0,1) will replace the further of a and b, if closer. + if (xins + wins < yins + zins) + { + double score = xins + wins; + if (aScore <= bScore && score < bScore) + { + bScore = score; + bPoint = 0x06; + } + else if (aScore > bScore && score < aScore) + { + aScore = score; + aPoint = 0x06; + } + } + else + { + double score = yins + zins; + if (aScore <= bScore && score < bScore) + { + bScore = score; + bPoint = 0x09; + } + else if (aScore > bScore && score < aScore) + { + aScore = score; + aPoint = 0x09; + } + } + + //Decide if (0,1,1,1) is closer. + double p1 = 3 - inSum + xins; + if (aScore <= bScore && p1 < bScore) + { + bScore = p1; + bPoint = 0x0E; + bIsBiggerSide = false; + } + else if (aScore > bScore && p1 < aScore) + { + aScore = p1; + aPoint = 0x0E; + aIsBiggerSide = false; + } + + //Decide if (1,0,1,1) is closer. + double p2 = 3 - inSum + yins; + if (aScore <= bScore && p2 < bScore) + { + bScore = p2; + bPoint = 0x0D; + bIsBiggerSide = false; + } + else if (aScore > bScore && p2 < aScore) + { + aScore = p2; + aPoint = 0x0D; + aIsBiggerSide = false; + } + + //Decide if (1,1,0,1) is closer. + double p3 = 3 - inSum + zins; + if (aScore <= bScore && p3 < bScore) + { + bScore = p3; + bPoint = 0x0B; + bIsBiggerSide = false; + } + else if (aScore > bScore && p3 < aScore) + { + aScore = p3; + aPoint = 0x0B; + aIsBiggerSide = false; + } + + //Decide if (1,1,1,0) is closer. + double p4 = 3 - inSum + wins; + if (aScore <= bScore && p4 < bScore) + { + bScore = p4; + bPoint = 0x07; + bIsBiggerSide = false; + } + else if (aScore > bScore && p4 < aScore) + { + aScore = p4; + aPoint = 0x07; + aIsBiggerSide = false; + } + + //Where each of the two closest points are determines how the extra three vertices are calculated. + if (aIsBiggerSide == bIsBiggerSide) + { + if (aIsBiggerSide) + { //Both closest points on the bigger side + char c1 = static_cast(aPoint & bPoint); + char c2 = static_cast(aPoint | bPoint); + + //Two contributions are permutations of (0,0,0,1) and (0,0,0,2) based on c1 + xsv_ext0 = xsv_ext1 = xsb; + ysv_ext0 = ysv_ext1 = ysb; + zsv_ext0 = zsv_ext1 = zsb; + wsv_ext0 = wsv_ext1 = wsb; + dx_ext0 = dx0 - m_squish4d; + dy_ext0 = dy0 - m_squish4d; + dz_ext0 = dz0 - m_squish4d; + dw_ext0 = dw0 - m_squish4d; + dx_ext1 = dx0 - 2 * m_squish4d; + dy_ext1 = dy0 - 2 * m_squish4d; + dz_ext1 = dz0 - 2 * m_squish4d; + dw_ext1 = dw0 - 2 * m_squish4d; + if ((c1 & 0x01) != 0) + { + xsv_ext0 += 1; + dx_ext0 -= 1; + xsv_ext1 += 2; + dx_ext1 -= 2; + } + else if ((c1 & 0x02) != 0) + { + ysv_ext0 += 1; + dy_ext0 -= 1; + ysv_ext1 += 2; + dy_ext1 -= 2; + } + else if ((c1 & 0x04) != 0) + { + zsv_ext0 += 1; + dz_ext0 -= 1; + zsv_ext1 += 2; + dz_ext1 -= 2; + } + else + { + wsv_ext0 += 1; + dw_ext0 -= 1; + wsv_ext1 += 2; + dw_ext1 -= 2; + } + + //One contribution is a permutation of (1,1,1,-1) based on c2 + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 2 * m_squish4d; + dy_ext2 = dy0 - 1 - 2 * m_squish4d; + dz_ext2 = dz0 - 1 - 2 * m_squish4d; + dw_ext2 = dw0 - 1 - 2 * m_squish4d; + if ((c2 & 0x01) == 0) + { + xsv_ext2 -= 2; + dx_ext2 += 2; + } + else if ((c2 & 0x02) == 0) + { + ysv_ext2 -= 2; + dy_ext2 += 2; + } + else if ((c2 & 0x04) == 0) + { + zsv_ext2 -= 2; + dz_ext2 += 2; + } + else + { + wsv_ext2 -= 2; + dw_ext2 += 2; + } + } + else + { //Both closest points on the smaller side + //One of the two extra points is (1,1,1,1) + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 4 * m_squish4d; + dy_ext2 = dy0 - 1 - 4 * m_squish4d; + dz_ext2 = dz0 - 1 - 4 * m_squish4d; + dw_ext2 = dw0 - 1 - 4 * m_squish4d; + + //Other two points are based on the shared axes. + char c = static_cast(aPoint & bPoint); + + if ((c & 0x01) != 0) + { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * m_squish4d; + dx_ext1 = dx0 - 1 - 3 * m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * m_squish4d; + } + + if ((c & 0x02) != 0) + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * m_squish4d; + if ((c & 0x01) == 0) + { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + else + { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * m_squish4d; + } + + if ((c & 0x04) != 0) + { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - 3 * m_squish4d; + if ((c & 0x03) == 0) + { + zsv_ext0 += 1; + dz_ext0 -= 1; + } + else + { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * m_squish4d; + } + + if ((c & 0x08) != 0) + { + wsv_ext0 = wsb + 1; + wsv_ext1 = wsb + 2; + dw_ext0 = dw0 - 1 - 3 * m_squish4d; + dw_ext1 = dw0 - 2 - 3 * m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsb; + dw_ext0 = dw_ext1 = dw0 - 3 * m_squish4d; + } + } + } + else + { //One point on each "side" + char c1, c2; + if (aIsBiggerSide) + { + c1 = aPoint; + c2 = bPoint; + } + else + { + c1 = bPoint; + c2 = aPoint; + } + + //Two contributions are the bigger-sided point with each 1 replaced with 2. + if ((c1 & 0x01) != 0) + { + xsv_ext0 = xsb + 2; + xsv_ext1 = xsb + 1; + dx_ext0 = dx0 - 2 - 3 * m_squish4d; + dx_ext1 = dx0 - 1 - 3 * m_squish4d; + } + else + { + xsv_ext0 = xsv_ext1 = xsb; + dx_ext0 = dx_ext1 = dx0 - 3 * m_squish4d; + } + + if ((c1 & 0x02) != 0) + { + ysv_ext0 = ysv_ext1 = ysb + 1; + dy_ext0 = dy_ext1 = dy0 - 1 - 3 * m_squish4d; + if ((c1 & 0x01) == 0) + { + ysv_ext0 += 1; + dy_ext0 -= 1; + } + else + { + ysv_ext1 += 1; + dy_ext1 -= 1; + } + } + else + { + ysv_ext0 = ysv_ext1 = ysb; + dy_ext0 = dy_ext1 = dy0 - 3 * m_squish4d; + } + + if ((c1 & 0x04) != 0) + { + zsv_ext0 = zsv_ext1 = zsb + 1; + dz_ext0 = dz_ext1 = dz0 - 1 - 3 * m_squish4d; + if ((c1 & 0x03) == 0) + { + zsv_ext0 += 1; + dz_ext0 -= 1; + } + else + { + zsv_ext1 += 1; + dz_ext1 -= 1; + } + } + else + { + zsv_ext0 = zsv_ext1 = zsb; + dz_ext0 = dz_ext1 = dz0 - 3 * m_squish4d; + } + + if ((c1 & 0x08) != 0) + { + wsv_ext0 = wsb + 1; + wsv_ext1 = wsb + 2; + dw_ext0 = dw0 - 1 - 3 * m_squish4d; + dw_ext1 = dw0 - 2 - 3 * m_squish4d; + } + else + { + wsv_ext0 = wsv_ext1 = wsb; + dw_ext0 = dw_ext1 = dw0 - 3 * m_squish4d; + } + + //One contribution is a permutation of (1,1,1,-1) based on the smaller-sided point + xsv_ext2 = xsb + 1; + ysv_ext2 = ysb + 1; + zsv_ext2 = zsb + 1; + wsv_ext2 = wsb + 1; + dx_ext2 = dx0 - 1 - 2 * m_squish4d; + dy_ext2 = dy0 - 1 - 2 * m_squish4d; + dz_ext2 = dz0 - 1 - 2 * m_squish4d; + dw_ext2 = dw0 - 1 - 2 * m_squish4d; + if ((c2 & 0x01) == 0) + { + xsv_ext2 -= 2; + dx_ext2 += 2; + } + else if ((c2 & 0x02) == 0) + { + ysv_ext2 -= 2; + dy_ext2 += 2; + } + else if ((c2 & 0x04) == 0) + { + zsv_ext2 -= 2; + dz_ext2 += 2; + } + else + { + wsv_ext2 -= 2; + dw_ext2 += 2; + } + } + + //Contribution (1,1,1,0) + double dx4 = dx0 - 1 - 3 * m_squish4d; + double dy4 = dy0 - 1 - 3 * m_squish4d; + double dz4 = dz0 - 1 - 3 * m_squish4d; + double dw4 = dw0 - 3 * m_squish4d; + double attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; + if (attn4 > 0) + { + attn4 *= attn4; + value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); + } + + //Contribution (1,1,0,1) + double dx3 = dx4; + double dy3 = dy4; + double dz3 = dz0 - 3 * m_squish4d; + double dw3 = dw0 - 1 - 3 * m_squish4d; + double attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; + if (attn3 > 0) + { + attn3 *= attn3; + value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); + } + + //Contribution (1,0,1,1) + double dx2 = dx4; + double dy2 = dy0 - 3 * m_squish4d; + double dz2 = dz4; + double dw2 = dw3; + double attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; + if (attn2 > 0) + { + attn2 *= attn2; + value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); + } + + //Contribution (0,1,1,1) + double dx1 = dx0 - 3 * m_squish4d; + double dz1 = dz4; + double dy1 = dy4; + double dw1 = dw3; + double attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; + if (attn1 > 0) + { + attn1 *= attn1; + value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); + } + + //Contribution (1,1,0,0) + double dx5 = dx0 - 1 - 2 * m_squish4d; + double dy5 = dy0 - 1 - 2 * m_squish4d; + double dz5 = dz0 - 0 - 2 * m_squish4d; + double dw5 = dw0 - 0 - 2 * m_squish4d; + double attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; + if (attn5 > 0) + { + attn5 *= attn5; + value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); + } + + //Contribution (1,0,1,0) + double dx6 = dx0 - 1 - 2 * m_squish4d; + double dy6 = dy0 - 0 - 2 * m_squish4d; + double dz6 = dz0 - 1 - 2 * m_squish4d; + double dw6 = dw0 - 0 - 2 * m_squish4d; + double attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; + if (attn6 > 0) + { + attn6 *= attn6; + value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); + } + + //Contribution (1,0,0,1) + double dx7 = dx0 - 1 - 2 * m_squish4d; + double dy7 = dy0 - 0 - 2 * m_squish4d; + double dz7 = dz0 - 0 - 2 * m_squish4d; + double dw7 = dw0 - 1 - 2 * m_squish4d; + double attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; + if (attn7 > 0) + { + attn7 *= attn7; + value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); + } + + //Contribution (0,1,1,0) + double dx8 = dx0 - 0 - 2 * m_squish4d; + double dy8 = dy0 - 1 - 2 * m_squish4d; + double dz8 = dz0 - 1 - 2 * m_squish4d; + double dw8 = dw0 - 0 - 2 * m_squish4d; + double attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; + if (attn8 > 0) + { + attn8 *= attn8; + value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); + } + + //Contribution (0,1,0,1) + double dx9 = dx0 - 0 - 2 * m_squish4d; + double dy9 = dy0 - 1 - 2 * m_squish4d; + double dz9 = dz0 - 0 - 2 * m_squish4d; + double dw9 = dw0 - 1 - 2 * m_squish4d; + double attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; + if (attn9 > 0) + { + attn9 *= attn9; + value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); + } + + //Contribution (0,0,1,1) + double dx10 = dx0 - 0 - 2 * m_squish4d; + double dy10 = dy0 - 0 - 2 * m_squish4d; + double dz10 = dz0 - 1 - 2 * m_squish4d; + double dw10 = dw0 - 1 - 2 * m_squish4d; + double attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; + if (attn10 > 0) + { + attn10 *= attn10; + value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); + } + } + + //First extra vertex + double attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0; + if (attn_ext0 > 0) + { + attn_ext0 *= attn_ext0; + value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0, dx_ext0, dy_ext0, dz_ext0, dw_ext0); + } + + //Second extra vertex + double attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1; + if (attn_ext1 > 0) + { + attn_ext1 *= attn_ext1; + value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1, dx_ext1, dy_ext1, dz_ext1, dw_ext1); + } + + //Third extra vertex + double attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2; + if (attn_ext2 > 0) + { + attn_ext2 *= attn_ext2; + value += attn_ext2 * attn_ext2 * extrapolate(xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2, dx_ext2, dy_ext2, dz_ext2, dw_ext2); + } + + return value / m_norm4d; + } + + double Noise::extrapolate(int xsb, int ysb, double dx, double dy) const + { + int index = m_perm[(m_perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E; + return m_gradients2d[index] * dx + + m_gradients2d[index + 1] * dy; + } + + double Noise::extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz) const + { + int index = m_permGradIndex3d[(m_perm[(m_perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF]; + return m_gradients3d[index] * dx + + m_gradients3d[index + 1] * dy + + m_gradients3d[index + 2] * dz; + } + + double Noise::extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw) const + { + int index = m_perm[(m_perm[(m_perm[(m_perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC; + return m_gradients4d[index] * dx + + m_gradients4d[index + 1] * dy + + m_gradients4d[index + 2] * dz + + m_gradients4d[index + 3] * dw; + } + +} \ No newline at end of file diff --git a/SQCSim-common/opensimplex.h b/SQCSim-common/opensimplex.h new file mode 100644 index 0000000..4b1b1f4 --- /dev/null +++ b/SQCSim-common/opensimplex.h @@ -0,0 +1,51 @@ +/** + Open Simple Noise for C++ + + Port to C++ from https://gist.github.com/KdotJPG/b1270127455a94ac5d19 + by Rickard Lundberg, 2019. +*/ +#ifndef _OPENSIMPLEX_H__ +#define _OPENSIMPLEX_H__ + +#include +#include + +namespace OpenSimplexNoise +{ + class Noise + { + public: + Noise(); + Noise(int64_t seed); + //2D Open Simplex Noise. + double eval(const double x, const double y) const; + //3D Open Simplex Noise. + double eval(double x, double y, double z) const; + //4D Open Simplex Noise. + double eval(double x, double y, double z, double w) const; + private: + const double m_stretch2d; + const double m_squish2d; + const double m_stretch3d; + const double m_squish3d; + const double m_stretch4d; + const double m_squish4d; + + const double m_norm2d; + const double m_norm3d; + const double m_norm4d; + + const long m_defaultSeed; + + std::array m_perm; + std::array m_permGradIndex3d; + std::array m_gradients2d; + std::array m_gradients3d; + std::array m_gradients4d; + double extrapolate(int xsb, int ysb, double dx, double dy) const; + double extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz) const; + double extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw) const; + }; +} + +#endif // _OPENSIMPLEX_H__ \ No newline at end of file diff --git a/SQCSim-common/player.cpp b/SQCSim-common/player.cpp new file mode 100644 index 0000000..080fc2d --- /dev/null +++ b/SQCSim-common/player.cpp @@ -0,0 +1,160 @@ +#include "player.h" +#include "world.h" + +Player::Player(const Vector3f& position, float rotX, float rotY) : m_position(position), m_rotX(rotX), m_rotY(rotY) { + m_velocity = Vector3f(0, 0, 0); + m_airborne = true; +} + +void Player::TurnLeftRight(float value) { + m_rotY += value; + if (m_rotY > 360) m_rotY = 0; + else if (m_rotY < -360) m_rotY = 0; +} + +void Player::TurnTopBottom(float value) { + m_rotX += value; + if (m_rotX > 80) m_rotX = 80; + else if (m_rotX < -80) m_rotX = -80; +} + +Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jump, bool shoot, float elapsedTime) { + + Vector3f delta = Vector3f(0, 0, 0); + + float yrotrad = (m_rotY / 57.2957795056f); // 180/Pi = 57.295... + float xrotrad = (m_rotX / 57.2957795056f); + + m_direction = Vector3f(cos(xrotrad) * sin(yrotrad), + -sin(xrotrad), + cos(xrotrad) * -cos(yrotrad)); + + m_direction.Normalize(); + + if (front) { + delta.x += float(sin(yrotrad)) * elapsedTime * 10.f; + delta.z += float(-cos(yrotrad)) * elapsedTime * 10.f; + } + else if (back) { + delta.x += float(-sin(yrotrad)) * elapsedTime * 10.f; + delta.z += float(cos(yrotrad)) * elapsedTime * 10.f; + } + + if (left) { + delta.x += float(-cos(yrotrad)) * elapsedTime * 10.f; + delta.z += float(-sin(yrotrad)) * elapsedTime * 10.f; + } + else if (right) { + delta.x += float(cos(yrotrad)) * elapsedTime * 10.f; + delta.z += float(sin(yrotrad)) * elapsedTime * 10.f; + } + + delta.Normalize(); + delta.x *= .6f; + delta.z *= .6f; + + if ((jump || shoot ) && !m_airborne) { + delta.y += jump? .32f: shoot? .1f : 0.f; + m_airborne = true; + } + + if (shoot) // Recoil! + TurnTopBottom(-1); + + return delta; +} + +void Player::ApplyPhysics(Vector3f input, World* world, float elapsedTime) { + static float timing = 0.f; + /* Gestion de collisions */ + BlockType bt1, bt2, bt3; + + bt1 = world->BlockAt(GetPosition().x, GetPosition().y + input.y, GetPosition().z); + bt2 = world->BlockAt(GetPosition().x, GetPosition().y + input.y - 0.9f, GetPosition().z); + bt3 = world->BlockAt(GetPosition().x, GetPosition().y + input.y - 1.7f, GetPosition().z); + if ((bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR) && m_position.y < 129.7f) { + bt1 = world->BlockAt(GetPosition().x, GetPosition().y + .3f, GetPosition().z); + if (bt1 == BTYPE_AIR) m_position.y = (int)m_position.y + .7f; + m_velocity.y = input.y = 0; + m_airborne = false; + } + else { + if (abs(m_velocity.y) < 1.1f) m_velocity.y += input.y - 1.1f * elapsedTime; + bt3 = world->BlockAt(GetPosition().x, GetPosition().y + m_velocity.y - 1.7f, GetPosition().z); + bt1 = world->BlockAt(GetPosition().x, GetPosition().y + .3f, GetPosition().z); + if (bt3 != BTYPE_AIR) { + m_velocity.y = 0; + if (timing == 0.f) { + timing = .3f; + } + m_airborne = false; + } + else if (bt1 != BTYPE_AIR) { + m_velocity.y = -.1f; + } + else m_airborne = true; + } + + if (timing > 0.f) timing -= elapsedTime; + if (timing < 0.f) timing = 0.f; + + bt1 = world->BlockAt(GetPosition().x + input.x, GetPosition().y, GetPosition().z); + bt2 = world->BlockAt(GetPosition().x + input.x, GetPosition().y - 0.9f, GetPosition().z); + bt3 = world->BlockAt(GetPosition().x + input.x, GetPosition().y - 1.7f, GetPosition().z); + if (bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR) { + input.x = m_velocity.x = 0; + m_velocity.z *= .5f; + } + + bt1 = world->BlockAt(GetPosition().x, GetPosition().y, GetPosition().z + input.z); + bt2 = world->BlockAt(GetPosition().x, GetPosition().y - 0.9f, GetPosition().z + input.z); + bt3 = world->BlockAt(GetPosition().x, GetPosition().y - 1.7f, GetPosition().z + input.z); + if (bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR) { + input.z = m_velocity.z = 0; + m_velocity.x *= .5f; + } + + /* Fin gestion de collisions */ + /* Gestion de la friction */ + + if (!m_airborne) { + m_velocity.x += input.x * 2.f * elapsedTime; + m_velocity.z += input.z * 2.f * elapsedTime; + + if (input.x == 0.f) + m_velocity.x *= .8f; + + if (input.z == 0.f) + m_velocity.z *= .8f; + } + else { + m_velocity.x += input.x * .4f * elapsedTime; // Techniquement contre les lois de la physique, mais c'est beaucoup moins chiant pour grimper sur les blocs. + m_velocity.z += input.z * .4f * elapsedTime; + m_velocity.x *= .99f; + m_velocity.z *= .99f; + } + + /* Fin gestion de la friction */ + + float vy = m_velocity.y; + m_velocity.y = 1.f; // Padding pour limiter le x et z lors du Normalize(). + if (m_velocity.Length() >= 1.f) m_velocity.Normalize(); // Limiteur de vitesse en x/z. + m_velocity.y = 0; + if (m_velocity.Length() < .005f) m_velocity.Zero(); // Threshold en x/z. + m_velocity.y = vy; + + m_position += m_velocity; +} + +Vector3f Player::GetPosition() const { return Vector3f(m_position.x + CHUNK_SIZE_X * WORLD_SIZE_X / 2, m_position.y, m_position.z + CHUNK_SIZE_Z * WORLD_SIZE_Y / 2); } + +Vector3f Player::GetVelocity() const { return m_velocity; } + +Vector3f Player::GetPOV() const { return Vector3f(GetPosition().x, m_POV, GetPosition().z); } + +Vector3f Player::GetDirection() const { return m_direction; } + +void Player::Teleport(int& x, int& z) { + m_position.x -= x * CHUNK_SIZE_X; + m_position.z -= z * CHUNK_SIZE_Z; +} diff --git a/SQCSim-common/player.h b/SQCSim-common/player.h new file mode 100644 index 0000000..f889b68 --- /dev/null +++ b/SQCSim-common/player.h @@ -0,0 +1,34 @@ +#ifndef _PLAYER_H__ +#define _PLAYER_H__ +#include "vector3.h" +#include + +class World; + +class Player { +public: + Player(const Vector3f& position, float rotX = 0, float rotY = 0); + void TurnLeftRight(float value); + void TurnTopBottom(float value); + Vector3f GetInput(bool front, bool back, bool left, bool right, bool jump, bool dash, float elapsedTime); + void ApplyPhysics(Vector3f input, World* world, float elapsedTime); + + Vector3f GetPosition() const; + Vector3f GetDirection() const; + Vector3f GetVelocity() const; + Vector3f GetPOV() const; + void Teleport(int& x, int& z); + +protected: + Vector3f m_position; + Vector3f m_velocity; + Vector3f m_direction; + + float m_rotX = 0; + float m_rotY = 0; + float m_POV; + + bool m_airborne; +}; +#endif //_PLAYER_H__ + diff --git a/SQCSim-common/vector3.h b/SQCSim-common/vector3.h new file mode 100644 index 0000000..b191681 --- /dev/null +++ b/SQCSim-common/vector3.h @@ -0,0 +1,219 @@ +#ifndef VECTOR3_H__ +#define VECTOR3_H__ + +#include +#include + +template +class Vector3 +{ +public: + Vector3(); + Vector3(const T& x, const T& y, const T& z); + ~Vector3(); + + T Length() const; + void Normalize(); + void Zero(); + + T Dot(const Vector3& v) const; + Vector3 Cross(const Vector3& v) const; + + Vector3 operator+(const Vector3& v) const; + Vector3 operator-(const Vector3& v) const; + Vector3 operator-() const; + Vector3 operator+(const T& v) const; + Vector3 operator-(const T& v) const; + Vector3 operator/(const T& v) const; + Vector3 operator*(const T& v) const; + + Vector3& operator=(const Vector3& v); + + Vector3& operator+=(const Vector3& v); + Vector3& operator-=(const Vector3& v); + Vector3& operator+=(const T& v); + Vector3& operator-=(const T& v); + Vector3& operator/=(const T& v); + Vector3& operator*=(const T& v); + + bool operator==(const Vector3& v) const; + bool operator!=(const Vector3& v) const; + + void Afficher() const; + +public: + T x, y, z; +}; + +typedef Vector3 Vector3i; +typedef Vector3 Vector3f; + +template +inline std::ostream& operator<<(std::ostream& out, const Vector3& v) +{ + out << "[" << v.x << ", " << v.y << ", " << v.z << "]"; + return out; +} + + +template +Vector3::Vector3() +{ +} + +template +Vector3::Vector3(const T& x, const T& y, const T& z) : x(x), y(y), z(z) +{ +} + +template +Vector3::~Vector3() +{ +} + +template +T Vector3::Length() const +{ + return sqrt(x*x + y*y + z*z); +} + +template +void Vector3::Normalize() +{ + T len = Length(); + if (len != 0) + { + x /= len; + y /= len; + z /= len; + } +} + +template +void Vector3::Zero() +{ + x = y = z = 0; +} + +template +T Vector3::Dot(const Vector3& v) const +{ + return (x * v.x) + (y * v.y) + (z * v.z); +} + +template +Vector3 Vector3::Cross(const Vector3& v) const +{ + return Vector3( + y * v.z - v.y * z, + z * v.x - v.z * x, + x * v.y - v.x * y); +} + +template +Vector3 Vector3::operator+(const Vector3& v) const +{ + return Vector3(x + v.x, y + v.y, z + v.z); +} + +template +Vector3 Vector3::operator-(const Vector3& v) const +{ + return Vector3(x - v.x, y - v.y, z - v.z); +} + +template +Vector3 Vector3::operator-() const +{ + return Vector3(-x, -y, -z); +} + +template +Vector3 Vector3::operator+(const T& v) const +{ + return Vector3(x + v, y + v, z + v); +} + +template +Vector3 Vector3::operator-(const T& v) const +{ + return Vector3(x - v, y - v, z - v); +} + +template +Vector3 Vector3::operator/(const T& v) const +{ + return Vector3(x / v, y / v, z / v); +} + +template +Vector3 Vector3::operator*(const T& v) const +{ + return Vector3(x * v, y * v, z * v); +} + +template +Vector3& Vector3::operator=(const Vector3& v) +{ + x = v.x; + y = v.y; + z = v.z; + return *this; +} + +template +Vector3& Vector3::operator+=(const Vector3& v) +{ + return (*this = *this + v); +} + +template +Vector3& Vector3::operator-=(const Vector3& v) +{ + return (*this = *this - v); +} + +template +Vector3& Vector3::operator+=(const T& v) +{ + return (*this = *this + v); +} + +template +Vector3& Vector3::operator-=(const T& v) +{ + return (*this = *this - v); +} + +template +Vector3& Vector3::operator/=(const T& v) +{ + return (*this = *this / v); +} + +template +Vector3& Vector3::operator*=(const T& v) +{ + return (*this = *this * v); +} + +template +bool Vector3::operator==(const Vector3& v) const +{ + return (x == v.x && y == v.y && z == v.z); +} + +template +bool Vector3::operator!=(const Vector3& v) const +{ + return !(*this == v); +} + +template +void Vector3::Afficher() const +{ + std::cout << "[" << x << ", " << y << ", " << z << "]" << std::endl; +} + + +#endif // VECTOR3_H__ diff --git a/SQCSim-common/world.cpp b/SQCSim-common/world.cpp new file mode 100644 index 0000000..6b4ccf6 --- /dev/null +++ b/SQCSim-common/world.cpp @@ -0,0 +1,109 @@ +#include "world.h" + +World::World() {} + +World::~World() {} + +Array2d& World::GetChunks() { return m_chunks; } + +Chunk* World::ChunkAt(float x, float y, float z) const { + int cx = (int)x / CHUNK_SIZE_X; + int cz = (int)z / CHUNK_SIZE_Z; + + if (x < 0 || y < 0 || z < 0 || + x >= WORLD_SIZE_X * CHUNK_SIZE_X || + z >= CHUNK_SIZE_Z * WORLD_SIZE_Y || + y > CHUNK_SIZE_Y) + return 0; + + return m_chunks.Get(cx, cz); +} + +Chunk* World::ChunkAt(const Vector3f& pos) const { return ChunkAt(pos.x, pos.y, pos.z); } + +BlockType World::BlockAt(float x, float y, float z, BlockType defaultBlockType) const { + Chunk* c = ChunkAt(x, y, z); + + if (!c) + return defaultBlockType; + + int bx = (int)x % CHUNK_SIZE_X; + int by = (int)y % CHUNK_SIZE_Y; + int bz = (int)z % CHUNK_SIZE_Z; + + return c->GetBlock(bx, by, bz); +} + +BlockType World::BlockAt(const Vector3f& pos, BlockType defaultBlockType) const { + return BlockAt(pos.x, pos.y, pos.z, defaultBlockType); +} + +void World::GetScope(unsigned int& x, unsigned int& y) { + x = m_center[0]; + y = m_center[1]; +} + +void World::ChangeBlockAtPosition(BlockType blockType, Vector3f pos) { + int bx = (int)pos.x % CHUNK_SIZE_X; + int by = (int)pos.y % CHUNK_SIZE_Y; + int bz = (int)pos.z % CHUNK_SIZE_Z; + + ChunkAt(pos)->SetBlock(bx, by, bz, blockType, this); +} + +void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block) { + Vector3f currentPos = player.GetPosition(); + Vector3f currentBlock = currentPos; + Vector3f ray = player.GetDirection(); + bool found = false; + + if (block) return; + + while ((currentPos - currentBlock).Length() <= MAX_SELECTION_DISTANCE && !found) { + currentBlock += ray / 10.f; + + BlockType bt = BlockAt(currentBlock); + + if (bt != BTYPE_AIR) + found = true; + } + + if (found) + if (blockType != BTYPE_AIR) { + found = false; + while ((currentPos - currentBlock).Length() >= 1.7f && !found) { + currentBlock -= ray / 10.f; + + BlockType bt = BlockAt(currentBlock); + + if (bt == BTYPE_AIR) { // V?rification pour ?tre s?r que le bloc ? changer n'est pas dans le joueur. + int Bx = (int)currentBlock.x; + int By = (int)currentBlock.y; + int Bz = (int)currentBlock.z; + + int Px = (int)currentPos.x; + int PyA = (int)currentPos.y; + int PyB = (int)(currentPos.y - .9f); + int PyC = (int)(currentPos.y - 1.7f); + int Pz = (int)currentPos.z; + + if (!(Bx == Px && + (By == PyA || + By == PyB || + By == PyC) && + Bz == Pz)) + found = true; + } + } + } + + if (found && (int)currentBlock.y < CHUNK_SIZE_Y) { + int bx = (int)currentBlock.x % CHUNK_SIZE_X; + int by = (int)currentBlock.y % CHUNK_SIZE_Y; + int bz = (int)currentBlock.z % CHUNK_SIZE_Z; + + ChunkAt(currentBlock)->SetBlock(bx, by, bz, blockType, this); + ChunkAt(currentBlock)->MakeModified(); + block = true; + } +} diff --git a/SQCSim-common/world.h b/SQCSim-common/world.h new file mode 100644 index 0000000..dd9967a --- /dev/null +++ b/SQCSim-common/world.h @@ -0,0 +1,45 @@ +#ifndef WORLD_H__ +#define WORLD_H__ +#include +#include +#include +#include +#include +#include "define.h" +#include "chunk.h" +#include "array2d.h" +#include "vector3.h" +#include "player.h" +#include "bullet.h" + +class Chunk; +class Player; +class Bullet; + +class World { +public: + World(); + ~World(); + + Array2d& GetChunks(); + + Chunk* ChunkAt(float x, float y, float z) const; + Chunk* ChunkAt(const Vector3f& pos) const; + + BlockType BlockAt(float x, float y, float z, BlockType defaultBlockType = BTYPE_AIR) const; + BlockType BlockAt(const Vector3f& pos, BlockType defaultBlockType = BTYPE_AIR) const; + + void GetScope(unsigned int& x, unsigned int& y); + + void ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block); + void ChangeBlockAtPosition(BlockType blockType, Vector3f pos); + +private: + Array2d m_chunks = Array2d(WORLD_SIZE_X, WORLD_SIZE_Y); + std::vector m_tbDeleted; + + unsigned int m_center[2] = { UINT16_MAX / 2 - WORLD_SIZE_X, UINT16_MAX / 2 - WORLD_SIZE_Y }; + +}; +#endif // WORLD_H__ + diff --git a/SQCSim-srv/SQCSim-srv.vcxproj b/SQCSim-srv/SQCSim-srv.vcxproj new file mode 100644 index 0000000..ae7b24f --- /dev/null +++ b/SQCSim-srv/SQCSim-srv.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + 17.0 + Win32Proj + {d3bb3300-25f0-42bf-a934-fac33b5c7d25} + SQCSimsrv + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + diff --git a/SQCSim-srv/SQCSim-srv.vcxproj.filters b/SQCSim-srv/SQCSim-srv.vcxproj.filters new file mode 100644 index 0000000..1e51e38 --- /dev/null +++ b/SQCSim-srv/SQCSim-srv.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/SQCSim2021/SQCSim2021.vcxproj b/SQCSim2021/SQCSim2021.vcxproj index 5cda6d0..dfed398 100644 --- a/SQCSim2021/SQCSim2021.vcxproj +++ b/SQCSim2021/SQCSim2021.vcxproj @@ -112,8 +112,8 @@ true - external\irrKlang-1.6.0\include;external\glew170\include;external\devil178\include;external\sfml23\include;$(IncludePath) - external\glew170\lib;external\devil178\lib;external\sfml23\lib;$(LibraryPath);external\irrKlang-1.6.0\lib\Win32-visualStudio + external\irrKlang-1.6.0\include;external\glew210\include;external\devil178\include;external\sfml251\include;$(IncludePath) + external\glew210\lib;external\sfml251\lib;external\devil178\lib;external\irrKlang-1.6.0\lib\Win32-visualStudio;$(LibraryPath) true @@ -122,8 +122,8 @@ false - external\irrKlang-1.6.0\include;external\sfml23\include;external\devil178\include;external\glew170\include;$(IncludePath) - external\sfml23\lib;external\devil178\lib;external\glew170\lib;$(LibraryPath);external\irrKlang-1.6.0\lib\Win32-visualStudio + external\devil180\include;external\irrKlang-1.6.0\include;external\sfml251\include;external\glew210\include;$(IncludePath) + external\sfml251\lib;external\devil180\lib\x86\Release;external\glew210\lib\Release\Win32;$(LibraryPath);external\irrKlang-1.6.0\lib\Win32-visualStudio false diff --git a/SQCSim2021/define.h b/SQCSim2021/define.h index 6104552..6fc950f 100644 --- a/SQCSim2021/define.h +++ b/SQCSim2021/define.h @@ -12,9 +12,9 @@ #include #endif -#define CHUNK_SIZE_X 16 -#define CHUNK_SIZE_Y 128 -#define CHUNK_SIZE_Z 16 +#define CHUNK_SIZE_X 4 +#define CHUNK_SIZE_Y 64 +#define CHUNK_SIZE_Z 4 #define MAX_SELECTION_DISTANCE 5 #define SEED 12345 @@ -36,18 +36,18 @@ #endif #ifdef NDEBUG -#define WORLD_SIZE_X 16 -#define WORLD_SIZE_Y 16 +#define WORLD_SIZE_X 64 +#define WORLD_SIZE_Y 64 #define FRAMES_RENDER_CHUNKS 1 #define FRAMES_UPDATE_CHUNKS 1 #define FRAMES_DELETE_CHUNKS 1 -#define THREADS_GENERATE_CHUNKS 12 -#define THREADS_UPDATE_CHUNKS 5 +#define THREADS_GENERATE_CHUNKS 6 +#define THREADS_UPDATE_CHUNKS 3 #define THREADS_DELETE_CHUNKS 2 -#define VIEW_DISTANCE 1024 +#define VIEW_DISTANCE 512 #define TEXTURE_SIZE 512 #define MAX_BULLETS 512 #endif @@ -56,11 +56,6 @@ typedef uint8_t BlockType; enum BLOCK_TYPE { BTYPE_AIR, BTYPE_DIRT, BTYPE_GRASS, BTYPE_METAL, BTYPE_ICE, BTYPE_LAST }; -//#define TEXTURE_PATH "../SQCSim2021/media/textures/" -//#define SHADER_PATH "../SQCSim2021/media/shaders/" -//#define AUDIO_PATH "../SQCSim2021/media/audio/" -//#define CHUNK_PATH "../SQCSim2021/media/chunks/" - #define TEXTURE_PATH "./media/textures/" #define SHADER_PATH "./media/shaders/" #define AUDIO_PATH "./media/audio/" diff --git a/SQCSim2021/world.cpp b/SQCSim2021/world.cpp index 57b2bbe..bbd86c0 100644 --- a/SQCSim2021/world.cpp +++ b/SQCSim2021/world.cpp @@ -223,7 +223,7 @@ void World::RenderWorld(int& rendercount, Player& player, Transformation& world, direct.Normalize(); pos.y = 1; - static Vector3 renderManifest[VIEW_DISTANCE * 4]; // Nombre de Chunks maximal à être rendus. + static Vector3 renderManifest[VIEW_DISTANCE * 8]; // Nombre de Chunks maximal à être rendus. //for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) { for (int dist = 0; dist <= VIEW_DISTANCE; dist += CHUNK_SIZE_X) { @@ -231,26 +231,26 @@ void World::RenderWorld(int& rendercount, Player& player, Transformation& world, float sinus, cosinus; int echantillons; - if (dist > VIEW_DISTANCE * .5f) { + if (dist > VIEW_DISTANCE * .1f) { sinus = .00872653549f; // sin(1/2 degré) cosinus = .99996192306; // cos(1/2 degré) echantillons = 180; } - else if (dist > VIEW_DISTANCE * .4f) { - sinus = .01151891831f; // sin(2/3 degré) - cosinus = .99993365506; // cos(2/3 degré) - echantillons = 120; - } - else if (dist > VIEW_DISTANCE * .3f) { - sinus = .01745240643; // sin(1 degré) - cosinus = .99984769515; // cos(1 degré) - echantillons = 90; - } - else if (dist > VIEW_DISTANCE * .2f) { - sinus = .0261769483; - cosinus = .99965732497; - echantillons = 60; - } + //else if (dist > VIEW_DISTANCE * .3f) { + // sinus = .01151891831f; // sin(2/3 degré) + // cosinus = .99993365506; // cos(2/3 degré) + // echantillons = 120; + //} + //else if (dist > VIEW_DISTANCE * .2f) { + // sinus = .01745240643; // sin(1 degré) + // cosinus = .99984769515; // cos(1 degré) + // echantillons = 90; + //} + //else if (dist > VIEW_DISTANCE * .1f) { + // sinus = .0261769483; + // cosinus = .99965732497; + // echantillons = 60; + //} else { sinus = .0348994967; cosinus = .99939082701; @@ -293,7 +293,7 @@ void World::RenderWorld(int& rendercount, Player& player, Transformation& world, world.ApplyTranslation(chx, 0, chy); world.Use(); - float blcolor = renderManifest[index].y / (VIEW_DISTANCE * 1000.f); + float blcolor = renderManifest[index].y / (VIEW_DISTANCE / 50.f); glBlendColor(blcolor, blcolor, blcolor, 1.f); ChunkAt(chx, 1, chy)->Render(); world.ApplyTranslation(-chx, 0, -chy); diff --git a/SQCSim2023.sln b/SQCSim2023.sln index 7f8c39d..640b854 100644 --- a/SQCSim2023.sln +++ b/SQCSim2023.sln @@ -1,10 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31702.278 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34031.279 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQCSim2021", "SQCSim2021\SQCSim2021.vcxproj", "{A21FD938-1FEA-4687-AB86-0EABAC30877B}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQCSim-common", "SQCSim-common\SQCSim-common.vcxproj", "{EE91AB12-4225-4A4D-931D-69D72F6D91FB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQCSim-srv", "SQCSim-srv\SQCSim-srv.vcxproj", "{D3BB3300-25F0-42BF-A934-FAC33B5C7D25}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -21,6 +25,22 @@ Global {A21FD938-1FEA-4687-AB86-0EABAC30877B}.Release|x64.Build.0 = Release|x64 {A21FD938-1FEA-4687-AB86-0EABAC30877B}.Release|x86.ActiveCfg = Release|Win32 {A21FD938-1FEA-4687-AB86-0EABAC30877B}.Release|x86.Build.0 = Release|Win32 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Debug|x64.ActiveCfg = Debug|x64 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Debug|x64.Build.0 = Debug|x64 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Debug|x86.ActiveCfg = Debug|Win32 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Debug|x86.Build.0 = Debug|Win32 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Release|x64.ActiveCfg = Release|x64 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Release|x64.Build.0 = Release|x64 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Release|x86.ActiveCfg = Release|Win32 + {EE91AB12-4225-4A4D-931D-69D72F6D91FB}.Release|x86.Build.0 = Release|Win32 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Debug|x64.ActiveCfg = Debug|x64 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Debug|x64.Build.0 = Debug|x64 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Debug|x86.ActiveCfg = Debug|Win32 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Debug|x86.Build.0 = Debug|Win32 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Release|x64.ActiveCfg = Release|x64 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Release|x64.Build.0 = Release|x64 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Release|x86.ActiveCfg = Release|Win32 + {D3BB3300-25F0-42BF-A934-FAC33B5C7D25}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE