diff --git a/PlanetData.cpp b/PlanetData.cpp index dc3eb5f..23669af 100644 --- a/PlanetData.cpp +++ b/PlanetData.cpp @@ -326,17 +326,18 @@ namespace ZL { // UV- // . - const std::array triangleUVs = { + /*const std::array triangleUVs = { Vector2f(0.5f, 1.0f), Vector2f(0.0f, 1.0f - sqrt(3)*0.5), Vector2f(1.0f, 1.0f - sqrt(3) * 0.5), - }; - /*const std::array triangleUVs2 = { + };*/ + const std::array triangleUVs = { + Vector2f(0.5f, 1.0f), Vector2f(0.0f, 0.0f), Vector2f(1.0f, 0.0f), - Vector2f(0.0f, 1.0f) - };*/ + + }; result.VertexIDs.reserve(geometry.size() * 3); // ID for (const auto& t : geometry) { diff --git a/PlanetData.h b/PlanetData.h index 553bd3c..75f996d 100644 --- a/PlanetData.h +++ b/PlanetData.h @@ -16,8 +16,8 @@ namespace ZL { VertexID generateEdgeID(const VertexID& id1, const VertexID& id2); - //constexpr static int MAX_LOD_LEVELS = 6; - constexpr static int MAX_LOD_LEVELS = 1; + constexpr static int MAX_LOD_LEVELS = 6; + //constexpr static int MAX_LOD_LEVELS = 2; struct Triangle { diff --git a/PlanetObject.cpp b/PlanetObject.cpp index 4b08a0b..75be9cc 100644 --- a/PlanetObject.cpp +++ b/PlanetObject.cpp @@ -8,6 +8,57 @@ namespace ZL { + Matrix3f GetRotationForTriangle(const Triangle& tri) { + // Для треугольника №0: + // tri.data[0] = {0, 20000, 0} (A) + // tri.data[1] = {0, 0, 20000} (B) + // tri.data[2] = {20000, 0, 0} (C) + + Vector3f vA = tri.data[0]; + Vector3f vB = tri.data[1]; + Vector3f vC = tri.data[2]; + + // 1. Вычисляем ось X (горизонталь). + // Нам нужна грань BC: от (0, 0, 20000) до (20000, 0, 0) + Vector3f x_axis = (vC - vB).normalized(); + + // 2. Вычисляем нормаль (ось Z). + // Порядок cross product (AB x AC) определит "лицевую" сторону. + Vector3f edge1 = vB - vA; + Vector3f edge2 = vC - vA; + Vector3f z_axis = edge1.cross(edge2).normalized(); + + // 3. Вычисляем ось Y (вертикаль). + // В ортонормированном базисе Y всегда перпендикулярна Z и X. + Vector3f y_axis = z_axis.cross(x_axis).normalized(); + + // 4. Формируем прямую матрицу поворота (Rotation/World Matrix). + // Векторы базиса записываются в СТОЛБЦЫ. + // В памяти Matrix3f m (std::array): + // m[0]=X.x, m[1]=Y.x, m[2]=Z.x + // m[3]=X.y, m[4]=Y.y, m[5]=Z.y + // m[6]=X.z, m[7]=Y.z, m[8]=Z.z + + Matrix3f rot; + + // Столбец 0: Ось X + rot.m[0] = x_axis.v[0]; + rot.m[3] = x_axis.v[1]; + rot.m[6] = x_axis.v[2]; + + // Столбец 1: Ось Y + rot.m[1] = y_axis.v[0]; + rot.m[4] = y_axis.v[1]; + rot.m[7] = y_axis.v[2]; + + // Столбец 2: Ось Z + rot.m[2] = z_axis.v[0]; + rot.m[5] = z_axis.v[1]; + rot.m[8] = z_axis.v[2]; + + return rot; + } + PlanetObject::PlanetObject() { @@ -24,7 +75,29 @@ namespace ZL { planetRenderStruct.RefreshVBO(); planetRenderStructCut.data = planetData.getLodLevel(lodIndex).vertexData; + /*planetRenderStructCut.data.PositionData[0] = planetRenderStructCut.data.PositionData[3 * 1 + 0]; + planetRenderStructCut.data.PositionData[1] = planetRenderStructCut.data.PositionData[3 * 1 + 1]; + planetRenderStructCut.data.PositionData[2] = planetRenderStructCut.data.PositionData[3 * 1 + 2]; + */ planetRenderStructCut.data.PositionData.resize(3); + + /* + Vector4f q1 = QuatFromRotateAroundX(-M_PI * 45.0 / 180.0); + Vector4f q2 = QuatFromRotateAroundY(M_PI * 45.0 / 180.0); + //Vector4f q3 = {-cos(0.5*M_PI * x / 180.0), -cos(0.5 * M_PI * x / 180.0), -cos(0.5 * M_PI * x / 180.0),sin(0.5 * M_PI * x / 180.0) }; + + Matrix3f r1 = QuatToMatrix(q1); + + Matrix3f r2 = QuatToMatrix(q2); + + //Matrix3f r3 = QuatToMatrix(q3); + + Matrix3f m = MultMatrixMatrix(r2, r1); + + Matrix3f invr = InverseMatrix(m); + + planetRenderStructCut.data.RotateByMatrix(invr);*/ + planetRenderStructCut.RefreshVBO(); //sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/sand2.png", "")); sandTexture = std::make_unique(CreateTextureDataFromPng("./resources/sandx.png", "")); @@ -49,6 +122,7 @@ namespace ZL { drawDataDirty = false; } + void PlanetObject::update(float deltaTimeMs) { // 1. Получаем базовые треугольники под камерой auto lr = planetData.getTrianglesUnderCamera(Environment::shipPosition); @@ -104,196 +178,93 @@ namespace ZL { } - void PlanetObject::bakeStoneTexture(Renderer& renderer) { - // 1. Создаем FB (размер 512x512 для четкости) - - glViewport(0, 0, 1024, 1024); + + void PlanetObject::bakeStoneTexture(Renderer& renderer) { + glViewport(0, 0, 512, 512); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - /* - static const std::string stoneShader = "defaultColor2"; - renderer.shaderManager.PushShader(stoneShader); - - static const std::string vPositionName = "vPosition"; - static const std::string vColorName = "vColor"; - static const std::string vNormalName = "vNormal"; - static const std::string vTexCoordName = "vTexCoord"; - //static const std::string vTexCoord3Name = "vTexCoord3"; - static const std::string textureUniformName = "Texture"; - - renderer.EnableVertexAttribArray(vPositionName); - renderer.EnableVertexAttribArray(vColorName); - renderer.EnableVertexAttribArray(vNormalName); - renderer.EnableVertexAttribArray(vTexCoordName); - - // 2. Очищаем (черный фон - это "нет камня") - glClearColor(0.0f, 0.5f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // 3. Настраиваем камеру (Ортографическая проекция над треугольником) - // Смотрим на плоскость, где лежит эталонный треугольник - renderer.PushProjectionMatrix(0.666667f, 1.777779f, 2000, 200000); - renderer.PushMatrix(); - renderer.LoadIdentity(); - renderer.TranslateMatrix({ 0, 0, -45000.0f }); // Отодвигаемся, чтобы видеть камни - - // 4. Рендерим камни - // Берем семена и параметры из первого треугольника (индекс 0) - // Используем упрощенный вызов отрисовки геометрии камней - - // Рисуем меш камней для ОДНОГО эталонного треугольника - // Здесь используем уже созданную нами функцию inflate для индекса 0 - planetStones.inflate({ 0 }); - VertexRenderStruct tempStoneRender; - tempStoneRender.AssignFrom(planetStones.mesh); - - renderer.DrawVertexRenderStruct(tempStoneRender); - - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - - //stoneMapFB->Unbind(); - - renderer.DisableVertexAttribArray(vPositionName); - renderer.DisableVertexAttribArray(vColorName); - renderer.DisableVertexAttribArray(vNormalName); - renderer.DisableVertexAttribArray(vTexCoordName); - renderer.shaderManager.PopShader(); - - - - // Восстанавливаем вьюпорт под экран - glViewport(0, 0, Environment::width, Environment::height);*/ - - //static const std::string defaultShaderName = "defaultColor"; static const std::string defaultShaderName2 = "defaultColor2"; static const std::string vPositionName = "vPosition"; - static const std::string vColorName = "vColor"; - static const std::string vNormalName = "vNormal"; static const std::string vTexCoordName = "vTexCoord"; - //static const std::string vTexCoord3Name = "vTexCoord3"; static const std::string textureUniformName = "Texture"; - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - renderer.shaderManager.PushShader(defaultShaderName2); renderer.RenderUniform1i(textureUniformName, 0); renderer.EnableVertexAttribArray(vPositionName); - renderer.EnableVertexAttribArray(vColorName); - renderer.EnableVertexAttribArray(vNormalName); renderer.EnableVertexAttribArray(vTexCoordName); - //renderer.EnableVertexAttribArray(vTexCoord3Name); float dist = planetData.distanceToPlanetSurface(Environment::shipPosition); auto zRange = planetData.calculateZRange(dist); const float currentZNear = zRange.first; const float currentZFar = zRange.second; - // 2. Применяем динамическую матрицу проекции - /*renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, - 1.0, - currentZNear, currentZFar);*/ + + + Triangle tr = planetData.getLodLevel(planetData.getCurrentLodIndex()).triangles[0]; + + // 1. Получаем матрицу вращения (оси в столбцах) + Matrix3f mr = GetRotationForTriangle(tr); + + // 2. Трансформируем вершины в локальное пространство экрана, чтобы найти габариты + // Используем MultMatrixVector(Matrix, Vector). + // Если ваша функция считает V * M, то передайте Inverse(mr). + Vector3f rA = MultMatrixVector(mr, tr.data[0]); + Vector3f rB = MultMatrixVector(mr, tr.data[1]); + Vector3f rC = MultMatrixVector(mr, tr.data[2]); + + // 3. Вычисляем реальные границы треугольника после поворота + float minX = min(rA.v[0], min(rB.v[0], rC.v[0])); + float maxX = max(rA.v[0], max(rB.v[0], rC.v[0])); + float minY = min(rA.v[1], min(rB.v[1], rC.v[1])); + float maxY = max(rA.v[1], max(rB.v[1], rC.v[1])); + + // Находим центр и размеры + float width = maxX - minX; + float height = maxY - minY; + float centerX = (minX + maxX) * 0.5f; + float centerY = (minY + maxY) * 0.5f; + + //float size = max(width, height); + //float hSize = size * 0.5f; + renderer.PushProjectionMatrix( - -PlanetData::PLANET_RADIUS*sqrt(2)*(1-0/100.f)*0.5, - PlanetData::PLANET_RADIUS * sqrt(2) * (1 - 0 / 100.f) * 0.5, - -PlanetData::PLANET_RADIUS * sqrt(2) * (1 - 0 / 100.f) * 0.5, - PlanetData::PLANET_RADIUS * sqrt(2) * (1 - 0 / 100.f) * 0.5, + centerX - width*0.5, centerX + width * 0.5, + centerY - height * 0.5, centerY + height * 0.5, currentZNear, currentZFar); renderer.PushMatrix(); renderer.LoadIdentity(); - //renderer.RotateMatrix(Environment::inverseShipMatrix); - renderer.TranslateMatrix(Vector3f{ 0,0,-45000 }); + // Сдвигаем камеру по Z + renderer.TranslateMatrix(Vector3f{ 0, 0, -45000 }); - Vector4f q1 = QuatFromRotateAroundX(-M_PI * 45.0 / 180.0); - Vector4f q2 = QuatFromRotateAroundY(M_PI * 45.0 / 180.0); - //Vector4f q3 = {-cos(0.5*M_PI * x / 180.0), -cos(0.5 * M_PI * x / 180.0), -cos(0.5 * M_PI * x / 180.0),sin(0.5 * M_PI * x / 180.0) }; - - Matrix3f r1 = QuatToMatrix(q1); - - Matrix3f r2 = QuatToMatrix(q2); - - //Matrix3f r3 = QuatToMatrix(q3); - - Matrix3f invr = InverseMatrix( MultMatrixMatrix(r2, r1)); - - renderer.RotateMatrix(invr); - - - - const Matrix4f viewMatrix = renderer.GetCurrentModelViewMatrix(); - - - Vector3f lightDir_World = Vector3f(1.0f, 0.0f, -1.0f).normalized(); - // В OpenGL/шейдерах удобнее работать с вектором, указывающим ОТ источника к поверхности. - Vector3f lightDirection_World = -lightDir_World; // Вектор, направленный от источника - Vector3f lightDirection_View; - - lightDirection_View.v[0] = viewMatrix.m[0] * lightDirection_World.v[0] + viewMatrix.m[4] * lightDirection_World.v[1] + viewMatrix.m[8] * lightDirection_World.v[2]; - lightDirection_View.v[1] = viewMatrix.m[1] * lightDirection_World.v[0] + viewMatrix.m[5] * lightDirection_World.v[1] + viewMatrix.m[9] * lightDirection_World.v[2]; - lightDirection_View.v[2] = viewMatrix.m[2] * lightDirection_World.v[0] + viewMatrix.m[6] * lightDirection_World.v[1] + viewMatrix.m[10] * lightDirection_World.v[2]; - lightDirection_View = lightDirection_View.normalized(); // Нормализуем на всякий случай - - // Установка uniform-переменной - // Предполагается, что RenderUniform3fv определена в Renderer.h - /* - renderer.RenderUniform3fv("uLightDirection", &lightDirection_View.v[0]); - renderer.RenderUniformMatrix4fv("ModelViewMatrix", false, &viewMatrix.m[0]); - - renderer.RenderUniform1f("uDistanceToPlanetSurface", dist); - renderer.RenderUniform1f("uCurrentZFar", currentZFar); - Vector3f color2 = { 1.0, 1.0, 1.0 }; - - renderer.RenderUniform3fv("uColor", &color2.v[0]);*/ - - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE);// Аддитивное смешивание для эффекта свечения + // Применяем вращение + renderer.RotateMatrix(mr); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID()); - - //planetRenderStructCut.AssignFrom(planetRenderStruct.data); - //planetRenderStructCut.data.PositionData.resize(3); - //planetRenderStructCut.RefreshVBO(); renderer.DrawVertexRenderStruct(planetRenderStructCut); - - - //planetStones.inflate({0/*,1,2,3,4,5,6,7*/}); - //planetStonesRenderStruct.AssignFrom(planetStones.mesh); - //planetStonesRenderStruct.RefreshVBO(); - glClear(GL_DEPTH_BUFFER_BIT); - + if (planetStonesRenderStruct.data.PositionData.size() > 0) { - //glBindTexture(GL_TEXTURE_2D, fb->getTextureID()); glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID()); renderer.DrawVertexRenderStruct(planetStonesRenderStruct); - //glDisable(GL_BLEND); CheckGlError(); } - + renderer.PopMatrix(); renderer.PopProjectionMatrix(); - //renderer.DisableVertexAttribArray(vTexCoord3Name); renderer.DisableVertexAttribArray(vTexCoordName); - renderer.DisableVertexAttribArray(vNormalName); - renderer.DisableVertexAttribArray(vColorName); renderer.DisableVertexAttribArray(vPositionName); renderer.shaderManager.PopShader(); CheckGlError(); - - - //glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - } @@ -305,7 +276,7 @@ namespace ZL { { if (stoneMapFB == nullptr) { - stoneMapFB = std::make_unique(1024, 1024); + stoneMapFB = std::make_unique(512, 512); } stoneMapFB->Bind(); @@ -315,7 +286,7 @@ namespace ZL { } - //bakeStoneTexture(renderer); + bakeStoneTexture(renderer); glViewport(0, 0, Environment::width, Environment::height); //-------------------------- diff --git a/StoneObject.cpp b/StoneObject.cpp index d6db66b..024d4a4 100644 --- a/StoneObject.cpp +++ b/StoneObject.cpp @@ -46,8 +46,8 @@ namespace ZL { VertexDataStruct CreateBaseConvexPolyhedron(uint64_t seed) { // --- ( ) --- - //const float BASE_SCALE = 3.0f; // - const float BASE_SCALE = 800.0f; // + const float BASE_SCALE = 3.0f; // + //const float BASE_SCALE = 100.0f; // const float MIN_AXIS_SCALE = 0.5f; // / const float MAX_AXIS_SCALE = 1.5f; // / const float MIN_PERTURBATION = 0.05f; // diff --git a/ZLMath.h b/ZLMath.h index 49d022c..07caa84 100755 --- a/ZLMath.h +++ b/ZLMath.h @@ -79,11 +79,6 @@ namespace ZL { ); } - // - /*Vector3f operator-(const Vector3f& other) const { - return Vector3f(v[0] - other.v[0], v[1] - other.v[1], v[2] - other.v[2]); - }*/ - bool operator<(const Vector3f& other) const { if (v[0] != other.v[0]) return v[0] < other.v[0]; if (v[1] != other.v[1]) return v[1] < other.v[1]; diff --git a/shaders/defaultColor_fog_stones_desktop.fragment b/shaders/defaultColor_fog_stones_desktop.fragment index 983e62d..12b33e4 100644 --- a/shaders/defaultColor_fog_stones_desktop.fragment +++ b/shaders/defaultColor_fog_stones_desktop.fragment @@ -8,11 +8,11 @@ void main() { vec2 newTexCoord; newTexCoord.x = TexCoord.x; - //newTexCoord.y = 1.0 - TexCoord.y - 0.0122; + //newTexCoord.y = TexCoord.y - 0.0122; //newTexCoord.y = TexCoord.y * (1.0+testShift) + 0.0122; //newTexCoord.y = (TexCoord.y + 0.0122)*(1.0 +x/500.0); - newTexCoord.y = TexCoord.y * (1.0-6.0/500.0) + 0.0122+ (11.0/500.0) *0.1 -6/5000.0; - //newTexCoord.y = TexCoord.y; + //newTexCoord.y = TexCoord.y * (1.0-6.0/500.0) + 0.0122+ (11.0/500.0) *0.1 -6/5000.0; + newTexCoord.y = TexCoord.y; vec4 sandColor = texture2D(Texture, TexCoord); vec4 stoneData = texture2D(StoneMap, newTexCoord);