Mapgen progress
This commit is contained in:
parent
f57d6a467b
commit
efccd934fb
9 changed files with 279 additions and 278 deletions
BIN
Data/resources/textures/block.png
Normal file
BIN
Data/resources/textures/block.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
Data/resources/textures/stem.png
Normal file
BIN
Data/resources/textures/stem.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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
82
KP3Dii/src/KP3D_Noise.cpp
Normal 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
9
KP3Dii/src/KP3D_Noise.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "KP3D_Common.h"
|
||||
|
||||
namespace kp3d {
|
||||
|
||||
double PerlinNoise2D(double x, double y, double freq, int depth);
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue