Mapgen progress

This commit is contained in:
KP 2024-07-22 15:02:38 -05:00
parent f57d6a467b
commit efccd934fb
9 changed files with 279 additions and 278 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -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

View file

@ -151,6 +151,7 @@
<ClInclude Include="src\KP3D_Math.h" />
<ClInclude Include="src\KP3D_MethodHandler.h" />
<ClInclude Include="src\KP3D_Model.h" />
<ClInclude Include="src\KP3D_Noise.h" />
<ClInclude Include="src\KP3D_Packet.h" />
<ClInclude Include="src\KP3D_Packet.inl.h" />
<ClInclude Include="src\KP3D_Network.h" />
@ -197,6 +198,7 @@
<ClCompile Include="src\KP3D_Mat4.cpp" />
<ClCompile Include="src\KP3D_MethodHandler.cpp" />
<ClCompile Include="src\KP3D_Model.cpp" />
<ClCompile Include="src\KP3D_Noise.cpp" />
<ClCompile Include="src\KP3D_Packet.cpp" />
<ClCompile Include="src\KP3D_Network.cpp" />
<ClCompile Include="src\KP3D_Quaternion.cpp" />

View file

@ -38,6 +38,7 @@
<ClInclude Include="src\ksi\KSI.h" />
<ClInclude Include="src\KP3D_Console.h" />
<ClInclude Include="src\KP3D_Map.h" />
<ClInclude Include="src\KP3D_Noise.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\KP3D_Vec2.cpp" />
@ -86,6 +87,7 @@
<ClCompile Include="ext\src\poly2tri\sweep.cc" />
<ClCompile Include="ext\src\poly2tri\sweep_context.cc" />
<ClCompile Include="ext\src\clipper\clipper.cpp" />
<ClCompile Include="src\KP3D_Noise.cpp" />
</ItemGroup>
<ItemGroup>
<None Include=".clang-format" />

View file

@ -2,12 +2,27 @@
#include <math.h>
#include <unordered_set>
#include <clip2tri/clip2tri.h>
#include <clipper/clipper.hpp>
#include <poly2tri/poly2tri.h>
#include "KP3D_Renderer3D.h"
#include "KP3D_Shader.h"
#include "KP3D_Noise.h"
namespace std {
template<>
struct hash<kp3d::Vec3> {
std::size_t operator()(const kp3d::Vec3& point) const {
return std::hash<float>()(point.x) ^ std::hash<float>()(point.y) ^ std::hash<float>()(point.z);
}
};
}
namespace {
@ -28,61 +43,6 @@ bool PointInPolygon(std::vector<kp3d::Wall> polygon, kp3d::XYf p)
return c;
}
Vec3 calculateCentroid(const std::vector<Vec3>& 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<float>{}(v.x);
std::size_t h2 = std::hash<float>{}(v.y);
std::size_t h3 = std::hash<float>{}(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<Point>;
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<Point> points = { _v1, _v2, _v3 };
return Polygon(points);
}
double_t distance(Point q) const { return _normal.Dot(q) + _d; }
};
Polygon SutherlandHodgman(const Polygon startingPolygon, vector<Plane> 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<Point> 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<std::vector<c2t::Point>> subsector_polygons; // unused for now
for (Sector& s : sectors)
{
if (s.id == sector.id)
continue;
std::vector<c2t::Point> 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<c2t::Point> 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<std::vector<c2t::Point>> 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<Vec3> 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<Vec3> 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();
}

82
KP3Dii/src/KP3D_Noise.cpp Normal file
View file

@ -0,0 +1,82 @@
#include "KP3D_Noise.h"
#include <math.h>
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

9
KP3Dii/src/KP3D_Noise.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#include "KP3D_Common.h"
namespace kp3d {
double PerlinNoise2D(double x, double y, double freq, int depth);
}

View file

@ -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)