From 6e82fce4808709f12f3891a233d5c8a3b3ea4734 Mon Sep 17 00:00:00 2001 From: timofei iniushin Date: Fri, 26 Apr 2024 22:10:11 -0400 Subject: [PATCH] rotating car, base dot product shading --- .vscode/launch.json | 2 +- makefile | 2 +- src/car_view/model_obj.cpp | 28 ++- src/car_view/model_obj.h | 240 ------------------------- src/car_view/shaders/shader_car.cpp | 264 ++++++++++++++++++++++------ src/car_view/shaders/shader_car.hpp | 35 ++-- src/car_widget.cpp | 221 ++++++++++++++++++----- src/car_widget.hpp | 12 +- src/gauge.cpp | 4 +- src/gui.cpp | 7 +- src/main.cpp | 5 +- 11 files changed, 456 insertions(+), 364 deletions(-) delete mode 100644 src/car_view/model_obj.h diff --git a/.vscode/launch.json b/.vscode/launch.json index c7471de..345f51a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/out/dbg/carcockpit", - "args": [], + "args": ["--window", "--res-path=res"], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], diff --git a/makefile b/makefile index 3964620..b63a8b0 100644 --- a/makefile +++ b/makefile @@ -20,7 +20,7 @@ else ifeq ($(os),linux) this_ldflags += -rdynamic endif -this_ldlibs += -lruisapp-opengles -lpapki -lclargs -ltml -lruis -lutki -lm +this_ldlibs += -lruisapp-opengles-xorg -lpapki -lclargs -ltml -lruis -lutki -lm -l ruis-render-opengles $(eval $(prorab-build-app)) diff --git a/src/car_view/model_obj.cpp b/src/car_view/model_obj.cpp index 8f079b0..4c28060 100644 --- a/src/car_view/model_obj.cpp +++ b/src/car_view/model_obj.cpp @@ -15,7 +15,7 @@ // //----------------------------------------------------------------------------- -#include "model_obj.h" +#include "model_obj.hpp" #include #include #include @@ -1291,6 +1291,30 @@ void ModelOBJ::buildShortIndexBuffer() m_shortIndexBuffer.push_back(static_cast(index)); } +void ModelOBJ::buildVBOs() +{ + buildShortIndexBuffer(); + + GLuint vn = getNumberOfVertices(); + + positions.clear(); positions.reserve(vn); + textureCoords.clear(); textureCoords.reserve(vn); + normals.clear(); normals.reserve(vn); + tangents.clear(); tangents.reserve(vn); + bitangents.clear(); bitangents.reserve(vn); + + for(uint32_t i = 0; i < vn; ++i) + { + const Vertex& v = m_vertexBuffer[i]; + + positions.push_back (ruis::vec4 {v.position[0], v.position[1], v.position[2], 1.0f}); + textureCoords.push_back (ruis::vec2 {v.texCoord[0], v.texCoord[1]}); + normals.push_back (ruis::vec3 {v.normal[0], v.normal[1], v.normal[2]}); + tangents.push_back (ruis::vec4 {v.tangent[0], v.tangent[1], v.tangent[2], v.tangent[3]}); + bitangents.push_back (ruis::vec4 {v.bitangent[0], v.bitangent[1], v.bitangent[2], 1.0f}); + } +} + void ModelOBJ::createVBOs() { buildShortIndexBuffer(); // TODO: make it a non-kolkhoz fashion. OpenGLES 2 requires us to use 16-bit indices @@ -1335,7 +1359,7 @@ void ModelOBJ::createVBOs() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboHandles[1]); //glBufferData(GL_ELEMENT_ARRAY_BUFFER, getNumberOfIndices() * sizeof(GLuint), getIndexBuffer(), GL_STATIC_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, getNumberOfIndices() * sizeof(GLushort), getShortIndexBuffer(), GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, getNumberOfIndices() * sizeof(GLushort), getShortIndexBufferPtr(), GL_STATIC_DRAW); //glBindVertexArray(0); diff --git a/src/car_view/model_obj.h b/src/car_view/model_obj.h deleted file mode 100644 index 36d4b7c..0000000 --- a/src/car_view/model_obj.h +++ /dev/null @@ -1,240 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//----------------------------------------------------------------------------- -// Alias|Wavefront OBJ file loader. -// -// This OBJ file loader contains the following restrictions: -// 1. Group information is ignored. Faces are grouped based on the material -// that each face uses. -// 2. Object information is ignored. This loader will merge everything into a -// single object. -// 3. The MTL file must be located in the same directory as the OBJ file. If -// it isn't then the MTL file will fail to load and a default material is -// used instead. -// 4. This loader triangulates all polygonal faces during importing. -//----------------------------------------------------------------------------- - - -class ModelOBJ -{ -public: - - //unsigned int vaoHandle; - unsigned int vboHandles[2]; - void createVBOs(); - void render(); - - struct Material - { - float ambient[4]; - float diffuse[4]; - float specular[4]; - float shininess; // [0 = min shininess, 1 = max shininess] - float alpha; // [0 = fully transparent, 1 = fully opaque] - - std::string name; - std::string colorMapFilename; - std::string bumpMapFilename; - }; - - struct Vertex - { - //float position[3]; - float position[4]; - float texCoord[2]; - float normal[3]; - float tangent[4]; - float bitangent[3]; - }; - - struct Mesh - { - int startIndex; - int triangleCount; - const Material *pMaterial; - }; - - ModelOBJ(); - ~ModelOBJ(); - - void destroy(); - bool import(const std::string& filename, bool rebuildNormals = false); - void normalize(float scaleTo = 1.0f, bool center = true); - void reverseWinding(); - - // Getter methods. - - void getCenter(float &x, float &y, float &z) const; - float getWidth() const; - float getHeight() const; - float getLength() const; - float getRadius() const; - - const int* getIndexBuffer() const; - const uint16_t* getShortIndexBuffer() const; - int getIndexSize() const; - - const Material &getMaterial(int i) const; - const Mesh &getMesh(int i) const; - - int getNumberOfIndices() const; - int getNumberOfMaterials() const; - int getNumberOfMeshes() const; - int getNumberOfTriangles() const; - int getNumberOfVertices() const; - - const std::string &getPath() const; - - const Vertex &getVertex(int i) const; - const Vertex *getVertexBuffer() const; - int getVertexSize() const; - - bool hasNormals() const; - bool hasPositions() const; - bool hasTangents() const; - bool hasTextureCoords() const; - - void bounds(float center[3], float &width, float &height, - float &length, float &radius) const; -private: - void addTrianglePos(int index, int material, - int v0, int v1, int v2); - void addTrianglePosNormal(int index, int material, - int v0, int v1, int v2, - int vn0, int vn1, int vn2); - void addTrianglePosTexCoord(int index, int material, - int v0, int v1, int v2, - int vt0, int vt1, int vt2); - void addTrianglePosTexCoordNormal(int index, int material, - int v0, int v1, int v2, - int vt0, int vt1, int vt2, - int vn0, int vn1, int vn2); - int addVertex(int hash, const Vertex *pVertex); - - void buildMeshes(); - void generateNormals(); - void generateTangents(); - void importGeometryFirstPass(FILE *pFile); - void importGeometrySecondPass(FILE *pFile); - bool importMaterials(const char *pszFilename); - void scale(float scaleFactor, float offset[3]); - - void buildShortIndexBuffer(); - - bool m_hasPositions; - bool m_hasTextureCoords; - bool m_hasNormals; - bool m_hasTangents; - - int m_numberOfVertexCoords; - int m_numberOfTextureCoords; - int m_numberOfNormals; - int m_numberOfTriangles; - int m_numberOfMaterials; - int m_numberOfMeshes; - - float m_center[3]; - float m_width; - float m_height; - float m_length; - float m_radius; - - std::string m_directoryPath; - - std::vector m_meshes; - std::vector m_materials; - std::vector m_vertexBuffer; - std::vector m_indexBuffer; - std::vector m_shortIndexBuffer; - std::vector m_attributeBuffer; - std::vector m_vertexCoords; - std::vector m_textureCoords; - std::vector m_normals; - - std::map m_materialCache; - std::map > m_vertexCache; -}; - -//----------------------------------------------------------------------------- - -inline void ModelOBJ::getCenter(float &x, float &y, float &z) const -{ x = m_center[0]; y = m_center[1]; z = m_center[2]; } - -inline float ModelOBJ::getWidth() const -{ return m_width; } - -inline float ModelOBJ::getHeight() const -{ return m_height; } - -inline float ModelOBJ::getLength() const -{ return m_length; } - -inline float ModelOBJ::getRadius() const -{ return m_radius; } - -inline const int* ModelOBJ::getIndexBuffer() const -{ return &m_indexBuffer[0]; } - -inline const uint16_t* ModelOBJ::getShortIndexBuffer() const -{ return &m_shortIndexBuffer[0]; } - - -inline int ModelOBJ::getIndexSize() const -{ return static_cast(sizeof(int)); } - -inline const ModelOBJ::Material &ModelOBJ::getMaterial(int i) const -{ return m_materials[i]; } - -inline const ModelOBJ::Mesh &ModelOBJ::getMesh(int i) const -{ return m_meshes[i]; } - -inline int ModelOBJ::getNumberOfIndices() const -{ return m_numberOfTriangles * 3; } - -inline int ModelOBJ::getNumberOfMaterials() const -{ return m_numberOfMaterials; } - -inline int ModelOBJ::getNumberOfMeshes() const -{ return m_numberOfMeshes; } - -inline int ModelOBJ::getNumberOfTriangles() const -{ return m_numberOfTriangles; } - -inline int ModelOBJ::getNumberOfVertices() const -{ return static_cast(m_vertexBuffer.size()); } - -inline const std::string &ModelOBJ::getPath() const -{ return m_directoryPath; } - -inline const ModelOBJ::Vertex &ModelOBJ::getVertex(int i) const -{ return m_vertexBuffer[i]; } - -inline const ModelOBJ::Vertex *ModelOBJ::getVertexBuffer() const -{ return &m_vertexBuffer[0]; } - -inline int ModelOBJ::getVertexSize() const -{ return static_cast(sizeof(Vertex)); } - -inline bool ModelOBJ::hasNormals() const -{ return m_hasNormals; } - -inline bool ModelOBJ::hasPositions() const -{ return m_hasPositions; } - -inline bool ModelOBJ::hasTangents() const -{ return m_hasTangents; } - -inline bool ModelOBJ::hasTextureCoords() const -{ return m_hasTextureCoords; } - diff --git a/src/car_view/shaders/shader_car.cpp b/src/car_view/shaders/shader_car.cpp index 146ee5c..1c56467 100644 --- a/src/car_view/shaders/shader_car.cpp +++ b/src/car_view/shaders/shader_car.cpp @@ -1,70 +1,224 @@ -// /* -// ruis-render-opengl - OpenGL GUI renderer +/* +ruis-render-opengles - OpenGL ES GUI renderer -// Copyright (C) 2012-2024 Ivan Gagis +Copyright (C) 2012-2024 Ivan Gagis -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// */ +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ -// /* ================ LICENSE END ================ */ +/* ================ LICENSE END ================ */ -// #include "shader_car.hpp" +#include "shader_car.hpp" -// #include "index_buffer.hpp" -// #include "texture_2d.hpp" -// #include "util.hpp" -// #include "vertex_array.hpp" -// #include "vertex_buffer.hpp" +#include +#include +#include +#include +#include -// using namespace ruis::render_opengl; +using namespace carcockpit; +/* +shader_car::shader_car() : + shader_base( + R"qwertyuiop( + attribute highp vec4 a0; // position + attribute highp vec2 a1; // texture coordinate + attribute highp vec3 a2; // normal -// shader_car::shader_car() : -// shader_base( -// R"qwertyuiop( -// attribute vec4 a0; // position + uniform highp mat4 matrix; -// attribute vec2 a1; // texture coordinates + varying highp vec2 tc0; + varying highp vec3 norm; -// uniform mat4 matrix; + void main(void) + { + gl_Position = matrix * a0; + tc0 = a1; + norm = a2; + } + )qwertyuiop", + R"qwertyuiop( + uniform sampler2D texture0; + varying highp vec2 tc0; + varying highp vec3 norm; + precision highp float; + void main(void) + { + float f = dot(norm, vec3(1.0, 0, 0)); + //gl_FragColor = vec4(f, f, f, 1); + gl_FragColor = (0.4 + f) * texture2D(texture0, tc0); + } + )qwertyuiop" + ) +{ +} +*/ +shader_car::shader_car() : + shader_base( + R"qwertyuiop( + attribute highp vec4 a0; // position + attribute highp vec2 a1; // texture coordinate + attribute highp vec3 a2; // normal -// varying vec2 tc0; + uniform highp mat4 matrix; // mvp matrix + uniform highp mat4 mat4_mv; // modelview matrix + uniform highp mat4 mat4_p; // projection matrix + uniform highp mat3 mat3_n; // normal matrix (mat3) -// void main(void){ -// gl_Position = matrix * a0; -// tc0 = a1; -// } -// )qwertyuiop", -// R"qwertyuiop( -// uniform sampler2D texture0; + varying highp vec3 pos; + varying highp vec2 tc0; + varying highp vec3 norm; + + void main(void) + { + //mat3 normalMatrix = mat3( transpose(inverse( mat4_mv )) ); //TODO: remove from shader + //norm = normalize( normalMatrix * a2 ); + norm = normalize( matrix * vec4(a2, 0) ).xyz; + pos = vec3( mat4_mv * a0 ); + gl_Position = matrix * a0; + } + + )qwertyuiop", + R"qwertyuiop( -// varying vec2 tc0; + + + + + + uniform sampler2D texture0; + precision highp float; -// void main(void){ -// gl_FragColor = texture2D(texture0, tc0); -// } -// )qwertyuiop" -// ), -// texture_uniform(this->get_uniform("texture0")) -// {} - -// void shader_car::render(const r4::matrix4& m, const ruis::vertex_array& va, const ruis::texture_2d& tex) -// const -// { -// ASSERT(dynamic_cast(&tex)) -// // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast) -// static_cast(tex).bind(0); -// this->bind(); - -// this->shader_base::render(m, va); -// } + varying highp vec3 pos; + varying highp vec2 tc0; + varying highp vec3 norm; + + uniform vec4 LightPosition; + uniform vec3 LightIntensity; + // uniform vec3 Kd; // Diffuse reflectivity + // uniform vec3 Ka; // Ambient reflectivity + // uniform vec3 Ks; // Specular reflectivity + // uniform float Shininess; // Specular shininess factor + + const vec3 Kd = vec3(0.5, 0.5, 0.5); // Diffuse reflectivity + const vec3 Ka = vec3(0.5, 0.5, 0.5); // Ambient reflectivity + const vec3 Ks = vec3(0.5, 0.5, 0.5); // Specular reflectivity + const float Shininess = 8.0; // Specular shininess factor + + vec3 ads() + { + vec3 n = normalize( norm ); + vec3 s = normalize( vec3(LightPosition) - pos ); + vec3 v = normalize( vec3(-pos) ); + vec3 r = reflect( -s, n ); + return LightIntensity * ( Ka + Kd * max( dot(s, n), 0.0 ) + Ks * pow( max( dot(r,v), 0.0 ), Shininess ) ) * 4.0; + } + + void main() + { + float f = max( dot(norm, vec3(1.0, 0, 0)), 0.0); + gl_FragColor = vec4(f+0.05, f+0.05, f+0.05, 1.0); + //gl_FragColor = vec4(ads(), 1.0); + //gl_FragColor = vec4(LightIntensity, 1.0); + //gl_FragColor = vec4(1, 1, 1, 1); + } + + )qwertyuiop" + ), + //texture_diffuse_uniform(this->get_uniform("texture0")), + //texture_normal_uniform(this->get_uniform("texture1")) + mat4_modelview(this->get_uniform("mat4_mv")), + mat4_projection(this->get_uniform("mat4_p")), + mat3_normal(this->get_uniform("mat3_n")), + vec4_light_position(this->get_uniform("LightPosition")), + vec3_light_intensity(this->get_uniform("LightIntensity")) +{ +} + +void shader_car::render(const r4::matrix4& m, const ruis::vertex_array& va, const ruis::texture_2d& tex) const +{ + ASSERT(dynamic_cast(&tex)) + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast) + static_cast(tex).bind(0); + this->bind(); + + this->shader_base::render(m, va); +} + +void shader_car::set_uniform_matrix3f(GLint id, const r4::matrix3& m) const +{ + auto mm = m.tposed(); + glUniformMatrix3fv( + id, + 1, + // OpenGL ES 2 does not support transposing, see description of + // 'transpose' parameter of glUniformMatrix4fv(): + // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glUniform.xml + GL_FALSE, + mm.front().data() + ); + //ruis::render_opengles::assert_opengl_no_error(); +} + +void shader_car::set_uniform_matrix4f(GLint id, const r4::matrix4& m) const +{ + auto mm = m.tposed(); + glUniformMatrix4fv( + id, + 1, + // OpenGL ES 2 does not support transposing, see description of + // 'transpose' parameter of glUniformMatrix4fv(): + // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glUniform.xml + GL_FALSE, + mm.front().data() + ); + //ruis::render_opengles::assert_opengl_no_error(); +} + +void shader_car::set_uniform3f(GLint id, float x, float y, float z) const +{ + glUniform3f(id, x, y, z); + //ruis::render_opengles::assert_opengl_no_error(); +} + +void shader_car::set_uniform4f(GLint id, float x, float y, float z, float w) const +{ + glUniform4f(id, x, y, z, w); + //ruis::render_opengles::assert_opengl_no_error(); +} + +class shader_base_fake +{ +public: + ruis::render_opengles::program_wrapper program; + const GLint matrix_uniform = 0; + virtual ~shader_base_fake(){} +}; + +GLint shader_car::get_uniform(const char* name) +{ + int i = sizeof(shader_base_fake); + int j = sizeof(ruis::render_opengles::shader_base); + + std::cout<< i << " " << j << std::endl; + ruis::render_opengles::shader_base* sbf = static_cast(this); + shader_base_fake *rbf = reinterpret_cast( sbf ); + + GLint ret = glGetUniformLocation(rbf->program.id, name); + //assert_opengl_no_error(); + // if (ret < 0) { + // throw std::logic_error(utki::cat("No uniform found in the shader program: ", name)); + // } + return ret; +} \ No newline at end of file diff --git a/src/car_view/shaders/shader_car.hpp b/src/car_view/shaders/shader_car.hpp index 6d1bc94..b15d138 100644 --- a/src/car_view/shaders/shader_car.hpp +++ b/src/car_view/shaders/shader_car.hpp @@ -1,5 +1,5 @@ /* -ruis-render-opengl - OpenGL GUI renderer +ruis-render-opengles - OpenGL ES GUI renderer Copyright (C) 2012-2024 Ivan Gagis @@ -19,22 +19,27 @@ along with this program. If not, see . /* ================ LICENSE END ================ */ -// #pragma once +#pragma once -// #include +//#include +#include +#include -// //#include "shader_base.hpp" +namespace carcockpit { -// namespace carcockpit { +class shader_car : public ruis::render_opengles::shader_base +{ + +public: + GLint mat4_modelview, mat4_projection, mat3_normal, vec4_light_position, vec3_light_intensity; -// class shader_car : public ruis::texturing_shader, public shader_base -// { -// GLint texture_uniform; + shader_car(); + void render(const r4::matrix4& m, const ruis::vertex_array& va, const ruis::texture_2d& tex) const; + virtual void set_uniform_matrix3f(GLint id, const r4::matrix3& m) const; + virtual void set_uniform_matrix4f(GLint id, const r4::matrix4& m) const; + virtual void set_uniform3f(GLint id, float x, float y, float z) const; + virtual void set_uniform4f(GLint id, float x, float y, float z, float w) const; + virtual GLint get_uniform(const char* name); +}; -// public: -// shader_car(); - -// void render(const r4::matrix4& m, const ruis::vertex_array& va, const ruis::texture_2d& tex) const override; -// }; - -} // namespace carcockpit +} // namespace ruis::render_opengles \ No newline at end of file diff --git a/src/car_widget.cpp b/src/car_widget.cpp index 7e577b1..3ebf3aa 100644 --- a/src/car_widget.cpp +++ b/src/car_widget.cpp @@ -25,40 +25,49 @@ along with this program. If not, see . #include #include #include +#include using namespace carcockpit; // something +ruis::mat3 from_mat4(const ruis::mat4& mat) +{ + ruis::mat3 m; + for(int i = 0; i < 3; ++i) + for(int j = 0; j < 3; ++j) + m[i][j] = mat[i][j]; + return m; +} car_widget::car_widget(utki::shared_ref context, all_parameters params) : ruis::widget(std::move(context), {.widget_params = std::move(params.widget_params)}), - ruis::fraction_widget(this->context) + ruis::fraction_widget(this->context, {}) { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - std::array cube_pos = { - {ruis::vector3(-0, -0, 0), ruis::vector3(0, -0, 0), ruis::vector3(-0, 0, 0), ruis::vector3(0, -0, 0), - ruis::vector3(0, 0, 0), ruis::vector3(-0, 0, 0), ruis::vector3(0, -0, 0), ruis::vector3(0, -0, -0), - ruis::vector3(0, 0, 0), ruis::vector3(0, -0, -0), ruis::vector3(0, 0, -0), ruis::vector3(0, 0, 0), - ruis::vector3(0, -0, -0), ruis::vector3(-0, -0, -0), ruis::vector3(0, 0, -0), ruis::vector3(-0, -0, -0), - ruis::vector3(-0, 0, -0), ruis::vector3(0, 0, -0), ruis::vector3(-0, -0, -0), ruis::vector3(-0, -0, 0), - ruis::vector3(-0, 0, -0), ruis::vector3(-0, -0, 0), ruis::vector3(-0, 0, 0), ruis::vector3(-0, 0, -0), - ruis::vector3(-0, 0, -0), ruis::vector3(-0, 0, 0), ruis::vector3(0, 0, -0), ruis::vector3(-0, 0, 0), - ruis::vector3(0, 0, 0), ruis::vector3(0, 0, -0), ruis::vector3(-0, -0, -0), ruis::vector3(0, -0, -0), - ruis::vector3(-0, -0, 0), ruis::vector3(-0, -0, 0), ruis::vector3(0, -0, -0), ruis::vector3(0, -0, 0)} - }; - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + // // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) // std::array cube_pos = { - // {ruis::vector3(-1, -1, 1), ruis::vector3(1, -1, 1), ruis::vector3(-1, 1, 1), ruis::vector3(1, -1, 1), - // ruis::vector3(1, 1, 1), ruis::vector3(-1, 1, 1), ruis::vector3(1, -1, 1), ruis::vector3(1, -1, -1), - // ruis::vector3(1, 1, 1), ruis::vector3(1, -1, -1), ruis::vector3(1, 1, -1), ruis::vector3(1, 1, 1), - // ruis::vector3(1, -1, -1), ruis::vector3(-1, -1, -1), ruis::vector3(1, 1, -1), ruis::vector3(-1, -1, -1), - // ruis::vector3(-1, 1, -1), ruis::vector3(1, 1, -1), ruis::vector3(-1, -1, -1), ruis::vector3(-1, -1, 1), - // ruis::vector3(-1, 1, -1), ruis::vector3(-1, -1, 1), ruis::vector3(-1, 1, 1), ruis::vector3(-1, 1, -1), - // ruis::vector3(-1, 1, -1), ruis::vector3(-1, 1, 1), ruis::vector3(1, 1, -1), ruis::vector3(-1, 1, 1), - // ruis::vector3(1, 1, 1), ruis::vector3(1, 1, -1), ruis::vector3(-1, -1, -1), ruis::vector3(1, -1, -1), - // ruis::vector3(-1, -1, 1), ruis::vector3(-1, -1, 1), ruis::vector3(1, -1, -1), ruis::vector3(1, -1, 1)} + // {ruis::vector3(-0, -0, 0), ruis::vector3(0, -0, 0), ruis::vector3(-0, 0, 0), ruis::vector3(0, -0, 0), + // ruis::vector3(0, 0, 0), ruis::vector3(-0, 0, 0), ruis::vector3(0, -0, 0), ruis::vector3(0, -0, -0), + // ruis::vector3(0, 0, 0), ruis::vector3(0, -0, -0), ruis::vector3(0, 0, -0), ruis::vector3(0, 0, 0), + // ruis::vector3(0, -0, -0), ruis::vector3(-0, -0, -0), ruis::vector3(0, 0, -0), ruis::vector3(-0, -0, -0), + // ruis::vector3(-0, 0, -0), ruis::vector3(0, 0, -0), ruis::vector3(-0, -0, -0), ruis::vector3(-0, -0, 0), + // ruis::vector3(-0, 0, -0), ruis::vector3(-0, -0, 0), ruis::vector3(-0, 0, 0), ruis::vector3(-0, 0, -0), + // ruis::vector3(-0, 0, -0), ruis::vector3(-0, 0, 0), ruis::vector3(0, 0, -0), ruis::vector3(-0, 0, 0), + // ruis::vector3(0, 0, 0), ruis::vector3(0, 0, -0), ruis::vector3(-0, -0, -0), ruis::vector3(0, -0, -0), + // ruis::vector3(-0, -0, 0), ruis::vector3(-0, -0, 0), ruis::vector3(0, -0, -0), ruis::vector3(0, -0, 0)} // }; + +// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + std::array cube_pos = { + {ruis::vector3(-1, -1, 1), ruis::vector3(1, -1, 1), ruis::vector3(-1, 1, 1), ruis::vector3(1, -1, 1), + ruis::vector3(1, 1, 1), ruis::vector3(-1, 1, 1), ruis::vector3(1, -1, 1), ruis::vector3(1, -1, -1), + ruis::vector3(1, 1, 1), ruis::vector3(1, -1, -1), ruis::vector3(1, 1, -1), ruis::vector3(1, 1, 1), + ruis::vector3(1, -1, -1), ruis::vector3(-1, -1, -1), ruis::vector3(1, 1, -1), ruis::vector3(-1, -1, -1), + ruis::vector3(-1, 1, -1), ruis::vector3(1, 1, -1), ruis::vector3(-1, -1, -1), ruis::vector3(-1, -1, 1), + ruis::vector3(-1, 1, -1), ruis::vector3(-1, -1, 1), ruis::vector3(-1, 1, 1), ruis::vector3(-1, 1, -1), + ruis::vector3(-1, 1, -1), ruis::vector3(-1, 1, 1), ruis::vector3(1, 1, -1), ruis::vector3(-1, 1, 1), + ruis::vector3(1, 1, 1), ruis::vector3(1, 1, -1), ruis::vector3(-1, -1, -1), ruis::vector3(1, -1, -1), + ruis::vector3(-1, -1, 1), ruis::vector3(-1, -1, 1), ruis::vector3(1, -1, -1), ruis::vector3(1, -1, 1)} + }; auto pos_vbo = this->context.get().renderer.get().factory->create_vertex_buffer(utki::make_span(cube_pos)); @@ -75,6 +84,7 @@ car_widget::car_widget(utki::shared_ref context, all_parameters p ruis::vector2(0, 1)} }; + auto tex_vbo = this->context.get().renderer.get().factory->create_vertex_buffer(utki::make_span(cube_tex)); // clang-format off @@ -106,11 +116,24 @@ car_widget::car_widget(utki::shared_ref context, all_parameters p std::cout << "car_W" << std::endl; this->car_model_obj = std::make_shared(); + + //car_model_obj->import("res/car/monkey.obj"); car_model_obj->import("res/car/car3d.obj"); - car_model_obj->createVBOs(); - //this->car_model_obj - //this->tex_car_opacity = this->context.get().loader.load("tex_car_opacity").to_shared_ptr(); - //this->tex_car_metallic = this->context.get().loader.load("tex_car_metallic").to_shared_ptr(); + car_model_obj->buildVBOs(); + + auto car_vbo_positions = this->context.get().renderer.get().factory->create_vertex_buffer(utki::make_span(car_model_obj->getPositionsBuffer())); + auto car_vbo_texcoords = this->context.get().renderer.get().factory->create_vertex_buffer(utki::make_span(car_model_obj->getTextureCoordsBuffer())); + auto car_vbo_normals = this->context.get().renderer.get().factory->create_vertex_buffer(utki::make_span(car_model_obj->getNormalsBuffer())); + auto car_vbo_indices = this->context.get().renderer.get().factory->create_index_buffer(utki::make_span(car_model_obj->getShortIndexBuffer())); + + this->car_vao = + this->context.get() + .renderer.get() + .factory->create_vertex_array({car_vbo_positions, car_vbo_texcoords, car_vbo_normals}, car_vbo_indices, ruis::vertex_array::mode::triangles) + .to_shared_ptr(); + + LOG([&](auto& o) { o << "<< SHADER KOM PILE >>\n" << std::endl; }) + this->shader = std::make_shared(); } void car_widget::update(uint32_t dt) @@ -120,7 +143,7 @@ void car_widget::update(uint32_t dt) ++this->fps; this->rot = // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - (ruis::quaternion().set_rotation(r4::vector3(0, 1, 0).normalize(), 2.0f * 3.1415926f * float(fraction()))) * + (ruis::quaternion().set_rotation(r4::vector3(0, 1, 0).normalize(), 2.0f * 3.1415926f * float(get_fraction()))) * //ruis::quaternion().set_identity() * (ruis::quaternion().set_rotation(r4::vector3(0, 1, 0).normalize(), 0.1f * (float(this->time_sec) / std::milli::den))); //(ruis::quaternion().set_rotation(r4::vector3(0, 1, 0).normalize(), 0.1f * (float(this->time_sec) / std::milli::den))); @@ -132,27 +155,141 @@ void car_widget::update(uint32_t dt) this->clear_cache(); } +ruis::mat4 look_at(const ruis::vec3& eye, const ruis::vec3& center, const ruis::vec3& up) +{ + ruis::vec3 f = (center - eye).normalize(); + ruis::vec3 s = f.cross(up).normalize(); + ruis::vec3 u = s.cross(f); + + ruis::mat4 lookat; + lookat.set_identity(); + lookat.transpose(); + //lookat.set(1.f); + lookat[0][0] = s[0]; + lookat[1][0] = s[1]; + lookat[2][0] = s[2]; + lookat[0][1] = u[0]; + lookat[1][1] = u[1]; + lookat[2][1] = u[2]; + lookat[0][2] = -f[0]; + lookat[1][2] = -f[1]; + lookat[2][2] = -f[2]; + lookat[3][0] = -s * eye; // * = dot product + lookat[3][1] = -u * eye; + lookat[3][2] = f * eye; + + return lookat.tposed(); +} + +//// look_at in case of other handedness +// { +// vec<3, T, Q> const f(normalize(center - eye)); +// vec<3, T, Q> const s(normalize(cross(up, f))); +// vec<3, T, Q> const u(cross(f, s)); + +// mat<4, 4, T, Q> Result(1); +// Result[0][0] = s.x; +// Result[1][0] = s.y; +// Result[2][0] = s.z; +// Result[0][1] = u.x; +// Result[1][1] = u.y; +// Result[2][1] = u.z; +// Result[0][2] = f.x; +// Result[1][2] = f.y; +// Result[2][2] = f.z; +// Result[3][0] = -dot(s, eye); +// Result[3][1] = -dot(u, eye); +// Result[3][2] = -dot(f, eye); +// return Result; +// } + +ruis::mat4 perspective(float fovy, float aspect, float zNear, float zFar) +{ + // assert(aspect != 0); + // assert(zFar != zNear); + float tan_half_fov_y = tan(fovy / 2.0f); + ruis::mat4 persp; + persp.set(0.f); + persp[0][0] = 1.0f / (aspect * tan_half_fov_y); + persp[1][1] = 1.0f / (tan_half_fov_y); + persp[2][2] = -(zFar + zNear) / (zFar - zNear); + persp[2][3] = -1.0f; + persp[3][2] = -(2.0f * zFar * zNear) / (zFar - zNear); + + return persp.tposed(); +} + void car_widget::render(const ruis::matrix4& matrix) const { this->widget::render(matrix); - ruis::matrix4 matr(matrix); - matr.scale(this->rect().d / 2); - matr.translate(1, 1); - matr.scale(1, -1); - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - matr.frustum(-1, 1, -1, 1, 1, 100); - matr.translate(0, -1.6, -4); - matr.rotate(this->rot); + // ruis::mat4 mvp(matrix); // matr = mvp matrix + // mvp.scale(this->rect().d / 2); + // mvp.translate(1, 1); + // mvp.scale(1, 1); + // mvp.scale(1, -1, -1); + //mvp.frustum(-1, 1, -1, 1, 1, 10); + //mvp.translate(0, -1.6, -4); + //mvp.rotate(this->rot); + //mvp.scale(2, 2, 2); + + // old ^^ + // new below + + //std::cout << "sin(30) = " << sin(30 * 3.1415926535 / 180) << std::endl; + ruis::mat4 modelview, model, view, projection, mvp; + ruis::vec3 pos{3, 1, 3}; + projection = perspective(3.1415926535f / 2.8f, this->rect().d[0] / this->rect().d[1], 0.1f, 10.0f); + view.set_identity(); + view = look_at(pos, ruis::vec3(0, 1, 0), ruis::vec3(0, 2, 0)); + model.set_identity(); + //model.translate(0, -0.7, -3); + model.rotate(this->rot); + + modelview = view * model; + mvp = projection * view * model; // p * v * m + //mvp = projection;// * mvp; + + // The normal matrix is typically the inverse transpose of the + // upper-left 3 x 3 portion of the model-view matrix. We use the + // inverse transpose because normal vectors transform differently + // than the vertex position. + ruis::mat3 normal = from_mat4(modelview); + normal.invert(); + normal.transpose(); + + ruis::vec4 light_pos{3.0f, 4.0f, 5.0f, 1.0f}; + ruis::vec3 light_int{0.5f, 0.7f, 0.9f}; + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + //this->context.get().renderer.get().shader->pos_tex->render(matr, *this->cube_vao, this->tex->tex()); + //static_cast(tex_car_diffuse->tex()).bind(0); // rewritten by official draw call + + // void set_uniform_sampler(GLint id, GLint texture_unit_num) const; + // void set_uniform_matrix4f(GLint id, const r4::matrix4& m) const; + // void set_uniform4f(GLint id, float x, float y, float z, float a) const; + +// mat4_modelview, mat4_projection, mat3_normal, vec4_light_position, vec3_light_intensity; + + //(static_cast(shader)) + shader->set_uniform4f(shader->vec4_light_position, light_pos[0], light_pos[1], light_pos[2], light_pos[3]); + shader->set_uniform3f(shader->vec3_light_intensity, light_int[0], light_int[1], light_int[2]); + shader->set_uniform_matrix4f(shader->mat4_modelview, modelview); + shader->set_uniform_matrix4f(shader->mat4_projection, projection); + shader->set_uniform_matrix3f(shader->mat3_normal, normal); - //glEnable(GL_CULL_FACE); + GLenum err; + while((err = glGetError()) != GL_NO_ERROR) {} // skip all uniform-related errors - this->context.get().renderer.get().shader->pos_tex->render(matr, *this->cube_vao, this->tex->tex()); + shader->render(mvp, *this->car_vao, this->tex_car_diffuse->tex()); //glActiveTexture(GL_TEXTURE0 + 0); - //glBindTexture(GL_TEXTURE_2D, 1); + //glBindTexture(GL_TEXTURE_2D, static_cast(tex_car_diffuse->tex())); - car_model_obj->render(); + //car_model_obj->render(); - //glDisable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); } diff --git a/src/car_widget.hpp b/src/car_widget.hpp index 74846af..6244157 100644 --- a/src/car_widget.hpp +++ b/src/car_widget.hpp @@ -25,8 +25,16 @@ along with this program. If not, see . #include #include #include -#include "car_view/model_obj.h" +#include "car_view/model_obj.hpp" +#include "car_view/shaders/shader_car.hpp" + +namespace ruis // TODO: move to ruis config.hpp +{ + using mat3 = r4::matrix3; + using matrix3 = mat3; + static_assert(sizeof(mat3) == sizeof(real) * 3 * 3, "size mismatch"); +} namespace carcockpit { class car_widget : public ruis::fraction_widget, public ruis::updateable, virtual public ruis::widget @@ -46,6 +54,8 @@ class car_widget : public ruis::fraction_widget, public ruis::updateable, virtua std::shared_ptr cube_vao; std::shared_ptr car_vao; + std::shared_ptr shader; + unsigned fps = 0; uint32_t fps_sec_counter = 0; uint32_t time_sec = 0; diff --git a/src/gauge.cpp b/src/gauge.cpp index ba15464..68fe50c 100644 --- a/src/gauge.cpp +++ b/src/gauge.cpp @@ -28,7 +28,7 @@ using namespace ruis; gauge::gauge(utki::shared_ref c, all_parameters p) : widget(std::move(c), {.widget_params = std::move(p.widget_params)}), blending_widget(this->context, std::move(p.blending_params)), - fraction_widget(this->context), + fraction_widget(this->context, {}), params(std::move(p.params)) {} @@ -69,7 +69,7 @@ void gauge::render(const matrix4& matrix) const matrix4 mmm; mmm.set_identity(); mmm.rotate( - -(this->params.start_angle_rad + (this->params.end_angle_rad - this->params.start_angle_rad) * this->fraction()) + -(this->params.start_angle_rad + (this->params.end_angle_rad - this->params.start_angle_rad) * this->get_fraction()) ); { auto div = this->arrow_tex->dims.x() * this->params.arm_fraction; diff --git a/src/gui.cpp b/src/gui.cpp index 2614878..e5c22de 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -127,7 +127,8 @@ utki::shared_ref carcockpit::make_root_layout(utki::shared_ref carcockpit::make_root_layout(utki::shared_ref("car_widget"); diff --git a/src/main.cpp b/src/main.cpp index 271af10..a23ec7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,6 +42,7 @@ class application : public ruisapp::application []() { // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) ruisapp::window_params wp(r4::vector2(1024, 600)); + wp.buffers.set(ruisapp::window_params::buffer::depth); return wp; }() ) @@ -60,8 +61,8 @@ const ruisapp::application_factory app_fac([](auto executable, auto args) { bool window = false; // TODO: look in /usr/local/share/carcockpit first? - //std::string res_path = utki::cat("/usr/share/"sv, app_name); - std::string res_path = "res/"s; + std::string res_path = utki::cat("/usr/share/"sv, app_name); + //std::string res_path = "res/"s; clargs::parser p;