123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 |
- #include "Control.h"
- #include "GameEngine.h"
- #include "Vector3D.h"
- #include <math.h>
- long tickCounter = 0;
- long renderTickCounter = 0;
- long tickSum = 0;
- long renderTickSum = 0;
- long tickTime = -1;
- long renderTickTime = -1;
- typedef struct GameField {
- int id;
- float r;
- float g;
- float b;
- float a;
- } GameField;
- int amountGameFields = -1;
- GameField* gameFields = NULL;
- GLuint vbo = -1;
- GLuint vba = -1;
- int fieldSize = 0;
- int quality = 0;
- int vertices = 0;
- GLsizeiptr size = 0;
- GLfloat* data = NULL;
- Vector3D oldCamera;
- Vector3D camera;
- float oldLengthAngle;
- float lengthAngle;
- float oldWidthAngle;
- float widthAngle;
- float mouseX = 0.0f;
- float mouseY = 0.0f;
- Vector3D front;
- Vector3D back;
- Vector3D right;
- Vector3D left;
- Vector3D up;
- Vector3D down;
- int selectedIndex = -1;
- int selectedLayer = -1;
- GameField* getGameField(int layer, int index) {
- if(layer == 0) {
- return &gameFields[0];
- } else if(layer == 1 + fieldSize) {
- return &gameFields[1];
- }
- index += (layer - 1) * fieldSize + 2;
- if(index < 2 || index >= amountGameFields) {
- return NULL;
- }
- return &gameFields[index];
- }
- float interpolate(float lag, float old, float new) {
- return old + lag * (new - old);
- }
- void colorField(GameField* field) {
- if(field->id) {
- field->r = 1.0f;
- field->g = 0.0f;
- field->b = 0.0f;
- field->a = 1.0f;
- } else {
- field->r = 1.0f;
- field->g = 1.0f;
- field->b = 1.0f;
- field->a = 1.0f;
- }
- }
- void generateSphere() {
- int triangles = fieldSize * quality;
- int layers = (2 + fieldSize) * quality;
- if(gameFields == NULL) {
- amountGameFields = 2 + fieldSize * fieldSize;
- gameFields = malloc(sizeof(GameField) * amountGameFields);
- for(int i = 0; i < amountGameFields; i++) {
- gameFields[i].id = (rand() < RAND_MAX / 2) ? 1 : 0;
- colorField(&gameFields[i]);
- }
- }
- if(data == NULL) {
- vertices = triangles * layers * 3 * 2;
- size = sizeof(GLfloat) * 9 * vertices;
- data = malloc(size);
- }
- for(int l = 0; l < layers; l++) {
- float high1 = cos((M_PI * l) / layers);
- float high2 = cos((M_PI * (l + 1)) / layers);
- float texHigh1 = (l % quality) * (1.0f / quality);
- float texHigh2 = texHigh1 + (1.0f / quality);
- float r1 = sqrt(1 - high1 * high1);
- float r2 = sqrt(1 - high2 * high2);
- int flag = (l / quality) == 0;
- if(flag) {
- texHigh1 = 1 - texHigh1;
- texHigh2 = 1 - texHigh2;
- }
- flag |= (l / quality) >= fieldSize + 1;
- for(int i = 0; i < triangles; i++) {
- float first = 2 * M_PI * i / triangles;
- float second = 2 * M_PI * (i + 1) / triangles;
- int off = 27 * 2 * i + l * triangles * 27 * 2;
- float texWidth1 = (i % quality) * (1.0f / quality);
- float texWidth2 = texWidth1 + (1.0f / quality);
- float r = 0.0f;
- float g = 0.0f;
- float b = 0.0f;
- float a = 0.0f;
- GameField* field = getGameField(l / quality, i / quality);
- if(field != NULL) {
- r = field->r;
- g = field->g;
- b = field->b;
- a = field->a;
- }
- for(int j = 0; j < 54; j += 9) {
- data[3 + off + j] = r;
- data[4 + off + j] = g;
- data[5 + off + j] = b;
- data[6 + off + j] = a;
- }
- data[0 + off] = r2 * cos(first);
- data[1 + off] = high2;
- data[2 + off] = r2 * sin(first);
- data[9 + off] = r1 * cos(first);
- data[10 + off] = high1;
- data[11 + off] = r1 * sin(first);
- data[18 + off] = r1 * cos(second);
- data[19 + off] = high1;
- data[20 + off] = r1 * sin(second);
- if(flag) {
- data[7 + off] = texHigh2 * 0.5f;
- data[8 + off] = texHigh2 * 0.5f;
- data[16 + off] = texHigh1 * 0.5f;
- data[17 + off] = texHigh1 * 0.5f;
- data[25 + off] = texHigh1 * 0.5f;
- data[26 + off] = texHigh1 * 0.5f;
- } else {
- data[7 + off] = texWidth1;
- data[8 + off] = texHigh2;
- data[16 + off] = texWidth1;
- data[17 + off] = texHigh1;
- data[25 + off] = texWidth2;
- data[26 + off] = texHigh1;
- }
- data[27 + off] = r2 * cos(first);
- data[28 + off] = high2;
- data[29 + off] = r2 * sin(first);
- data[36 + off] = r1 * cos(second);
- data[37 + off] = high1;
- data[38 + off] = r1 * sin(second);
- data[45 + off] = r2 * cos(second);
- data[46 + off] = high2;
- data[47 + off] = r2 * sin(second);
- if(flag) {
- data[34 + off] = texHigh2 * 0.5f;
- data[35 + off] = texHigh2 * 0.5f;
- data[43 + off] = texHigh1 * 0.5f;
- data[44 + off] = texHigh1 * 0.5f;
- data[52 + off] = texHigh2 * 0.5f;
- data[53 + off] = texHigh2 * 0.5f;
- } else {
- data[34 + off] = texWidth1;
- data[35 + off] = texHigh2;
- data[43 + off] = texWidth2;
- data[44 + off] = texHigh1;
- data[52 + off] = texWidth2;
- data[53 + off] = texHigh2;
- }
- }
- }
- glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
- }
- void updateProjection(float aspect, int program) {
- float fovY = 60.0f;
- float nearClip = 0.1f;
- float farClip = 1000;
- float q = 1.0f / (float)tan((0.5f * fovY) * M_PI / 180.0f);
- float a = q / aspect;
- float b = (nearClip + farClip) / (nearClip - farClip);
- float c = (2.0f * nearClip * farClip) / (nearClip - farClip);
- GLfloat data[16];
- data[0] = a;
- data[1] = 0.0f;
- data[2] = 0.0f;
- data[3] = 0.0f;
- data[4] = 0.0f;
- data[5] = q;
- data[6] = 0.0f;
- data[7] = 0.0f;
- data[8] = 0.0f;
- data[9] = 0.0f;
- data[10] = b;
- data[11] = -1.0f;
- data[12] = 0.0f;
- data[13] = 0.0f;
- data[14] = c;
- data[15] = 0;
- GLint loc = glGetUniformLocation(program, "projMatrix");
- glUniformMatrix4fv(loc, 1, 0, data);
- }
- float chooseSmallerPositive(float a, float b) {
- if(a < 0) {
- return b;
- } else if(b < 0 || b > a) {
- return a;
- }
- return b;
- }
- void updateView(int program, float lag) {
- // front
- vectorSetAngles(&front, interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
- // calculate selected tile
- float a = camera.x * camera.x + camera.y * camera.y + camera.z * camera.z - 1;
- float b = 2 * (camera.x * front.x + camera.y * front.y + camera.z * front.z);
- float c = front.x * front.x + front.y * front.y + front.z * front.z;
- float p = b / c;
- float q = a / c;
- float det = p * p * 0.25f - q;
- if(det >= 0) {
- float k = sqrt(det);
- k = chooseSmallerPositive(-0.5f * p + k, -0.5f * p - k);
- if(k >= 0) {
- Vector3D v;
- vectorSetTo(&v, &camera);
- vectorAddMul(&v, &front, k);
- selectedLayer = (asin(-v.y) + M_PI_2) * M_1_PI * (2 + fieldSize);
- if(selectedLayer == 2 + fieldSize) {
- selectedLayer = fieldSize + 1;
- }
- float tan = atan2(v.z, v.x) * M_1_PI * 0.5;
- tan += (tan < 0);
- selectedIndex = tan * fieldSize;
- }
- }
- // back
- vectorSetToInverse(&back, &front);
- // right
- vectorSetTo(&right, &front);
- vectorCross(&right, 0.0f, 1.0f, 0.0f);
- vectorNormalize(&right);
- // left
- vectorSetToInverse(&left, &right);
- // up
- vectorSetTo(&up, &front);
- vectorCrossWith(&up, &left);
- vectorNormalize(&up);
- // down
- vectorSetToInverse(&down, &up);
- GLfloat data[16];
- data[0] = right.x;
- data[1] = up.x;
- data[2] = back.x;
- data[3] = 0.0f;
- data[4] = right.y;
- data[5] = up.y;
- data[6] = back.y;
- data[7] = 0.0f;
- data[8] = right.z;
- data[9] = up.z;
- data[10] = back.z;
- data[11] = 0.0f;
- Vector3D interCam;
- vectorSetTo(&interCam, &oldCamera);
- vectorAddMul(&interCam, &camera, lag);
- vectorAddMul(&interCam, &oldCamera, -lag);
- data[12] = vectorDotInverse(&right, &interCam);
- data[13] = vectorDotInverse(&up, &interCam);
- data[14] = vectorDotInverse(&back, &interCam);
- data[15] = 1.0f;
- // printf("%f %f %f %f\n", data[0], data[4], data[8], data[12]);
- // printf("%f %f %f %f\n", data[1], data[5], data[9], data[13]);
- // printf("%f %f %f %f\n", data[2], data[6], data[10], data[14]);
- // printf("%f %f %f %f\n", data[3], data[7], data[11], data[15]);
- // front
- vectorSetAngles(&front, interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
- front.y = 0;
- vectorNormalize(&front);
- // back
- vectorSetToInverse(&back, &front);
- // right
- vectorSetTo(&right, &front);
- vectorCross(&right, 0.0f, 1.0f, 0.0f);
- vectorNormalize(&right);
- // left
- vectorSetToInverse(&left, &right);
- // up
- vectorSet(&up, 0.0f, 1.0f, 0.0f);
- // down
- vectorSetToInverse(&down, &up);
- GLint loc = glGetUniformLocation(program, "viewMatrix");
- glUniformMatrix4fv(loc, 1, 0, data);
- }
- void init(int program) {
- printf("Init\n");
- glGenBuffers(1, &vbo);
- glGenVertexArrays(1, &vba);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBindVertexArray(vba);
- glVertexAttribPointer(0, 3, GL_FLOAT, 0, 36, (GLvoid*)0);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 4, GL_FLOAT, 0, 36, (GLvoid*)12);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(2, 2, GL_FLOAT, 0, 36, (GLvoid*)28);
- glEnableVertexAttribArray(2);
- generateSphere();
- vectorSet(&camera, 0.0f, 0.0f, -5.0f);
- lengthAngle = 0.0f;
- widthAngle = 0.0f;
- updateProjection(4.0f / 3.0f, program);
- }
- void invertField(int layer, int index) {
- GameField* field = getGameField(layer, index);
- if(field != NULL) {
- field->id = 1 - field->id;
- colorField(field);
- }
- }
- void invertAt(int layer, int index) {
- if(layer == 0) {
- invertField(layer, index);
- layer++;
- for(int i = 0; i < fieldSize; i++) {
- invertField(layer, i);
- }
- } else if(layer == fieldSize + 1) {
- invertField(layer, index);
- layer--;
- for(int i = 0; i < fieldSize; i++) {
- invertField(layer, i);
- }
- } else {
- invertField(layer, index);
- invertField(layer, (index + 1) % fieldSize);
- invertField(layer, (index - 1 + fieldSize) % fieldSize);
- invertField(layer + 1, index);
- invertField(layer - 1, index);
- }
- }
- void tick(int program) {
- if(tickTime == -1) {
- tickTime = glfwGetTimerValue();
- } else {
- long time = glfwGetTimerValue();
- tickSum += time - tickTime;
- tickTime = time;
- tickCounter++;
- }
- vectorSetTo(&oldCamera, &camera);
- oldLengthAngle = lengthAngle;
- oldWidthAngle = widthAngle;
- float factor = 0.05f;
- if(keyIsDown(GLFW_KEY_A)) {
- vectorAddMul(&camera, &left, factor);
- }
- if(keyIsDown(GLFW_KEY_D)) {
- vectorAddMul(&camera, &right, factor);
- }
- if(keyIsDown(GLFW_KEY_W)) {
- vectorAddMul(&camera, &front, factor);
- }
- if(keyIsDown(GLFW_KEY_S)) {
- vectorAddMul(&camera, &back, factor);
- }
- if(keyIsDown(GLFW_KEY_SPACE)) {
- vectorAddMul(&camera, &up, factor);
- }
- if(keyIsDown(GLFW_KEY_LEFT_SHIFT)) {
- vectorAddMul(&camera, &down, factor);
- }
- if(mouseIsJustDown(GLFW_MOUSE_BUTTON_1) && selectedLayer != -1 && selectedIndex != -1) {
- invertAt(selectedLayer, selectedIndex);
- generateSphere();
- selectedLayer = -1;
- selectedIndex = -1;
- }
- widthAngle -= mouseY * 0.1f;
- lengthAngle -= mouseX * 0.1f;
- if(widthAngle >= 89.5) {
- widthAngle = 89.5f;
- } else if(widthAngle <= -89.5) {
- widthAngle = -89.5f;
- }
- mouseX = 0.0f;
- mouseY = 0.0f;
- }
- void renderTick(int program, float lag) {
- if(renderTickTime == -1) {
- renderTickTime = glfwGetTimerValue();
- } else {
- long time = glfwGetTimerValue();
- renderTickSum += time - renderTickTime;
- renderTickTime = time;
- renderTickCounter++;
- }
- updateView(program, lag);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBindVertexArray(vba);
- glDrawArrays(GL_TRIANGLES, 0, vertices);
- }
- void onWindowResize(int width, int height) {
- updateProjection((float)width / height, getProgram());
- }
- void onMouseMove(float x, float y) {
- mouseX += x;
- mouseY += y;
- }
- int readPositiveInt(int from, int to, char* message, int error) {
- fputs(message, stdout);
- fflush(stdout);
- int size = 16;
- int index = 0;
- char* buffer = malloc(sizeof(char) * size);
- while(1) {
- int c = fgetc(stdin);
- if(c == EOF) {
- free(buffer);
- return error;
- } else if(c == '\n') {
- int number = 0;
- int i = 0;
- while(i < index) {
- int n = buffer[i] - '0';
- if(n < 0 || n > 9) {
- break;
- }
- number = number * 10 + n;
- if(number > to) {
- break;
- }
- i++;
- }
- if(i >= index && number >= from) {
- free(buffer);
- return number;
- }
- fputs(message, stdout);
- fflush(stdout);
- index = 0;
- continue;
- }
- if(index >= size) {
- size *= 2;
- buffer = realloc(buffer, sizeof(char) * size);
- }
- buffer[index] = c;
- index++;
- }
- }
- int main() {
- /*fieldSize = readPositiveInt(5, 20, "Select a game size from 5 to 20:\n", 0);
- if(fieldSize == 0)
- {
- printf("Cannot read from stdin\n");
- return EXIT_SUCCESS;
- }
- quality = readPositiveInt(1, 9, "Select a rendering quality from 1 to 9:\n", 0);
- if(quality == 0)
- {
- printf("Cannot read from stdin\n");
- return EXIT_SUCCESS;
- }*/
- fieldSize = 5;
- quality = 8;
- if(startGame("Test Game", init, tick, renderTick, onWindowResize, onMouseMove)) {
- fprintf(stderr, "Exited with error\n");
- // return EXIT_FAILURE;
- }
- if(data != NULL) {
- free(data);
- }
- if(gameFields != NULL) {
- free(gameFields);
- }
- glDeleteBuffers(1, &vbo);
- glDeleteVertexArrays(1, &vba);
- printf("_______________TPS_______________\n");
- printf("%ld %ld %ld\n", tickCounter, tickSum, tickTime);
- printf("%lf\n", (double)tickSum / tickCounter);
- printf("%lf\n", 1000000000.0 * tickCounter / tickSum);
- printf("_______________FPS_______________\n");
- printf("%ld %ld %ld\n", renderTickCounter, renderTickSum, renderTickTime);
- printf("%lf\n", (double)renderTickSum / renderTickCounter);
- printf("%lf\n", 1000000000.0 * renderTickCounter / renderTickSum);
- return EXIT_SUCCESS;
- }
|