Make IcoSphere
This commit is contained in:
parent
570c96a628
commit
c553780b6e
@ -137,82 +137,7 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float PlanetData::distanceToPlanetSurface(const Vector3f& viewerPosition) {
|
std::vector<int> PlanetData::getBestTriangleUnderCamera(const Vector3f& viewerPosition) {
|
||||||
Vector3f shipLocalPosition = viewerPosition - PLANET_CENTER_OFFSET;
|
|
||||||
|
|
||||||
// Èñïîëüçóåì getTrianglesUnderCamera äëÿ ïîèñêà
|
|
||||||
// ÂÍÈÌÀÍÈÅ: Çäåñü ðåêóðñèÿ ëîãèêè. Ìåòîä getTrianglesUnderCamera èñïîëüçóåò âíóòðè viewerPosition.
|
|
||||||
// ×òîáû íå äóáëèðîâàòü êîä, ïåðåïèøåì ëîãèêó ïîèñêà çäåñü èëè áóäåì èñïîëüçîâàòü óæå íàéäåííûé ðàíåå.
|
|
||||||
// Äëÿ ïðîñòîòû îñòàâèì ëîãèêó êàê â îðèãèíàëå, íî àäàïòèðîâàííóþ.
|
|
||||||
|
|
||||||
// ÂÀÆÍÎ: getTrianglesUnderCamera - ýòî "òÿæåëàÿ" ôóíêöèÿ. Â îðèãèíàëå îíà âûçûâàëàñü âíóòðè distanceToPlanetSurface.
|
|
||||||
// Íî îíà òðåáóåò LOD. Èñïîëüçóåì MAX LOD äëÿ òî÷íîñòè.
|
|
||||||
|
|
||||||
// Ðåêóðñèâíûé ïîèñê òðåóãîëüíèêîâ ïîä êàìåðîé.
|
|
||||||
// Çäåñü íàì íóæíî ðåàëèçîâàòü àíàëîã triangleUnderCamera, íî íå çàâèñÿùèé îò ãëîáàëüíîãî ñîñòîÿíèÿ.
|
|
||||||
// Â îðèãèíàëå ôóíêöèÿ triangleUnderCamera áûëà ðåêóðñèâíîé.
|
|
||||||
// Íèæå ÿ ðåàëèçóþ èòåðàòèâíûé èëè ðåêóðñèâíûé ïîäõîä âíóòðè getTrianglesUnderCamera.
|
|
||||||
|
|
||||||
// Âðåìåííîå ðåøåíèå: ïîëíàÿ êîïèÿ ëîãèêè ïîèñêà òðåóãîëüíèêà
|
|
||||||
// Íî íàì íóæåí äîñòóï ê ìåòîäó.
|
|
||||||
std::vector<int> targetTriangles = getTrianglesUnderCameraNew(viewerPosition);
|
|
||||||
|
|
||||||
if (targetTriangles.empty()) {
|
|
||||||
return (shipLocalPosition.length() - PLANET_RADIUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
float lowestDistance;
|
|
||||||
|
|
||||||
int tri_index = targetTriangles[0];
|
|
||||||
const auto& posData = planetMeshLods[currentLod].vertexData.PositionData;
|
|
||||||
|
|
||||||
size_t data_index = tri_index * 3;
|
|
||||||
if (data_index + 2 >= posData.size()) {
|
|
||||||
return (shipLocalPosition.length() - PLANET_RADIUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3f& A = posData[data_index];
|
|
||||||
const Vector3f& B = posData[data_index + 1];
|
|
||||||
const Vector3f& C = posData[data_index + 2];
|
|
||||||
|
|
||||||
Vector3f P_proj = projectPointOnPlane(shipLocalPosition, A, B, C);
|
|
||||||
Vector3f P_closest = P_proj;
|
|
||||||
|
|
||||||
lowestDistance = (shipLocalPosition - P_closest).length();
|
|
||||||
|
|
||||||
if (targetTriangles.size() <= 1)
|
|
||||||
{
|
|
||||||
return lowestDistance;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < targetTriangles.size(); i++)
|
|
||||||
{
|
|
||||||
int tri_index = targetTriangles[i];
|
|
||||||
const auto& posData = planetMeshLods[currentLod].vertexData.PositionData;
|
|
||||||
|
|
||||||
size_t data_index = tri_index * 3;
|
|
||||||
if (data_index + 2 >= posData.size()) {
|
|
||||||
return (shipLocalPosition.length() - PLANET_RADIUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3f& A = posData[data_index];
|
|
||||||
const Vector3f& B = posData[data_index + 1];
|
|
||||||
const Vector3f& C = posData[data_index + 2];
|
|
||||||
|
|
||||||
Vector3f P_proj = projectPointOnPlane(shipLocalPosition, A, B, C);
|
|
||||||
Vector3f P_closest = P_proj;
|
|
||||||
|
|
||||||
if (lowestDistance < (shipLocalPosition - P_closest).length())
|
|
||||||
{
|
|
||||||
lowestDistance = (shipLocalPosition - P_closest).length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lowestDistance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::vector<int> PlanetData::getTrianglesUnderCameraNew(const Vector3f& viewerPosition) {
|
|
||||||
const LodLevel& finalLod = planetMeshLods[currentLod]; // Ðàáîòàåì ñ òåêóùèì àêòèâíûì LOD
|
const LodLevel& finalLod = planetMeshLods[currentLod]; // Ðàáîòàåì ñ òåêóùèì àêòèâíûì LOD
|
||||||
Vector3f targetDir = (viewerPosition - PLANET_CENTER_OFFSET).normalized();
|
Vector3f targetDir = (viewerPosition - PLANET_CENTER_OFFSET).normalized();
|
||||||
|
|
||||||
@ -238,24 +163,42 @@ namespace ZL {
|
|||||||
|
|
||||||
if (bestTriangle == -1) return {};
|
if (bestTriangle == -1) return {};
|
||||||
|
|
||||||
// Øàã 2: Ñîáèðàåì "ïÿòíî" âîêðóã íàéäåííîãî òðåóãîëüíèêà
|
return { bestTriangle };
|
||||||
// Èñïîëüçóåì óæå èìåþùèéñÿ ó òåáÿ ìåòîä findNeighbors
|
}
|
||||||
std::set<int> resultSet;
|
|
||||||
resultSet.insert(bestTriangle);
|
|
||||||
|
|
||||||
// Äîáàâëÿåì ïåðâûé êðóã ñîñåäåé
|
std::vector<int> PlanetData::getTrianglesUnderCameraNew2(const Vector3f& viewerPosition) {
|
||||||
std::vector<int> neighbors = findNeighbors(bestTriangle, currentLod);
|
const LodLevel& finalLod = planetMeshLods[currentLod];
|
||||||
for (int n : neighbors) {
|
Vector3f shipLocal = viewerPosition - PLANET_CENTER_OFFSET;
|
||||||
resultSet.insert(n);
|
float currentDist = shipLocal.length();
|
||||||
|
Vector3f targetDir = shipLocal.normalized();
|
||||||
|
|
||||||
// Îïöèîíàëüíî: Äîáàâëÿåì âòîðîé êðóã ñîñåäåé äëÿ çàïàñà (ïðèõâàòûâàåì áîëüøå)
|
// Æåëàåìûé ðàäèóñ ïîêðûòèÿ íà ïîâåðõíîñòè ïëàíåòû (â ìåòðàõ/åäèíèöàõ äâèæêà)
|
||||||
std::vector<int> secondCircle = findNeighbors(n, currentLod);
|
// Ïîäáåðè ýòî çíà÷åíèå òàê, ÷òîáû êàìíè âîêðóã êîðàáëÿ âñåãäà áûëè âèäíû.
|
||||||
for (int nn : secondCircle) {
|
const float desiredCoverageRadius = 3000.0f;
|
||||||
resultSet.insert(nn);
|
|
||||||
|
// Âû÷èñëÿåì ïîðîã êîñèíóñà íà îñíîâå æåëàåìîãî ðàäèóñà è òåêóùåãî ðàññòîÿíèÿ.
|
||||||
|
// ×åì ìû äàëüøå (currentDist áîëüøå), òåì ìåíüøå äîëæåí áûòü óãîë îòêëîíåíèÿ
|
||||||
|
// îò íîðìàëè, ÷òîáû çàõâàòèòü òó æå ïëîùàäü.
|
||||||
|
float angle = atan2(desiredCoverageRadius, currentDist);
|
||||||
|
float searchThreshold = cos(angle);
|
||||||
|
|
||||||
|
// Îãðàíè÷èòåëü, ÷òîáû íå çàõâàòèòü âñþ ïëàíåòó èëè âîîáùå íè÷åãî
|
||||||
|
searchThreshold = std::clamp(searchThreshold, 0.90f, 0.9999f);
|
||||||
|
|
||||||
|
std::vector<int> result;
|
||||||
|
for (int i = 0; i < (int)finalLod.triangles.size(); ++i) {
|
||||||
|
// Èñïîëüçóåì öåíòðîèä (ìîæíî êýøèðîâàòü â LodLevel äëÿ ñêîðîñòè)
|
||||||
|
Vector3f triDir = (finalLod.triangles[i].data[0] +
|
||||||
|
finalLod.triangles[i].data[1] +
|
||||||
|
finalLod.triangles[i].data[2]).normalized();
|
||||||
|
|
||||||
|
if (targetDir.dot(triDir) > searchThreshold) {
|
||||||
|
result.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::vector<int>(resultSet.begin(), resultSet.end());
|
if (result.empty()) return getBestTriangleUnderCamera(viewerPosition);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Triangle> PlanetData::subdivideTriangles(const std::vector<Triangle>& input, float noiseCoeff) {
|
std::vector<Triangle> PlanetData::subdivideTriangles(const std::vector<Triangle>& input, float noiseCoeff) {
|
||||||
@ -394,141 +337,94 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LodLevel PlanetData::generateSphere(int subdivisions, float noiseCoeff) {
|
LodLevel PlanetData::generateSphere(int subdivisions, float noiseCoeff) {
|
||||||
// 1. Èñõîäíûé îêòàýäð è ïðèñâîåíèå ID
|
const float t = (1.0f + std::sqrt(5.0f)) / 2.0f;
|
||||||
std::vector<Triangle> geometry = {
|
|
||||||
// Âåðõíÿÿ ïîëóñôåðà (Y > 0)
|
// 12 áàçîâûõ âåðøèí èêîñàýäðà
|
||||||
{{ 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}}, // 0
|
std::vector<Vector3f> icosaVertices = {
|
||||||
{{ 0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}, { 1.0f, 0.0f, 0.0f}}, // 1
|
{-1, t, 0}, { 1, t, 0}, {-1, -t, 0}, { 1, -t, 0},
|
||||||
{{ 0.0f, 1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}}, // 2
|
{ 0, -1, t}, { 0, 1, t}, { 0, -1, -t}, { 0, 1, -t},
|
||||||
{{ 0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}}, // 3
|
{ t, 0, -1}, { t, 0, 1}, {-t, 0, -1}, {-t, 0, 1}
|
||||||
// Íèæíÿÿ ïîëóñôåðà (Y < 0)
|
|
||||||
{{ 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 1.0f, 0.0f, 0.0f}}, // 4
|
|
||||||
{{ 0.0f, -1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}}, // 5
|
|
||||||
{{ 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}}, // 6
|
|
||||||
{{ 0.0f, -1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}} // 7
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ïðèñâîåíèå ID èñõîäíûì âåðøèíàì
|
// Íîðìàëèçóåì âåðøèíû
|
||||||
for (auto& t : geometry) {
|
for (auto& v : icosaVertices) v = v.normalized();
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
// Èñïîëüçóåì map äëÿ ïîëó÷åíèÿ ID ïî ÷èñòûì êîîðäèíàòàì (íîðì. == ÷èñòûå)
|
// 20 ãðàíåé èêîñàýäðà
|
||||||
t.ids[i] = initialVertexMap[t.data[i].normalized()];
|
struct IndexedTri { int v1, v2, v3; };
|
||||||
|
std::vector<IndexedTri> faces = {
|
||||||
|
{0, 11, 5}, {0, 5, 1}, {0, 1, 7}, {0, 7, 10}, {0, 10, 11},
|
||||||
|
{1, 5, 9}, {5, 11, 4}, {11, 10, 2}, {10, 7, 6}, {7, 1, 8},
|
||||||
|
{3, 9, 4}, {3, 4, 2}, {3, 2, 6}, {3, 6, 8}, {3, 8, 9},
|
||||||
|
{4, 9, 5}, {2, 4, 11}, {6, 2, 10}, {8, 6, 7}, {9, 8, 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Triangle> geometry;
|
||||||
|
for (auto& f : faces) {
|
||||||
|
Triangle tri;
|
||||||
|
tri.data[0] = icosaVertices[f.v1];
|
||||||
|
tri.data[1] = icosaVertices[f.v2];
|
||||||
|
tri.data[2] = icosaVertices[f.v3];
|
||||||
|
|
||||||
|
// Ãåíåðèðóåì ID äëÿ áàçîâûõ âåðøèí (ìîæíî èñïîëüçîâàòü èõ êîîðäèíàòû)
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
tri.ids[i] = std::to_string(tri.data[i].v[0]) + "_" +
|
||||||
|
std::to_string(tri.data[i].v[1]) + "_" +
|
||||||
|
std::to_string(tri.data[i].v[2]);
|
||||||
}
|
}
|
||||||
}
|
geometry.push_back(tri);
|
||||||
// 3. Ðàçáèâàåì N ðàç (â subdivideTriangles ãåíåðèðóþòñÿ ID íîâûõ âåðøèí)
|
|
||||||
for (int i = 0; i < subdivisions; i++) {
|
|
||||||
geometry = subdivideTriangles(geometry, noiseCoeff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Ãåíåðèðóåì PositionData, NormalData è VertexIDs
|
// 3. Ðàçáèâàåì N ðàç
|
||||||
|
for (int i = 0; i < subdivisions; i++) {
|
||||||
|
geometry = subdivideTriangles(geometry, 0.0f); // Øóì ïîêà èãíîðèðóåì
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Ñîçäàåì LodLevel è çàïîëíÿåì òîïîëîãèþ (v2tMap)
|
||||||
LodLevel lodLevel = createLodLevel(geometry);
|
LodLevel lodLevel = createLodLevel(geometry);
|
||||||
|
|
||||||
// 5. Ñîçäàíèå V2T-Map íà îñíîâå VertexIDs (ÒÎÏÎËÎÃÈ×ÅÑÊÈÉ ÊËÞ×)
|
// Ïåðåñîáèðàåì v2tMap (îíà êðèòè÷íà äëÿ ðåëàêñàöèè)
|
||||||
V2TMap v2tMap;
|
lodLevel.v2tMap.clear();
|
||||||
const auto& finalVertexIDs = lodLevel.VertexIDs;
|
for (size_t i = 0; i < geometry.size(); ++i) {
|
||||||
size_t num_triangles = geometry.size();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < num_triangles; ++i) {
|
|
||||||
for (int j = 0; j < 3; ++j) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
VertexID v_id = finalVertexIDs[i * 3 + j];
|
lodLevel.v2tMap[geometry[i].ids[j]].push_back((int)i);
|
||||||
|
|
||||||
// Åñëè êëþ÷ óæå åñòü, ïðîñòî äîáàâëÿåì èíäåêñ
|
|
||||||
v2tMap[v_id].push_back((int)i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lodLevel.v2tMap = v2tMap;
|
|
||||||
|
|
||||||
applySphericalLaplacianSmoothing(lodLevel, 5, 0.5f);
|
// 5. Ïðèìåíÿåì èòåðàòèâíóþ ðåëàêñàöèþ (Lloyd-like)
|
||||||
|
// 5-10 èòåðàöèé äîñòàòî÷íî äëÿ îòëè÷íîé ñåòêè
|
||||||
|
applySphericalRelaxation(lodLevel, 8);
|
||||||
|
|
||||||
// Ïðèìåíåíèå øóìà ÷åðåç óíèêàëüíûå ID ïîñëå ñãëàæèâàíèÿ
|
// 6. Íàêëàäûâàåì øóì è îáíîâëÿåì àòðèáóòû
|
||||||
std::map<VertexID, Vector3f> displacedPositions;
|
// ... (òâîé êîä íàëîæåíèÿ øóìà ÷åðåç Perlin)
|
||||||
for (const auto& tri : lodLevel.triangles) {
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
if (displacedPositions.find(tri.ids[i]) == displacedPositions.end()) {
|
|
||||||
Vector3f dir = tri.data[i].normalized();
|
|
||||||
displacedPositions[tri.ids[i]] = dir * perlin.getSurfaceHeight(dir, noiseCoeff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Îáíîâëÿåì òðåóãîëüíèêè ôèíàëüíûìè ïîçèöèÿìè
|
|
||||||
for (auto& tri : lodLevel.triangles) {
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
tri.data[i] = displacedPositions[tri.ids[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recalculateMeshAttributes(lodLevel);
|
recalculateMeshAttributes(lodLevel);
|
||||||
|
|
||||||
return lodLevel;
|
return lodLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Ïðèìåð findNeighbors:
|
|
||||||
std::vector<int> PlanetData::findNeighbors(int index, int lod) {
|
|
||||||
const V2TMap& v2tMap = planetMeshLods[lod].v2tMap;
|
|
||||||
const auto& vertexIDs = planetMeshLods[lod].VertexIDs;
|
|
||||||
if ((index * 3 + 2) >= vertexIDs.size()) return {};
|
|
||||||
std::set<int> neighbors;
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
VertexID v_id = vertexIDs[index * 3 + i];
|
|
||||||
auto it = v2tMap.find(v_id);
|
|
||||||
if (it != v2tMap.end()) {
|
|
||||||
for (int tri_index : it->second) {
|
|
||||||
if (tri_index != index) {
|
|
||||||
neighbors.insert(tri_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::vector<int>(neighbors.begin(), neighbors.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void PlanetData::applySphericalRelaxation(LodLevel& lod, int iterations) {
|
||||||
void PlanetData::applySphericalLaplacianSmoothing(LodLevel& lod, int iterations, float relaxationFactor) {
|
|
||||||
for (int iter = 0; iter < iterations; ++iter) {
|
for (int iter = 0; iter < iterations; ++iter) {
|
||||||
std::map<VertexID, Vector3f> newPositions;
|
std::map<VertexID, Vector3f> newPositions;
|
||||||
|
|
||||||
// 1. Ñîáèðàåì ñîñåäåé è òåêóùèå ïîçèöèè èç triangles
|
for (auto const& [vID, connectedTris] : lod.v2tMap) {
|
||||||
for (auto const& [vID, connectedTriangles] : lod.v2tMap) {
|
|
||||||
Vector3f currentPos;
|
|
||||||
std::set<VertexID> neighborIDs;
|
|
||||||
|
|
||||||
for (int triIdx : connectedTriangles) {
|
|
||||||
const auto& tri = lod.triangles[triIdx];
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
if (tri.ids[i] == vID) {
|
|
||||||
currentPos = tri.data[i]; // Áåðåì èç triangles
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
neighborIDs.insert(tri.ids[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (neighborIDs.empty()) continue;
|
|
||||||
|
|
||||||
// 2. Öåíòðîèä ñîñåäåé
|
|
||||||
Vector3f centroid(0, 0, 0);
|
Vector3f centroid(0, 0, 0);
|
||||||
for (const auto& nID : neighborIDs) {
|
|
||||||
int firstTriIdx = lod.v2tMap[nID][0];
|
|
||||||
const auto& tri = lod.triangles[firstTriIdx];
|
|
||||||
for (int k = 0; k < 3; ++k) {
|
|
||||||
if (tri.ids[k] == nID) {
|
|
||||||
centroid = centroid + tri.data[k];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
centroid = centroid * (1.0f / (float)neighborIDs.size());
|
|
||||||
|
|
||||||
// 3. Ðàññëàáëåíèå è ñôåðè÷åñêàÿ ïðîåêöèÿ
|
// Íàõîäèì ñðåäíþþ òî÷êó ñðåäè öåíòðîâ âñåõ ñîñåäíèõ òðåóãîëüíèêîâ
|
||||||
Vector3f relaxedPos = currentPos + (centroid - currentPos) * relaxationFactor;
|
for (int triIdx : connectedTris) {
|
||||||
newPositions[vID] = relaxedPos.normalized() * currentPos.length();
|
const auto& tri = lod.triangles[triIdx];
|
||||||
|
Vector3f faceCenter = (tri.data[0] + tri.data[1] + tri.data[2]) * (1.0f / 3.0f);
|
||||||
|
centroid = centroid + faceCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
centroid = centroid * (1.0f / (float)connectedTris.size());
|
||||||
|
|
||||||
|
// Ïðîåöèðóåì îáðàòíî íà åäèíè÷íóþ ñôåðó
|
||||||
|
newPositions[vID] = centroid.normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Îáíîâëÿåì êîîðäèíàòû ïðÿìî â îáúåêòàõ Triangle
|
// Ñèíõðîíèçèðóåì äàííûå â òðåóãîëüíèêàõ
|
||||||
for (auto& tri : lod.triangles) {
|
for (auto& tri : lod.triangles) {
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
tri.data[i] = newPositions[tri.ids[i]];
|
tri.data[i] = newPositions[tri.ids[i]];
|
||||||
|
|||||||
@ -102,14 +102,13 @@ namespace ZL {
|
|||||||
|
|
||||||
// Ëîãèêà
|
// Ëîãèêà
|
||||||
std::pair<float, float> calculateZRange(float distanceToSurface);
|
std::pair<float, float> calculateZRange(float distanceToSurface);
|
||||||
float distanceToPlanetSurface(const Vector3f& viewerPosition);
|
|
||||||
float distanceToPlanetSurfaceFast(const Vector3f& viewerPosition);
|
float distanceToPlanetSurfaceFast(const Vector3f& viewerPosition);
|
||||||
|
|
||||||
// Âîçâðàùàåò èíäåêñû òðåóãîëüíèêîâ, âèäèìûõ êàìåðîé
|
// Âîçâðàùàåò èíäåêñû òðåóãîëüíèêîâ, âèäèìûõ êàìåðîé
|
||||||
std::vector<int> getTrianglesUnderCameraNew(const Vector3f& viewerPosition);
|
std::vector<int> getBestTriangleUnderCamera(const Vector3f& viewerPosition);
|
||||||
std::vector<int> findNeighbors(int index, int lod);
|
std::vector<int> getTrianglesUnderCameraNew2(const Vector3f& viewerPosition);
|
||||||
|
|
||||||
void applySphericalLaplacianSmoothing(LodLevel& lod, int iterations, float relaxationFactor);
|
void applySphericalRelaxation(LodLevel& lod, int iterations);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
@ -81,51 +81,27 @@ namespace ZL {
|
|||||||
planetStones = CreateStoneGroupData(778, planetData.getLodLevel(lodIndex));
|
planetStones = CreateStoneGroupData(778, planetData.getLodLevel(lodIndex));
|
||||||
|
|
||||||
stonesToRender = planetStones.inflate(planetStones.allInstances.size());
|
stonesToRender = planetStones.inflate(planetStones.allInstances.size());
|
||||||
}
|
|
||||||
|
|
||||||
void PlanetObject::prepareDrawData() {
|
stoneToBake = planetStones.inflateOne(0, 0.75);
|
||||||
if (!drawDataDirty) return;
|
|
||||||
drawDataDirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PlanetObject::update(float deltaTimeMs) {
|
void PlanetObject::update(float deltaTimeMs) {
|
||||||
// 1. Получаем базовые треугольники под камерой
|
|
||||||
auto lr = planetData.getTrianglesUnderCameraNew(Environment::shipPosition);
|
|
||||||
int currentLod = planetData.getCurrentLodIndex();
|
|
||||||
|
|
||||||
|
float movementThreshold = 1.0f;
|
||||||
|
if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold && !triangleIndicesToDraw.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastUpdatePos = Environment::shipPosition;
|
||||||
|
|
||||||
// Временный вектор для сбора новых индексов
|
auto newIndices = planetData.getTrianglesUnderCameraNew2(Environment::shipPosition);
|
||||||
std::vector<int> newIndices;
|
|
||||||
|
|
||||||
newIndices = lr;
|
// Сортировка важна для сравнения векторов
|
||||||
|
|
||||||
// 2. Сортируем новый список, чтобы порядок не влиял на сравнение
|
|
||||||
std::sort(newIndices.begin(), newIndices.end());
|
std::sort(newIndices.begin(), newIndices.end());
|
||||||
|
|
||||||
// 3. Сравниваем с тем, что было нарисовано в прошлый раз
|
|
||||||
if (newIndices != triangleIndicesToDraw) {
|
if (newIndices != triangleIndicesToDraw) {
|
||||||
// Обновляем список индексов (используем move для эффективности)
|
|
||||||
triangleIndicesToDraw = std::move(newIndices);
|
triangleIndicesToDraw = std::move(newIndices);
|
||||||
/*
|
|
||||||
// --- ОБНОВЛЯЕМ ЖЕЛТУЮ ЗОНУ (только когда изменился состав треугольников) ---
|
|
||||||
const auto& fullMesh = planetData.getLodLevel(currentLod).vertexData;
|
|
||||||
planetRenderYellowStruct.data.PositionData.clear();
|
|
||||||
planetRenderYellowStruct.data.TexCoordData.clear();
|
|
||||||
|
|
||||||
for (int i : triangleIndicesToDraw) {
|
|
||||||
// Копируем геометрию для подсветки
|
|
||||||
for (int j = 0; j < 3; ++j) {
|
|
||||||
planetRenderYellowStruct.data.PositionData.push_back(fullMesh.PositionData[i * 3 + j]);
|
|
||||||
planetRenderYellowStruct.data.TexCoordData.push_back(fullMesh.TexCoordData[i * 3 + j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (planetRenderYellowStruct.data.PositionData.size() > 0)
|
|
||||||
{
|
|
||||||
planetRenderYellowStruct.RefreshVBO();
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -146,13 +122,6 @@ namespace ZL {
|
|||||||
renderer.EnableVertexAttribArray(vPositionName);
|
renderer.EnableVertexAttribArray(vPositionName);
|
||||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||||
|
|
||||||
float dist = planetData.distanceToPlanetSurface(Environment::shipPosition);
|
|
||||||
auto zRange = planetData.calculateZRange(dist);
|
|
||||||
const float currentZNear = zRange.first;
|
|
||||||
const float currentZFar = zRange.second;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Triangle tr = planetData.getLodLevel(planetData.getCurrentLodIndex()).triangles[0];
|
Triangle tr = planetData.getLodLevel(planetData.getCurrentLodIndex()).triangles[0];
|
||||||
|
|
||||||
// 1. Получаем матрицу вращения (оси в столбцах)
|
// 1. Получаем матрицу вращения (оси в столбцах)
|
||||||
@ -207,11 +176,11 @@ namespace ZL {
|
|||||||
|
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glCullFace(GL_BACK); // Отсекаем задние грани
|
glCullFace(GL_BACK); // Отсекаем задние грани
|
||||||
if (stonesToRender[0].data.PositionData.size() > 0)
|
if (stoneToBake.data.PositionData.size() > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
|
||||||
renderer.DrawVertexRenderStruct(stonesToRender[0]);
|
renderer.DrawVertexRenderStruct(stoneToBake);
|
||||||
CheckGlError();
|
CheckGlError();
|
||||||
}
|
}
|
||||||
glDisable(GL_CULL_FACE); // Не забываем выключить, чтобы не сломать остальной рендер
|
glDisable(GL_CULL_FACE); // Не забываем выключить, чтобы не сломать остальной рендер
|
||||||
@ -226,8 +195,6 @@ namespace ZL {
|
|||||||
|
|
||||||
void PlanetObject::draw(Renderer& renderer) {
|
void PlanetObject::draw(Renderer& renderer) {
|
||||||
|
|
||||||
prepareDrawData();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
if (stoneMapFB == nullptr)
|
if (stoneMapFB == nullptr)
|
||||||
{
|
{
|
||||||
@ -248,7 +215,6 @@ namespace ZL {
|
|||||||
|
|
||||||
|
|
||||||
drawPlanet(renderer);
|
drawPlanet(renderer);
|
||||||
//drawYellowZone(renderer);
|
|
||||||
drawStones(renderer);
|
drawStones(renderer);
|
||||||
|
|
||||||
drawAtmosphere(renderer);
|
drawAtmosphere(renderer);
|
||||||
@ -400,79 +366,6 @@ namespace ZL {
|
|||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlanetObject::drawYellowZone(Renderer& renderer)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
|
|
||||||
static const std::string defaultShaderName = "planetLand";
|
|
||||||
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 textureUniformName = "Texture";
|
|
||||||
|
|
||||||
float dist = planetData.distanceToPlanetSurface(Environment::shipPosition);
|
|
||||||
auto zRange = planetData.calculateZRange(dist);
|
|
||||||
const float currentZNear = zRange.first;
|
|
||||||
const float currentZFar = zRange.second;
|
|
||||||
|
|
||||||
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
|
||||||
if (planetRenderYellowStruct.data.PositionData.size() > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
renderer.shaderManager.PushShader(defaultShaderName);
|
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
|
||||||
renderer.EnableVertexAttribArray(vPositionName);
|
|
||||||
renderer.EnableVertexAttribArray(vColorName);
|
|
||||||
renderer.EnableVertexAttribArray(vNormalName);
|
|
||||||
renderer.EnableVertexAttribArray("vTangent");
|
|
||||||
renderer.EnableVertexAttribArray("vBinormal");
|
|
||||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
|
||||||
|
|
||||||
// 2. Применяем динамическую матрицу проекции
|
|
||||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
|
||||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
|
||||||
currentZNear, currentZFar);
|
|
||||||
|
|
||||||
renderer.PushMatrix();
|
|
||||||
renderer.LoadIdentity();
|
|
||||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
|
||||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
|
||||||
|
|
||||||
renderer.TranslateMatrix(-Environment::shipPosition);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
renderer.RenderUniform1f("uDistanceToPlanetSurface", dist);
|
|
||||||
renderer.RenderUniform1f("uCurrentZFar", currentZFar);
|
|
||||||
|
|
||||||
renderer.RenderUniform3fv("uViewPos", &Environment::shipPosition.v[0]);
|
|
||||||
|
|
||||||
Vector3f color2 = { 1.0, 1.0, 0.0 };
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, sandTexture->getTexID());
|
|
||||||
|
|
||||||
renderer.RenderUniform3fv("uColor", &color2.v[0]);
|
|
||||||
renderer.DrawVertexRenderStruct(planetRenderYellowStruct);
|
|
||||||
//glDisable(GL_BLEND);
|
|
||||||
CheckGlError();
|
|
||||||
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
|
||||||
renderer.PopProjectionMatrix();
|
|
||||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
|
||||||
renderer.DisableVertexAttribArray(vNormalName);
|
|
||||||
renderer.DisableVertexAttribArray("vTangent");
|
|
||||||
renderer.DisableVertexAttribArray("vBinormal");
|
|
||||||
renderer.DisableVertexAttribArray(vColorName);
|
|
||||||
renderer.DisableVertexAttribArray(vPositionName);
|
|
||||||
renderer.shaderManager.PopShader();
|
|
||||||
CheckGlError();
|
|
||||||
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlanetObject::drawAtmosphere(Renderer& renderer) {
|
void PlanetObject::drawAtmosphere(Renderer& renderer) {
|
||||||
static const std::string defaultShaderName = "defaultAtmosphere";
|
static const std::string defaultShaderName = "defaultAtmosphere";
|
||||||
static const std::string vPositionName = "vPosition";
|
static const std::string vPositionName = "vPosition";
|
||||||
|
|||||||
@ -22,26 +22,24 @@ namespace ZL {
|
|||||||
|
|
||||||
class PlanetObject {
|
class PlanetObject {
|
||||||
public:
|
public:
|
||||||
// Агрегация: логика и данные теперь здесь
|
|
||||||
PlanetData planetData;
|
PlanetData planetData;
|
||||||
|
|
||||||
// Данные только для рендеринга (OpenGL specific)
|
// Данные только для рендеринга (OpenGL specific)
|
||||||
VertexRenderStruct planetRenderStruct;
|
VertexRenderStruct planetRenderStruct;
|
||||||
VertexRenderStruct planetRenderYellowStruct;
|
|
||||||
VertexRenderStruct planetAtmosphereRenderStruct;
|
VertexRenderStruct planetAtmosphereRenderStruct;
|
||||||
StoneGroup planetStones;
|
StoneGroup planetStones;
|
||||||
std::vector<VertexRenderStruct> stonesToRender;
|
std::vector<VertexRenderStruct> stonesToRender;
|
||||||
|
VertexRenderStruct stoneToBake;
|
||||||
|
|
||||||
std::vector<int> triangleIndicesToDraw;
|
std::vector<int> triangleIndicesToDraw;
|
||||||
|
|
||||||
std::shared_ptr<Texture> sandTexture;
|
std::shared_ptr<Texture> sandTexture;
|
||||||
std::shared_ptr<Texture> stoneTexture;
|
std::shared_ptr<Texture> stoneTexture;
|
||||||
|
|
||||||
bool drawDataDirty = true;
|
|
||||||
void prepareDrawData();
|
|
||||||
|
|
||||||
std::unique_ptr<FrameBuffer> stoneMapFB;
|
std::unique_ptr<FrameBuffer> stoneMapFB;
|
||||||
|
|
||||||
|
Vector3f lastUpdatePos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlanetObject();
|
PlanetObject();
|
||||||
|
|
||||||
@ -51,10 +49,8 @@ namespace ZL {
|
|||||||
void draw(Renderer& renderer);
|
void draw(Renderer& renderer);
|
||||||
void drawStones(Renderer& renderer);
|
void drawStones(Renderer& renderer);
|
||||||
void drawPlanet(Renderer& renderer);
|
void drawPlanet(Renderer& renderer);
|
||||||
void drawYellowZone(Renderer& renderer);
|
|
||||||
void drawAtmosphere(Renderer& renderer);
|
void drawAtmosphere(Renderer& renderer);
|
||||||
|
|
||||||
|
|
||||||
float distanceToPlanetSurface(const Vector3f& viewerPosition);
|
float distanceToPlanetSurface(const Vector3f& viewerPosition);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -12,17 +12,16 @@ namespace ZL {
|
|||||||
|
|
||||||
|
|
||||||
const float StoneParams::BASE_SCALE = 15.0f; // Общий размер камня
|
const float StoneParams::BASE_SCALE = 15.0f; // Общий размер камня
|
||||||
/*const float StoneParams::BASE_SCALE = 150.0f; // Общий размер камня
|
|
||||||
const float StoneParams::MIN_AXIS_SCALE = 1.0f; // Минимальное растяжение/сжатие по оси
|
const float StoneParams::MIN_AXIS_SCALE = 1.0f; // Минимальное растяжение/сжатие по оси
|
||||||
const float StoneParams::MAX_AXIS_SCALE = 1.0f; // Максимальное растяжение/сжатие по оси
|
const float StoneParams::MAX_AXIS_SCALE = 1.0f; // Максимальное растяжение/сжатие по оси
|
||||||
const float StoneParams::MIN_PERTURBATION = 0.0f; // Минимальное радиальное возмущение вершины
|
const float StoneParams::MIN_PERTURBATION = 0.0f; // Минимальное радиальное возмущение вершины
|
||||||
const float StoneParams::MAX_PERTURBATION = 0.0f;*/ // Максимальное радиальное возмущение вершины
|
const float StoneParams::MAX_PERTURBATION = 0.0f; // Максимальное радиальное возмущение вершины
|
||||||
const float StoneParams::MIN_AXIS_SCALE = 0.5f; // Минимальное растяжение/сжатие по оси
|
/*const float StoneParams::MIN_AXIS_SCALE = 0.5f; // Минимальное растяжение/сжатие по оси
|
||||||
const float StoneParams::MAX_AXIS_SCALE = 1.5f; // Максимальное растяжение/сжатие по оси
|
const float StoneParams::MAX_AXIS_SCALE = 1.5f; // Максимальное растяжение/сжатие по оси
|
||||||
const float StoneParams::MIN_PERTURBATION = 0.05f; // Минимальное радиальное возмущение вершины
|
const float StoneParams::MIN_PERTURBATION = 0.05f; // Минимальное радиальное возмущение вершины
|
||||||
const float StoneParams::MAX_PERTURBATION = 0.25f; // Максимальное радиальное возмущение вершины
|
const float StoneParams::MAX_PERTURBATION = 0.25f; // Максимальное радиальное возмущение вершины
|
||||||
|
*/
|
||||||
const int StoneParams::STONES_PER_TRIANGLE = 100;
|
const int StoneParams::STONES_PER_TRIANGLE = 40;
|
||||||
|
|
||||||
// Вспомогательная функция для получения случайного числа в диапазоне [min, max]
|
// Вспомогательная функция для получения случайного числа в диапазоне [min, max]
|
||||||
float getRandomFloat(std::mt19937& gen, float min, float max) {
|
float getRandomFloat(std::mt19937& gen, float min, float max) {
|
||||||
@ -110,6 +109,7 @@ namespace ZL {
|
|||||||
v.v[2] *= scaleFactors.v[2];
|
v.v[2] *= scaleFactors.v[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Случайный поворот (например, вокруг трех осей)
|
// Случайный поворот (например, вокруг трех осей)
|
||||||
Vector4f qx = QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f));
|
Vector4f qx = QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f));
|
||||||
Vector4f qy = QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f));
|
Vector4f qy = QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f));
|
||||||
@ -120,7 +120,7 @@ namespace ZL {
|
|||||||
|
|
||||||
for (Vector3f& v : initialVertices) {
|
for (Vector3f& v : initialVertices) {
|
||||||
v = MultMatrixVector(rotationMatrix, v);
|
v = MultMatrixVector(rotationMatrix, v);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// 3. Сглаженные Нормали и Формирование Mesh
|
// 3. Сглаженные Нормали и Формирование Mesh
|
||||||
VertexDataStruct result;
|
VertexDataStruct result;
|
||||||
@ -249,23 +249,28 @@ namespace ZL {
|
|||||||
instance.seed = globalSeed;// + tIdx * 1000 + i;
|
instance.seed = globalSeed;// + tIdx * 1000 + i;
|
||||||
instance.position = GetRandomPointOnTriangle(tri, engine);
|
instance.position = GetRandomPointOnTriangle(tri, engine);
|
||||||
|
|
||||||
|
float SCALE_MIN = 0.75f;
|
||||||
|
float SCALE_MAX = 2.5f;
|
||||||
|
|
||||||
instance.scale = {
|
instance.scale = {
|
||||||
getRandomFloat(engine, 0.5f, 1.5f),
|
getRandomFloat(engine, SCALE_MIN, SCALE_MAX),
|
||||||
getRandomFloat(engine, 0.5f, 1.5f),
|
getRandomFloat(engine, SCALE_MIN, SCALE_MAX),
|
||||||
getRandomFloat(engine, 0.5f, 1.5f)
|
getRandomFloat(engine, SCALE_MIN, SCALE_MAX)
|
||||||
};
|
};
|
||||||
|
|
||||||
//!!! Hack - to fix it! -- Vladislav Khorev
|
/*
|
||||||
if (tIdx == 0)
|
if (tIdx == 0)
|
||||||
{
|
{
|
||||||
instance.scale = instance.scale * 0.6f;
|
instance.scale = instance.scale * 0.7f;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
Vector4f qx = QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f));
|
Vector4f qx = QuatFromRotateAroundX(getRandomFloat(engine, 0.0f, 360.0f));
|
||||||
Vector4f qy = QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f));
|
Vector4f qy = QuatFromRotateAroundY(getRandomFloat(engine, 0.0f, 360.0f));
|
||||||
Vector4f qz = QuatFromRotateAroundZ(getRandomFloat(engine, 0.0f, 360.0f));
|
Vector4f qz = QuatFromRotateAroundZ(getRandomFloat(engine, 0.0f, 360.0f));
|
||||||
instance.rotation = slerp(slerp(qx, qy, 0.5f), qz, 0.5f).normalized();
|
instance.rotation = slerp(slerp(qx, qy, 0.5f), qz, 0.5f).normalized();
|
||||||
|
*/
|
||||||
|
instance.rotation = Vector4f(0.f, 0.f, 0.f, 1.f);
|
||||||
group.allInstances[tIdx].push_back(instance);
|
group.allInstances[tIdx].push_back(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,13 +279,15 @@ namespace ZL {
|
|||||||
|
|
||||||
std::vector<VertexRenderStruct> StoneGroup::inflate(int count)
|
std::vector<VertexRenderStruct> StoneGroup::inflate(int count)
|
||||||
{
|
{
|
||||||
static VertexDataStruct baseStone = CreateBaseConvexPolyhedron(1337);
|
//static VertexDataStruct baseStone = CreateBaseConvexPolyhedron(1337);
|
||||||
|
|
||||||
std::vector<VertexRenderStruct> result;
|
std::vector<VertexRenderStruct> result;
|
||||||
result.resize(count);
|
result.resize(count);
|
||||||
|
|
||||||
for (int tIdx = 0; tIdx < count; tIdx++)
|
for (int tIdx = 0; tIdx < count; tIdx++)
|
||||||
{
|
{
|
||||||
|
result[tIdx] = inflateOne(tIdx, 1.0f);
|
||||||
|
/*
|
||||||
for (const auto& inst : allInstances[tIdx]) {
|
for (const auto& inst : allInstances[tIdx]) {
|
||||||
Matrix3f rotMat = QuatToMatrix(inst.rotation);
|
Matrix3f rotMat = QuatToMatrix(inst.rotation);
|
||||||
|
|
||||||
@ -299,10 +306,41 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result[tIdx].RefreshVBO();
|
result[tIdx].RefreshVBO();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VertexRenderStruct StoneGroup::inflateOne(int index, float scaleModifier)
|
||||||
|
{
|
||||||
|
static VertexDataStruct baseStone = CreateBaseConvexPolyhedron(1337);
|
||||||
|
|
||||||
|
VertexRenderStruct result;
|
||||||
|
|
||||||
|
|
||||||
|
for (const auto& inst : allInstances[index]) {
|
||||||
|
Matrix3f rotMat = QuatToMatrix(inst.rotation);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < baseStone.PositionData.size(); ++j) {
|
||||||
|
Vector3f p = baseStone.PositionData[j];
|
||||||
|
Vector3f n = baseStone.NormalData[j];
|
||||||
|
|
||||||
|
p.v[0] *= inst.scale.v[0] * scaleModifier;
|
||||||
|
p.v[1] *= inst.scale.v[1] * scaleModifier;
|
||||||
|
p.v[2] *= inst.scale.v[2] * scaleModifier;
|
||||||
|
|
||||||
|
result.data.PositionData.push_back(MultMatrixVector(rotMat, p) + inst.position);
|
||||||
|
result.data.NormalData.push_back(MultMatrixVector(rotMat, n));
|
||||||
|
result.data.TexCoordData.push_back(baseStone.TexCoordData[j]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result.RefreshVBO();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
|
|||||||
@ -31,6 +31,8 @@ namespace ZL {
|
|||||||
|
|
||||||
// Очищает старую геометрию и генерирует новую для указанных индексов
|
// Очищает старую геометрию и генерирует новую для указанных индексов
|
||||||
std::vector<VertexRenderStruct> inflate(int count);
|
std::vector<VertexRenderStruct> inflate(int count);
|
||||||
|
|
||||||
|
VertexRenderStruct inflateOne(int index, float scaleModifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Теперь возвращает заготовку со всеми параметрами, но без тяжелого меша
|
// Теперь возвращает заготовку со всеми параметрами, но без тяжелого меша
|
||||||
|
|||||||
@ -9,6 +9,16 @@ namespace ZL {
|
|||||||
|
|
||||||
struct Vector4f
|
struct Vector4f
|
||||||
{
|
{
|
||||||
|
Vector4f()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector4f(float x, float y, float z, float t)
|
||||||
|
: v{ x,y,z,t }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::array<float, 4> v = { 0.f, 0.f, 0.f, 0.f };
|
std::array<float, 4> v = { 0.f, 0.f, 0.f, 0.f };
|
||||||
|
|
||||||
Vector4f normalized() const {
|
Vector4f normalized() const {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user