fix spark
This commit is contained in:
parent
b855cff0e6
commit
115cbbb7fa
948
Game.cpp
948
Game.cpp
@ -12,516 +12,528 @@
|
|||||||
namespace ZL
|
namespace ZL
|
||||||
{
|
{
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
const char* CONST_ZIP_FILE = "space-game001.zip";
|
const char* CONST_ZIP_FILE = "space-game001.zip";
|
||||||
#else
|
#else
|
||||||
const char* CONST_ZIP_FILE = "";
|
const char* CONST_ZIP_FILE = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Vector4f generateRandomQuaternion(std::mt19937& gen)
|
Vector4f generateRandomQuaternion(std::mt19937& gen)
|
||||||
{
|
{
|
||||||
// Ðàñïðåäåëåíèå äëÿ ãåíåðàöèè ñëó÷àéíûõ êîîðäèíàò êâàòåðíèîíà
|
// Ðàñïðåäåëåíèå äëÿ ãåíåðàöèè ñëó÷àéíûõ êîîðäèíàò êâàòåðíèîíà
|
||||||
std::normal_distribution<> distrib(0.0, 1.0);
|
std::normal_distribution<> distrib(0.0, 1.0);
|
||||||
|
|
||||||
// Ãåíåðèðóåì ÷åòûðå ñëó÷àéíûõ ÷èñëà èç íîðìàëüíîãî ðàñïðåäåëåíèÿ N(0, 1).
|
// Ãåíåðèðóåì ÷åòûðå ñëó÷àéíûõ ÷èñëà èç íîðìàëüíîãî ðàñïðåäåëåíèÿ N(0, 1).
|
||||||
// Íîðìàëèçàöèÿ ýòîãî âåêòîðà äàåò ðàâíîìåðíîå ðàñïðåäåëåíèå ïî 4D-ñôåðå (ò.å. êâàòåðíèîí åäèíè÷íîé äëèíû).
|
// Íîðìàëèçàöèÿ ýòîãî âåêòîðà äàåò ðàâíîìåðíîå ðàñïðåäåëåíèå ïî 4D-ñôåðå (ò.å. êâàòåðíèîí åäèíè÷íîé äëèíû).
|
||||||
Vector4f randomQuat = {
|
Vector4f randomQuat = {
|
||||||
(float)distrib(gen),
|
(float)distrib(gen),
|
||||||
(float)distrib(gen),
|
(float)distrib(gen),
|
||||||
(float)distrib(gen),
|
(float)distrib(gen),
|
||||||
(float)distrib(gen)
|
(float)distrib(gen)
|
||||||
};
|
};
|
||||||
|
|
||||||
return randomQuat.normalized();
|
return randomQuat.normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- Îñíîâíàÿ ôóíêöèÿ ãåíåðàöèè ---
|
// --- Îñíîâíàÿ ôóíêöèÿ ãåíåðàöèè ---
|
||||||
std::vector<BoxCoords> generateRandomBoxCoords(int N)
|
std::vector<BoxCoords> generateRandomBoxCoords(int N)
|
||||||
{
|
{
|
||||||
// Êîíñòàíòû
|
// Êîíñòàíòû
|
||||||
const float MIN_DISTANCE = 3.0f;
|
const float MIN_DISTANCE = 3.0f;
|
||||||
const float MIN_DISTANCE_SQUARED = MIN_DISTANCE * MIN_DISTANCE; // Ðàáîòàåì ñ êâàäðàòîì ðàññòîÿíèÿ
|
const float MIN_DISTANCE_SQUARED = MIN_DISTANCE * MIN_DISTANCE; // Ðàáîòàåì ñ êâàäðàòîì ðàññòîÿíèÿ
|
||||||
const float MIN_COORD = -100.0f;
|
const float MIN_COORD = -100.0f;
|
||||||
const float MAX_COORD = 100.0f;
|
const float MAX_COORD = 100.0f;
|
||||||
const int MAX_ATTEMPTS = 1000; // Îãðàíè÷åíèå íà êîëè÷åñòâî ïîïûòîê, ÷òîáû èçáåæàòü áåñêîíå÷íîãî öèêëà
|
const int MAX_ATTEMPTS = 1000; // Îãðàíè÷åíèå íà êîëè÷åñòâî ïîïûòîê, ÷òîáû èçáåæàòü áåñêîíå÷íîãî öèêëà
|
||||||
|
|
||||||
std::vector<BoxCoords> boxCoordsArr;
|
std::vector<BoxCoords> boxCoordsArr;
|
||||||
boxCoordsArr.reserve(N); // Ðåçåðâèðóåì ïàìÿòü
|
boxCoordsArr.reserve(N); // Ðåçåðâèðóåì ïàìÿòü
|
||||||
|
|
||||||
// 1. Èíèöèàëèçàöèÿ ãåíåðàòîðà ïñåâäîñëó÷àéíûõ ÷èñåë
|
// 1. Èíèöèàëèçàöèÿ ãåíåðàòîðà ïñåâäîñëó÷àéíûõ ÷èñåë
|
||||||
// Èñïîëüçóåì Mersenne Twister (mt19937) êàê âûñîêîêà÷åñòâåííûé ãåíåðàòîð
|
// Èñïîëüçóåì Mersenne Twister (mt19937) êàê âûñîêîêà÷åñòâåííûé ãåíåðàòîð
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 gen(rd());
|
std::mt19937 gen(rd());
|
||||||
|
|
||||||
// 2. Îïðåäåëåíèå ðàâíîìåðíîãî ðàñïðåäåëåíèÿ äëÿ êîîðäèíàò [MIN_COORD, MAX_COORD]
|
// 2. Îïðåäåëåíèå ðàâíîìåðíîãî ðàñïðåäåëåíèÿ äëÿ êîîðäèíàò [MIN_COORD, MAX_COORD]
|
||||||
std::uniform_real_distribution<> distrib(MIN_COORD, MAX_COORD);
|
std::uniform_real_distribution<> distrib(MIN_COORD, MAX_COORD);
|
||||||
|
|
||||||
int generatedCount = 0;
|
int generatedCount = 0;
|
||||||
|
|
||||||
while (generatedCount < N)
|
while (generatedCount < N)
|
||||||
{
|
{
|
||||||
bool accepted = false;
|
bool accepted = false;
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
|
|
||||||
// Ïîïûòêà íàéòè ïîäõîäÿùèå êîîðäèíàòû
|
// Ïîïûòêà íàéòè ïîäõîäÿùèå êîîðäèíàòû
|
||||||
while (!accepted && attempts < MAX_ATTEMPTS)
|
while (!accepted && attempts < MAX_ATTEMPTS)
|
||||||
{
|
{
|
||||||
// Ãåíåðèðóåì íîâûå ñëó÷àéíûå êîîðäèíàòû
|
// Ãåíåðèðóåì íîâûå ñëó÷àéíûå êîîðäèíàòû
|
||||||
Vector3f newPos(
|
Vector3f newPos(
|
||||||
(float)distrib(gen),
|
(float)distrib(gen),
|
||||||
(float)distrib(gen),
|
(float)distrib(gen),
|
||||||
(float)distrib(gen)
|
(float)distrib(gen)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ïðîâåðêà ðàññòîÿíèÿ äî âñåõ óæå ñóùåñòâóþùèõ îáúåêòîâ
|
// Ïðîâåðêà ðàññòîÿíèÿ äî âñåõ óæå ñóùåñòâóþùèõ îáúåêòîâ
|
||||||
accepted = true; // Ïðåäïîëàãàåì, ÷òî ïîäõîäèò, ïîêà íå äîêàçàíî îáðàòíîå
|
accepted = true; // Ïðåäïîëàãàåì, ÷òî ïîäõîäèò, ïîêà íå äîêàçàíî îáðàòíîå
|
||||||
for (const auto& existingBox : boxCoordsArr)
|
for (const auto& existingBox : boxCoordsArr)
|
||||||
{
|
{
|
||||||
// Ðàñ÷åò âåêòîðà ðàçíîñòè
|
// Ðàñ÷åò âåêòîðà ðàçíîñòè
|
||||||
Vector3f diff = newPos - existingBox.pos;
|
Vector3f diff = newPos - existingBox.pos;
|
||||||
|
|
||||||
// Ðàñ÷åò êâàäðàòà ðàññòîÿíèÿ
|
// Ðàñ÷åò êâàäðàòà ðàññòîÿíèÿ
|
||||||
float distanceSquared = diff.squaredNorm();
|
float distanceSquared = diff.squaredNorm();
|
||||||
|
|
||||||
// Åñëè êâàäðàò ðàññòîÿíèÿ ìåíüøå êâàäðàòà ìèíèìàëüíîãî ðàññòîÿíèÿ
|
// Åñëè êâàäðàò ðàññòîÿíèÿ ìåíüøå êâàäðàòà ìèíèìàëüíîãî ðàññòîÿíèÿ
|
||||||
if (distanceSquared < MIN_DISTANCE_SQUARED)
|
if (distanceSquared < MIN_DISTANCE_SQUARED)
|
||||||
{
|
{
|
||||||
accepted = false; // Îòêëîíÿåì, ñëèøêîì áëèçêî
|
accepted = false; // Îòêëîíÿåì, ñëèøêîì áëèçêî
|
||||||
break; // Íåò ñìûñëà ïðîâåðÿòü äàëüøå, åñëè îäíî íàðóøåíèå íàéäåíî
|
break; // Íåò ñìûñëà ïðîâåðÿòü äàëüøå, åñëè îäíî íàðóøåíèå íàéäåíî
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accepted)
|
if (accepted)
|
||||||
{
|
{
|
||||||
// 2. Ãåíåðèðóåì ñëó÷àéíûé êâàòåðíèîí
|
// 2. Ãåíåðèðóåì ñëó÷àéíûé êâàòåðíèîí
|
||||||
Vector4f randomQuat = generateRandomQuaternion(gen);
|
Vector4f randomQuat = generateRandomQuaternion(gen);
|
||||||
|
|
||||||
// 3. Ïðåîáðàçóåì åãî â ìàòðèöó âðàùåíèÿ
|
// 3. Ïðåîáðàçóåì åãî â ìàòðèöó âðàùåíèÿ
|
||||||
Matrix3f randomMatrix = QuatToMatrix(randomQuat);
|
Matrix3f randomMatrix = QuatToMatrix(randomQuat);
|
||||||
|
|
||||||
// 4. Äîáàâëÿåì îáúåêò ñ íîâîé ñëó÷àéíîé ìàòðèöåé
|
// 4. Äîáàâëÿåì îáúåêò ñ íîâîé ñëó÷àéíîé ìàòðèöåé
|
||||||
boxCoordsArr.emplace_back(BoxCoords{ newPos, randomMatrix });
|
boxCoordsArr.emplace_back(BoxCoords{ newPos, randomMatrix });
|
||||||
generatedCount++;
|
generatedCount++;
|
||||||
}
|
}
|
||||||
attempts++;
|
attempts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Åñëè ïðåâûøåíî ìàêñèìàëüíîå êîëè÷åñòâî ïîïûòîê, âûõîäèì èç öèêëà,
|
// Åñëè ïðåâûøåíî ìàêñèìàëüíîå êîëè÷åñòâî ïîïûòîê, âûõîäèì èç öèêëà,
|
||||||
// ÷òîáû èçáåæàòü çàâèñàíèÿ, åñëè N ñëèøêîì âåëèêî èëè äèàïàçîí ñëèøêîì ìàë.
|
// ÷òîáû èçáåæàòü çàâèñàíèÿ, åñëè N ñëèøêîì âåëèêî èëè äèàïàçîí ñëèøêîì ìàë.
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
std::cerr << "Ïðåäóïðåæäåíèå: Íå óäàëîñü ñãåíåðèðîâàòü " << N << " îáúåêòîâ. Ñãåíåðèðîâàíî: " << generatedCount << std::endl;
|
std::cerr << "Ïðåäóïðåæäåíèå: Íå óäàëîñü ñãåíåðèðîâàòü " << N << " îáúåêòîâ. Ñãåíåðèðîâàíî: " << generatedCount << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return boxCoordsArr;
|
return boxCoordsArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::Game()
|
Game::Game()
|
||||||
: window(nullptr)
|
: window(nullptr)
|
||||||
, glContext(nullptr)
|
, glContext(nullptr)
|
||||||
, newTickCount(0)
|
, newTickCount(0)
|
||||||
, lastTickCount(0)
|
, lastTickCount(0)
|
||||||
{
|
{
|
||||||
std::vector<Vector3f> emissionPoints = {
|
std::vector<Vector3f> emissionPoints = {
|
||||||
Vector3f{-2.1f, 0.9f, 5.0f},
|
Vector3f{-2.1f, 0.9f, 5.0f},
|
||||||
Vector3f{2.1f, 0.9f, 5.0f}
|
Vector3f{2.1f, 0.9f, 5.0f}
|
||||||
};
|
};
|
||||||
sparkEmitter = SparkEmitter(emissionPoints, 100.0f);
|
sparkEmitter = SparkEmitter(emissionPoints, 100.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::~Game() {
|
Game::~Game() {
|
||||||
if (glContext) {
|
if (glContext) {
|
||||||
SDL_GL_DeleteContext(glContext);
|
SDL_GL_DeleteContext(glContext);
|
||||||
}
|
}
|
||||||
if (window) {
|
if (window) {
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
}
|
}
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::setup() {
|
void Game::setup() {
|
||||||
glContext = SDL_GL_CreateContext(ZL::Environment::window);
|
glContext = SDL_GL_CreateContext(ZL::Environment::window);
|
||||||
|
|
||||||
ZL::BindOpenGlFunctions();
|
ZL::BindOpenGlFunctions();
|
||||||
ZL::CheckGlError();
|
ZL::CheckGlError();
|
||||||
|
|
||||||
// Initialize renderer
|
// Initialize renderer
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env.vertex", "./shaders/env_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env.vertex", "./shaders/env_web.fragment", CONST_ZIP_FILE);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_desktop.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("default", "./shaders/default.vertex", "./shaders/default_desktop.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("defaultColor", "./shaders/defaultColor.vertex", "./shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env.vertex", "./shaders/env_desktop.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("env", "./shaders/env.vertex", "./shaders/env_desktop.fragment", CONST_ZIP_FILE);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cubemapTexture = std::make_shared<Texture>(
|
cubemapTexture = std::make_shared<Texture>(
|
||||||
std::array<TextureDataStruct, 6>{
|
std::array<TextureDataStruct, 6>{
|
||||||
CreateTextureDataFromBmp24("./resources/sky/space_rt.bmp", CONST_ZIP_FILE),
|
CreateTextureDataFromBmp24("./resources/sky/space_rt.bmp", CONST_ZIP_FILE),
|
||||||
CreateTextureDataFromBmp24("./resources/sky/space_lf.bmp", CONST_ZIP_FILE),
|
CreateTextureDataFromBmp24("./resources/sky/space_lf.bmp", CONST_ZIP_FILE),
|
||||||
CreateTextureDataFromBmp24("./resources/sky/space_up.bmp", CONST_ZIP_FILE),
|
CreateTextureDataFromBmp24("./resources/sky/space_up.bmp", CONST_ZIP_FILE),
|
||||||
CreateTextureDataFromBmp24("./resources/sky/space_dn.bmp", CONST_ZIP_FILE),
|
CreateTextureDataFromBmp24("./resources/sky/space_dn.bmp", CONST_ZIP_FILE),
|
||||||
CreateTextureDataFromBmp24("./resources/sky/space_bk.bmp", CONST_ZIP_FILE),
|
CreateTextureDataFromBmp24("./resources/sky/space_bk.bmp", CONST_ZIP_FILE),
|
||||||
CreateTextureDataFromBmp24("./resources/sky/space_ft.bmp", CONST_ZIP_FILE)
|
CreateTextureDataFromBmp24("./resources/sky/space_ft.bmp", CONST_ZIP_FILE)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
cubemap.data = ZL::CreateCubemap(500);
|
|
||||||
cubemap.RefreshVBO();
|
|
||||||
|
|
||||||
//Load texture
|
|
||||||
spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/DefaultMaterial_BaseColor.png", CONST_ZIP_FILE));
|
|
||||||
spaceshipBase = LoadFromTextFile02("./resources/spaceship005.txt", CONST_ZIP_FILE);
|
|
||||||
spaceshipBase.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundY(M_PI / 2.0)));
|
|
||||||
//spaceshipBase.Move(Vector3f{ -0.52998, -13, 0 });
|
|
||||||
spaceshipBase.Move(Vector3f{ -0.52998, -10, 10 });
|
|
||||||
|
|
||||||
spaceship.AssignFrom(spaceshipBase);
|
|
||||||
spaceship.RefreshVBO();
|
|
||||||
|
|
||||||
//Boxes
|
|
||||||
boxTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/box/box.png", CONST_ZIP_FILE));
|
|
||||||
boxBase = LoadFromTextFile02("./resources/box/box.txt", CONST_ZIP_FILE);
|
|
||||||
|
|
||||||
boxCoordsArr = generateRandomBoxCoords(50);
|
|
||||||
|
|
||||||
boxRenderArr.resize(boxCoordsArr.size());
|
|
||||||
|
|
||||||
for (int i = 0; i < boxCoordsArr.size(); i++)
|
|
||||||
{
|
|
||||||
boxRenderArr[i].AssignFrom(boxBase);
|
|
||||||
boxRenderArr[i].RefreshVBO();
|
|
||||||
}
|
|
||||||
|
|
||||||
sparkTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/spark.png", CONST_ZIP_FILE));
|
|
||||||
|
|
||||||
/*singleSpark.data.PositionData.push_back({-1, -1, 0});
|
|
||||||
singleSpark.data.PositionData.push_back({ -1, 1, 0 });
|
|
||||||
singleSpark.data.PositionData.push_back({ 1, 1, 0 });
|
|
||||||
singleSpark.data.PositionData.push_back({ -1, -1, 0 });
|
|
||||||
singleSpark.data.PositionData.push_back({ 1, 1, 0 });
|
|
||||||
singleSpark.data.PositionData.push_back({ 1, -1, 0 });
|
|
||||||
|
|
||||||
singleSpark.data.TexCoordData.push_back({0,0});
|
|
||||||
singleSpark.data.TexCoordData.push_back({ 0,1 });
|
|
||||||
singleSpark.data.TexCoordData.push_back({1,1});
|
|
||||||
singleSpark.data.TexCoordData.push_back({0,0});
|
|
||||||
singleSpark.data.TexCoordData.push_back({ 1,1 });
|
|
||||||
singleSpark.data.TexCoordData.push_back({ 1,0 });
|
|
||||||
|
|
||||||
singleSpark.RefreshVBO();*/
|
|
||||||
sparkQuad.data = CreateRect2D({ 0, 0 }, { 0.08f, 0.08f }, 0);
|
|
||||||
sparkQuad.RefreshVBO();
|
|
||||||
|
|
||||||
renderer.InitOpenGL();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::drawCubemap()
|
|
||||||
{
|
|
||||||
static const std::string defaultShaderName = "default";
|
|
||||||
static const std::string envShaderName = "env";
|
|
||||||
static const std::string vPositionName = "vPosition";
|
|
||||||
static const std::string vTexCoordName = "vTexCoord";
|
|
||||||
static const std::string textureUniformName = "Texture";
|
|
||||||
|
|
||||||
renderer.shaderManager.PushShader(envShaderName);
|
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
|
||||||
renderer.EnableVertexAttribArray(vPositionName);
|
|
||||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
|
||||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
|
||||||
1, 1000);
|
|
||||||
renderer.PushMatrix();
|
|
||||||
renderer.LoadIdentity();
|
|
||||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
|
||||||
|
|
||||||
CheckGlError();
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture->getTexID());
|
|
||||||
renderer.DrawVertexRenderStruct(cubemap);
|
|
||||||
|
|
||||||
CheckGlError();
|
|
||||||
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
|
||||||
renderer.PopProjectionMatrix();
|
|
||||||
renderer.DisableVertexAttribArray(vPositionName);
|
|
||||||
|
|
||||||
renderer.shaderManager.PopShader();
|
|
||||||
CheckGlError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::drawEffects()
|
|
||||||
{
|
|
||||||
static const std::string defaultShaderName = "default";
|
|
||||||
static const std::string vPositionName = "vPosition";
|
|
||||||
static const std::string vTexCoordName = "vTexCoord";
|
|
||||||
static const std::string textureUniformName = "Texture";
|
|
||||||
|
|
||||||
if (sparkEmitter.getActiveParticleCount() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer.shaderManager.PushShader(defaultShaderName);
|
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
|
||||||
renderer.EnableVertexAttribArray(vPositionName);
|
|
||||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
|
||||||
|
|
||||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
|
||||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
|
||||||
1, 1000);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, sparkTexture->getTexID());
|
|
||||||
|
|
||||||
const auto& particles = sparkEmitter.getParticles();
|
|
||||||
for (const auto& particle : particles) {
|
|
||||||
if (!particle.active) continue;
|
|
||||||
|
|
||||||
renderer.PushMatrix();
|
|
||||||
renderer.LoadIdentity();
|
|
||||||
renderer.TranslateMatrix({ 0, 0, -1.0f * Environment::zoom });
|
|
||||||
renderer.TranslateMatrix(particle.position);
|
|
||||||
renderer.ScaleMatrix(particle.scale);
|
|
||||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
|
||||||
renderer.DrawVertexRenderStruct(sparkQuad);
|
|
||||||
renderer.PopMatrix();
|
|
||||||
}
|
|
||||||
renderer.PopProjectionMatrix();
|
|
||||||
renderer.DisableVertexAttribArray(vPositionName);
|
|
||||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
|
||||||
renderer.shaderManager.PopShader();
|
|
||||||
CheckGlError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::drawShip()
|
|
||||||
{
|
|
||||||
static const std::string defaultShaderName = "default";
|
|
||||||
static const std::string envShaderName = "env";
|
|
||||||
static const std::string vPositionName = "vPosition";
|
|
||||||
static const std::string vTexCoordName = "vTexCoord";
|
|
||||||
static const std::string textureUniformName = "Texture";
|
|
||||||
|
|
||||||
renderer.shaderManager.PushShader(defaultShaderName);
|
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
|
||||||
renderer.EnableVertexAttribArray(vPositionName);
|
|
||||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
|
||||||
|
|
||||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
|
||||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
|
||||||
1, 1000);
|
|
||||||
renderer.PushMatrix();
|
|
||||||
|
|
||||||
renderer.LoadIdentity();
|
|
||||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
|
||||||
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
|
||||||
renderer.DrawVertexRenderStruct(spaceship);
|
|
||||||
|
|
||||||
drawEffects();
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
|
||||||
renderer.PopProjectionMatrix();
|
|
||||||
renderer.DisableVertexAttribArray(vPositionName);
|
|
||||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
|
||||||
|
|
||||||
renderer.shaderManager.PopShader();
|
|
||||||
CheckGlError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::drawBoxes()
|
cubemap.data = ZL::CreateCubemap(500);
|
||||||
{
|
cubemap.RefreshVBO();
|
||||||
static const std::string defaultShaderName = "default";
|
|
||||||
static const std::string envShaderName = "env";
|
|
||||||
static const std::string vPositionName = "vPosition";
|
|
||||||
static const std::string vTexCoordName = "vTexCoord";
|
|
||||||
static const std::string textureUniformName = "Texture";
|
|
||||||
|
|
||||||
renderer.shaderManager.PushShader(defaultShaderName);
|
//Load texture
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/DefaultMaterial_BaseColor.png", CONST_ZIP_FILE));
|
||||||
renderer.EnableVertexAttribArray(vPositionName);
|
spaceshipBase = LoadFromTextFile02("./resources/spaceship005.txt", CONST_ZIP_FILE);
|
||||||
renderer.EnableVertexAttribArray(vTexCoordName);
|
spaceshipBase.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundY(M_PI / 2.0)));
|
||||||
|
//spaceshipBase.Move(Vector3f{ -0.52998, -13, 0 });
|
||||||
|
spaceshipBase.Move(Vector3f{ -0.52998, -10, 10 });
|
||||||
|
|
||||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
spaceship.AssignFrom(spaceshipBase);
|
||||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
spaceship.RefreshVBO();
|
||||||
1, 1000);
|
|
||||||
|
|
||||||
for (int i = 0; i < boxCoordsArr.size(); i++)
|
//Boxes
|
||||||
{
|
boxTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/box/box.png", CONST_ZIP_FILE));
|
||||||
renderer.PushMatrix();
|
boxBase = LoadFromTextFile02("./resources/box/box.txt", CONST_ZIP_FILE);
|
||||||
|
|
||||||
renderer.LoadIdentity();
|
boxCoordsArr = generateRandomBoxCoords(50);
|
||||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
|
||||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
|
||||||
renderer.TranslateMatrix(-Environment::shipPosition);
|
|
||||||
renderer.TranslateMatrix(boxCoordsArr[i].pos);
|
|
||||||
renderer.RotateMatrix(boxCoordsArr[i].m);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, boxTexture->getTexID());
|
boxRenderArr.resize(boxCoordsArr.size());
|
||||||
renderer.DrawVertexRenderStruct(boxRenderArr[i]);
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
for (int i = 0; i < boxCoordsArr.size(); i++)
|
||||||
}
|
{
|
||||||
renderer.PopProjectionMatrix();
|
boxRenderArr[i].AssignFrom(boxBase);
|
||||||
renderer.DisableVertexAttribArray(vPositionName);
|
boxRenderArr[i].RefreshVBO();
|
||||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
}
|
||||||
|
|
||||||
renderer.shaderManager.PopShader();
|
sparkTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/spark.png", CONST_ZIP_FILE));
|
||||||
CheckGlError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::drawScene() {
|
sparkQuad.data = CreateRect2D({ 0, 0 }, { 0.08f, 0.08f }, 0);
|
||||||
static const std::string defaultShaderName = "default";
|
sparkQuad.RefreshVBO();
|
||||||
static const std::string envShaderName = "env";
|
|
||||||
static const std::string vPositionName = "vPosition";
|
renderer.InitOpenGL();
|
||||||
static const std::string vTexCoordName = "vTexCoord";
|
|
||||||
static const std::string textureUniformName = "Texture";
|
}
|
||||||
|
|
||||||
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
|
void Game::drawCubemap()
|
||||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
{
|
||||||
|
static const std::string defaultShaderName = "default";
|
||||||
glViewport(0, 0, Environment::width, Environment::height);
|
static const std::string envShaderName = "env";
|
||||||
|
static const std::string vPositionName = "vPosition";
|
||||||
CheckGlError();
|
static const std::string vTexCoordName = "vTexCoord";
|
||||||
|
static const std::string textureUniformName = "Texture";
|
||||||
drawCubemap();
|
|
||||||
drawShip();
|
renderer.shaderManager.PushShader(envShaderName);
|
||||||
drawBoxes();
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
|
renderer.EnableVertexAttribArray(vPositionName);
|
||||||
CheckGlError();
|
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||||
}
|
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||||
|
1, 1000);
|
||||||
void Game::processTickCount() {
|
renderer.PushMatrix();
|
||||||
|
renderer.LoadIdentity();
|
||||||
if (lastTickCount == 0) {
|
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||||
lastTickCount = SDL_GetTicks64();
|
|
||||||
return;
|
CheckGlError();
|
||||||
}
|
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture->getTexID());
|
||||||
newTickCount = SDL_GetTicks64();
|
renderer.DrawVertexRenderStruct(cubemap);
|
||||||
if (newTickCount - lastTickCount > CONST_TIMER_INTERVAL) {
|
|
||||||
size_t delta = (newTickCount - lastTickCount > CONST_MAX_TIME_INTERVAL) ?
|
CheckGlError();
|
||||||
CONST_MAX_TIME_INTERVAL : newTickCount - lastTickCount;
|
|
||||||
|
|
||||||
//gameObjects.updateScene(delta);
|
renderer.PopMatrix();
|
||||||
sparkEmitter.update(static_cast<float>(delta));
|
renderer.PopProjectionMatrix();
|
||||||
|
renderer.DisableVertexAttribArray(vPositionName);
|
||||||
if (Environment::tapDownHold) {
|
|
||||||
|
renderer.shaderManager.PopShader();
|
||||||
float diffx = Environment::tapDownCurrentPos.v[0] - Environment::tapDownStartPos.v[0];
|
CheckGlError();
|
||||||
float diffy = Environment::tapDownCurrentPos.v[1] - Environment::tapDownStartPos.v[1];
|
}
|
||||||
|
|
||||||
|
void Game::drawEffects()
|
||||||
if (abs(diffy) > 5.0 || abs(diffx) > 5.0) //threshold
|
{
|
||||||
{
|
if (sparkEmitter.getActiveParticleCount() == 0) {
|
||||||
|
return;
|
||||||
float rotationPower = sqrtf(diffx * diffx + diffy * diffy);
|
}
|
||||||
|
|
||||||
//std::cout << rotationPower << std::endl;
|
sparkQuad.data.PositionData.clear();
|
||||||
|
sparkQuad.data.TexCoordData.clear();
|
||||||
float deltaAlpha = rotationPower * delta * M_PI / 500000.f;
|
|
||||||
|
const auto& particles = sparkEmitter.getParticles();
|
||||||
Vector3f rotationDirection = { diffy, diffx, 0 };
|
for (const auto& particle : particles) {
|
||||||
|
if (!particle.active) continue;
|
||||||
rotationDirection = rotationDirection.normalized();
|
|
||||||
|
Vector3f pos = particle.position;
|
||||||
Vector4f rotateQuat = {
|
float size = 0.04f * particle.scale;
|
||||||
rotationDirection.v[0] * sin(deltaAlpha * 0.5f),
|
|
||||||
rotationDirection.v[1] * sin(deltaAlpha * 0.5f),
|
sparkQuad.data.PositionData.push_back({ pos.v[0] - size, pos.v[1] - size, pos.v[2] });
|
||||||
rotationDirection.v[2] * sin(deltaAlpha * 0.5f),
|
sparkQuad.data.TexCoordData.push_back({ 0.0f, 0.0f });
|
||||||
cos(deltaAlpha * 0.5f) };
|
|
||||||
|
sparkQuad.data.PositionData.push_back({ pos.v[0] - size, pos.v[1] + size, pos.v[2] });
|
||||||
Matrix3f rotateMat = QuatToMatrix(rotateQuat);
|
sparkQuad.data.TexCoordData.push_back({ 0.0f, 1.0f });
|
||||||
|
|
||||||
Environment::shipMatrix = MultMatrixMatrix(Environment::shipMatrix, rotateMat);
|
sparkQuad.data.PositionData.push_back({ pos.v[0] + size, pos.v[1] + size, pos.v[2] });
|
||||||
Environment::inverseShipMatrix = InverseMatrix(Environment::shipMatrix);
|
sparkQuad.data.TexCoordData.push_back({ 1.0f, 1.0f });
|
||||||
|
|
||||||
}
|
sparkQuad.data.PositionData.push_back({ pos.v[0] - size, pos.v[1] - size, pos.v[2] });
|
||||||
}
|
sparkQuad.data.TexCoordData.push_back({ 0.0f, 0.0f });
|
||||||
|
|
||||||
if (fabs(Environment::shipVelocity) > 0.01f)
|
sparkQuad.data.PositionData.push_back({ pos.v[0] + size, pos.v[1] + size, pos.v[2] });
|
||||||
{
|
sparkQuad.data.TexCoordData.push_back({ 1.0f, 1.0f });
|
||||||
Vector3f velocityDirection = { 0,0, -Environment::shipVelocity*delta / 1000.f };
|
|
||||||
Vector3f velocityDirectionAdjusted = MultMatrixVector(Environment::shipMatrix, velocityDirection);
|
sparkQuad.data.PositionData.push_back({ pos.v[0] + size, pos.v[1] - size, pos.v[2] });
|
||||||
|
sparkQuad.data.TexCoordData.push_back({ 1.0f, 0.0f });
|
||||||
Environment::shipPosition = Environment::shipPosition + velocityDirectionAdjusted;
|
}
|
||||||
}
|
|
||||||
|
if (sparkQuad.data.PositionData.empty()) return;
|
||||||
lastTickCount = newTickCount;
|
|
||||||
}
|
sparkQuad.RefreshVBO();
|
||||||
}
|
|
||||||
|
static const std::string defaultShaderName = "default";
|
||||||
void Game::render() {
|
static const std::string vPositionName = "vPosition";
|
||||||
SDL_GL_MakeCurrent(ZL::Environment::window, glContext);
|
static const std::string vTexCoordName = "vTexCoord";
|
||||||
ZL::CheckGlError();
|
static const std::string textureUniformName = "Texture";
|
||||||
|
|
||||||
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
|
renderer.shaderManager.PushShader(defaultShaderName);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
|
renderer.EnableVertexAttribArray(vPositionName);
|
||||||
drawScene();
|
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||||
processTickCount();
|
|
||||||
|
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||||
SDL_GL_SwapWindow(ZL::Environment::window);
|
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||||
}
|
1, 1000);
|
||||||
void Game::update() {
|
|
||||||
SDL_Event event;
|
glBindTexture(GL_TEXTURE_2D, sparkTexture->getTexID());
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
if (event.type == SDL_QUIT) {
|
renderer.PushMatrix();
|
||||||
Environment::exitGameLoop = true;
|
renderer.LoadIdentity();
|
||||||
|
renderer.TranslateMatrix({ 0, 0, -1.0f * Environment::zoom });
|
||||||
}
|
|
||||||
else if (event.type == SDL_MOUSEBUTTONDOWN) {
|
renderer.DrawVertexRenderStruct(sparkQuad);
|
||||||
// 1. Îáðàáîòêà íàæàòèÿ êíîïêè ìûøè
|
|
||||||
Environment::tapDownHold = true;
|
renderer.PopMatrix();
|
||||||
// Êîîðäèíàòû íà÷àëüíîãî íàæàòèÿ
|
renderer.PopProjectionMatrix();
|
||||||
Environment::tapDownStartPos.v[0] = event.button.x;
|
renderer.DisableVertexAttribArray(vPositionName);
|
||||||
Environment::tapDownStartPos.v[1] = event.button.y;
|
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||||
// Íà÷àëüíàÿ ïîçèöèÿ òàêæå ñòàíîâèòñÿ òåêóùåé
|
renderer.shaderManager.PopShader();
|
||||||
Environment::tapDownCurrentPos.v[0] = event.button.x;
|
CheckGlError();
|
||||||
Environment::tapDownCurrentPos.v[1] = event.button.y;
|
}
|
||||||
}
|
|
||||||
else if (event.type == SDL_MOUSEBUTTONUP) {
|
void Game::drawShip()
|
||||||
// 2. Îáðàáîòêà îòïóñêàíèÿ êíîïêè ìûøè
|
{
|
||||||
Environment::tapDownHold = false;
|
static const std::string defaultShaderName = "default";
|
||||||
}
|
static const std::string envShaderName = "env";
|
||||||
else if (event.type == SDL_MOUSEMOTION) {
|
static const std::string vPositionName = "vPosition";
|
||||||
// 3. Îáðàáîòêà ïåðåìåùåíèÿ ìûøè
|
static const std::string vTexCoordName = "vTexCoord";
|
||||||
if (Environment::tapDownHold) {
|
static const std::string textureUniformName = "Texture";
|
||||||
// Îáíîâëåíèå òåêóùåé ïîçèöèè, åñëè êíîïêà óäåðæèâàåòñÿ
|
|
||||||
Environment::tapDownCurrentPos.v[0] = event.motion.x;
|
renderer.shaderManager.PushShader(defaultShaderName);
|
||||||
Environment::tapDownCurrentPos.v[1] = event.motion.y;
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
}
|
renderer.EnableVertexAttribArray(vPositionName);
|
||||||
}
|
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||||
else if (event.type == SDL_MOUSEWHEEL) {
|
|
||||||
static const float zoomstep = 2.0f;
|
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||||
if (event.wheel.y > 0) {
|
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||||
Environment::zoom -= zoomstep;
|
1, 1000);
|
||||||
}
|
renderer.PushMatrix();
|
||||||
else if (event.wheel.y < 0) {
|
|
||||||
Environment::zoom += zoomstep;
|
renderer.LoadIdentity();
|
||||||
}
|
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||||
if (Environment::zoom < zoomstep) {
|
|
||||||
Environment::zoom = zoomstep;
|
|
||||||
}
|
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
||||||
}
|
renderer.DrawVertexRenderStruct(spaceship);
|
||||||
else if (event.type == SDL_KEYUP)
|
|
||||||
{
|
drawEffects();
|
||||||
if (event.key.keysym.sym == SDLK_i)
|
|
||||||
{
|
renderer.PopMatrix();
|
||||||
Environment::shipVelocity += 1.f;
|
renderer.PopProjectionMatrix();
|
||||||
}
|
renderer.DisableVertexAttribArray(vPositionName);
|
||||||
if (event.key.keysym.sym == SDLK_k)
|
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||||
{
|
|
||||||
Environment::shipVelocity -= 1.f;
|
renderer.shaderManager.PopShader();
|
||||||
}
|
CheckGlError();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
render();
|
void Game::drawBoxes()
|
||||||
}
|
{
|
||||||
|
static const std::string defaultShaderName = "default";
|
||||||
|
static const std::string envShaderName = "env";
|
||||||
|
static const std::string vPositionName = "vPosition";
|
||||||
|
static const std::string vTexCoordName = "vTexCoord";
|
||||||
|
static const std::string textureUniformName = "Texture";
|
||||||
|
|
||||||
|
renderer.shaderManager.PushShader(defaultShaderName);
|
||||||
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
|
renderer.EnableVertexAttribArray(vPositionName);
|
||||||
|
renderer.EnableVertexAttribArray(vTexCoordName);
|
||||||
|
|
||||||
|
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||||
|
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||||
|
1, 1000);
|
||||||
|
|
||||||
|
for (int i = 0; i < boxCoordsArr.size(); i++)
|
||||||
|
{
|
||||||
|
renderer.PushMatrix();
|
||||||
|
|
||||||
|
renderer.LoadIdentity();
|
||||||
|
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||||
|
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||||
|
renderer.TranslateMatrix(-Environment::shipPosition);
|
||||||
|
renderer.TranslateMatrix(boxCoordsArr[i].pos);
|
||||||
|
renderer.RotateMatrix(boxCoordsArr[i].m);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, boxTexture->getTexID());
|
||||||
|
renderer.DrawVertexRenderStruct(boxRenderArr[i]);
|
||||||
|
|
||||||
|
renderer.PopMatrix();
|
||||||
|
}
|
||||||
|
renderer.PopProjectionMatrix();
|
||||||
|
renderer.DisableVertexAttribArray(vPositionName);
|
||||||
|
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||||
|
|
||||||
|
renderer.shaderManager.PopShader();
|
||||||
|
CheckGlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::drawScene() {
|
||||||
|
static const std::string defaultShaderName = "default";
|
||||||
|
static const std::string envShaderName = "env";
|
||||||
|
static const std::string vPositionName = "vPosition";
|
||||||
|
static const std::string vTexCoordName = "vTexCoord";
|
||||||
|
static const std::string textureUniformName = "Texture";
|
||||||
|
|
||||||
|
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glViewport(0, 0, Environment::width, Environment::height);
|
||||||
|
|
||||||
|
CheckGlError();
|
||||||
|
|
||||||
|
drawCubemap();
|
||||||
|
drawShip();
|
||||||
|
drawBoxes();
|
||||||
|
|
||||||
|
CheckGlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::processTickCount() {
|
||||||
|
|
||||||
|
if (lastTickCount == 0) {
|
||||||
|
lastTickCount = SDL_GetTicks64();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
newTickCount = SDL_GetTicks64();
|
||||||
|
if (newTickCount - lastTickCount > CONST_TIMER_INTERVAL) {
|
||||||
|
size_t delta = (newTickCount - lastTickCount > CONST_MAX_TIME_INTERVAL) ?
|
||||||
|
CONST_MAX_TIME_INTERVAL : newTickCount - lastTickCount;
|
||||||
|
|
||||||
|
//gameObjects.updateScene(delta);
|
||||||
|
sparkEmitter.update(static_cast<float>(delta));
|
||||||
|
|
||||||
|
if (Environment::tapDownHold) {
|
||||||
|
|
||||||
|
float diffx = Environment::tapDownCurrentPos.v[0] - Environment::tapDownStartPos.v[0];
|
||||||
|
float diffy = Environment::tapDownCurrentPos.v[1] - Environment::tapDownStartPos.v[1];
|
||||||
|
|
||||||
|
|
||||||
|
if (abs(diffy) > 5.0 || abs(diffx) > 5.0) //threshold
|
||||||
|
{
|
||||||
|
|
||||||
|
float rotationPower = sqrtf(diffx * diffx + diffy * diffy);
|
||||||
|
|
||||||
|
//std::cout << rotationPower << std::endl;
|
||||||
|
|
||||||
|
float deltaAlpha = rotationPower * delta * M_PI / 500000.f;
|
||||||
|
|
||||||
|
Vector3f rotationDirection = { diffy, diffx, 0 };
|
||||||
|
|
||||||
|
rotationDirection = rotationDirection.normalized();
|
||||||
|
|
||||||
|
Vector4f rotateQuat = {
|
||||||
|
rotationDirection.v[0] * sin(deltaAlpha * 0.5f),
|
||||||
|
rotationDirection.v[1] * sin(deltaAlpha * 0.5f),
|
||||||
|
rotationDirection.v[2] * sin(deltaAlpha * 0.5f),
|
||||||
|
cos(deltaAlpha * 0.5f) };
|
||||||
|
|
||||||
|
Matrix3f rotateMat = QuatToMatrix(rotateQuat);
|
||||||
|
|
||||||
|
Environment::shipMatrix = MultMatrixMatrix(Environment::shipMatrix, rotateMat);
|
||||||
|
Environment::inverseShipMatrix = InverseMatrix(Environment::shipMatrix);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fabs(Environment::shipVelocity) > 0.01f)
|
||||||
|
{
|
||||||
|
Vector3f velocityDirection = { 0,0, -Environment::shipVelocity * delta / 1000.f };
|
||||||
|
Vector3f velocityDirectionAdjusted = MultMatrixVector(Environment::shipMatrix, velocityDirection);
|
||||||
|
|
||||||
|
Environment::shipPosition = Environment::shipPosition + velocityDirectionAdjusted;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTickCount = newTickCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::render() {
|
||||||
|
SDL_GL_MakeCurrent(ZL::Environment::window, glContext);
|
||||||
|
ZL::CheckGlError();
|
||||||
|
|
||||||
|
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
drawScene();
|
||||||
|
processTickCount();
|
||||||
|
|
||||||
|
SDL_GL_SwapWindow(ZL::Environment::window);
|
||||||
|
}
|
||||||
|
void Game::update() {
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
if (event.type == SDL_QUIT) {
|
||||||
|
Environment::exitGameLoop = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
// 1. Îáðàáîòêà íàæàòèÿ êíîïêè ìûøè
|
||||||
|
Environment::tapDownHold = true;
|
||||||
|
// Êîîðäèíàòû íà÷àëüíîãî íàæàòèÿ
|
||||||
|
Environment::tapDownStartPos.v[0] = event.button.x;
|
||||||
|
Environment::tapDownStartPos.v[1] = event.button.y;
|
||||||
|
// Íà÷àëüíàÿ ïîçèöèÿ òàêæå ñòàíîâèòñÿ òåêóùåé
|
||||||
|
Environment::tapDownCurrentPos.v[0] = event.button.x;
|
||||||
|
Environment::tapDownCurrentPos.v[1] = event.button.y;
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEBUTTONUP) {
|
||||||
|
// 2. Îáðàáîòêà îòïóñêàíèÿ êíîïêè ìûøè
|
||||||
|
Environment::tapDownHold = false;
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEMOTION) {
|
||||||
|
// 3. Îáðàáîòêà ïåðåìåùåíèÿ ìûøè
|
||||||
|
if (Environment::tapDownHold) {
|
||||||
|
// Îáíîâëåíèå òåêóùåé ïîçèöèè, åñëè êíîïêà óäåðæèâàåòñÿ
|
||||||
|
Environment::tapDownCurrentPos.v[0] = event.motion.x;
|
||||||
|
Environment::tapDownCurrentPos.v[1] = event.motion.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_MOUSEWHEEL) {
|
||||||
|
static const float zoomstep = 2.0f;
|
||||||
|
if (event.wheel.y > 0) {
|
||||||
|
Environment::zoom -= zoomstep;
|
||||||
|
}
|
||||||
|
else if (event.wheel.y < 0) {
|
||||||
|
Environment::zoom += zoomstep;
|
||||||
|
}
|
||||||
|
if (Environment::zoom < zoomstep) {
|
||||||
|
Environment::zoom = zoomstep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.type == SDL_KEYUP)
|
||||||
|
{
|
||||||
|
if (event.key.keysym.sym == SDLK_i)
|
||||||
|
{
|
||||||
|
Environment::shipVelocity += 1.f;
|
||||||
|
}
|
||||||
|
if (event.key.keysym.sym == SDLK_k)
|
||||||
|
{
|
||||||
|
Environment::shipVelocity -= 1.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
82
Game.h
82
Game.h
@ -9,59 +9,59 @@
|
|||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
|
|
||||||
struct BoxCoords
|
struct BoxCoords
|
||||||
{
|
{
|
||||||
Vector3f pos;
|
Vector3f pos;
|
||||||
Matrix3f m;
|
Matrix3f m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
~Game();
|
~Game();
|
||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
void update();
|
void update();
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
bool shouldExit() const { return Environment::exitGameLoop; }
|
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processTickCount();
|
void processTickCount();
|
||||||
void drawScene();
|
void drawScene();
|
||||||
void drawCubemap();
|
void drawCubemap();
|
||||||
void drawEffects();
|
void drawEffects();
|
||||||
void drawShip();
|
void drawShip();
|
||||||
void drawBoxes();
|
void drawBoxes();
|
||||||
|
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_GLContext glContext;
|
SDL_GLContext glContext;
|
||||||
Renderer renderer;
|
Renderer renderer;
|
||||||
|
|
||||||
size_t newTickCount;
|
size_t newTickCount;
|
||||||
size_t lastTickCount;
|
size_t lastTickCount;
|
||||||
|
|
||||||
static const size_t CONST_TIMER_INTERVAL = 10;
|
static const size_t CONST_TIMER_INTERVAL = 10;
|
||||||
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
||||||
|
|
||||||
std::shared_ptr<Texture> sparkTexture;
|
std::shared_ptr<Texture> sparkTexture;
|
||||||
std::shared_ptr<Texture> spaceshipTexture;
|
std::shared_ptr<Texture> spaceshipTexture;
|
||||||
std::shared_ptr<Texture> cubemapTexture;
|
std::shared_ptr<Texture> cubemapTexture;
|
||||||
VertexDataStruct spaceshipBase;
|
VertexDataStruct spaceshipBase;
|
||||||
VertexRenderStruct spaceship;
|
VertexRenderStruct spaceship;
|
||||||
|
|
||||||
VertexRenderStruct cubemap;
|
VertexRenderStruct cubemap;
|
||||||
|
|
||||||
std::shared_ptr<Texture> boxTexture;
|
std::shared_ptr<Texture> boxTexture;
|
||||||
VertexDataStruct boxBase;
|
VertexDataStruct boxBase;
|
||||||
|
|
||||||
std::vector<BoxCoords> boxCoordsArr;
|
std::vector<BoxCoords> boxCoordsArr;
|
||||||
std::vector<VertexRenderStruct> boxRenderArr;
|
std::vector<VertexRenderStruct> boxRenderArr;
|
||||||
|
|
||||||
//VertexRenderStruct singleSpark;
|
//VertexRenderStruct singleSpark;
|
||||||
SparkEmitter sparkEmitter;
|
SparkEmitter sparkEmitter;
|
||||||
VertexRenderStruct sparkQuad;
|
VertexRenderStruct sparkQuad;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
296
SparkEmitter.cpp
296
SparkEmitter.cpp
@ -5,143 +5,207 @@
|
|||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
SparkEmitter::SparkEmitter()
|
SparkEmitter::SparkEmitter()
|
||||||
: emissionRate(100.0f), isActive(true) {
|
: emissionRate(100.0f), isActive(true), buffersDirty(true), maxParticles(200) {
|
||||||
particles.resize(200);
|
particles.resize(maxParticles);
|
||||||
lastEmissionTime = std::chrono::steady_clock::now();
|
positionBuffer.resize(maxParticles * 4, 0.0f);
|
||||||
}
|
texCoordBuffer.resize(maxParticles * 2, 0.0f);
|
||||||
|
lastEmissionTime = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
SparkEmitter::SparkEmitter(const std::vector<Vector3f>& positions, float rate)
|
SparkEmitter::SparkEmitter(const std::vector<Vector3f>& positions, float rate)
|
||||||
: emissionPoints(positions), emissionRate(rate), isActive(true) {
|
: emissionPoints(positions), emissionRate(rate), isActive(true),
|
||||||
particles.resize(positions.size() * 100);
|
buffersDirty(true), maxParticles(positions.size() * 100) {
|
||||||
lastEmissionTime = std::chrono::steady_clock::now();
|
particles.resize(maxParticles);
|
||||||
}
|
positionBuffer.resize(maxParticles * 4, 0.0f);
|
||||||
|
texCoordBuffer.resize(maxParticles * 2, 0.0f);
|
||||||
|
lastEmissionTime = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
void SparkEmitter::setEmissionPoints(const std::vector<Vector3f>& positions) {
|
void SparkEmitter::setEmissionPoints(const std::vector<Vector3f>& positions) {
|
||||||
emissionPoints = positions;
|
emissionPoints = positions;
|
||||||
particles.resize(positions.size() * 100);
|
maxParticles = positions.size() * 100;
|
||||||
}
|
particles.resize(maxParticles);
|
||||||
|
positionBuffer.resize(maxParticles * 4, 0.0f);
|
||||||
|
texCoordBuffer.resize(maxParticles * 2, 0.0f);
|
||||||
|
buffersDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
void SparkEmitter::setEmissionRate(float rateMs) {
|
void SparkEmitter::updateBuffers() {
|
||||||
emissionRate = rateMs;
|
if (!buffersDirty) return;
|
||||||
}
|
|
||||||
|
|
||||||
void SparkEmitter::setActive(bool active) {
|
size_t bufferIndex = 0;
|
||||||
isActive = active;
|
for (const auto& particle : particles) {
|
||||||
}
|
if (particle.active) {
|
||||||
|
positionBuffer[bufferIndex * 4] = particle.position.v[0];
|
||||||
|
positionBuffer[bufferIndex * 4 + 1] = particle.position.v[1];
|
||||||
|
positionBuffer[bufferIndex * 4 + 2] = particle.position.v[2];
|
||||||
|
positionBuffer[bufferIndex * 4 + 3] = particle.scale;
|
||||||
|
|
||||||
void SparkEmitter::update(float deltaTimeMs) {
|
texCoordBuffer[bufferIndex * 2] = 0.0f;
|
||||||
auto currentTime = std::chrono::steady_clock::now();
|
texCoordBuffer[bufferIndex * 2 + 1] = 0.0f;
|
||||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
||||||
currentTime - lastEmissionTime).count();
|
|
||||||
|
|
||||||
if (isActive && elapsed >= emissionRate) {
|
bufferIndex++;
|
||||||
emit();
|
}
|
||||||
lastEmissionTime = currentTime;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& particle : particles) {
|
for (size_t i = bufferIndex; i < maxParticles; i++) {
|
||||||
if (particle.active) {
|
positionBuffer[i * 4] = 0.0f;
|
||||||
particle.position.v[0] += particle.velocity.v[0] * deltaTimeMs / 1000.0f;
|
positionBuffer[i * 4 + 1] = 0.0f;
|
||||||
particle.position.v[1] += particle.velocity.v[1] * deltaTimeMs / 1000.0f;
|
positionBuffer[i * 4 + 2] = 0.0f;
|
||||||
particle.position.v[2] += particle.velocity.v[2] * deltaTimeMs / 1000.0f;
|
positionBuffer[i * 4 + 3] = 0.0f;
|
||||||
|
texCoordBuffer[i * 2] = 0.0f;
|
||||||
|
texCoordBuffer[i * 2 + 1] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
particle.lifeTime += deltaTimeMs;
|
buffersDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (particle.lifeTime >= particle.maxLifeTime) {
|
void SparkEmitter::update(float deltaTimeMs) {
|
||||||
particle.active = false;
|
auto currentTime = std::chrono::steady_clock::now();
|
||||||
}
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
currentTime - lastEmissionTime).count();
|
||||||
|
|
||||||
float lifeRatio = particle.lifeTime / particle.maxLifeTime;
|
if (isActive && elapsed >= emissionRate) {
|
||||||
particle.scale = 1.0f - lifeRatio * 0.8f;
|
emit();
|
||||||
}
|
lastEmissionTime = currentTime;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void SparkEmitter::emit() {
|
bool anyChanged = false;
|
||||||
if (emissionPoints.empty()) return;
|
for (auto& particle : particles) {
|
||||||
|
if (particle.active) {
|
||||||
|
Vector3f oldPosition = particle.position;
|
||||||
|
|
||||||
for (int i = 0; i < emissionPoints.size(); ++i) {
|
particle.position.v[0] += particle.velocity.v[0] * deltaTimeMs / 1000.0f;
|
||||||
bool particleFound = false;
|
particle.position.v[1] += particle.velocity.v[1] * deltaTimeMs / 1000.0f;
|
||||||
|
particle.position.v[2] += particle.velocity.v[2] * deltaTimeMs / 1000.0f;
|
||||||
|
|
||||||
for (auto& particle : particles) {
|
particle.lifeTime += deltaTimeMs;
|
||||||
if (!particle.active) {
|
|
||||||
initParticle(particle, i);
|
|
||||||
particle.active = true;
|
|
||||||
particle.lifeTime = 0;
|
|
||||||
particle.position = emissionPoints[i];
|
|
||||||
particle.emitterIndex = i;
|
|
||||||
particleFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!particleFound && !particles.empty()) {
|
if (particle.lifeTime >= particle.maxLifeTime) {
|
||||||
size_t oldestIndex = 0;
|
particle.active = false;
|
||||||
float maxLifeTime = 0;
|
anyChanged = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float lifeRatio = particle.lifeTime / particle.maxLifeTime;
|
||||||
|
particle.scale = 1.0f - lifeRatio * 0.8f;
|
||||||
|
|
||||||
for (size_t j = 0; j < particles.size(); ++j) {
|
if (oldPosition.v[0] != particle.position.v[0] ||
|
||||||
if (particles[j].lifeTime > maxLifeTime) {
|
oldPosition.v[1] != particle.position.v[1] ||
|
||||||
maxLifeTime = particles[j].lifeTime;
|
oldPosition.v[2] != particle.position.v[2]) {
|
||||||
oldestIndex = j;
|
anyChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
initParticle(particles[oldestIndex], i);
|
if (anyChanged) {
|
||||||
particles[oldestIndex].active = true;
|
buffersDirty = true;
|
||||||
particles[oldestIndex].lifeTime = 0;
|
}
|
||||||
particles[oldestIndex].position = emissionPoints[i];
|
}
|
||||||
particles[oldestIndex].emitterIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SparkEmitter::initParticle(SparkParticle& particle, int emitterIndex) {
|
void SparkEmitter::emit() {
|
||||||
particle.velocity = getRandomVelocity(emitterIndex);
|
if (emissionPoints.empty()) return;
|
||||||
particle.scale = 1.0f;
|
bool emitted = false;
|
||||||
particle.maxLifeTime = 800.0f + (rand() % 400); // От 800 до 1200 мс
|
|
||||||
particle.emitterIndex = emitterIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3f SparkEmitter::getRandomVelocity(int emitterIndex) {
|
for (int i = 0; i < emissionPoints.size(); ++i) {
|
||||||
static std::random_device rd;
|
bool particleFound = false;
|
||||||
static std::mt19937 gen(rd());
|
|
||||||
static std::uniform_real_distribution<> angleDist(0, 2 * M_PI);
|
|
||||||
static std::uniform_real_distribution<> speedDist(0.5f, 2.0f);
|
|
||||||
static std::uniform_real_distribution<> zSpeedDist(1.0f, 3.0f);
|
|
||||||
|
|
||||||
float angle = angleDist(gen);
|
for (auto& particle : particles) {
|
||||||
float speed = speedDist(gen);
|
if (!particle.active) {
|
||||||
float zSpeed = zSpeedDist(gen);
|
initParticle(particle, i);
|
||||||
|
particle.active = true;
|
||||||
|
particle.lifeTime = 0;
|
||||||
|
particle.position = emissionPoints[i];
|
||||||
|
particle.emitterIndex = i;
|
||||||
|
particleFound = true;
|
||||||
|
emitted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (emitterIndex == 0) {
|
if (!particleFound && !particles.empty()) {
|
||||||
return Vector3f{
|
size_t oldestIndex = 0;
|
||||||
cosf(angle) * speed - 0.3f,
|
float maxLifeTime = 0;
|
||||||
sinf(angle) * speed,
|
|
||||||
zSpeed
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Vector3f{
|
|
||||||
cosf(angle) * speed + 0.3f,
|
|
||||||
sinf(angle) * speed,
|
|
||||||
zSpeed
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<SparkParticle>& SparkEmitter::getParticles() const {
|
for (size_t j = 0; j < particles.size(); ++j) {
|
||||||
return particles;
|
if (particles[j].lifeTime > maxLifeTime) {
|
||||||
}
|
maxLifeTime = particles[j].lifeTime;
|
||||||
|
oldestIndex = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t SparkEmitter::getActiveParticleCount() const {
|
initParticle(particles[oldestIndex], i);
|
||||||
size_t count = 0;
|
particles[oldestIndex].active = true;
|
||||||
for (const auto& particle : particles) {
|
particles[oldestIndex].lifeTime = 0;
|
||||||
if (particle.active) {
|
particles[oldestIndex].position = emissionPoints[i];
|
||||||
count++;
|
particles[oldestIndex].emitterIndex = i;
|
||||||
}
|
emitted = true;
|
||||||
}
|
}
|
||||||
return count;
|
}
|
||||||
}
|
|
||||||
|
if (emitted) {
|
||||||
|
buffersDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SparkEmitter::initParticle(SparkParticle& particle, int emitterIndex) {
|
||||||
|
particle.velocity = getRandomVelocity(emitterIndex);
|
||||||
|
particle.scale = 1.0f;
|
||||||
|
particle.maxLifeTime = 800.0f + (rand() % 400);
|
||||||
|
particle.emitterIndex = emitterIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3f SparkEmitter::getRandomVelocity(int emitterIndex) {
|
||||||
|
static std::random_device rd;
|
||||||
|
static std::mt19937 gen(rd());
|
||||||
|
static std::uniform_real_distribution<> angleDist(0, 2 * M_PI);
|
||||||
|
static std::uniform_real_distribution<> speedDist(0.5f, 2.0f);
|
||||||
|
static std::uniform_real_distribution<> zSpeedDist(1.0f, 3.0f);
|
||||||
|
|
||||||
|
float angle = angleDist(gen);
|
||||||
|
float speed = speedDist(gen);
|
||||||
|
float zSpeed = zSpeedDist(gen);
|
||||||
|
|
||||||
|
if (emitterIndex == 0) {
|
||||||
|
return Vector3f{
|
||||||
|
cosf(angle) * speed - 0.3f,
|
||||||
|
sinf(angle) * speed,
|
||||||
|
zSpeed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Vector3f{
|
||||||
|
cosf(angle) * speed + 0.3f,
|
||||||
|
sinf(angle) * speed,
|
||||||
|
zSpeed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SparkParticle>& SparkEmitter::getParticles() const {
|
||||||
|
return particles;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SparkEmitter::getActiveParticleCount() const {
|
||||||
|
size_t count = 0;
|
||||||
|
for (const auto& particle : particles) {
|
||||||
|
if (particle.active) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SparkEmitter::getActiveParticleBufferIndex(size_t particleIndex) const {
|
||||||
|
size_t activeIndex = 0;
|
||||||
|
for (size_t i = 0; i <= particleIndex; i++) {
|
||||||
|
if (particles[i].active) {
|
||||||
|
if (i == particleIndex) return activeIndex;
|
||||||
|
activeIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
@ -6,45 +6,56 @@
|
|||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
struct SparkParticle {
|
struct SparkParticle {
|
||||||
Vector3f position;
|
Vector3f position;
|
||||||
Vector3f velocity;
|
Vector3f velocity;
|
||||||
float scale;
|
float scale;
|
||||||
float lifeTime;
|
float lifeTime;
|
||||||
float maxLifeTime;
|
float maxLifeTime;
|
||||||
bool active;
|
bool active;
|
||||||
int emitterIndex;
|
int emitterIndex;
|
||||||
|
Vector2f texCoord;
|
||||||
|
|
||||||
SparkParticle() : position({ 0,0,0 }), velocity({ 0,0,0 }), scale(1.0f),
|
SparkParticle() : position({ 0,0,0 }), velocity({ 0,0,0 }), scale(1.0f),
|
||||||
lifeTime(0), maxLifeTime(1000.0f), active(false), emitterIndex(0) {
|
lifeTime(0), maxLifeTime(1000.0f), active(false), emitterIndex(0) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SparkEmitter {
|
class SparkEmitter {
|
||||||
private:
|
private:
|
||||||
std::vector<SparkParticle> particles;
|
std::vector<SparkParticle> particles;
|
||||||
std::vector<Vector3f> emissionPoints;
|
std::vector<Vector3f> emissionPoints;
|
||||||
std::chrono::steady_clock::time_point lastEmissionTime;
|
std::chrono::steady_clock::time_point lastEmissionTime;
|
||||||
float emissionRate;
|
float emissionRate;
|
||||||
bool isActive;
|
bool isActive;
|
||||||
|
|
||||||
public:
|
std::vector<float> positionBuffer;
|
||||||
SparkEmitter();
|
std::vector<float> texCoordBuffer;
|
||||||
SparkEmitter(const std::vector<Vector3f>& positions, float rate = 100.0f);
|
bool buffersDirty;
|
||||||
|
int maxParticles;
|
||||||
|
|
||||||
void setEmissionPoints(const std::vector<Vector3f>& positions);
|
public:
|
||||||
void setEmissionRate(float rateMs);
|
SparkEmitter();
|
||||||
void setActive(bool active);
|
SparkEmitter(const std::vector<Vector3f>& positions, float rate = 100.0f);
|
||||||
|
|
||||||
void update(float deltaTimeMs);
|
void setEmissionPoints(const std::vector<Vector3f>& positions);
|
||||||
void emit();
|
|
||||||
|
|
||||||
const std::vector<SparkParticle>& getParticles() const;
|
void update(float deltaTimeMs);
|
||||||
size_t getActiveParticleCount() const;
|
void emit();
|
||||||
|
|
||||||
private:
|
const std::vector<SparkParticle>& getParticles() const;
|
||||||
void initParticle(SparkParticle& particle, int emitterIndex);
|
size_t getActiveParticleCount() const;
|
||||||
Vector3f getRandomVelocity(int emitterIndex);
|
|
||||||
};
|
const float* getPositionBuffer() const { return positionBuffer.data(); }
|
||||||
|
const float* getTexCoordBuffer() const { return texCoordBuffer.data(); }
|
||||||
|
size_t getBufferSize() const { return positionBuffer.size() / 4; }
|
||||||
|
void updateBuffers();
|
||||||
|
|
||||||
|
size_t getActiveParticleBufferIndex(size_t particleIndex) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initParticle(SparkParticle& particle, int emitterIndex);
|
||||||
|
Vector3f getRandomVelocity(int emitterIndex);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
Loading…
Reference in New Issue
Block a user