From d5fed78bf5d2faf52533e3f0e54a322df91b0a3d Mon Sep 17 00:00:00 2001 From: Omar Mohamed Ali Mudhir Date: Mon, 16 Jan 2017 14:42:22 +0000 Subject: [PATCH] add Slice9 type --- data/uvs.jpg | Bin 0 -> 31830 bytes engine/app.cpp | 90 ++++++++++++++++++++++------------------------- engine/app.hpp | 4 +-- engine/image.cpp | 3 +- engine/main.cpp | 4 +-- engine/shape.cpp | 89 +++++++++++++++++++++++++++++++++++++--------- engine/shape.hpp | 15 +++++++- 7 files changed, 135 insertions(+), 70 deletions(-) create mode 100644 data/uvs.jpg diff --git a/data/uvs.jpg b/data/uvs.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7b1aef73c8b15deb03e027c8b0fefab75a1f96f5 GIT binary patch literal 31830 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 literal 0 HcmV?d00001 diff --git a/engine/app.cpp b/engine/app.cpp index 6b6edf3..2e4df3a 100644 --- a/engine/app.cpp +++ b/engine/app.cpp @@ -6,7 +6,7 @@ App App::I; // singleton void App::create() { width = 800; - height = 600; + height = 800; } void App::init() @@ -27,7 +27,7 @@ void App::init() "in vec2 uv;" "out vec4 frag;" "void main(){" - " frag = texture(tex, uv, 0.0);" + " frag = texture(tex, uv);" "}"; static const char* shader_uv_f = "#version 150\n" @@ -55,12 +55,11 @@ void App::init() shader_color.create(shader_color_v, shader_color_f); shader_uv.create(shader_v, shader_uv_f); plane.create<5>(50, 50); - longPlane.create<1>(50, 25); - circle.create<6>(25, 12); - circle1.create<4>(25, 12); + circle.create<6>(25); circle2.create<15>(25, 12); - rounded.create<5>(50, 50, 10); - if (!tex.load("data/image.png")) + rounded.create<3>(50, 50, 10); + slice.create(50, 50, 10); + if (!tex.load("data/uvs.jpg")) printf("error loading image\n"); glViewport(0, 0, width, height); @@ -97,49 +96,46 @@ void App::update(float dt) glm::mat4 proj = glm::ortho(0, width, height, 0, -1, 1); - Shape* shapes[] = { &circle, &circle1, &circle2, &plane, &longPlane }; + Shape* shapes[] = { &circle, &circle2, &plane, &rounded, &slice }; //glClearColor(red, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); auto s = glm::scale(glm::vec3(2)); -// for (int i = 0; i < 5; i++) -// { -// shader.use(); -// -// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -// glActiveTexture(GL_TEXTURE0); -// tex.bind(); -// shader.u_int("tex", 0); -// shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 1, 75 + 120 * i, 0.f}) * s); -// shapes[i]->draw_fill(); -// tex.unbind(); -// -// shader_color.use(); -// shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 2, 75 + 120 * i, 0.f}) * s); -// shader_color.u_vec4("col", {1, 1, 1, 1}); -// shapes[i]->draw_stroke(); -// -// shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 0, 75 + 120 * i, 0.f}) * s); -// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -// shapes[i]->draw_fill(); -// -// shader_uv.use(); -// shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 3, 75 + 120 * i, 0.f}) * s); -// shader_uv.u_int("tex", 0); -// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -// shapes[i]->draw_fill(); -// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -// shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 4, 75 + 120 * i, 0.f}) * s); -// shapes[i]->draw_fill(); -// tex.unbind(); -// } - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - shader_uv.use(); - shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{width/2, height/2, 0.f}) * glm::scale(glm::vec3(10))); - shader_uv.u_int("tex", 0); - glActiveTexture(GL_TEXTURE0); - tex.bind(); - rounded.draw_fill(); - tex.unbind(); + for (int i = 0; i < 5; i++) + { + shader.use(); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glActiveTexture(GL_TEXTURE0); + tex.bind(); + shader.u_int("tex", 0); + shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 1, 75 + 120 * i, 0.f}) * s); + shapes[i]->draw_fill(); + tex.unbind(); + + shader_color.use(); + shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 2, 75 + 120 * i, 0.f}) * s); + shader_color.u_vec4("col", {1, 1, 1, 1}); + shapes[i]->draw_stroke(); + + shader.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 0, 75 + 120 * i, 0.f}) * s); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + shapes[i]->draw_fill(); + + shader_uv.use(); + shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 3, 75 + 120 * i, 0.f}) * s); + shader_uv.u_int("tex", 0); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + shapes[i]->draw_fill(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + shader_uv.u_mat4("mvp", proj * glm::translate(glm::vec3{75 + 120 * 4, 75 + 120 * i, 0.f}) * s); + shapes[i]->draw_fill(); + tex.unbind(); + } + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +// shader_color.use(); +// shader_color.u_mat4("mvp", proj * glm::translate(glm::vec3{width/2, height/2, 0.f}) * glm::scale(glm::vec3(8))); +// shader_color.u_vec4("col", {1, 1, 1, 1}); +// slice.draw_fill(); } diff --git a/engine/app.hpp b/engine/app.hpp index 940bf26..8bbad96 100644 --- a/engine/app.hpp +++ b/engine/app.hpp @@ -10,9 +10,9 @@ class App Shader shader_color; Shader shader_uv; Plane plane; - Plane longPlane; - Circle circle, circle1, circle2; + Circle circle, circle2; Rounded rounded; + Slice9 slice; Texture2D tex; public: static App I; diff --git a/engine/image.cpp b/engine/image.cpp index 9cf3234..6189db1 100644 --- a/engine/image.cpp +++ b/engine/image.cpp @@ -7,7 +7,8 @@ bool Image::load(std::string filename) { stbi_set_flip_vertically_on_load(true); - uint8_t* buffer = stbi_load(filename.c_str(), &width, &height, &comp, 0); + uint8_t* buffer = stbi_load(filename.c_str(), &width, &height, nullptr, 4); + comp = 4; m_data = std::unique_ptr(buffer); return true; } diff --git a/engine/main.cpp b/engine/main.cpp index f3dfb6a..cf99d6e 100644 --- a/engine/main.cpp +++ b/engine/main.cpp @@ -22,7 +22,7 @@ NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 24, // Must specify the 3.2 Core Profile to use OpenGL 3.2 - NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, // Multisample NSOpenGLPFAMultisample, NSOpenGLPFASamples, 2, @@ -159,7 +159,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO]; - [window setTitle:@"hello engine"]; + [window setTitle:@"hello engine - ui shapes"]; [window center]; [window makeKeyAndOrderFront:controller]; [window setContentView:view]; diff --git a/engine/shape.cpp b/engine/shape.cpp index 7a0dec6..07f97f3 100644 --- a/engine/shape.cpp +++ b/engine/shape.cpp @@ -47,8 +47,8 @@ void Plane::create_impl(float w, float h, int div, GLushort *idx, Shape::vertex_ { count[0] = div * div * 6; count[1] = 8; - ioff[0] = (GLvoid*)(count[1] * sizeof(GLushort)); - ioff[1] = (GLvoid*)0; + ioff[0] = (GLvoid*)0; + ioff[1] = (GLvoid*)(count[0] * sizeof(GLushort)); const float dx = w / div; const float dy = h / div; @@ -69,14 +69,6 @@ void Plane::create_impl(float w, float h, int div, GLushort *idx, Shape::vertex_ } // generate indices - *idx++ = 0; // A - *idx++ = (div+1)*(div); // B - *idx++ = (div+1)*(div); // B - *idx++ = (div+1)*(div+1)-1; // C - *idx++ = (div+1)*(div+1)-1; // C - *idx++ = div; // D - *idx++ = div; // D - *idx++ = 0; // A for (int y = 0; y < div; y++) { int i = y * (div+1); @@ -91,6 +83,15 @@ void Plane::create_impl(float w, float h, int div, GLushort *idx, Shape::vertex_ i++; } } + // outline indices + *idx++ = 0; // A + *idx++ = (div+1)*(div); // B + *idx++ = (div+1)*(div); // B + *idx++ = (div+1)*(div+1)-1; // C + *idx++ = (div+1)*(div+1)-1; // C + *idx++ = div; // D + *idx++ = div; // D + *idx++ = 0; // A } void Circle::create_impl(float radius, int div, GLushort* idx, Shape::vertex_t* vertices) @@ -101,7 +102,7 @@ void Circle::create_impl(float radius, int div, GLushort* idx, Shape::vertex_t* ioff[1] = (GLvoid*)(count[0] * sizeof(GLushort)); auto pidx = idx; - auto pidx2 = idx + div * 3; + auto pidx2 = idx + count[0]; for (int i = 0; i < div; i++) { vertex_t v; @@ -130,7 +131,7 @@ void Circle::create_impl(float radius_out, float radius_in, int div, GLushort* i ioff[1] = (GLvoid*)(count[0] * sizeof(GLushort)); auto pidx = idx; - auto pidx2 = idx + div * 6; + auto pidx2 = idx + count[0]; for (int i = 0; i < div; i++) { float theta = (float)i / div * M_PI * 2.f; @@ -163,6 +164,8 @@ void Rounded::create_impl(float w, float h, float r, int div, GLushort* idx, GLu ioff[0] = (GLvoid*)0; ioff[1] = (GLvoid*)(count[0] * sizeof(GLushort)); + auto idx2 = idx + count[0]; + float X[] = { -w/2, -w/2+r, w/2-r, w/2 }; float Y[] = { -h/2, -h/2+r, h/2-r, h/2 }; @@ -200,27 +203,79 @@ void Rounded::create_impl(float w, float h, float r, int div, GLushort* idx, GLu Q(7,10,11, 8); auto corner = [&](int c, int a, int b, int n) { + auto v = vertices-12; idx_tmp[0] = a; idx_tmp[div] = b; - auto v = vertices-12; for (int i = 1; i < div; i++) { float t = (float)(i) / div; - auto p = glm::normalize(glm::mix(v[a].pos.xyz(), v[b].pos.xyz(), t)); + auto p = glm::normalize(glm::mix(v[a].pos.xyz()-v[c].pos.xyz(), v[b].pos.xyz()-v[c].pos.xyz(), t)); v[n].pos = glm::vec4(p * r + v[c].pos.xyz(), 1); - v[n].uvs = glm::normalize(glm::mix(v[a].uvs, v[b].uvs, t)) * glm::vec2(r/w, r/h) + v[c].uvs; + v[n].uvs = glm::normalize(glm::mix(v[a].uvs-v[c].uvs, v[b].uvs-v[c].uvs, t)) * glm::vec2(r/w, r/h) + v[c].uvs; idx_tmp[i] = n; n++; } for (int i = 0; i < div; i++) { *idx++ = c; - *idx++ = idx_tmp[i]; - *idx++ = idx_tmp[i+1]; + *idx++ = *idx2++ = idx_tmp[i]; + *idx++ = *idx2++ = idx_tmp[i+1]; } }; corner(3, 0, 2, 12 + (div-1)*0); corner(7, 6,10, 12 + (div-1)*1); corner(8,11, 9, 12 + (div-1)*2); corner(4, 5, 1, 12 + (div-1)*3); + + *idx2++ = 0; + *idx2++ = 1; + *idx2++ = 5; + *idx2++ = 9; + *idx2++ = 11; + *idx2++ = 10; + *idx2++ = 6; + *idx2++ = 2; +} + +void Slice9::create_impl(float w, float h, float r, GLushort *idx, Shape::vertex_t *vertices) +{ + count[0] = 3 * 3 * 6; + count[1] = 4 * 2; + ioff[0] = (GLvoid*)0; + ioff[1] = (GLvoid*)(count[0] * sizeof(GLushort)); + + float X[] = { -w/2, -w/2+r, w/2-r, w/2 }; + float Y[] = { -h/2, -h/2+r, h/2-r, h/2 }; + + auto V = [&](int x, int y) -> Shape::vertex_t { + return { glm::vec4(X[x], Y[y], 0, 1), glm::vec2(X[x]/w, Y[y]/h) + 0.5f }; + }; + + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + *vertices++ = V(x,y); + + for (int y = 0; y < 3; y++) + { + int i = y * (3+1); + for (int x = 0; x < 3; x++) + { + *idx++ = i; + *idx++ = i + 3 + 1; + *idx++ = i + 3 + 2; + *idx++ = i; + *idx++ = i + 3 + 2; + *idx++ = i + 1; + i++; + } + } + // outline indices + *idx++ = 0; // A + *idx++ = 3; // B + *idx++ = 3; // B + *idx++ = 15; // C + *idx++ = 15; // C + *idx++ = 12; // D + *idx++ = 12; // D + *idx++ = 0; // A } diff --git a/engine/shape.hpp b/engine/shape.hpp index 45a8281..baf3c8d 100644 --- a/engine/shape.hpp +++ b/engine/shape.hpp @@ -58,10 +58,23 @@ public: template bool create(float w, float h, float r) { - static GLushort idx[(10 + div * 4) * 3]; + static GLushort idx[(10 + div * 4) * 3 + (4 + div * 4) * 2]; static GLushort idx_tmp[div+1]; static vertex_t vertices[12 + (div-1) * 4]; create_impl(w, h, r, div, idx, idx_tmp, vertices); return create_buffers(idx, vertices, sizeof(idx), sizeof(vertices)); } }; + +class Slice9 : public Shape +{ + void create_impl(float w, float h, float r, GLushort* idx, vertex_t* vertices); +public: + bool create(float w, float h, float r) + { + static GLushort idx[3 * 3 * 6 + 4 * 2]; + static vertex_t vertices[4 * 4]; + create_impl(w, h, r, idx, vertices); + return create_buffers(idx, vertices, sizeof(idx), sizeof(vertices)); + } +};