Clean up
This commit is contained in:
parent
519d780b3c
commit
e04fcbb9bd
@ -32,8 +32,6 @@ add_executable(witcher001
|
||||
../src/TextModel.h
|
||||
../src/AudioPlayerAsync.cpp
|
||||
../src/AudioPlayerAsync.h
|
||||
../src/BoneAnimatedModel.cpp
|
||||
../src/BoneAnimatedModel.h
|
||||
../src/BoneAnimatedModelNew.cpp
|
||||
../src/BoneAnimatedModelNew.h
|
||||
../src/render/OpenGlExtensions.cpp
|
||||
@ -42,8 +40,6 @@ add_executable(witcher001
|
||||
../src/utils/Utils.h
|
||||
../src/SparkEmitter.cpp
|
||||
../src/SparkEmitter.h
|
||||
../src/utils/Perlin.cpp
|
||||
../src/utils/Perlin.h
|
||||
../src/utils/TaskManager.cpp
|
||||
../src/utils/TaskManager.h
|
||||
../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;
|
||||
#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)
|
||||
{
|
||||
@ -23,6 +37,42 @@ namespace ZL
|
||||
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)
|
||||
{
|
||||
std::ifstream filestream;
|
||||
|
||||
@ -1,9 +1,48 @@
|
||||
#pragma once
|
||||
#include "BoneAnimatedModel.h"
|
||||
#include "render/Renderer.h"
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
VertexDataStruct mesh;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include "Game.h"
|
||||
#include "AnimatedModel.h"
|
||||
#include "BoneAnimatedModel.h"
|
||||
#include "utils/Utils.h"
|
||||
#include "render/OpenGlExtensions.h"
|
||||
#include <iostream>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "Character.h"
|
||||
#include "BoneAnimatedModel.h"
|
||||
#include "render/Renderer.h"
|
||||
#include "Environment.h"
|
||||
#include "render/TextureManager.h"
|
||||
|
||||
@ -10,219 +10,6 @@
|
||||
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 result;
|
||||
|
||||
@ -6,6 +6,5 @@
|
||||
|
||||
namespace ZL
|
||||
{
|
||||
VertexDataStruct LoadFromTextFile(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