diff --git a/Data/resources/textures/block.png b/Data/resources/textures/block.png new file mode 100644 index 0000000..9d1ef3f Binary files /dev/null and b/Data/resources/textures/block.png differ diff --git a/Data/resources/textures/stem.png b/Data/resources/textures/stem.png new file mode 100644 index 0000000..038dd0c Binary files /dev/null and b/Data/resources/textures/stem.png differ diff --git a/Data/sandbox-log.txt b/Data/sandbox-log.txt index 3b722ec..05e2957 100644 --- a/Data/sandbox-log.txt +++ b/Data/sandbox-log.txt @@ -1,14 +1,19 @@ -[08:40:36 AM] Info: Starting... +[02:58:42 PM] Info: Starting... KP3D version 2 =============================== Copyright (C) kpworld.xyz 2018-2024 Contact me! @kp_cftsz -[08:40:36 AM] Info: Initializing SDL -[08:40:36 AM] Info: Initializing OpenGL -[08:40:36 AM] Info: OpenGL version: 4.6.0 NVIDIA 536.23 -[08:40:36 AM] Info: Initializing GLEW -[08:40:36 AM] Info: Initializing SDL_mixer -[08:40:36 AM] Info: Reticulating splines... -[08:40:37 AM] Info: Ready! +[02:58:42 PM] Info: Initializing SDL +[02:58:42 PM] Info: Initializing OpenGL +[02:58:42 PM] Info: OpenGL version: 4.6.0 NVIDIA 517.70 +[02:58:42 PM] Info: Initializing GLEW +[02:58:42 PM] Info: Initializing SDL_mixer +[02:58:43 PM] Info: Reticulating splines... +[02:58:43 PM] Info: Ready! +[02:58:43 PM] Info: BUILDING SECTOR: 1 +[02:58:43 PM] Info: BUILDING SECTOR: 2 +[02:58:43 PM] Info: BUILDING SECTOR: 3 +[02:58:43 PM] Info: BUILDING SECTOR: 4 +[02:58:43 PM] Info: BUILDING SECTOR: 5 diff --git a/KP3Dii/KP3Dii.vcxproj b/KP3Dii/KP3Dii.vcxproj index 3b31201..29bf168 100644 --- a/KP3Dii/KP3Dii.vcxproj +++ b/KP3Dii/KP3Dii.vcxproj @@ -151,6 +151,7 @@ + @@ -197,6 +198,7 @@ + diff --git a/KP3Dii/KP3Dii.vcxproj.filters b/KP3Dii/KP3Dii.vcxproj.filters index 7f36d80..b4ef0b6 100644 --- a/KP3Dii/KP3Dii.vcxproj.filters +++ b/KP3Dii/KP3Dii.vcxproj.filters @@ -38,6 +38,7 @@ + @@ -86,6 +87,7 @@ + diff --git a/KP3Dii/src/KP3D_Map.cpp b/KP3Dii/src/KP3D_Map.cpp index d8a5b64..37af8d4 100644 --- a/KP3Dii/src/KP3D_Map.cpp +++ b/KP3Dii/src/KP3D_Map.cpp @@ -2,12 +2,27 @@ #include +#include + #include #include #include #include "KP3D_Renderer3D.h" #include "KP3D_Shader.h" +#include "KP3D_Noise.h" + + + +namespace std { +template<> +struct hash { + std::size_t operator()(const kp3d::Vec3& point) const { + return std::hash()(point.x) ^ std::hash()(point.y) ^ std::hash()(point.z); + } +}; +} + namespace { @@ -28,61 +43,6 @@ bool PointInPolygon(std::vector polygon, kp3d::XYf p) return c; } -Vec3 calculateCentroid(const std::vector& points) { - Vec3 centroid = { 0.0f, 0.0f, 0.0f }; - float signedArea = 0.0f; - float x0 = 0.0f; // Current vertex X - float y0 = 0.0f; // Current vertex Y - float x1 = 0.0f; // Next vertex X - float y1 = 0.0f; // Next vertex Y - float a = 0.0f; // Partial signed area - - // For all vertices except last - for (size_t i = 0; i < points.size() - 1; ++i) { - x0 = points[i].x; - y0 = points[i].y; - x1 = points[i + 1].x; - y1 = points[i + 1].y; - a = x0 * y1 - x1 * y0; - signedArea += a; - centroid.x += (x0 + x1) * a; - centroid.y += (y0 + y1) * a; - } - - // Do last vertex separately to complete the loop - x0 = points.back().x; - y0 = points.back().y; - x1 = points[0].x; - y1 = points[0].y; - a = x0 * y1 - x1 * y0; - signedArea += a; - centroid.x += (x0 + x1) * a; - centroid.y += (y0 + y1) * a; - - signedArea *= 0.5; - centroid.x /= (6.0f * signedArea); - centroid.y /= (6.0f * signedArea); - - return centroid; -} - - - -// Define a hash function for Vec3 -struct Vec3Hash { - std::size_t operator()(const Vec3& v) const { - std::size_t h1 = std::hash{}(v.x); - std::size_t h2 = std::hash{}(v.y); - std::size_t h3 = std::hash{}(v.z); - - std::size_t hash = h1; - hash ^= h2 + 0x9e3779b9 + (hash << 6) + (hash >> 2); - hash ^= h3 + 0x9e3779b9 + (hash << 6) + (hash >> 2); - - return hash; - } -}; - float Distance(XYf p1, XYf p2) { return sqrtf((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)); @@ -99,146 +59,6 @@ bool PointInLine(float x1, float y1, float x2, float y2, float x0, float y0) return kp3d::FloatCmp((y2 - y1) * x0 + (x1 - x2) * y0 + (x2 * y1 - x1 * y2), 0.0f, 0.0001f) && in_bounds; } - -static const int SEED = 1985; - -static const unsigned char HASH[] = { - 208,34,231,213,32,248,233,56,161,78,24,140,71,48,140,254,245,255,247,247,40, - 185,248,251,245,28,124,204,204,76,36,1,107,28,234,163,202,224,245,128,167,204, - 9,92,217,54,239,174,173,102,193,189,190,121,100,108,167,44,43,77,180,204,8,81, - 70,223,11,38,24,254,210,210,177,32,81,195,243,125,8,169,112,32,97,53,195,13, - 203,9,47,104,125,117,114,124,165,203,181,235,193,206,70,180,174,0,167,181,41, - 164,30,116,127,198,245,146,87,224,149,206,57,4,192,210,65,210,129,240,178,105, - 228,108,245,148,140,40,35,195,38,58,65,207,215,253,65,85,208,76,62,3,237,55,89, - 232,50,217,64,244,157,199,121,252,90,17,212,203,149,152,140,187,234,177,73,174, - 193,100,192,143,97,53,145,135,19,103,13,90,135,151,199,91,239,247,33,39,145, - 101,120,99,3,186,86,99,41,237,203,111,79,220,135,158,42,30,154,120,67,87,167, - 135,176,183,191,253,115,184,21,233,58,129,233,142,39,128,211,118,137,139,255, - 114,20,218,113,154,27,127,246,250,1,8,198,250,209,92,222,173,21,88,102,219 -}; - -static int noise2(int x, int y) -{ - int yindex = (y + SEED) % 256; - if (yindex < 0) - yindex += 256; - int xindex = (HASH[yindex] + x) % 256; - if (xindex < 0) - xindex += 256; - const int result = HASH[xindex]; - return result; -} - -static double lin_inter(double x, double y, double s) -{ - return x + s * (y - x); -} - -static double smooth_inter(double x, double y, double s) -{ - return lin_inter(x, y, s * s * (3 - 2 * s)); -} - -static double noise2d(double x, double y) -{ - const int x_int = floor(x); - const int y_int = floor(y); - const double x_frac = x - x_int; - const double y_frac = y - y_int; - const int s = noise2(x_int, y_int); - const int t = noise2(x_int + 1, y_int); - const int u = noise2(x_int, y_int + 1); - const int v = noise2(x_int + 1, y_int + 1); - const double low = smooth_inter(s, t, x_frac); - const double high = smooth_inter(u, v, x_frac); - const double result = smooth_inter(low, high, y_frac); - return result; -} - -double Perlin_Get2d(double x, double y, double freq, int depth) -{ - double xa = x * freq; - double ya = y * freq; - double amp = 1.0; - double fin = 0; - double div = 0.0; - for (int i = 0; i < depth; i++) - { - div += 256 * amp; - fin += noise2d(xa, ya) * amp; - amp /= 2; - xa *= 2; - ya *= 2; - } - return fin / div; -} - -using namespace kp3d; -using Point = Vec3; -using Polygon = std::vector; -class Plane { -private: - Point _normal, _v1, _v2, _v3; - double_t _d; -public: - Plane(Point normal, double_t d) : _normal(normal), _d(d) {} - Plane(Point v1, Point v2, Point v3) : _v1(v1), _v2(v2), _v3(v3) { - //Create a plane from 3 non-colinear points (i.e. triangle) - _normal = (v2 - v1).Cross(v3 - v1).Normalized(); - _d = -_normal.Dot(v1); - } - Point intersectionPoint(Point p1, Point p2) const { - //Return the intersection point of a line passing two points and this plane - return p1 + (p2 - p1) * (-distance(p1) / _normal.Dot(p2 - p1)); - }; - void invert() { _normal = _normal * (-1); } - Point getNormal() const { return _normal; } - Polygon getTriangle() const { - vector points = { _v1, _v2, _v3 }; - return Polygon(points); - } - double_t distance(Point q) const { return _normal.Dot(q) + _d; } -}; - -Polygon SutherlandHodgman(const Polygon startingPolygon, vector clippingPlanes) { - float epsilon = 0.000001f; - double_t D1, D2 = 0; - Polygon polygon = Polygon(startingPolygon); - for (unsigned int c = 0; c < clippingPlanes.size(); c++) { - if (polygon.empty()) { return polygon; } - Polygon clippedPolygon = Polygon(); - vector points = polygon; - for (unsigned int i = 0; i < points.size() - 1; i++) { - D1 = clippingPlanes[c].distance(points[i]); - D2 = clippingPlanes[c].distance(points[i + 1]); - if ((D1 <= 0) && (D2 <= 0)) - { - clippedPolygon.push_back(points[i + 1]); - } - else if ((D1 > 0) && ((D2 > -epsilon) && (D2 < epsilon))) - { - clippedPolygon.push_back(points[i + 1]); - } - else if (((D1 > -epsilon) && (D1 < epsilon)) && (D2 > 0)) - { - continue; - } - else if ((D1 <= 0) && (D2 > 0)) - { - clippedPolygon.push_back(clippingPlanes[c].intersectionPoint(points[i], - points[i + 1])); - } - else if ((D1 > 0) && (D2 <= 0)) - { - clippedPolygon.push_back(clippingPlanes[c].intersectionPoint(points[i], - points[i + 1])); - clippedPolygon.push_back(points[i + 1]); - } - } - polygon = Polygon(clippedPolygon); // keep on working with the new polygon - } - return polygon; -} } // namespace namespace kp3d { @@ -275,6 +95,35 @@ void Map::BuildFlat(Sector& sector, Flat& flat, bool invert) steiner_points.emplace_back(st.x, st.z); std::vector> subsector_polygons; // unused for now + + for (Sector& s : sectors) + { + if (s.id == sector.id) + continue; + + std::vector ss; + + for (Wall& l : s.walls) + { + if (PointInPolygon(sector.walls, l.start)) + { + ss.push_back({l.start.x, l.start.y}); + } + } + + if (ss.size() == s.walls.size()) + { + + for (Wall& l : s.walls) + { + l.textures[TEX_FRONT] = nullptr; + l.textures[TEX_BACK] = nullptr; + } + + subsector_polygons.push_back(ss); + } + } + std::vector sector_polygons; for (Wall& l: sector.walls) sector_polygons.emplace_back(l.start.x, l.start.y); @@ -344,6 +193,9 @@ void Map::BuildFlat(Sector& sector, Flat& flat, bool invert) */ void Map::BuildQuad(Sector& sector, const Texture* texture, Vec3 pos_a, Vec3 pos_b, bool flip, bool flip_u, bool flip_v, XYf uv_offset) { + if (!texture) + return; + Vec3 p1 = Vec3(pos_a.x, pos_a.y, pos_a.z); Vec3 p2 = Vec3(pos_a.x, pos_b.y, pos_a.z); Vec3 p3 = Vec3(pos_b.x, pos_a.y, pos_b.z); @@ -373,32 +225,6 @@ void Map::BuildQuad(Sector& sector, const Texture* texture, Vec3 pos_a, Vec3 pos // Test: Put points back in their original positions float angle = atan2({ p4.z - p1.z }, { p4.x - p1.x }); -#if 0 - // Debug - for (Vec3& p: points) - { - // Convert back into 3D - p = p.Rotated({0, 1, 0}, -ToDegrees(angle)); - p.x += p1.x; - p.z += p1.z; - } - for (Vec3 p: points) - m_dots.push_back(p); - - // Enforce clockwise-ness - float area = 0.0f; - for (int i = 0; i < points.size(); i++) - { - Vec3 start = points[i]; - Vec3 end = points[(i + 1) % points.size()]; - area += start.x * end.y; - area -= end.x * start.y; - } - area /= 2.0f; - if (area <= 0.0f) - std::reverse(points.begin(), points.end()); -#endif - points.erase(unique(points.begin(), points.end()), points.end()); std::vector> holes; // unused for now @@ -451,72 +277,146 @@ void Map::Init() {11, 13}, {4, 14}, {4, 12}, - {1, 12}, + {1, 12}, // Main sector + }; + + XYf points2[] = { + {4,5},{7,5},{7,6},{8,6},{8,10},{4,10} // Middle area + }; + + XYf points3[] = { + {7,5},{8,5},{8,6},{7,6} // Column (neighboring/outside middle area, not within) + }; + + XYf points4[] = { + {points3[0].x, points3[0].y + 4}, + {points3[1].x, points3[1].y + 4}, + {points3[2].x, points3[2].y + 4}, + {points3[3].x, points3[3].y + 4} // Column (within middle area) + }; + + XYf points5[] = { + {11,4},{14,4},{14,2},{16,2},{16,10},{11,10} // Neighbor of main sector }; BuildSkybox("skybox_16.jpg"); - static kp3d::Texture tex, tex2, tex3; + static kp3d::Texture tex, tex2, tex3, tex4; tex.Load("GRASS2.png"); tex2.Load("floor0.png"); tex3.Load("FLAT5_7.png"); + tex4.Load("block.png"); m_dot.Load("dot.png"); - Sector s; - s.ceiling.texture = &tex2; - s.floor.texture = &tex; - s.floor.base_height = -1.0f; - s.ceiling.base_height = 5.0f; - s.id = 1; - s.parent_id = 0; - float scl = 1.0f; - for (size_t i = 0; i < std::size(points); i++) - { - XYf start = points[i]; - XYf end = points[(i + 1) % std::size(points)]; - start.x *= 2.0f; - end.x *= 2.0f; - start.y *= 2.0f; - end.y *= 2.0f; - s.walls.push_back(Wall{{nullptr,&tex3,nullptr,nullptr}, {{0, 0}}, start, end, Wall::NO_FLAGS, (uint) i}); - } - sectors.push_back(s); - // Build up "steiner points" for terrain only - // We'll do this along a grid for now; it should be noted that this will be expected to be part of the sector data later - int num_steiners_along_xy = 50 * scl; - float steiner_size = 1.0f; - for (int i = 0; i < num_steiners_along_xy; i++) - { - for (int j = 0; j < num_steiners_along_xy; j++) + auto build_sector = [&](Texture* wall, Texture* floor, Texture* ceil, float floor_height, float ceil_height, int id, XYf* points, size_t num_points) { + Sector s; + s.ceiling.texture = ceil; + s.floor.texture = floor; + s.floor.base_height = floor_height; + s.ceiling.base_height = ceil_height; + s.id = id; + s.parent_id = 0; + float scl = 1.0f; + for (size_t i = 0; i < num_points; i++) { - // Build a Steiner point to be used in the triangulation process; with this we can get slopes, terrain, etc. - XYf steiner_point = {((float) i * steiner_size), ((float) j * steiner_size)}; - if (!PointInPolygon(s.walls, steiner_point)) - continue; + XYf start = points[i]; + XYf end = points[(i + 1) % num_points]; + s.walls.push_back(Wall{ {nullptr,wall,nullptr,nullptr}, {{0, 0}}, start, end, Wall::NO_FLAGS, (uint)i }); + } + sectors.push_back(s); - // Since Clipper doesn't allow for duplicate points, remove any Steiner points that may have landed on a map vertex - bool bail = false; - for (Wall& ld: s.walls) + }; + + build_sector(&tex3, &tex, &tex2, -1.0f, 5.0f, 1, points, std::size(points)); + build_sector(&tex4, &tex2, &tex2, -1.5f, 4.0f, 2, points2, std::size(points2)); + build_sector(&tex4, &tex, &tex2, -1.5f, 4.0f, 3, points3, std::size(points3)); + build_sector(&tex4, &tex, &tex2, -1.5f, 4.0f, 4, points4, std::size(points4)); + build_sector(&tex3, &tex, &tex2, -0.5f, 3.0f, 5, points5, std::size(points5)); + + for (Sector& s : sectors) + { + KP3D_LOG_INFO("BUILDING SECTOR: {}", s.id); + + // Build up "steiner points" for terrain only + // We'll do this along a grid for now; it should be noted that this will be expected to be part of the sector data later + int num_steiners_along_xy = 50; + float steiner_size = 1.0f; + for (int i = 0; i < num_steiners_along_xy; i++) + { + for (int j = 0; j < num_steiners_along_xy; j++) { - if ((FloatCmp(steiner_point.x, ld.start.x, 0.0f) && FloatCmp(steiner_point.y, ld.start.y, 0.0f)) || - (FloatCmp(steiner_point.x, ld.end.x, 0.0f) && FloatCmp(steiner_point.y, ld.end.y, 0.0f))) - bail = true; + // Build a Steiner point to be used in the triangulation process; with this we can get slopes, terrain, etc. + XYf steiner_point = { ((float)i * steiner_size), ((float)j * steiner_size) }; + if (!PointInPolygon(s.walls, steiner_point)) + continue; + + // Since Clipper doesn't allow for duplicate points, remove any Steiner points that may have landed on a map vertex + bool bail = false; + for (Wall& ld : s.walls) + { + if ((FloatCmp(steiner_point.x, ld.start.x, 0.0f) && FloatCmp(steiner_point.y, ld.start.y, 0.0f)) || + (FloatCmp(steiner_point.x, ld.end.x, 0.0f) && FloatCmp(steiner_point.y, ld.end.y, 0.0f))) + bail = true; + } + + if (bail) + continue; + + float yv = PerlinNoise2D(steiner_point.x, steiner_point.y, 1.0, 10.0); // Temp + if (s.id == 1) + s.floor.steiner_points.push_back({ steiner_point.x, yv, steiner_point.y }); } + } - if (bail) - continue; + // Build level geometry + BuildFlat(s, s.floor, false); + BuildFlat(s, s.ceiling, true); - float yv = Perlin_Get2d(steiner_point.x, steiner_point.y, 1.0, 10.0); // Temp - s.floor.steiner_points.push_back({steiner_point.x, yv, steiner_point.y}); + for (Wall& ld : s.walls) + BuildWall(s, ld); + } + + // Go through all of the vertices and align them to a grid (very roughly; might want to revisit this later) +#if 0 + const float grid_size = 1.0f / (texture_scale - 1.0f), tolerance = (1.0f / texture_scale); + for (RenderBatch3D& b: m_mesh.GetBatchesRef()) + { + std::unordered_set unique_points; + for (Vertex3D& v: b.vertex_data) + { + v.position.x = std::round(v.position.x / grid_size) * grid_size; + v.position.y = std::round(v.position.y / grid_size) * grid_size; + v.position.z = std::round(v.position.z / grid_size) * grid_size; + bool snapped = false; + for (const auto& unique_point: unique_points) + { + if (std::abs(v.position.x - unique_point.x) <= tolerance && + std::abs(v.position.y - unique_point.y) <= tolerance && + std::abs(v.position.z - unique_point.z) <= tolerance) + { + v.position = unique_point; + snapped = true; + break; + } + } + if (!snapped) + unique_points.insert(v.position); + } + } +#endif + for (RenderBatch3D& b : m_mesh.GetBatchesRef()) + { + std::unordered_set unique_points; + for (size_t i = 0; i < b.vertex_data.size(); i += 3) + { + std::swap(b.vertex_data[i + 1], b.vertex_data[i + 2]); + b.vertex_data[i].position.z = -b.vertex_data[i].position.z; + b.vertex_data[i+1].position.z = -b.vertex_data[i+1].position.z; + b.vertex_data[i+2].position.z = -b.vertex_data[i+2].position.z; } } - BuildFlat(s, s.floor, false); - BuildFlat(s, s.ceiling, true); - - for (Wall& ld: s.walls) - BuildWall(s, ld); - + // Finalize the mesh m_mesh.Finalize(); } diff --git a/KP3Dii/src/KP3D_Noise.cpp b/KP3Dii/src/KP3D_Noise.cpp new file mode 100644 index 0000000..17f3e17 --- /dev/null +++ b/KP3Dii/src/KP3D_Noise.cpp @@ -0,0 +1,82 @@ +#include "KP3D_Noise.h" + +#include + +namespace { + +const int SEED = 1985; + +const unsigned char HASH[] = { + 208, 34, 231, 213, 32, 248, 233, 56, 161, 78, 24, 140, 71, 48, 140, 254, 245, 255, 247, 247, 40, 185, 248, 251, + 245, 28, 124, 204, 204, 76, 36, 1, 107, 28, 234, 163, 202, 224, 245, 128, 167, 204, 9, 92, 217, 54, 239, 174, + 173, 102, 193, 189, 190, 121, 100, 108, 167, 44, 43, 77, 180, 204, 8, 81, 70, 223, 11, 38, 24, 254, 210, 210, + 177, 32, 81, 195, 243, 125, 8, 169, 112, 32, 97, 53, 195, 13, 203, 9, 47, 104, 125, 117, 114, 124, 165, 203, + 181, 235, 193, 206, 70, 180, 174, 0, 167, 181, 41, 164, 30, 116, 127, 198, 245, 146, 87, 224, 149, 206, 57, 4, + 192, 210, 65, 210, 129, 240, 178, 105, 228, 108, 245, 148, 140, 40, 35, 195, 38, 58, 65, 207, 215, 253, 65, 85, + 208, 76, 62, 3, 237, 55, 89, 232, 50, 217, 64, 244, 157, 199, 121, 252, 90, 17, 212, 203, 149, 152, 140, 187, + 234, 177, 73, 174, 193, 100, 192, 143, 97, 53, 145, 135, 19, 103, 13, 90, 135, 151, 199, 91, 239, 247, 33, 39, + 145, 101, 120, 99, 3, 186, 86, 99, 41, 237, 203, 111, 79, 220, 135, 158, 42, 30, 154, 120, 67, 87, 167, 135, + 176, 183, 191, 253, 115, 184, 21, 233, 58, 129, 233, 142, 39, 128, 211, 118, 137, 139, 255, 114, 20, 218, 113, 154, + 27, 127, 246, 250, 1, 8, 198, 250, 209, 92, 222, 173, 21, 88, 102, 219}; + +int Noise2(int x, int y) +{ + int yindex = (y + SEED) % 256; + if (yindex < 0) + yindex += 256; + int xindex = (HASH[yindex] + x) % 256; + if (xindex < 0) + xindex += 256; + const int result = HASH[xindex]; + return result; +} + +double LinInterp(double x, double y, double s) +{ + return x + s * (y - x); +} + +double SmoothInterp(double x, double y, double s) +{ + return LinInterp(x, y, s * s * (3 - 2 * s)); +} + +double Noise2D(double x, double y) +{ + const int x_int = floor(x); + const int y_int = floor(y); + const double x_frac = x - x_int; + const double y_frac = y - y_int; + const int s = Noise2(x_int, y_int); + const int t = Noise2(x_int + 1, y_int); + const int u = Noise2(x_int, y_int + 1); + const int v = Noise2(x_int + 1, y_int + 1); + const double low = SmoothInterp(s, t, x_frac); + const double high = SmoothInterp(u, v, x_frac); + const double result = SmoothInterp(low, high, y_frac); + return result; +} + +} // namespace + +namespace kp3d { + +double PerlinNoise2D(double x, double y, double freq, int depth) +{ + double xa = x * freq; + double ya = y * freq; + double amp = 1.0; + double fin = 0; + double div = 0.0; + for (int i = 0; i < depth; i++) + { + div += 256 * amp; + fin += Noise2D(xa, ya) * amp; + amp /= 2; + xa *= 2; + ya *= 2; + } + return fin / div; +} + +} // namespace kp3d diff --git a/KP3Dii/src/KP3D_Noise.h b/KP3Dii/src/KP3D_Noise.h new file mode 100644 index 0000000..cf61758 --- /dev/null +++ b/KP3Dii/src/KP3D_Noise.h @@ -0,0 +1,9 @@ +#pragma once + +#include "KP3D_Common.h" + +namespace kp3d { + +double PerlinNoise2D(double x, double y, double freq, int depth); + +} diff --git a/KP3Dii/src/KP3D_Vec3.cpp b/KP3Dii/src/KP3D_Vec3.cpp index 841a2e0..3f4d053 100644 --- a/KP3Dii/src/KP3D_Vec3.cpp +++ b/KP3Dii/src/KP3D_Vec3.cpp @@ -155,7 +155,8 @@ Vec3 Vec3::operator-() const bool operator==(const Vec3& lhs, const Vec3& rhs) { - return std::tie(lhs.x, lhs.y, lhs.z) == std::tie(rhs.x, rhs.y, rhs.z); + return std::abs(lhs.x - rhs.x) < 1e-6 && std::abs(lhs.y - rhs.y) < 1e-6 && std::abs(lhs.z - rhs.z) < 1e-6; + // return std::tie(lhs.x, lhs.y, lhs.z) == std::tie(rhs.x, rhs.y, rhs.z); } bool operator!=(const Vec3& lhs, const Vec3& rhs)