fix some and add spaceship with shaders and textures
This commit is contained in:
parent
1c9b1b1969
commit
70db96a52e
@ -2,166 +2,247 @@
|
|||||||
#include "AnimatedModel.h"
|
#include "AnimatedModel.h"
|
||||||
#include "BoneAnimatedModel.h"
|
#include "BoneAnimatedModel.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
//#include "OpenGlExtensions.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "TextureManager.h"
|
#include "TextureManager.h"
|
||||||
#include "TextModel.h"
|
#include "TextModel.h"
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
#include <GLES2/gl2ext.h>
|
#include <GLES2/gl2ext.h>
|
||||||
|
|
||||||
namespace ZL
|
#ifdef __ANDROID__
|
||||||
{
|
#include <android/log.h>
|
||||||
const char* CONST_ZIP_FILE = "";
|
|
||||||
|
|
||||||
Game::Game()
|
|
||||||
: window(nullptr)
|
|
||||||
, glContext(nullptr)
|
|
||||||
, newTickCount(0)
|
|
||||||
, lastTickCount(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Game::~Game() {
|
|
||||||
if (glContext) {
|
|
||||||
SDL_GL_DeleteContext(glContext);
|
|
||||||
}
|
|
||||||
if (window) {
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
}
|
|
||||||
SDL_Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::setup() {
|
|
||||||
glContext = SDL_GL_CreateContext(ZL::Environment::window);
|
|
||||||
|
|
||||||
// ZL::BindOpenGlFunctions();
|
|
||||||
// ZL::CheckGlError();
|
|
||||||
|
|
||||||
// Initialize renderer
|
|
||||||
|
|
||||||
/*#ifdef EMSCRIPTEN
|
|
||||||
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);
|
|
||||||
#else
|
|
||||||
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);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Load texture
|
namespace ZL {
|
||||||
spaceshipTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sship001x.png"));
|
const char *CONST_ZIP_FILE = "";
|
||||||
spaceshipBase = LoadFromTextFile02("./resources/spaceship004.txt");
|
|
||||||
spaceshipBase.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundY(M_PI / 2.0)));
|
|
||||||
spaceship.AssignFrom(spaceshipBase);
|
|
||||||
spaceship.RefreshVBO();
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderer.InitOpenGL();
|
Game::Game()
|
||||||
|
: window(nullptr), glContext(nullptr), newTickCount(0), lastTickCount(0),
|
||||||
}
|
resourcesLoaded(false), modelLoaded(false) {
|
||||||
|
|
||||||
void Game::drawScene() {
|
|
||||||
static const std::string defaultShaderName = "default";
|
|
||||||
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();
|
|
||||||
|
|
||||||
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 });
|
|
||||||
renderer.RotateMatrix(QuatFromRotateAroundX(M_PI/6.0));
|
|
||||||
//renderer.RotateMatrix(QuatFromRotateAroundX(Environment::cameraAlpha));
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
|
||||||
renderer.DrawVertexRenderStruct(spaceship);
|
|
||||||
|
|
||||||
renderer.PopMatrix();
|
|
||||||
renderer.PopProjectionMatrix();
|
|
||||||
renderer.DisableVertexAttribArray(vPositionName);
|
|
||||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
|
||||||
|
|
||||||
renderer.shaderManager.PopShader();*/
|
|
||||||
|
|
||||||
//CheckGlError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::processTickCount() {
|
|
||||||
|
|
||||||
if (lastTickCount == 0) {
|
|
||||||
lastTickCount = SDL_GetTicks64();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newTickCount = SDL_GetTicks64();
|
Game::~Game() {
|
||||||
if (newTickCount - lastTickCount > CONST_TIMER_INTERVAL) {
|
if (glContext) {
|
||||||
size_t delta = (newTickCount - lastTickCount > CONST_MAX_TIME_INTERVAL) ?
|
SDL_GL_DeleteContext(glContext);
|
||||||
CONST_MAX_TIME_INTERVAL : newTickCount - lastTickCount;
|
|
||||||
|
|
||||||
//gameObjects.updateScene(delta);
|
|
||||||
|
|
||||||
Environment::cameraAlpha = Environment::cameraAlpha + delta * M_PI / 10000.f;
|
|
||||||
|
|
||||||
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_MOUSEWHEEL) {
|
if (window) {
|
||||||
static const float zoomstep = 2.0f;
|
SDL_DestroyWindow(window);
|
||||||
if (event.wheel.y > 0) {
|
}
|
||||||
Environment::zoom -= zoomstep;
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
else if (event.wheel.y < 0) {
|
|
||||||
Environment::zoom += zoomstep;
|
|
||||||
}
|
|
||||||
if (Environment::zoom < zoomstep) {
|
|
||||||
Environment::zoom = zoomstep;
|
|
||||||
}
|
|
||||||
/*if (Environment::zoom > 4) {
|
|
||||||
Environment::zoom = 4;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//this->modelMeshRender.data.Scale(0.5);
|
void Game::setup() {
|
||||||
//this->modelMeshRender.RefreshVBO();
|
glContext = SDL_GL_CreateContext(ZL::Environment::window);
|
||||||
|
|
||||||
|
// Initialize renderer
|
||||||
|
renderer.InitOpenGL();
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Start for Android");
|
||||||
|
|
||||||
|
const char* testFiles[] = {
|
||||||
|
"resources/spaceship004.txt",
|
||||||
|
"shaders/default.vertex",
|
||||||
|
"shaders/default_android.fragment",
|
||||||
|
"shaders/defaultColor.vertex",
|
||||||
|
"shaders/defaultColor_android.fragment",
|
||||||
|
"resources/sship001x.bmp",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; testFiles[i] != nullptr; i++) {
|
||||||
|
SDL_RWops* file = SDL_RWFromFile(testFiles[i], "rb");
|
||||||
|
if (file) {
|
||||||
|
Sint64 size = SDL_RWsize(file);
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Found: %s (size: %lld)", testFiles[i], size);
|
||||||
|
SDL_RWclose(file);
|
||||||
|
} else {
|
||||||
|
__android_log_print(ANDROID_LOG_WARN, "Game", "Not found: %s (SDL error: %s)",
|
||||||
|
testFiles[i], SDL_GetError());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Shaders...");
|
||||||
|
|
||||||
|
renderer.shaderManager.AddShaderFromFiles("default",
|
||||||
|
"shaders/default.vertex",
|
||||||
|
"shaders/default_android.fragment",
|
||||||
|
CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
renderer.shaderManager.AddShaderFromFiles("defaultColor",
|
||||||
|
"shaders/defaultColor.vertex",
|
||||||
|
"shaders/defaultColor_android.fragment",
|
||||||
|
CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Textures...");
|
||||||
|
try {
|
||||||
|
spaceshipTexture = std::make_shared<Texture>(
|
||||||
|
CreateTextureDataFromBmp32("resources/sship001x.bmp")
|
||||||
|
);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
spaceshipTexture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Model...");
|
||||||
|
|
||||||
|
std::string modelPaths[] = {
|
||||||
|
"resources/spaceship004.txt",
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
|
bool modelLoadSuccess = false;
|
||||||
|
for (int i = 0; !modelLoadSuccess && !modelPaths[i].empty(); i++) {
|
||||||
|
try {
|
||||||
|
spaceshipBase = LoadFromTextFile02(modelPaths[i]);
|
||||||
|
spaceshipBase.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundY(M_PI / 2.0)));
|
||||||
|
spaceship.AssignFrom(spaceshipBase);
|
||||||
|
spaceship.RefreshVBO();
|
||||||
|
modelLoaded = true;
|
||||||
|
modelLoadSuccess = true;
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Model loaded successfully from: %s", modelPaths[i].c_str());
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
__android_log_print(ANDROID_LOG_WARN, "Game", "Failed to load model from %s: %s",
|
||||||
|
modelPaths[i].c_str(), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resourcesLoaded = (spaceshipTexture != nullptr && modelLoaded);
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "Setup failed: %s", e.what());
|
||||||
|
resourcesLoaded = false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Десктопная версия
|
||||||
|
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);
|
||||||
|
|
||||||
|
//Load texture
|
||||||
|
spaceshipTexture = std::make_shared<Texture>(
|
||||||
|
CreateTextureDataFromPng("./resources/sship001x.png"));
|
||||||
|
spaceshipBase = LoadFromTextFile02("./resources/spaceship004.txt");
|
||||||
|
spaceshipBase.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundY(M_PI / 2.0)));
|
||||||
|
spaceship.AssignFrom(spaceshipBase);
|
||||||
|
spaceship.RefreshVBO();
|
||||||
|
resourcesLoaded = true;
|
||||||
|
modelLoaded = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::drawScene() {
|
||||||
|
static const std::string defaultShaderName = "default";
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!resourcesLoaded) {
|
||||||
|
glClearColor(0.2f, 0.3f, 0.8f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
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);
|
||||||
|
renderer.PushMatrix();
|
||||||
|
|
||||||
|
renderer.LoadIdentity();
|
||||||
|
renderer.TranslateMatrix({0, 0, -1.0f * Environment::zoom});
|
||||||
|
renderer.RotateMatrix(QuatFromRotateAroundX(M_PI / 6.0));
|
||||||
|
//renderer.RotateMatrix(QuatFromRotateAroundX(Environment::cameraAlpha));
|
||||||
|
|
||||||
|
if (spaceshipTexture) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID());
|
||||||
|
renderer.DrawVertexRenderStruct(spaceship);
|
||||||
|
} else {
|
||||||
|
renderer.DrawVertexRenderStruct(spaceship);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.PopMatrix();
|
||||||
|
renderer.PopProjectionMatrix();
|
||||||
|
renderer.DisableVertexAttribArray(vPositionName);
|
||||||
|
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||||
|
|
||||||
|
renderer.shaderManager.PopShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Environment::cameraAlpha = Environment::cameraAlpha + delta * M_PI / 10000.f;
|
||||||
|
|
||||||
|
lastTickCount = newTickCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::render() {
|
||||||
|
SDL_GL_MakeCurrent(ZL::Environment::window, glContext);
|
||||||
|
|
||||||
|
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_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;
|
||||||
|
}
|
||||||
|
/*if (Environment::zoom > 4) {
|
||||||
|
Environment::zoom = 4;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//this->modelMeshRender.data.Scale(0.5);
|
||||||
|
//this->modelMeshRender.RefreshVBO();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
render();
|
||||||
}
|
}
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//#include "OpenGlExtensions.h"
|
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "Environment.h"
|
#include "Environment.h"
|
||||||
#include "TextureManager.h"
|
#include "TextureManager.h"
|
||||||
@ -9,34 +8,41 @@
|
|||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
~Game();
|
|
||||||
|
|
||||||
void setup();
|
~Game();
|
||||||
void update();
|
|
||||||
void render();
|
|
||||||
|
|
||||||
bool shouldExit() const { return Environment::exitGameLoop; }
|
void setup();
|
||||||
|
|
||||||
private:
|
void update();
|
||||||
void processTickCount();
|
|
||||||
void drawScene();
|
|
||||||
|
|
||||||
SDL_Window* window;
|
void render();
|
||||||
SDL_GLContext glContext;
|
|
||||||
Renderer renderer;
|
|
||||||
|
|
||||||
size_t newTickCount;
|
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||||
size_t lastTickCount;
|
|
||||||
|
|
||||||
static const size_t CONST_TIMER_INTERVAL = 10;
|
private:
|
||||||
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
void processTickCount();
|
||||||
|
|
||||||
std::shared_ptr<Texture> spaceshipTexture;
|
void drawScene();
|
||||||
VertexDataStruct spaceshipBase;
|
|
||||||
VertexRenderStruct spaceship;
|
SDL_Window *window;
|
||||||
};
|
SDL_GLContext glContext;
|
||||||
|
Renderer renderer;
|
||||||
|
|
||||||
|
size_t newTickCount;
|
||||||
|
size_t lastTickCount;
|
||||||
|
|
||||||
|
bool resourcesLoaded;
|
||||||
|
bool modelLoaded;
|
||||||
|
|
||||||
|
static const size_t CONST_TIMER_INTERVAL = 10;
|
||||||
|
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
||||||
|
|
||||||
|
std::shared_ptr <Texture> spaceshipTexture;
|
||||||
|
VertexDataStruct spaceshipBase;
|
||||||
|
VertexRenderStruct spaceship;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
@ -1,212 +1,222 @@
|
|||||||
#include "ShaderManager.h"
|
#include "ShaderManager.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <android/log.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ZL {
|
namespace ZL {
|
||||||
|
|
||||||
ShaderResource::ShaderResource(const std::string& vertexCode, const std::string& fragmentCode)
|
ShaderResource::ShaderResource(const std::string &vertexCode, const std::string &fragmentCode) {
|
||||||
{
|
|
||||||
|
|
||||||
const int CONST_INFOLOG_LENGTH = 256;
|
const int CONST_INFOLOG_LENGTH = 256;
|
||||||
|
|
||||||
char infoLog[CONST_INFOLOG_LENGTH];
|
char infoLog[CONST_INFOLOG_LENGTH];
|
||||||
int infoLogLength;
|
int infoLogLength;
|
||||||
|
|
||||||
int vertexShaderCompiled;
|
int vertexShaderCompiled;
|
||||||
int fragmentShaderCompiled;
|
int fragmentShaderCompiled;
|
||||||
int programLinked;
|
int programLinked;
|
||||||
|
|
||||||
GLuint vertexShader;
|
GLuint vertexShader;
|
||||||
GLuint fragmentShader;
|
GLuint fragmentShader;
|
||||||
|
|
||||||
int vertexCodeLength = static_cast<int>(strlen(vertexCode.c_str()));
|
int vertexCodeLength = static_cast<int>(strlen(vertexCode.c_str()));
|
||||||
int fragmentCodeLength = static_cast<int>(strlen(fragmentCode.c_str()));
|
int fragmentCodeLength = static_cast<int>(strlen(fragmentCode.c_str()));
|
||||||
|
|
||||||
const char* vc = &vertexCode[0];
|
const char *vc = &vertexCode[0];
|
||||||
const char* fc = &fragmentCode[0];
|
const char *fc = &fragmentCode[0];
|
||||||
|
|
||||||
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
glShaderSource(vertexShader, 1, &(vc), &vertexCodeLength);
|
glShaderSource(vertexShader, 1, &(vc), &vertexCodeLength);
|
||||||
|
|
||||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(fragmentShader, 1, &(fc), &fragmentCodeLength);
|
glShaderSource(fragmentShader, 1, &(fc), &fragmentCodeLength);
|
||||||
|
|
||||||
glCompileShader(vertexShader);
|
glCompileShader(vertexShader);
|
||||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexShaderCompiled);
|
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexShaderCompiled);
|
||||||
glGetShaderInfoLog(vertexShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
glGetShaderInfoLog(vertexShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
||||||
|
|
||||||
glCompileShader(fragmentShader);
|
glCompileShader(fragmentShader);
|
||||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled);
|
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled);
|
||||||
glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
||||||
|
|
||||||
if (!vertexShaderCompiled)
|
if (!vertexShaderCompiled) {
|
||||||
{
|
#ifdef __ANDROID__
|
||||||
throw std::runtime_error("Failed to compile vertex shader code!");
|
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
|
||||||
}
|
"Failed to compile vertex shader: %s", infoLog);
|
||||||
|
#endif
|
||||||
if (!fragmentShaderCompiled)
|
throw std::runtime_error("Failed to compile vertex shader code!");
|
||||||
{
|
}
|
||||||
throw std::runtime_error("Failed to compile fragment shader code!");
|
|
||||||
}
|
|
||||||
|
|
||||||
shaderProgram = glCreateProgram();
|
if (!fragmentShaderCompiled) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
|
||||||
|
"Failed to compile fragment shader: %s", infoLog);
|
||||||
|
#endif
|
||||||
|
throw std::runtime_error("Failed to compile fragment shader code!");
|
||||||
|
}
|
||||||
|
|
||||||
glAttachShader(shaderProgram, vertexShader);
|
shaderProgram = glCreateProgram();
|
||||||
glAttachShader(shaderProgram, fragmentShader);
|
|
||||||
|
|
||||||
glLinkProgram(shaderProgram);
|
glAttachShader(shaderProgram, vertexShader);
|
||||||
|
glAttachShader(shaderProgram, fragmentShader);
|
||||||
|
|
||||||
glDeleteShader(vertexShader);
|
glLinkProgram(shaderProgram);
|
||||||
glDeleteShader(fragmentShader);
|
|
||||||
|
|
||||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &programLinked);
|
glDeleteShader(vertexShader);
|
||||||
glGetProgramInfoLog(shaderProgram, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
glDeleteShader(fragmentShader);
|
||||||
|
|
||||||
if (!programLinked)
|
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &programLinked);
|
||||||
{
|
glGetProgramInfoLog(shaderProgram, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
|
||||||
shaderProgram = 0;
|
|
||||||
throw std::runtime_error("Failed to link shader program!");
|
if (!programLinked) {
|
||||||
}
|
shaderProgram = 0;
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
|
||||||
|
"Failed to link shader program: %s", infoLog);
|
||||||
|
#endif
|
||||||
|
throw std::runtime_error("Failed to link shader program!");
|
||||||
|
}
|
||||||
|
|
||||||
|
//================= Parsing all uniforms ================
|
||||||
|
|
||||||
|
int dummySize; //Dummy
|
||||||
|
int dummyLen; //Dummy
|
||||||
|
GLenum dummyEnum;
|
||||||
|
|
||||||
|
int activeUniforms;
|
||||||
|
|
||||||
|
const int CONST_UNIFORM_NAME_LENGTH = 256;
|
||||||
|
char uniformName[CONST_UNIFORM_NAME_LENGTH];
|
||||||
|
|
||||||
|
glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &activeUniforms);
|
||||||
|
|
||||||
|
for (int i = 0; i < activeUniforms; i++) {
|
||||||
|
glGetActiveUniform(shaderProgram, i, CONST_UNIFORM_NAME_LENGTH, &dummyLen, &dummySize,
|
||||||
|
&dummyEnum, uniformName);
|
||||||
|
|
||||||
|
uniformList[uniformName] = glGetUniformLocation(shaderProgram, uniformName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//================= Parsing all attributes ================
|
||||||
|
int activeAttribs;
|
||||||
|
|
||||||
|
const int CONST_ATTRIB_NAME_LENGTH = 256;
|
||||||
|
char attribName[CONST_ATTRIB_NAME_LENGTH];
|
||||||
|
|
||||||
|
glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
|
||||||
|
|
||||||
|
for (int i = 0; i < activeAttribs; i++) {
|
||||||
|
glGetActiveAttrib(shaderProgram, i, CONST_ATTRIB_NAME_LENGTH, &dummyLen, &dummySize,
|
||||||
|
&dummyEnum, attribName);
|
||||||
|
attribList[attribName] = glGetAttribLocation(shaderProgram, attribName);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
||||||
|
"Shader created successfully, program ID: %u", shaderProgram);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderResource::~ShaderResource() {
|
||||||
|
if (shaderProgram != 0) {
|
||||||
|
glDeleteProgram(shaderProgram);
|
||||||
|
|
||||||
|
shaderProgram = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint ShaderResource::getShaderProgram() {
|
||||||
|
return shaderProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int dummySize; //Dummy
|
void ShaderManager::AddShaderFromFiles(const std::string &shaderName,
|
||||||
int dummyLen; //Dummy
|
const std::string &vertexShaderFileName,
|
||||||
GLenum dummyEnum;
|
const std::string &fragmentShaderFileName,
|
||||||
|
const std::string &ZIPFileName) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
||||||
|
"Loading shader: %s", shaderName.c_str());
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
||||||
|
"Vertex shader: %s", vertexShaderFileName.c_str());
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
||||||
|
"Fragment shader: %s", fragmentShaderFileName.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string vertexShader;
|
||||||
|
std::string fragmentShader;
|
||||||
|
|
||||||
|
if (!ZIPFileName.empty()) {
|
||||||
|
|
||||||
|
std::vector<char> vertexShaderData;
|
||||||
|
std::vector<char> fragmentShaderData;
|
||||||
|
|
||||||
|
vertexShaderData = readFileFromZIP(vertexShaderFileName, ZIPFileName);
|
||||||
|
fragmentShaderData = readFileFromZIP(fragmentShaderFileName, ZIPFileName);
|
||||||
|
|
||||||
|
vertexShader = std::string(vertexShaderData.begin(), vertexShaderData.end());
|
||||||
|
fragmentShader = std::string(fragmentShaderData.begin(), fragmentShaderData.end());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
vertexShader = readTextFile(vertexShaderFileName);
|
||||||
|
fragmentShader = readTextFile(fragmentShaderFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
///std::cout << "Shader: "<< vertexShader << std::endl;
|
||||||
|
shaderResourceMap[shaderName] = std::make_shared<ShaderResource>(vertexShader,
|
||||||
|
fragmentShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderManager::PushShader(const std::string &shaderName) {
|
||||||
|
if (shaderStack.size() >= CONST_MAX_SHADER_STACK_SIZE) {
|
||||||
|
throw std::runtime_error("Shader stack overflow!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shaderResourceMap.find(shaderName) == shaderResourceMap.end()) {
|
||||||
|
throw std::runtime_error("Shader does not exist!");
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderStack.push(shaderName);
|
||||||
|
|
||||||
|
glUseProgram(shaderResourceMap[shaderName]->getShaderProgram());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//================= Parsing all uniforms ================
|
void ShaderManager::PopShader() {
|
||||||
|
if (shaderStack.size() == 0) {
|
||||||
|
throw std::runtime_error("Shader stack underflow!");
|
||||||
|
}
|
||||||
|
|
||||||
int activeUniforms;
|
shaderStack.pop();
|
||||||
|
|
||||||
const int CONST_UNIFORM_NAME_LENGTH = 256;
|
if (shaderStack.size() == 0) {
|
||||||
char uniformName[CONST_UNIFORM_NAME_LENGTH];
|
glUseProgram(0);
|
||||||
|
} else {
|
||||||
|
glUseProgram(shaderResourceMap[shaderStack.top()]->getShaderProgram());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &activeUniforms);
|
std::shared_ptr <ShaderResource> ShaderManager::GetCurrentShader() {
|
||||||
|
if (shaderStack.size() == 0) {
|
||||||
for (int i = 0; i < activeUniforms; i++)
|
throw std::runtime_error("Shader stack underflow!");
|
||||||
{
|
}
|
||||||
glGetActiveUniform(shaderProgram, i, CONST_UNIFORM_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, uniformName);
|
|
||||||
|
|
||||||
uniformList[uniformName] = glGetUniformLocation(shaderProgram, uniformName);
|
|
||||||
}
|
|
||||||
|
|
||||||
//================= Parsing all attributes ================
|
|
||||||
int activeAttribs;
|
|
||||||
|
|
||||||
const int CONST_ATTRIB_NAME_LENGTH = 256;
|
|
||||||
char attribName[CONST_ATTRIB_NAME_LENGTH];
|
|
||||||
|
|
||||||
glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
|
|
||||||
|
|
||||||
for (int i = 0; i < activeAttribs; i++)
|
|
||||||
{
|
|
||||||
glGetActiveAttrib(shaderProgram, i, CONST_ATTRIB_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, attribName);
|
|
||||||
attribList[attribName] = glGetAttribLocation(shaderProgram, attribName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderResource::~ShaderResource()
|
|
||||||
{
|
|
||||||
if (shaderProgram != 0)
|
|
||||||
{
|
|
||||||
glDeleteProgram(shaderProgram);
|
|
||||||
|
|
||||||
shaderProgram = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint ShaderResource::getShaderProgram()
|
|
||||||
{
|
|
||||||
return shaderProgram;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ShaderManager::AddShaderFromFiles(const std::string& shaderName, const std::string& vertexShaderFileName, const std::string& fragmentShaderFileName, const std::string& ZIPFileName)
|
return shaderResourceMap[shaderStack.top()];
|
||||||
{
|
|
||||||
|
|
||||||
std::string vertexShader;
|
}
|
||||||
std::string fragmentShader;
|
|
||||||
|
|
||||||
if (!ZIPFileName.empty()){
|
|
||||||
|
|
||||||
std::vector<char> vertexShaderData;
|
|
||||||
std::vector<char> fragmentShaderData;
|
|
||||||
|
|
||||||
vertexShaderData = readFileFromZIP(vertexShaderFileName, ZIPFileName);
|
|
||||||
fragmentShaderData = readFileFromZIP(fragmentShaderFileName, ZIPFileName);
|
|
||||||
|
|
||||||
vertexShader = std::string(vertexShaderData.begin(), vertexShaderData.end());
|
|
||||||
fragmentShader = std::string(fragmentShaderData.begin(), fragmentShaderData.end());
|
|
||||||
|
|
||||||
}else{
|
|
||||||
vertexShader = readTextFile(vertexShaderFileName);
|
|
||||||
fragmentShader = readTextFile(fragmentShaderFileName);
|
|
||||||
}
|
|
||||||
///std::cout << "Shader: "<< vertexShader << std::endl;
|
|
||||||
shaderResourceMap[shaderName] = std::make_shared<ShaderResource>(vertexShader, fragmentShader);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderManager::PushShader(const std::string& shaderName)
|
|
||||||
{
|
|
||||||
if (shaderStack.size() >= CONST_MAX_SHADER_STACK_SIZE)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Shader stack overflow!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shaderResourceMap.find(shaderName) == shaderResourceMap.end())
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Shader does not exist!");
|
|
||||||
}
|
|
||||||
|
|
||||||
shaderStack.push(shaderName);
|
|
||||||
|
|
||||||
glUseProgram(shaderResourceMap[shaderName]->getShaderProgram());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ShaderManager::PopShader()
|
ShaderSetter::ShaderSetter(ShaderManager &inShaderManager, const std::string &shaderName)
|
||||||
{
|
: shaderManager(inShaderManager) {
|
||||||
if (shaderStack.size() == 0)
|
shaderManager.PushShader(shaderName);
|
||||||
{
|
}
|
||||||
throw std::runtime_error("Shader stack underflow!");
|
|
||||||
}
|
|
||||||
|
|
||||||
shaderStack.pop();
|
ShaderSetter::~ShaderSetter() {
|
||||||
|
shaderManager.PopShader();
|
||||||
if (shaderStack.size() == 0)
|
}
|
||||||
{
|
|
||||||
glUseProgram(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glUseProgram(shaderResourceMap[shaderStack.top()]->getShaderProgram());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ShaderResource> ShaderManager::GetCurrentShader()
|
|
||||||
{
|
|
||||||
if (shaderStack.size() == 0)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Shader stack underflow!");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return shaderResourceMap[shaderStack.top()];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ShaderSetter::ShaderSetter(ShaderManager& inShaderManager, const std::string& shaderName)
|
|
||||||
: shaderManager(shaderManager)
|
|
||||||
{
|
|
||||||
shaderManager.PushShader(shaderName);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderSetter::~ShaderSetter()
|
|
||||||
{
|
|
||||||
shaderManager.PopShader();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -5,386 +5,393 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace ZL
|
#ifdef __ANDROID__
|
||||||
{
|
#include <android/log.h>
|
||||||
|
#endif
|
||||||
|
namespace ZL {
|
||||||
VertexDataStruct LoadFromTextFile(const std::string& fileName, const std::string& ZIPFileName)
|
|
||||||
{
|
|
||||||
VertexDataStruct result;
|
|
||||||
std::ifstream filestream;
|
|
||||||
std::istringstream zipStream;
|
|
||||||
|
|
||||||
if (!ZIPFileName.empty())
|
|
||||||
{
|
|
||||||
std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
|
|
||||||
std::string fileContents(fileData.begin(), fileData.end());
|
|
||||||
zipStream.str(fileContents);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filestream.open(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаем ссылку f на нужный поток – после этого код ниже остается без изменений
|
|
||||||
std::istream& f = (!ZIPFileName.empty()) ? static_cast<std::istream&>(zipStream) : static_cast<std::istream&>(filestream);
|
|
||||||
|
|
||||||
|
|
||||||
//Skip first 5 lines
|
|
||||||
std::string tempLine;
|
|
||||||
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
static const std::regex pattern_count(R"(\d+)");
|
|
||||||
static const std::regex pattern_float(R"([-]?\d+\.\d+)");
|
|
||||||
static const std::regex pattern_int(R"([-]?\d+)");
|
|
||||||
|
|
||||||
|
|
||||||
std::smatch match;
|
|
||||||
|
|
||||||
int numberVertices;
|
|
||||||
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
std::string number_str = match.str();
|
|
||||||
numberVertices = std::stoi(number_str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::runtime_error("No number found in the input string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Vector3f> vertices;
|
|
||||||
|
|
||||||
vertices.resize(numberVertices);
|
|
||||||
for (int i = 0; i < numberVertices; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
std::vector<float> floatValues;
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
while (std::regex_search(b, e, match, pattern_float)) {
|
|
||||||
floatValues.push_back(std::stof(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertices[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "UV Coordinates" << std::endl;
|
VertexDataStruct LoadFromTextFile(const std::string &fileName, const std::string &ZIPFileName) {
|
||||||
|
VertexDataStruct result;
|
||||||
|
std::ifstream filestream;
|
||||||
|
std::istringstream zipStream;
|
||||||
|
|
||||||
std::getline(f, tempLine); //===UV Coordinates:
|
if (!ZIPFileName.empty()) {
|
||||||
|
std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
|
||||||
|
std::string fileContents(fileData.begin(), fileData.end());
|
||||||
|
zipStream.str(fileContents);
|
||||||
|
} else {
|
||||||
|
filestream.open(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
std::getline(f, tempLine); //triangle count
|
// Создаем ссылку f на нужный поток – после этого код ниже остается без изменений
|
||||||
int numberTriangles;
|
std::istream &f = (!ZIPFileName.empty()) ? static_cast<std::istream &>(zipStream)
|
||||||
|
: static_cast<std::istream &>(filestream);
|
||||||
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
std::string number_str = match.str();
|
|
||||||
numberTriangles = std::stoi(number_str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::runtime_error("No number found in the input string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//Skip first 5 lines
|
||||||
|
std::string tempLine;
|
||||||
|
|
||||||
// Now process UVs
|
std::getline(f, tempLine);
|
||||||
std::vector<std::array<Vector2f, 3>> uvCoords;
|
|
||||||
|
|
||||||
uvCoords.resize(numberTriangles);
|
static const std::regex pattern_count(R"(\d+)");
|
||||||
|
static const std::regex pattern_float(R"([-]?\d+\.\d+)");
|
||||||
|
static const std::regex pattern_int(R"([-]?\d+)");
|
||||||
|
|
||||||
for (int i = 0; i < numberTriangles; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine); //Face 0
|
|
||||||
|
|
||||||
int uvCount;
|
std::smatch match;
|
||||||
std::getline(f, tempLine);
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
std::string number_str = match.str();
|
|
||||||
uvCount = std::stoi(number_str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::runtime_error("No number found in the input string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uvCount != 3)
|
int numberVertices;
|
||||||
{
|
|
||||||
throw std::runtime_error("more than 3 uvs");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<float> floatValues;
|
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||||
|
std::string number_str = match.str();
|
||||||
|
numberVertices = std::stoi(number_str);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("No number found in the input string.");
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
std::vector <Vector3f> vertices;
|
||||||
{
|
|
||||||
std::getline(f, tempLine); //UV <Vector (-0.3661, -1.1665)>
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
floatValues.clear();
|
|
||||||
while (std::regex_search(b, e, match, pattern_float)) {
|
|
||||||
floatValues.push_back(std::stof(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (floatValues.size() != 2)
|
vertices.resize(numberVertices);
|
||||||
{
|
for (int i = 0; i < numberVertices; i++) {
|
||||||
throw std::runtime_error("more than 2 uvs---");
|
std::getline(f, tempLine);
|
||||||
}
|
|
||||||
|
|
||||||
uvCoords[i][j] = Vector2f{ floatValues[0],floatValues[1] };
|
std::vector<float> floatValues;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Normals go" << std::endl;
|
auto b = tempLine.cbegin();
|
||||||
|
auto e = tempLine.cend();
|
||||||
|
while (std::regex_search(b, e, match, pattern_float)) {
|
||||||
|
floatValues.push_back(std::stof(match.str()));
|
||||||
|
b = match.suffix().first;
|
||||||
|
}
|
||||||
|
|
||||||
std::getline(f, tempLine); //===Normals:
|
vertices[i] = Vector3f{floatValues[0], floatValues[1], floatValues[2]};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "UV Coordinates" << std::endl;
|
||||||
|
|
||||||
std::vector<Vector3f> normals;
|
std::getline(f, tempLine); //===UV Coordinates:
|
||||||
|
|
||||||
normals.resize(numberVertices);
|
std::getline(f, tempLine); //triangle count
|
||||||
for (int i = 0; i < numberVertices; i++)
|
int numberTriangles;
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
std::vector<float> floatValues;
|
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||||
|
std::string number_str = match.str();
|
||||||
|
numberTriangles = std::stoi(number_str);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("No number found in the input string.");
|
||||||
|
}
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
while (std::regex_search(b, e, match, pattern_float)) {
|
|
||||||
floatValues.push_back(std::stof(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
normals[i] = Vector3f{ floatValues[0], floatValues[1], floatValues[2] };
|
// Now process UVs
|
||||||
}
|
std::vector <std::array<Vector2f, 3>> uvCoords;
|
||||||
|
|
||||||
std::cout << "Triangles go:" << std::endl;
|
uvCoords.resize(numberTriangles);
|
||||||
|
|
||||||
std::getline(f, tempLine); //===Triangles: 3974
|
for (int i = 0; i < numberTriangles; i++) {
|
||||||
|
std::getline(f, tempLine); //Face 0
|
||||||
|
|
||||||
|
int uvCount;
|
||||||
|
std::getline(f, tempLine);
|
||||||
|
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||||
|
std::string number_str = match.str();
|
||||||
|
uvCount = std::stoi(number_str);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("No number found in the input string.");
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::array<int, 3>> triangles;
|
if (uvCount != 3) {
|
||||||
|
throw std::runtime_error("more than 3 uvs");
|
||||||
|
}
|
||||||
|
|
||||||
triangles.resize(numberTriangles);
|
std::vector<float> floatValues;
|
||||||
for (int i = 0; i < numberTriangles; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
|
|
||||||
std::vector<int> intValues;
|
for (int j = 0; j < 3; j++) {
|
||||||
|
std::getline(f, tempLine); //UV <Vector (-0.3661, -1.1665)>
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
auto b = tempLine.cbegin();
|
||||||
auto e = tempLine.cend();
|
auto e = tempLine.cend();
|
||||||
while (std::regex_search(b, e, match, pattern_int)) {
|
floatValues.clear();
|
||||||
intValues.push_back(std::stoi(match.str()));
|
while (std::regex_search(b, e, match, pattern_float)) {
|
||||||
b = match.suffix().first;
|
floatValues.push_back(std::stof(match.str()));
|
||||||
}
|
b = match.suffix().first;
|
||||||
|
}
|
||||||
triangles[i] = { intValues[0], intValues[1], intValues[2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::cout << "Process vertices" << std::endl;
|
|
||||||
|
|
||||||
|
if (floatValues.size() != 2) {
|
||||||
|
throw std::runtime_error("more than 2 uvs---");
|
||||||
|
}
|
||||||
|
|
||||||
|
uvCoords[i][j] = Vector2f{floatValues[0], floatValues[1]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now let's process vertices
|
std::cout << "Normals go" << std::endl;
|
||||||
|
|
||||||
for (int i = 0; i < numberTriangles; i++)
|
|
||||||
{
|
|
||||||
|
|
||||||
result.PositionData.push_back(vertices[triangles[i][0]]);
|
|
||||||
result.PositionData.push_back(vertices[triangles[i][1]]);
|
|
||||||
result.PositionData.push_back(vertices[triangles[i][2]]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
result.NormalData.push_back(normals[triangles[i][0]]);
|
|
||||||
result.NormalData.push_back(normals[triangles[i][1]]);
|
|
||||||
result.NormalData.push_back(normals[triangles[i][2]]);
|
|
||||||
*/
|
|
||||||
result.TexCoordData.push_back(uvCoords[i][0]);
|
|
||||||
result.TexCoordData.push_back(uvCoords[i][1]);
|
|
||||||
result.TexCoordData.push_back(uvCoords[i][2]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Swap from Blender format to OpenGL format
|
|
||||||
for (int i = 0; i < result.PositionData.size(); i++)
|
|
||||||
{
|
|
||||||
Vector3f tempVec = result.PositionData[i];
|
|
||||||
result.PositionData[i].v[0] = tempVec.v[1];
|
|
||||||
result.PositionData[i].v[1] = tempVec.v[2];
|
|
||||||
result.PositionData[i].v[2] = tempVec.v[0];
|
|
||||||
|
|
||||||
/*
|
|
||||||
tempVec = result.NormalData[i];
|
|
||||||
result.NormalData[i].v[0] = tempVec.v[1];
|
|
||||||
result.NormalData[i].v[1] = tempVec.v[2];
|
|
||||||
result.NormalData[i].v[2] = tempVec.v[0];*/
|
|
||||||
|
|
||||||
}
|
std::getline(f, tempLine); //===Normals:
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
std::vector <Vector3f> normals;
|
||||||
|
|
||||||
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName)
|
|
||||||
{
|
|
||||||
VertexDataStruct result;
|
|
||||||
std::ifstream filestream;
|
|
||||||
std::istringstream zipStream;
|
|
||||||
|
|
||||||
// --- 1. Открытие потока (без изменений) ---
|
normals.resize(numberVertices);
|
||||||
if (!ZIPFileName.empty())
|
for (int i = 0; i < numberVertices; i++) {
|
||||||
{
|
std::getline(f, tempLine);
|
||||||
std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
|
|
||||||
std::string fileContents(fileData.begin(), fileData.end());
|
|
||||||
zipStream.str(fileContents);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filestream.open(fileName);
|
|
||||||
if (!filestream.is_open()) {
|
|
||||||
throw std::runtime_error("Failed to open file: " + fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istream& f = (!ZIPFileName.empty()) ? static_cast<std::istream&>(zipStream) : static_cast<std::istream&>(filestream);
|
|
||||||
|
|
||||||
std::string tempLine;
|
|
||||||
std::smatch match;
|
|
||||||
|
|
||||||
// Обновленные регулярки
|
|
||||||
// pattern_float стал чуть надежнее для чисел вида "0" или "-1" без точки, если вдруг Python округлит до int
|
|
||||||
static const std::regex pattern_count(R"(\d+)");
|
|
||||||
static const std::regex pattern_float(R"([-]?\d+(\.\d+)?)");
|
|
||||||
static const std::regex pattern_int(R"([-]?\d+)");
|
|
||||||
|
|
||||||
// --- 2. Парсинг Вершин (Pos + Norm + UV) ---
|
|
||||||
|
|
||||||
// Ищем заголовок ===Vertices
|
|
||||||
while (std::getline(f, tempLine)) {
|
|
||||||
if (tempLine.find("===Vertices") != std::string::npos) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numberVertices = 0;
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
numberVertices = std::stoi(match.str());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::runtime_error("Vertices header not found or invalid.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Временные буферы для хранения "уникальных" вершин перед разверткой по индексам
|
|
||||||
std::vector<Vector3f> tempPositions(numberVertices);
|
|
||||||
std::vector<Vector3f> tempNormals(numberVertices);
|
|
||||||
std::vector<Vector2f> tempUVs(numberVertices);
|
|
||||||
|
|
||||||
for (int i = 0; i < numberVertices; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
// Строка вида: V 0: Pos(x, y, z) Norm(x, y, z) UV(u, v)
|
|
||||||
|
|
||||||
std::vector<float> floatValues;
|
|
||||||
floatValues.reserve(8); // Ожидаем ровно 8 чисел (3 pos + 3 norm + 2 uv)
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
while (std::regex_search(b, e, match, pattern_float)) {
|
|
||||||
floatValues.push_back(std::stof(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверка целостности строки (ID вершины regex может поймать первым, но нас интересуют данные)
|
|
||||||
// Обычно ID идет первым (0), потом 3+3+2 float. Итого 9 чисел, если считать ID.
|
|
||||||
// Ваш Python пишет "V 0:", regex поймает 0. Потом 8 флоатов.
|
|
||||||
|
|
||||||
// Если regex ловит ID вершины как float (что вероятно), нам нужно смещение.
|
|
||||||
// ID - floatValues[0]
|
|
||||||
// Pos - [1], [2], [3]
|
|
||||||
// Norm - [4], [5], [6]
|
|
||||||
// UV - [7], [8]
|
|
||||||
|
|
||||||
if (floatValues.size() < 9) {
|
|
||||||
throw std::runtime_error("Malformed vertex line at index " + std::to_string(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
tempPositions[i] = Vector3f{ floatValues[1], floatValues[2], floatValues[3] };
|
|
||||||
tempNormals[i] = Vector3f{ floatValues[4], floatValues[5], floatValues[6] };
|
|
||||||
tempUVs[i] = Vector2f{ floatValues[7], floatValues[8] };
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 3. Парсинг Треугольников (Индексов) ---
|
|
||||||
|
|
||||||
// Пропускаем пустые строки до заголовка треугольников
|
|
||||||
while (std::getline(f, tempLine)) {
|
|
||||||
if (tempLine.find("===Triangles") != std::string::npos) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numberTriangles = 0;
|
|
||||||
if (std::regex_search(tempLine, match, pattern_count)) {
|
|
||||||
numberTriangles = std::stoi(match.str());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::runtime_error("Triangles header not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Резервируем память в result, чтобы избежать лишних аллокаций
|
|
||||||
result.PositionData.reserve(numberTriangles * 3);
|
|
||||||
result.NormalData.reserve(numberTriangles * 3);
|
|
||||||
result.TexCoordData.reserve(numberTriangles * 3);
|
|
||||||
|
|
||||||
for (int i = 0; i < numberTriangles; i++)
|
|
||||||
{
|
|
||||||
std::getline(f, tempLine);
|
|
||||||
// Строка вида: Tri: 0 1 2
|
|
||||||
|
|
||||||
std::vector<int> indices;
|
|
||||||
indices.reserve(3);
|
|
||||||
|
|
||||||
auto b = tempLine.cbegin();
|
|
||||||
auto e = tempLine.cend();
|
|
||||||
while (std::regex_search(b, e, match, pattern_int)) {
|
|
||||||
indices.push_back(std::stoi(match.str()));
|
|
||||||
b = match.suffix().first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices.size() != 3) {
|
|
||||||
throw std::runtime_error("Malformed triangle line at index " + std::to_string(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 4. Заполнение VertexDataStruct (Flattening) ---
|
|
||||||
// Берем данные из временных буферов по индексам и кладем в итоговый массив
|
|
||||||
|
|
||||||
for (int k = 0; k < 3; k++) {
|
|
||||||
int idx = indices[k];
|
|
||||||
result.PositionData.push_back(tempPositions[idx]);
|
|
||||||
result.NormalData.push_back(tempNormals[idx]);
|
|
||||||
result.TexCoordData.push_back(tempUVs[idx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 5. Конвертация координат (Blender -> OpenGL/Engine) ---
|
|
||||||
// Сохраняем вашу логику смены осей: X->Z, Y->X, Z->Y
|
|
||||||
|
|
||||||
for (size_t i = 0; i < result.PositionData.size(); i++)
|
|
||||||
{
|
|
||||||
Vector3f originalPos = result.PositionData[i];
|
|
||||||
result.PositionData[i].v[0] = originalPos.v[1]; // New X = Old Y
|
|
||||||
result.PositionData[i].v[1] = originalPos.v[2]; // New Y = Old Z
|
|
||||||
result.PositionData[i].v[2] = originalPos.v[0]; // New Z = Old X
|
|
||||||
|
|
||||||
Vector3f originalNorm = result.NormalData[i];
|
|
||||||
result.NormalData[i].v[0] = originalNorm.v[1];
|
|
||||||
result.NormalData[i].v[1] = originalNorm.v[2];
|
|
||||||
result.NormalData[i].v[2] = originalNorm.v[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Model loaded: " << numberVertices << " verts, " << numberTriangles << " tris." << std::endl;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::vector<float> floatValues;
|
||||||
|
|
||||||
|
auto b = tempLine.cbegin();
|
||||||
|
auto e = tempLine.cend();
|
||||||
|
while (std::regex_search(b, e, match, pattern_float)) {
|
||||||
|
floatValues.push_back(std::stof(match.str()));
|
||||||
|
b = match.suffix().first;
|
||||||
|
}
|
||||||
|
|
||||||
|
normals[i] = Vector3f{floatValues[0], floatValues[1], floatValues[2]};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Triangles go:" << std::endl;
|
||||||
|
|
||||||
|
std::getline(f, tempLine); //===Triangles: 3974
|
||||||
|
|
||||||
|
|
||||||
|
std::vector <std::array<int, 3>> triangles;
|
||||||
|
|
||||||
|
triangles.resize(numberTriangles);
|
||||||
|
for (int i = 0; i < numberTriangles; i++) {
|
||||||
|
std::getline(f, tempLine);
|
||||||
|
|
||||||
|
std::vector<int> intValues;
|
||||||
|
|
||||||
|
auto b = tempLine.cbegin();
|
||||||
|
auto e = tempLine.cend();
|
||||||
|
while (std::regex_search(b, e, match, pattern_int)) {
|
||||||
|
intValues.push_back(std::stoi(match.str()));
|
||||||
|
b = match.suffix().first;
|
||||||
|
}
|
||||||
|
|
||||||
|
triangles[i] = {intValues[0], intValues[1], intValues[2]};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "Process vertices" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Now let's process vertices
|
||||||
|
|
||||||
|
for (int i = 0; i < numberTriangles; i++) {
|
||||||
|
|
||||||
|
result.PositionData.push_back(vertices[triangles[i][0]]);
|
||||||
|
result.PositionData.push_back(vertices[triangles[i][1]]);
|
||||||
|
result.PositionData.push_back(vertices[triangles[i][2]]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
result.NormalData.push_back(normals[triangles[i][0]]);
|
||||||
|
result.NormalData.push_back(normals[triangles[i][1]]);
|
||||||
|
result.NormalData.push_back(normals[triangles[i][2]]);
|
||||||
|
*/
|
||||||
|
result.TexCoordData.push_back(uvCoords[i][0]);
|
||||||
|
result.TexCoordData.push_back(uvCoords[i][1]);
|
||||||
|
result.TexCoordData.push_back(uvCoords[i][2]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Swap from Blender format to OpenGL format
|
||||||
|
for (int i = 0; i < result.PositionData.size(); i++) {
|
||||||
|
Vector3f tempVec = result.PositionData[i];
|
||||||
|
result.PositionData[i].v[0] = tempVec.v[1];
|
||||||
|
result.PositionData[i].v[1] = tempVec.v[2];
|
||||||
|
result.PositionData[i].v[2] = tempVec.v[0];
|
||||||
|
|
||||||
|
/*
|
||||||
|
tempVec = result.NormalData[i];
|
||||||
|
result.NormalData[i].v[0] = tempVec.v[1];
|
||||||
|
result.NormalData[i].v[1] = tempVec.v[2];
|
||||||
|
result.NormalData[i].v[2] = tempVec.v[0];*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexDataStruct
|
||||||
|
LoadFromTextFile02(const std::string &fileName, const std::string &ZIPFileName) {
|
||||||
|
VertexDataStruct result;
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
// Для Android используем SDL_RWops для чтения файлов
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "TextModel",
|
||||||
|
"LoadFromTextFile02 called for Android: %s", fileName.c_str());
|
||||||
|
|
||||||
|
// Читаем файл с помощью readTextFile
|
||||||
|
std::string fileContent = readTextFile(fileName);
|
||||||
|
if (fileContent.empty()) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "TextModel",
|
||||||
|
"Failed to read file: %s", fileName.c_str());
|
||||||
|
throw std::runtime_error("Failed to read file: " + fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "TextModel",
|
||||||
|
"File read successfully, size: %zu", fileContent.size());
|
||||||
|
|
||||||
|
std::istringstream f(fileContent);
|
||||||
|
#else
|
||||||
|
// Оригинальный код для десктопа
|
||||||
|
std::ifstream filestream;
|
||||||
|
std::istringstream zipStream;
|
||||||
|
|
||||||
|
if (!ZIPFileName.empty()) {
|
||||||
|
std::vector<char> fileData = readFileFromZIP(fileName, ZIPFileName);
|
||||||
|
std::string fileContents(fileData.begin(), fileData.end());
|
||||||
|
zipStream.str(fileContents);
|
||||||
|
f = static_cast<std::istream &>(zipStream);
|
||||||
|
} else {
|
||||||
|
filestream.open(fileName);
|
||||||
|
if (!filestream.is_open()) {
|
||||||
|
throw std::runtime_error("Failed to open file: " + fileName);
|
||||||
|
}
|
||||||
|
f = static_cast<std::istream &>(filestream);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string tempLine;
|
||||||
|
std::smatch match;
|
||||||
|
|
||||||
|
// Обновленные регулярки
|
||||||
|
static const std::regex pattern_count(R"(\d+)");
|
||||||
|
static const std::regex pattern_float(R"([-]?\d+(\.\d+)?)");
|
||||||
|
static const std::regex pattern_int(R"([-]?\d+)");
|
||||||
|
|
||||||
|
// --- 2. Парсинг Вершин (Pos + Norm + UV) ---
|
||||||
|
|
||||||
|
// Ищем заголовок ===Vertices
|
||||||
|
while (std::getline(f, tempLine)) {
|
||||||
|
if (tempLine.find("===Vertices") != std::string::npos) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numberVertices = 0;
|
||||||
|
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||||
|
numberVertices = std::stoi(match.str());
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Vertices header not found or invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Временные буферы для хранения "уникальных" вершин перед разверткой по индексам
|
||||||
|
std::vector <Vector3f> tempPositions(numberVertices);
|
||||||
|
std::vector <Vector3f> tempNormals(numberVertices);
|
||||||
|
std::vector <Vector2f> tempUVs(numberVertices);
|
||||||
|
|
||||||
|
for (int i = 0; i < numberVertices; i++) {
|
||||||
|
std::getline(f, tempLine);
|
||||||
|
// Строка вида: V 0: Pos(x, y, z) Norm(x, y, z) UV(u, v)
|
||||||
|
|
||||||
|
std::vector<float> floatValues;
|
||||||
|
floatValues.reserve(9); // ID + 3 pos + 3 norm + 2 uv
|
||||||
|
|
||||||
|
auto b = tempLine.cbegin();
|
||||||
|
auto e = tempLine.cend();
|
||||||
|
while (std::regex_search(b, e, match, pattern_float)) {
|
||||||
|
floatValues.push_back(std::stof(match.str()));
|
||||||
|
b = match.suffix().first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка, что у нас достаточно данных
|
||||||
|
if (floatValues.size() < 9) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_WARN, "TextModel",
|
||||||
|
"Warning: vertex line has only %zu values, expected 9",
|
||||||
|
floatValues.size());
|
||||||
|
#endif
|
||||||
|
// Попробуем с меньшим количеством, возможно данные упрощенные
|
||||||
|
if (floatValues.size() >= 8) {
|
||||||
|
// Без ID
|
||||||
|
tempPositions[i] = Vector3f{floatValues[0], floatValues[1], floatValues[2]};
|
||||||
|
tempNormals[i] = Vector3f{floatValues[3], floatValues[4], floatValues[5]};
|
||||||
|
tempUVs[i] = Vector2f{floatValues[6], floatValues[7]};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Malformed vertex line at index " + std::to_string(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID - floatValues[0]
|
||||||
|
// Pos - [1], [2], [3]
|
||||||
|
// Norm - [4], [5], [6]
|
||||||
|
// UV - [7], [8]
|
||||||
|
tempPositions[i] = Vector3f{floatValues[1], floatValues[2], floatValues[3]};
|
||||||
|
tempNormals[i] = Vector3f{floatValues[4], floatValues[5], floatValues[6]};
|
||||||
|
tempUVs[i] = Vector2f{floatValues[7], floatValues[8]};
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 3. Парсинг Треугольников (Индексов) ---
|
||||||
|
|
||||||
|
// Пропускаем пустые строки до заголовка треугольников
|
||||||
|
while (std::getline(f, tempLine)) {
|
||||||
|
if (tempLine.find("===Triangles") != std::string::npos) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numberTriangles = 0;
|
||||||
|
if (std::regex_search(tempLine, match, pattern_count)) {
|
||||||
|
numberTriangles = std::stoi(match.str());
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Triangles header not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Резервируем память в result, чтобы избежать лишних аллокаций
|
||||||
|
result.PositionData.reserve(numberTriangles * 3);
|
||||||
|
result.NormalData.reserve(numberTriangles * 3);
|
||||||
|
result.TexCoordData.reserve(numberTriangles * 3);
|
||||||
|
|
||||||
|
for (int i = 0; i < numberTriangles; i++) {
|
||||||
|
std::getline(f, tempLine);
|
||||||
|
// Строка вида: Tri: 0 1 2
|
||||||
|
|
||||||
|
std::vector<int> indices;
|
||||||
|
indices.reserve(3);
|
||||||
|
|
||||||
|
auto b = tempLine.cbegin();
|
||||||
|
auto e = tempLine.cend();
|
||||||
|
while (std::regex_search(b, e, match, pattern_int)) {
|
||||||
|
indices.push_back(std::stoi(match.str()));
|
||||||
|
b = match.suffix().first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indices.size() != 3) {
|
||||||
|
throw std::runtime_error("Malformed triangle line at index " + std::to_string(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 4. Заполнение VertexDataStruct (Flattening) ---
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
int idx = indices[k];
|
||||||
|
result.PositionData.push_back(tempPositions[idx]);
|
||||||
|
result.NormalData.push_back(tempNormals[idx]);
|
||||||
|
result.TexCoordData.push_back(tempUVs[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 5. Конвертация координат (Blender -> OpenGL/Engine) ---
|
||||||
|
for (size_t i = 0; i < result.PositionData.size(); i++) {
|
||||||
|
Vector3f originalPos = result.PositionData[i];
|
||||||
|
result.PositionData[i].v[0] = originalPos.v[1]; // New X = Old Y
|
||||||
|
result.PositionData[i].v[1] = originalPos.v[2]; // New Y = Old Z
|
||||||
|
result.PositionData[i].v[2] = originalPos.v[0]; // New Z = Old X
|
||||||
|
|
||||||
|
Vector3f originalNorm = result.NormalData[i];
|
||||||
|
result.NormalData[i].v[0] = originalNorm.v[1];
|
||||||
|
result.NormalData[i].v[1] = originalNorm.v[2];
|
||||||
|
result.NormalData[i].v[2] = originalNorm.v[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "TextModel",
|
||||||
|
"Model loaded successfully: %d verts, %d tris",
|
||||||
|
numberVertices, numberTriangles);
|
||||||
|
#else
|
||||||
|
std::cout << "Model loaded: " << numberVertices << " verts, " << numberTriangles << " tris."
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -5,8 +5,14 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
namespace ZL
|
#ifdef __ANDROID__
|
||||||
{
|
#include <android/log.h>
|
||||||
VertexDataStruct LoadFromTextFile(const std::string& fileName, const std::string& ZIPFileName = "");
|
#endif
|
||||||
VertexDataStruct LoadFromTextFile02(const std::string& fileName, const std::string& ZIPFileName = "");
|
|
||||||
|
namespace ZL {
|
||||||
|
VertexDataStruct
|
||||||
|
LoadFromTextFile(const std::string &fileName, const std::string &ZIPFileName = "");
|
||||||
|
|
||||||
|
VertexDataStruct
|
||||||
|
LoadFromTextFile02(const std::string &fileName, const std::string &ZIPFileName = "");
|
||||||
}
|
}
|
||||||
@ -6,95 +6,139 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
//#include <zip.h>
|
//#include <zip.h>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
namespace ZL
|
#ifdef __ANDROID__
|
||||||
{
|
#include <android/log.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string readTextFile(const std::string& filename)
|
namespace ZL {
|
||||||
{
|
std::string readTextFile(const std::string &filename) {
|
||||||
std::ifstream f(filename);
|
#ifdef __ANDROID__
|
||||||
|
SDL_RWops* file = SDL_RWFromFile(filename.c_str(), "rb");
|
||||||
|
if (!file) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Utils",
|
||||||
|
"Failed to open: %s", filename.c_str());
|
||||||
|
#endif
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
Sint64 size = SDL_RWsize(file);
|
||||||
|
if (size <= 0) {
|
||||||
|
SDL_RWclose(file);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
return str;
|
std::string content(size, '\0');
|
||||||
}
|
if (SDL_RWread(file, &content[0], size, 1) != 1) {
|
||||||
|
SDL_RWclose(file);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<char> readFile(const std::string& filename)
|
SDL_RWclose(file);
|
||||||
{
|
return content;
|
||||||
std::ifstream file(filename, std::ios::binary);
|
#else
|
||||||
|
std::ifstream f(filename);
|
||||||
|
if (!f.is_open()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return std::string((std::istreambuf_iterator<char>(f)),
|
||||||
|
std::istreambuf_iterator<char>());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
file.unsetf(std::ios::skipws);
|
std::vector<char> readFile(const std::string &filename) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
SDL_RWops* file = SDL_RWFromFile(filename.c_str(), "rb");
|
||||||
|
if (!file) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::streampos fileSize;
|
Sint64 size = SDL_RWsize(file);
|
||||||
|
if (size <= 0) {
|
||||||
|
SDL_RWclose(file);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
file.seekg(0, std::ios::end);
|
std::vector<char> data(size);
|
||||||
fileSize = file.tellg();
|
if (SDL_RWread(file, data.data(), size, 1) != 1) {
|
||||||
file.seekg(0, std::ios::beg);
|
SDL_RWclose(file);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<char> vec;
|
SDL_RWclose(file);
|
||||||
vec.reserve(fileSize);
|
return data;
|
||||||
|
#else
|
||||||
|
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
||||||
|
if (!file) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
vec.insert(vec.begin(),
|
std::streamsize size = file.tellg();
|
||||||
std::istream_iterator<char>(file),
|
if (size <= 0) {
|
||||||
std::istream_iterator<char>());
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
return vec;
|
file.seekg(0, std::ios::beg);
|
||||||
}
|
std::vector<char> buffer(size);
|
||||||
|
|
||||||
std::vector<char> readFileFromZIP(const std::string& filename, const std::string& zipfilename) {
|
|
||||||
/*const std::string zipPath = zipfilename;
|
|
||||||
int zipErr;
|
|
||||||
zip_t* archive = zip_open(zipPath.c_str(), ZIP_RDONLY, &zipErr);
|
|
||||||
if (!archive) {
|
|
||||||
throw std::runtime_error("Ошибка открытия ZIP: " + zipPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string cleanFilename = filename;
|
|
||||||
if (cleanFilename.rfind("./", 0) == 0) {
|
|
||||||
cleanFilename = cleanFilename.substr(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Ищем в ZIP: " << cleanFilename << std::endl;
|
|
||||||
|
|
||||||
zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0);
|
|
||||||
if (!zipFile) {
|
|
||||||
zip_close(archive);
|
|
||||||
throw std::runtime_error("Файл не найден в ZIP: " + cleanFilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_stat_t fileStat;
|
|
||||||
if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) {
|
|
||||||
zip_fclose(zipFile);
|
|
||||||
zip_close(archive);
|
|
||||||
throw std::runtime_error("Ошибка чтения ZIP-статистики.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<char> fileData;
|
|
||||||
fileData.resize(fileStat.size);
|
|
||||||
|
|
||||||
zip_fread(zipFile, fileData.data(), fileData.size());
|
|
||||||
|
|
||||||
zip_fclose(zipFile);
|
|
||||||
zip_close(archive);
|
|
||||||
|
|
||||||
return fileData;*/
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool findString(const char* in, char* list)
|
if (!file.read(buffer.data(), size)) {
|
||||||
{
|
return {};
|
||||||
size_t thisLength = strlen(in);
|
}
|
||||||
while (*list != 0)
|
|
||||||
{
|
|
||||||
size_t length = strcspn(list, " ");
|
|
||||||
|
|
||||||
if (thisLength == length)
|
return buffer;
|
||||||
if (!strncmp(in, list, length))
|
#endif
|
||||||
return true;
|
}
|
||||||
|
|
||||||
list += length;
|
std::vector<char> readFileFromZIP(const std::string &filename, const std::string &zipfilename) {
|
||||||
list += 1;
|
/*const std::string zipPath = zipfilename;
|
||||||
}
|
int zipErr;
|
||||||
return false;
|
zip_t* archive = zip_open(zipPath.c_str(), ZIP_RDONLY, &zipErr);
|
||||||
}
|
if (!archive) {
|
||||||
};
|
throw std::runtime_error("Ошибка открытия ZIP: " + zipPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cleanFilename = filename;
|
||||||
|
if (cleanFilename.rfind("./", 0) == 0) {
|
||||||
|
cleanFilename = cleanFilename.substr(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Ищем в ZIP: " << cleanFilename << std::endl;
|
||||||
|
|
||||||
|
zip_file_t* zipFile = zip_fopen(archive, cleanFilename.c_str(), 0);
|
||||||
|
if (!zipFile) {
|
||||||
|
zip_close(archive);
|
||||||
|
throw std::runtime_error("Файл не найден в ZIP: " + cleanFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_stat_t fileStat;
|
||||||
|
if (zip_stat(archive, cleanFilename.c_str(), 0, &fileStat) != 0) {
|
||||||
|
zip_fclose(zipFile);
|
||||||
|
zip_close(archive);
|
||||||
|
throw std::runtime_error("Ошибка чтения ZIP-статистики.");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> fileData;
|
||||||
|
fileData.resize(fileStat.size);
|
||||||
|
|
||||||
|
zip_fread(zipFile, fileData.data(), fileData.size());
|
||||||
|
|
||||||
|
zip_fclose(zipFile);
|
||||||
|
zip_close(archive);
|
||||||
|
|
||||||
|
return fileData;*/
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool findString(const char *in, char *list) {
|
||||||
|
size_t thisLength = strlen(in);
|
||||||
|
while (*list != 0) {
|
||||||
|
size_t length = strcspn(list, " ");
|
||||||
|
if (thisLength == length && !strncmp(in, list, length))
|
||||||
|
return true;
|
||||||
|
list += length + 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,25 +1,48 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Environment.h"
|
#include "Environment.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <android/log.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
ZL::Game game;
|
ZL::Game game;
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
extern "C" int SDL_main(int argc, char* argv[]) {
|
extern "C" int SDL_main(int argc, char* argv[]) {
|
||||||
#else
|
#else
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
|
// Инициализация SDL перед получением информации о дисплее
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL init failed: %s", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_DisplayMode displayMode;
|
SDL_DisplayMode displayMode;
|
||||||
SDL_GetCurrentDisplayMode(0, &displayMode);
|
if (SDL_GetCurrentDisplayMode(0, &displayMode) != 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
ZL::Environment::width = displayMode.w;
|
ZL::Environment::width = displayMode.w;
|
||||||
ZL::Environment::height = displayMode.h;
|
ZL::Environment::height = displayMode.h;
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "Game", "Display resolution: %dx%d",
|
||||||
|
ZL::Environment::width, ZL::Environment::height);
|
||||||
#else
|
#else
|
||||||
constexpr int CONST_WIDTH = 1280;
|
constexpr int CONST_WIDTH = 1280;
|
||||||
constexpr int CONST_HEIGHT = 720;
|
constexpr int CONST_HEIGHT = 720;
|
||||||
ZL::Environment::width = CONST_WIDTH;
|
ZL::Environment::width = CONST_WIDTH;
|
||||||
ZL::Environment::height = CONST_HEIGHT;
|
ZL::Environment::height = CONST_HEIGHT;
|
||||||
|
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||||
|
SDL_Log("SDL init failed: %s", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
@ -52,15 +75,18 @@ int main(int argc, char* argv[]) {
|
|||||||
ZL::Environment::window = win;
|
ZL::Environment::window = win;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
|
||||||
SDL_Log("SDL init failed: %s", SDL_GetError());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
|
||||||
|
|
||||||
ZL::Environment::window = SDL_CreateWindow(
|
ZL::Environment::window = SDL_CreateWindow(
|
||||||
"Space Ship Game",
|
"Space Ship Game",
|
||||||
@ -69,9 +95,12 @@ int main(int argc, char* argv[]) {
|
|||||||
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
|
// Для десктопа
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||||
|
|
||||||
ZL::Environment::window = SDL_CreateWindow(
|
ZL::Environment::window = SDL_CreateWindow(
|
||||||
"Space Ship Game",
|
"Space Ship Game",
|
||||||
@ -81,11 +110,63 @@ int main(int argc, char* argv[]) {
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
if (!ZL::Environment::window) {
|
||||||
SDL_GL_MakeCurrent(ZL::Environment::window, ctx);
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "Failed to create window: %s", SDL_GetError());
|
||||||
|
#else
|
||||||
|
SDL_Log("Failed to create window: %s", SDL_GetError());
|
||||||
|
#endif
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
game.setup();
|
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
||||||
|
if (!ctx) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_CreateContext failed: %s", SDL_GetError());
|
||||||
|
#else
|
||||||
|
SDL_Log("SDL_GL_CreateContext failed: %s", SDL_GetError());
|
||||||
|
#endif
|
||||||
|
SDL_DestroyWindow(ZL::Environment::window);
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GL_MakeCurrent(ZL::Environment::window, ctx) != 0) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_MakeCurrent failed: %s", SDL_GetError());
|
||||||
|
#else
|
||||||
|
SDL_Log("SDL_GL_MakeCurrent failed: %s", SDL_GetError());
|
||||||
|
#endif
|
||||||
|
SDL_GL_DeleteContext(ctx);
|
||||||
|
SDL_DestroyWindow(ZL::Environment::window);
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Настройка VSync
|
||||||
|
if (SDL_GL_SetSwapInterval(1) < 0) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_WARN, "Game", "Unable to set VSync: %s", SDL_GetError());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Настройка игры
|
||||||
|
try {
|
||||||
|
game.setup();
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, "Game", "Game setup failed: %s", e.what());
|
||||||
|
#else
|
||||||
|
std::cerr << "Game setup failed: " << e.what() << std::endl;
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
emscripten_set_main_loop(MainLoop, 0, 1);
|
emscripten_set_main_loop(MainLoop, 0, 1);
|
||||||
|
|||||||
BIN
app/src/main/assets/resources/sship001x.bmp
Normal file
BIN
app/src/main/assets/resources/sship001x.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 MiB |
@ -1,8 +1,7 @@
|
|||||||
#version 100
|
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
varying vec3 color;
|
||||||
|
|
||||||
varying vec3 fragmentColor;
|
void main()
|
||||||
|
{
|
||||||
void main(void) {
|
gl_FragColor = vec4(color, 1.0);
|
||||||
gl_FragColor = vec4(fragmentColor, 1.0);
|
|
||||||
}
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
#version 100
|
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
varying vec2 TexCoordOut;
|
|
||||||
uniform sampler2D Texture;
|
uniform sampler2D Texture;
|
||||||
|
varying vec2 texCoord;
|
||||||
|
|
||||||
void main(void) {
|
void main()
|
||||||
gl_FragColor = texture2D(Texture, TexCoordOut);
|
{
|
||||||
|
vec4 color = texture2D(Texture, texCoord);
|
||||||
|
gl_FragColor = color;
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
Loading…
Reference in New Issue
Block a user