Clean up
This commit is contained in:
parent
519d780b3c
commit
e04fcbb9bd
@ -32,8 +32,6 @@ add_executable(witcher001
|
|||||||
../src/TextModel.h
|
../src/TextModel.h
|
||||||
../src/AudioPlayerAsync.cpp
|
../src/AudioPlayerAsync.cpp
|
||||||
../src/AudioPlayerAsync.h
|
../src/AudioPlayerAsync.h
|
||||||
../src/BoneAnimatedModel.cpp
|
|
||||||
../src/BoneAnimatedModel.h
|
|
||||||
../src/BoneAnimatedModelNew.cpp
|
../src/BoneAnimatedModelNew.cpp
|
||||||
../src/BoneAnimatedModelNew.h
|
../src/BoneAnimatedModelNew.h
|
||||||
../src/render/OpenGlExtensions.cpp
|
../src/render/OpenGlExtensions.cpp
|
||||||
@ -42,8 +40,6 @@ add_executable(witcher001
|
|||||||
../src/utils/Utils.h
|
../src/utils/Utils.h
|
||||||
../src/SparkEmitter.cpp
|
../src/SparkEmitter.cpp
|
||||||
../src/SparkEmitter.h
|
../src/SparkEmitter.h
|
||||||
../src/utils/Perlin.cpp
|
|
||||||
../src/utils/Perlin.h
|
|
||||||
../src/utils/TaskManager.cpp
|
../src/utils/TaskManager.cpp
|
||||||
../src/utils/TaskManager.h
|
../src/utils/TaskManager.h
|
||||||
../src/render/FrameBuffer.cpp
|
../src/render/FrameBuffer.cpp
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,103 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "render/Renderer.h"
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
|
|
||||||
namespace ZL
|
|
||||||
{
|
|
||||||
constexpr int MAX_BONE_COUNT = 6;
|
|
||||||
constexpr int MAX_GPU_BONES = 64;
|
|
||||||
struct Bone
|
|
||||||
{
|
|
||||||
Vector3f boneStartWorld;
|
|
||||||
float boneLength;
|
|
||||||
Matrix4f boneMatrixWorld;
|
|
||||||
|
|
||||||
int parent;
|
|
||||||
std::vector<int> children;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BoneWeight
|
|
||||||
{
|
|
||||||
int boneIndex = -1;
|
|
||||||
float weight = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AnimationKeyFrame
|
|
||||||
{
|
|
||||||
int frame;
|
|
||||||
std::vector<Bone> bones;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Animation
|
|
||||||
{
|
|
||||||
std::vector<AnimationKeyFrame> keyFrames;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GpuBoneData {
|
|
||||||
std::vector<Vector4f> boneIndices0; // bone indices 0-3 per vertex (as float)
|
|
||||||
std::vector<Vector2f> boneIndices1; // bone indices 4-5 per vertex
|
|
||||||
std::vector<Vector4f> boneWeights0; // bone weights 0-3 per vertex
|
|
||||||
std::vector<Vector2f> boneWeights1; // bone weights 4-5 per vertex
|
|
||||||
bool prepared = false;
|
|
||||||
void PrepareGpuSkinningData(const std::vector<std::array<BoneWeight, MAX_BONE_COUNT>>& verticesBoneWeight);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BoneSystem
|
|
||||||
{
|
|
||||||
VertexDataStruct mesh;
|
|
||||||
VertexDataStruct startMesh;
|
|
||||||
std::vector<std::array<BoneWeight, MAX_BONE_COUNT>> verticesBoneWeight;
|
|
||||||
|
|
||||||
Matrix4f armatureMatrix;
|
|
||||||
|
|
||||||
std::vector<Bone> startBones;
|
|
||||||
std::vector<Bone> currentBones;
|
|
||||||
std::vector<std::string> boneNames;
|
|
||||||
|
|
||||||
std::vector<Animation> animations;
|
|
||||||
int startingFrame = 0;
|
|
||||||
|
|
||||||
void LoadFromFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
|
||||||
void LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
|
||||||
|
|
||||||
void Interpolate(int frame);
|
|
||||||
|
|
||||||
int findBoneIndex(const std::string& name) const;
|
|
||||||
|
|
||||||
// GPU skinning: compute skinning matrices without modifying the mesh
|
|
||||||
//void ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct GpuSkinningShaderData {
|
|
||||||
GpuBoneData gpuBoneData;
|
|
||||||
|
|
||||||
// GPU skinning data (lazily initialized)
|
|
||||||
VertexRenderStruct bindPoseMutable;
|
|
||||||
std::shared_ptr<VBOHolder> boneIndices0VBO;
|
|
||||||
std::shared_ptr<VBOHolder> boneIndices1VBO;
|
|
||||||
std::shared_ptr<VBOHolder> boneWeights0VBO;
|
|
||||||
std::shared_ptr<VBOHolder> boneWeights1VBO;
|
|
||||||
bool gpuSkinningPrepared = false;
|
|
||||||
std::vector<Eigen::Matrix4f> skinningMatrices;
|
|
||||||
|
|
||||||
void prepareGpuSkinningVBOs(BoneSystem& model);
|
|
||||||
void RenderVBO(Renderer& renderer);
|
|
||||||
void ComputeSkinningMatrices(const std::vector<Bone>& startBones, const std::vector<AnimationKeyFrame>& keyFrames, int frame);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BoneAnimationData {
|
|
||||||
BoneSystem model;
|
|
||||||
float currentFrame = 0.f;
|
|
||||||
int lastFrame = -1;
|
|
||||||
int totalFrames = 1;
|
|
||||||
|
|
||||||
GpuSkinningShaderData gpuSkinningShaderData;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -13,7 +13,21 @@ namespace ZL
|
|||||||
using std::max;
|
using std::max;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int getIndexByValue(const std::string& name, const std::vector<std::string>& words);
|
int getIndexByValue(const std::string& name, const std::vector<std::string>& words)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < words.size(); i++)
|
||||||
|
{
|
||||||
|
if (words[i] == name)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Bone name not found: " << name << std::endl;
|
||||||
|
throw std::runtime_error("Bone name not found: " + name);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static std::string trimRight(const std::string& s)
|
static std::string trimRight(const std::string& s)
|
||||||
{
|
{
|
||||||
@ -23,6 +37,42 @@ namespace ZL
|
|||||||
return s.substr(0, end);
|
return s.substr(0, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GpuBoneData::PrepareGpuSkinningData(const std::vector<std::array<BoneWeight, MAX_BONE_COUNT>>& verticesBoneWeight)
|
||||||
|
{
|
||||||
|
size_t vertexCount = verticesBoneWeight.size();
|
||||||
|
boneIndices0.resize(vertexCount);
|
||||||
|
boneIndices1.resize(vertexCount);
|
||||||
|
boneWeights0.resize(vertexCount);
|
||||||
|
boneWeights1.resize(vertexCount);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < vertexCount; i++)
|
||||||
|
{
|
||||||
|
boneIndices0[i] = Vector4f(
|
||||||
|
static_cast<float>(max(0, verticesBoneWeight[i][0].boneIndex)),
|
||||||
|
static_cast<float>(max(0, verticesBoneWeight[i][1].boneIndex)),
|
||||||
|
static_cast<float>(max(0, verticesBoneWeight[i][2].boneIndex)),
|
||||||
|
static_cast<float>(max(0, verticesBoneWeight[i][3].boneIndex))
|
||||||
|
);
|
||||||
|
boneIndices1[i] = Vector2f(
|
||||||
|
static_cast<float>(max(0, verticesBoneWeight[i][4].boneIndex)),
|
||||||
|
static_cast<float>(max(0, verticesBoneWeight[i][5].boneIndex))
|
||||||
|
);
|
||||||
|
boneWeights0[i] = Vector4f(
|
||||||
|
verticesBoneWeight[i][0].weight,
|
||||||
|
verticesBoneWeight[i][1].weight,
|
||||||
|
verticesBoneWeight[i][2].weight,
|
||||||
|
verticesBoneWeight[i][3].weight
|
||||||
|
);
|
||||||
|
boneWeights1[i] = Vector2f(
|
||||||
|
verticesBoneWeight[i][4].weight,
|
||||||
|
verticesBoneWeight[i][5].weight
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepared = true;
|
||||||
|
}
|
||||||
|
|
||||||
void BoneSystemNew::LoadFromFile(const std::string& fileName, const std::string& ZIPFileName)
|
void BoneSystemNew::LoadFromFile(const std::string& fileName, const std::string& ZIPFileName)
|
||||||
{
|
{
|
||||||
std::ifstream filestream;
|
std::ifstream filestream;
|
||||||
|
|||||||
@ -1,9 +1,48 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "BoneAnimatedModel.h"
|
#include "render/Renderer.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
namespace ZL
|
namespace ZL
|
||||||
{
|
{
|
||||||
|
constexpr int MAX_BONE_COUNT = 6;
|
||||||
|
constexpr int MAX_GPU_BONES = 64;
|
||||||
|
struct Bone
|
||||||
|
{
|
||||||
|
Eigen::Vector3f boneStartWorld;
|
||||||
|
float boneLength;
|
||||||
|
Eigen::Matrix4f boneMatrixWorld;
|
||||||
|
|
||||||
|
int parent;
|
||||||
|
std::vector<int> children;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoneWeight
|
||||||
|
{
|
||||||
|
int boneIndex = -1;
|
||||||
|
float weight = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnimationKeyFrame
|
||||||
|
{
|
||||||
|
int frame;
|
||||||
|
std::vector<Bone> bones;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Animation
|
||||||
|
{
|
||||||
|
std::vector<AnimationKeyFrame> keyFrames;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GpuBoneData {
|
||||||
|
std::vector<Vector4f> boneIndices0; // bone indices 0-3 per vertex (as float)
|
||||||
|
std::vector<Vector2f> boneIndices1; // bone indices 4-5 per vertex
|
||||||
|
std::vector<Vector4f> boneWeights0; // bone weights 0-3 per vertex
|
||||||
|
std::vector<Vector2f> boneWeights1; // bone weights 4-5 per vertex
|
||||||
|
bool prepared = false;
|
||||||
|
void PrepareGpuSkinningData(const std::vector<std::array<BoneWeight, MAX_BONE_COUNT>>& verticesBoneWeight);
|
||||||
|
};
|
||||||
|
|
||||||
struct MeshBoneData
|
struct MeshBoneData
|
||||||
{
|
{
|
||||||
VertexDataStruct mesh;
|
VertexDataStruct mesh;
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "AnimatedModel.h"
|
#include "AnimatedModel.h"
|
||||||
#include "BoneAnimatedModel.h"
|
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
#include "render/OpenGlExtensions.h"
|
#include "render/OpenGlExtensions.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Character.h"
|
#include "Character.h"
|
||||||
#include "BoneAnimatedModel.h"
|
|
||||||
#include "render/Renderer.h"
|
#include "render/Renderer.h"
|
||||||
#include "Environment.h"
|
#include "Environment.h"
|
||||||
#include "render/TextureManager.h"
|
#include "render/TextureManager.h"
|
||||||
|
|||||||
@ -10,219 +10,6 @@
|
|||||||
namespace ZL
|
namespace ZL
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
VertexDataStruct LoadFromTextFile(const std::string& fileName, const std::string& ZIPFileName)
|
|
||||||
{
|
|
||||||
VertexDataStruct result;
|
|
||||||
std::ifstream filestream;
|
|
||||||
std::istringstream zipStream;
|
|
||||||
|
|
||||||
if (!ZIPFileName.empty())
|
|
||||||
{
|
|
||||||
std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
|
|
||||||
std::string fileContents(fileData.begin(), fileData.end());
|
|
||||||
zipStream.str(fileContents);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filestream.open(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаем ссылку f на нужный поток – после этого код ниже остается без изменений
|
|
||||||
std::istream& f = (!ZIPFileName.empty()) ? static_cast<std::istream&>(zipStream) : static_cast<std::istream&>(filestream);
|
|
||||||
|
|
||||||
|
|
||||||
//Skip first 5 lines
|
|
||||||
std::string tempLine;
|
|
||||||
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
static const std::regex pattern_count(R"(\d+)");
|
|
||||||
static const std::regex pattern_float(R"([-]?\d+\.\d+)");
|
|
||||||
static const std::regex pattern_int(R"([-]?\d+)");
|
|
||||||
|
|
||||||
|
|
||||||
std::smatch match;
|
|
||||||
|
|
||||||
int numberVertices;
|
|
||||||
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
std::string number_str = match.str();
|
|
||||||
numberVertices = std::stoi(number_str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "No number found in the input string: " << tempLine << std::endl;
|
|
||||||
throw std::runtime_error("No number found in the input string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Vector3f> vertices;
|
|
||||||
|
|
||||||
vertices.resize(numberVertices);
|
|
||||||
for (int i = 0; i < numberVertices; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
std::vector<float> floatValues;
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
while (std::regex_search(b, e, match, pattern_float)) {
|
|
||||||
floatValues.push_back(std::stof(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertices[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "UV Coordinates" << std::endl;
|
|
||||||
|
|
||||||
std::getline(f, tempLine); //===UV Coordinates:
|
|
||||||
|
|
||||||
std::getline(f, tempLine); //triangle count
|
|
||||||
int numberTriangles;
|
|
||||||
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
std::string number_str = match.str();
|
|
||||||
numberTriangles = std::stoi(number_str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "-No number found in the input string: " << tempLine << std::endl;
|
|
||||||
throw std::runtime_error("-No number found in the input string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Now process UVs
|
|
||||||
std::vector<std::array<Vector2f, 3>> uvCoords;
|
|
||||||
|
|
||||||
uvCoords.resize(numberTriangles);
|
|
||||||
|
|
||||||
for (int i = 0; i < numberTriangles; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine); //Face 0
|
|
||||||
|
|
||||||
int uvCount;
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
std::string number_str = match.str();
|
|
||||||
uvCount = std::stoi(number_str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "2 No number found in the input string: " << tempLine << std::endl;
|
|
||||||
throw std::runtime_error("2 No number found in the input string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uvCount != 3)
|
|
||||||
{
|
|
||||||
std::cout << "UV count is not 3 for triangle " << i << ": " << uvCount << std::endl;
|
|
||||||
throw std::runtime_error("more than 3 uvs");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<float> floatValues;
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine); //UV <Vector (-0.3661, -1.1665)>
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
floatValues.clear();
|
|
||||||
while (std::regex_search(b, e, match, pattern_float)) {
|
|
||||||
floatValues.push_back(std::stof(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (floatValues.size() != 2)
|
|
||||||
{
|
|
||||||
std::cout << "UV count is not 2: " << j << " " << floatValues.size() << std::endl;
|
|
||||||
throw std::runtime_error("more than 2 uvs---");
|
|
||||||
}
|
|
||||||
|
|
||||||
uvCoords[i][j] = Vector2f{ floatValues[0],floatValues[1] };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//std::cout << "Normals go" << std::endl;
|
|
||||||
|
|
||||||
std::getline(f, tempLine); //===Normals:
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<Vector3f> normals;
|
|
||||||
|
|
||||||
normals.resize(numberVertices);
|
|
||||||
for (int i = 0; i < numberVertices; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
std::vector<float> floatValues;
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
while (std::regex_search(b, e, match, pattern_float)) {
|
|
||||||
floatValues.push_back(std::stof(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
normals[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
//std::cout << "Triangles go:" << std::endl;
|
|
||||||
|
|
||||||
std::getline(f, tempLine); //===Triangles: 3974
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::array<int, 3>> triangles;
|
|
||||||
|
|
||||||
triangles.resize(numberTriangles);
|
|
||||||
for (int i = 0; i < numberTriangles; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
std::vector<int> intValues;
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
while (std::regex_search(b, e, match, pattern_int)) {
|
|
||||||
intValues.push_back(std::stoi(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
triangles[i] = { intValues[0], intValues[1], intValues[2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::cout << "Process vertices" << std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Now let's process vertices
|
|
||||||
|
|
||||||
for (int i = 0; i < numberTriangles; i++)
|
|
||||||
{
|
|
||||||
|
|
||||||
result.PositionData.push_back(vertices[triangles[i][0]]);
|
|
||||||
result.PositionData.push_back(vertices[triangles[i][1]]);
|
|
||||||
result.PositionData.push_back(vertices[triangles[i][2]]);
|
|
||||||
|
|
||||||
result.TexCoordData.push_back(uvCoords[i][0]);
|
|
||||||
result.TexCoordData.push_back(uvCoords[i][1]);
|
|
||||||
result.TexCoordData.push_back(uvCoords[i][2]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Swap from Blender format to OpenGL format
|
|
||||||
for (int i = 0; i < result.PositionData.size(); i++)
|
|
||||||
{
|
|
||||||
Vector3f tempVec = result.PositionData[i];
|
|
||||||
result.PositionData[i](0) = tempVec(1);
|
|
||||||
result.PositionData[i](1) = tempVec(2);
|
|
||||||
result.PositionData[i](2) = tempVec(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName)
|
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName)
|
||||||
{
|
{
|
||||||
VertexDataStruct result;
|
VertexDataStruct result;
|
||||||
|
|||||||
@ -6,6 +6,5 @@
|
|||||||
|
|
||||||
namespace ZL
|
namespace ZL
|
||||||
{
|
{
|
||||||
VertexDataStruct LoadFromTextFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
|
||||||
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName = "");
|
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName = "");
|
||||||
}
|
}
|
||||||
@ -1,73 +0,0 @@
|
|||||||
#include "Perlin.h"
|
|
||||||
#include <cmath>
|
|
||||||
#include <numeric>
|
|
||||||
#include <random>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
|
|
||||||
PerlinNoise::PerlinNoise() {
|
|
||||||
p.resize(256);
|
|
||||||
std::iota(p.begin(), p.end(), 0);
|
|
||||||
// Перемешиваем для случайности (можно задать seed)
|
|
||||||
std::default_random_engine engine(77777);
|
|
||||||
std::shuffle(p.begin(), p.end(), engine);
|
|
||||||
p.insert(p.end(), p.begin(), p.end()); // Дублируем для переполнения
|
|
||||||
}
|
|
||||||
|
|
||||||
PerlinNoise::PerlinNoise(uint64_t seed) {
|
|
||||||
p.resize(256);
|
|
||||||
std::iota(p.begin(), p.end(), 0);
|
|
||||||
// Перемешиваем для случайности (используем переданный seed)
|
|
||||||
std::default_random_engine engine(static_cast<unsigned int>(seed));
|
|
||||||
std::shuffle(p.begin(), p.end(), engine);
|
|
||||||
p.insert(p.end(), p.begin(), p.end()); // Дублируем для переполнения
|
|
||||||
}
|
|
||||||
|
|
||||||
float PerlinNoise::fade(float t) { return t * t * t * (t * (t * 6 - 15) + 10); }
|
|
||||||
|
|
||||||
float PerlinNoise::lerp(float t, float a, float b) { return a + t * (b - a); }
|
|
||||||
|
|
||||||
float PerlinNoise::grad(int hash, float x, float y, float z) {
|
|
||||||
int h = hash & 15;
|
|
||||||
float u = h < 8 ? x : y;
|
|
||||||
float v = h < 4 ? y : (h == 12 || h == 14 ? x : z);
|
|
||||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
|
||||||
}
|
|
||||||
|
|
||||||
float PerlinNoise::noise(float x, float y, float z) {
|
|
||||||
int X = (int)floor(x) & 255;
|
|
||||||
int Y = (int)floor(y) & 255;
|
|
||||||
int Z = (int)floor(z) & 255;
|
|
||||||
|
|
||||||
x -= floor(x);
|
|
||||||
y -= floor(y);
|
|
||||||
z -= floor(z);
|
|
||||||
|
|
||||||
float u = fade(x);
|
|
||||||
float v = fade(y);
|
|
||||||
float w = fade(z);
|
|
||||||
|
|
||||||
int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z;
|
|
||||||
int B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;
|
|
||||||
|
|
||||||
return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z)),
|
|
||||||
lerp(u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z))),
|
|
||||||
lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1)),
|
|
||||||
lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1))));
|
|
||||||
}
|
|
||||||
|
|
||||||
float PerlinNoise::getSurfaceHeight(Eigen::Vector3f pos, float noiseCoeff) {
|
|
||||||
// Частота шума (чем больше, тем больше "холмов")
|
|
||||||
float frequency = 7.0f;
|
|
||||||
|
|
||||||
// Получаем значение шума (обычно от -1 до 1)
|
|
||||||
float noiseValue = noise(pos(0) * frequency, pos(1) * frequency, pos(2) * frequency);
|
|
||||||
|
|
||||||
// Масштабируем: хотим отклонение от 1.0 до 1.1 (примерно)
|
|
||||||
float height = 1.0f + (noiseValue * noiseCoeff);
|
|
||||||
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ZL
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <Eigen/Dense>
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
|
|
||||||
class PerlinNoise {
|
|
||||||
std::vector<int> p;
|
|
||||||
public:
|
|
||||||
PerlinNoise();
|
|
||||||
PerlinNoise(uint64_t seed);
|
|
||||||
|
|
||||||
float fade(float t);
|
|
||||||
float lerp(float t, float a, float b);
|
|
||||||
float grad(int hash, float x, float y, float z);
|
|
||||||
|
|
||||||
float noise(float x, float y, float z);
|
|
||||||
|
|
||||||
float getSurfaceHeight(Eigen::Vector3f pos, float noiseCoeff);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ZL
|
|
||||||
Loading…
Reference in New Issue
Block a user