diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 1c493fc24a9ef34a7e29be0c7ea17495919c9e0f..9e97f693384baf9aa39d556430b30daf1937f3b9 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,12 +7,12 @@ - + - + diff --git a/app/build.gradle b/app/build.gradle index 04434c57b32c10320e0f73b7d77af9cf0c040f5a..3dfd20828ec1e53e327c1a24f61c99845b683d59 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ android { defaultConfig { applicationId "com.example.game" - minSdk 33 + minSdk 21 targetSdk 33 versionCode 1 versionName "1.0" @@ -38,12 +38,6 @@ android { prefab true compose true } - externalNativeBuild { - cmake { - path file('src/main/cpp/CMakeLists.txt') - version '3.22.1' - } - } composeOptions { kotlinCompilerExtensionVersion '1.3.2' } diff --git a/app/src/main/cpp/AndroidOut.cpp b/app/src/main/cpp/AndroidOut.cpp deleted file mode 100644 index ade0014647f358cec127118981b789175f3a0ad9..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/AndroidOut.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "AndroidOut.h" - -AndroidOut androidOut("AO"); -std::ostream aout(&androidOut); \ No newline at end of file diff --git a/app/src/main/cpp/AndroidOut.h b/app/src/main/cpp/AndroidOut.h deleted file mode 100644 index 5c7b1397e45c939eb94078d9ae7d97a920d994db..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/AndroidOut.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ANDROIDGLINVESTIGATIONS_ANDROIDOUT_H -#define ANDROIDGLINVESTIGATIONS_ANDROIDOUT_H - -#include -#include - -/*! - * Use this to log strings out to logcat. Note that you should use std::endl to commit the line - * - * ex: - * aout << "Hello World" << std::endl; - */ -extern std::ostream aout; - -/*! - * Use this class to create an output stream that writes to logcat. By default, a global one is - * defined as @a aout - */ -class AndroidOut: public std::stringbuf { -public: - /*! - * Creates a new output stream for logcat - * @param kLogTag the log tag to output - */ - inline AndroidOut(const char* kLogTag) : logTag_(kLogTag){} - -protected: - virtual int sync() override { - __android_log_print(ANDROID_LOG_DEBUG, logTag_, "%s", str().c_str()); - str(""); - return 0; - } - -private: - const char* logTag_; -}; - -#endif //ANDROIDGLINVESTIGATIONS_ANDROIDOUT_H \ No newline at end of file diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt deleted file mode 100644 index cfb5e276196242a48918c041002b0a1ade63f1f9..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# For more information about using CMake with Android Studio, read the -# documentation: https://d.android.com/studio/projects/add-native-code.html - -cmake_minimum_required(VERSION 3.22.1) - -project("game") - -# Creates your game shared library. The name must be the same as the -# one used for loading in your Kotlin/Java or AndroidManifest.txt files. -add_library(game SHARED - main.cpp - AndroidOut.cpp - Renderer.cpp - Shader.cpp - TextureAsset.cpp - Utility.cpp) - -# Searches for a package provided by the game activity dependency -find_package(game-activity REQUIRED CONFIG) - -# Configure libraries CMake uses to link your target library. -target_link_libraries(game - # The game activity - game-activity::game-activity - - # EGL and other dependent libraries required for drawing - # and interacting with Android system - EGL - GLESv3 - jnigraphics - android - log) \ No newline at end of file diff --git a/app/src/main/cpp/Model.h b/app/src/main/cpp/Model.h deleted file mode 100644 index d78283caf357b41cb052f3ddd3692875640b6965..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/Model.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef ANDROIDGLINVESTIGATIONS_MODEL_H -#define ANDROIDGLINVESTIGATIONS_MODEL_H - -#include -#include "TextureAsset.h" - -union Vector3 { - struct { - float x, y, z; - }; - float idx[3]; -}; - -union Vector2 { - struct { - float x, y; - }; - struct { - float u, v; - }; - float idx[2]; -}; - -struct Vertex { - constexpr Vertex(const Vector3 &inPosition, const Vector2 &inUV) : position(inPosition), - uv(inUV) {} - - Vector3 position; - Vector2 uv; -}; - -typedef uint16_t Index; - -class Model { -public: - inline Model( - std::vector vertices, - std::vector indices, - std::shared_ptr spTexture) - : vertices_(std::move(vertices)), - indices_(std::move(indices)), - spTexture_(std::move(spTexture)) {} - - inline const Vertex *getVertexData() const { - return vertices_.data(); - } - - inline const size_t getIndexCount() const { - return indices_.size(); - } - - inline const Index *getIndexData() const { - return indices_.data(); - } - - inline const TextureAsset &getTexture() const { - return *spTexture_; - } - -private: - std::vector vertices_; - std::vector indices_; - std::shared_ptr spTexture_; -}; - -#endif //ANDROIDGLINVESTIGATIONS_MODEL_H \ No newline at end of file diff --git a/app/src/main/cpp/Renderer.cpp b/app/src/main/cpp/Renderer.cpp deleted file mode 100644 index d9c9a5508c4aaf1c68e83111ee654923c70c5425..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/Renderer.cpp +++ /dev/null @@ -1,378 +0,0 @@ -#include "Renderer.h" - -#include -#include -#include -#include -#include - -#include "AndroidOut.h" -#include "Shader.h" -#include "Utility.h" -#include "TextureAsset.h" - -//! executes glGetString and outputs the result to logcat -#define PRINT_GL_STRING(s) {aout << #s": "<< glGetString(s) << std::endl;} - -/*! - * @brief if glGetString returns a space separated list of elements, prints each one on a new line - * - * This works by creating an istringstream of the input c-style string. Then that is used to create - * a vector -- each element of the vector is a new element in the input string. Finally a foreach - * loop consumes this and outputs it to logcat using @a aout - */ -#define PRINT_GL_STRING_AS_LIST(s) { \ -std::istringstream extensionStream((const char *) glGetString(s));\ -std::vector extensionList(\ - std::istream_iterator{extensionStream},\ - std::istream_iterator());\ -aout << #s":\n";\ -for (auto& extension: extensionList) {\ - aout << extension << "\n";\ -}\ -aout << std::endl;\ -} - -//! Color for cornflower blue. Can be sent directly to glClearColor -#define CORNFLOWER_BLUE 100 / 255.f, 149 / 255.f, 237 / 255.f, 1 - -// Vertex shader, you'd typically load this from assets -static const char *vertex = R"vertex(#version 300 es -in vec3 inPosition; -in vec2 inUV; - -out vec2 fragUV; - -uniform mat4 uProjection; - -void main() { - fragUV = inUV; - gl_Position = uProjection * vec4(inPosition, 1.0); -} -)vertex"; - -// Fragment shader, you'd typically load this from assets -static const char *fragment = R"fragment(#version 300 es -precision mediump float; - -in vec2 fragUV; - -uniform sampler2D uTexture; - -out vec4 outColor; - -void main() { - outColor = texture(uTexture, fragUV); -} -)fragment"; - -/*! - * Half the height of the projection matrix. This gives you a renderable area of height 4 ranging - * from -2 to 2 - */ -static constexpr float kProjectionHalfHeight = 2.f; - -/*! - * The near plane distance for the projection matrix. Since this is an orthographic projection - * matrix, it's convenient to have negative values for sorting (and avoiding z-fighting at 0). - */ -static constexpr float kProjectionNearPlane = -1.f; - -/*! - * The far plane distance for the projection matrix. Since this is an orthographic porjection - * matrix, it's convenient to have the far plane equidistant from 0 as the near plane. - */ -static constexpr float kProjectionFarPlane = 1.f; - -Renderer::~Renderer() { - if (display_ != EGL_NO_DISPLAY) { - eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (context_ != EGL_NO_CONTEXT) { - eglDestroyContext(display_, context_); - context_ = EGL_NO_CONTEXT; - } - if (surface_ != EGL_NO_SURFACE) { - eglDestroySurface(display_, surface_); - surface_ = EGL_NO_SURFACE; - } - eglTerminate(display_); - display_ = EGL_NO_DISPLAY; - } -} - -void Renderer::render() { - // Check to see if the surface has changed size. This is _necessary_ to do every frame when - // using immersive mode as you'll get no other notification that your renderable area has - // changed. - updateRenderArea(); - - // When the renderable area changes, the projection matrix has to also be updated. This is true - // even if you change from the sample orthographic projection matrix as your aspect ratio has - // likely changed. - if (shaderNeedsNewProjectionMatrix_) { - // a placeholder projection matrix allocated on the stack. Column-major memory layout - float projectionMatrix[16] = {0}; - - // build an orthographic projection matrix for 2d rendering - Utility::buildOrthographicMatrix( - projectionMatrix, - kProjectionHalfHeight, - float(width_) / height_, - kProjectionNearPlane, - kProjectionFarPlane); - - // send the matrix to the shader - // Note: the shader must be active for this to work. Since we only have one shader for this - // demo, we can assume that it's active. - shader_->setProjectionMatrix(projectionMatrix); - - // make sure the matrix isn't generated every frame - shaderNeedsNewProjectionMatrix_ = false; - } - - // clear the color buffer - glClear(GL_COLOR_BUFFER_BIT); - - // Render all the models. There's no depth testing in this sample so they're accepted in the - // order provided. But the sample EGL setup requests a 24 bit depth buffer so you could - // configure it at the end of initRenderer - if (!models_.empty()) { - for (const auto &model: models_) { - shader_->drawModel(model); - } - } - - // Present the rendered image. This is an implicit glFlush. - auto swapResult = eglSwapBuffers(display_, surface_); - assert(swapResult == EGL_TRUE); -} - -void Renderer::initRenderer() { - // Choose your render attributes - constexpr EGLint attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_DEPTH_SIZE, 24, - EGL_NONE - }; - - // The default display is probably what you want on Android - auto display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(display, nullptr, nullptr); - - // figure out how many configs there are - EGLint numConfigs; - eglChooseConfig(display, attribs, nullptr, 0, &numConfigs); - - // get the list of configurations - std::unique_ptr supportedConfigs(new EGLConfig[numConfigs]); - eglChooseConfig(display, attribs, supportedConfigs.get(), numConfigs, &numConfigs); - - // Find a config we like. - // Could likely just grab the first if we don't care about anything else in the config. - // Otherwise hook in your own heuristic - auto config = *std::find_if( - supportedConfigs.get(), - supportedConfigs.get() + numConfigs, - [&display](const EGLConfig &config) { - EGLint red, green, blue, depth; - if (eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red) - && eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green) - && eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue) - && eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth)) { - - aout << "Found config with " << red << ", " << green << ", " << blue << ", " - << depth << std::endl; - return red == 8 && green == 8 && blue == 8 && depth == 24; - } - return false; - }); - - aout << "Found " << numConfigs << " configs" << std::endl; - aout << "Chose " << config << std::endl; - - // create the proper window surface - EGLint format; - eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); - EGLSurface surface = eglCreateWindowSurface(display, config, app_->window, nullptr); - - // Create a GLES 3 context - EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; - EGLContext context = eglCreateContext(display, config, nullptr, contextAttribs); - - // get some window metrics - auto madeCurrent = eglMakeCurrent(display, surface, surface, context); - assert(madeCurrent); - - display_ = display; - surface_ = surface; - context_ = context; - - // make width and height invalid so it gets updated the first frame in @a updateRenderArea() - width_ = -1; - height_ = -1; - - PRINT_GL_STRING(GL_VENDOR); - PRINT_GL_STRING(GL_RENDERER); - PRINT_GL_STRING(GL_VERSION); - PRINT_GL_STRING_AS_LIST(GL_EXTENSIONS); - - shader_ = std::unique_ptr( - Shader::loadShader(vertex, fragment, "inPosition", "inUV", "uProjection")); - assert(shader_); - - // Note: there's only one shader in this demo, so I'll activate it here. For a more complex game - // you'll want to track the active shader and activate/deactivate it as necessary - shader_->activate(); - - // setup any other gl related global states - glClearColor(CORNFLOWER_BLUE); - - // enable alpha globally for now, you probably don't want to do this in a game - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // get some demo models into memory - createModels(); -} - -void Renderer::updateRenderArea() { - EGLint width; - eglQuerySurface(display_, surface_, EGL_WIDTH, &width); - - EGLint height; - eglQuerySurface(display_, surface_, EGL_HEIGHT, &height); - - if (width != width_ || height != height_) { - width_ = width; - height_ = height; - glViewport(0, 0, width, height); - - // make sure that we lazily recreate the projection matrix before we render - shaderNeedsNewProjectionMatrix_ = true; - } -} - -/** - * @brief Create any demo models we want for this demo. - */ -void Renderer::createModels() { - /* - * This is a square: - * 0 --- 1 - * | \ | - * | \ | - * | \ | - * 3 --- 2 - */ - std::vector vertices = { - Vertex(Vector3{1, 1, 0}, Vector2{0, 0}), // 0 - Vertex(Vector3{-1, 1, 0}, Vector2{1, 0}), // 1 - Vertex(Vector3{-1, -1, 0}, Vector2{1, 1}), // 2 - Vertex(Vector3{1, -1, 0}, Vector2{0, 1}) // 3 - }; - std::vector indices = { - 0, 1, 2, 0, 2, 3 - }; - - // loads an image and assigns it to the square. - // - // Note: there is no texture management in this sample, so if you reuse an image be careful not - // to load it repeatedly. Since you get a shared_ptr you can safely reuse it in many models. - auto assetManager = app_->activity->assetManager; - auto spAndroidRobotTexture = TextureAsset::loadAsset(assetManager, "android_robot.png"); - - // Create a model and put it in the back of the render list. - models_.emplace_back(vertices, indices, spAndroidRobotTexture); -} - -void Renderer::handleInput() { - // handle all queued inputs - auto *inputBuffer = android_app_swap_input_buffers(app_); - if (!inputBuffer) { - // no inputs yet. - return; - } - - // handle motion events (motionEventsCounts can be 0). - for (auto i = 0; i < inputBuffer->motionEventsCount; i++) { - auto &motionEvent = inputBuffer->motionEvents[i]; - auto action = motionEvent.action; - - // Find the pointer index, mask and bitshift to turn it into a readable value. - auto pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) - >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; - aout << "Pointer(s): "; - - // get the x and y position of this event if it is not ACTION_MOVE. - auto &pointer = motionEvent.pointers[pointerIndex]; - auto x = GameActivityPointerAxes_getX(&pointer); - auto y = GameActivityPointerAxes_getY(&pointer); - - // determine the action type and process the event accordingly. - switch (action & AMOTION_EVENT_ACTION_MASK) { - case AMOTION_EVENT_ACTION_DOWN: - case AMOTION_EVENT_ACTION_POINTER_DOWN: - aout << "(" << pointer.id << ", " << x << ", " << y << ") " - << "Pointer Down"; - break; - - case AMOTION_EVENT_ACTION_CANCEL: - // treat the CANCEL as an UP event: doing nothing in the app, except - // removing the pointer from the cache if pointers are locally saved. - // code pass through on purpose. - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_POINTER_UP: - aout << "(" << pointer.id << ", " << x << ", " << y << ") " - << "Pointer Up"; - break; - - case AMOTION_EVENT_ACTION_MOVE: - // There is no pointer index for ACTION_MOVE, only a snapshot of - // all active pointers; app needs to cache previous active pointers - // to figure out which ones are actually moved. - for (auto index = 0; index < motionEvent.pointerCount; index++) { - pointer = motionEvent.pointers[index]; - x = GameActivityPointerAxes_getX(&pointer); - y = GameActivityPointerAxes_getY(&pointer); - aout << "(" << pointer.id << ", " << x << ", " << y << ")"; - - if (index != (motionEvent.pointerCount - 1)) aout << ","; - aout << " "; - } - aout << "Pointer Move"; - break; - default: - aout << "Unknown MotionEvent Action: " << action; - } - aout << std::endl; - } - // clear the motion input count in this buffer for main thread to re-use. - android_app_clear_motion_events(inputBuffer); - - // handle input key events. - for (auto i = 0; i < inputBuffer->keyEventsCount; i++) { - auto &keyEvent = inputBuffer->keyEvents[i]; - aout << "Key: " << keyEvent.keyCode <<" "; - switch (keyEvent.action) { - case AKEY_EVENT_ACTION_DOWN: - aout << "Key Down"; - break; - case AKEY_EVENT_ACTION_UP: - aout << "Key Up"; - break; - case AKEY_EVENT_ACTION_MULTIPLE: - // Deprecated since Android API level 29. - aout << "Multiple Key Actions"; - break; - default: - aout << "Unknown KeyEvent Action: " << keyEvent.action; - } - aout << std::endl; - } - // clear the key input count too. - android_app_clear_key_events(inputBuffer); -} \ No newline at end of file diff --git a/app/src/main/cpp/Renderer.h b/app/src/main/cpp/Renderer.h deleted file mode 100644 index ec6805160e5304e09fb02831035987fe3660a13c..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/Renderer.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef ANDROIDGLINVESTIGATIONS_RENDERER_H -#define ANDROIDGLINVESTIGATIONS_RENDERER_H - -#include -#include - -#include "Model.h" -#include "Shader.h" - -struct android_app; - -class Renderer { -public: - /*! - * @param pApp the android_app this Renderer belongs to, needed to configure GL - */ - inline Renderer(android_app *pApp) : - app_(pApp), - display_(EGL_NO_DISPLAY), - surface_(EGL_NO_SURFACE), - context_(EGL_NO_CONTEXT), - width_(0), - height_(0), - shaderNeedsNewProjectionMatrix_(true) { - initRenderer(); - } - - virtual ~Renderer(); - - /*! - * Handles input from the android_app. - * - * Note: this will clear the input queue - */ - void handleInput(); - - /*! - * Renders all the models in the renderer - */ - void render(); - -private: - /*! - * Performs necessary OpenGL initialization. Customize this if you want to change your EGL - * context or application-wide settings. - */ - void initRenderer(); - - /*! - * @brief we have to check every frame to see if the framebuffer has changed in size. If it has, - * update the viewport accordingly - */ - void updateRenderArea(); - - /*! - * Creates the models for this sample. You'd likely load a scene configuration from a file or - * use some other setup logic in your full game. - */ - void createModels(); - - android_app *app_; - EGLDisplay display_; - EGLSurface surface_; - EGLContext context_; - EGLint width_; - EGLint height_; - - bool shaderNeedsNewProjectionMatrix_; - - std::unique_ptr shader_; - std::vector models_; -}; - -#endif //ANDROIDGLINVESTIGATIONS_RENDERER_H \ No newline at end of file diff --git a/app/src/main/cpp/Shader.cpp b/app/src/main/cpp/Shader.cpp deleted file mode 100644 index 7784693cae67f06a9e5a7bd0ea012a71e9ceb5c8..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/Shader.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "Shader.h" - -#include "AndroidOut.h" -#include "Model.h" -#include "Utility.h" - -Shader *Shader::loadShader( - const std::string &vertexSource, - const std::string &fragmentSource, - const std::string &positionAttributeName, - const std::string &uvAttributeName, - const std::string &projectionMatrixUniformName) { - Shader *shader = nullptr; - - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource); - if (!vertexShader) { - return nullptr; - } - - GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource); - if (!fragmentShader) { - glDeleteShader(vertexShader); - return nullptr; - } - - GLuint program = glCreateProgram(); - if (program) { - glAttachShader(program, vertexShader); - glAttachShader(program, fragmentShader); - - glLinkProgram(program); - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint logLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); - - // If we fail to link the shader program, log the result for debugging - if (logLength) { - GLchar *log = new GLchar[logLength]; - glGetProgramInfoLog(program, logLength, nullptr, log); - aout << "Failed to link program with:\n" << log << std::endl; - delete[] log; - } - - glDeleteProgram(program); - } else { - // Get the attribute and uniform locations by name. You may also choose to hardcode - // indices with layout= in your shader, but it is not done in this sample - GLint positionAttribute = glGetAttribLocation(program, positionAttributeName.c_str()); - GLint uvAttribute = glGetAttribLocation(program, uvAttributeName.c_str()); - GLint projectionMatrixUniform = glGetUniformLocation( - program, - projectionMatrixUniformName.c_str()); - - // Only create a new shader if all the attributes are found. - if (positionAttribute != -1 - && uvAttribute != -1 - && projectionMatrixUniform != -1) { - - shader = new Shader( - program, - positionAttribute, - uvAttribute, - projectionMatrixUniform); - } else { - glDeleteProgram(program); - } - } - } - - // The shaders are no longer needed once the program is linked. Release their memory. - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - - return shader; -} - -GLuint Shader::loadShader(GLenum shaderType, const std::string &shaderSource) { - Utility::assertGlError(); - GLuint shader = glCreateShader(shaderType); - if (shader) { - auto *shaderRawString = (GLchar *) shaderSource.c_str(); - GLint shaderLength = shaderSource.length(); - glShaderSource(shader, 1, &shaderRawString, &shaderLength); - glCompileShader(shader); - - GLint shaderCompiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompiled); - - // If the shader doesn't compile, log the result to the terminal for debugging - if (!shaderCompiled) { - GLint infoLength = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength); - - if (infoLength) { - auto *infoLog = new GLchar[infoLength]; - glGetShaderInfoLog(shader, infoLength, nullptr, infoLog); - aout << "Failed to compile with:\n" << infoLog << std::endl; - delete[] infoLog; - } - - glDeleteShader(shader); - shader = 0; - } - } - return shader; -} - -void Shader::activate() const { - glUseProgram(program_); -} - -void Shader::deactivate() const { - glUseProgram(0); -} - -void Shader::drawModel(const Model &model) const { - // The position attribute is 3 floats - glVertexAttribPointer( - position_, // attrib - 3, // elements - GL_FLOAT, // of type float - GL_FALSE, // don't normalize - sizeof(Vertex), // stride is Vertex bytes - model.getVertexData() // pull from the start of the vertex data - ); - glEnableVertexAttribArray(position_); - - // The uv attribute is 2 floats - glVertexAttribPointer( - uv_, // attrib - 2, // elements - GL_FLOAT, // of type float - GL_FALSE, // don't normalize - sizeof(Vertex), // stride is Vertex bytes - ((uint8_t *) model.getVertexData()) + sizeof(Vector3) // offset Vector3 from the start - ); - glEnableVertexAttribArray(uv_); - - // Setup the texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, model.getTexture().getTextureID()); - - // Draw as indexed triangles - glDrawElements(GL_TRIANGLES, model.getIndexCount(), GL_UNSIGNED_SHORT, model.getIndexData()); - - glDisableVertexAttribArray(uv_); - glDisableVertexAttribArray(position_); -} - -void Shader::setProjectionMatrix(float *projectionMatrix) const { - glUniformMatrix4fv(projectionMatrix_, 1, false, projectionMatrix); -} \ No newline at end of file diff --git a/app/src/main/cpp/Shader.h b/app/src/main/cpp/Shader.h deleted file mode 100644 index f04324dfb7a9dbafb1f0eabe3ae0403b93316f77..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/Shader.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef ANDROIDGLINVESTIGATIONS_SHADER_H -#define ANDROIDGLINVESTIGATIONS_SHADER_H - -#include -#include - -class Model; - -/*! - * A class representing a simple shader program. It consists of vertex and fragment components. The - * input attributes are a position (as a Vector3) and a uv (as a Vector2). It also takes a uniform - * to be used as the entire model/view/projection matrix. The shader expects a single texture for - * fragment shading, and does no other lighting calculations (thus no uniforms for lights or normal - * attributes). - */ -class Shader { -public: - /*! - * Loads a shader given the full sourcecode and names for necessary attributes and uniforms to - * link to. Returns a valid shader on success or null on failure. Shader resources are - * automatically cleaned up on destruction. - * - * @param vertexSource The full source code for your vertex program - * @param fragmentSource The full source code of your fragment program - * @param positionAttributeName The name of the position attribute in your vertex program - * @param uvAttributeName The name of the uv coordinate attribute in your vertex program - * @param projectionMatrixUniformName The name of your model/view/projection matrix uniform - * @return a valid Shader on success, otherwise null. - */ - static Shader *loadShader( - const std::string &vertexSource, - const std::string &fragmentSource, - const std::string &positionAttributeName, - const std::string &uvAttributeName, - const std::string &projectionMatrixUniformName); - - inline ~Shader() { - if (program_) { - glDeleteProgram(program_); - program_ = 0; - } - } - - /*! - * Prepares the shader for use, call this before executing any draw commands - */ - void activate() const; - - /*! - * Cleans up the shader after use, call this after executing any draw commands - */ - void deactivate() const; - - /*! - * Renders a single model - * @param model a model to render - */ - void drawModel(const Model &model) const; - - /*! - * Sets the model/view/projection matrix in the shader. - * @param projectionMatrix sixteen floats, column major, defining an OpenGL projection matrix. - */ - void setProjectionMatrix(float *projectionMatrix) const; - -private: - /*! - * Helper function to load a shader of a given type - * @param shaderType The OpenGL shader type. Should either be GL_VERTEX_SHADER or GL_FRAGMENT_SHADER - * @param shaderSource The full source of the shader - * @return the id of the shader, as returned by glCreateShader, or 0 in the case of an error - */ - static GLuint loadShader(GLenum shaderType, const std::string &shaderSource); - - /*! - * Constructs a new instance of a shader. Use @a loadShader - * @param program the GL program id of the shader - * @param position the attribute location of the position - * @param uv the attribute location of the uv coordinates - * @param projectionMatrix the uniform location of the projection matrix - */ - constexpr Shader( - GLuint program, - GLint position, - GLint uv, - GLint projectionMatrix) - : program_(program), - position_(position), - uv_(uv), - projectionMatrix_(projectionMatrix) {} - - GLuint program_; - GLint position_; - GLint uv_; - GLint projectionMatrix_; -}; - -#endif //ANDROIDGLINVESTIGATIONS_SHADER_H \ No newline at end of file diff --git a/app/src/main/cpp/TextureAsset.cpp b/app/src/main/cpp/TextureAsset.cpp deleted file mode 100644 index 0ff1a9ccb9350e236bc796e9b1a32663bb2fadeb..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/TextureAsset.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include "TextureAsset.h" -#include "AndroidOut.h" -#include "Utility.h" - -std::shared_ptr -TextureAsset::loadAsset(AAssetManager *assetManager, const std::string &assetPath) { - // Get the image from asset manager - auto pAndroidRobotPng = AAssetManager_open( - assetManager, - assetPath.c_str(), - AASSET_MODE_BUFFER); - - // Make a decoder to turn it into a texture - AImageDecoder *pAndroidDecoder = nullptr; - auto result = AImageDecoder_createFromAAsset(pAndroidRobotPng, &pAndroidDecoder); - assert(result == ANDROID_IMAGE_DECODER_SUCCESS); - - // make sure we get 8 bits per channel out. RGBA order. - AImageDecoder_setAndroidBitmapFormat(pAndroidDecoder, ANDROID_BITMAP_FORMAT_RGBA_8888); - - // Get the image header, to help set everything up - const AImageDecoderHeaderInfo *pAndroidHeader = nullptr; - pAndroidHeader = AImageDecoder_getHeaderInfo(pAndroidDecoder); - - // important metrics for sending to GL - auto width = AImageDecoderHeaderInfo_getWidth(pAndroidHeader); - auto height = AImageDecoderHeaderInfo_getHeight(pAndroidHeader); - auto stride = AImageDecoder_getMinimumStride(pAndroidDecoder); - - // Get the bitmap data of the image - auto upAndroidImageData = std::make_unique>(height * stride); - auto decodeResult = AImageDecoder_decodeImage( - pAndroidDecoder, - upAndroidImageData->data(), - stride, - upAndroidImageData->size()); - assert(decodeResult == ANDROID_IMAGE_DECODER_SUCCESS); - - // Get an opengl texture - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); - - // Clamp to the edge, you'll get odd results alpha blending if you don't - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Load the texture into VRAM - glTexImage2D( - GL_TEXTURE_2D, // target - 0, // mip level - GL_RGBA, // internal format, often advisable to use BGR - width, // width of the texture - height, // height of the texture - 0, // border (always 0) - GL_RGBA, // format - GL_UNSIGNED_BYTE, // type - upAndroidImageData->data() // Data to upload - ); - - // generate mip levels. Not really needed for 2D, but good to do - glGenerateMipmap(GL_TEXTURE_2D); - - // cleanup helpers - AImageDecoder_delete(pAndroidDecoder); - AAsset_close(pAndroidRobotPng); - - // Create a shared pointer so it can be cleaned up easily/automatically - return std::shared_ptr(new TextureAsset(textureId)); -} - -TextureAsset::~TextureAsset() { - // return texture resources - glDeleteTextures(1, &textureID_); - textureID_ = 0; -} \ No newline at end of file diff --git a/app/src/main/cpp/TextureAsset.h b/app/src/main/cpp/TextureAsset.h deleted file mode 100644 index 8337145cfdc24b2d4409c3d6773ae29f3cab0fec..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/TextureAsset.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef ANDROIDGLINVESTIGATIONS_TEXTUREASSET_H -#define ANDROIDGLINVESTIGATIONS_TEXTUREASSET_H - -#include -#include -#include -#include -#include - -class TextureAsset { -public: - /*! - * Loads a texture asset from the assets/ directory - * @param assetManager Asset manager to use - * @param assetPath The path to the asset - * @return a shared pointer to a texture asset, resources will be reclaimed when it's cleaned up - */ - static std::shared_ptr - loadAsset(AAssetManager *assetManager, const std::string &assetPath); - - ~TextureAsset(); - - /*! - * @return the texture id for use with OpenGL - */ - constexpr GLuint getTextureID() const { return textureID_; } - -private: - inline TextureAsset(GLuint textureId) : textureID_(textureId) {} - - GLuint textureID_; -}; - -#endif //ANDROIDGLINVESTIGATIONS_TEXTUREASSET_H \ No newline at end of file diff --git a/app/src/main/cpp/Utility.cpp b/app/src/main/cpp/Utility.cpp deleted file mode 100644 index be66a87a76047646adbe3cb9af24dcd61a54b5cd..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/Utility.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "Utility.h" -#include "AndroidOut.h" - -#include - -#define CHECK_ERROR(e) case e: aout << "GL Error: "#e << std::endl; break; - -bool Utility::checkAndLogGlError(bool alwaysLog) { - GLenum error = glGetError(); - if (error == GL_NO_ERROR) { - if (alwaysLog) { - aout << "No GL error" << std::endl; - } - return true; - } else { - switch (error) { - CHECK_ERROR(GL_INVALID_ENUM); - CHECK_ERROR(GL_INVALID_VALUE); - CHECK_ERROR(GL_INVALID_OPERATION); - CHECK_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION); - CHECK_ERROR(GL_OUT_OF_MEMORY); - default: - aout << "Unknown GL error: " << error << std::endl; - } - return false; - } -} - -float * -Utility::buildOrthographicMatrix(float *outMatrix, float halfHeight, float aspect, float near, - float far) { - float halfWidth = halfHeight * aspect; - - // column 1 - outMatrix[0] = 1.f / halfWidth; - outMatrix[1] = 0.f; - outMatrix[2] = 0.f; - outMatrix[3] = 0.f; - - // column 2 - outMatrix[4] = 0.f; - outMatrix[5] = 1.f / halfHeight; - outMatrix[6] = 0.f; - outMatrix[7] = 0.f; - - // column 3 - outMatrix[8] = 0.f; - outMatrix[9] = 0.f; - outMatrix[10] = -2.f / (far - near); - outMatrix[11] = -(far + near) / (far - near); - - // column 4 - outMatrix[12] = 0.f; - outMatrix[13] = 0.f; - outMatrix[14] = 0.f; - outMatrix[15] = 1.f; - - return outMatrix; -} - -float *Utility::buildIdentityMatrix(float *outMatrix) { - // column 1 - outMatrix[0] = 1.f; - outMatrix[1] = 0.f; - outMatrix[2] = 0.f; - outMatrix[3] = 0.f; - - // column 2 - outMatrix[4] = 0.f; - outMatrix[5] = 1.f; - outMatrix[6] = 0.f; - outMatrix[7] = 0.f; - - // column 3 - outMatrix[8] = 0.f; - outMatrix[9] = 0.f; - outMatrix[10] = 1.f; - outMatrix[11] = 0.f; - - // column 4 - outMatrix[12] = 0.f; - outMatrix[13] = 0.f; - outMatrix[14] = 0.f; - outMatrix[15] = 1.f; - - return outMatrix; -} \ No newline at end of file diff --git a/app/src/main/cpp/Utility.h b/app/src/main/cpp/Utility.h deleted file mode 100644 index 99e49f12c1dd9c6d7a3c468423c21a196d010f95..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/Utility.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef ANDROIDGLINVESTIGATIONS_UTILITY_H -#define ANDROIDGLINVESTIGATIONS_UTILITY_H - -#include - -class Utility { -public: - static bool checkAndLogGlError(bool alwaysLog = false); - - static inline void assertGlError() { assert(checkAndLogGlError()); } - - /** - * Generates an orthographic projection matrix given the half height, aspect ratio, near, and far - * planes - * - * @param outMatrix the matrix to write into - * @param halfHeight half of the height of the screen - * @param aspect the width of the screen divided by the height - * @param near the distance of the near plane - * @param far the distance of the far plane - * @return the generated matrix, this will be the same as @a outMatrix so you can chain calls - * together if needed - */ - static float *buildOrthographicMatrix( - float *outMatrix, - float halfHeight, - float aspect, - float near, - float far); - - static float *buildIdentityMatrix(float *outMatrix); -}; - -#endif //ANDROIDGLINVESTIGATIONS_UTILITY_H \ No newline at end of file diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp deleted file mode 100644 index 09983cd1b197226d77a725a8e9051c0d1be62680..0000000000000000000000000000000000000000 --- a/app/src/main/cpp/main.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include - -#include "AndroidOut.h" -#include "Renderer.h" - -#include -#include - -extern "C" { - -#include - -/*! - * Handles commands sent to this Android application - * @param pApp the app the commands are coming from - * @param cmd the command to handle - */ -void handle_cmd(android_app *pApp, int32_t cmd) { - switch (cmd) { - case APP_CMD_INIT_WINDOW: - // A new window is created, associate a renderer with it. You may replace this with a - // "game" class if that suits your needs. Remember to change all instances of userData - // if you change the class here as a reinterpret_cast is dangerous this in the - // android_main function and the APP_CMD_TERM_WINDOW handler case. - pApp->userData = new Renderer(pApp); - break; - case APP_CMD_TERM_WINDOW: - // The window is being destroyed. Use this to clean up your userData to avoid leaking - // resources. - // - // We have to check if userData is assigned just in case this comes in really quickly - if (pApp->userData) { - // - auto *pRenderer = reinterpret_cast(pApp->userData); - pApp->userData = nullptr; - delete pRenderer; - } - break; - default: - break; - } -} - -/*! - * Enable the motion events you want to handle; not handled events are - * passed back to OS for further processing. For this example case, - * only pointer and joystick devices are enabled. - * - * @param motionEvent the newly arrived GameActivityMotionEvent. - * @return true if the event is from a pointer or joystick device, - * false for all other input devices. - */ -bool motion_event_filter_func(const GameActivityMotionEvent *motionEvent) { - auto sourceClass = motionEvent->source & AINPUT_SOURCE_CLASS_MASK; - return (sourceClass == AINPUT_SOURCE_CLASS_POINTER || - sourceClass == AINPUT_SOURCE_CLASS_JOYSTICK); -} - -/*! - * This the main entry point for a native activity - */ -void android_main(struct android_app *pApp) { - // Can be removed, useful to ensure your code is running - aout << "Welcome to android_main" << std::endl; - - // Register an event handler for Android events - pApp->onAppCmd = handle_cmd; - - // Set input event filters (set it to NULL if the app wants to process all inputs). - // Note that for key inputs, this example uses the default default_key_filter() - // implemented in android_native_app_glue.c. - android_app_set_motion_event_filter(pApp, motion_event_filter_func); - - // This sets up a typical game/event loop. It will run until the app is destroyed. - int events; - android_poll_source *pSource; - do { - // Process all pending events before running game logic. - if (ALooper_pollAll(0, nullptr, &events, (void **) &pSource) >= 0) { - if (pSource) { - pSource->process(pApp, pSource); - } - } - - // Check if any user data is associated. This is assigned in handle_cmd - if (pApp->userData) { - - // We know that our user data is a Renderer, so reinterpret cast it. If you change your - // user data remember to change it here - auto *pRenderer = reinterpret_cast(pApp->userData); - - // Process game input - pRenderer->handleInput(); - - // Render a frame - pRenderer->render(); - } - } while (!pApp->destroyRequested); -} -} \ No newline at end of file diff --git a/app/src/main/java/com/example/game/TicTacToe.kt b/app/src/main/java/com/example/game/TicTacToe.kt index 69d7dd46bc91135fa05a0e396831a54f28e40433..5b34048c69ea184d7a3cc599bf1ed8b16a6da28c 100644 --- a/app/src/main/java/com/example/game/TicTacToe.kt +++ b/app/src/main/java/com/example/game/TicTacToe.kt @@ -9,6 +9,7 @@ import android.util.Log import android.view.View import android.widget.Button import android.widget.ImageButton +import android.widget.ImageView import android.widget.TextView import androidx.activity.ComponentActivity import androidx.appcompat.app.AlertDialog @@ -194,7 +195,10 @@ class TicTacToe : ComponentActivity() { } else { resources.getDrawable(R.drawable.cross_blue) } - buttons[number.first*3 + number.second].background = w + //buttons[number.first*3 + number.second].background = w + //buttons[number.first*3 + number.second].setImageResource(R.drawable.cross_blue) + val iv: ImageView = findViewById(R.id.imageView) + iv.setImageResource(R.drawable.cross_blue) enableAllButtons() // Смена текущего игрока currentPlayer = if (currentPlayer == 1) 2 else 1 @@ -490,6 +494,7 @@ class TicTacToe : ComponentActivity() { writer.close() reader.close() } + timer.cancel() finish() // Закрываем меню после запуска игры } diff --git a/app/src/main/res/drawable/circle.png b/app/src/main/res/drawable/circle.png deleted file mode 100644 index 875f1479acc07fdbbe7402b0f67504577b65a4da..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/drawable/circle.png and /dev/null differ diff --git a/app/src/main/res/drawable/circle_blue.png b/app/src/main/res/drawable/circle_blue.png deleted file mode 100644 index 8b90dc2b00153e40aa6ba4483cc5568ca33a30f8..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/drawable/circle_blue.png and /dev/null differ diff --git a/app/src/main/res/drawable/loading.gif b/app/src/main/res/drawable/loading.gif deleted file mode 100644 index b8df3ff1da6fea1b2670be37c98d9a57e038dead..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/drawable/loading.gif and /dev/null differ diff --git a/app/src/main/res/drawable/map.png b/app/src/main/res/drawable/map.png deleted file mode 100644 index dc0fa9e05b4d3fd6c84cb22997d646254b0cd003..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/drawable/map.png and /dev/null differ diff --git a/app/src/main/res/drawable/zamok.jpg b/app/src/main/res/drawable/zamok.jpg deleted file mode 100644 index c5ff6b23a5ed19952f8334fc0d9f6bfcfe914823..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/drawable/zamok.jpg and /dev/null differ diff --git a/app/src/main/res/drawable/zamokenemy.jpg b/app/src/main/res/drawable/zamokenemy.jpg deleted file mode 100644 index 02b89ee0d14d6dd217151a4a1b5f117483f8b830..0000000000000000000000000000000000000000 Binary files a/app/src/main/res/drawable/zamokenemy.jpg and /dev/null differ diff --git a/app/src/main/res/font/logosfont.xml b/app/src/main/res/font/logosfont.xml deleted file mode 100644 index 4ff745bfd74f5816140c9196b8ee726d2df0366d..0000000000000000000000000000000000000000 --- a/app/src/main/res/font/logosfont.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - xmlns:app="http://schemas.android.com/apk/res-auto"> - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_knb.xml b/app/src/main/res/layout/activity_knb.xml index 03ab48f049f941c2731f5a22615e135369461df4..12ffab2ec595820b7030117d559e16ee7b0b3a66 100644 --- a/app/src/main/res/layout/activity_knb.xml +++ b/app/src/main/res/layout/activity_knb.xml @@ -1,7 +1,6 @@ diff --git a/app/src/main/res/layout/activity_menu.xml b/app/src/main/res/layout/activity_menu.xml index b170a088e1291177f8a93effca1a426456067e36..3c7f59c44735b094b5438ccaf2b971ecab05522f 100644 --- a/app/src/main/res/layout/activity_menu.xml +++ b/app/src/main/res/layout/activity_menu.xml @@ -53,7 +53,6 @@ android:backgroundTint="#FFE45E"/>