From 16d9d575381b40fce0b87755935a6906a33c4f1d Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 18 Sep 2018 11:19:11 +0200 Subject: [PATCH 001/114] Fix clearing --- m3dialib/source/graphics/screen.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index dbf3c47..8a5cc75 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -69,11 +69,13 @@ namespace m3d { void Screen::render(bool t_clear) { if(m_drawStackTop.size() > 0 || m_drawStackBottom.size() > 0) { C3D_FrameBegin(C3D_FRAME_SYNCDRAW); - m_targetTopLeft->clear(); - m_targetTopRight->clear(); - m_targetBottom->clear(); - if (t_clear) clear(); + if (t_clear) { + m_targetTopLeft->clear(); + m_targetTopRight->clear(); + m_targetBottom->clear(); + clear(); + } if(m_drawStackBottom.size() > 0) { C2D_SceneBegin(m_targetBottom->getRenderTarget()); From b888baa7797296a59fa3d04029a1777c8e145b66 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:06:40 +0200 Subject: [PATCH 002/114] Fix texture loading --- m3dialib/source/graphics/texture.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/m3dialib/source/graphics/texture.cpp b/m3dialib/source/graphics/texture.cpp index 8512d69..a797db1 100644 --- a/m3dialib/source/graphics/texture.cpp +++ b/m3dialib/source/graphics/texture.cpp @@ -148,7 +148,6 @@ namespace m3d { png_destroy_read_struct(&png, &info, NULL); unloadImage(m_image); - C3D_TexSetFilter(m_texture, GPU_LINEAR, GPU_LINEAR); m_texture = static_cast(malloc(sizeof(C3D_Tex))); m_image.tex = m_texture; @@ -174,8 +173,8 @@ namespace m3d { } } + C3D_TexSetFilter(m_texture, GPU_LINEAR, GPU_LINEAR); m_image.tex->border = 0xFFFFFFFF; - C3D_TexSetWrap(m_image.tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER); return true; } From 9ecbfa68f214adcc02fb3642b931a103ef378869 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:07:01 +0200 Subject: [PATCH 003/114] Add graphics-private --- m3dialib/includes/m3d/private/graphics.hpp | 17 ++++++++++++++ m3dialib/source/private/graphics.cpp | 26 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 m3dialib/includes/m3d/private/graphics.hpp create mode 100644 m3dialib/source/private/graphics.cpp diff --git a/m3dialib/includes/m3d/private/graphics.hpp b/m3dialib/includes/m3d/private/graphics.hpp new file mode 100644 index 0000000..44de546 --- /dev/null +++ b/m3dialib/includes/m3d/private/graphics.hpp @@ -0,0 +1,17 @@ +#ifndef GRAPHICS_PRIVATE_H +#define GRAPHICS_PRIVATE_H + +#pragma once +#include + +namespace m3d { + namespace priv { + namespace graphics { + extern const C3D_Material material; + extern const C3D_Mtx materialMatrix; + } /* graphics */ + } /* priv */ +} /* m3d */ + + +#endif /* end of include guard: GRAPHICS_PRIVATE_H */ diff --git a/m3dialib/source/private/graphics.cpp b/m3dialib/source/private/graphics.cpp new file mode 100644 index 0000000..e3b9461 --- /dev/null +++ b/m3dialib/source/private/graphics.cpp @@ -0,0 +1,26 @@ +#include +#include "m3d/private/graphics.hpp" + +namespace m3d { + namespace priv { + namespace graphics { + const C3D_Material material = { + { 0.1f, 0.1f, 0.1f }, //ambient + { 0.4f, 0.4f, 0.4f }, //diffuse + { 0.5f, 0.5f, 0.5f }, //specular0 + { 0.0f, 0.0f, 0.0f }, //specular1 + { 0.0f, 0.0f, 0.0f }, //emission + }; + + const C3D_Mtx materialMatrix = + { + { + { { 0.0f, 0.2f, 0.2f, 0.2f } }, // Ambient + { { 0.0f, 0.4f, 0.4f, 0.4f } }, // Diffuse + { { 0.0f, 0.8f, 0.8f, 0.8f } }, // Specular + { { 1.0f, 0.0f, 0.0f, 0.0f } }, // Emission + } + }; + } /* graphics */ + } /* priv */ +} /* m3d */ From 0a027073bd486eb52c857cc69ad07ae50ca39c38 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:07:11 +0200 Subject: [PATCH 004/114] Include graphics-private --- m3dialib/includes/m3d/private/private.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/m3dialib/includes/m3d/private/private.hpp b/m3dialib/includes/m3d/private/private.hpp index 5400dc2..3290b76 100644 --- a/m3dialib/includes/m3d/private/private.hpp +++ b/m3dialib/includes/m3d/private/private.hpp @@ -3,6 +3,7 @@ #pragma once #include "ndsp.hpp" +#include "graphics.hpp" #endif /* end of include guard: PRIVATE_H */ From 59984702014b0fd39630b4adcad45405ba95aecb Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:09:36 +0200 Subject: [PATCH 005/114] Add RenderContext-class --- .../includes/m3d/graphics/renderContext.hpp | 84 +++++++++++++++++++ m3dialib/source/graphics/renderContext.cpp | 78 +++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 m3dialib/includes/m3d/graphics/renderContext.hpp create mode 100644 m3dialib/source/graphics/renderContext.cpp diff --git a/m3dialib/includes/m3d/graphics/renderContext.hpp b/m3dialib/includes/m3d/graphics/renderContext.hpp new file mode 100644 index 0000000..79d1028 --- /dev/null +++ b/m3dialib/includes/m3d/graphics/renderContext.hpp @@ -0,0 +1,84 @@ +#ifndef RENDERCONTEXT_H +#define RENDERCONTEXT_H + +#pragma once +#include + +namespace m3d { + class RenderContext { + public: + /** + * @brief Defines the screen targets (top/bottom) + */ + enum class ScreenTarget { + Top, ///< Top screen + Bottom ///< Bottom/touch screen + }; + + /** + * @brief Defines the two sides in stereoscopic 3D mode + */ + enum class Stereo3dSide { + Left, ///< Left side + Right ///< Right side + }; + + /** + * @brief Defines the two drawing-modes + */ + enum class Mode { + Flat, ///< 2D + Spatial ///< 3D + }; + + RenderContext( + int t_projectionUniform, + int t_modelViewUniform, + int t_lightVecUniform, + int t_lightHalfVecUniform, + int t_lightColorUniform, + int t_materialUniform, + bool t_3dEnabled, + m3d::RenderContext::Mode t_mode, + m3d::RenderContext::Stereo3dSide t_side, + m3d::RenderContext::ScreenTarget t_target, + C3D_Mtx& t_projection, + C3D_Mtx& t_modelView + ); + + int getProjectionUniform(); + + int getModelViewUniform(); + + int getLightVecUniform(); + + int getLightHalfVecUniform(); + + int getLightColorUniform(); + + int getMaterialUniform(); + + bool is3dEnabled(); + + m3d::RenderContext::Mode getMode(); + + m3d::RenderContext::Stereo3dSide getSide(); + + m3d::RenderContext::ScreenTarget getScreenTarget(); + + C3D_Mtx& getProjectionMatrix(); + + C3D_Mtx& getModelViewMatrix(); + + private: + /* data */ + int m_projectionUniformLocation, m_modelViewUniformLocation, m_lightVecUniformLocation, m_lightHalfVecUniformLocation, m_lightColorUniformLocation, m_materialUniformLocation; + bool m_3dEnabled; + m3d::RenderContext::Mode m_mode; + m3d::RenderContext::Stereo3dSide m_side; + m3d::RenderContext::ScreenTarget m_target; + C3D_Mtx &m_projection, &m_modelView; + }; +} /* m3d */ + +#endif /* end of include guard: RENDERCONTEXT_H */ diff --git a/m3dialib/source/graphics/renderContext.cpp b/m3dialib/source/graphics/renderContext.cpp new file mode 100644 index 0000000..9483308 --- /dev/null +++ b/m3dialib/source/graphics/renderContext.cpp @@ -0,0 +1,78 @@ +#include "m3d/graphics/renderContext.hpp" + +namespace m3d { + RenderContext::RenderContext( + int t_projectionUniform, + int t_modelViewUniform, + int t_lightVecUniform, + int t_lightHalfVecUniform, + int t_lightColorUniform, + int t_materialUniform, + bool t_3dEnabled, + m3d::RenderContext::Mode t_mode, + m3d::RenderContext::Stereo3dSide t_side, + m3d::RenderContext::ScreenTarget t_target, + C3D_Mtx& t_projection, + C3D_Mtx& t_modelView + ) : + m_projectionUniformLocation(t_projectionUniform), + m_modelViewUniformLocation(t_modelViewUniform), + m_lightVecUniformLocation(t_lightVecUniform), + m_lightHalfVecUniformLocation(t_lightHalfVecUniform), + m_lightColorUniformLocation(t_lightColorUniform), + m_materialUniformLocation(t_materialUniform), + m_3dEnabled(t_3dEnabled), + m_mode(t_mode), + m_side(t_side), + m_target(t_target), + m_projection(t_projection), + m_modelView(t_modelView) { /* do nothing */ } + + int RenderContext::getProjectionUniform() { + return m_projectionUniformLocation; + } + + int RenderContext::getModelViewUniform() { + return m_modelViewUniformLocation; + } + + int RenderContext::getLightVecUniform() { + return m_lightVecUniformLocation; + } + + int RenderContext::getLightHalfVecUniform() { + return m_lightHalfVecUniformLocation; + } + + int RenderContext::getLightColorUniform() { + return m_lightColorUniformLocation; + } + + int RenderContext::getMaterialUniform() { + return m_materialUniformLocation; + } + + bool RenderContext::is3dEnabled() { + return m_3dEnabled; + } + + m3d::RenderContext::Mode RenderContext::getMode() { + return m_mode; + } + + m3d::RenderContext::Stereo3dSide RenderContext::getSide() { + return m_side; + } + + m3d::RenderContext::ScreenTarget RenderContext::getScreenTarget() { + return m_target; + } + + C3D_Mtx& RenderContext::getProjectionMatrix() { + return m_projection; + } + + C3D_Mtx& RenderContext::getModelViewMatrix() { + return m_modelView; + } +} /* m3d */ From 5838ca0895e0fb23f2421f2fd1fe78fd738a9e8a Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:09:44 +0200 Subject: [PATCH 006/114] Add 3D shader --- m3dialib/source/graphics/render3d.v.pica | 87 ++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 m3dialib/source/graphics/render3d.v.pica diff --git a/m3dialib/source/graphics/render3d.v.pica b/m3dialib/source/graphics/render3d.v.pica new file mode 100644 index 0000000..03272ad --- /dev/null +++ b/m3dialib/source/graphics/render3d.v.pica @@ -0,0 +1,87 @@ +; Example PICA200 vertex shader + +; Uniforms +.fvec projection[4], modelView[4] +.fvec lightVec, lightHalfVec, lightClr, material[4] +.alias mat_amb material[0] +.alias mat_dif material[1] +.alias mat_spe material[2] +.alias mat_emi material[3] + +; Constants +.constf myconst(0.0, 1.0, -1.0, -0.5) +.alias zeros myconst.xxxx ; Vector full of zeros +.alias ones myconst.yyyy ; Vector full of ones + +; Outputs +.out outpos position +.out outtc0 texcoord0 +.out outclr color + +; Inputs (defined as aliases for convenience) +.alias inpos v0 +.alias intex v1 +.alias innrm v2 + +.proc main + ; Force the w component of inpos to be 1.0 + mov r0.xyz, inpos + mov r0.w, ones + + ; r1 = modelView * inpos + dp4 r1.x, modelView[0], r0 + dp4 r1.y, modelView[1], r0 + dp4 r1.z, modelView[2], r0 + dp4 r1.w, modelView[3], r0 + + ; outpos = projection * r1 + dp4 outpos.x, projection[0], r1 + dp4 outpos.y, projection[1], r1 + dp4 outpos.z, projection[2], r1 + dp4 outpos.w, projection[3], r1 + + ; outtex = intex + mov outtc0, intex + + ; Transform the normal vector with the modelView matrix + ; r1 = normalize(modelView * innrm) + mov r0.xyz, innrm + mov r0.w, zeros + dp4 r1.x, modelView[0], r0 + dp4 r1.y, modelView[1], r0 + dp4 r1.z, modelView[2], r0 + mov r1.w, zeros + dp3 r2, r1, r1 ; r2 = x^2+y^2+z^2 for each component + rsq r2, r2 ; r2 = 1/sqrt(r2) '' + mul r1, r2, r1 ; r1 = r1*r2 + + ; Calculate the diffuse level (r0.x) and the shininess level (r0.y) + ; r0.x = max(0, -(lightVec * r1)) + ; r0.y = max(0, (-lightHalfVec[i]) * r1) ^ 2 + dp3 r0.x, lightVec, r1 + add r0.x, zeros, -r0 + dp3 r0.y, -lightHalfVec, r1 + max r0, zeros, r0 + mul r0.y, r0, r0 + + ; Accumulate the vertex color in r1, initializing it to the emission color + mov r1, mat_emi + + ; r1 += specularColor * lightClr * shininessLevel + mul r2, lightClr, r0.yyyy + mad r1, r2, mat_spe, r1 + + ; r1 += diffuseColor * lightClr * diffuseLevel + mul r2, lightClr, r0.xxxx + mad r1, r2, mat_dif, r1 + + ; r1 += ambientColor * lightClr + mov r2, lightClr + mad r1, r2, mat_amb, r1 + + ; outclr = clamp r1 to [0,1] + min outclr, ones, r1 + + ; We're finished + end +.end From 938abc2790b39c9b63af36520489937825f16775 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:10:26 +0200 Subject: [PATCH 007/114] Remove useless constructor --- m3dialib/includes/m3d/graphics/renderTarget.hpp | 16 +--------------- m3dialib/source/graphics/renderTarget.cpp | 12 ------------ 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/renderTarget.hpp b/m3dialib/includes/m3d/graphics/renderTarget.hpp index c019309..3e2599d 100644 --- a/m3dialib/includes/m3d/graphics/renderTarget.hpp +++ b/m3dialib/includes/m3d/graphics/renderTarget.hpp @@ -15,13 +15,6 @@ namespace m3d { */ class RenderTarget { public: - /** - * @brief Creates a render target - * @param t_width The width of the target - * @param t_height The height of the target - */ - RenderTarget(int t_width, int t_height); - /** * @brief Creates a render target * @param t_width The width of the target @@ -37,12 +30,6 @@ namespace m3d { */ C3D_RenderTarget* getRenderTarget(); - /** - * @brief Returns the projection matrix of this render target - * @return The projection matrix - */ - C3D_Mtx* getProjectionMatrix(); - /** * @brief Returns the width of this render target * @return The width of the render target @@ -76,10 +63,9 @@ namespace m3d { private: /* data */ - C3D_RenderTarget* m_target; - C3D_Mtx m_projection; int m_width, m_height; u32 m_clearColor; + C3D_RenderTarget* m_target; }; } /* m3d */ diff --git a/m3dialib/source/graphics/renderTarget.cpp b/m3dialib/source/graphics/renderTarget.cpp index 485675f..dc6ef8d 100644 --- a/m3dialib/source/graphics/renderTarget.cpp +++ b/m3dialib/source/graphics/renderTarget.cpp @@ -3,14 +3,6 @@ #include "m3d/graphics/color.hpp" namespace m3d { - RenderTarget::RenderTarget(int t_width, int t_height) : - m_width(t_width), - m_height(t_height), - m_clearColor(RGBA8(0, 0, 0, 255)) { - m_target = C3D_RenderTargetCreate(t_height, t_width, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - Mtx_OrthoTilt(&m_projection, 0.0f, t_width, t_height, 0.0f, 0.0f, 1.0f, true); - } - RenderTarget::RenderTarget(int t_width, int t_height, gfxScreen_t t_screen, gfx3dSide_t t_side = GFX_LEFT) : m_width(t_width), m_height(t_height), @@ -22,10 +14,6 @@ namespace m3d { return m_target; } - C3D_Mtx* RenderTarget::getProjectionMatrix() { - return &m_projection; - } - int RenderTarget::getWidth() { return m_width; } From 741d1e587702ea1721f7b7ad40ada0d24a8eda3b Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:12:23 +0200 Subject: [PATCH 008/114] Adapt to RenderContext --- m3dialib/includes/m3d/graphics/drawable.hpp | 10 +++++----- m3dialib/includes/m3d/graphics/drawables/shape.hpp | 5 ++--- m3dialib/includes/m3d/graphics/drawables/sprite.hpp | 6 ++---- m3dialib/includes/m3d/graphics/drawables/text.hpp | 5 ++--- m3dialib/source/graphics/shape.cpp | 4 +--- m3dialib/source/graphics/sprite.cpp | 2 +- m3dialib/source/graphics/text.cpp | 2 +- 7 files changed, 14 insertions(+), 20 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/drawable.hpp b/m3dialib/includes/m3d/graphics/drawable.hpp index e94cc67..73eeb2e 100644 --- a/m3dialib/includes/m3d/graphics/drawable.hpp +++ b/m3dialib/includes/m3d/graphics/drawable.hpp @@ -7,23 +7,23 @@ #pragma once #include +#include "renderContext.hpp" namespace m3d { /** * @brief The base class for all drawable classes. * - * To create your own drawable class, create a child class of this one and implement the draw()-function. + * To create your own drawable class, create a child class of this one and implement the draw()-method. */ class Drawable { public: /** * @brief Draws the drawable object - * @param t_3dEnabled Whether stereoscopic 3D is enabled or not - * @param t_side The current 3D side (0 = left, 1 = right) + * @param t_context the RenderContext * - * Implement this function in your own class to draw stuff on the screen using Citro2D-functions. + * Implement this function in your own class to draw stuff on the screen using Citro3D/2D-functions. */ - virtual void draw(bool t_3dEnabled = false, int t_side = 0) = 0; + virtual void draw(m3d::RenderContext t_context) = 0; }; } /* m3d */ diff --git a/m3dialib/includes/m3d/graphics/drawables/shape.hpp b/m3dialib/includes/m3d/graphics/drawables/shape.hpp index 0bc7af0..5a6966d 100644 --- a/m3dialib/includes/m3d/graphics/drawables/shape.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/shape.hpp @@ -47,10 +47,9 @@ namespace m3d { /** * @brief Draws the shape - * @param t_3dEnabled Whether stereoscopic 3D is enabled or not - * @param t_side The current 3D side (0 = left, 1 = right) + * @param t_context the RenderContext */ - void draw(bool t_3dEnabled = false, int t_side = 0); + void draw(m3d::RenderContext t_context); private: /* data */ diff --git a/m3dialib/includes/m3d/graphics/drawables/sprite.hpp b/m3dialib/includes/m3d/graphics/drawables/sprite.hpp index 168e186..1265361 100644 --- a/m3dialib/includes/m3d/graphics/drawables/sprite.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/sprite.hpp @@ -259,10 +259,9 @@ namespace m3d { /** * @brief Draws the shape - * @param t_3dEnabled Whether stereoscopic 3D is enabled or not - * @param t_side The current 3D side (0 = left, 1 = right) + * @param t_context the RenderContext */ - void draw(bool t_3dEnabled = false, int t_side = 0); + void draw(m3d::RenderContext t_context); private: void updateTint(); @@ -279,4 +278,3 @@ namespace m3d { } /* m3d */ #endif /* end of include guard: SPRITE_H */ - diff --git a/m3dialib/includes/m3d/graphics/drawables/text.hpp b/m3dialib/includes/m3d/graphics/drawables/text.hpp index 483a719..c8a11fa 100644 --- a/m3dialib/includes/m3d/graphics/drawables/text.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/text.hpp @@ -192,10 +192,9 @@ namespace m3d { /** * @brief Draws the text - * @param t_3dEnabled Whether stereoscopic 3D is enabled or not - * @param t_side The current 3D side (0 = left, 1 = right) + * @param t_context the RenderContext */ - void draw(bool t_3dEnabled = false, int t_side = 0); + void draw(m3d::RenderContext t_context); private: /* data */ diff --git a/m3dialib/source/graphics/shape.cpp b/m3dialib/source/graphics/shape.cpp index 37eeb49..f758811 100644 --- a/m3dialib/source/graphics/shape.cpp +++ b/m3dialib/source/graphics/shape.cpp @@ -21,8 +21,7 @@ namespace m3d { m_changed = true; } - void Shape::draw(bool, int) { - if (m_changed) { + void Shape::draw(m3d::RenderContext t_context) { m_changed = false; std::vector>> polygon; @@ -34,7 +33,6 @@ namespace m3d { polygon.push_back(polyline); m_indices = mapbox::earcut(polygon); - } for (unsigned int i = 0; i < m_indices.size(); i += 3) { C2D_DrawTriangle( diff --git a/m3dialib/source/graphics/sprite.cpp b/m3dialib/source/graphics/sprite.cpp index d36cb13..02af3ec 100644 --- a/m3dialib/source/graphics/sprite.cpp +++ b/m3dialib/source/graphics/sprite.cpp @@ -215,7 +215,7 @@ namespace m3d { return m_spriteSheetPath; } - void Sprite::draw(bool t_3dEnabled, int t_side) { + void Sprite::draw(m3d::RenderContext t_context) { C2D_DrawSpriteTinted(&m_sprite, &m_imageTint); } diff --git a/m3dialib/source/graphics/text.cpp b/m3dialib/source/graphics/text.cpp index 4398551..545f8a2 100644 --- a/m3dialib/source/graphics/text.cpp +++ b/m3dialib/source/graphics/text.cpp @@ -132,7 +132,7 @@ namespace m3d { return m_baseline; } - void Text::draw(bool, int) { + void Text::draw(m3d::RenderContext t_context) { C2D_DrawText( &m_textObject, (m_baseline ? C2D_AtBaseline | C2D_WithColor : C2D_WithColor), From 4c23f65e4e60d955bc1b4e56696e54705f202f39 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:13:15 +0200 Subject: [PATCH 009/114] Add 3D renderqueue --- m3dialib/includes/m3d/graphics/screen.hpp | 47 ++-- m3dialib/source/graphics/screen.cpp | 266 ++++++++++++++++++---- 2 files changed, 245 insertions(+), 68 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index 136730e..dadfd4c 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -6,10 +6,10 @@ #define SCREEN_H #pragma once -#include -#include -#include #include +#include +#include +#include #include "renderTarget.hpp" #include "drawable.hpp" #include "color.hpp" @@ -23,22 +23,6 @@ namespace m3d { */ class Screen { public: - /** - * @brief Defines the screen targets (top/bottom) - */ - enum ScreenTarget { - Top, ///< Top screen - Bottom ///< Bottom/touch screen - }; - - /** - * @brief Defines the two sides in stereoscopic 3D mode - */ - enum Stereo3dSide { - Left = 0, ///< Left side - Right = 1 ///< Right side - }; - /** * @brief Initializes the m3d::Screen object * @param t_enable3d Whether to enable stereoscopic 3D by default @@ -67,28 +51,30 @@ namespace m3d { * @param t_color The color to clear the screen with * @param t_target The screen to clear set the color for */ - void setClearColor(m3d::Color t_color, m3d::Screen::ScreenTarget t_target); + void setClearColor(m3d::Color t_color, m3d::RenderContext::ScreenTarget t_target); /** * @brief Returns the clear color for the given screen * @param t_target The screen to get the color from * @return The set clear color for the screen */ - m3d::Color getClearColor(m3d::Screen::ScreenTarget t_target); + m3d::Color getClearColor(m3d::RenderContext::ScreenTarget t_target); /** * @brief Draws something on the top screen * @param t_object The object that should be drawn + * @param t_mode The drawing-mode * @param t_layer The z-inex the object should be drawn at */ - void drawTop(m3d::Drawable& t_object, int t_layer = 0); + void drawTop(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode = m3d::RenderContext::Mode::Flat, int t_layer = 0); /** * @brief Draws something on the bottom screen * @param t_object The object that should be drawn + * @param t_mode The drawing-mode * @param t_layer The z-inex the object should be drawn at */ - void drawBottom(m3d::Drawable& t_object, int t_layer = 0); + void drawBottom(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode = m3d::RenderContext::Mode::Flat, int t_layer = 0); /** * @brief Renders the current screen @@ -101,7 +87,7 @@ namespace m3d { * @param t_target The target screen * @return The width of the screen in pixels */ - static int getScreenWidth(m3d::Screen::ScreenTarget t_target); + static int getScreenWidth(m3d::RenderContext::ScreenTarget t_target); /** * @brief Returns the height of the screen @@ -109,18 +95,23 @@ namespace m3d { */ static int getScreenHeight(); - private: + /** + * @brief Clears the screen manually + */ void clear(); + private: + void prepare(); /* data */ - int m_projection, m_transform, m_useTransform; + int m_projectionUniform, m_modelViewUniform, m_lightVecUniform, m_lightHalfVecUniform, m_lightColorUniform, m_materialUniform; bool m_3dEnabled; m3d::Color m_clearColorTop, m_clearColorBottom; m3d::RenderTarget *m_targetTopLeft, *m_targetTopRight, *m_targetBottom; - std::map, std::less> m_drawStackTop, m_drawStackBottom; + std::map, std::less> m_drawStackTop2d, m_drawStackTop3d, m_drawStackBottom2d, m_drawStackBottom3d; DVLB_s *m_dvlb; shaderProgram_s m_shader; - + C3D_AttrInfo* m_attributeInfo; + C3D_Mtx m_projection, m_projectionBottom, m_modelView, m_modelViewBottom; }; } /* m3d */ diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 8a5cc75..b3b8b0b 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -1,6 +1,8 @@ #include #include "m3d/graphics/screen.hpp" #include "m3d/graphics/color.hpp" +#include "m3d/private/graphics.hpp" +#include "render3d_shbin.h" namespace m3d { Screen::Screen(bool t_enable3d) : @@ -9,7 +11,6 @@ namespace m3d { gfxInitDefault(); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); C2D_Init(C2D_DEFAULT_MAX_OBJECTS); - C2D_Prepare(); gfxSet3D(t_enable3d); C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); m_3dEnabled = t_enable3d; @@ -17,10 +18,30 @@ namespace m3d { m_targetTopRight = new m3d::RenderTarget(400, 240, GFX_TOP, GFX_RIGHT); m_targetBottom = new m3d::RenderTarget(320, 240, GFX_BOTTOM, GFX_LEFT); + u32 flags = GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO); + + C3D_RenderTargetSetOutput(m_targetTopLeft->getRenderTarget(), GFX_TOP, GFX_LEFT, flags); + C3D_RenderTargetSetOutput(m_targetTopRight->getRenderTarget(), GFX_TOP, GFX_RIGHT, flags); + C3D_RenderTargetSetOutput(m_targetBottom->getRenderTarget(), GFX_BOTTOM, GFX_LEFT, flags); + + m_dvlb = DVLB_ParseFile((u32*) render3d_shbin, render3d_shbin_size); + shaderProgramInit(&m_shader); + shaderProgramSetVsh(&m_shader, &m_dvlb->DVLE[0]); + + // get location of uniforms used in the vertex shader. + m_projectionUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "projection"); + m_modelViewUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "modelView"); + m_lightVecUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "lightVec"); + m_lightHalfVecUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "lightHalfVec"); + m_lightColorUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "lightClr"); + m_materialUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "material"); + clear(); } Screen::~Screen() { + shaderProgramFree(&m_shader); + DVLB_Free(m_dvlb); C2D_Fini(); C3D_Fini(); gfxExit(); @@ -36,95 +57,260 @@ namespace m3d { m_clearColorBottom = t_color; } - void Screen::setClearColor(m3d::Color t_color, m3d::Screen::ScreenTarget t_target) { - t_target == m3d::Screen::ScreenTarget::Top ? + void Screen::setClearColor(m3d::Color t_color, m3d::RenderContext::ScreenTarget t_target) { + t_target == m3d::RenderContext::ScreenTarget::Top ? m_clearColorTop = t_color : m_clearColorBottom = t_color; } - m3d::Color Screen::getClearColor(m3d::Screen::ScreenTarget t_target) { - return t_target == m3d::Screen::ScreenTarget::Top ? m_clearColorTop : m_clearColorBottom; + m3d::Color Screen::getClearColor(m3d::RenderContext::ScreenTarget t_target) { + return t_target == m3d::RenderContext::ScreenTarget::Top ? m_clearColorTop : m_clearColorBottom; } - void Screen::drawTop(m3d::Drawable& t_object, int t_layer) { - if(m_drawStackTop.count(t_layer) > 0) { - m_drawStackTop[t_layer].insert(m_drawStackTop[t_layer].end(), &t_object); + void Screen::drawTop(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode, int t_layer) { + if (t_mode == m3d::RenderContext::Mode::Flat) { + if(m_drawStackTop2d.count(t_layer) > 0) { + m_drawStackTop2d[t_layer].insert(m_drawStackTop2d[t_layer].end(), &t_object); + } else { + std::vector newStack; + newStack.push_back(&t_object); + m_drawStackTop2d.insert(std::make_pair(t_layer, newStack)); + } } else { - std::vector newStack; - newStack.push_back(&t_object); - m_drawStackTop.insert(std::make_pair(t_layer, newStack)); + if(m_drawStackTop3d.count(t_layer) > 0) { + m_drawStackTop3d[t_layer].insert(m_drawStackTop3d[t_layer].end(), &t_object); + } else { + std::vector newStack; + newStack.push_back(&t_object); + m_drawStackTop3d.insert(std::make_pair(t_layer, newStack)); + } } } - void Screen::drawBottom(m3d::Drawable& t_object, int t_layer) { - if(m_drawStackBottom.count(t_layer) > 0) { - m_drawStackBottom[t_layer].insert(m_drawStackBottom[t_layer].end(), &t_object); + void Screen::drawBottom(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode, int t_layer) { + if (t_mode == m3d::RenderContext::Mode::Flat) { + if(m_drawStackBottom2d.count(t_layer) > 0) { + m_drawStackBottom2d[t_layer].insert(m_drawStackBottom2d[t_layer].end(), &t_object); + } else { + std::vector newStack; + newStack.push_back(&t_object); + m_drawStackBottom2d.insert(std::make_pair(t_layer, newStack)); + } } else { - std::vector newStack; - newStack.push_back(&t_object); - m_drawStackBottom.insert(std::make_pair(t_layer, newStack)); + if(m_drawStackBottom3d.count(t_layer) > 0) { + m_drawStackBottom3d[t_layer].insert(m_drawStackBottom3d [t_layer].end(), &t_object); + } else { + std::vector newStack; + newStack.push_back(&t_object); + m_drawStackBottom3d.insert(std::make_pair(t_layer, newStack)); + } } } void Screen::render(bool t_clear) { - if(m_drawStackTop.size() > 0 || m_drawStackBottom.size() > 0) { - C3D_FrameBegin(C3D_FRAME_SYNCDRAW); - - if (t_clear) { - m_targetTopLeft->clear(); - m_targetTopRight->clear(); - m_targetBottom->clear(); - clear(); + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); + + if (t_clear) { + m_targetTopLeft->clear(); + m_targetTopRight->clear(); + m_targetBottom->clear(); + clear(); + } + + // draw 3d + if(m_drawStackTop3d.size() > 0 || m_drawStackBottom3d.size() > 0) { + prepare(); + + if(m_drawStackBottom3d.size() > 0) { + C3D_FrameDrawOn(m_targetBottom->getRenderTarget()); + + for(const auto &entry : m_drawStackBottom3d) { // for every layer + for(const auto &drawable : entry.second) { // draw every object + drawable->draw(m3d::RenderContext( + m_projectionUniform, // projectionUniform + m_modelViewUniform, // modelViewUniform + m_lightVecUniform, // lightVecUniform + m_lightHalfVecUniform, // lightHalfVecUniform + m_lightColorUniform, // lightColorUniform + m_materialUniform, // materialUniform + m_3dEnabled, // 3dEnabled + m3d::RenderContext::Mode::Spatial, // mode + m3d::RenderContext::Stereo3dSide::Left, // side + m3d::RenderContext::ScreenTarget::Bottom, // target + m_projection, // projection + m_modelView // model + )); + } + } + + m_drawStackBottom3d.clear(); + } + + if (m_drawStackTop3d.size() > 0) { + C3D_FrameDrawOn(m_targetTopLeft->getRenderTarget()); + + for (const auto &entry : m_drawStackTop3d) { // for every layer + for (const auto &drawable : entry.second) { // draw every object + drawable->draw(m3d::RenderContext( + m_projectionUniform, // projectionUniform + m_modelViewUniform, // modelViewUniform + m_lightVecUniform, // lightVecUniform + m_lightHalfVecUniform, // lightHalfVecUniform + m_lightColorUniform, // lightColorUniform + m_materialUniform, // materialUniform + m_3dEnabled, // 3dEnabled + m3d::RenderContext::Mode::Spatial, // mode + m3d::RenderContext::Stereo3dSide::Left, // side + m3d::RenderContext::ScreenTarget::Top, // target + m_projection, // projection + m_modelView // model + )); + } + } + + if (m_3dEnabled) { + C3D_FrameDrawOn(m_targetTopRight->getRenderTarget()); + + for (const auto &entry : m_drawStackTop3d) { // for every layer + for (const auto &drawable : entry.second) { // draw every object + drawable->draw(m3d::RenderContext( + m_projectionUniform, // projectionUniform + m_modelViewUniform, // modelViewUniform + m_lightVecUniform, // lightVecUniform + m_lightHalfVecUniform, // lightHalfVecUniform + m_lightColorUniform, // lightColorUniform + m_materialUniform, // materialUniform + m_3dEnabled, // 3dEnabled + m3d::RenderContext::Mode::Spatial, // mode + m3d::RenderContext::Stereo3dSide::Right, // side + m3d::RenderContext::ScreenTarget::Top, // target + m_projection, // projection + m_modelView // modelview + )); + } + } + } + + m_drawStackTop3d.clear(); } + } + + // draw 2d + if (m_drawStackTop2d.size() > 0 || m_drawStackBottom2d.size() > 0) { + C2D_Prepare(); - if(m_drawStackBottom.size() > 0) { + if(m_drawStackBottom2d.size() > 0) { C2D_SceneBegin(m_targetBottom->getRenderTarget()); - for(const auto &entry : m_drawStackBottom) { // for every layer + for(const auto &entry : m_drawStackBottom2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object - drawable->draw(m_3dEnabled, m3d::Screen::Stereo3dSide::Left); + drawable->draw(m3d::RenderContext( + m_projectionUniform, // projectionUniform + m_modelViewUniform, // modelViewUniform + m_lightVecUniform, // lightVecUniform + m_lightHalfVecUniform, // lightHalfVecUniform + m_lightColorUniform, // lightColorUniform + m_materialUniform, // materialUniform + m_3dEnabled, // 3dEnabled + m3d::RenderContext::Mode::Flat, // mode + m3d::RenderContext::Stereo3dSide::Left, // side + m3d::RenderContext::ScreenTarget::Bottom, // target + m_projection, // projection + m_modelView // modelview + )); } } + + m_drawStackBottom2d.clear(); } - if(m_drawStackTop.size() > 0) { + if(m_drawStackTop2d.size() > 0) { C2D_SceneBegin(m_targetTopLeft->getRenderTarget()); - for(const auto &entry : m_drawStackTop) { // for every layer + for(const auto &entry : m_drawStackTop2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object - drawable->draw(m_3dEnabled, m3d::Screen::Stereo3dSide::Left); + drawable->draw(m3d::RenderContext( + m_projectionUniform, // projectionUniform + m_modelViewUniform, // modelViewUniform + m_lightVecUniform, // lightVecUniform + m_lightHalfVecUniform, // lightHalfVecUniform + m_lightColorUniform, // lightColorUniform + m_materialUniform, // materialUniform + m_3dEnabled, // 3dEnabled + m3d::RenderContext::Mode::Flat, // mode + m3d::RenderContext::Stereo3dSide::Left, // side + m3d::RenderContext::ScreenTarget::Top, // target + m_projection, // projection + m_modelView // model + )); } } if(m_3dEnabled) { C2D_SceneBegin(m_targetTopRight->getRenderTarget()); - for(const auto &entry : m_drawStackTop) { // for every layer + for(const auto &entry : m_drawStackTop2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object - drawable->draw(m_3dEnabled, m3d::Screen::Stereo3dSide::Right); + drawable->draw(m3d::RenderContext( + m_projectionUniform, // projectionUniform + m_modelViewUniform, // modelViewUniform + m_lightVecUniform, // lightVecUniform + m_lightHalfVecUniform, // lightHalfVecUniform + m_lightColorUniform, // lightColorUniform + m_materialUniform, // materialUniform + m_3dEnabled, // 3dEnabled + m3d::RenderContext::Mode::Flat, // mode + m3d::RenderContext::Stereo3dSide::Right, // side + m3d::RenderContext::ScreenTarget::Top, // target + m_projection, // projection + m_modelView // model + )); } } } - } - C3D_FrameEnd(0); - m_drawStackTop.clear(); - m_drawStackBottom.clear(); + m_drawStackTop2d.clear(); + } } + + C3D_FrameEnd(0); } - int Screen::getScreenWidth(m3d::Screen::ScreenTarget t_target) { - return t_target == m3d::Screen::ScreenTarget::Top ? 400 : 320; + int Screen::getScreenWidth(m3d::RenderContext::ScreenTarget t_target) { + return t_target == m3d::RenderContext::ScreenTarget::Top ? 400 : 320; } int Screen::getScreenHeight() { return 240; } - // private methods void Screen::clear() { C2D_TargetClear(m_targetTopLeft->getRenderTarget(), m_clearColorTop.getRgba8()); C2D_TargetClear(m_targetTopRight->getRenderTarget(), m_clearColorTop.getRgba8()); C2D_TargetClear(m_targetBottom->getRenderTarget(), m_clearColorBottom.getRgba8()); } + + // private methods + void Screen::prepare() { + C3D_BindProgram(&m_shader); + + // initialize and configure attributes + m_attributeInfo = C3D_GetAttrInfo(); + AttrInfo_Init(m_attributeInfo); + AttrInfo_AddLoader(m_attributeInfo, 0, GPU_FLOAT, 3); // v0=position + AttrInfo_AddLoader(m_attributeInfo, 1, GPU_FLOAT, 2); // v1=texcoord + AttrInfo_AddLoader(m_attributeInfo, 2, GPU_FLOAT, 3); // v2=normal + + // Configure the first fragment shading substage to blend the fragment primary color + // with the fragment secondary color. + // See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight + // C3D_TexEnv* environment = C3D_GetTexEnv(0); + // C3D_TexEnvSrc(environment, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, (GPU_TEVSRC) 0); + // C3D_TexEnvOp(environment, C3D_Both, 0, 0, 0); + // C3D_TexEnvFunc(environment, C3D_Both, GPU_ADD); + C3D_TexEnv* env = C3D_GetTexEnv(0); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR); + C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); + } } /* m3d */ From bf3a01c83fffee4ee0339ba3e6597f9a35778a1c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:18:28 +0200 Subject: [PATCH 010/114] Adapt to RenderContext --- m3dialib/includes/m3d/graphics/renderTarget.hpp | 7 ++++--- m3dialib/source/graphics/renderTarget.cpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/renderTarget.hpp b/m3dialib/includes/m3d/graphics/renderTarget.hpp index 3e2599d..d416efe 100644 --- a/m3dialib/includes/m3d/graphics/renderTarget.hpp +++ b/m3dialib/includes/m3d/graphics/renderTarget.hpp @@ -7,6 +7,7 @@ #pragma once #include +#include "renderContext.hpp" namespace m3d { /** @@ -19,10 +20,10 @@ namespace m3d { * @brief Creates a render target * @param t_width The width of the target * @param t_height The height of the target - * @param t_screen The screen (GFX_TOP or GFX_BOTTOM) - * @param t_side The side (GFX_LEFT or GFX_RIGHT) + * @param t_screen The screen + * @param t_side The side */ - RenderTarget(int t_width, int t_height, gfxScreen_t t_screen, gfx3dSide_t t_side); + RenderTarget(int t_width, int t_height, m3d::RenderContext::ScreenTarget t_screen, m3d::RenderContext::Stereo3dSide t_side = m3d::RenderContext::Stereo3dSide::Left); /** * @brief Returns the render target diff --git a/m3dialib/source/graphics/renderTarget.cpp b/m3dialib/source/graphics/renderTarget.cpp index dc6ef8d..b53140d 100644 --- a/m3dialib/source/graphics/renderTarget.cpp +++ b/m3dialib/source/graphics/renderTarget.cpp @@ -3,11 +3,11 @@ #include "m3d/graphics/color.hpp" namespace m3d { - RenderTarget::RenderTarget(int t_width, int t_height, gfxScreen_t t_screen, gfx3dSide_t t_side = GFX_LEFT) : + RenderTarget::RenderTarget(int t_width, int t_height, m3d::RenderContext::ScreenTarget t_screen, m3d::RenderContext::Stereo3dSide t_side) : m_width(t_width), m_height(t_height), m_clearColor(RGBA8(0, 0, 0, 255)) { - m_target = C2D_CreateScreenTarget(t_screen, t_side); + m_target = C2D_CreateScreenTarget((t_screen == m3d::RenderContext::ScreenTarget::Top ? GFX_TOP : GFX_BOTTOM), (t_side == m3d::RenderContext::Stereo3dSide::Left ? GFX_LEFT : GFX_RIGHT)); } C3D_RenderTarget* RenderTarget::getRenderTarget() { From 91deaee9539fa15a9dfe45313c65ef52f63e4378 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 16:18:39 +0200 Subject: [PATCH 011/114] Fix RenderTarget-creation --- m3dialib/source/graphics/screen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index b3b8b0b..c2df47e 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -14,9 +14,9 @@ namespace m3d { gfxSet3D(t_enable3d); C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); m_3dEnabled = t_enable3d; - m_targetTopLeft = new m3d::RenderTarget(400, 240, GFX_TOP, GFX_LEFT); - m_targetTopRight = new m3d::RenderTarget(400, 240, GFX_TOP, GFX_RIGHT); - m_targetBottom = new m3d::RenderTarget(320, 240, GFX_BOTTOM, GFX_LEFT); + m_targetTopLeft = new m3d::RenderTarget(400, 240, m3d::RenderContext::ScreenTarget::Top, m3d::RenderContext::Stereo3dSide::Left); + m_targetTopRight = new m3d::RenderTarget(400, 240, m3d::RenderContext::ScreenTarget::Top, m3d::RenderContext::Stereo3dSide::Right); + m_targetBottom = new m3d::RenderTarget(320, 240, m3d::RenderContext::ScreenTarget::Bottom, m3d::RenderContext::Stereo3dSide::Left); u32 flags = GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO); From 80fac1402174fc21c41784da3e2f987fd7eafd3c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 19:58:14 +0200 Subject: [PATCH 012/114] Add stereo tilting --- m3dialib/source/graphics/screen.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index c2df47e..15fbd60 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -12,7 +12,6 @@ namespace m3d { C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); C2D_Init(C2D_DEFAULT_MAX_OBJECTS); gfxSet3D(t_enable3d); - C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); m_3dEnabled = t_enable3d; m_targetTopLeft = new m3d::RenderTarget(400, 240, m3d::RenderContext::ScreenTarget::Top, m3d::RenderContext::Stereo3dSide::Left); m_targetTopRight = new m3d::RenderTarget(400, 240, m3d::RenderContext::ScreenTarget::Top, m3d::RenderContext::Stereo3dSide::Right); @@ -120,6 +119,7 @@ namespace m3d { // draw 3d if(m_drawStackTop3d.size() > 0 || m_drawStackBottom3d.size() > 0) { prepare(); + Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioBot, 0.01f, 1000.0f, 0, 2.0f, false); if(m_drawStackBottom3d.size() > 0) { C3D_FrameDrawOn(m_targetBottom->getRenderTarget()); @@ -148,6 +148,12 @@ namespace m3d { if (m_drawStackTop3d.size() > 0) { C3D_FrameDrawOn(m_targetTopLeft->getRenderTarget()); + // tilt stereo perspective + if (m_3dEnabled) { + Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, osGet3DSliderState() / 3.0f, 2.0f, false); + } else { + Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, 0, 2.0f, false); + } for (const auto &entry : m_drawStackTop3d) { // for every layer for (const auto &drawable : entry.second) { // draw every object @@ -170,6 +176,12 @@ namespace m3d { if (m_3dEnabled) { C3D_FrameDrawOn(m_targetTopRight->getRenderTarget()); + // tilt stereo perspective + if (m_3dEnabled) { + Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, -(osGet3DSliderState() / 3.0f), 2.0f, false); + } else { + Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, 0, 2.0f, false); + } for (const auto &entry : m_drawStackTop3d) { // for every layer for (const auto &drawable : entry.second) { // draw every object @@ -198,6 +210,7 @@ namespace m3d { // draw 2d if (m_drawStackTop2d.size() > 0 || m_drawStackBottom2d.size() > 0) { C2D_Prepare(); + C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); if(m_drawStackBottom2d.size() > 0) { C2D_SceneBegin(m_targetBottom->getRenderTarget()); @@ -304,13 +317,10 @@ namespace m3d { // Configure the first fragment shading substage to blend the fragment primary color // with the fragment secondary color. // See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight - // C3D_TexEnv* environment = C3D_GetTexEnv(0); - // C3D_TexEnvSrc(environment, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, (GPU_TEVSRC) 0); - // C3D_TexEnvOp(environment, C3D_Both, 0, 0, 0); - // C3D_TexEnvFunc(environment, C3D_Both, GPU_ADD); C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnvInit(env); C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR); - C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); + C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); } } /* m3d */ From 3259707b5d87cb510ca657384228d1859443f461 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 20:01:26 +0200 Subject: [PATCH 013/114] Add culling --- m3dialib/source/graphics/screen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 15fbd60..214ae84 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -321,6 +321,7 @@ namespace m3d { C3D_TexEnvInit(env); C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR); C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + C3D_CullFace(GPU_CULL_BACK_CCW); C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); } } /* m3d */ From 6134f6b7a8223d0f6d37e6ab2324f4a7332ca5a6 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 20:01:40 +0200 Subject: [PATCH 014/114] Disable texture filter for now --- m3dialib/source/graphics/texture.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/m3dialib/source/graphics/texture.cpp b/m3dialib/source/graphics/texture.cpp index a797db1..5251a0b 100644 --- a/m3dialib/source/graphics/texture.cpp +++ b/m3dialib/source/graphics/texture.cpp @@ -173,7 +173,8 @@ namespace m3d { } } - C3D_TexSetFilter(m_texture, GPU_LINEAR, GPU_LINEAR); + // C3D_TexSetFilter(m_texture, GPU_LINEAR, GPU_LINEAR); + C3D_TexSetWrap(m_image.tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER); m_image.tex->border = 0xFFFFFFFF; return true; From cede88abc22326e3acf40ed2942c87bd9b67e944 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 22:41:22 +0200 Subject: [PATCH 015/114] Fix shader for textures --- m3dialib/source/graphics/render3d.v.pica | 72 ++++++++++-------------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/m3dialib/source/graphics/render3d.v.pica b/m3dialib/source/graphics/render3d.v.pica index 03272ad..e994949 100644 --- a/m3dialib/source/graphics/render3d.v.pica +++ b/m3dialib/source/graphics/render3d.v.pica @@ -2,21 +2,19 @@ ; Uniforms .fvec projection[4], modelView[4] -.fvec lightVec, lightHalfVec, lightClr, material[4] -.alias mat_amb material[0] -.alias mat_dif material[1] -.alias mat_spe material[2] -.alias mat_emi material[3] ; Constants -.constf myconst(0.0, 1.0, -1.0, -0.5) +.constf myconst(0.0, 1.0, -1.0, 0.5) .alias zeros myconst.xxxx ; Vector full of zeros .alias ones myconst.yyyy ; Vector full of ones +.alias half myconst.wwww ; Outputs .out outpos position .out outtc0 texcoord0 .out outclr color +.out outview view +.out outnq normalquat ; Inputs (defined as aliases for convenience) .alias inpos v0 @@ -34,6 +32,9 @@ dp4 r1.z, modelView[2], r0 dp4 r1.w, modelView[3], r0 + ; outview = -r1 + mov outview, -r1 + ; outpos = projection * r1 dp4 outpos.x, projection[0], r1 dp4 outpos.y, projection[1], r1 @@ -44,43 +45,28 @@ mov outtc0, intex ; Transform the normal vector with the modelView matrix - ; r1 = normalize(modelView * innrm) - mov r0.xyz, innrm - mov r0.w, zeros - dp4 r1.x, modelView[0], r0 - dp4 r1.y, modelView[1], r0 - dp4 r1.z, modelView[2], r0 - mov r1.w, zeros - dp3 r2, r1, r1 ; r2 = x^2+y^2+z^2 for each component - rsq r2, r2 ; r2 = 1/sqrt(r2) '' - mul r1, r2, r1 ; r1 = r1*r2 - - ; Calculate the diffuse level (r0.x) and the shininess level (r0.y) - ; r0.x = max(0, -(lightVec * r1)) - ; r0.y = max(0, (-lightHalfVec[i]) * r1) ^ 2 - dp3 r0.x, lightVec, r1 - add r0.x, zeros, -r0 - dp3 r0.y, -lightHalfVec, r1 - max r0, zeros, r0 - mul r0.y, r0, r0 - - ; Accumulate the vertex color in r1, initializing it to the emission color - mov r1, mat_emi - - ; r1 += specularColor * lightClr * shininessLevel - mul r2, lightClr, r0.yyyy - mad r1, r2, mat_spe, r1 - - ; r1 += diffuseColor * lightClr * diffuseLevel - mul r2, lightClr, r0.xxxx - mad r1, r2, mat_dif, r1 - - ; r1 += ambientColor * lightClr - mov r2, lightClr - mad r1, r2, mat_amb, r1 - - ; outclr = clamp r1 to [0,1] - min outclr, ones, r1 + ; TODO: use a separate normal matrix that is the transpose of the inverse of modelView + dp3 r14.x, modelView[0], innrm + dp3 r14.y, modelView[1], innrm + dp3 r14.z, modelView[2], innrm + dp3 r6.x, r14, r14 + rsq r6.x, r6.x + mul r14.xyz, r14.xyz, r6.x + + mov r0, myconst.yxxx + add r4, ones, r14.z + mul r4, half, r4 + cmp zeros, ge, ge, r4.x + rsq r4, r4.x + mul r5, half, r14 + jmpc cmp.x, degenerate + + rcp r0.z, r4.x + mul r0.xy, r5, r4 + +degenerate: + mov outnq, r0 + mov outclr, ones ; We're finished end From a7cf4d381b44841436619087a5a144badce32378 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 22:41:42 +0200 Subject: [PATCH 016/114] Remove useless arguments --- m3dialib/includes/m3d/graphics/renderTarget.hpp | 7 ++----- m3dialib/source/graphics/renderTarget.cpp | 5 ++--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/renderTarget.hpp b/m3dialib/includes/m3d/graphics/renderTarget.hpp index d416efe..970a39d 100644 --- a/m3dialib/includes/m3d/graphics/renderTarget.hpp +++ b/m3dialib/includes/m3d/graphics/renderTarget.hpp @@ -6,8 +6,7 @@ #define RENDERTARGET_H #pragma once -#include -#include "renderContext.hpp" +#include namespace m3d { /** @@ -20,10 +19,8 @@ namespace m3d { * @brief Creates a render target * @param t_width The width of the target * @param t_height The height of the target - * @param t_screen The screen - * @param t_side The side */ - RenderTarget(int t_width, int t_height, m3d::RenderContext::ScreenTarget t_screen, m3d::RenderContext::Stereo3dSide t_side = m3d::RenderContext::Stereo3dSide::Left); + RenderTarget(int t_width, int t_height); /** * @brief Returns the render target diff --git a/m3dialib/source/graphics/renderTarget.cpp b/m3dialib/source/graphics/renderTarget.cpp index b53140d..57d8346 100644 --- a/m3dialib/source/graphics/renderTarget.cpp +++ b/m3dialib/source/graphics/renderTarget.cpp @@ -1,13 +1,12 @@ -#include #include "m3d/graphics/renderTarget.hpp" #include "m3d/graphics/color.hpp" namespace m3d { - RenderTarget::RenderTarget(int t_width, int t_height, m3d::RenderContext::ScreenTarget t_screen, m3d::RenderContext::Stereo3dSide t_side) : + RenderTarget::RenderTarget(int t_width, int t_height) : m_width(t_width), m_height(t_height), m_clearColor(RGBA8(0, 0, 0, 255)) { - m_target = C2D_CreateScreenTarget((t_screen == m3d::RenderContext::ScreenTarget::Top ? GFX_TOP : GFX_BOTTOM), (t_side == m3d::RenderContext::Stereo3dSide::Left ? GFX_LEFT : GFX_RIGHT)); + m_target = C3D_RenderTargetCreate(t_height, t_width, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); } C3D_RenderTarget* RenderTarget::getRenderTarget() { From 9961e961dec2226a00ebdafd8c589414e733d541 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 22:42:01 +0200 Subject: [PATCH 017/114] Add enableTextures-method --- .../includes/m3d/graphics/renderContext.hpp | 2 ++ m3dialib/source/graphics/renderContext.cpp | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/m3dialib/includes/m3d/graphics/renderContext.hpp b/m3dialib/includes/m3d/graphics/renderContext.hpp index 79d1028..0546731 100644 --- a/m3dialib/includes/m3d/graphics/renderContext.hpp +++ b/m3dialib/includes/m3d/graphics/renderContext.hpp @@ -70,6 +70,8 @@ namespace m3d { C3D_Mtx& getModelViewMatrix(); + void enableTextures(bool t_enable); + private: /* data */ int m_projectionUniformLocation, m_modelViewUniformLocation, m_lightVecUniformLocation, m_lightHalfVecUniformLocation, m_lightColorUniformLocation, m_materialUniformLocation; diff --git a/m3dialib/source/graphics/renderContext.cpp b/m3dialib/source/graphics/renderContext.cpp index 9483308..55f428a 100644 --- a/m3dialib/source/graphics/renderContext.cpp +++ b/m3dialib/source/graphics/renderContext.cpp @@ -75,4 +75,23 @@ namespace m3d { C3D_Mtx& RenderContext::getModelViewMatrix() { return m_modelView; } + + void RenderContext::enableTextures(bool t_enable) { + C3D_TexEnv* env; + + switch (t_enable) { + case true: + env = C3D_GetTexEnv(0); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + break; + default: + env = C3D_GetTexEnv(0); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + } + } } /* m3d */ From 6ad1346df6c7cac819ec51d0fcbadd49cc76c8ca Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 22:59:47 +0200 Subject: [PATCH 018/114] Add light members and remove unnecessary uniforms --- .../includes/m3d/graphics/renderContext.hpp | 28 +++++------ m3dialib/source/graphics/renderContext.cpp | 46 ++++++++----------- 2 files changed, 34 insertions(+), 40 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/renderContext.hpp b/m3dialib/includes/m3d/graphics/renderContext.hpp index 0546731..6b1f404 100644 --- a/m3dialib/includes/m3d/graphics/renderContext.hpp +++ b/m3dialib/includes/m3d/graphics/renderContext.hpp @@ -34,30 +34,21 @@ namespace m3d { RenderContext( int t_projectionUniform, int t_modelViewUniform, - int t_lightVecUniform, - int t_lightHalfVecUniform, - int t_lightColorUniform, - int t_materialUniform, bool t_3dEnabled, m3d::RenderContext::Mode t_mode, m3d::RenderContext::Stereo3dSide t_side, m3d::RenderContext::ScreenTarget t_target, C3D_Mtx& t_projection, - C3D_Mtx& t_modelView + C3D_Mtx& t_modelView, + C3D_LightEnv& t_lightEnv, + C3D_Light& t_light, + C3D_LightLut& t_lightLut ); int getProjectionUniform(); int getModelViewUniform(); - int getLightVecUniform(); - - int getLightHalfVecUniform(); - - int getLightColorUniform(); - - int getMaterialUniform(); - bool is3dEnabled(); m3d::RenderContext::Mode getMode(); @@ -70,16 +61,25 @@ namespace m3d { C3D_Mtx& getModelViewMatrix(); + C3D_LightEnv& getLightEnvironment(); + + C3D_Light& getLight(); + + C3D_LightLut& getLightLut(); + void enableTextures(bool t_enable); private: /* data */ - int m_projectionUniformLocation, m_modelViewUniformLocation, m_lightVecUniformLocation, m_lightHalfVecUniformLocation, m_lightColorUniformLocation, m_materialUniformLocation; + int m_projectionUniformLocation, m_modelViewUniformLocation, m_materialUniformLocation; bool m_3dEnabled; m3d::RenderContext::Mode m_mode; m3d::RenderContext::Stereo3dSide m_side; m3d::RenderContext::ScreenTarget m_target; C3D_Mtx &m_projection, &m_modelView; + C3D_LightEnv& m_lightEnv; + C3D_Light& m_light; + C3D_LightLut& m_lightLut; }; } /* m3d */ diff --git a/m3dialib/source/graphics/renderContext.cpp b/m3dialib/source/graphics/renderContext.cpp index 55f428a..e0a60d8 100644 --- a/m3dialib/source/graphics/renderContext.cpp +++ b/m3dialib/source/graphics/renderContext.cpp @@ -4,29 +4,27 @@ namespace m3d { RenderContext::RenderContext( int t_projectionUniform, int t_modelViewUniform, - int t_lightVecUniform, - int t_lightHalfVecUniform, - int t_lightColorUniform, - int t_materialUniform, bool t_3dEnabled, m3d::RenderContext::Mode t_mode, m3d::RenderContext::Stereo3dSide t_side, m3d::RenderContext::ScreenTarget t_target, C3D_Mtx& t_projection, - C3D_Mtx& t_modelView + C3D_Mtx& t_modelView, + C3D_LightEnv& t_lightEnv, + C3D_Light& t_light, + C3D_LightLut& t_lightLut ) : m_projectionUniformLocation(t_projectionUniform), m_modelViewUniformLocation(t_modelViewUniform), - m_lightVecUniformLocation(t_lightVecUniform), - m_lightHalfVecUniformLocation(t_lightHalfVecUniform), - m_lightColorUniformLocation(t_lightColorUniform), - m_materialUniformLocation(t_materialUniform), m_3dEnabled(t_3dEnabled), m_mode(t_mode), m_side(t_side), m_target(t_target), m_projection(t_projection), - m_modelView(t_modelView) { /* do nothing */ } + m_modelView(t_modelView), + m_lightEnv(t_lightEnv), + m_light(t_light), + m_lightLut(t_lightLut) { /* do nothing */ } int RenderContext::getProjectionUniform() { return m_projectionUniformLocation; @@ -36,22 +34,6 @@ namespace m3d { return m_modelViewUniformLocation; } - int RenderContext::getLightVecUniform() { - return m_lightVecUniformLocation; - } - - int RenderContext::getLightHalfVecUniform() { - return m_lightHalfVecUniformLocation; - } - - int RenderContext::getLightColorUniform() { - return m_lightColorUniformLocation; - } - - int RenderContext::getMaterialUniform() { - return m_materialUniformLocation; - } - bool RenderContext::is3dEnabled() { return m_3dEnabled; } @@ -76,6 +58,18 @@ namespace m3d { return m_modelView; } + C3D_LightEnv& RenderContext::getLightEnvironment() { + return m_lightEnv; + } + + C3D_Light& RenderContext::getLight() { + return m_light; + } + + C3D_LightLut& RenderContext::getLightLut() { + return m_lightLut; + } + void RenderContext::enableTextures(bool t_enable) { C3D_TexEnv* env; From b2b9b049377171ff8e574471e09750d6eff87d39 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 20 Sep 2018 23:00:42 +0200 Subject: [PATCH 019/114] Add light members and adapt to new RenderContext --- m3dialib/includes/m3d/graphics/screen.hpp | 7 +- m3dialib/source/graphics/screen.cpp | 109 ++++++++++++++-------- 2 files changed, 75 insertions(+), 41 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index dadfd4c..b7a50e5 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -13,7 +13,6 @@ #include "renderTarget.hpp" #include "drawable.hpp" #include "color.hpp" - /** * @brief The general m3d-namespace */ @@ -101,6 +100,7 @@ namespace m3d { void clear(); private: void prepare(); + void prepareLights(m3d::RenderContext::ScreenTarget t_target); /* data */ int m_projectionUniform, m_modelViewUniform, m_lightVecUniform, m_lightHalfVecUniform, m_lightColorUniform, m_materialUniform; @@ -111,7 +111,10 @@ namespace m3d { DVLB_s *m_dvlb; shaderProgram_s m_shader; C3D_AttrInfo* m_attributeInfo; - C3D_Mtx m_projection, m_projectionBottom, m_modelView, m_modelViewBottom; + C3D_Mtx m_projection, m_modelView; + C3D_LightEnv m_lightEnvTop, m_lightEnvBottom; + C3D_Light m_lightTop, m_lightBottom; + C3D_LightLut m_lutPhongTop, m_lutPhongBottom; }; } /* m3d */ diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 214ae84..50e62e2 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -13,9 +13,9 @@ namespace m3d { C2D_Init(C2D_DEFAULT_MAX_OBJECTS); gfxSet3D(t_enable3d); m_3dEnabled = t_enable3d; - m_targetTopLeft = new m3d::RenderTarget(400, 240, m3d::RenderContext::ScreenTarget::Top, m3d::RenderContext::Stereo3dSide::Left); - m_targetTopRight = new m3d::RenderTarget(400, 240, m3d::RenderContext::ScreenTarget::Top, m3d::RenderContext::Stereo3dSide::Right); - m_targetBottom = new m3d::RenderTarget(320, 240, m3d::RenderContext::ScreenTarget::Bottom, m3d::RenderContext::Stereo3dSide::Left); + m_targetTopLeft = new m3d::RenderTarget(400, 240); + m_targetTopRight = new m3d::RenderTarget(400, 240); + m_targetBottom = new m3d::RenderTarget(320, 240); u32 flags = GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO); @@ -30,10 +30,6 @@ namespace m3d { // get location of uniforms used in the vertex shader. m_projectionUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "projection"); m_modelViewUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "modelView"); - m_lightVecUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "lightVec"); - m_lightHalfVecUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "lightHalfVec"); - m_lightColorUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "lightClr"); - m_materialUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "material"); clear(); } @@ -44,6 +40,10 @@ namespace m3d { C2D_Fini(); C3D_Fini(); gfxExit(); + delete m_targetTopLeft; + delete m_targetTopRight; + delete m_targetBottom; + delete m_attributeInfo; } void Screen::set3d(bool t_enabled) { @@ -123,22 +123,22 @@ namespace m3d { if(m_drawStackBottom3d.size() > 0) { C3D_FrameDrawOn(m_targetBottom->getRenderTarget()); + prepareLights(m3d::RenderContext::ScreenTarget::Bottom); for(const auto &entry : m_drawStackBottom3d) { // for every layer for(const auto &drawable : entry.second) { // draw every object drawable->draw(m3d::RenderContext( m_projectionUniform, // projectionUniform m_modelViewUniform, // modelViewUniform - m_lightVecUniform, // lightVecUniform - m_lightHalfVecUniform, // lightHalfVecUniform - m_lightColorUniform, // lightColorUniform - m_materialUniform, // materialUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Bottom, // target m_projection, // projection - m_modelView // model + m_modelView, // model + m_lightEnvBottom, // lightEnv + m_lightBottom, // light + m_lutPhongBottom // lutPhong )); } } @@ -148,6 +148,8 @@ namespace m3d { if (m_drawStackTop3d.size() > 0) { C3D_FrameDrawOn(m_targetTopLeft->getRenderTarget()); + prepareLights(m3d::RenderContext::ScreenTarget::Top); + // tilt stereo perspective if (m_3dEnabled) { Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, osGet3DSliderState() / 3.0f, 2.0f, false); @@ -160,22 +162,22 @@ namespace m3d { drawable->draw(m3d::RenderContext( m_projectionUniform, // projectionUniform m_modelViewUniform, // modelViewUniform - m_lightVecUniform, // lightVecUniform - m_lightHalfVecUniform, // lightHalfVecUniform - m_lightColorUniform, // lightColorUniform - m_materialUniform, // materialUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Top, // target m_projection, // projection - m_modelView // model + m_modelView, // model + m_lightEnvTop, // lightEnv + m_lightTop, // light + m_lutPhongTop // lutPhong )); } } if (m_3dEnabled) { C3D_FrameDrawOn(m_targetTopRight->getRenderTarget()); + // tilt stereo perspective if (m_3dEnabled) { Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, -(osGet3DSliderState() / 3.0f), 2.0f, false); @@ -188,16 +190,15 @@ namespace m3d { drawable->draw(m3d::RenderContext( m_projectionUniform, // projectionUniform m_modelViewUniform, // modelViewUniform - m_lightVecUniform, // lightVecUniform - m_lightHalfVecUniform, // lightHalfVecUniform - m_lightColorUniform, // lightColorUniform - m_materialUniform, // materialUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode m3d::RenderContext::Stereo3dSide::Right, // side m3d::RenderContext::ScreenTarget::Top, // target m_projection, // projection - m_modelView // modelview + m_modelView, // model + m_lightEnvTop, // lightEnv + m_lightTop, // light + m_lutPhongTop // lutPhong )); } } @@ -220,16 +221,15 @@ namespace m3d { drawable->draw(m3d::RenderContext( m_projectionUniform, // projectionUniform m_modelViewUniform, // modelViewUniform - m_lightVecUniform, // lightVecUniform - m_lightHalfVecUniform, // lightHalfVecUniform - m_lightColorUniform, // lightColorUniform - m_materialUniform, // materialUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Bottom, // target m_projection, // projection - m_modelView // modelview + m_modelView, // model + m_lightEnvBottom, // lightEnv + m_lightBottom, // light + m_lutPhongBottom // lutPhong )); } } @@ -245,16 +245,15 @@ namespace m3d { drawable->draw(m3d::RenderContext( m_projectionUniform, // projectionUniform m_modelViewUniform, // modelViewUniform - m_lightVecUniform, // lightVecUniform - m_lightHalfVecUniform, // lightHalfVecUniform - m_lightColorUniform, // lightColorUniform - m_materialUniform, // materialUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Top, // target m_projection, // projection - m_modelView // model + m_modelView, // model + m_lightEnvTop, // lightEnv + m_lightTop, // light + m_lutPhongTop // lutPhong )); } } @@ -267,16 +266,15 @@ namespace m3d { drawable->draw(m3d::RenderContext( m_projectionUniform, // projectionUniform m_modelViewUniform, // modelViewUniform - m_lightVecUniform, // lightVecUniform - m_lightHalfVecUniform, // lightHalfVecUniform - m_lightColorUniform, // lightColorUniform - m_materialUniform, // materialUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode m3d::RenderContext::Stereo3dSide::Right, // side m3d::RenderContext::ScreenTarget::Top, // target m_projection, // projection - m_modelView // model + m_modelView, // model + m_lightEnvTop, // lightEnv + m_lightTop, // light + m_lutPhongTop // lutPhong )); } } @@ -319,9 +317,42 @@ namespace m3d { // See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnvInit(env); - C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR); - C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE); + C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); + C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); + C3D_CullFace(GPU_CULL_BACK_CCW); C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); } + + void Screen::prepareLights(m3d::RenderContext::ScreenTarget t_target) { + C3D_FVec lightVec; + + switch (t_target) { + case m3d::RenderContext::ScreenTarget::Bottom: + C3D_LightEnvInit(&m_lightEnvBottom); + C3D_LightEnvBind(&m_lightEnvBottom); + + LightLut_Phong(&m_lutPhongBottom, 30); + C3D_LightEnvLut(&m_lightEnvBottom, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &m_lutPhongBottom); + + lightVec = FVec4_New(0.0f, 0.0f, -0.5f, 1.0f); + + C3D_LightInit(&m_lightBottom, &m_lightEnvBottom); + C3D_LightColor(&m_lightBottom, 1.0, 1.0, 1.0); + C3D_LightPosition(&m_lightBottom, &lightVec); + break; + default: + C3D_LightEnvInit(&m_lightEnvTop); + C3D_LightEnvBind(&m_lightEnvTop); + + LightLut_Phong(&m_lutPhongTop, 30); + C3D_LightEnvLut(&m_lightEnvTop, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &m_lutPhongTop); + + lightVec = FVec4_New(0.0f, 0.0f, -0.5f, 1.0f); + + C3D_LightInit(&m_lightTop, &m_lightEnvTop); + C3D_LightColor(&m_lightTop, 1.0, 1.0, 1.0); + C3D_LightPosition(&m_lightTop, &lightVec); + } + } } /* m3d */ From d7715c36aa1994530f4904eb70751084e1fffd2a Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 09:27:06 +0200 Subject: [PATCH 020/114] Add Material-class --- m3dialib/includes/m3d/graphics/material.hpp | 155 ++++++++++++++++++++ m3dialib/source/graphics/material.cpp | 127 ++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 m3dialib/includes/m3d/graphics/material.hpp create mode 100644 m3dialib/source/graphics/material.cpp diff --git a/m3dialib/includes/m3d/graphics/material.hpp b/m3dialib/includes/m3d/graphics/material.hpp new file mode 100644 index 0000000..3f2d244 --- /dev/null +++ b/m3dialib/includes/m3d/graphics/material.hpp @@ -0,0 +1,155 @@ +/** + * @file material.hpp + * @brief Defines the Material-class + */ +#ifndef MATERIAL_H +#define MATERIAL_H + +#pragma once +#include +#include "color.hpp" + +namespace m3d { + /** + * @brief A material that can be applied to meshes + */ + class Material { + public: + /** + * @brief Default constructor + */ + Material(); + + /** + * @brief Initializes the material with a C3D_Material + * @param t_material The material to initialize from + */ + Material(C3D_Material t_material); + + /** + * @brief Destructs the material + */ + ~Material(); + + /** + * @brief Sets the material with C3D_Materfial + * @param t_material The material to copy + */ + void setMaterial(C3D_Material t_material); + + /** + * @brief Returns the C3D_Material of this material + * @return The C3D_Material + */ + C3D_Material* getMaterial() const; + + /** + * @brief Sets the ambient-color of the material + * @param t_color The ambient-color + */ + void setAmbient(m3d::Color t_color); + + /** + * @brief Sets the ambient-color of the material + * @param t_r The red component + * @param t_g The green component + * @param t_b The blue component + */ + void setAmbient(float t_r, float t_g, float t_b); + + /** + * @brief Returns the ambient-color of the material + * @return The ambient-color + */ + m3d::Color getAmbient(); + + /** + * @brief Sets the diffuse-color of the material + * @param t_color The diffuse-color + */ + void setDiffuse(m3d::Color t_color); + + /** + * @brief Sets the diffuse-color of the material + * @param t_r The red component + * @param t_g The green component + * @param t_b The blue component + */ + void setDiffuse(float t_r, float t_g, float t_b); + + /** + * @brief Returns the diffuse-color of the material + * @return The diffuse-color + */ + m3d::Color getDiffuse(); + + /** + * @brief Sets the specular0-color of the material + * @param t_color The specular0-color + */ + void setSpecular0(m3d::Color t_color); + + /** + * @brief Sets the specular0-color of the material + * @param t_r The red component + * @param t_g The green component + * @param t_b The blue component + */ + void setSpecular0(float t_r, float t_g, float t_b); + + /** + * @brief Returns the specular0-color of the material + * @return The specular0-color + */ + m3d::Color getSpecular0(); + + /** + * @brief Sets the specular1-color of the material + * @param t_color The specular1-color + */ + void setSpecular1(m3d::Color t_color); + + /** + * @brief Sets the specular1-color of the material + * @param t_r The red component + * @param t_g The green component + * @param t_b The blue component + */ + void setSpecular1(float t_r, float t_g, float t_b); + + /** + * @brief Returns the specular1-color of the material + * @return The specular1-color + */ + m3d::Color getSpecular1(); + /** + * @brief Sets the emission-color of the material + * @param t_color The emission-color + */ + void setEmission(m3d::Color t_color); + + /** + * @brief Sets the emission-color of the material + * @param t_r The red component + * @param t_g The green component + * @param t_b The blue component + */ + void setEmission(float t_r, float t_g, float t_b); + + /** + * @brief Returns the emission-color of the material + * @return The emission-color + */ + m3d::Color getEmission(); + + private: + void updateMaterial(); + + /* data */ + m3d::Color m_ambient, m_diffuse, m_specular0, m_specular1, m_emission; + C3D_Material* m_material; + }; +} /* m3d */ + + +#endif /* end of include guard: MATERIAL_H */ diff --git a/m3dialib/source/graphics/material.cpp b/m3dialib/source/graphics/material.cpp new file mode 100644 index 0000000..04ac818 --- /dev/null +++ b/m3dialib/source/graphics/material.cpp @@ -0,0 +1,127 @@ +#include "m3d/graphics/material.hpp" + +namespace m3d { + Material::Material() : + m_ambient(51, 51, 51), + m_diffuse(102, 102, 102), + m_specular0(127, 127, 127) { + m_material = new C3D_Material; + updateMaterial(); + } + + Material::Material(C3D_Material t_material) { + setMaterial(t_material); + updateMaterial(); + } + + Material::~Material() { + delete m_material; + } + + void Material::setMaterial(C3D_Material t_material) { + m_ambient.setColor(t_material.ambient[2], t_material.ambient[1], t_material.ambient[0]); + m_diffuse.setColor(t_material.diffuse[2], t_material.diffuse[1], t_material.diffuse[0]); + m_specular0.setColor(t_material.specular0[2], t_material.specular0[1], t_material.specular0[0]); + m_specular1.setColor(t_material.specular1[2], t_material.specular1[1], t_material.specular1[0]); + m_emission.setColor(t_material.emission[2], t_material.emission[1], t_material.emission[0]); + + updateMaterial(); + } + + C3D_Material* Material::getMaterial() const { + return m_material; + } + + void Material::setAmbient(m3d::Color t_color) { + m_ambient = t_color; + updateMaterial(); + } + + void Material::setAmbient(float t_r, float t_g, float t_b) { + m_ambient = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + updateMaterial(); + } + + m3d::Color Material::getAmbient() { + return m_ambient; + } + + void Material::setDiffuse(m3d::Color t_color) { + m_diffuse = t_color; + updateMaterial(); + } + + void Material::setDiffuse(float t_r, float t_g, float t_b) { + m_diffuse = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + updateMaterial(); + } + + m3d::Color Material::getDiffuse() { + return m_diffuse; + } + + void Material::setSpecular0(m3d::Color t_color) { + m_specular0 = t_color; + updateMaterial(); + } + + void Material::setSpecular0(float t_r, float t_g, float t_b) { + m_specular0 = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + updateMaterial(); + } + + m3d::Color Material::getSpecular0() { + return m_specular0; + } + + void Material::setSpecular1(m3d::Color t_color) { + m_specular1 = t_color; + updateMaterial(); + } + + void Material::setSpecular1(float t_r, float t_g, float t_b) { + m_specular1 = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + updateMaterial(); + } + + m3d::Color Material::getSpecular1() { + return m_specular1; + } + + void Material::setEmission(m3d::Color t_color) { + m_emission = t_color; + updateMaterial(); + } + + void Material::setEmission(float t_r, float t_g, float t_b) { + m_emission = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + updateMaterial(); + } + + m3d::Color Material::getEmission() { + return m_emission; + } + + // private methods + void Material::updateMaterial() { + m_material->ambient[0] = (float) m_ambient.getBlue() / 255; + m_material->ambient[1] = (float) m_ambient.getGreen() / 255; + m_material->ambient[2] = (float) m_ambient.getRed() / 255; + + m_material->diffuse[0] = (float) m_diffuse.getBlue() / 255; + m_material->diffuse[1] = (float) m_diffuse.getGreen() / 255; + m_material->diffuse[2] = (float) m_diffuse.getRed() / 255; + + m_material->specular0[0] = (float) m_specular0.getBlue() / 255; + m_material->specular0[1] = (float) m_specular0.getGreen() / 255; + m_material->specular0[2] = (float) m_specular0.getRed() / 255; + + m_material->specular1[0] = (float) m_specular1.getBlue() / 255; + m_material->specular1[1] = (float) m_specular1.getGreen() / 255; + m_material->specular1[2] = (float) m_specular1.getRed() / 255; + + m_material->emission[0] = (float) m_emission.getBlue() / 255; + m_material->emission[0] = (float) m_emission.getGreen() / 255; + m_material->emission[0] = (float) m_emission.getRed() / 255; + } +} /* m3d */ From c395c38482723cad37f5e8d8ed5b8d18bc2fea3c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 09:27:20 +0200 Subject: [PATCH 021/114] Add default material --- m3dialib/includes/m3d/private/graphics.hpp | 4 ++-- m3dialib/source/private/graphics.cpp | 19 +------------------ 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/m3dialib/includes/m3d/private/graphics.hpp b/m3dialib/includes/m3d/private/graphics.hpp index 44de546..17b4725 100644 --- a/m3dialib/includes/m3d/private/graphics.hpp +++ b/m3dialib/includes/m3d/private/graphics.hpp @@ -3,12 +3,12 @@ #pragma once #include +#include "m3d/graphics/material.hpp" namespace m3d { namespace priv { namespace graphics { - extern const C3D_Material material; - extern const C3D_Mtx materialMatrix; + extern const m3d::Material defaultMaterial; } /* graphics */ } /* priv */ } /* m3d */ diff --git a/m3dialib/source/private/graphics.cpp b/m3dialib/source/private/graphics.cpp index e3b9461..303a5eb 100644 --- a/m3dialib/source/private/graphics.cpp +++ b/m3dialib/source/private/graphics.cpp @@ -1,26 +1,9 @@ -#include #include "m3d/private/graphics.hpp" namespace m3d { namespace priv { namespace graphics { - const C3D_Material material = { - { 0.1f, 0.1f, 0.1f }, //ambient - { 0.4f, 0.4f, 0.4f }, //diffuse - { 0.5f, 0.5f, 0.5f }, //specular0 - { 0.0f, 0.0f, 0.0f }, //specular1 - { 0.0f, 0.0f, 0.0f }, //emission - }; - - const C3D_Mtx materialMatrix = - { - { - { { 0.0f, 0.2f, 0.2f, 0.2f } }, // Ambient - { { 0.0f, 0.4f, 0.4f, 0.4f } }, // Diffuse - { { 0.0f, 0.8f, 0.8f, 0.8f } }, // Specular - { { 1.0f, 0.0f, 0.0f, 0.0f } }, // Emission - } - }; + const m3d::Material defaultMaterial; } /* graphics */ } /* priv */ } /* m3d */ From 52f4d234e84e0068f70c64b294fac73040c4378c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 09:35:23 +0200 Subject: [PATCH 022/114] Remove useless members --- m3dialib/includes/m3d/graphics/screen.hpp | 25 +++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index b7a50e5..e2930ba 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -103,15 +103,32 @@ namespace m3d { void prepareLights(m3d::RenderContext::ScreenTarget t_target); /* data */ - int m_projectionUniform, m_modelViewUniform, m_lightVecUniform, m_lightHalfVecUniform, m_lightColorUniform, m_materialUniform; + int m_projectionUniform, m_modelViewUniform; bool m_3dEnabled; m3d::Color m_clearColorTop, m_clearColorBottom; - m3d::RenderTarget *m_targetTopLeft, *m_targetTopRight, *m_targetBottom; - std::map, std::less> m_drawStackTop2d, m_drawStackTop3d, m_drawStackBottom2d, m_drawStackBottom3d; - DVLB_s *m_dvlb; + + // rendertargets + m3d::RenderTarget *m_targetTopLeft, + *m_targetTopRight, + *m_targetBottom; + + // draw stacks + std::map, std::less> m_drawStackTop2d, + m_drawStackTop3d, + m_drawStackBottom2d, + m_drawStackBottom3d; + + // shader + DVLB_s* m_dvlb; shaderProgram_s m_shader; + + // attribute information C3D_AttrInfo* m_attributeInfo; + + // matrices C3D_Mtx m_projection, m_modelView; + + // light C3D_LightEnv m_lightEnvTop, m_lightEnvBottom; C3D_Light m_lightTop, m_lightBottom; C3D_LightLut m_lutPhongTop, m_lutPhongBottom; From 29b4f293ac9fccde89313e7631c1eaa1d00e1291 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 10:35:08 +0200 Subject: [PATCH 023/114] Add documentation --- .../includes/m3d/graphics/renderContext.hpp | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/m3dialib/includes/m3d/graphics/renderContext.hpp b/m3dialib/includes/m3d/graphics/renderContext.hpp index 6b1f404..2e838a0 100644 --- a/m3dialib/includes/m3d/graphics/renderContext.hpp +++ b/m3dialib/includes/m3d/graphics/renderContext.hpp @@ -1,3 +1,7 @@ +/** + * @file renderContext.hpp + * @brief Defines the RenderContext-class + */ #ifndef RENDERCONTEXT_H #define RENDERCONTEXT_H @@ -5,6 +9,9 @@ #include namespace m3d { + /** + * @brief The RenderContext-class which holds information about the current rendering process + */ class RenderContext { public: /** @@ -31,6 +38,20 @@ namespace m3d { Spatial ///< 3D }; + /** + * @brief Default constructor + * @param t_projectionUniform The location of the projection uniform + * @param t_modelViewUniform The location of the model view uniform + * @param t_3dEnabled Whether stereoscopic 3D is enabled + * @param t_mode The current rendering mode + * @param t_side The current side for stereoscopic 3D + * @param t_target The current screen target + * @param t_projection The projection matrix + * @param t_modelView The model view matrix + * @param t_lightEnv The light environment + * @param t_light The light + * @param t_lightLut The light LUT + */ RenderContext( int t_projectionUniform, int t_modelViewUniform, @@ -45,28 +66,76 @@ namespace m3d { C3D_LightLut& t_lightLut ); + /** + * @brief Returns the location of the projection uniform + * @return The location of the uniform + */ int getProjectionUniform(); + /** + * @brief Returns the location of the model view uniform + * @return The location of the uniform + */ int getModelViewUniform(); + /** + * @brief Returns whether or not stereoscopic 3D is enabled + * @return Whether or not stereoscopic 3D is enabled + */ bool is3dEnabled(); + /** + * @brief Returns the current rendering mode (flat (2D) or spatial (3D)) + * @return The current mode + */ m3d::RenderContext::Mode getMode(); + /** + * @brief Returns the current side for stereoscopic 3D + * @return The current side + */ m3d::RenderContext::Stereo3dSide getSide(); + /** + * @brief Returns the current screen target + * @return The current target + */ m3d::RenderContext::ScreenTarget getScreenTarget(); + /** + * @brief Returns the projection matrix + * @return The projection matrix + */ C3D_Mtx& getProjectionMatrix(); + /** + * @brief Returns the model view matrix + * @return The model view matrix + */ C3D_Mtx& getModelViewMatrix(); + /** + * @brief Returns the light environment + * @return The light environment + */ C3D_LightEnv& getLightEnvironment(); + /** + * @brief Returns the light + * @return The light + */ C3D_Light& getLight(); + /** + * @brief Returns the light LUT + * @return The light LUT + */ C3D_LightLut& getLightLut(); + /** + * @brief Enables or disables textures + * @param t_enable Whether or not to enable textures + */ void enableTextures(bool t_enable); private: From c2af102246b992c7c59053ad8a7b94e3dcaa1ef8 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 10:41:45 +0200 Subject: [PATCH 024/114] Add assignment operator and copy constructor --- m3dialib/includes/m3d/graphics/material.hpp | 16 +++++++++++++++- m3dialib/source/graphics/material.cpp | 20 ++++++++++++++------ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/material.hpp b/m3dialib/includes/m3d/graphics/material.hpp index 3f2d244..e5c3736 100644 --- a/m3dialib/includes/m3d/graphics/material.hpp +++ b/m3dialib/includes/m3d/graphics/material.hpp @@ -26,13 +26,19 @@ namespace m3d { */ Material(C3D_Material t_material); + /** + * @brief Copy constructor + * @param t_source Material to copy + */ + Material(const m3d::Material& t_source); + /** * @brief Destructs the material */ ~Material(); /** - * @brief Sets the material with C3D_Materfial + * @brief Sets the material with C3D_Material * @param t_material The material to copy */ void setMaterial(C3D_Material t_material); @@ -122,6 +128,7 @@ namespace m3d { * @return The specular1-color */ m3d::Color getSpecular1(); + /** * @brief Sets the emission-color of the material * @param t_color The emission-color @@ -142,6 +149,13 @@ namespace m3d { */ m3d::Color getEmission(); + /** + * @brief Overloads the assignment operator + * @param rhs The material to copy + * @return A reference to this material + */ + m3d::Material& operator=(const m3d::Material& rhs); + private: void updateMaterial(); diff --git a/m3dialib/source/graphics/material.cpp b/m3dialib/source/graphics/material.cpp index 04ac818..e9c0458 100644 --- a/m3dialib/source/graphics/material.cpp +++ b/m3dialib/source/graphics/material.cpp @@ -14,17 +14,20 @@ namespace m3d { updateMaterial(); } + Material::Material(const m3d::Material& t_source) { + operator=(t_source); + } + Material::~Material() { delete m_material; } void Material::setMaterial(C3D_Material t_material) { - m_ambient.setColor(t_material.ambient[2], t_material.ambient[1], t_material.ambient[0]); - m_diffuse.setColor(t_material.diffuse[2], t_material.diffuse[1], t_material.diffuse[0]); - m_specular0.setColor(t_material.specular0[2], t_material.specular0[1], t_material.specular0[0]); - m_specular1.setColor(t_material.specular1[2], t_material.specular1[1], t_material.specular1[0]); - m_emission.setColor(t_material.emission[2], t_material.emission[1], t_material.emission[0]); - + m_ambient.setColor(t_material.ambient[2] * 255, t_material.ambient[1] * 255, t_material.ambient[0] * 255); + m_diffuse.setColor(t_material.diffuse[2] * 255, t_material.diffuse[1] * 255, t_material.diffuse[0] * 255); + m_specular0.setColor(t_material.specular0[2] * 255, t_material.specular0[1] * 255, t_material.specular0[0] * 255); + m_specular1.setColor(t_material.specular1[2] * 255, t_material.specular1[1] * 255, t_material.specular1[0] * 255); + m_emission.setColor(t_material.emission[2] * 255, t_material.emission[1] * 255, t_material.emission[0] * 255); updateMaterial(); } @@ -102,6 +105,11 @@ namespace m3d { return m_emission; } + Material& Material::operator=(const Material& rhs) { + setMaterial(*rhs.getMaterial()); + return *this; + } + // private methods void Material::updateMaterial() { m_material->ambient[0] = (float) m_ambient.getBlue() / 255; From 26349b2c16a7972e659eaef017692d0e601d9a52 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:33:42 +0200 Subject: [PATCH 025/114] Make destructor virtual --- m3dialib/includes/m3d/graphics/material.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m3dialib/includes/m3d/graphics/material.hpp b/m3dialib/includes/m3d/graphics/material.hpp index e5c3736..5870180 100644 --- a/m3dialib/includes/m3d/graphics/material.hpp +++ b/m3dialib/includes/m3d/graphics/material.hpp @@ -35,7 +35,7 @@ namespace m3d { /** * @brief Destructs the material */ - ~Material(); + virtual ~Material(); /** * @brief Sets the material with C3D_Material From c76a746c10b463a5d94caab04c6b6d9313453402 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:34:28 +0200 Subject: [PATCH 026/114] Add and implement Mesh-class --- .../includes/m3d/graphics/drawables/mesh.hpp | 331 ++++++++++++++++++ m3dialib/source/graphics/mesh.cpp | 261 ++++++++++++++ 2 files changed, 592 insertions(+) create mode 100644 m3dialib/includes/m3d/graphics/drawables/mesh.hpp create mode 100644 m3dialib/source/graphics/mesh.cpp diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp new file mode 100644 index 0000000..97515fa --- /dev/null +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -0,0 +1,331 @@ +/** + * @file mesh.hpp + * @brief Defines the base class for all 3D-meshes + */ +#ifndef MESH_H +#define MESH_H + +#pragma once +#include +#include +#include "m3d/graphics/color.hpp" +#include "m3d/graphics/drawable.hpp" +#include "m3d/graphics/material.hpp" +#include "m3d/graphics/texture.hpp" +#include "m3d/graphics/vertex.hpp" + +namespace m3d { + /** + * @brief The base class for all meshes + */ + class Mesh: public m3d::Drawable { + public: + /** + * @brief Defines a polygon used by meshes + */ + class Polygon { + public: + /** + * @brief Represents a vertex of a polygon + */ + struct Vertex { + float position[3]; ///< the position + float texcoord[2]; ///< the texture coordinates + float normal[3]; ///< the normals + }; + + /** + * @brief Initializes the polygon + * @param t_vertex0 The first vertex + * @param t_vertex1 The second vertex + * @param t_vertex2 The third vertex + */ + Polygon(m3d::Mesh::Polygon::Vertex t_vertex0, m3d::Mesh::Polygon::Vertex t_vertex1, m3d::Mesh::Polygon::Vertex t_vertex2); + + /** + * @brief Destructs the polygon + */ + virtual ~Polygon(); + + /** + * @brief Sets the vertices of the polygon + * @param t_vertex0 The first vertex + * @param t_vertex1 The second vertex + * @param t_vertex2 The third vertex + */ + void setVertices(m3d::Mesh::Polygon::Vertex t_vertex0, m3d::Mesh::Polygon::Vertex t_vertex1, m3d::Mesh::Polygon::Vertex t_vertex2); + + /** + * @brief Returns a vertex given it's id + * @param t_id The id of the vertex + * @return The vertex at the given id + */ + m3d::Mesh::Polygon::Vertex getVertex(int t_id); + + private: + /* data */ + m3d::Mesh::Polygon::Vertex* m_vertices; + }; + /** + * @brief Initializes the mesh + */ + Mesh(); + + /** + * @brief Adds a polygon to the mesh + * @param t_polygon The polygon to add + */ + void addPolygon(m3d::Mesh::Polygon t_polygon); + + /** + * @brief Removes all vertices + */ + void clearVertices(); + + /** + * @brief Sets the rotation on the X-axis + * @param t_rotation The absolute rotation + */ + void setRotationX(float t_rotation); + + /** + * @brief Returns the rotation on the X-axis + * @return The absolute rotation + */ + float getRotationX(); + + /** + * @brief Sets the rotation on the Y-axis + * @param t_rotation The absolute rotation + */ + void setRotationY(float t_rotation); + + /** + * @brief Returns the rotation on the Y-axis + * @return The absolute rotation + */ + float getRotationY(); + + /** + * @brief Sets the rotation on the Z-axis + * @param t_rotation The absolute rotation + */ + void setRotationZ(float t_rotation); + + /** + * @brief Returns the rotation on the /-axis + * @return The absolute rotation + */ + float getRotationZ(); + + /** + * @brief Sets the rotation of the mesh + * @param t_rotationX The rotation on the X-axis + * @param t_rotationY The rotation on the Y-axis + * @param t_rotationZ The rotation on the Z-axis + */ + void setRotation(float t_rotationX, float t_rotationY, float t_rotationZ); + + /** + * @brief Rotates the mesh a given amount on the X-axis + * @param t_delta The amount to rotate + */ + void rotateX(float t_delta); + + /** + * @brief Rotates the mesh a given amount on the Y-axis + * @param t_delta The amount to rotate + */ + void rotateY(float t_delta); + + /** + * @brief Rotates the mesh a given amount on the /-axis + * @param t_delta The amount to rotate + */ + void rotateZ(float t_delta); + + /** + * @brief Sets the position on the X-axis + * @param t_position The absolute position + */ + void setPositionX(float t_position); + + /** + * @brief Returns the current position on the X-axis + * @return The absolute position + */ + float getPositionX(); + + /** + * @brief Sets the position on the Y-axis + * @param t_position The absolute position + */ + void setPositionY(float t_position); + + /** + * @brief Returns the current position on the Y-axis + * @return The absolute position + */ + float getPositionY(); + + /** + * @brief Sets the position on the Z-axis + * @param t_position The absolute position + */ + void setPositionZ(float t_position); + + /** + * @brief Returns the current position on the Z-axis + * @return The absolute position + */ + float getPositionZ(); + + /** + * @brief Sets the position of the mesh + * @param t_positionX The position on the X-axis + * @param t_positionY The position on the Y-axis + * @param t_positionZ The position on the Z-axis + */ + void setPosition(float t_positionX, float t_positionY, float t_positionZ); + + /** + * @brief Sets the position of the mesh + * @param t_position The absolute position, represented as a vector + */ + void setPosition(m3d::Vector3f t_position); + + /** + * @brief Moves the sprite along the X-axis + * @param t_delta The amount to move + */ + void moveX(float t_delta); + + /** + * @brief Moves the sprite along the Y-axis + * @param t_delta The amount to move + */ + void moveY(float t_delta); + + /** + * @brief Moves the sprite along the Z-axis + * @param t_delta The amount to move + */ + void moveZ(float t_delta); + + /** + * @brief Sets the scale along the mesh's X-axis + * @param t_scale The scale + */ + void setScaleX(float t_scale); + + /** + * @brief Returns the scale along the mesh's X-axis + * @return The scale + */ + float getScaleX(); + + /** + * @brief Sets the scale along the mesh's Y-axis + * @param t_scale The scale + */ + void setScaleY(float t_scale); + + /** + * @brief Returns the scale along the mesh's Y-axis + * @return The scale + */ + float getScaleY(); + + /** + * @brief Sets the scale along the mesh's Z-axis + * @param t_scale The scale + */ + void setScaleZ(float t_scale); + + /** + * @brief Returns the scale along the mesh's Z-axis + * @return The scale + */ + float getScaleZ(); + + /** + * @brief Sets the scale of the mesh + * @param t_scaleX The scale along it's X-axis + * @param t_scaleY The scale along it's Y-axis + * @param t_scaleZ The scale along it's Z-axis + */ + void setScale(float t_scaleX, float t_scaleY, float t_scaleZ); + + /** + * @brief Scales the mesh along it's X-axis + * @param t_delta The amount to scale + */ + void scaleX(float t_delta); + + /** + * @brief Scales the mesh along it's Y-axis + * @param t_delta The amount to scale + */ + void scaleY(float t_delta); + + /** + * @brief Scales the mesh along it's Z-axis + * @param t_delta The amount to scale + */ + void scaleZ(float t_delta); + + /** + * @brief Sets the material of the mesh + * @param t_material The material + */ + void setMaterial(m3d::Material t_material); + + /** + * @brief Returns the material of the mesh + * @return The material + */ + m3d::Material& getMaterial(); + + /** + * @brief Binds a texture to the mesh + * @param t_texture The texture to bind + */ + void bindTexture(m3d::Texture& t_texture); + + /** + * @brief Unbinds the bound texture (disables texture using) + */ + void unbindTexture(); + + /** + * @brief Returns a reference to the current texture + * @return The current texture (or nullptr if no texture was bound) + */ + m3d::Texture& getTexture(); + + /** + * @brief Draws the shape + * @param t_context The RenderContext + */ + void draw(m3d::RenderContext t_context); + + protected: + void updateVbo(); + + private: + /* data */ + float m_rotationX, m_rotationY, m_rotationZ, m_posX, m_posY, m_posZ, m_scaleX, m_scaleY, m_scaleZ; + bool m_useTexture; + + // polygons + std::vector m_vertices; + m3d::Mesh::Polygon::Vertex* m_vbo; + + // display properties + m3d::Texture m_texture; + m3d::Material m_material; + }; +} /* m3d */ + + +#endif /* end of include guard: MESH_H */ diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp new file mode 100644 index 0000000..2113807 --- /dev/null +++ b/m3dialib/source/graphics/mesh.cpp @@ -0,0 +1,261 @@ +#include +#include +#include "m3d/graphics/drawables/mesh.hpp" +#include "m3d/private/graphics.hpp" + +namespace m3d { + Mesh::Mesh() : + m_rotationX(0.0f), + m_rotationY(0.0f), + m_rotationZ(0.0f), + m_posX(0.0f), + m_posY(0.0f), + m_posZ(0.0f), + m_scaleX(1.0f), + m_scaleY(1.0f), + m_scaleZ(1.0f), + m_useTexture(false) { /* do nothing */ } + + void Mesh::addPolygon(m3d::Mesh::Polygon t_polygon) { + m3d::Mesh::Polygon::Vertex vertex0 = t_polygon.getVertex(0), + vertex1 = t_polygon.getVertex(1), + vertex2 = t_polygon.getVertex(2); + + m_vertices.push_back({ + { vertex0.position[0], vertex0.position[1], vertex0.position[2] }, + { vertex0.texcoord[0], vertex0.texcoord[1] }, + { vertex0.normal[0], vertex0.normal[1], vertex0.normal[2] }, + }); + + m_vertices.push_back({ + { vertex1.position[0], vertex1.position[1], vertex1.position[2] }, + { vertex1.texcoord[0], vertex1.texcoord[1] }, + { vertex1.normal[0], vertex1.normal[1], vertex1.normal[2] }, + }); + + m_vertices.push_back({ + { vertex2.position[0], vertex2.position[1], vertex2.position[2] }, + { vertex2.texcoord[0], vertex2.texcoord[1] }, + { vertex2.normal[0], vertex2.normal[1], vertex2.normal[2] }, + }); + + updateVbo(); + } + + void Mesh::clearVertices() { + m_vertices.clear(); + } + + void Mesh::setRotationX(float t_rotation) { + m_rotationX = t_rotation; + } + + float Mesh::getRotationX() { + return m_rotationX; + } + + void Mesh::setRotationY(float t_rotation) { + m_rotationY = t_rotation; + } + + float Mesh::getRotationY() { + return m_rotationY; + } + + void Mesh::setRotationZ(float t_rotation) { + m_rotationZ = t_rotation; + } + + float Mesh::getRotationZ() { + return m_rotationZ; + } + + void Mesh::setRotation(float t_rotationX, float t_rotationY, float t_rotationZ) { + m_rotationX = t_rotationX; + m_rotationY = t_rotationY; + m_rotationZ = t_rotationZ; + } + + void Mesh::rotateX(float t_delta) { + m_rotationX += t_delta; + } + + void Mesh::rotateY(float t_delta) { + m_rotationY += t_delta; + } + + void Mesh::rotateZ(float t_delta) { + m_rotationZ += t_delta; + } + + void Mesh::setPositionX(float t_position) { + m_posX = t_position; + } + + float Mesh::getPositionX() { + return m_posX; + } + + void Mesh::setPositionY(float t_position) { + m_posY = t_position; + } + + float Mesh::getPositionY() { + return m_posY; + } + + void Mesh::setPositionZ(float t_position) { + m_posZ = t_position; + } + + float Mesh::getPositionZ() { + return m_posZ; + } + + void Mesh::setPosition(float t_positionX, float t_positionY, float t_positionZ) { + m_posX = t_positionX; + m_posY = t_positionY; + m_posZ = t_positionZ; + } + + void Mesh::setPosition(m3d::Vector3f t_position) { + m_posX = t_position.x; + m_posY = t_position.y; + m_posZ = t_position.z; + } + + void Mesh::moveX(float t_delta) { + m_posX += t_delta; + } + + void Mesh::moveY(float t_delta) { + m_posY += t_delta; + } + + void Mesh::moveZ(float t_delta) { + m_posZ += t_delta; + } + + void Mesh::setScaleX(float t_scale) { + m_scaleX = t_scale; + } + + float Mesh::getScaleX() { + return m_scaleX; + } + + void Mesh::setScaleY(float t_scale) { + m_scaleY = t_scale; + } + + float Mesh::getScaleY() { + return m_scaleY; + } + + void Mesh::setScaleZ(float t_scale) { + m_scaleZ = t_scale; + } + + float Mesh::getScaleZ() { + return m_scaleZ; + } + + void Mesh::setScale(float t_scaleX, float t_scaleY, float t_scaleZ) { + m_scaleX = t_scaleX; + m_scaleY = t_scaleY; + m_scaleZ = t_scaleZ; + } + + void Mesh::scaleX(float t_delta) { + m_scaleX += t_delta; + } + + void Mesh::scaleY(float t_delta) { + m_scaleY += t_delta; + } + + void Mesh::scaleZ(float t_delta) { + m_scaleZ += t_delta; + } + + void Mesh::setMaterial(m3d::Material t_material) { + m_material = t_material; + } + + m3d::Material& Mesh::getMaterial() { + return m_material; + } + + void Mesh::bindTexture(m3d::Texture& t_texture) { + m_useTexture = true; + m_texture = t_texture; + } + + void Mesh::unbindTexture() { + m_useTexture = false; + } + + m3d::Texture& Mesh::getTexture() { + return m_texture; + } + + void Mesh::draw(m3d::RenderContext t_context) { + if (t_context.getMode() == m3d::RenderContext::Mode::Spatial) { + // Mtx_Translate(&t_context.getProjectionMatrix(), posX, 0.0, , true); + + // manipulate modelview matrix + Mtx_Identity(&t_context.getModelViewMatrix()); + Mtx_Translate(&t_context.getModelViewMatrix(), m_posX, m_posY, -1.87 - m_posZ, true); + Mtx_RotateX(&t_context.getModelViewMatrix(), m_rotationX, true); + Mtx_RotateY(&t_context.getModelViewMatrix(), m_rotationY, true); + Mtx_RotateZ(&t_context.getModelViewMatrix(), m_rotationZ, true); + Mtx_Scale(&t_context.getModelViewMatrix(), m_scaleX, m_scaleY, m_scaleZ); + + // set material + C3D_LightEnvMaterial(&t_context.getLightEnvironment(), m_material.getMaterial()); + + if (m_useTexture) { + // enable textures + t_context.enableTextures(true); + + // bind the texture + C3D_TexSetFilter(m_texture.getTexture(), GPU_LINEAR, GPU_LINEAR); + C3D_TexBind(0, m_texture.getTexture()); + } else { + // disable textures + t_context.enableTextures(false); + } + + // create buffer + C3D_BufInfo* bufInfo = C3D_GetBufInfo(); + BufInfo_Init(bufInfo); + BufInfo_Add(bufInfo, m_vbo, sizeof(m3d::Mesh::Polygon::Vertex), 3, 0x210); + + // update the uniforms + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, t_context.getProjectionUniform(), &t_context.getProjectionMatrix()); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, t_context.getModelViewUniform(), &t_context.getModelViewMatrix()); + + // draw the VBO + C3D_DrawArrays(GPU_TRIANGLES, 0, m_vertices.size()); + } + } + + // private methods + void Mesh::updateVbo() { + linearFree(m_vbo); + m_vbo = static_cast(linearAlloc(m_vertices.size() * sizeof(m3d::Mesh::Polygon::Vertex))); + + for (unsigned int i = 0; i < m_vertices.size(); i++) { + float x = m_vertices[i].position[0], + y = m_vertices[i].position[1], + z = m_vertices[i].position[2], + u = m_vertices[i].texcoord[0], + v = m_vertices[i].texcoord[1], + nx = m_vertices[i].normal[0], + ny = m_vertices[i].normal[1], + nz = m_vertices[i].normal[2]; + + m_vbo[i] = (m3d::Mesh::Polygon::Vertex) { { x, y, z }, { u, v }, { nx, ny, nz } }; + } + } +} /* m3d */ From 9fa1c27a5a1ad1fdc2f239da3b01479904263a8c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:34:36 +0200 Subject: [PATCH 027/114] Fix texture copying --- m3dialib/source/graphics/texture.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/m3dialib/source/graphics/texture.cpp b/m3dialib/source/graphics/texture.cpp index 5251a0b..326f94a 100644 --- a/m3dialib/source/graphics/texture.cpp +++ b/m3dialib/source/graphics/texture.cpp @@ -65,8 +65,12 @@ namespace m3d { m_width = rhs.getWidth(); m_height = rhs.getHeight(); m_path = rhs.getPath(); - C3D_TexDelete(m_texture); - m_texture = rhs.getTexture(); + + if (m_texture) C3D_TexDelete(m_texture); + + m_texture = static_cast(malloc(sizeof(C3D_Tex))); + C3D_TexInit(m_texture, getNextPow2(rhs.getTexture()->width), getNextPow2(rhs.getTexture()->height), GPU_RGBA8); + *m_texture = *rhs.getTexture(); return *this; } From 7cec97d548bbac0ff8e74c6a1b8cbcf833f0fb3b Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:34:44 +0200 Subject: [PATCH 028/114] Implement Polygon-class --- m3dialib/source/graphics/polygon.cpp | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 m3dialib/source/graphics/polygon.cpp diff --git a/m3dialib/source/graphics/polygon.cpp b/m3dialib/source/graphics/polygon.cpp new file mode 100644 index 0000000..8f7f787 --- /dev/null +++ b/m3dialib/source/graphics/polygon.cpp @@ -0,0 +1,36 @@ +#include "m3d/graphics/drawables/mesh.hpp" + +namespace m3d { + Mesh::Polygon::Polygon(m3d::Mesh::Polygon::Vertex t_vertex0, m3d::Mesh::Polygon::Vertex t_vertex1, m3d::Mesh::Polygon::Vertex t_vertex2) { + m_vertices = new m3d::Mesh::Polygon::Vertex[3]; + setVertices(t_vertex0, t_vertex1, t_vertex2); + } + + /** + * @brief Destructs the polygon + */ + Mesh::Polygon::~Polygon() { + delete m_vertices; + } + + /** + * @brief Sets the vertices of the polygon + * @param t_vertex0 The first vertex + * @param t_vertex1 The second vertex + * @param t_vertex2 The third vertex + */ + void Mesh::Polygon::setVertices(m3d::Mesh::Polygon::Vertex t_vertex0, m3d::Mesh::Polygon::Vertex t_vertex1, m3d::Mesh::Polygon::Vertex t_vertex2) { + m_vertices[0] = t_vertex0; + m_vertices[1] = t_vertex1; + m_vertices[2] = t_vertex2; + } + + /** + * @brief Returns a vertex given it's id + * @param t_id The id of the vertex + * @return The vertex at the given id + */ + m3d::Mesh::Polygon::Vertex Mesh::Polygon::getVertex(int t_id) { + return m_vertices[t_id]; + } +} /* m3d */ From 05ffa5ed9ac58d822cf82ea12ea0b9f1a1137ae1 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:51:00 +0200 Subject: [PATCH 029/114] Add and implement Cuboid-mesh --- .../m3d/graphics/drawables/meshes/cuboid.hpp | 70 +++++++++++ m3dialib/source/graphics/cuboid.cpp | 117 ++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 m3dialib/includes/m3d/graphics/drawables/meshes/cuboid.hpp create mode 100644 m3dialib/source/graphics/cuboid.cpp diff --git a/m3dialib/includes/m3d/graphics/drawables/meshes/cuboid.hpp b/m3dialib/includes/m3d/graphics/drawables/meshes/cuboid.hpp new file mode 100644 index 0000000..8872af8 --- /dev/null +++ b/m3dialib/includes/m3d/graphics/drawables/meshes/cuboid.hpp @@ -0,0 +1,70 @@ +/** + * @file cuboid.hpp + * @brief Defines the cuboid mesh + */ +#ifndef CUBOID_H +#define CUBOID_H + +#pragma once +#include "m3d/graphics/drawables/mesh.hpp" + +namespace m3d { + /** + * @brief The cuboid mesh + */ + class Cuboid: public m3d::Mesh { + public: + /** + * @brief Creates the cuboid + * @param t_length The length of the cuboid + * @param t_width The width of the cuboid + * @param t_height The height of the cuboid + */ + Cuboid(float t_length, float t_width, float t_height); + + /** + * @brief Sets the length of the cuboid + * @param t_length The length + */ + void setLength(float t_length); + + /** + * @brief Returns the length of the cuboid + * @return The length + */ + float getLength(); + + /** + * @brief Sets the width of the cuboid + * @param t_width The width + */ + void setWidth(float t_width); + + /** + * @brief Returns the width of the cuboid + * @return The width + */ + float getWidth(); + + /** + * @brief Sets the height of the cuboid + * @param t_height The height + */ + void setHeight(float t_height); + + /** + * @brief Returns the height of the cuboid + * @return The height + */ + float getHeight(); + + private: + void update(); + + /* data */ + float m_length, m_width, m_height; + }; +} /* m3d */ + + +#endif /* end of include guard: CUBOID_H */ diff --git a/m3dialib/source/graphics/cuboid.cpp b/m3dialib/source/graphics/cuboid.cpp new file mode 100644 index 0000000..c68711b --- /dev/null +++ b/m3dialib/source/graphics/cuboid.cpp @@ -0,0 +1,117 @@ +#include "m3d/graphics/drawables/meshes/cuboid.hpp" + +namespace m3d { + Cuboid::Cuboid(float t_length, float t_width, float t_height) { + m_length = t_length; + m_width = t_width; + m_height = t_height; + update(); + } + + void Cuboid::setLength(float t_length) { + m_length = t_length; + } + + float Cuboid::getLength() { + return m_length; + } + + void Cuboid::setWidth(float t_width) { + m_width = t_width; + } + + float Cuboid::getWidth() { + return m_width; + } + + void Cuboid::setHeight(float t_height) { + m_height = t_height; + } + + float Cuboid::getHeight() { + return m_height; + } + + // private methods + void Cuboid::update() { + clearVertices(); + + // first face (PZ) + addPolygon(m3d::Mesh::Polygon( + { {-(m_width / 2), -(m_height / 2), (m_length / 2)}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} }, + { {(m_width / 2), -(m_height / 2), (m_length / 2)}, {1.0f, 0.0f}, {0.0f, 0.0f, +1.0f} }, + { {(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} } + )); + + addPolygon(m3d::Mesh::Polygon( + { {(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} }, + { {-(m_width / 2), (m_height / 2), (m_length / 2)}, {0.0f, 1.0f}, {0.0f, 0.0f, +1.0f} }, + { {-(m_width / 2), -(m_height / 2), (m_length / 2)}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} } + )); + + // second face (MZ) + addPolygon(m3d::Mesh::Polygon( + { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} }, + { {-(m_width / 2), (m_height / 2), -(m_length / 2)}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f} }, + { {(m_width / 2), (m_height / 2), -(m_length / 2)}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} } + )); + + addPolygon(m3d::Mesh::Polygon( + { {(m_width / 2), (m_height / 2), -(m_length / 2)}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} }, + { {(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} }, + { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} } + )); + + // third face (PX) + addPolygon(m3d::Mesh::Polygon( + { {(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} }, + { {(m_width / 2), (m_height / 2), -(m_length / 2)}, {1.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} }, + { {(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} } + )); + + addPolygon(m3d::Mesh::Polygon( + { {(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} }, + { {(m_width / 2), -(m_height / 2), (m_length / 2)}, {0.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} }, + { {(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} } + )); + + // fourth face (MX) + addPolygon(m3d::Mesh::Polygon( + { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} }, + { {-(m_width / 2), -(m_height / 2), (m_length / 2)}, {1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} }, + { {-(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} } + )); + + addPolygon(m3d::Mesh::Polygon( + { {-(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} }, + { {-(m_width / 2), (m_height / 2), -(m_length / 2)}, {0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} }, + { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} } + )); + + // fifth face (PY) + addPolygon(m3d::Mesh::Polygon( + { {-(m_width / 2), (m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} }, + { {-(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 0.0f}, {0.0f, +1.0f, 0.0f} }, + { {(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} } + )); + + addPolygon(m3d::Mesh::Polygon( + { {(m_width / 2), (m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} }, + { {(m_width / 2), (m_height / 2), -(m_length / 2)}, {0.0f, 1.0f}, {0.0f, +1.0f, 0.0f} }, + { {-(m_width / 2), (m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} } + )); + + // sixth face (MY) + addPolygon(m3d::Mesh::Polygon( + { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} }, + { {(m_width / 2), -(m_height / 2), -(m_length / 2)}, {1.0f, 0.0f}, {0.0f, -1.0f, 0.0f} }, + { {(m_width / 2), -(m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} } + )); + + addPolygon(m3d::Mesh::Polygon( + { {(m_width / 2), -(m_height / 2), (m_length / 2)}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} }, + { {-(m_width / 2), -(m_height / 2), (m_length / 2)}, {0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} }, + { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} } + )); + } +} /* m3d */ From 4a0217bb30f25e8412755eff6a7eb0fc0740ea23 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:51:13 +0200 Subject: [PATCH 030/114] Include all meshes --- m3dialib/includes/m3d/graphics/meshes.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 m3dialib/includes/m3d/graphics/meshes.hpp diff --git a/m3dialib/includes/m3d/graphics/meshes.hpp b/m3dialib/includes/m3d/graphics/meshes.hpp new file mode 100644 index 0000000..803775c --- /dev/null +++ b/m3dialib/includes/m3d/graphics/meshes.hpp @@ -0,0 +1,13 @@ +/** + * @file meshes.hpp + * @brief Includes all pre-coded meshes + */ +#ifndef MESHES_H +#define MESHES_H + +#pragma once + +#include "drawables/meshes/cuboid.hpp" + + +#endif /* end of include guard: MESHES_H */ From f7b9286eaea712896faeaf2fd2263ea69c806afa Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:51:20 +0200 Subject: [PATCH 031/114] Add meshes-include --- m3dialib/includes/m3d/graphics/graphics.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/m3dialib/includes/m3d/graphics/graphics.hpp b/m3dialib/includes/m3d/graphics/graphics.hpp index cdf9c31..d34523d 100644 --- a/m3dialib/includes/m3d/graphics/graphics.hpp +++ b/m3dialib/includes/m3d/graphics/graphics.hpp @@ -11,12 +11,14 @@ #include "color.hpp" #include "boundingBox.hpp" #include "drawable.hpp" +#include "material.hpp" #include "renderTarget.hpp" #include "screen.hpp" #include "texture.hpp" -// all pre-coded drawables +// all pre-coded drawables and meshes #include "drawables.hpp" +#include "meshes.hpp" #endif /* end of include guard: GRAPHICS_H */ From eda1c08b0245e5d073217ae67d61fa6d2de12d44 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:51:29 +0200 Subject: [PATCH 032/114] Include Mesh-class --- m3dialib/includes/m3d/graphics/drawables.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/m3dialib/includes/m3d/graphics/drawables.hpp b/m3dialib/includes/m3d/graphics/drawables.hpp index 3dc4e72..8703e8c 100644 --- a/m3dialib/includes/m3d/graphics/drawables.hpp +++ b/m3dialib/includes/m3d/graphics/drawables.hpp @@ -8,6 +8,7 @@ #pragma once #include "drawables/circle.hpp" +#include "drawables/mesh.hpp" #include "drawables/rectangle.hpp" #include "drawables/shape.hpp" #include "drawables/sprite.hpp" From 2619c84874f17bcca7a5adf03ffa46c14882f3f7 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 13:52:10 +0200 Subject: [PATCH 033/114] Fix breakpoints --- m3dialib/includes/m3dia.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m3dialib/includes/m3dia.hpp b/m3dialib/includes/m3dia.hpp index f31d3b0..81a29a7 100644 --- a/m3dialib/includes/m3dia.hpp +++ b/m3dialib/includes/m3dia.hpp @@ -23,7 +23,7 @@ */ #define M3D_BREAKPOINT() \ std::cout << "\u001b[33;1mBreakpoint reached: \n" << (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) << ":" << __LINE__ << "\u001b[0m\n"; \ - while (true) { hidScanInput(); if (m3d::buttons::buttonPressed(m3d::buttons::BUTTON_A)) break; } + while (true) { hidScanInput(); if (m3d::buttons::buttonPressed(m3d::buttons::Button::A)) break; } /** * @brief Breaks the execution and waits for the A-button to be pressed @@ -33,7 +33,7 @@ */ #define M3D_DEBUGPOINT(msg) \ std::cout << "\u001b[33;1mBreakpoint reached: \n" << (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) << ":" << __LINE__ << ": " << msg << "\u001b[0m\n"; \ - while (true) { hidScanInput(); if (m3d::buttons::buttonPressed(m3d::buttons::BUTTON_A)) break; } + while (true) { hidScanInput(); if (m3d::buttons::buttonPressed(m3d::buttons::Button::A)) break; } #else #define M3D_BREAKPOINT() #define M3D_DEBUGPOINT(msg) From d317552810f2c7f5ed0358c743dc6eb1175ad0e3 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Fri, 21 Sep 2018 14:00:33 +0200 Subject: [PATCH 034/114] Fix documentation --- m3dialib/includes/m3d/graphics/drawables/mesh.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index 97515fa..6c784c4 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -195,19 +195,19 @@ namespace m3d { void setPosition(m3d::Vector3f t_position); /** - * @brief Moves the sprite along the X-axis + * @brief Moves the mesh along the X-axis * @param t_delta The amount to move */ void moveX(float t_delta); /** - * @brief Moves the sprite along the Y-axis + * @brief Moves the mesh along the Y-axis * @param t_delta The amount to move */ void moveY(float t_delta); /** - * @brief Moves the sprite along the Z-axis + * @brief Moves the mesh along the Z-axis * @param t_delta The amount to move */ void moveZ(float t_delta); @@ -304,7 +304,7 @@ namespace m3d { m3d::Texture& getTexture(); /** - * @brief Draws the shape + * @brief Draws the mesh * @param t_context The RenderContext */ void draw(m3d::RenderContext t_context); From 9f1b8bb027c50c5827e4741daf50919ce171d666 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sat, 22 Sep 2018 22:22:08 +0200 Subject: [PATCH 035/114] Update shader --- m3dialib/source/graphics/render3d.v.pica | 45 +++++++++++++++--------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/m3dialib/source/graphics/render3d.v.pica b/m3dialib/source/graphics/render3d.v.pica index e994949..ba21a4b 100644 --- a/m3dialib/source/graphics/render3d.v.pica +++ b/m3dialib/source/graphics/render3d.v.pica @@ -1,13 +1,15 @@ ; Example PICA200 vertex shader +; For more in-depth information, see the following Manual: +; https://github.com/fincs/picasso/blob/master/Manual.md ; Uniforms -.fvec projection[4], modelView[4] +.fvec projection[4], model[4], view[4] ; Constants .constf myconst(0.0, 1.0, -1.0, 0.5) .alias zeros myconst.xxxx ; Vector full of zeros .alias ones myconst.yyyy ; Vector full of ones -.alias half myconst.wwww +.alias half myconst.wwww ; Vector full of 0.5 ; Outputs .out outpos position @@ -17,25 +19,34 @@ .out outnq normalquat ; Inputs (defined as aliases for convenience) -.alias inpos v0 -.alias intex v1 -.alias innrm v2 +.alias inpos v0 ; Goes with AttrInfo_AddLoader register ID value. +.alias intex v1 ; Same for v1 and v2. +.alias innrm v2 ; v0: Position, v1: Texture Coordinates, v2: Normals. .proc main - ; Force the w component of inpos to be 1.0 - mov r0.xyz, inpos - mov r0.w, ones + ; Vertex position vectors. + mov r0.xyz, inpos.xyz + mov r0.w, myconst.y ; This is how you set the variables with a constant. + ; Homeogeneous coordinates: + ; If w == 1, then the vector is a position. Else if w == 0, it's a direction. - ; r1 = modelView * inpos - dp4 r1.x, modelView[0], r0 - dp4 r1.y, modelView[1], r0 - dp4 r1.z, modelView[2], r0 - dp4 r1.w, modelView[3], r0 + ; r1 = modelview matrix, (model matrix * vertex positions) + dp4 r2.x, model[0], r0 + dp4 r2.y, model[1], r0 + dp4 r2.z, model[2], r0 + dp4 r2.w, model[3], r0 + + + ; r1 = modelview matrix, (view * results) + dp4 r1.x, view[0], r2 + dp4 r1.y, view[1], r2 + dp4 r1.z, view[2], r2 + dp4 r1.w, view[3], r2 ; outview = -r1 mov outview, -r1 - ; outpos = projection * r1 + ; outpos = modelview projection matrix, (projection * results) dp4 outpos.x, projection[0], r1 dp4 outpos.y, projection[1], r1 dp4 outpos.z, projection[2], r1 @@ -46,9 +57,9 @@ ; Transform the normal vector with the modelView matrix ; TODO: use a separate normal matrix that is the transpose of the inverse of modelView - dp3 r14.x, modelView[0], innrm - dp3 r14.y, modelView[1], innrm - dp3 r14.z, modelView[2], innrm + dp3 r14.x, model[0], innrm + dp3 r14.y, model[1], innrm + dp3 r14.z, model[2], innrm dp3 r6.x, r14, r14 rsq r6.x, r6.x mul r14.xyz, r14.xyz, r6.x From 649c1d3cb127d401a5faf731d783a795c28fbd99 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sat, 22 Sep 2018 22:22:25 +0200 Subject: [PATCH 036/114] Add and implement Camera-class --- m3dialib/includes/m3d/graphics/camera.hpp | 162 ++++++++++++++++++++++ m3dialib/source/graphics/camera.cpp | 112 +++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 m3dialib/includes/m3d/graphics/camera.hpp create mode 100644 m3dialib/source/graphics/camera.cpp diff --git a/m3dialib/includes/m3d/graphics/camera.hpp b/m3dialib/includes/m3d/graphics/camera.hpp new file mode 100644 index 0000000..66699a5 --- /dev/null +++ b/m3dialib/includes/m3d/graphics/camera.hpp @@ -0,0 +1,162 @@ +/** + * @file camera.hpp + * @brief Defines the Camera-class + */ +#ifndef CAMERA_H +#define CAMERA_H + +#pragma once +#include +#include "vertex.hpp" + +namespace m3d { + class Camera { + public: + /** + * @brief Default constructor + */ + Camera(); + + /** + * @brief Sets the rotation on the X-axis + * @param t_rotation The absolute rotation + */ + void setRotationX(float t_rotation); + + /** + * @brief Returns the rotation on the X-axis + * @return The absolute rotation + */ + float getRotationX(); + + /** + * @brief Sets the rotation on the Y-axis + * @param t_rotation The absolute rotation + */ + void setRotationY(float t_rotation); + + /** + * @brief Returns the rotation on the Y-axis + * @return The absolute rotation + */ + float getRotationY(); + + /** + * @brief Sets the rotation on the Z-axis + * @param t_rotation The absolute rotation + */ + void setRotationZ(float t_rotation); + + /** + * @brief Returns the rotation on the /-axis + * @return The absolute rotation + */ + float getRotationZ(); + + /** + * @brief Sets the rotation of the camera + * @param t_rotationX The rotation on the X-axis + * @param t_rotationY The rotation on the Y-axis + * @param t_rotationZ The rotation on the Z-axis + */ + void setRotation(float t_rotationX, float t_rotationY, float t_rotationZ); + + /** + * @brief Rotates the camera a given amount on the X-axis + * @param t_delta The amount to rotate + */ + void rotateX(float t_delta); + + /** + * @brief Rotates the camera a given amount on the Y-axis + * @param t_delta The amount to rotate + */ + void rotateY(float t_delta); + + /** + * @brief Rotates the camera a given amount on the /-axis + * @param t_delta The amount to rotate + */ + void rotateZ(float t_delta); + + /** + * @brief Sets the position on the X-axis + * @param t_position The absolute position + */ + void setPositionX(float t_position); + + /** + * @brief Returns the current position on the X-axis + * @return The absolute position + */ + float getPositionX(); + + /** + * @brief Sets the position on the Y-axis + * @param t_position The absolute position + */ + void setPositionY(float t_position); + + /** + * @brief Returns the current position on the Y-axis + * @return The absolute position + */ + float getPositionY(); + + /** + * @brief Sets the position on the Z-axis + * @param t_position The absolute position + */ + void setPositionZ(float t_position); + + /** + * @brief Returns the current position on the Z-axis + * @return The absolute position + */ + float getPositionZ(); + + /** + * @brief Sets the position of the camera + * @param t_positionX The position on the X-axis + * @param t_positionY The position on the Y-axis + * @param t_positionZ The position on the Z-axis + */ + void setPosition(float t_positionX, float t_positionY, float t_positionZ); + + /** + * @brief Sets the position of the camera + * @param t_position The absolute position, represented as a vector + */ + void setPosition(m3d::Vector3f t_position); + + /** + * @brief Moves the camera along the X-axis + * @param t_delta The amount to move + * @param t_relative Whether or not to move on the camera's relative axis instead of the absolute axis + */ + void moveX(float t_delta, bool t_relative = true); + + /** + * @brief Moves the camera along the Y-axis + * @param t_delta The amount to move + * @param t_relative Whether or not to move on the camera's relative axis instead of the absolute axis + */ + void moveY(float t_delta, bool t_relative = true); + + /** + * @brief Moves the camera along the Z-axis + * @param t_delta The amount to move + * @param t_relative Whether or not to move on the camera's relative axis instead of the absolute axis + */ + void moveZ(float t_delta, bool t_relative = true); + + C3D_Mtx& getViewMatrix(); + + private: + /* data */ + float m_posX, m_posY, m_posZ, m_rotationX, m_rotationY, m_rotationZ; + C3D_Mtx m_view; + }; +} /* m3d */ + +#endif /* end of include guard: CAMERA_H */ diff --git a/m3dialib/source/graphics/camera.cpp b/m3dialib/source/graphics/camera.cpp new file mode 100644 index 0000000..c53aca8 --- /dev/null +++ b/m3dialib/source/graphics/camera.cpp @@ -0,0 +1,112 @@ +#include +#include "m3d/graphics/camera.hpp" + +namespace m3d { + Camera::Camera() : + m_posX(0.0f), + m_posY(0.0f), + m_posZ(0.0f), + m_rotationX(0.0f), + m_rotationY(0.0f), + m_rotationZ(0.0f) { /* do nothing */ } + + void Camera::setRotationX(float t_rotation) { + m_rotationX = t_rotation; + } + + float Camera::getRotationX() { + return m_rotationX; + } + + void Camera::setRotationY(float t_rotation) { + m_rotationY = t_rotation; + } + + float Camera::getRotationY() { + return m_rotationY; + } + + void Camera::setRotationZ(float t_rotation) { + m_rotationZ = t_rotation; + } + + float Camera::getRotationZ() { + return m_rotationZ; + } + + void Camera::setRotation(float t_rotationX, float t_rotationY, float t_rotationZ) { + m_rotationX = t_rotationX; + m_rotationY = t_rotationY; + m_rotationZ = t_rotationZ; + } + + void Camera::rotateX(float t_delta) { + m_rotationX += t_delta; + } + + void Camera::rotateY(float t_delta) { + m_rotationY += t_delta; + } + + void Camera::rotateZ(float t_delta) { + m_rotationZ += t_delta; + } + + void Camera::setPositionX(float t_position) { + m_posX = t_position; + } + + float Camera::getPositionX() { + return m_posX; + } + + void Camera::setPositionY(float t_position) { + m_posY = t_position; + } + + float Camera::getPositionY() { + return m_posY; + } + + void Camera::setPositionZ(float t_position) { + m_posZ = t_position; + } + + float Camera::getPositionZ() { + return m_posZ; + } + + void Camera::setPosition(float t_positionX, float t_positionY, float t_positionZ) { + m_posX = t_positionX; + m_posY = t_positionY; + m_posZ = t_positionZ; + } + + void Camera::setPosition(m3d::Vector3f t_position) { + m_posX = t_position.x; + m_posY = t_position.y; + m_posZ = t_position.z; + } + + void Camera::moveX(float t_delta, bool t_relative) { + m_posX += t_delta; + } + + void Camera::moveY(float t_delta, bool t_relative) { + m_posY += t_delta; + } + + void Camera::moveZ(float t_delta, bool t_relative) { + m_posZ += t_delta; + } + + C3D_Mtx& Camera::getViewMatrix() { + Mtx_Identity(&m_view); + Mtx_RotateX(&m_view, m_rotationX, true); + Mtx_RotateY(&m_view, m_rotationY, true); + Mtx_RotateZ(&m_view, m_rotationZ, true); + Mtx_Translate(&m_view, -m_posX, m_posY, -m_posZ, true); + + return m_view; + } +} /* m3d */ From 931df59ed81aa26413a2ac9626028fe09f36067f Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 19:47:19 +0200 Subject: [PATCH 037/114] Fix arm11 exception on destruction --- m3dialib/source/graphics/texture.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/m3dialib/source/graphics/texture.cpp b/m3dialib/source/graphics/texture.cpp index 326f94a..026bf8b 100644 --- a/m3dialib/source/graphics/texture.cpp +++ b/m3dialib/source/graphics/texture.cpp @@ -13,8 +13,6 @@ namespace m3d { Texture::~Texture() { if (m_texture != nullptr) { unloadImage(m_image); - free(m_image.tex); - free((Tex3DS_SubTexture*) m_image.subtex); } } From e132d88947ad71ae66f189bd4964680fb5f569c9 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:04:36 +0200 Subject: [PATCH 038/114] Update RenderContext-class --- .../includes/m3d/graphics/renderContext.hpp | 50 +++++++------------ m3dialib/source/graphics/renderContext.cpp | 28 +++-------- 2 files changed, 25 insertions(+), 53 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/renderContext.hpp b/m3dialib/includes/m3d/graphics/renderContext.hpp index 2e838a0..7823fe9 100644 --- a/m3dialib/includes/m3d/graphics/renderContext.hpp +++ b/m3dialib/includes/m3d/graphics/renderContext.hpp @@ -40,43 +40,33 @@ namespace m3d { /** * @brief Default constructor - * @param t_projectionUniform The location of the projection uniform - * @param t_modelViewUniform The location of the model view uniform - * @param t_3dEnabled Whether stereoscopic 3D is enabled - * @param t_mode The current rendering mode - * @param t_side The current side for stereoscopic 3D - * @param t_target The current screen target - * @param t_projection The projection matrix - * @param t_modelView The model view matrix - * @param t_lightEnv The light environment - * @param t_light The light - * @param t_lightLut The light LUT + * @param t_modelUniform The location of the model uniform + * @param t_mode The current rendering mode + * @param t_side The current side for stereoscopic 3D + * @param t_target The current screen target + * @param t_projection The projection matrix + * @param t_model The model matrix + * @param t_lightEnv The light environment + * @param t_light The light + * @param t_lightLut The light LUT */ RenderContext( - int t_projectionUniform, - int t_modelViewUniform, + int t_modelUniform, bool t_3dEnabled, m3d::RenderContext::Mode t_mode, m3d::RenderContext::Stereo3dSide t_side, m3d::RenderContext::ScreenTarget t_target, - C3D_Mtx& t_projection, - C3D_Mtx& t_modelView, + C3D_Mtx& t_model, C3D_LightEnv& t_lightEnv, C3D_Light& t_light, C3D_LightLut& t_lightLut ); - /** - * @brief Returns the location of the projection uniform - * @return The location of the uniform - */ - int getProjectionUniform(); - /** * @brief Returns the location of the model view uniform * @return The location of the uniform */ - int getModelViewUniform(); + int getModelUniform(); /** * @brief Returns whether or not stereoscopic 3D is enabled @@ -103,16 +93,10 @@ namespace m3d { m3d::RenderContext::ScreenTarget getScreenTarget(); /** - * @brief Returns the projection matrix - * @return The projection matrix - */ - C3D_Mtx& getProjectionMatrix(); - - /** - * @brief Returns the model view matrix - * @return The model view matrix + * @brief Returns the model matrix + * @return The model matrix */ - C3D_Mtx& getModelViewMatrix(); + C3D_Mtx& getModelMatrix(); /** * @brief Returns the light environment @@ -140,12 +124,12 @@ namespace m3d { private: /* data */ - int m_projectionUniformLocation, m_modelViewUniformLocation, m_materialUniformLocation; + int m_modelUniformLocation; bool m_3dEnabled; m3d::RenderContext::Mode m_mode; m3d::RenderContext::Stereo3dSide m_side; m3d::RenderContext::ScreenTarget m_target; - C3D_Mtx &m_projection, &m_modelView; + C3D_Mtx &m_model; C3D_LightEnv& m_lightEnv; C3D_Light& m_light; C3D_LightLut& m_lightLut; diff --git a/m3dialib/source/graphics/renderContext.cpp b/m3dialib/source/graphics/renderContext.cpp index e0a60d8..9999f32 100644 --- a/m3dialib/source/graphics/renderContext.cpp +++ b/m3dialib/source/graphics/renderContext.cpp @@ -2,36 +2,28 @@ namespace m3d { RenderContext::RenderContext( - int t_projectionUniform, - int t_modelViewUniform, + int t_modelUniform, bool t_3dEnabled, m3d::RenderContext::Mode t_mode, m3d::RenderContext::Stereo3dSide t_side, m3d::RenderContext::ScreenTarget t_target, - C3D_Mtx& t_projection, - C3D_Mtx& t_modelView, + C3D_Mtx& t_model, C3D_LightEnv& t_lightEnv, C3D_Light& t_light, C3D_LightLut& t_lightLut ) : - m_projectionUniformLocation(t_projectionUniform), - m_modelViewUniformLocation(t_modelViewUniform), + m_modelUniformLocation(t_modelUniform), m_3dEnabled(t_3dEnabled), m_mode(t_mode), m_side(t_side), m_target(t_target), - m_projection(t_projection), - m_modelView(t_modelView), + m_model(t_model), m_lightEnv(t_lightEnv), m_light(t_light), m_lightLut(t_lightLut) { /* do nothing */ } - int RenderContext::getProjectionUniform() { - return m_projectionUniformLocation; - } - - int RenderContext::getModelViewUniform() { - return m_modelViewUniformLocation; + int RenderContext::getModelUniform() { + return m_modelUniformLocation; } bool RenderContext::is3dEnabled() { @@ -50,12 +42,8 @@ namespace m3d { return m_target; } - C3D_Mtx& RenderContext::getProjectionMatrix() { - return m_projection; - } - - C3D_Mtx& RenderContext::getModelViewMatrix() { - return m_modelView; + C3D_Mtx& RenderContext::getModelMatrix() { + return m_model; } C3D_LightEnv& RenderContext::getLightEnvironment() { From 5f8104a651245c4933074c1f3fbfef22ac39865f Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:05:23 +0200 Subject: [PATCH 039/114] Adapt to new RenderContext-class --- m3dialib/source/graphics/mesh.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 2113807..86e012b 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -1,7 +1,6 @@ #include #include #include "m3d/graphics/drawables/mesh.hpp" -#include "m3d/private/graphics.hpp" namespace m3d { Mesh::Mesh() : @@ -201,15 +200,13 @@ namespace m3d { void Mesh::draw(m3d::RenderContext t_context) { if (t_context.getMode() == m3d::RenderContext::Mode::Spatial) { - // Mtx_Translate(&t_context.getProjectionMatrix(), posX, 0.0, , true); - // manipulate modelview matrix - Mtx_Identity(&t_context.getModelViewMatrix()); - Mtx_Translate(&t_context.getModelViewMatrix(), m_posX, m_posY, -1.87 - m_posZ, true); - Mtx_RotateX(&t_context.getModelViewMatrix(), m_rotationX, true); - Mtx_RotateY(&t_context.getModelViewMatrix(), m_rotationY, true); - Mtx_RotateZ(&t_context.getModelViewMatrix(), m_rotationZ, true); - Mtx_Scale(&t_context.getModelViewMatrix(), m_scaleX, m_scaleY, m_scaleZ); + Mtx_Identity(&t_context.getModelMatrix()); + Mtx_Translate(&t_context.getModelMatrix(), m_posX, m_posY, -1.87 - m_posZ, true); + Mtx_RotateX(&t_context.getModelMatrix(), m_rotationX, true); + Mtx_RotateY(&t_context.getModelMatrix(), m_rotationY, true); + Mtx_RotateZ(&t_context.getModelMatrix(), m_rotationZ, true); + Mtx_Scale(&t_context.getModelMatrix(), m_scaleX, m_scaleY, m_scaleZ); // set material C3D_LightEnvMaterial(&t_context.getLightEnvironment(), m_material.getMaterial()); @@ -232,8 +229,7 @@ namespace m3d { BufInfo_Add(bufInfo, m_vbo, sizeof(m3d::Mesh::Polygon::Vertex), 3, 0x210); // update the uniforms - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, t_context.getProjectionUniform(), &t_context.getProjectionMatrix()); - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, t_context.getModelViewUniform(), &t_context.getModelViewMatrix()); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, t_context.getModelUniform(), &t_context.getModelMatrix()); // draw the VBO C3D_DrawArrays(GPU_TRIANGLES, 0, m_vertices.size()); From cb7b6de939c1c8f0707899941ec56e6efbf48843 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:06:42 +0200 Subject: [PATCH 040/114] Adapt to new RenderContext-class and use Cameras --- m3dialib/includes/m3d/graphics/screen.hpp | 19 +++++- m3dialib/source/graphics/screen.cpp | 77 +++++++++++++---------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index e2930ba..025e711 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -98,14 +98,29 @@ namespace m3d { * @brief Clears the screen manually */ void clear(); + + /** + * @brief Sets the camera for the given screen target + * @param t_camera The camera + * @param t_target The target + */ + void setCamera(m3d::Camera& t_camera, m3d::RenderContext::ScreenTarget t_target); + + /** + * @brief Returns the camera of the given screen target + * @param t_target The target + * @return The camera + */ + m3d::Camera& getCamera(m3d::RenderContext::ScreenTarget t_target); private: void prepare(); void prepareLights(m3d::RenderContext::ScreenTarget t_target); /* data */ - int m_projectionUniform, m_modelViewUniform; + int m_projectionUniform, m_modelUniform, m_viewUniform; bool m_3dEnabled; m3d::Color m_clearColorTop, m_clearColorBottom; + m3d::Camera &m_cameraTop, &m_cameraBottom; // rendertargets m3d::RenderTarget *m_targetTopLeft, @@ -126,7 +141,7 @@ namespace m3d { C3D_AttrInfo* m_attributeInfo; // matrices - C3D_Mtx m_projection, m_modelView; + C3D_Mtx m_projection, m_model, m_view; // light C3D_LightEnv m_lightEnvTop, m_lightEnvBottom; diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 50e62e2..a072090 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -6,13 +6,15 @@ namespace m3d { Screen::Screen(bool t_enable3d) : + m_3dEnabled(t_enable3d), m_clearColorTop(m3d::colors::Black), - m_clearColorBottom(m3d::colors::Black) { + m_clearColorBottom(m3d::colors::Black), + m_cameraTop(m3d::priv::graphics::defaultCamera0), + m_cameraBottom(m3d::priv::graphics::defaultCamera1) { gfxInitDefault(); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); C2D_Init(C2D_DEFAULT_MAX_OBJECTS); - gfxSet3D(t_enable3d); - m_3dEnabled = t_enable3d; + gfxSet3D(m_3dEnabled); m_targetTopLeft = new m3d::RenderTarget(400, 240); m_targetTopRight = new m3d::RenderTarget(400, 240); m_targetBottom = new m3d::RenderTarget(320, 240); @@ -29,17 +31,18 @@ namespace m3d { // get location of uniforms used in the vertex shader. m_projectionUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "projection"); - m_modelViewUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "modelView"); + m_modelUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "model"); + m_viewUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "view"); clear(); } Screen::~Screen() { - shaderProgramFree(&m_shader); - DVLB_Free(m_dvlb); C2D_Fini(); C3D_Fini(); gfxExit(); + shaderProgramFree(&m_shader); + DVLB_Free(m_dvlb); delete m_targetTopLeft; delete m_targetTopRight; delete m_targetBottom; @@ -121,6 +124,9 @@ namespace m3d { prepare(); Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioBot, 0.01f, 1000.0f, 0, 2.0f, false); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, m_projectionUniform, &m_projection); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, m_viewUniform, &m_cameraBottom.getViewMatrix()); + if(m_drawStackBottom3d.size() > 0) { C3D_FrameDrawOn(m_targetBottom->getRenderTarget()); prepareLights(m3d::RenderContext::ScreenTarget::Bottom); @@ -128,14 +134,12 @@ namespace m3d { for(const auto &entry : m_drawStackBottom3d) { // for every layer for(const auto &drawable : entry.second) { // draw every object drawable->draw(m3d::RenderContext( - m_projectionUniform, // projectionUniform - m_modelViewUniform, // modelViewUniform + m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Bottom, // target - m_projection, // projection - m_modelView, // model + m_model, // model m_lightEnvBottom, // lightEnv m_lightBottom, // light m_lutPhongBottom // lutPhong @@ -157,17 +161,18 @@ namespace m3d { Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, 0, 2.0f, false); } + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, m_projectionUniform, &m_projection); + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, m_viewUniform, &m_cameraTop.getViewMatrix()); + for (const auto &entry : m_drawStackTop3d) { // for every layer for (const auto &drawable : entry.second) { // draw every object drawable->draw(m3d::RenderContext( - m_projectionUniform, // projectionUniform - m_modelViewUniform, // modelViewUniform + m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Top, // target - m_projection, // projection - m_modelView, // model + m_model, // model m_lightEnvTop, // lightEnv m_lightTop, // light m_lutPhongTop // lutPhong @@ -175,7 +180,7 @@ namespace m3d { } } - if (m_3dEnabled) { + if (m_3dEnabled && osGet3DSliderState() < 0.0f) { C3D_FrameDrawOn(m_targetTopRight->getRenderTarget()); // tilt stereo perspective @@ -185,17 +190,17 @@ namespace m3d { Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, 0, 2.0f, false); } + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, m_projectionUniform, &m_projection); + for (const auto &entry : m_drawStackTop3d) { // for every layer for (const auto &drawable : entry.second) { // draw every object drawable->draw(m3d::RenderContext( - m_projectionUniform, // projectionUniform - m_modelViewUniform, // modelViewUniform + m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode m3d::RenderContext::Stereo3dSide::Right, // side m3d::RenderContext::ScreenTarget::Top, // target - m_projection, // projection - m_modelView, // model + m_model, // model m_lightEnvTop, // lightEnv m_lightTop, // light m_lutPhongTop // lutPhong @@ -219,14 +224,12 @@ namespace m3d { for(const auto &entry : m_drawStackBottom2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object drawable->draw(m3d::RenderContext( - m_projectionUniform, // projectionUniform - m_modelViewUniform, // modelViewUniform + m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Bottom, // target - m_projection, // projection - m_modelView, // model + m_model, // model m_lightEnvBottom, // lightEnv m_lightBottom, // light m_lutPhongBottom // lutPhong @@ -243,14 +246,12 @@ namespace m3d { for(const auto &entry : m_drawStackTop2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object drawable->draw(m3d::RenderContext( - m_projectionUniform, // projectionUniform - m_modelViewUniform, // modelViewUniform + m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode m3d::RenderContext::Stereo3dSide::Left, // side m3d::RenderContext::ScreenTarget::Top, // target - m_projection, // projection - m_modelView, // model + m_model, // model m_lightEnvTop, // lightEnv m_lightTop, // light m_lutPhongTop // lutPhong @@ -258,20 +259,18 @@ namespace m3d { } } - if(m_3dEnabled) { + if(m_3dEnabled && osGet3DSliderState() < 0.0f) { C2D_SceneBegin(m_targetTopRight->getRenderTarget()); for(const auto &entry : m_drawStackTop2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object drawable->draw(m3d::RenderContext( - m_projectionUniform, // projectionUniform - m_modelViewUniform, // modelViewUniform + m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode m3d::RenderContext::Stereo3dSide::Right, // side m3d::RenderContext::ScreenTarget::Top, // target - m_projection, // projection - m_modelView, // model + m_model, // model m_lightEnvTop, // lightEnv m_lightTop, // light m_lutPhongTop // lutPhong @@ -301,6 +300,20 @@ namespace m3d { C2D_TargetClear(m_targetBottom->getRenderTarget(), m_clearColorBottom.getRgba8()); } + void Screen::setCamera(m3d::Camera& t_camera, m3d::RenderContext::ScreenTarget t_target) { + switch (t_target) { + case m3d::RenderContext::ScreenTarget::Top: + m_cameraTop = t_camera; + break; + default: + m_cameraBottom = t_camera; + } + } + + m3d::Camera& Screen::getCamera(m3d::RenderContext::ScreenTarget t_target) { + return (t_target == m3d::RenderContext::ScreenTarget::Top ? m_cameraTop : m_cameraBottom); + } + // private methods void Screen::prepare() { C3D_BindProgram(&m_shader); From 3e35285f699b81153eb0e1ca72c7b4d1102bcf11 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:07:20 +0200 Subject: [PATCH 041/114] Add default cameras --- m3dialib/source/private/graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m3dialib/source/private/graphics.cpp b/m3dialib/source/private/graphics.cpp index 303a5eb..df61729 100644 --- a/m3dialib/source/private/graphics.cpp +++ b/m3dialib/source/private/graphics.cpp @@ -3,7 +3,7 @@ namespace m3d { namespace priv { namespace graphics { - const m3d::Material defaultMaterial; + m3d::Camera defaultCamera0, defaultCamera1; } /* graphics */ } /* priv */ } /* m3d */ From fcb25090e33edeb396062b23fdaf0e8432921222 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:07:29 +0200 Subject: [PATCH 042/114] Fix emission color --- m3dialib/source/graphics/material.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m3dialib/source/graphics/material.cpp b/m3dialib/source/graphics/material.cpp index e9c0458..507fd83 100644 --- a/m3dialib/source/graphics/material.cpp +++ b/m3dialib/source/graphics/material.cpp @@ -129,7 +129,7 @@ namespace m3d { m_material->specular1[2] = (float) m_specular1.getRed() / 255; m_material->emission[0] = (float) m_emission.getBlue() / 255; - m_material->emission[0] = (float) m_emission.getGreen() / 255; - m_material->emission[0] = (float) m_emission.getRed() / 255; + m_material->emission[1] = (float) m_emission.getGreen() / 255; + m_material->emission[2] = (float) m_emission.getRed() / 255; } } /* m3d */ From 69dcedd79982b5647007df1106fca47f6d22e611 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:07:48 +0200 Subject: [PATCH 043/114] Fix includes and declarations --- m3dialib/includes/m3d/private/graphics.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/m3dialib/includes/m3d/private/graphics.hpp b/m3dialib/includes/m3d/private/graphics.hpp index 17b4725..208b49d 100644 --- a/m3dialib/includes/m3d/private/graphics.hpp +++ b/m3dialib/includes/m3d/private/graphics.hpp @@ -2,13 +2,12 @@ #define GRAPHICS_PRIVATE_H #pragma once -#include -#include "m3d/graphics/material.hpp" +#include "m3d/graphics/camera.hpp" namespace m3d { namespace priv { namespace graphics { - extern const m3d::Material defaultMaterial; + extern m3d::Camera defaultCamera0, defaultCamera1; } /* graphics */ } /* priv */ } /* m3d */ From cea156de8cc7239b2d89ec46cde49a089902dfb0 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:08:09 +0200 Subject: [PATCH 044/114] Tidy up includes and enable 3D by default --- m3dialib/includes/m3d/graphics/screen.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index 025e711..7e22fae 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -10,9 +10,10 @@ #include #include #include -#include "renderTarget.hpp" -#include "drawable.hpp" +#include "camera.hpp" #include "color.hpp" +#include "drawable.hpp" +#include "renderTarget.hpp" /** * @brief The general m3d-namespace */ @@ -26,7 +27,7 @@ namespace m3d { * @brief Initializes the m3d::Screen object * @param t_enable3d Whether to enable stereoscopic 3D by default */ - Screen(bool t_enable3d = false); + Screen(bool t_enable3d = true); /** * @brief Destructs the screen object From 21d9756de8eedcfeffb8ed92ae03b5d1a80fcf2c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:09:21 +0200 Subject: [PATCH 045/114] Remove relative movement --- m3dialib/includes/m3d/graphics/camera.hpp | 11 ++++------- m3dialib/source/graphics/camera.cpp | 6 +++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/camera.hpp b/m3dialib/includes/m3d/graphics/camera.hpp index 66699a5..a745d1d 100644 --- a/m3dialib/includes/m3d/graphics/camera.hpp +++ b/m3dialib/includes/m3d/graphics/camera.hpp @@ -131,24 +131,21 @@ namespace m3d { /** * @brief Moves the camera along the X-axis - * @param t_delta The amount to move - * @param t_relative Whether or not to move on the camera's relative axis instead of the absolute axis + * @param t_delta The amount to move */ - void moveX(float t_delta, bool t_relative = true); + void moveX(float t_delta); /** * @brief Moves the camera along the Y-axis * @param t_delta The amount to move - * @param t_relative Whether or not to move on the camera's relative axis instead of the absolute axis */ - void moveY(float t_delta, bool t_relative = true); + void moveY(float t_delta); /** * @brief Moves the camera along the Z-axis * @param t_delta The amount to move - * @param t_relative Whether or not to move on the camera's relative axis instead of the absolute axis */ - void moveZ(float t_delta, bool t_relative = true); + void moveZ(float t_delta); C3D_Mtx& getViewMatrix(); diff --git a/m3dialib/source/graphics/camera.cpp b/m3dialib/source/graphics/camera.cpp index c53aca8..72e38ac 100644 --- a/m3dialib/source/graphics/camera.cpp +++ b/m3dialib/source/graphics/camera.cpp @@ -88,15 +88,15 @@ namespace m3d { m_posZ = t_position.z; } - void Camera::moveX(float t_delta, bool t_relative) { + void Camera::moveX(float t_delta) { m_posX += t_delta; } - void Camera::moveY(float t_delta, bool t_relative) { + void Camera::moveY(float t_delta) { m_posY += t_delta; } - void Camera::moveZ(float t_delta, bool t_relative) { + void Camera::moveZ(float t_delta) { m_posZ += t_delta; } From a7ee4191201fd8c0f942c8ea06c847abeaccbce2 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:24:52 +0200 Subject: [PATCH 046/114] Fix arm11 exception or destruction --- m3dialib/source/graphics/screen.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index a072090..d33bf54 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -46,7 +46,6 @@ namespace m3d { delete m_targetTopLeft; delete m_targetTopRight; delete m_targetBottom; - delete m_attributeInfo; } void Screen::set3d(bool t_enabled) { From 8818d4e48e15d90b32bf0a20f3a35afbc1ed6944 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:25:02 +0200 Subject: [PATCH 047/114] Fix movement --- m3dialib/source/graphics/camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m3dialib/source/graphics/camera.cpp b/m3dialib/source/graphics/camera.cpp index 72e38ac..4bc1977 100644 --- a/m3dialib/source/graphics/camera.cpp +++ b/m3dialib/source/graphics/camera.cpp @@ -105,7 +105,7 @@ namespace m3d { Mtx_RotateX(&m_view, m_rotationX, true); Mtx_RotateY(&m_view, m_rotationY, true); Mtx_RotateZ(&m_view, m_rotationZ, true); - Mtx_Translate(&m_view, -m_posX, m_posY, -m_posZ, true); + Mtx_Translate(&m_view, m_posX, m_posY, m_posZ, true); return m_view; } From 271151fec1a068eda4f181dd0bde45a6d6a104d2 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Sun, 23 Sep 2018 20:31:21 +0200 Subject: [PATCH 048/114] Fix triangulation happening at every frame --- m3dialib/source/graphics/shape.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/m3dialib/source/graphics/shape.cpp b/m3dialib/source/graphics/shape.cpp index f758811..5ee8136 100644 --- a/m3dialib/source/graphics/shape.cpp +++ b/m3dialib/source/graphics/shape.cpp @@ -22,6 +22,7 @@ namespace m3d { } void Shape::draw(m3d::RenderContext t_context) { + if (m_changed) { m_changed = false; std::vector>> polygon; @@ -33,6 +34,7 @@ namespace m3d { polygon.push_back(polyline); m_indices = mapbox::earcut(polygon); + } for (unsigned int i = 0; i < m_indices.size(); i += 3) { C2D_DrawTriangle( From 79b09ff9fab1cb09934975334ed719bf0cee26f6 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 08:26:44 +0200 Subject: [PATCH 049/114] Remove useless include --- m3dialib/includes/m3d/graphics/drawables/sprite.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/m3dialib/includes/m3d/graphics/drawables/sprite.hpp b/m3dialib/includes/m3d/graphics/drawables/sprite.hpp index 1265361..87097eb 100644 --- a/m3dialib/includes/m3d/graphics/drawables/sprite.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/sprite.hpp @@ -12,7 +12,6 @@ #include "m3d/graphics/drawable.hpp" #include "m3d/graphics/texture.hpp" #include "m3d/graphics/vertex.hpp" -#include namespace m3d { /** From 135be0a3d9774b820d2a2e587a2f6b5dc0613d4a Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 10:40:58 +0200 Subject: [PATCH 050/114] Fix deadlocks and arm11 exceptions --- m3dialib/source/audio/music.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/m3dialib/source/audio/music.cpp b/m3dialib/source/audio/music.cpp index 7591dcb..cc27436 100644 --- a/m3dialib/source/audio/music.cpp +++ b/m3dialib/source/audio/music.cpp @@ -26,10 +26,10 @@ namespace m3d { m_thread.initialize([](m3d::Parameter){}, nullptr); m_thread.start(); } else { - m_thread.join(); + if (m_status != m3d::Music::Status::Stopped) { + m_thread.join(); + } } - - delete m_reader; } void Music::setFile(const std::string& t_filename) { @@ -39,19 +39,16 @@ namespace m3d { switch(m_filetype) { case m3d::Music::FileType::Mp3: - delete m_reader; m_reader = new m3d::Playable::Mp3Reader; m_reader->set(m_decoder); break; case m3d::Music::FileType::Wav: - delete m_reader; m_reader = new m3d::Playable::WavReader; m_reader->set(m_decoder); break; default: - delete m_reader; m_reader = nullptr; } } From 923e5e9ab36d62ae708469398a1193041b86cfa6 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 10:41:24 +0200 Subject: [PATCH 051/114] Add ndsp init check --- m3dialib/source/core/applet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m3dialib/source/core/applet.cpp b/m3dialib/source/core/applet.cpp index 9af75f5..7109599 100644 --- a/m3dialib/source/core/applet.cpp +++ b/m3dialib/source/core/applet.cpp @@ -22,7 +22,7 @@ namespace m3d { } Applet::~Applet() { - ndspExit(); + if (m3d::priv::ndsp::initialized) ndspExit(); sdmcExit(); romfsExit(); acExit(); From f7ef967856914a4d24dac16e12f8ebf12a247988 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 10:41:50 +0200 Subject: [PATCH 052/114] Auto-unlock mutex on destruction --- m3dialib/includes/m3d/core/mutex.hpp | 7 +++++++ m3dialib/source/core/mutex.cpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/m3dialib/includes/m3d/core/mutex.hpp b/m3dialib/includes/m3d/core/mutex.hpp index 77825d8..2055ac3 100644 --- a/m3dialib/includes/m3d/core/mutex.hpp +++ b/m3dialib/includes/m3d/core/mutex.hpp @@ -19,6 +19,13 @@ namespace m3d { */ Mutex(); + /** + * @brief Destructor + * + * This automatically unlocks the mutex + */ + ~Mutex(); + /** * @brief Locks the mutex */ diff --git a/m3dialib/source/core/mutex.cpp b/m3dialib/source/core/mutex.cpp index 1a63024..1435f22 100644 --- a/m3dialib/source/core/mutex.cpp +++ b/m3dialib/source/core/mutex.cpp @@ -5,6 +5,10 @@ namespace m3d { RecursiveLock_Init(&m_mutex); } + Mutex::~Mutex() { + RecursiveLock_Unlock(&m_mutex); + } + void Mutex::lock() { RecursiveLock_Lock(&m_mutex); } From 1d346b878ef64a58ed20929e7cac5674e293afdd Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 10:54:47 +0200 Subject: [PATCH 053/114] Improve error API --- m3dialib/includes/m3d/core/error.hpp | 7 +++---- m3dialib/source/core/error.cpp | 7 ++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/m3dialib/includes/m3d/core/error.hpp b/m3dialib/includes/m3d/core/error.hpp index 7883a34..156fe23 100644 --- a/m3dialib/includes/m3d/core/error.hpp +++ b/m3dialib/includes/m3d/core/error.hpp @@ -20,8 +20,7 @@ namespace m3d { */ enum class ErrorType { Text, ///< Displays text passed to this applet - Eula, ///< Displays the EULA - WordWrap ///< Displays the custom error message passed to this applet with automatic line wrapping + WordWrap ///< Displays the custom error message passed to this applet with automatic line wrapping }; /** @@ -74,7 +73,7 @@ namespace m3d { * @brief Sets whether to allow the use of the home button * @param t_allowed Whether the use of the home button is allowed or not */ - void setAllowHomebutton(bool t_allowed); + void allowHomebutton(bool t_allowed); /** * @brief Returns whether the use of the home button is allowed @@ -86,7 +85,7 @@ namespace m3d { * @brief Sets whether to show an error code * @param t_show Whether to show an error code or not */ - void setShowErrorCode(bool t_show); + void showErrorCode(bool t_show); /** * @brief Returns whether to show an error code diff --git a/m3dialib/source/core/error.cpp b/m3dialib/source/core/error.cpp index 66750ac..8f309cd 100644 --- a/m3dialib/source/core/error.cpp +++ b/m3dialib/source/core/error.cpp @@ -16,9 +16,6 @@ namespace m3d { case m3d::Error::ErrorType::Text: type = ERROR_TEXT; break; - case m3d::Error::ErrorType::Eula: - type = ERROR_EULA; - break; case m3d::Error::ErrorType::WordWrap: type = ERROR_TEXT_WORD_WRAP; break; @@ -62,7 +59,7 @@ namespace m3d { return m_text; } - void Error::setAllowHomebutton(bool t_allowed) { + void Error::allowHomebutton(bool t_allowed) { m_allowHomeButton = t_allowed; } @@ -70,7 +67,7 @@ namespace m3d { return m_allowHomeButton; } - void Error::setShowErrorCode(bool t_show) { + void Error::showErrorCode(bool t_show) { m_showErrorCode = t_show; } From b2a9e7c4a667e052aa5865d007e609e045803a23 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 12:30:54 +0200 Subject: [PATCH 054/114] Change rotationX/Y/Z to pitch/yaw/roll --- m3dialib/includes/m3d/graphics/camera.hpp | 32 +++++++++++++---------- m3dialib/source/graphics/camera.cpp | 26 +++++++++--------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/camera.hpp b/m3dialib/includes/m3d/graphics/camera.hpp index a745d1d..89e424c 100644 --- a/m3dialib/includes/m3d/graphics/camera.hpp +++ b/m3dialib/includes/m3d/graphics/camera.hpp @@ -21,63 +21,63 @@ namespace m3d { * @brief Sets the rotation on the X-axis * @param t_rotation The absolute rotation */ - void setRotationX(float t_rotation); + void setPitch(float t_rotation); /** * @brief Returns the rotation on the X-axis * @return The absolute rotation */ - float getRotationX(); + float getPitch(); /** * @brief Sets the rotation on the Y-axis * @param t_rotation The absolute rotation */ - void setRotationY(float t_rotation); + void setYaw(float t_rotation); /** * @brief Returns the rotation on the Y-axis * @return The absolute rotation */ - float getRotationY(); + float getYaw(); /** * @brief Sets the rotation on the Z-axis * @param t_rotation The absolute rotation */ - void setRotationZ(float t_rotation); + void setRoll(float t_rotation); /** * @brief Returns the rotation on the /-axis * @return The absolute rotation */ - float getRotationZ(); + float getRoll(); /** * @brief Sets the rotation of the camera - * @param t_rotationX The rotation on the X-axis - * @param t_rotationY The rotation on the Y-axis - * @param t_rotationZ The rotation on the Z-axis + * @param t_pitch The rotation on the X-axis + * @param t_yaw The rotation on the Y-axis + * @param t_roll The rotation on the Z-axis */ - void setRotation(float t_rotationX, float t_rotationY, float t_rotationZ); + void setRotation(float t_pitch, float t_yaw, float t_roll); /** * @brief Rotates the camera a given amount on the X-axis * @param t_delta The amount to rotate */ - void rotateX(float t_delta); + void rotatePitch(float t_delta); /** * @brief Rotates the camera a given amount on the Y-axis * @param t_delta The amount to rotate */ - void rotateY(float t_delta); + void rotateYaw(float t_delta); /** - * @brief Rotates the camera a given amount on the /-axis + * @brief Rotates the camera a given amount on the Z-axis * @param t_delta The amount to rotate */ - void rotateZ(float t_delta); + void rotateRoll(float t_delta); /** * @brief Sets the position on the X-axis @@ -147,6 +147,10 @@ namespace m3d { */ void moveZ(float t_delta); + void moveSideways(float t_delta); + + void moveForward(float t_delta); + C3D_Mtx& getViewMatrix(); private: diff --git a/m3dialib/source/graphics/camera.cpp b/m3dialib/source/graphics/camera.cpp index 4bc1977..8c7d6c6 100644 --- a/m3dialib/source/graphics/camera.cpp +++ b/m3dialib/source/graphics/camera.cpp @@ -10,45 +10,45 @@ namespace m3d { m_rotationY(0.0f), m_rotationZ(0.0f) { /* do nothing */ } - void Camera::setRotationX(float t_rotation) { + void Camera::setPitch(float t_rotation) { m_rotationX = t_rotation; } - float Camera::getRotationX() { + float Camera::getPitch() { return m_rotationX; } - void Camera::setRotationY(float t_rotation) { + void Camera::setYaw(float t_rotation) { m_rotationY = t_rotation; } - float Camera::getRotationY() { + float Camera::getYaw() { return m_rotationY; } - void Camera::setRotationZ(float t_rotation) { + void Camera::setRoll(float t_rotation) { m_rotationZ = t_rotation; } - float Camera::getRotationZ() { + float Camera::getRoll() { return m_rotationZ; } - void Camera::setRotation(float t_rotationX, float t_rotationY, float t_rotationZ) { - m_rotationX = t_rotationX; - m_rotationY = t_rotationY; - m_rotationZ = t_rotationZ; + void Camera::setRotation(float t_pitch, float t_yaw, float t_roll) { + m_rotationX = t_pitch; + m_rotationY = t_yaw; + m_rotationZ = t_roll; } - void Camera::rotateX(float t_delta) { + void Camera::rotatePitch(float t_delta) { m_rotationX += t_delta; } - void Camera::rotateY(float t_delta) { + void Camera::rotateYaw(float t_delta) { m_rotationY += t_delta; } - void Camera::rotateZ(float t_delta) { + void Camera::rotateRoll(float t_delta) { m_rotationZ += t_delta; } From 25b11e7e50df467df31296aefabb884613fd232a Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 12:35:06 +0200 Subject: [PATCH 055/114] Don't use camera references --- m3dialib/includes/m3d/graphics/screen.hpp | 2 +- m3dialib/source/graphics/screen.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index 7e22fae..b732d51 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -105,7 +105,7 @@ namespace m3d { * @param t_camera The camera * @param t_target The target */ - void setCamera(m3d::Camera& t_camera, m3d::RenderContext::ScreenTarget t_target); + void setCamera(m3d::Camera t_camera, m3d::RenderContext::ScreenTarget t_target); /** * @brief Returns the camera of the given screen target diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index d33bf54..9257b34 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -299,7 +299,7 @@ namespace m3d { C2D_TargetClear(m_targetBottom->getRenderTarget(), m_clearColorBottom.getRgba8()); } - void Screen::setCamera(m3d::Camera& t_camera, m3d::RenderContext::ScreenTarget t_target) { + void Screen::setCamera(m3d::Camera t_camera, m3d::RenderContext::ScreenTarget t_target) { switch (t_target) { case m3d::RenderContext::ScreenTarget::Top: m_cameraTop = t_camera; From 772b00580c1eaedd30ca1802d94ce35d0b5c7849 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 12:58:06 +0200 Subject: [PATCH 056/114] Improve color API --- m3dialib/includes/m3d/graphics/color.hpp | 80 ++++++------------------ m3dialib/source/graphics/color.cpp | 12 ++-- 2 files changed, 23 insertions(+), 69 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/color.hpp b/m3dialib/includes/m3d/graphics/color.hpp index eefad4c..7f7e292 100644 --- a/m3dialib/includes/m3d/graphics/color.hpp +++ b/m3dialib/includes/m3d/graphics/color.hpp @@ -9,63 +9,7 @@ #include #include <3ds.h> -/** - * @brief Creates a new RGBA8 color - * @param r the red component of the color to create - * @param g the green component of the color to create - * @param b the blue component of the color to create - * @param a the alpha component of the color to create - */ -#define RGBA8(r, g, b, a) ((((a)&0xFF)<<24) | (((b)&0xFF)<<16) | (((g)&0xFF)<<8) | (((r)&0xFF)<<0)) - -/** - * @brief Gets the red value of a RGBA8 color - * @param c The RGBA8 color - * @return The red value - */ -#define RGBA8_GET_R(c) (((c) >> 0) & 0xFF) - -/** - * @brief Gets the green value of a RGBA8 color - * @param c The RGBA8 color - * @return The green value - */ -#define RGBA8_GET_G(c) (((c) >> 8) & 0xFF) - -/** - * @brief Gets the blue value of a RGBA8 color - * @param c The RGBA8 color - * @return The blue value - */ -#define RGBA8_GET_B(c) (((c) >> 16) & 0xFF) - -/** - * @brief Gets the alpha value of a RGBA8 color - * @param c The RGBA8 color - * @return The alpha value - */ -#define RGBA8_GET_A(c) (((c) >> 24) & 0xFF) - namespace m3d { - /** - * @brief Namespace used for pre-defined colors - */ - namespace colors { - /** - * @brief Pre-defined colors - */ - enum Color { - Red = RGBA8(255, 0, 0, 255), ///< FF0000 - Green = RGBA8(0, 255, 0, 255), ///< 00FF00 - Blue = RGBA8(0, 0, 255, 255), ///< 0000FF - Yellow = RGBA8(255, 255, 0, 255), ///< FFFF00 - Magenta = RGBA8(255, 0, 255, 255), ///< FF00FF - Cyan = RGBA8(0, 255, 255, 255), ///< 00FFFF - White = RGBA8(255, 255, 255, 255), ///< FFFFFF - Black = RGBA8(0, 0, 0, 255) ///< 000000 - }; - } /* colors */ - /** * @brief The color class */ @@ -76,12 +20,6 @@ namespace m3d { */ Color(); - /** - * @brief Creates a color from an m3d::colors::Color enum - * @param t_color The color to use - */ - Color(m3d::colors::Color t_color); - /** * @brief Creates a color using a red, green and blue value * @param t_r The red value @@ -179,6 +117,24 @@ namespace m3d { */ u32 getRgba8(); + /** + * @brief Returns the color as an RGB8 integer + * @return The color in RGB8 format + */ + u32 getRgb8(); + + /** + * @brief Converts four color components to RGBA8 format + * @param t_red The red component + * @param t_green The green component + * @param t_blue The blue component + * @param t_alpha The alpha component + * @return The color in RGBA8 format + */ + static inline u32 rgba8(int t_red, int t_green, int t_blue, int t_alpha = 255) { + return ((((t_alpha)&0xFF)<<24) | (((t_blue)&0xFF)<<16) | (((t_green)&0xFF)<<8) | (((t_red)&0xFF)<<0)); + } + private: /* data */ uint8_t m_red, m_green, m_blue, m_alpha; diff --git a/m3dialib/source/graphics/color.cpp b/m3dialib/source/graphics/color.cpp index cc3d77d..f916ff9 100644 --- a/m3dialib/source/graphics/color.cpp +++ b/m3dialib/source/graphics/color.cpp @@ -7,12 +7,6 @@ namespace m3d { m_blue(0), m_alpha(255) { /* do nothing */ } - Color::Color(m3d::colors::Color t_color) : - m_red(RGBA8_GET_R(t_color)), - m_green(RGBA8_GET_G(t_color)), - m_blue(RGBA8_GET_B(t_color)), - m_alpha(RGBA8_GET_A(t_color)) { /* do nothing */ } - Color::Color(uint8_t t_r, uint8_t t_g, uint8_t t_b) : m_red(t_r), m_green(t_g), @@ -78,6 +72,10 @@ namespace m3d { } u32 Color::getRgba8() { - return RGBA8(m_red, m_green, m_blue, m_alpha); + return ((((m_alpha)&0xFF)<<24) | (((m_blue)&0xFF)<<16) | (((m_green)&0xFF)<<8) | (((m_red)&0xFF)<<0)); + } + + u32 Color::getRgb8() { + return ((((m_blue)&0xFF)<<16) | (((m_green)&0xFF)<<8) | (((m_red)&0xFF)<<0)); } } /* m3d */ From 2093c84c4b0328c93ebef26aac1fdae4071e0bd8 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 12:58:26 +0200 Subject: [PATCH 057/114] Adapt to new color API --- m3dialib/source/graphics/renderTarget.cpp | 2 +- m3dialib/source/graphics/screen.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/m3dialib/source/graphics/renderTarget.cpp b/m3dialib/source/graphics/renderTarget.cpp index 57d8346..6040b38 100644 --- a/m3dialib/source/graphics/renderTarget.cpp +++ b/m3dialib/source/graphics/renderTarget.cpp @@ -5,7 +5,7 @@ namespace m3d { RenderTarget::RenderTarget(int t_width, int t_height) : m_width(t_width), m_height(t_height), - m_clearColor(RGBA8(0, 0, 0, 255)) { + m_clearColor(m3d::Color::rgba8(0, 0, 0, 255)) { m_target = C3D_RenderTargetCreate(t_height, t_width, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); } diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 9257b34..d7b343a 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -7,8 +7,8 @@ namespace m3d { Screen::Screen(bool t_enable3d) : m_3dEnabled(t_enable3d), - m_clearColorTop(m3d::colors::Black), - m_clearColorBottom(m3d::colors::Black), + m_clearColorTop(m3d::Color(0, 0, 0)), + m_clearColorBottom(m3d::Color(0, 0, 0)), m_cameraTop(m3d::priv::graphics::defaultCamera0), m_cameraBottom(m3d::priv::graphics::defaultCamera1) { gfxInitDefault(); From 37650364cd8377581f4c083372dafc4d88083d5b Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 17:30:36 +0200 Subject: [PATCH 058/114] Fix stereoscopic 3D --- m3dialib/source/graphics/screen.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index d7b343a..6c6ef6d 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -155,7 +155,7 @@ namespace m3d { // tilt stereo perspective if (m_3dEnabled) { - Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, osGet3DSliderState() / 3.0f, 2.0f, false); + Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, -(osGet3DSliderState() / 3.0f), 2.0f, false); } else { Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, 0, 2.0f, false); } @@ -179,12 +179,12 @@ namespace m3d { } } - if (m_3dEnabled && osGet3DSliderState() < 0.0f) { + if (m_3dEnabled && osGet3DSliderState() > 0.0f) { C3D_FrameDrawOn(m_targetTopRight->getRenderTarget()); // tilt stereo perspective if (m_3dEnabled) { - Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, -(osGet3DSliderState() / 3.0f), 2.0f, false); + Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, osGet3DSliderState() / 3.0f, 2.0f, false); } else { Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioTop, 0.01f, 1000.0f, 0, 2.0f, false); } @@ -258,7 +258,7 @@ namespace m3d { } } - if(m_3dEnabled && osGet3DSliderState() < 0.0f) { + if(m_3dEnabled && osGet3DSliderState() > 0.0f) { C2D_SceneBegin(m_targetTopRight->getRenderTarget()); for(const auto &entry : m_drawStackTop2d) { // for every layer From 1488efe201d94c404bf109ccb429b9f7cf47c21a Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 17:30:44 +0200 Subject: [PATCH 059/114] Add documentation --- m3dialib/includes/m3d/graphics/camera.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/camera.hpp b/m3dialib/includes/m3d/graphics/camera.hpp index 89e424c..6d0d0b1 100644 --- a/m3dialib/includes/m3d/graphics/camera.hpp +++ b/m3dialib/includes/m3d/graphics/camera.hpp @@ -147,10 +147,10 @@ namespace m3d { */ void moveZ(float t_delta); - void moveSideways(float t_delta); - - void moveForward(float t_delta); - + /** + * @brief Returns a reference to the view matrix of the camera and applies all calculations to it + * @return The view matrix + */ C3D_Mtx& getViewMatrix(); private: From 131f4497401695f641f400663bf2ab76450632ac Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 18:04:09 +0200 Subject: [PATCH 060/114] Add support for custom shading functions --- m3dialib/includes/m3d/graphics/screen.hpp | 25 ++++++- m3dialib/source/graphics/screen.cpp | 88 ++++++++++++++++++----- 2 files changed, 94 insertions(+), 19 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index b732d51..5e8b911 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -8,6 +8,7 @@ #pragma once #include #include +#include #include #include #include "camera.hpp" @@ -68,6 +69,17 @@ namespace m3d { */ void drawTop(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode = m3d::RenderContext::Mode::Flat, int t_layer = 0); + /** + * @brief Draws something on the top screen + * @param t_object The object that should be drawn + * @param t_shadingFunction A function to call right before drawing + * @param t_mode The drawing-mode + * @param t_layer The z-inex the object should be drawn at + * + * @note `t_shadingFunction` allows you to bind your own shaders and to execute your own code. It get's called just before the `draw` method of your drawable gets executed and should return `true` on success. If it returns `false`, the drawable will not be drawn. + */ + void drawTop(m3d::Drawable& t_object, std::function t_shadingFunction, m3d::RenderContext::Mode t_mode = m3d::RenderContext::Mode::Flat, int t_layer = 0); + /** * @brief Draws something on the bottom screen * @param t_object The object that should be drawn @@ -76,6 +88,17 @@ namespace m3d { */ void drawBottom(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode = m3d::RenderContext::Mode::Flat, int t_layer = 0); + /** + * @brief Draws something on the bottom screen + * @param t_object The object that should be drawn + * @param t_shadingFunction A function to call right before drawing + * @param t_mode The drawing-mode + * @param t_layer The z-inex the object should be drawn at + * + * @note `t_shadingFunction` allows you to bind your own shaders and to execute your own code. It get's called just before the `draw` method of your drawable gets executed and should return `true` on success. If it returns `false`, the drawable will not be drawn. + */ + void drawBottom(m3d::Drawable& t_object, std::function t_shadingFunction, m3d::RenderContext::Mode t_mode = m3d::RenderContext::Mode::Flat, int t_layer = 0); + /** * @brief Renders the current screen * @param t_clear Whether or not to clear the screens in between frames @@ -129,7 +152,7 @@ namespace m3d { *m_targetBottom; // draw stacks - std::map, std::less> m_drawStackTop2d, + std::map>>, std::less> m_drawStackTop2d, m_drawStackTop3d, m_drawStackBottom2d, m_drawStackBottom3d; diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 6c6ef6d..a3b65b7 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -71,18 +71,38 @@ namespace m3d { void Screen::drawTop(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode, int t_layer) { if (t_mode == m3d::RenderContext::Mode::Flat) { if(m_drawStackTop2d.count(t_layer) > 0) { - m_drawStackTop2d[t_layer].insert(m_drawStackTop2d[t_layer].end(), &t_object); + m_drawStackTop2d[t_layer].insert(m_drawStackTop2d[t_layer].end(), std::make_pair(&t_object, [](){return true;})); } else { - std::vector newStack; - newStack.push_back(&t_object); + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, [](){return true;})); m_drawStackTop2d.insert(std::make_pair(t_layer, newStack)); } } else { if(m_drawStackTop3d.count(t_layer) > 0) { - m_drawStackTop3d[t_layer].insert(m_drawStackTop3d[t_layer].end(), &t_object); + m_drawStackTop3d[t_layer].insert(m_drawStackTop3d[t_layer].end(), std::make_pair(&t_object, [](){return true;})); } else { - std::vector newStack; - newStack.push_back(&t_object); + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, [](){return true;})); + m_drawStackTop3d.insert(std::make_pair(t_layer, newStack)); + } + } + } + + void Screen::drawTop(m3d::Drawable& t_object, std::function t_shadingFunction, m3d::RenderContext::Mode t_mode, int t_layer) { + if (t_mode == m3d::RenderContext::Mode::Flat) { + if(m_drawStackTop2d.count(t_layer) > 0) { + m_drawStackTop2d[t_layer].insert(m_drawStackTop2d[t_layer].end(), std::make_pair(&t_object, t_shadingFunction)); + } else { + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, t_shadingFunction)); + m_drawStackTop2d.insert(std::make_pair(t_layer, newStack)); + } + } else { + if(m_drawStackTop3d.count(t_layer) > 0) { + m_drawStackTop3d[t_layer].insert(m_drawStackTop3d[t_layer].end(), std::make_pair(&t_object, t_shadingFunction)); + } else { + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, t_shadingFunction)); m_drawStackTop3d.insert(std::make_pair(t_layer, newStack)); } } @@ -91,18 +111,38 @@ namespace m3d { void Screen::drawBottom(m3d::Drawable& t_object, m3d::RenderContext::Mode t_mode, int t_layer) { if (t_mode == m3d::RenderContext::Mode::Flat) { if(m_drawStackBottom2d.count(t_layer) > 0) { - m_drawStackBottom2d[t_layer].insert(m_drawStackBottom2d[t_layer].end(), &t_object); + m_drawStackBottom2d[t_layer].insert(m_drawStackBottom2d[t_layer].end(), std::make_pair(&t_object, [](){return true;})); + } else { + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, [](){return true;})); + m_drawStackBottom2d.insert(std::make_pair(t_layer, newStack)); + } + } else { + if(m_drawStackBottom3d.count(t_layer) > 0) { + m_drawStackBottom3d[t_layer].insert(m_drawStackBottom3d[t_layer].end(), std::make_pair(&t_object, [](){return true;})); + } else { + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, [](){return true;})); + m_drawStackBottom3d.insert(std::make_pair(t_layer, newStack)); + } + } + } + + void Screen::drawBottom(m3d::Drawable& t_object, std::function t_shadingFunction, m3d::RenderContext::Mode t_mode, int t_layer) { + if (t_mode == m3d::RenderContext::Mode::Flat) { + if(m_drawStackBottom2d.count(t_layer) > 0) { + m_drawStackBottom2d[t_layer].insert(m_drawStackBottom2d[t_layer].end(), std::make_pair(&t_object, t_shadingFunction)); } else { - std::vector newStack; - newStack.push_back(&t_object); + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, t_shadingFunction)); m_drawStackBottom2d.insert(std::make_pair(t_layer, newStack)); } } else { if(m_drawStackBottom3d.count(t_layer) > 0) { - m_drawStackBottom3d[t_layer].insert(m_drawStackBottom3d [t_layer].end(), &t_object); + m_drawStackBottom3d[t_layer].insert(m_drawStackBottom3d[t_layer].end(), std::make_pair(&t_object, t_shadingFunction)); } else { - std::vector newStack; - newStack.push_back(&t_object); + std::vector>> newStack; + newStack.push_back(std::make_pair(&t_object, t_shadingFunction)); m_drawStackBottom3d.insert(std::make_pair(t_layer, newStack)); } } @@ -132,7 +172,8 @@ namespace m3d { for(const auto &entry : m_drawStackBottom3d) { // for every layer for(const auto &drawable : entry.second) { // draw every object - drawable->draw(m3d::RenderContext( + if (drawable.second()) { + drawable.first->draw(m3d::RenderContext( m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode @@ -143,6 +184,7 @@ namespace m3d { m_lightBottom, // light m_lutPhongBottom // lutPhong )); + } } } @@ -165,7 +207,8 @@ namespace m3d { for (const auto &entry : m_drawStackTop3d) { // for every layer for (const auto &drawable : entry.second) { // draw every object - drawable->draw(m3d::RenderContext( + if (drawable.second()) { + drawable.first->draw(m3d::RenderContext( m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode @@ -176,6 +219,7 @@ namespace m3d { m_lightTop, // light m_lutPhongTop // lutPhong )); + } } } @@ -193,7 +237,8 @@ namespace m3d { for (const auto &entry : m_drawStackTop3d) { // for every layer for (const auto &drawable : entry.second) { // draw every object - drawable->draw(m3d::RenderContext( + if (drawable.second()) { + drawable.first->draw(m3d::RenderContext( m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Spatial, // mode @@ -204,6 +249,7 @@ namespace m3d { m_lightTop, // light m_lutPhongTop // lutPhong )); + } } } } @@ -222,7 +268,8 @@ namespace m3d { for(const auto &entry : m_drawStackBottom2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object - drawable->draw(m3d::RenderContext( + if (drawable.second()) { + drawable.first->draw(m3d::RenderContext( m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode @@ -233,6 +280,7 @@ namespace m3d { m_lightBottom, // light m_lutPhongBottom // lutPhong )); + } } } @@ -244,7 +292,8 @@ namespace m3d { for(const auto &entry : m_drawStackTop2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object - drawable->draw(m3d::RenderContext( + if (drawable.second()) { + drawable.first->draw(m3d::RenderContext( m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode @@ -255,6 +304,7 @@ namespace m3d { m_lightTop, // light m_lutPhongTop // lutPhong )); + } } } @@ -263,7 +313,8 @@ namespace m3d { for(const auto &entry : m_drawStackTop2d) { // for every layer for(const auto &drawable : entry.second) { // draw every object - drawable->draw(m3d::RenderContext( + if (drawable.second()) { + drawable.first->draw(m3d::RenderContext( m_modelUniform, // modelUniform m_3dEnabled, // 3dEnabled m3d::RenderContext::Mode::Flat, // mode @@ -274,6 +325,7 @@ namespace m3d { m_lightTop, // light m_lutPhongTop // lutPhong )); + } } } } From 19a844d3c798cfa54dd0449b4a4030411c67c491 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:20:11 +0200 Subject: [PATCH 061/114] Use ints instead of floats --- m3dialib/includes/m3d/graphics/material.hpp | 10 +++++----- m3dialib/source/graphics/material.cpp | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/material.hpp b/m3dialib/includes/m3d/graphics/material.hpp index 5870180..42b8d57 100644 --- a/m3dialib/includes/m3d/graphics/material.hpp +++ b/m3dialib/includes/m3d/graphics/material.hpp @@ -61,7 +61,7 @@ namespace m3d { * @param t_g The green component * @param t_b The blue component */ - void setAmbient(float t_r, float t_g, float t_b); + void setAmbient(int t_r, int t_g, int t_b); /** * @brief Returns the ambient-color of the material @@ -81,7 +81,7 @@ namespace m3d { * @param t_g The green component * @param t_b The blue component */ - void setDiffuse(float t_r, float t_g, float t_b); + void setDiffuse(int t_r, int t_g, int t_b); /** * @brief Returns the diffuse-color of the material @@ -101,7 +101,7 @@ namespace m3d { * @param t_g The green component * @param t_b The blue component */ - void setSpecular0(float t_r, float t_g, float t_b); + void setSpecular0(int t_r, int t_g, int t_b); /** * @brief Returns the specular0-color of the material @@ -121,7 +121,7 @@ namespace m3d { * @param t_g The green component * @param t_b The blue component */ - void setSpecular1(float t_r, float t_g, float t_b); + void setSpecular1(int t_r, int t_g, int t_b); /** * @brief Returns the specular1-color of the material @@ -141,7 +141,7 @@ namespace m3d { * @param t_g The green component * @param t_b The blue component */ - void setEmission(float t_r, float t_g, float t_b); + void setEmission(int t_r, int t_g, int t_b); /** * @brief Returns the emission-color of the material diff --git a/m3dialib/source/graphics/material.cpp b/m3dialib/source/graphics/material.cpp index 507fd83..2ce5087 100644 --- a/m3dialib/source/graphics/material.cpp +++ b/m3dialib/source/graphics/material.cpp @@ -40,8 +40,8 @@ namespace m3d { updateMaterial(); } - void Material::setAmbient(float t_r, float t_g, float t_b) { - m_ambient = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + void Material::setAmbient(int t_r, int t_g, int t_b) { + m_ambient = m3d::Color(t_r, t_g, t_b); updateMaterial(); } @@ -54,8 +54,8 @@ namespace m3d { updateMaterial(); } - void Material::setDiffuse(float t_r, float t_g, float t_b) { - m_diffuse = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + void Material::setDiffuse(int t_r, int t_g, int t_b) { + m_diffuse = m3d::Color(t_r, t_g, t_b); updateMaterial(); } @@ -68,8 +68,8 @@ namespace m3d { updateMaterial(); } - void Material::setSpecular0(float t_r, float t_g, float t_b) { - m_specular0 = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + void Material::setSpecular0(int t_r, int t_g, int t_b) { + m_specular0 = m3d::Color(t_r, t_g, t_b); updateMaterial(); } @@ -82,8 +82,8 @@ namespace m3d { updateMaterial(); } - void Material::setSpecular1(float t_r, float t_g, float t_b) { - m_specular1 = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + void Material::setSpecular1(int t_r, int t_g, int t_b) { + m_specular1 = m3d::Color(t_r, t_g, t_b); updateMaterial(); } @@ -96,8 +96,8 @@ namespace m3d { updateMaterial(); } - void Material::setEmission(float t_r, float t_g, float t_b) { - m_emission = m3d::Color(t_r * 255, t_g * 255, t_b * 255); + void Material::setEmission(int t_r, int t_g, int t_b) { + m_emission = m3d::Color(t_r, t_g, t_b); updateMaterial(); } From fe72f23edb362fbecd049772ed530bbd607ce521 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:20:34 +0200 Subject: [PATCH 062/114] Use two texture coordinates --- m3dialib/source/graphics/render3d.v.pica | 2 ++ 1 file changed, 2 insertions(+) diff --git a/m3dialib/source/graphics/render3d.v.pica b/m3dialib/source/graphics/render3d.v.pica index ba21a4b..d9b459d 100644 --- a/m3dialib/source/graphics/render3d.v.pica +++ b/m3dialib/source/graphics/render3d.v.pica @@ -14,6 +14,7 @@ ; Outputs .out outpos position .out outtc0 texcoord0 +.out outtc1 texcoord1 .out outclr color .out outview view .out outnq normalquat @@ -54,6 +55,7 @@ ; outtex = intex mov outtc0, intex + mov outtc1, intex ; Transform the normal vector with the modelView matrix ; TODO: use a separate normal matrix that is the transpose of the inverse of modelView From e4913a518078eea8a39d5fbcafa66c4c51b3b41e Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:20:50 +0200 Subject: [PATCH 063/114] Use two texture environments --- m3dialib/source/graphics/renderContext.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/m3dialib/source/graphics/renderContext.cpp b/m3dialib/source/graphics/renderContext.cpp index 9999f32..8f94fd0 100644 --- a/m3dialib/source/graphics/renderContext.cpp +++ b/m3dialib/source/graphics/renderContext.cpp @@ -63,10 +63,16 @@ namespace m3d { switch (t_enable) { case true: + // ambient/diffuse env = C3D_GetTexEnv(0); C3D_TexEnvInit(env); - C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); - C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); + C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_FRAGMENT_PRIMARY_COLOR, GPU_PRIMARY_COLOR); + C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE); + + // specular + env = C3D_GetTexEnv(1); + C3D_TexEnvInit(env); + C3D_TexEnvSrc(env, C3D_Both, GPU_PREVIOUS, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); break; default: From 81684ac9ab80df22029fe6364cc072cb3620c47f Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:21:10 +0200 Subject: [PATCH 064/114] Disable lights (for now) --- m3dialib/source/graphics/screen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index a3b65b7..dd40b1d 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -168,7 +168,7 @@ namespace m3d { if(m_drawStackBottom3d.size() > 0) { C3D_FrameDrawOn(m_targetBottom->getRenderTarget()); - prepareLights(m3d::RenderContext::ScreenTarget::Bottom); + // prepareLights(m3d::RenderContext::ScreenTarget::Bottom); for(const auto &entry : m_drawStackBottom3d) { // for every layer for(const auto &drawable : entry.second) { // draw every object @@ -193,7 +193,7 @@ namespace m3d { if (m_drawStackTop3d.size() > 0) { C3D_FrameDrawOn(m_targetTopLeft->getRenderTarget()); - prepareLights(m3d::RenderContext::ScreenTarget::Top); + // prepareLights(m3d::RenderContext::ScreenTarget::Top); // tilt stereo perspective if (m_3dEnabled) { From b505167c1bf208db1598c21322440be9999aa0fe Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:21:41 +0200 Subject: [PATCH 065/114] Add option to reset the material on texture bind/unbind --- m3dialib/includes/m3d/graphics/drawables/mesh.hpp | 8 +++++--- m3dialib/source/graphics/mesh.cpp | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index 6c784c4..d4fff95 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -288,14 +288,16 @@ namespace m3d { /** * @brief Binds a texture to the mesh - * @param t_texture The texture to bind + * @param t_texture The texture to bind + * @param t_resetMaterial Whether or not to reset the material so that it won't interfere with the texture */ - void bindTexture(m3d::Texture& t_texture); + void bindTexture(m3d::Texture& t_texture, bool t_resetMaterial = true); /** * @brief Unbinds the bound texture (disables texture using) + * @param t_resetMaterial Whether or not to reset the material to the default material */ - void unbindTexture(); + void unbindTexture(bool t_resetMaterial = true); /** * @brief Returns a reference to the current texture diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 86e012b..8671f2d 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -185,13 +185,23 @@ namespace m3d { return m_material; } - void Mesh::bindTexture(m3d::Texture& t_texture) { + void Mesh::bindTexture(m3d::Texture& t_texture, bool t_resetMaterial) { m_useTexture = true; m_texture = t_texture; + + if (t_resetMaterial) { + m_material.setAmbient(125, 125, 125); + m_material.setDiffuse(255, 255, 255); + m_material.setEmission(255, 0, 0); + } } - void Mesh::unbindTexture() { + void Mesh::unbindTexture(bool t_resetMaterial) { m_useTexture = false; + + if (t_resetMaterial) { + m_material = m3d::Material(); + } } m3d::Texture& Mesh::getTexture() { From abcbbb07accb6e00469db2cdb8602ea48da30fb1 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:52:07 +0200 Subject: [PATCH 066/114] Add destructor --- m3dialib/includes/m3d/graphics/drawables/mesh.hpp | 6 ++++++ m3dialib/source/graphics/mesh.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index d4fff95..c843c37 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -66,11 +66,17 @@ namespace m3d { /* data */ m3d::Mesh::Polygon::Vertex* m_vertices; }; + /** * @brief Initializes the mesh */ Mesh(); + /** + * @brief Destructor + */ + ~Mesh(); + /** * @brief Adds a polygon to the mesh * @param t_polygon The polygon to add diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 8671f2d..0451a13 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -15,6 +15,10 @@ namespace m3d { m_scaleZ(1.0f), m_useTexture(false) { /* do nothing */ } + Mesh::~Mesh() { + linearFree(m_vbo); + } + void Mesh::addPolygon(m3d::Mesh::Polygon t_polygon) { m3d::Mesh::Polygon::Vertex vertex0 = t_polygon.getVertex(0), vertex1 = t_polygon.getVertex(1), From a0fe61c5701d49c4e392d1897fe2dd1c16cef393 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:52:58 +0200 Subject: [PATCH 067/114] Add fog support and fix depth-test --- m3dialib/includes/m3d/graphics/screen.hpp | 34 +++++++++++++++ m3dialib/source/graphics/screen.cpp | 53 +++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index 5e8b911..52b0cb6 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -136,8 +136,37 @@ namespace m3d { * @return The camera */ m3d::Camera& getCamera(m3d::RenderContext::ScreenTarget t_target); + + /** + * @brief Sets whether fog should be used for the given screen target + * @param t_useFog `true` if fog should be used, `false` otherwise for the given screen target + * @param t_target The target + */ + void useFog(bool t_useFog, m3d::RenderContext::ScreenTarget t_target); + + /** + * @brief Returns whether or not fog is being used on the given screen target + * @param t_target The target + * @return `true` if fog is being used, `false` otherwise on the given screen target + */ + bool getUseFog(m3d::RenderContext::ScreenTarget t_target); + + /** + * @brief Sets the fog density for the given screen target + * @param t_density The fog density for the given screen target + * @param t_target The target + */ + void setFogDensity(float t_density,m3d::RenderContext::ScreenTarget t_target); + + /** + * @brief Returns the fog density of the given screen target + * @param t_target The target + * @return The fog density of the given screen target + */ + float getFogDensity(m3d::RenderContext::ScreenTarget t_target); private: void prepare(); + void prepareFog(m3d::RenderContext::ScreenTarget t_target); void prepareLights(m3d::RenderContext::ScreenTarget t_target); /* data */ @@ -171,6 +200,11 @@ namespace m3d { C3D_LightEnv m_lightEnvTop, m_lightEnvBottom; C3D_Light m_lightTop, m_lightBottom; C3D_LightLut m_lutPhongTop, m_lutPhongBottom; + + // fog + bool m_useFogTop, m_useFogBottom; + float m_fogDensityTop, m_fogDensityBottom; + C3D_FogLut m_fogLutTop, m_fogLutBottom; }; } /* m3d */ diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index dd40b1d..c7bbc46 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -10,7 +10,11 @@ namespace m3d { m_clearColorTop(m3d::Color(0, 0, 0)), m_clearColorBottom(m3d::Color(0, 0, 0)), m_cameraTop(m3d::priv::graphics::defaultCamera0), - m_cameraBottom(m3d::priv::graphics::defaultCamera1) { + m_cameraBottom(m3d::priv::graphics::defaultCamera1), + m_useFogTop(false), + m_useFogBottom(false), + m_fogDensityTop(0.05), + m_fogDensityBottom(0.05) { gfxInitDefault(); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); C2D_Init(C2D_DEFAULT_MAX_OBJECTS); @@ -168,7 +172,8 @@ namespace m3d { if(m_drawStackBottom3d.size() > 0) { C3D_FrameDrawOn(m_targetBottom->getRenderTarget()); - // prepareLights(m3d::RenderContext::ScreenTarget::Bottom); + prepareLights(m3d::RenderContext::ScreenTarget::Bottom); + if (m_useFogBottom) prepareFog(m3d::RenderContext::ScreenTarget::Bottom); for(const auto &entry : m_drawStackBottom3d) { // for every layer for(const auto &drawable : entry.second) { // draw every object @@ -193,7 +198,8 @@ namespace m3d { if (m_drawStackTop3d.size() > 0) { C3D_FrameDrawOn(m_targetTopLeft->getRenderTarget()); - // prepareLights(m3d::RenderContext::ScreenTarget::Top); + prepareLights(m3d::RenderContext::ScreenTarget::Top); + if (m_useFogTop) prepareFog(m3d::RenderContext::ScreenTarget::Top); // tilt stereo perspective if (m_3dEnabled) { @@ -365,6 +371,30 @@ namespace m3d { return (t_target == m3d::RenderContext::ScreenTarget::Top ? m_cameraTop : m_cameraBottom); } + void Screen::useFog(bool t_useFog, m3d::RenderContext::ScreenTarget t_target) { + if (t_target == m3d::RenderContext::ScreenTarget::Top) { + m_useFogTop = t_useFog; + } else { + m_useFogBottom = t_useFog; + } + } + + bool Screen::getUseFog(m3d::RenderContext::ScreenTarget t_target) { + return (t_target == m3d::RenderContext::ScreenTarget::Top ? m_useFogTop : m_useFogBottom); + } + + void Screen::setFogDensity(float t_density, m3d::RenderContext::ScreenTarget t_target) { + if (t_target == m3d::RenderContext::ScreenTarget::Top) { + m_fogDensityTop = t_density; + } else { + m_fogDensityBottom = t_density; + } + } + + float Screen::getFogDensity(m3d::RenderContext::ScreenTarget t_target) { + return (t_target == m3d::RenderContext::ScreenTarget::Top ? m_fogDensityTop : m_fogDensityBottom); + } + // private methods void Screen::prepare() { C3D_BindProgram(&m_shader); @@ -385,7 +415,22 @@ namespace m3d { C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); C3D_CullFace(GPU_CULL_BACK_CCW); - C3D_DepthTest(true, GPU_ALWAYS, GPU_WRITE_ALL); + } + + void Screen::prepareFog(m3d::RenderContext::ScreenTarget t_target) { + switch (t_target) { + case m3d::RenderContext::ScreenTarget::Bottom: + FogLut_Exp(&m_fogLutBottom, m_fogDensityBottom, 1.5f, 0.01f, 20.0f); + C3D_FogGasMode(GPU_FOG, GPU_PLAIN_DENSITY, false); + C3D_FogColor(m_clearColorTop.getRgb8()); + C3D_FogLutBind(&m_fogLutBottom); + break; + default: + FogLut_Exp(&m_fogLutTop, m_fogDensityTop, 1.5f, 0.01f, 20.0f); + C3D_FogGasMode(GPU_FOG, GPU_PLAIN_DENSITY, false); + C3D_FogColor(m_clearColorTop.getRgb8()); + C3D_FogLutBind(&m_fogLutTop); + } } void Screen::prepareLights(m3d::RenderContext::ScreenTarget t_target) { From 8f4a8a1fe51f01e4e831f78276c4201966d2bb1a Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 21:56:31 +0200 Subject: [PATCH 068/114] Fix emission color --- m3dialib/source/graphics/mesh.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 0451a13..572092b 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -196,7 +196,6 @@ namespace m3d { if (t_resetMaterial) { m_material.setAmbient(125, 125, 125); m_material.setDiffuse(255, 255, 255); - m_material.setEmission(255, 0, 0); } } From cf649b270ccd5fe7b130cdb79ee373e068300145 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Mon, 24 Sep 2018 23:02:28 +0200 Subject: [PATCH 069/114] Add travis.yml --- travis.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 travis.yml diff --git a/travis.yml b/travis.yml new file mode 100644 index 0000000..9b69df3 --- /dev/null +++ b/travis.yml @@ -0,0 +1,25 @@ +language: cpp +dist: trusty +compiler: + - gcc +os: + - linux +before_install: + - wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb + - sudo dpkg -i devkitpro-pacman.deb + - dkp-pacman -S devkitARM picasso tex3ds 3dstools devkit-env libctru citro3d citro2d 3ds-zlib 3ds-tinyxml2 3ds-mpg123 3ds-libpng +script: + - make -C m3dialib/ +branches: + only: + - master +notifications: + email: + recipents: + - stunthacks@gmail.com + on_success: never + on_failure: always +env: + global: + - DEVKITPRO="/opt/devkitpro" + - DEVKITARM="/opt/devkitpro/devkitARM" From b254d4dea13e9fcffdd4daefe910e1cab4bf9569 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 18:48:11 +0200 Subject: [PATCH 070/114] Remove private header --- m3dialib/includes/m3d/private/private.hpp | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 m3dialib/includes/m3d/private/private.hpp diff --git a/m3dialib/includes/m3d/private/private.hpp b/m3dialib/includes/m3d/private/private.hpp deleted file mode 100644 index 3290b76..0000000 --- a/m3dialib/includes/m3d/private/private.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef PRIVATE_H -#define PRIVATE_H - -#pragma once -#include "ndsp.hpp" -#include "graphics.hpp" - - -#endif /* end of include guard: PRIVATE_H */ From 828e30e685ccd0fbf8e249875d2bf9d5c6a179cb Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 18:49:15 +0200 Subject: [PATCH 071/114] Add destructor and documentation --- m3dialib/includes/m3d/graphics/drawables/mesh.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index c843c37..fa3f462 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -318,6 +318,9 @@ namespace m3d { void draw(m3d::RenderContext t_context); protected: + /** + * @brief Updates the vertex buffer + */ void updateVbo(); private: From d9fe3eb77833aabf514ae24a72cc89abdd75c619 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 18:49:33 +0200 Subject: [PATCH 072/114] Use fixed-size array --- m3dialib/includes/m3d/graphics/drawables/mesh.hpp | 7 +------ m3dialib/source/graphics/polygon.cpp | 8 -------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index fa3f462..c0228db 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -42,11 +42,6 @@ namespace m3d { */ Polygon(m3d::Mesh::Polygon::Vertex t_vertex0, m3d::Mesh::Polygon::Vertex t_vertex1, m3d::Mesh::Polygon::Vertex t_vertex2); - /** - * @brief Destructs the polygon - */ - virtual ~Polygon(); - /** * @brief Sets the vertices of the polygon * @param t_vertex0 The first vertex @@ -64,7 +59,7 @@ namespace m3d { private: /* data */ - m3d::Mesh::Polygon::Vertex* m_vertices; + m3d::Mesh::Polygon::Vertex m_vertices[3]; }; /** diff --git a/m3dialib/source/graphics/polygon.cpp b/m3dialib/source/graphics/polygon.cpp index 8f7f787..afba268 100644 --- a/m3dialib/source/graphics/polygon.cpp +++ b/m3dialib/source/graphics/polygon.cpp @@ -2,17 +2,9 @@ namespace m3d { Mesh::Polygon::Polygon(m3d::Mesh::Polygon::Vertex t_vertex0, m3d::Mesh::Polygon::Vertex t_vertex1, m3d::Mesh::Polygon::Vertex t_vertex2) { - m_vertices = new m3d::Mesh::Polygon::Vertex[3]; setVertices(t_vertex0, t_vertex1, t_vertex2); } - /** - * @brief Destructs the polygon - */ - Mesh::Polygon::~Polygon() { - delete m_vertices; - } - /** * @brief Sets the vertices of the polygon * @param t_vertex0 The first vertex From d9c788e0d4da85c499095b8793c0c344b6587b42 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 18:49:44 +0200 Subject: [PATCH 073/114] Add obj loading header --- m3dialib/includes/m3d/private/OBJ_Loader.h | 1166 ++++++++++++++++++++ 1 file changed, 1166 insertions(+) create mode 100644 m3dialib/includes/m3d/private/OBJ_Loader.h diff --git a/m3dialib/includes/m3d/private/OBJ_Loader.h b/m3dialib/includes/m3d/private/OBJ_Loader.h new file mode 100644 index 0000000..d278489 --- /dev/null +++ b/m3dialib/includes/m3d/private/OBJ_Loader.h @@ -0,0 +1,1166 @@ +// OBJ_Loader.h - A Single Header OBJ Model Loader + +#pragma once + +// Iostream - STD I/O Library +#include + +// Vector - STD Vector/Array Library +#include + +// String - STD String Library +#include + +// fStream - STD File I/O Library +#include + +// Math.h - STD math Library +#include + +// Print progress to console while loading (large models) +// #define OBJL_CONSOLE_OUTPUT + +// Namespace: OBJL +// +// Description: The namespace that holds eveyrthing that +// is needed and used for the OBJ Model Loader +namespace objl +{ + // Structure: Vector2 + // + // Description: A 2D Vector that Holds Positional Data + struct Vector2 + { + // Default Constructor + Vector2() + { + X = 0.0f; + Y = 0.0f; + } + // Variable Set Constructor + Vector2(float X_, float Y_) + { + X = X_; + Y = Y_; + } + // Bool Equals Operator Overload + bool operator==(const Vector2& other) const + { + return (this->X == other.X && this->Y == other.Y); + } + // Bool Not Equals Operator Overload + bool operator!=(const Vector2& other) const + { + return !(this->X == other.X && this->Y == other.Y); + } + // Addition Operator Overload + Vector2 operator+(const Vector2& right) const + { + return Vector2(this->X + right.X, this->Y + right.Y); + } + // Subtraction Operator Overload + Vector2 operator-(const Vector2& right) const + { + return Vector2(this->X - right.X, this->Y - right.Y); + } + // Float Multiplication Operator Overload + Vector2 operator*(const float& other) const + { + return Vector2(this->X *other, this->Y * other); + } + + // Positional Variables + float X; + float Y; + }; + + // Structure: Vector3 + // + // Description: A 3D Vector that Holds Positional Data + struct Vector3 + { + // Default Constructor + Vector3() + { + X = 0.0f; + Y = 0.0f; + Z = 0.0f; + } + // Variable Set Constructor + Vector3(float X_, float Y_, float Z_) + { + X = X_; + Y = Y_; + Z = Z_; + } + // Bool Equals Operator Overload + bool operator==(const Vector3& other) const + { + return (this->X == other.X && this->Y == other.Y && this->Z == other.Z); + } + // Bool Not Equals Operator Overload + bool operator!=(const Vector3& other) const + { + return !(this->X == other.X && this->Y == other.Y && this->Z == other.Z); + } + // Addition Operator Overload + Vector3 operator+(const Vector3& right) const + { + return Vector3(this->X + right.X, this->Y + right.Y, this->Z + right.Z); + } + // Subtraction Operator Overload + Vector3 operator-(const Vector3& right) const + { + return Vector3(this->X - right.X, this->Y - right.Y, this->Z - right.Z); + } + // Float Multiplication Operator Overload + Vector3 operator*(const float& other) const + { + return Vector3(this->X * other, this->Y * other, this->Z * other); + } + // Float Division Operator Overload + Vector3 operator/(const float& other) const + { + return Vector3(this->X / other, this->Y / other, this->Z / other); + } + + // Positional Variables + float X; + float Y; + float Z; + }; + + // Structure: Vertex + // + // Description: Model Vertex object that holds + // a Position, Normal, and Texture Coordinate + struct Vertex + { + // Position Vector + Vector3 Position; + + // Normal Vector + Vector3 Normal; + + // Texture Coordinate Vector + Vector2 TextureCoordinate; + }; + + struct Material + { + Material() + { + Ns = 0.0f; + Ni = 0.0f; + d = 0.0f; + illum = 0; + } + + // Material Name + std::string name; + // Ambient Color + Vector3 Ka; + // Diffuse Color + Vector3 Kd; + // Specular Color + Vector3 Ks; + // Specular Exponent + float Ns; + // Optical Density + float Ni; + // Dissolve + float d; + // Illumination + int illum; + // Ambient Texture Map + std::string map_Ka; + // Diffuse Texture Map + std::string map_Kd; + // Specular Texture Map + std::string map_Ks; + // Specular Hightlight Map + std::string map_Ns; + // Alpha Texture Map + std::string map_d; + // Bump Map + std::string map_bump; + }; + + // Structure: Mesh + // + // Description: A Simple Mesh Object that holds + // a name, a vertex list, and an index list + struct Mesh + { + // Default Constructor + Mesh() + { + + } + // Variable Set Constructor + Mesh(std::vector& _Vertices, std::vector& _Indices) + { + Vertices = _Vertices; + Indices = _Indices; + } + // Mesh Name + std::string MeshName; + // Vertex List + std::vector Vertices; + // Index List + std::vector Indices; + + // Material + Material MeshMaterial; + }; + + // Namespace: Math + // + // Description: The namespace that holds all of the math + // functions need for OBJL + namespace math + { + // Vector3 Cross Product + Vector3 CrossV3(const Vector3 a, const Vector3 b) + { + return Vector3(a.Y * b.Z - a.Z * b.Y, + a.Z * b.X - a.X * b.Z, + a.X * b.Y - a.Y * b.X); + } + + // Vector3 Magnitude Calculation + float MagnitudeV3(const Vector3 in) + { + return (sqrtf(powf(in.X, 2) + powf(in.Y, 2) + powf(in.Z, 2))); + } + + // Vector3 DotProduct + float DotV3(const Vector3 a, const Vector3 b) + { + return (a.X * b.X) + (a.Y * b.Y) + (a.Z * b.Z); + } + + // Angle between 2 Vector3 Objects + float AngleBetweenV3(const Vector3 a, const Vector3 b) + { + float angle = DotV3(a, b); + angle /= (MagnitudeV3(a) * MagnitudeV3(b)); + return angle = acosf(angle); + } + + // Projection Calculation of a onto b + Vector3 ProjV3(const Vector3 a, const Vector3 b) + { + Vector3 bn = b / MagnitudeV3(b); + return bn * DotV3(a, bn); + } + } + + // Namespace: Algorithm + // + // Description: The namespace that holds all of the + // Algorithms needed for OBJL + namespace algorithm + { + // Vector3 Multiplication Opertor Overload + Vector3 operator*(const float& left, const Vector3& right) + { + return Vector3(right.X * left, right.Y * left, right.Z * left); + } + + // A test to see if P1 is on the same side as P2 of a line segment ab + bool SameSide(Vector3 p1, Vector3 p2, Vector3 a, Vector3 b) + { + Vector3 cp1 = math::CrossV3(b - a, p1 - a); + Vector3 cp2 = math::CrossV3(b - a, p2 - a); + + if (math::DotV3(cp1, cp2) >= 0) + return true; + else + return false; + } + + // Generate a cross produect normal for a triangle + Vector3 GenTriNormal(Vector3 t1, Vector3 t2, Vector3 t3) + { + Vector3 u = t2 - t1; + Vector3 v = t3 - t1; + + Vector3 normal = math::CrossV3(u,v); + + return normal; + } + + // Check to see if a Vector3 Point is within a 3 Vector3 Triangle + bool inTriangle(Vector3 point, Vector3 tri1, Vector3 tri2, Vector3 tri3) + { + // Test to see if it is within an infinite prism that the triangle outlines. + bool within_tri_prisim = SameSide(point, tri1, tri2, tri3) && SameSide(point, tri2, tri1, tri3) + && SameSide(point, tri3, tri1, tri2); + + // If it isn't it will never be on the triangle + if (!within_tri_prisim) + return false; + + // Calulate Triangle's Normal + Vector3 n = GenTriNormal(tri1, tri2, tri3); + + // Project the point onto this normal + Vector3 proj = math::ProjV3(point, n); + + // If the distance from the triangle to the point is 0 + // it lies on the triangle + if (math::MagnitudeV3(proj) == 0) + return true; + else + return false; + } + + // Split a String into a string array at a given token + inline void split(const std::string &in, + std::vector &out, + std::string token) + { + out.clear(); + + std::string temp; + + for (int i = 0; i < int(in.size()); i++) + { + std::string test = in.substr(i, token.size()); + + if (test == token) + { + if (!temp.empty()) + { + out.push_back(temp); + temp.clear(); + i += (int)token.size() - 1; + } + else + { + out.push_back(""); + } + } + else if (i + token.size() >= in.size()) + { + temp += in.substr(i, token.size()); + out.push_back(temp); + break; + } + else + { + temp += in[i]; + } + } + } + + // Get tail of string after first token and possibly following spaces + inline std::string tail(const std::string &in) + { + size_t token_start = in.find_first_not_of(" \t"); + size_t space_start = in.find_first_of(" \t", token_start); + size_t tail_start = in.find_first_not_of(" \t", space_start); + size_t tail_end = in.find_last_not_of(" \t"); + if (tail_start != std::string::npos && tail_end != std::string::npos) + { + return in.substr(tail_start, tail_end - tail_start + 1); + } + else if (tail_start != std::string::npos) + { + return in.substr(tail_start); + } + return ""; + } + + // Get first token of string + inline std::string firstToken(const std::string &in) + { + if (!in.empty()) + { + size_t token_start = in.find_first_not_of(" \t"); + size_t token_end = in.find_first_of(" \t", token_start); + if (token_start != std::string::npos && token_end != std::string::npos) + { + return in.substr(token_start, token_end - token_start); + } + else if (token_start != std::string::npos) + { + return in.substr(token_start); + } + } + return ""; + } + + // Get element at given index position + template + inline const T & getElement(const std::vector &elements, std::string &index) + { + int idx = std::stoi(index); + if (idx < 0) + idx = int(elements.size()) + idx; + else + idx--; + return elements[idx]; + } + } + + // Class: Loader + // + // Description: The OBJ Model Loader + class Loader + { + public: + // Default Constructor + Loader() + { + + } + ~Loader() + { + LoadedMeshes.clear(); + } + + // Load a file into the loader + // + // If file is loaded return true + // + // If the file is unable to be found + // or unable to be loaded return false + bool LoadFile(std::string Path) + { + // If the file is not an .obj file return false + if (Path.substr(Path.size() - 4, 4) != ".obj") + return false; + + + std::ifstream file(Path); + + if (!file.is_open()) + return false; + + LoadedMeshes.clear(); + LoadedVertices.clear(); + LoadedIndices.clear(); + + std::vector Positions; + std::vector TCoords; + std::vector Normals; + + std::vector Vertices; + std::vector Indices; + + std::vector MeshMatNames; + + bool listening = false; + std::string meshname; + + Mesh tempMesh; + + #ifdef OBJL_CONSOLE_OUTPUT + const unsigned int outputEveryNth = 1000; + unsigned int outputIndicator = outputEveryNth; + #endif + + std::string curline; + while (std::getline(file, curline)) + { + #ifdef OBJL_CONSOLE_OUTPUT + if ((outputIndicator = ((outputIndicator + 1) % outputEveryNth)) == 1) + { + if (!meshname.empty()) + { + std::cout + << "\r- " << meshname + << "\t| vertices > " << Positions.size() + << "\t| texcoords > " << TCoords.size() + << "\t| normals > " << Normals.size() + << "\t| triangles > " << (Vertices.size() / 3) + << (!MeshMatNames.empty() ? "\t| material: " + MeshMatNames.back() : ""); + } + } + #endif + + // Generate a Mesh Object or Prepare for an object to be created + if (algorithm::firstToken(curline) == "o" || algorithm::firstToken(curline) == "g" || curline[0] == 'g') + { + if (!listening) + { + listening = true; + + if (algorithm::firstToken(curline) == "o" || algorithm::firstToken(curline) == "g") + { + meshname = algorithm::tail(curline); + } + else + { + meshname = "unnamed"; + } + } + else + { + // Generate the mesh to put into the array + + if (!Indices.empty() && !Vertices.empty()) + { + // Create Mesh + tempMesh = Mesh(Vertices, Indices); + tempMesh.MeshName = meshname; + + // Insert Mesh + LoadedMeshes.push_back(tempMesh); + + // Cleanup + Vertices.clear(); + Indices.clear(); + meshname.clear(); + + meshname = algorithm::tail(curline); + } + else + { + if (algorithm::firstToken(curline) == "o" || algorithm::firstToken(curline) == "g") + { + meshname = algorithm::tail(curline); + } + else + { + meshname = "unnamed"; + } + } + } + #ifdef OBJL_CONSOLE_OUTPUT + std::cout << std::endl; + outputIndicator = 0; + #endif + } + // Generate a Vertex Position + if (algorithm::firstToken(curline) == "v") + { + std::vector spos; + Vector3 vpos; + algorithm::split(algorithm::tail(curline), spos, " "); + + vpos.X = std::stof(spos[0]); + vpos.Y = std::stof(spos[1]); + vpos.Z = std::stof(spos[2]); + + Positions.push_back(vpos); + } + // Generate a Vertex Texture Coordinate + if (algorithm::firstToken(curline) == "vt") + { + std::vector stex; + Vector2 vtex; + algorithm::split(algorithm::tail(curline), stex, " "); + + vtex.X = std::stof(stex[0]); + vtex.Y = std::stof(stex[1]); + + TCoords.push_back(vtex); + } + // Generate a Vertex Normal; + if (algorithm::firstToken(curline) == "vn") + { + std::vector snor; + Vector3 vnor; + algorithm::split(algorithm::tail(curline), snor, " "); + + vnor.X = std::stof(snor[0]); + vnor.Y = std::stof(snor[1]); + vnor.Z = std::stof(snor[2]); + + Normals.push_back(vnor); + } + // Generate a Face (vertices & indices) + if (algorithm::firstToken(curline) == "f") + { + // Generate the vertices + std::vector vVerts; + GenVerticesFromRawOBJ(vVerts, Positions, TCoords, Normals, curline); + + // Add Vertices + for (int i = 0; i < int(vVerts.size()); i++) + { + Vertices.push_back(vVerts[i]); + + LoadedVertices.push_back(vVerts[i]); + } + + std::vector iIndices; + + VertexTriangluation(iIndices, vVerts); + + // Add Indices + for (int i = 0; i < int(iIndices.size()); i++) + { + unsigned int indnum = (unsigned int)((Vertices.size()) - vVerts.size()) + iIndices[i]; + Indices.push_back(indnum); + + indnum = (unsigned int)((LoadedVertices.size()) - vVerts.size()) + iIndices[i]; + LoadedIndices.push_back(indnum); + + } + } + // Get Mesh Material Name + if (algorithm::firstToken(curline) == "usemtl") + { + MeshMatNames.push_back(algorithm::tail(curline)); + + // Create new Mesh, if Material changes within a group + if (!Indices.empty() && !Vertices.empty()) + { + // Create Mesh + tempMesh = Mesh(Vertices, Indices); + tempMesh.MeshName = meshname; + int i = 2; + while(1) { + tempMesh.MeshName = meshname + "_" + std::to_string(i); + + for (auto &m : LoadedMeshes) + if (m.MeshName == tempMesh.MeshName) + continue; + break; + } + + // Insert Mesh + LoadedMeshes.push_back(tempMesh); + + // Cleanup + Vertices.clear(); + Indices.clear(); + } + + #ifdef OBJL_CONSOLE_OUTPUT + outputIndicator = 0; + #endif + } + // Load Materials + if (algorithm::firstToken(curline) == "mtllib") + { + // Generate LoadedMaterial + + // Generate a path to the material file + std::vector temp; + algorithm::split(Path, temp, "/"); + + std::string pathtomat = ""; + + if (temp.size() != 1) + { + for (unsigned int i = 0; i < temp.size() - 1; i++) + { + pathtomat += temp[i] + "/"; + } + } + + + pathtomat += algorithm::tail(curline); + + #ifdef OBJL_CONSOLE_OUTPUT + std::cout << std::endl << "- find materials in: " << pathtomat << std::endl; + #endif + + // Load Materials + LoadMaterials(pathtomat); + } + } + + #ifdef OBJL_CONSOLE_OUTPUT + std::cout << std::endl; + #endif + + // Deal with last mesh + + if (!Indices.empty() && !Vertices.empty()) + { + // Create Mesh + tempMesh = Mesh(Vertices, Indices); + tempMesh.MeshName = meshname; + + // Insert Mesh + LoadedMeshes.push_back(tempMesh); + } + + file.close(); + + // Set Materials for each Mesh + for (unsigned int i = 0; i < MeshMatNames.size(); i++) + { + std::string matname = MeshMatNames[i]; + + // Find corresponding material name in loaded materials + // when found copy material variables into mesh material + for (unsigned int j = 0; j < LoadedMaterials.size(); j++) + { + if (LoadedMaterials[j].name == matname) + { + LoadedMeshes[i].MeshMaterial = LoadedMaterials[j]; + break; + } + } + } + + if (LoadedMeshes.empty() && LoadedVertices.empty() && LoadedIndices.empty()) + { + return false; + } + else + { + return true; + } + } + + // Loaded Mesh Objects + std::vector LoadedMeshes; + // Loaded Vertex Objects + std::vector LoadedVertices; + // Loaded Index Positions + std::vector LoadedIndices; + // Loaded Material Objects + std::vector LoadedMaterials; + + private: + // Generate vertices from a list of positions, + // tcoords, normals and a face line + void GenVerticesFromRawOBJ(std::vector& oVerts, + const std::vector& iPositions, + const std::vector& iTCoords, + const std::vector& iNormals, + std::string icurline) + { + std::vector sface, svert; + Vertex vVert; + algorithm::split(algorithm::tail(icurline), sface, " "); + + bool noNormal = false; + + // For every given vertex do this + for (int i = 0; i < int(sface.size()); i++) + { + // See What type the vertex is. + int vtype = -1; + + algorithm::split(sface[i], svert, "/"); + + // Check for just position - v1 + if (svert.size() == 1) + { + // Only position + vtype = 1; + } + + // Check for position & texture - v1/vt1 + if (svert.size() == 2) + { + // Position & Texture + vtype = 2; + } + + // Check for Position, Texture and Normal - v1/vt1/vn1 + // or if Position and Normal - v1//vn1 + if (svert.size() == 3) + { + if (svert[1] != "") + { + // Position, Texture, and Normal + vtype = 4; + } + else + { + // Position & Normal + vtype = 3; + } + } + + // Calculate and store the vertex + switch (vtype) + { + case 1: // P + { + vVert.Position = algorithm::getElement(iPositions, svert[0]); + vVert.TextureCoordinate = Vector2(0, 0); + noNormal = true; + oVerts.push_back(vVert); + break; + } + case 2: // P/T + { + vVert.Position = algorithm::getElement(iPositions, svert[0]); + vVert.TextureCoordinate = algorithm::getElement(iTCoords, svert[1]); + noNormal = true; + oVerts.push_back(vVert); + break; + } + case 3: // P//N + { + vVert.Position = algorithm::getElement(iPositions, svert[0]); + vVert.TextureCoordinate = Vector2(0, 0); + vVert.Normal = algorithm::getElement(iNormals, svert[2]); + oVerts.push_back(vVert); + break; + } + case 4: // P/T/N + { + vVert.Position = algorithm::getElement(iPositions, svert[0]); + vVert.TextureCoordinate = algorithm::getElement(iTCoords, svert[1]); + vVert.Normal = algorithm::getElement(iNormals, svert[2]); + oVerts.push_back(vVert); + break; + } + default: + { + break; + } + } + } + + // take care of missing normals + // these may not be truly acurate but it is the + // best they get for not compiling a mesh with normals + if (noNormal) + { + Vector3 A = oVerts[0].Position - oVerts[1].Position; + Vector3 B = oVerts[2].Position - oVerts[1].Position; + + Vector3 normal = math::CrossV3(A, B); + + for (int i = 0; i < int(oVerts.size()); i++) + { + oVerts[i].Normal = normal; + } + } + } + + // Triangulate a list of vertices into a face by printing + // inducies corresponding with triangles within it + void VertexTriangluation(std::vector& oIndices, + const std::vector& iVerts) + { + // If there are 2 or less verts, + // no triangle can be created, + // so exit + if (iVerts.size() < 3) + { + return; + } + // If it is a triangle no need to calculate it + if (iVerts.size() == 3) + { + oIndices.push_back(0); + oIndices.push_back(1); + oIndices.push_back(2); + return; + } + + // Create a list of vertices + std::vector tVerts = iVerts; + + while (true) + { + // For every vertex + for (unsigned int i = 0; i < tVerts.size(); i++) + { + // pPrev = the previous vertex in the list + Vertex pPrev; + if (i == 0) + { + pPrev = tVerts[tVerts.size() - 1]; + } + else + { + pPrev = tVerts[i - 1]; + } + + // pCur = the current vertex; + Vertex pCur = tVerts[i]; + + // pNext = the next vertex in the list + Vertex pNext; + if (i == tVerts.size() - 1) + { + pNext = tVerts[0]; + } + else + { + pNext = tVerts[i + 1]; + } + + // Check to see if there are only 3 verts left + // if so this is the last triangle + if (tVerts.size() == 3) + { + // Create a triangle from pCur, pPrev, pNext + for (int j = 0; j < int(tVerts.size()); j++) + { + if (iVerts[j].Position == pCur.Position) + oIndices.push_back(j); + if (iVerts[j].Position == pPrev.Position) + oIndices.push_back(j); + if (iVerts[j].Position == pNext.Position) + oIndices.push_back(j); + } + + tVerts.clear(); + break; + } + if (tVerts.size() == 4) + { + // Create a triangle from pCur, pPrev, pNext + for (int j = 0; j < int(iVerts.size()); j++) + { + if (iVerts[j].Position == pCur.Position) + oIndices.push_back(j); + if (iVerts[j].Position == pPrev.Position) + oIndices.push_back(j); + if (iVerts[j].Position == pNext.Position) + oIndices.push_back(j); + } + + Vector3 tempVec; + for (int j = 0; j < int(tVerts.size()); j++) + { + if (tVerts[j].Position != pCur.Position + && tVerts[j].Position != pPrev.Position + && tVerts[j].Position != pNext.Position) + { + tempVec = tVerts[j].Position; + break; + } + } + + // Create a triangle from pCur, pPrev, pNext + for (int j = 0; j < int(iVerts.size()); j++) + { + if (iVerts[j].Position == pPrev.Position) + oIndices.push_back(j); + if (iVerts[j].Position == pNext.Position) + oIndices.push_back(j); + if (iVerts[j].Position == tempVec) + oIndices.push_back(j); + } + + tVerts.clear(); + break; + } + + // If Vertex is not an interior vertex + float angle = math::AngleBetweenV3(pPrev.Position - pCur.Position, pNext.Position - pCur.Position) * (180 / 3.14159265359); + if (angle <= 0 && angle >= 180) + continue; + + // If any vertices are within this triangle + bool inTri = false; + for (int j = 0; j < int(iVerts.size()); j++) + { + if (algorithm::inTriangle(iVerts[j].Position, pPrev.Position, pCur.Position, pNext.Position) + && iVerts[j].Position != pPrev.Position + && iVerts[j].Position != pCur.Position + && iVerts[j].Position != pNext.Position) + { + inTri = true; + break; + } + } + if (inTri) + continue; + + // Create a triangle from pCur, pPrev, pNext + for (int j = 0; j < int(iVerts.size()); j++) + { + if (iVerts[j].Position == pCur.Position) + oIndices.push_back(j); + if (iVerts[j].Position == pPrev.Position) + oIndices.push_back(j); + if (iVerts[j].Position == pNext.Position) + oIndices.push_back(j); + } + + // Delete pCur from the list + for (int j = 0; j < int(tVerts.size()); j++) + { + if (tVerts[j].Position == pCur.Position) + { + tVerts.erase(tVerts.begin() + j); + break; + } + } + + // reset i to the start + // -1 since loop will add 1 to it + i = -1; + } + + // if no triangles were created + if (oIndices.size() == 0) + break; + + // if no more vertices + if (tVerts.size() == 0) + break; + } + } + + // Load Materials from .mtl file + bool LoadMaterials(std::string path) + { + // If the file is not a material file return false + if (path.substr(path.size() - 4, path.size()) != ".mtl") + return false; + + std::ifstream file(path); + + // If the file is not found return false + if (!file.is_open()) + return false; + + Material tempMaterial; + + bool listening = false; + + // Go through each line looking for material variables + std::string curline; + while (std::getline(file, curline)) + { + // new material and material name + if (algorithm::firstToken(curline) == "newmtl") + { + if (!listening) + { + listening = true; + + if (curline.size() > 7) + { + tempMaterial.name = algorithm::tail(curline); + } + else + { + tempMaterial.name = "none"; + } + } + else + { + // Generate the material + + // Push Back loaded Material + LoadedMaterials.push_back(tempMaterial); + + // Clear Loaded Material + tempMaterial = Material(); + + if (curline.size() > 7) + { + tempMaterial.name = algorithm::tail(curline); + } + else + { + tempMaterial.name = "none"; + } + } + } + // Ambient Color + if (algorithm::firstToken(curline) == "Ka") + { + std::vector temp; + algorithm::split(algorithm::tail(curline), temp, " "); + + if (temp.size() != 3) + continue; + + tempMaterial.Ka.X = std::stof(temp[0]); + tempMaterial.Ka.Y = std::stof(temp[1]); + tempMaterial.Ka.Z = std::stof(temp[2]); + } + // Diffuse Color + if (algorithm::firstToken(curline) == "Kd") + { + std::vector temp; + algorithm::split(algorithm::tail(curline), temp, " "); + + if (temp.size() != 3) + continue; + + tempMaterial.Kd.X = std::stof(temp[0]); + tempMaterial.Kd.Y = std::stof(temp[1]); + tempMaterial.Kd.Z = std::stof(temp[2]); + } + // Specular Color + if (algorithm::firstToken(curline) == "Ks") + { + std::vector temp; + algorithm::split(algorithm::tail(curline), temp, " "); + + if (temp.size() != 3) + continue; + + tempMaterial.Ks.X = std::stof(temp[0]); + tempMaterial.Ks.Y = std::stof(temp[1]); + tempMaterial.Ks.Z = std::stof(temp[2]); + } + // Specular Exponent + if (algorithm::firstToken(curline) == "Ns") + { + tempMaterial.Ns = std::stof(algorithm::tail(curline)); + } + // Optical Density + if (algorithm::firstToken(curline) == "Ni") + { + tempMaterial.Ni = std::stof(algorithm::tail(curline)); + } + // Dissolve + if (algorithm::firstToken(curline) == "d") + { + tempMaterial.d = std::stof(algorithm::tail(curline)); + } + // Illumination + if (algorithm::firstToken(curline) == "illum") + { + tempMaterial.illum = std::stoi(algorithm::tail(curline)); + } + // Ambient Texture Map + if (algorithm::firstToken(curline) == "map_Ka") + { + tempMaterial.map_Ka = algorithm::tail(curline); + } + // Diffuse Texture Map + if (algorithm::firstToken(curline) == "map_Kd") + { + tempMaterial.map_Kd = algorithm::tail(curline); + } + // Specular Texture Map + if (algorithm::firstToken(curline) == "map_Ks") + { + tempMaterial.map_Ks = algorithm::tail(curline); + } + // Specular Hightlight Map + if (algorithm::firstToken(curline) == "map_Ns") + { + tempMaterial.map_Ns = algorithm::tail(curline); + } + // Alpha Texture Map + if (algorithm::firstToken(curline) == "map_d") + { + tempMaterial.map_d = algorithm::tail(curline); + } + // Bump Map + if (algorithm::firstToken(curline) == "map_Bump" || algorithm::firstToken(curline) == "map_bump" || algorithm::firstToken(curline) == "bump") + { + tempMaterial.map_bump = algorithm::tail(curline); + } + } + + // Deal with last material + + // Push Back loaded Material + LoadedMaterials.push_back(tempMaterial); + + // Test to see if anything was loaded + // If not return false + if (LoadedMaterials.empty()) + return false; + // If so return true + else + return true; + } + }; +} From 21da3642f46d3b081c0234a34ed573a9b01d213d Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 18:50:00 +0200 Subject: [PATCH 074/114] Add and implement Model-class --- .../m3d/graphics/drawables/meshes/model.hpp | 22 +++++++++++++ m3dialib/source/graphics/model.cpp | 33 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp create mode 100644 m3dialib/source/graphics/model.cpp diff --git a/m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp b/m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp new file mode 100644 index 0000000..5e008eb --- /dev/null +++ b/m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp @@ -0,0 +1,22 @@ +/** + * @file model.hpp + * @brief Defines the Model-class which allows for loading 3D models + */ +#ifndef MODEL_H +#define MODEL_H + +#pragma once +#include "m3d/graphics/drawables/mesh.hpp" + +namespace m3d { + /** + * @brief The Model-class + */ + class Model: public m3d::Mesh { + public: + bool loadFromFile(const std::string& t_filename); + }; +} /* m3d */ + + +#endif /* end of include guard: MODEL_H */ diff --git a/m3dialib/source/graphics/model.cpp b/m3dialib/source/graphics/model.cpp new file mode 100644 index 0000000..083c371 --- /dev/null +++ b/m3dialib/source/graphics/model.cpp @@ -0,0 +1,33 @@ +#include "m3d/graphics/drawables/meshes/model.hpp" +#include "m3d/private/OBJ_Loader.h" + +namespace m3d { + bool Model::loadFromFile(const std::string& t_filename) { + objl::Loader loader; + + // Load .obj File + if(!loader.LoadFile(t_filename)) { + return false; + } + + // Go through each loaded mesh and out its contents + for (unsigned int i = 0; i < loader.LoadedMeshes.size(); i++) { + // Copy one of the loaded meshes to be our current mesh + objl::Mesh curMesh = loader.LoadedMeshes[i]; + + // Go through each vertex and print its number, + // position, normal, and texture coordinate + for (unsigned int j = 0; j < curMesh.Vertices.size() - 2; j += 3) { + addPolygon(m3d::Mesh::Polygon( + { {curMesh.Vertices[j].Position.X, curMesh.Vertices[j].Position.Y, curMesh.Vertices[j].Position.Z}, {curMesh.Vertices[j].TextureCoordinate.X, curMesh.Vertices[j].TextureCoordinate.Y}, {curMesh.Vertices[j].Normal.X, curMesh.Vertices[j].Normal.Y, curMesh.Vertices[j].Normal.Z} }, + { {curMesh.Vertices[j + 1].Position.X, curMesh.Vertices[j + 1].Position.Y, curMesh.Vertices[j + 1].Position.Z}, {curMesh.Vertices[j + 1].TextureCoordinate.X, curMesh.Vertices[j + 1].TextureCoordinate.Y}, {curMesh.Vertices[j + 1].Normal.X, curMesh.Vertices[j + 1].Normal.Y, curMesh.Vertices[j + 1].Normal.Z} }, + { {curMesh.Vertices[j + 2].Position.X, curMesh.Vertices[j + 2].Position.Y, curMesh.Vertices[j + 2].Position.Z}, {curMesh.Vertices[j + 2].TextureCoordinate.X, curMesh.Vertices[j + 2].TextureCoordinate.Y}, {curMesh.Vertices[j + 2].Normal.X, curMesh.Vertices[j + 1].Normal.Y, curMesh.Vertices[j + 1].Normal.Z} } + )); + } + } + + updateVbo(); + + return true; + } +} /* m3d */ From a3428d23ab876ad0a5b4b5e85605c7e6da755e85 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 19:15:39 +0200 Subject: [PATCH 075/114] Add option to enable and disable culling --- m3dialib/includes/m3d/graphics/screen.hpp | 15 ++++++++++++++- m3dialib/source/graphics/screen.cpp | 11 ++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/screen.hpp b/m3dialib/includes/m3d/graphics/screen.hpp index 52b0cb6..1d56288 100644 --- a/m3dialib/includes/m3d/graphics/screen.hpp +++ b/m3dialib/includes/m3d/graphics/screen.hpp @@ -41,6 +41,19 @@ namespace m3d { */ void set3d(bool t_enabled); + /** + * @brief Whether or not to use culling + * @param t_useCulling Whether to use culling or not + * @note By default, culling is enabled + */ + void useCulling(bool t_useCulling); + + /** + * @brief Returns whether culling is being used or not + * @return `true` if culling is being used, `false` otherwise + */ + bool isUsingCulling(); + /** * @brief Sets the clear color for both screens * @param t_color The color to clear the screen with @@ -171,7 +184,7 @@ namespace m3d { /* data */ int m_projectionUniform, m_modelUniform, m_viewUniform; - bool m_3dEnabled; + bool m_3dEnabled, m_useCulling; m3d::Color m_clearColorTop, m_clearColorBottom; m3d::Camera &m_cameraTop, &m_cameraBottom; diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index c7bbc46..9704741 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -7,6 +7,7 @@ namespace m3d { Screen::Screen(bool t_enable3d) : m_3dEnabled(t_enable3d), + m_useCulling(true), m_clearColorTop(m3d::Color(0, 0, 0)), m_clearColorBottom(m3d::Color(0, 0, 0)), m_cameraTop(m3d::priv::graphics::defaultCamera0), @@ -57,6 +58,14 @@ namespace m3d { m_3dEnabled = t_enabled; } + void Screen::useCulling(bool t_useCulling) { + m_useCulling = t_useCulling; + } + + bool Screen::isUsingCulling() { + return m_useCulling; + } + void Screen::setClearColor(m3d::Color t_color) { m_clearColorTop = t_color; m_clearColorBottom = t_color; @@ -414,7 +423,7 @@ namespace m3d { C3D_TexEnvSrc(env, C3D_Both, GPU_FRAGMENT_PRIMARY_COLOR, GPU_FRAGMENT_SECONDARY_COLOR, GPU_PRIMARY_COLOR); C3D_TexEnvFunc(env, C3D_Both, GPU_ADD); - C3D_CullFace(GPU_CULL_BACK_CCW); + C3D_CullFace(m_useCulling ? GPU_CULL_BACK_CCW : GPU_CULL_NONE); } void Screen::prepareFog(m3d::RenderContext::ScreenTarget t_target) { From cbfb38e027abcb374797884738605620cb00e32e Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 19:15:50 +0200 Subject: [PATCH 076/114] Update VBOs --- m3dialib/source/graphics/cuboid.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/m3dialib/source/graphics/cuboid.cpp b/m3dialib/source/graphics/cuboid.cpp index c68711b..caa8f9a 100644 --- a/m3dialib/source/graphics/cuboid.cpp +++ b/m3dialib/source/graphics/cuboid.cpp @@ -113,5 +113,7 @@ namespace m3d { { {-(m_width / 2), -(m_height / 2), (m_length / 2)}, {0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} }, { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} } )); + + updateVbo(); } } /* m3d */ From 526d2d5d1feca4bcde1c691e62fcdde8e8449d38 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 19:16:11 +0200 Subject: [PATCH 077/114] Remove updating VBOs on every vertex change --- m3dialib/source/graphics/mesh.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 572092b..36c980a 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -41,8 +41,6 @@ namespace m3d { { vertex2.texcoord[0], vertex2.texcoord[1] }, { vertex2.normal[0], vertex2.normal[1], vertex2.normal[2] }, }); - - updateVbo(); } void Mesh::clearVertices() { From 09202c5ed7d23edf23f3df7b419739c72e642f38 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 19:16:17 +0200 Subject: [PATCH 078/114] Add model include --- m3dialib/includes/m3d/graphics/meshes.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/m3dialib/includes/m3d/graphics/meshes.hpp b/m3dialib/includes/m3d/graphics/meshes.hpp index 803775c..50fbaff 100644 --- a/m3dialib/includes/m3d/graphics/meshes.hpp +++ b/m3dialib/includes/m3d/graphics/meshes.hpp @@ -8,6 +8,7 @@ #pragma once #include "drawables/meshes/cuboid.hpp" +#include "drawables/meshes/model.hpp" #endif /* end of include guard: MESHES_H */ From f91efb88fc2eb6f56485e9a3cf8e39bf6e576dfe Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 19:16:24 +0200 Subject: [PATCH 079/114] Update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e6a1432..31d89aa 100644 --- a/README.md +++ b/README.md @@ -125,3 +125,4 @@ To compile a m3diaLib-app, you need the following dependencies installed (instal * [ctrulib](https://github.com/smealum/ctrulib/) * [citro3d](https://github.com/fincs/citro3d) (zLib) * [citro2d](https://github.com/devkitPro/citro2d) (zLib) + * [OBJ-Loader](https://github.com/Bly7/OBJ-Loader) (MIT) From ec1dc4938d3b7a64f593f494e1c7b6d2344c92b4 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 19:38:03 +0200 Subject: [PATCH 080/114] Use pitch/yaw/roll instead of rotationX/Y/Z --- .../includes/m3d/graphics/drawables/mesh.hpp | 26 +++++++++---------- m3dialib/source/graphics/mesh.cpp | 26 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index c0228db..574587c 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -87,63 +87,63 @@ namespace m3d { * @brief Sets the rotation on the X-axis * @param t_rotation The absolute rotation */ - void setRotationX(float t_rotation); + void setPitch(float t_rotation); /** * @brief Returns the rotation on the X-axis * @return The absolute rotation */ - float getRotationX(); + float getPitch(); /** * @brief Sets the rotation on the Y-axis * @param t_rotation The absolute rotation */ - void setRotationY(float t_rotation); + void setYaw(float t_rotation); /** * @brief Returns the rotation on the Y-axis * @return The absolute rotation */ - float getRotationY(); + float getYaw(); /** * @brief Sets the rotation on the Z-axis * @param t_rotation The absolute rotation */ - void setRotationZ(float t_rotation); + void setRoll(float t_rotation); /** * @brief Returns the rotation on the /-axis * @return The absolute rotation */ - float getRotationZ(); + float getRoll(); /** * @brief Sets the rotation of the mesh - * @param t_rotationX The rotation on the X-axis - * @param t_rotationY The rotation on the Y-axis - * @param t_rotationZ The rotation on the Z-axis + * @param t_pitch The rotation on the X-axis + * @param t_yaw The rotation on the Y-axis + * @param t_roll The rotation on the Z-axis */ - void setRotation(float t_rotationX, float t_rotationY, float t_rotationZ); + void setRotation(float t_pitch, float t_yaw, float t_roll); /** * @brief Rotates the mesh a given amount on the X-axis * @param t_delta The amount to rotate */ - void rotateX(float t_delta); + void rotatePitch(float t_delta); /** * @brief Rotates the mesh a given amount on the Y-axis * @param t_delta The amount to rotate */ - void rotateY(float t_delta); + void rotateYaw(float t_delta); /** * @brief Rotates the mesh a given amount on the /-axis * @param t_delta The amount to rotate */ - void rotateZ(float t_delta); + void rotateRoll(float t_delta); /** * @brief Sets the position on the X-axis diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 36c980a..fca1111 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -47,45 +47,45 @@ namespace m3d { m_vertices.clear(); } - void Mesh::setRotationX(float t_rotation) { + void Mesh::setPitch(float t_rotation) { m_rotationX = t_rotation; } - float Mesh::getRotationX() { + float Mesh::getPitch() { return m_rotationX; } - void Mesh::setRotationY(float t_rotation) { + void Mesh::setYaw(float t_rotation) { m_rotationY = t_rotation; } - float Mesh::getRotationY() { + float Mesh::getYaw() { return m_rotationY; } - void Mesh::setRotationZ(float t_rotation) { + void Mesh::setRoll(float t_rotation) { m_rotationZ = t_rotation; } - float Mesh::getRotationZ() { + float Mesh::getRoll() { return m_rotationZ; } - void Mesh::setRotation(float t_rotationX, float t_rotationY, float t_rotationZ) { - m_rotationX = t_rotationX; - m_rotationY = t_rotationY; - m_rotationZ = t_rotationZ; + void Mesh::setRotation(float t_pitch, float t_yaw, float t_roll) { + m_rotationX = t_pitch; + m_rotationY = t_yaw; + m_rotationZ = t_roll; } - void Mesh::rotateX(float t_delta) { + void Mesh::rotatePitch(float t_delta) { m_rotationX += t_delta; } - void Mesh::rotateY(float t_delta) { + void Mesh::rotateYaw(float t_delta) { m_rotationY += t_delta; } - void Mesh::rotateZ(float t_delta) { + void Mesh::rotateRoll(float t_delta) { m_rotationZ += t_delta; } From a666cce8d35e81db82d1aa2274387b3efb50a74f Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 19:44:45 +0200 Subject: [PATCH 081/114] Add option to use radians instead of degrees --- m3dialib/includes/m3d/graphics/camera.hpp | 50 +++++++++++-------- .../includes/m3d/graphics/drawables/mesh.hpp | 42 ++++++++++------ m3dialib/source/graphics/camera.cpp | 50 +++++++++++-------- m3dialib/source/graphics/mesh.cpp | 50 +++++++++++-------- 4 files changed, 112 insertions(+), 80 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/camera.hpp b/m3dialib/includes/m3d/graphics/camera.hpp index 6d0d0b1..5f941bd 100644 --- a/m3dialib/includes/m3d/graphics/camera.hpp +++ b/m3dialib/includes/m3d/graphics/camera.hpp @@ -19,65 +19,75 @@ namespace m3d { /** * @brief Sets the rotation on the X-axis + * @param t_radians Whether to use radians instead of degrees * @param t_rotation The absolute rotation */ - void setPitch(float t_rotation); + void setPitch(float t_rotation, bool t_radians = false); /** * @brief Returns the rotation on the X-axis + * @param t_radians Whether to use radians instead of degrees * @return The absolute rotation */ - float getPitch(); + float getPitch(bool t_radians = false); /** * @brief Sets the rotation on the Y-axis + * @param t_radians Whether to use radians instead of degrees * @param t_rotation The absolute rotation */ - void setYaw(float t_rotation); + void setYaw(float t_rotation, bool t_radians = false); /** * @brief Returns the rotation on the Y-axis + * @param t_radians Whether to use radians instead of degrees * @return The absolute rotation */ - float getYaw(); + float getYaw(bool t_radians = false); /** * @brief Sets the rotation on the Z-axis + * @param t_radians Whether to use radians instead of degrees * @param t_rotation The absolute rotation */ - void setRoll(float t_rotation); + void setRoll(float t_rotation, bool t_radians = false); /** * @brief Returns the rotation on the /-axis + * @param t_radians Whether to use radians instead of degrees * @return The absolute rotation */ - float getRoll(); + float getRoll(bool t_radians = false); /** - * @brief Sets the rotation of the camera - * @param t_pitch The rotation on the X-axis - * @param t_yaw The rotation on the Y-axis - * @param t_roll The rotation on the Z-axis + * @brief Sets the rotation of the mesh + * @param t_pitch The rotation on the X-axis + * @param t_yaw The rotation on the Y-axis + * @param t_roll The rotation on the Z-axis + * @param t_radians Whether to use radians instead of degrees */ - void setRotation(float t_pitch, float t_yaw, float t_roll); + void setRotation(float t_pitch, float t_yaw, float t_roll, bool t_radians = false); /** - * @brief Rotates the camera a given amount on the X-axis - * @param t_delta The amount to rotate + * @brief Rotates the mesh a given amount on the X-axis + * @param t_delta The amount to rotate + * @param t_radians Whether to use radians instead of degrees */ - void rotatePitch(float t_delta); + void rotatePitch(float t_delta, bool t_radians = false); /** - * @brief Rotates the camera a given amount on the Y-axis - * @param t_delta The amount to rotate + * @brief Rotates the mesh a given amount on the Y-axis + * @param t_delta The amount to rotate + * @param t_radians Whether to use radians instead of degrees */ - void rotateYaw(float t_delta); + void rotateYaw(float t_delta, bool t_radians = false); /** - * @brief Rotates the camera a given amount on the Z-axis - * @param t_delta The amount to rotate + * @brief Rotates the mesh a given amount on the /-axis + * @param t_delta The amount to rotate + * @param t_radians Whether to use radians instead of degrees */ - void rotateRoll(float t_delta); + void rotateRoll(float t_delta, bool t_radians = false); /** * @brief Sets the position on the X-axis diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index 574587c..6d4bbc8 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -85,65 +85,75 @@ namespace m3d { /** * @brief Sets the rotation on the X-axis + * @param t_radians Whether to use radians instead of degrees * @param t_rotation The absolute rotation */ - void setPitch(float t_rotation); + void setPitch(float t_rotation, bool t_radians = false); /** * @brief Returns the rotation on the X-axis + * @param t_radians Whether to use radians instead of degrees * @return The absolute rotation */ - float getPitch(); + float getPitch(bool t_radians = false); /** * @brief Sets the rotation on the Y-axis + * @param t_radians Whether to use radians instead of degrees * @param t_rotation The absolute rotation */ - void setYaw(float t_rotation); + void setYaw(float t_rotation, bool t_radians = false); /** * @brief Returns the rotation on the Y-axis + * @param t_radians Whether to use radians instead of degrees * @return The absolute rotation */ - float getYaw(); + float getYaw(bool t_radians = false); /** * @brief Sets the rotation on the Z-axis + * @param t_radians Whether to use radians instead of degrees * @param t_rotation The absolute rotation */ - void setRoll(float t_rotation); + void setRoll(float t_rotation, bool t_radians = false); /** * @brief Returns the rotation on the /-axis + * @param t_radians Whether to use radians instead of degrees * @return The absolute rotation */ - float getRoll(); + float getRoll(bool t_radians = false); /** * @brief Sets the rotation of the mesh - * @param t_pitch The rotation on the X-axis - * @param t_yaw The rotation on the Y-axis - * @param t_roll The rotation on the Z-axis + * @param t_pitch The rotation on the X-axis + * @param t_yaw The rotation on the Y-axis + * @param t_roll The rotation on the Z-axis + * @param t_radians Whether to use radians instead of degrees */ - void setRotation(float t_pitch, float t_yaw, float t_roll); + void setRotation(float t_pitch, float t_yaw, float t_roll, bool t_radians = false); /** * @brief Rotates the mesh a given amount on the X-axis - * @param t_delta The amount to rotate + * @param t_delta The amount to rotate + * @param t_radians Whether to use radians instead of degrees */ - void rotatePitch(float t_delta); + void rotatePitch(float t_delta, bool t_radians = false); /** * @brief Rotates the mesh a given amount on the Y-axis - * @param t_delta The amount to rotate + * @param t_delta The amount to rotate + * @param t_radians Whether to use radians instead of degrees */ - void rotateYaw(float t_delta); + void rotateYaw(float t_delta, bool t_radians = false); /** * @brief Rotates the mesh a given amount on the /-axis - * @param t_delta The amount to rotate + * @param t_delta The amount to rotate + * @param t_radians Whether to use radians instead of degrees */ - void rotateRoll(float t_delta); + void rotateRoll(float t_delta, bool t_radians = false); /** * @brief Sets the position on the X-axis diff --git a/m3dialib/source/graphics/camera.cpp b/m3dialib/source/graphics/camera.cpp index 8c7d6c6..141114a 100644 --- a/m3dialib/source/graphics/camera.cpp +++ b/m3dialib/source/graphics/camera.cpp @@ -10,46 +10,52 @@ namespace m3d { m_rotationY(0.0f), m_rotationZ(0.0f) { /* do nothing */ } - void Camera::setPitch(float t_rotation) { - m_rotationX = t_rotation; + void Camera::setPitch(float t_rotation, bool t_radians) { + m_rotationX = (t_radians ? t_rotation : C3D_AngleFromDegrees(t_rotation)); } - float Camera::getPitch() { - return m_rotationX; + float Camera::getPitch(bool t_radians) { + return (t_radians ? m_rotationX : C3D_AngleFromDegrees(m_rotationX)); } - void Camera::setYaw(float t_rotation) { - m_rotationY = t_rotation; + void Camera::setYaw(float t_rotation, bool t_radians) { + m_rotationY = (t_radians ? t_rotation : C3D_AngleFromDegrees(t_rotation)); } - float Camera::getYaw() { - return m_rotationY; + float Camera::getYaw(bool t_radians) { + return (t_radians ? m_rotationY : C3D_AngleFromDegrees(m_rotationY)); } - void Camera::setRoll(float t_rotation) { - m_rotationZ = t_rotation; + void Camera::setRoll(float t_rotation, bool t_radians) { + m_rotationZ = (t_radians ? t_rotation : C3D_AngleFromDegrees(t_rotation)); } - float Camera::getRoll() { - return m_rotationZ; + float Camera::getRoll(bool t_radians) { + return (t_radians ? m_rotationZ : C3D_AngleFromDegrees(m_rotationZ)); } - void Camera::setRotation(float t_pitch, float t_yaw, float t_roll) { - m_rotationX = t_pitch; - m_rotationY = t_yaw; - m_rotationZ = t_roll; + void Camera::setRotation(float t_pitch, float t_yaw, float t_roll, bool t_radians) { + if (t_radians) { + m_rotationX = t_pitch; + m_rotationY = t_yaw; + m_rotationZ = t_roll; + } else { + m_rotationX = C3D_AngleFromDegrees(t_pitch); + m_rotationY = C3D_AngleFromDegrees(t_yaw); + m_rotationZ = C3D_AngleFromDegrees(t_roll); + } } - void Camera::rotatePitch(float t_delta) { - m_rotationX += t_delta; + void Camera::rotatePitch(float t_delta, bool t_radians) { + m_rotationX += (t_radians ? t_delta : C3D_AngleFromDegrees(t_delta)); } - void Camera::rotateYaw(float t_delta) { - m_rotationY += t_delta; + void Camera::rotateYaw(float t_delta, bool t_radians) { + m_rotationY += (t_radians ? t_delta : C3D_AngleFromDegrees(t_delta)); } - void Camera::rotateRoll(float t_delta) { - m_rotationZ += t_delta; + void Camera::rotateRoll(float t_delta, bool t_radians) { + m_rotationZ += (t_radians ? t_delta : C3D_AngleFromDegrees(t_delta)); } void Camera::setPositionX(float t_position) { diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index fca1111..10e1f08 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -47,46 +47,52 @@ namespace m3d { m_vertices.clear(); } - void Mesh::setPitch(float t_rotation) { - m_rotationX = t_rotation; + void Mesh::setPitch(float t_rotation, bool t_radians) { + m_rotationX = (t_radians ? t_rotation : C3D_AngleFromDegrees(t_rotation)); } - float Mesh::getPitch() { - return m_rotationX; + float Mesh::getPitch(bool t_radians) { + return (t_radians ? m_rotationX : C3D_AngleFromDegrees(m_rotationX)); } - void Mesh::setYaw(float t_rotation) { - m_rotationY = t_rotation; + void Mesh::setYaw(float t_rotation, bool t_radians) { + m_rotationY = (t_radians ? t_rotation : C3D_AngleFromDegrees(t_rotation)); } - float Mesh::getYaw() { - return m_rotationY; + float Mesh::getYaw(bool t_radians) { + return (t_radians ? m_rotationY : C3D_AngleFromDegrees(m_rotationY)); } - void Mesh::setRoll(float t_rotation) { - m_rotationZ = t_rotation; + void Mesh::setRoll(float t_rotation, bool t_radians) { + m_rotationZ = (t_radians ? t_rotation : C3D_AngleFromDegrees(t_rotation)); } - float Mesh::getRoll() { - return m_rotationZ; + float Mesh::getRoll(bool t_radians) { + return (t_radians ? m_rotationZ : C3D_AngleFromDegrees(m_rotationZ)); } - void Mesh::setRotation(float t_pitch, float t_yaw, float t_roll) { - m_rotationX = t_pitch; - m_rotationY = t_yaw; - m_rotationZ = t_roll; + void Mesh::setRotation(float t_pitch, float t_yaw, float t_roll, bool t_radians) { + if (t_radians) { + m_rotationX = t_pitch; + m_rotationY = t_yaw; + m_rotationZ = t_roll; + } else { + m_rotationX = C3D_AngleFromDegrees(t_pitch); + m_rotationY = C3D_AngleFromDegrees(t_yaw); + m_rotationZ = C3D_AngleFromDegrees(t_roll); + } } - void Mesh::rotatePitch(float t_delta) { - m_rotationX += t_delta; + void Mesh::rotatePitch(float t_delta, bool t_radians) { + m_rotationX += (t_radians ? t_delta : C3D_AngleFromDegrees(t_delta)); } - void Mesh::rotateYaw(float t_delta) { - m_rotationY += t_delta; + void Mesh::rotateYaw(float t_delta, bool t_radians) { + m_rotationY += (t_radians ? t_delta : C3D_AngleFromDegrees(t_delta)); } - void Mesh::rotateRoll(float t_delta) { - m_rotationZ += t_delta; + void Mesh::rotateRoll(float t_delta, bool t_radians) { + m_rotationZ += (t_radians ? t_delta : C3D_AngleFromDegrees(t_delta)); } void Mesh::setPositionX(float t_position) { From 4005bb1bc4b5a93bdd1641b1dfce7eee0c62aca1 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 20:55:42 +0200 Subject: [PATCH 082/114] Update .travis.yml --- .travis.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..815ef1c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +language: cpp +dist: trusty +sudo: required +compiler: + - gcc +os: + - linux +before_install: + - wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb + - sudo dpkg -i devkitpro-pacman.deb + - sudo dkp-pacman -S devkitARM picasso tex3ds 3dstools devkit-env libctru citro3d citro2d 3ds-zlib 3ds-tinyxml2 3ds-mpg123 3ds-libpng --noconfirm +script: + - make -C m3dialib/ +branches: + only: + - master + - develop +notifications: + email: + recipents: + - stunthacks@gmail.com + on_success: never + on_failure: always +env: + global: + - DEVKITPRO="/opt/devkitpro" + - DEVKITARM="/opt/devkitpro/devkitARM" From 47e4743c5aa8c90239936c35adfeae8174fdbef0 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 20:57:00 +0200 Subject: [PATCH 083/114] Add travis badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6a1432..1112e9e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# m3diaLib +# m3diaLib [![Build Status](https://travis-ci.org/StuntHacks/m3diaLib.svg?branch=master)](https://travis-ci.org/StuntHacks/m3diaLib) A fast, extensive and powerful allround media and game library for the Nintendo 3DS, written in C++. #### Click [here](#installation) to get to the installation instructions. From 5d810bf3d053f645a3f81f1e62f6209f1d93dddd Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 21:07:12 +0200 Subject: [PATCH 084/114] Fix makefile --- m3dialib/Makefile | 51 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/m3dialib/Makefile b/m3dialib/Makefile index e107db1..4ce2bd4 100644 --- a/m3dialib/Makefile +++ b/m3dialib/Makefile @@ -1,6 +1,7 @@ #--------------------------------------------------------------------------------- .SUFFIXES: #--------------------------------------------------------------------------------- + ifeq ($(strip $(DEVKITARM)),) $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") endif @@ -23,14 +24,14 @@ VERSION := $(M3D_MAJOR).$(M3D_MINOR).$(M3D_PATCH) TARGET := $(notdir $(CURDIR)) SOURCES := $(sort $(dir $(wildcard source/*/))) DATA := data -INCLUDES := $(sort $(dir $(wildcard includes/*/))) +INCLUDES := $(sort $(dir $(wildcard includes/*/))) #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -CFLAGS := -g -Wall -Werror -mword-relocations \ +CFLAGS := -g -Wall -Werror -mword-relocations -save-temps\ -ffunction-sections -fdata-sections \ $(ARCH) $(BUILD_CFLAGS) @@ -59,6 +60,8 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) +SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) #--------------------------------------------------------------------------------- @@ -75,14 +78,20 @@ else endif #--------------------------------------------------------------------------------- -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \ + $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) + +export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) + +export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(addsuffix .h,$(subst .,_,$(BINFILES))) export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ -I. -.PHONY: clean all doc +.PHONY: clean all docs #--------------------------------------------------------------------------------- all: lib/libm3dia.a lib/libm3diad.a @@ -132,12 +141,42 @@ DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- $(OUTPUT) : $(OFILES) +$(OFILES_SOURCES) : $(HFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data #--------------------------------------------------------------------------------- -%.bin.o : %.bin +%.bin.o %_bin.h : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) +#--------------------------------------------------------------------------------- +# rules for assembling GPU shaders +#--------------------------------------------------------------------------------- +define shader-as + $(eval CURBIN := $*.shbin) + $(eval DEPSFILE := $(DEPSDIR)/$*.shbin.d) + echo "$(CURBIN).o: $< $1" > $(DEPSFILE) + echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h + echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h + echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h + picasso -o $(CURBIN) $1 + bin2s $(CURBIN) | $(AS) -o $*.shbin.o +endef + +%.shbin.o %_shbin.h : %.v.pica %.g.pica + @echo $(notdir $^) + @$(call shader-as,$^) + +%.shbin.o %_shbin.h : %.v.pica + @echo $(notdir $<) + @$(call shader-as,$<) + +%.shbin.o %_shbin.h : %.shlist + @echo $(notdir $<) + @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)$(file))) + -include $(DEPENDS) #--------------------------------------------------------------------------------------- From 62f20b1124cd80633ded1d33904b0487b39aaba4 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 21:11:31 +0200 Subject: [PATCH 085/114] Fix wrong include --- m3dialib/source/audio/music.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m3dialib/source/audio/music.cpp b/m3dialib/source/audio/music.cpp index cc27436..f251f1f 100644 --- a/m3dialib/source/audio/music.cpp +++ b/m3dialib/source/audio/music.cpp @@ -1,7 +1,7 @@ #include #include #include "m3d/audio/music.hpp" -#include "m3d/private/private.hpp" +#include "m3d/private/ndsp.hpp" namespace m3d { Music::Music(const std::string& t_filename) : From ff2e8bb429723887d32a0de09570e99fd92aa197 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 21:11:42 +0200 Subject: [PATCH 086/114] Update installation instrctions --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ed05d1d..d2d25ea 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,9 @@ This module isn't availiable at the moment. However, it's planned features are: ...and anything that strikes my mind in the future. ## Installation -To install the library, download the latest release and then execute the following commands: +To install the library, download the latest build and then execute the command `make install`. + +If you want to build it from the source, download the latest release and then execute the following commands: ``` make From 561f10018a575ac160f72a0b868382000be555f8 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 21:14:41 +0200 Subject: [PATCH 087/114] Fix more broken includes --- m3dialib/source/audio/playable.cpp | 2 +- m3dialib/source/audio/sound.cpp | 2 +- m3dialib/source/core/applet.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/m3dialib/source/audio/playable.cpp b/m3dialib/source/audio/playable.cpp index c63e45f..123411b 100644 --- a/m3dialib/source/audio/playable.cpp +++ b/m3dialib/source/audio/playable.cpp @@ -1,5 +1,5 @@ #include "m3d/audio/playable.hpp" -#include "m3d/private/private.hpp" +#include "m3d/private/ndsp.hpp" namespace m3d { void m3d::Playable::onPlay(std::function t_callback) { diff --git a/m3dialib/source/audio/sound.cpp b/m3dialib/source/audio/sound.cpp index 8c65ba1..cc506c5 100644 --- a/m3dialib/source/audio/sound.cpp +++ b/m3dialib/source/audio/sound.cpp @@ -2,7 +2,7 @@ #include #include #include "m3d/audio/sound.hpp" -#include "m3d/private/private.hpp" +#include "m3d/private/ndsp.hpp" namespace m3d { Sound::Sound(const std::string& t_filename) : diff --git a/m3dialib/source/core/applet.cpp b/m3dialib/source/core/applet.cpp index 7109599..c8d014c 100644 --- a/m3dialib/source/core/applet.cpp +++ b/m3dialib/source/core/applet.cpp @@ -1,7 +1,7 @@ #include <3ds.h> #include #include "m3d/core/applet.hpp" -#include "m3d/private/private.hpp" +#include "m3d/private/ndsp.hpp" namespace m3d { Applet::Applet() : From 3a9fbf12c04096e915fa97923f6d03263ad2822b Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Tue, 25 Sep 2018 21:53:05 +0200 Subject: [PATCH 088/114] Add new 3DS speedup --- m3dialib/includes/m3d/core/applet.hpp | 9 ++++++++- m3dialib/source/core/applet.cpp | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/m3dialib/includes/m3d/core/applet.hpp b/m3dialib/includes/m3d/core/applet.hpp index 76d631f..f2f94fb 100644 --- a/m3dialib/includes/m3d/core/applet.hpp +++ b/m3dialib/includes/m3d/core/applet.hpp @@ -152,7 +152,7 @@ namespace m3d { * @brief Returns the model of the system * @return The system model */ - m3d::Applet::ConsoleModel getConsoleModel(); + static m3d::Applet::ConsoleModel getConsoleModel(); /** * @brief Returns whether the system is connected to a wifi network @@ -184,6 +184,13 @@ namespace m3d { */ int getCurrentFrame(); + /** + * @brief Whether to enable the New 3DS speedup or not + * @param t_enable Whether or not to enable the speedup + * @note By default, the speedup is enabled on New 3DS consoles + */ + static inline void enableSpeedup(bool t_enable); + private: /* data */ bool m_sleepAllowed, m_running; diff --git a/m3dialib/source/core/applet.cpp b/m3dialib/source/core/applet.cpp index c8d014c..906bebb 100644 --- a/m3dialib/source/core/applet.cpp +++ b/m3dialib/source/core/applet.cpp @@ -19,6 +19,10 @@ namespace m3d { if (!res) { m3d::priv::ndsp::initialized = true; } + + if (isNew3ds()) { + osSetSpeedupEnable(true); + } } Applet::~Applet() { @@ -198,4 +202,8 @@ namespace m3d { m_currentFrame = m_currentFrame % 60; return m_currentFrame; } + + inline void Applet::enableSpeedup(bool t_enable) { + osSetSpeedupEnable(t_enable); + } } /* m3d */ From 77c79f0620dc6369ace3e3e10570b4b54b4b4acc Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 11:06:34 +0200 Subject: [PATCH 089/114] Prepare lights in constructor --- m3dialib/source/graphics/screen.cpp | 41 +++++++++++++---------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 9704741..030aa00 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -39,6 +39,25 @@ namespace m3d { m_modelUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "model"); m_viewUniform = shaderInstanceGetUniformLocation(m_shader.vertexShader, "view"); + // light + C3D_FVec lightVec; + + C3D_LightEnvInit(&m_lightEnvTop); + LightLut_Phong(&m_lutPhongTop, 30); + C3D_LightEnvLut(&m_lightEnvTop, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &m_lutPhongTop); + lightVec = FVec4_New(0.0f, 0.0f, -0.5f, 1.0f); + C3D_LightInit(&m_lightTop, &m_lightEnvTop); + C3D_LightColor(&m_lightTop, 1.0, 1.0, 1.0); + C3D_LightPosition(&m_lightTop, &lightVec); + + C3D_LightEnvInit(&m_lightEnvBottom); + LightLut_Phong(&m_lutPhongBottom, 30); + C3D_LightEnvLut(&m_lightEnvBottom, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &m_lutPhongBottom); + lightVec = FVec4_New(0.0f, 0.0f, -0.5f, 1.0f); + C3D_LightInit(&m_lightBottom, &m_lightEnvBottom); + C3D_LightColor(&m_lightBottom, 1.0, 1.0, 1.0); + C3D_LightPosition(&m_lightBottom, &lightVec); + clear(); } @@ -443,34 +462,12 @@ namespace m3d { } void Screen::prepareLights(m3d::RenderContext::ScreenTarget t_target) { - C3D_FVec lightVec; - switch (t_target) { case m3d::RenderContext::ScreenTarget::Bottom: - C3D_LightEnvInit(&m_lightEnvBottom); C3D_LightEnvBind(&m_lightEnvBottom); - - LightLut_Phong(&m_lutPhongBottom, 30); - C3D_LightEnvLut(&m_lightEnvBottom, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &m_lutPhongBottom); - - lightVec = FVec4_New(0.0f, 0.0f, -0.5f, 1.0f); - - C3D_LightInit(&m_lightBottom, &m_lightEnvBottom); - C3D_LightColor(&m_lightBottom, 1.0, 1.0, 1.0); - C3D_LightPosition(&m_lightBottom, &lightVec); break; default: - C3D_LightEnvInit(&m_lightEnvTop); C3D_LightEnvBind(&m_lightEnvTop); - - LightLut_Phong(&m_lutPhongTop, 30); - C3D_LightEnvLut(&m_lightEnvTop, GPU_LUT_D0, GPU_LUTINPUT_LN, false, &m_lutPhongTop); - - lightVec = FVec4_New(0.0f, 0.0f, -0.5f, 1.0f); - - C3D_LightInit(&m_lightTop, &m_lightEnvTop); - C3D_LightColor(&m_lightTop, 1.0, 1.0, 1.0); - C3D_LightPosition(&m_lightTop, &lightVec); } } } /* m3d */ From 02cdade19846e837f431c2a209aca12cb34e2bf4 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 11:06:40 +0200 Subject: [PATCH 090/114] Tidy-up code --- m3dialib/source/graphics/model.cpp | 46 ++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/m3dialib/source/graphics/model.cpp b/m3dialib/source/graphics/model.cpp index 083c371..10ab1ac 100644 --- a/m3dialib/source/graphics/model.cpp +++ b/m3dialib/source/graphics/model.cpp @@ -5,23 +5,53 @@ namespace m3d { bool Model::loadFromFile(const std::string& t_filename) { objl::Loader loader; - // Load .obj File if(!loader.LoadFile(t_filename)) { return false; } - // Go through each loaded mesh and out its contents for (unsigned int i = 0; i < loader.LoadedMeshes.size(); i++) { - // Copy one of the loaded meshes to be our current mesh objl::Mesh curMesh = loader.LoadedMeshes[i]; - // Go through each vertex and print its number, - // position, normal, and texture coordinate for (unsigned int j = 0; j < curMesh.Vertices.size() - 2; j += 3) { addPolygon(m3d::Mesh::Polygon( - { {curMesh.Vertices[j].Position.X, curMesh.Vertices[j].Position.Y, curMesh.Vertices[j].Position.Z}, {curMesh.Vertices[j].TextureCoordinate.X, curMesh.Vertices[j].TextureCoordinate.Y}, {curMesh.Vertices[j].Normal.X, curMesh.Vertices[j].Normal.Y, curMesh.Vertices[j].Normal.Z} }, - { {curMesh.Vertices[j + 1].Position.X, curMesh.Vertices[j + 1].Position.Y, curMesh.Vertices[j + 1].Position.Z}, {curMesh.Vertices[j + 1].TextureCoordinate.X, curMesh.Vertices[j + 1].TextureCoordinate.Y}, {curMesh.Vertices[j + 1].Normal.X, curMesh.Vertices[j + 1].Normal.Y, curMesh.Vertices[j + 1].Normal.Z} }, - { {curMesh.Vertices[j + 2].Position.X, curMesh.Vertices[j + 2].Position.Y, curMesh.Vertices[j + 2].Position.Z}, {curMesh.Vertices[j + 2].TextureCoordinate.X, curMesh.Vertices[j + 2].TextureCoordinate.Y}, {curMesh.Vertices[j + 2].Normal.X, curMesh.Vertices[j + 1].Normal.Y, curMesh.Vertices[j + 1].Normal.Z} } + { { + curMesh.Vertices[j].Position.X, + curMesh.Vertices[j].Position.Y, + curMesh.Vertices[j].Position.Z + }, { + curMesh.Vertices[j].TextureCoordinate.X, + curMesh.Vertices[j].TextureCoordinate.Y + }, { + curMesh.Vertices[j].Normal.X, + curMesh.Vertices[j].Normal.Y, + curMesh.Vertices[j].Normal.Z + } }, + + { { + curMesh.Vertices[j + 1].Position.X, + curMesh.Vertices[j + 1].Position.Y, + curMesh.Vertices[j + 1].Position.Z + }, { + curMesh.Vertices[j + 1].TextureCoordinate.X, + curMesh.Vertices[j + 1].TextureCoordinate.Y + }, { + curMesh.Vertices[j + 1].Normal.X, + curMesh.Vertices[j + 1].Normal.Y, + curMesh.Vertices[j + 1].Normal.Z + } }, + + { { + curMesh.Vertices[j + 2].Position.X, + curMesh.Vertices[j + 2].Position.Y, + curMesh.Vertices[j + 2].Position.Z + }, { + curMesh.Vertices[j + 2].TextureCoordinate.X, + curMesh.Vertices[j + 2].TextureCoordinate.Y + }, { + curMesh.Vertices[j + 2].Normal.X, + curMesh.Vertices[j + 2].Normal.Y, + curMesh.Vertices[j + 2].Normal.Z + } } )); } } From 500c67fe5ad116a64fa77168739af51a3f2b2bdc Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 11:06:49 +0200 Subject: [PATCH 091/114] Add documentation --- m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp b/m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp index 5e008eb..34a5a91 100644 --- a/m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/meshes/model.hpp @@ -14,6 +14,12 @@ namespace m3d { */ class Model: public m3d::Mesh { public: + /** + * @brief Loads a model from a file (currently .obj-only) + * @param t_filename The path to the file + * @return `true` if loading was successful, `false` otherwise + * @warning Keep in mind, that your model needs to be triangulated in order to load correctly. An option to automatically triangulate will be added in the future however it will still be faster to triangulate them before-hand. + */ bool loadFromFile(const std::string& t_filename); }; } /* m3d */ From 674c67ba7e6d6e745ff397b12805219a00287a43 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 11:32:55 +0200 Subject: [PATCH 092/114] Add running indicator --- m3dialib/includes/m3d/core/thread.hpp | 7 +++- m3dialib/source/core/thread.cpp | 51 +++++++++++++++------------ 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/m3dialib/includes/m3d/core/thread.hpp b/m3dialib/includes/m3d/core/thread.hpp index 38c04fe..656c55b 100644 --- a/m3dialib/includes/m3d/core/thread.hpp +++ b/m3dialib/includes/m3d/core/thread.hpp @@ -7,6 +7,7 @@ #pragma once #include <3ds.h> +#include #include #include #include "parameter.hpp" @@ -74,6 +75,8 @@ namespace m3d { */ void join(long long unsigned int t_timeout = U64_MAX); + bool isRunning(); + /** * @brief Puts the thread to sleep * @@ -91,12 +94,14 @@ namespace m3d { struct ThreadData { m3d::Parameter m_parameter; std::function m_function; + std::atomic* m_running; }; static void threadFunction(void* t_arg); /* data */ int m_priority, m_stackSize; - bool m_running, m_started; + bool m_started; + std::atomic m_running; m3d::Thread::ThreadData m_data; CTRU_Thread m_thread; }; diff --git a/m3dialib/source/core/thread.cpp b/m3dialib/source/core/thread.cpp index 937185c..8f8b3bd 100644 --- a/m3dialib/source/core/thread.cpp +++ b/m3dialib/source/core/thread.cpp @@ -2,24 +2,26 @@ namespace m3d { Thread::Thread() : - m_running(false), - m_started(false) { /* do nothing */ } + m_started(false), + m_running(false) { /* do nothing */ } Thread::Thread(std::function t_function, m3d::Parameter t_parameter, bool t_autostart, bool t_detached, unsigned long long int t_stackSize) : - m_running(false), - m_started(false) { + m_started(false), + m_running(false) { initialize(t_function, t_parameter, t_autostart, t_detached, t_stackSize); } Thread::~Thread() { - threadJoin(m_thread, U64_MAX); - threadFree(m_thread); + join(); + + if (m_started) threadFree(m_thread); } void Thread::initialize(std::function t_function, m3d::Parameter t_parameter, bool t_autostart, bool t_detached, unsigned long long int t_stackSize) { m_stackSize = t_stackSize; m_data.m_parameter = t_parameter; m_data.m_function = t_function; + m_data.m_running = &m_running; if (t_autostart) { start(t_detached); @@ -31,12 +33,12 @@ namespace m3d { } void Thread::start(bool t_detached) { - if (!m_started && !m_running) { - s32 prio; - svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); - m_thread = threadCreate(threadFunction, &m_data, m_stackSize, prio - 1, -2, t_detached); + if (!m_running) { m_started = true; m_running = true; + s32 prio; + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + m_thread = threadCreate(threadFunction, &m_data, m_stackSize, prio + 1, -2, t_detached); } } @@ -47,7 +49,7 @@ namespace m3d { } void Thread::join(long long unsigned int t_timeout) { - if (m_started) { + if (m_running) { threadJoin(m_thread, t_timeout); threadFree(m_thread); m_running = false; @@ -55,17 +57,22 @@ namespace m3d { } } - void Thread::sleep() { - svcSleepThread(0); - } + bool Thread::isRunning() { + return m_running; + } - void Thread::sleep(int t_milliseconds) { - svcSleepThread(1000000 * t_milliseconds); - } + void Thread::sleep() { + svcSleepThread(0); + } - // private methods - void Thread::threadFunction(void* arg) { - m3d::Thread::ThreadData data = *static_cast(arg); - data.m_function(data.m_parameter); - } + void Thread::sleep(int t_milliseconds) { + svcSleepThread(1000000 * t_milliseconds); + } + + // private methods + void Thread::threadFunction(void* arg) { + m3d::Thread::ThreadData data = *static_cast(arg); + data.m_function(data.m_parameter); + *data.m_running = false; + } } /* m3d */ From 5a887d954a87ebf5b2873092a5eed303bc96d55f Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 11:33:08 +0200 Subject: [PATCH 093/114] Just join the thread in the constructor --- m3dialib/source/audio/music.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/m3dialib/source/audio/music.cpp b/m3dialib/source/audio/music.cpp index f251f1f..6daad4d 100644 --- a/m3dialib/source/audio/music.cpp +++ b/m3dialib/source/audio/music.cpp @@ -21,15 +21,7 @@ namespace m3d { Music::~Music() { stop(); - - if (!m_started) { - m_thread.initialize([](m3d::Parameter){}, nullptr); - m_thread.start(); - } else { - if (m_status != m3d::Music::Status::Stopped) { - m_thread.join(); - } - } + m_thread.join(); } void Music::setFile(const std::string& t_filename) { From 8457c34cea9c41f4444ac01efbbe44fde3cb404c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 12:07:02 +0200 Subject: [PATCH 094/114] Add copy constructor --- m3dialib/includes/m3d/graphics/texture.hpp | 6 ++++++ m3dialib/source/graphics/texture.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/m3dialib/includes/m3d/graphics/texture.hpp b/m3dialib/includes/m3d/graphics/texture.hpp index 09b5a93..0aeecad 100644 --- a/m3dialib/includes/m3d/graphics/texture.hpp +++ b/m3dialib/includes/m3d/graphics/texture.hpp @@ -22,6 +22,12 @@ namespace m3d { */ Texture(); + /** + * @brief Copy constructor + * @param t_texture The texture to copy + */ + Texture(m3d::Texture& t_texture); + /** * @brief Destroys the texture */ diff --git a/m3dialib/source/graphics/texture.cpp b/m3dialib/source/graphics/texture.cpp index 026bf8b..160dfd3 100644 --- a/m3dialib/source/graphics/texture.cpp +++ b/m3dialib/source/graphics/texture.cpp @@ -10,6 +10,10 @@ namespace m3d { m_path(""), m_texture(nullptr) { /* do nothing */ } + Texture::Texture(m3d::Texture& t_texture) { + operator=(t_texture); + } + Texture::~Texture() { if (m_texture != nullptr) { unloadImage(m_image); From 39c04a0bf9f46c2d1f0826ebc46fe4a95b85be24 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 12:07:13 +0200 Subject: [PATCH 095/114] Fix assignment operator when no texture was loaded --- m3dialib/source/graphics/texture.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/m3dialib/source/graphics/texture.cpp b/m3dialib/source/graphics/texture.cpp index 160dfd3..809c980 100644 --- a/m3dialib/source/graphics/texture.cpp +++ b/m3dialib/source/graphics/texture.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -70,9 +71,11 @@ namespace m3d { if (m_texture) C3D_TexDelete(m_texture); - m_texture = static_cast(malloc(sizeof(C3D_Tex))); - C3D_TexInit(m_texture, getNextPow2(rhs.getTexture()->width), getNextPow2(rhs.getTexture()->height), GPU_RGBA8); - *m_texture = *rhs.getTexture(); + if (rhs.getTexture() != nullptr) { + m_texture = static_cast(malloc(sizeof(C3D_Tex))); + C3D_TexInit(m_texture, getNextPow2(rhs.getTexture()->width), getNextPow2(rhs.getTexture()->height), GPU_RGBA8); + memcpy(m_texture, rhs.getTexture(), sizeof(C3D_Tex)); + } return *this; } From 684678879e0ce487085e8d91250130b2c4f02a97 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 12:07:55 +0200 Subject: [PATCH 096/114] Add isTextureBound-method --- m3dialib/includes/m3d/graphics/drawables/mesh.hpp | 6 ++++++ m3dialib/source/graphics/mesh.cpp | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index 6d4bbc8..f4ba038 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -316,6 +316,12 @@ namespace m3d { */ m3d::Texture& getTexture(); + /** + * @brief Returns whether a texture was bound or not + * @return `true` if a texture was bound, `false` otherwise + */ + bool isTextureBound(); + /** * @brief Draws the mesh * @param t_context The RenderContext diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 10e1f08..2744e0c 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -215,6 +215,10 @@ namespace m3d { return m_texture; } + bool Mesh::isTextureBound() { + return m_useTexture; + } + void Mesh::draw(m3d::RenderContext t_context) { if (t_context.getMode() == m3d::RenderContext::Mode::Spatial) { // manipulate modelview matrix @@ -253,7 +257,7 @@ namespace m3d { } } - // private methods + // protected methods void Mesh::updateVbo() { linearFree(m_vbo); m_vbo = static_cast(linearAlloc(m_vertices.size() * sizeof(m3d::Mesh::Polygon::Vertex))); From e2ba36d1ee67d2c3ad0df1df77c1f1ba5ea1c1f9 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 20:05:00 +0200 Subject: [PATCH 097/114] "Fix" text-case --- m3dialib/includes/m3d/audio/playable.hpp | 6 +-- .../includes/m3d/graphics/drawables/mesh.hpp | 2 +- m3dialib/source/audio/mp3Reader.cpp | 40 +++++++++---------- m3dialib/source/audio/music.cpp | 4 +- m3dialib/source/audio/sound.cpp | 4 +- m3dialib/source/audio/wavReader.cpp | 38 +++++++++--------- m3dialib/source/graphics/cuboid.cpp | 2 +- m3dialib/source/graphics/mesh.cpp | 2 +- m3dialib/source/graphics/model.cpp | 2 +- 9 files changed, 50 insertions(+), 50 deletions(-) diff --git a/m3dialib/includes/m3d/audio/playable.hpp b/m3dialib/includes/m3d/audio/playable.hpp index d21fcf0..479b2ff 100644 --- a/m3dialib/includes/m3d/audio/playable.hpp +++ b/m3dialib/includes/m3d/audio/playable.hpp @@ -94,9 +94,9 @@ namespace m3d { virtual void reset() = 0; }; - class Mp3Reader: public m3d::Playable::Reader { + class MP3Reader: public m3d::Playable::Reader { public: - virtual ~Mp3Reader(); + virtual ~MP3Reader(); void set(m3d::Playable::Decoder& t_decoder); int init(const std::string& t_file); uint32_t getRate(); @@ -116,7 +116,7 @@ namespace m3d { uint8_t m_channels; }; - class WavReader: public m3d::Playable::Reader { + class WAVReader: public m3d::Playable::Reader { public: void set(m3d::Playable::Decoder& t_decoder); int init(const std::string& t_file); diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index f4ba038..b43994b 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -332,7 +332,7 @@ namespace m3d { /** * @brief Updates the vertex buffer */ - void updateVbo(); + void updateVBO(); private: /* data */ diff --git a/m3dialib/source/audio/mp3Reader.cpp b/m3dialib/source/audio/mp3Reader.cpp index 1896f85..4c23026 100644 --- a/m3dialib/source/audio/mp3Reader.cpp +++ b/m3dialib/source/audio/mp3Reader.cpp @@ -3,24 +3,24 @@ #include "m3dia.hpp" namespace m3d { - Playable::Mp3Reader::~Mp3Reader() { + Playable::MP3Reader::~MP3Reader() { delete m_buffSize; } - void Playable::Mp3Reader::set(m3d::Playable::Decoder& t_decoder) { - t_decoder.init = std::bind(&m3d::Playable::Mp3Reader::init, this, std::placeholders::_1); - t_decoder.getRate = std::bind(&m3d::Playable::Mp3Reader::getRate, this); - t_decoder.getChannels = std::bind(&m3d::Playable::Mp3Reader::getChannels, this); + void Playable::MP3Reader::set(m3d::Playable::Decoder& t_decoder) { + t_decoder.init = std::bind(&m3d::Playable::MP3Reader::init, this, std::placeholders::_1); + t_decoder.getRate = std::bind(&m3d::Playable::MP3Reader::getRate, this); + t_decoder.getChannels = std::bind(&m3d::Playable::MP3Reader::getChannels, this); m_buffSize = &(t_decoder.m_buffSize); - t_decoder.setPosition = std::bind(&m3d::Playable::Mp3Reader::setPosition, this, std::placeholders::_1); - t_decoder.getPosition = std::bind(&m3d::Playable::Mp3Reader::getPosition, this); - t_decoder.getLength = std::bind(&m3d::Playable::Mp3Reader::getLength, this); - t_decoder.decode = std::bind(&m3d::Playable::Mp3Reader::decode, this, std::placeholders::_1); - t_decoder.exit = std::bind(&m3d::Playable::Mp3Reader::exit, this); - t_decoder.reset = std::bind(&m3d::Playable::Mp3Reader::reset, this); + t_decoder.setPosition = std::bind(&m3d::Playable::MP3Reader::setPosition, this, std::placeholders::_1); + t_decoder.getPosition = std::bind(&m3d::Playable::MP3Reader::getPosition, this); + t_decoder.getLength = std::bind(&m3d::Playable::MP3Reader::getLength, this); + t_decoder.decode = std::bind(&m3d::Playable::MP3Reader::decode, this, std::placeholders::_1); + t_decoder.exit = std::bind(&m3d::Playable::MP3Reader::exit, this); + t_decoder.reset = std::bind(&m3d::Playable::MP3Reader::reset, this); } - int Playable::Mp3Reader::init(const std::string& t_file) + int Playable::MP3Reader::init(const std::string& t_file) { int err = 0; int encoding = 0; @@ -57,39 +57,39 @@ namespace m3d { return 0; } - uint32_t Playable::Mp3Reader::getRate() { + uint32_t Playable::MP3Reader::getRate() { return m_rate; } - uint8_t Playable::Mp3Reader::getChannels() { + uint8_t Playable::MP3Reader::getChannels() { return m_channels; } - void Playable::Mp3Reader::setPosition(int t_position) { + void Playable::MP3Reader::setPosition(int t_position) { mpg123_seek(m_handle, t_position, SEEK_SET); } - int Playable::Mp3Reader::getPosition() { + int Playable::MP3Reader::getPosition() { return mpg123_tell(m_handle); } - int Playable::Mp3Reader::getLength() { + int Playable::MP3Reader::getLength() { return mpg123_length(m_handle); } - uint64_t Playable::Mp3Reader::decode(void* t_buffer) { + uint64_t Playable::MP3Reader::decode(void* t_buffer) { size_t done = 0; mpg123_read(m_handle, static_cast(t_buffer), *m_buffSize, &done); return done / (sizeof(int16_t)); } - void Playable::Mp3Reader::exit() { + void Playable::MP3Reader::exit() { mpg123_close(m_handle); mpg123_delete(m_handle); mpg123_exit(); } - void Playable::Mp3Reader::reset() { + void Playable::MP3Reader::reset() { mpg123_seek(m_handle, 0, SEEK_SET); } } /* m3d */ diff --git a/m3dialib/source/audio/music.cpp b/m3dialib/source/audio/music.cpp index 6daad4d..614aa8e 100644 --- a/m3dialib/source/audio/music.cpp +++ b/m3dialib/source/audio/music.cpp @@ -31,12 +31,12 @@ namespace m3d { switch(m_filetype) { case m3d::Music::FileType::Mp3: - m_reader = new m3d::Playable::Mp3Reader; + m_reader = new m3d::Playable::MP3Reader; m_reader->set(m_decoder); break; case m3d::Music::FileType::Wav: - m_reader = new m3d::Playable::WavReader; + m_reader = new m3d::Playable::WAVReader; m_reader->set(m_decoder); break; diff --git a/m3dialib/source/audio/sound.cpp b/m3dialib/source/audio/sound.cpp index cc506c5..6578e7c 100644 --- a/m3dialib/source/audio/sound.cpp +++ b/m3dialib/source/audio/sound.cpp @@ -38,13 +38,13 @@ namespace m3d { switch(m_filetype) { case m3d::Sound::FileType::Mp3: delete m_reader; - m_reader = new m3d::Playable::Mp3Reader; + m_reader = new m3d::Playable::MP3Reader; m_reader->set(m_decoder); break; case m3d::Sound::FileType::Wav: delete m_reader; - m_reader = new m3d::Playable::WavReader; + m_reader = new m3d::Playable::WAVReader; m_reader->set(m_decoder); break; diff --git a/m3dialib/source/audio/wavReader.cpp b/m3dialib/source/audio/wavReader.cpp index 5fbcde8..787af8c 100644 --- a/m3dialib/source/audio/wavReader.cpp +++ b/m3dialib/source/audio/wavReader.cpp @@ -1,20 +1,20 @@ #include "m3d/audio/playable.hpp" namespace m3d { - void Playable::WavReader::set(m3d::Playable::Decoder& t_decoder) { - t_decoder.init = std::bind(&m3d::Playable::WavReader::init, this, std::placeholders::_1); - t_decoder.getRate = std::bind(&m3d::Playable::WavReader::getRate, this); - t_decoder.getChannels = std::bind(&m3d::Playable::WavReader::getChannels, this); + void Playable::WAVReader::set(m3d::Playable::Decoder& t_decoder) { + t_decoder.init = std::bind(&m3d::Playable::WAVReader::init, this, std::placeholders::_1); + t_decoder.getRate = std::bind(&m3d::Playable::WAVReader::getRate, this); + t_decoder.getChannels = std::bind(&m3d::Playable::WAVReader::getChannels, this); t_decoder.m_buffSize = m_buffSize; - t_decoder.setPosition = std::bind(&m3d::Playable::WavReader::setPosition, this, std::placeholders::_1); - t_decoder.getPosition = std::bind(&m3d::Playable::WavReader::getPosition, this); - t_decoder.getLength = std::bind(&m3d::Playable::WavReader::getLength, this); - t_decoder.decode = std::bind(&m3d::Playable::WavReader::decode, this, std::placeholders::_1); - t_decoder.exit = std::bind(&m3d::Playable::WavReader::exit, this); - t_decoder.reset = std::bind(&m3d::Playable::WavReader::reset, this); + t_decoder.setPosition = std::bind(&m3d::Playable::WAVReader::setPosition, this, std::placeholders::_1); + t_decoder.getPosition = std::bind(&m3d::Playable::WAVReader::getPosition, this); + t_decoder.getLength = std::bind(&m3d::Playable::WAVReader::getLength, this); + t_decoder.decode = std::bind(&m3d::Playable::WAVReader::decode, this, std::placeholders::_1); + t_decoder.exit = std::bind(&m3d::Playable::WAVReader::exit, this); + t_decoder.reset = std::bind(&m3d::Playable::WAVReader::reset, this); } - int Playable::WavReader::init(const std::string& t_file) { + int Playable::WAVReader::init(const std::string& t_file) { m_file = fopen(t_file.c_str(), "rb"); if(m_file == NULL) @@ -40,35 +40,35 @@ namespace m3d { return 0; } - uint32_t Playable::WavReader::getRate() { + uint32_t Playable::WAVReader::getRate() { return (m_header[27] << 24) + (m_header[26] << 16) + (m_header[25] << 8) + (m_header[24]); } - uint8_t Playable::WavReader::getChannels() { + uint8_t Playable::WAVReader::getChannels() { return m_channels; } - void Playable::WavReader::setPosition(int t_position) { + void Playable::WAVReader::setPosition(int t_position) { fseek(m_file, 44 + t_position, SEEK_SET); } - int Playable::WavReader::getPosition() { + int Playable::WAVReader::getPosition() { return m_length; } - int Playable::WavReader::getLength() { + int Playable::WAVReader::getLength() { return ftell(m_file) - 44; } - uint64_t Playable::WavReader::decode(void* t_buffer) { + uint64_t Playable::WAVReader::decode(void* t_buffer) { return fread(t_buffer, 1, m_buffSize, m_file) / sizeof(int16_t); } - void Playable::WavReader::exit() { + void Playable::WAVReader::exit() { fclose(m_file); } - void Playable::WavReader::reset() { + void Playable::WAVReader::reset() { fseek(m_file, 44, SEEK_SET); } } /* m3d */ diff --git a/m3dialib/source/graphics/cuboid.cpp b/m3dialib/source/graphics/cuboid.cpp index caa8f9a..612410b 100644 --- a/m3dialib/source/graphics/cuboid.cpp +++ b/m3dialib/source/graphics/cuboid.cpp @@ -114,6 +114,6 @@ namespace m3d { { {-(m_width / 2), -(m_height / 2), -(m_length / 2)}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} } )); - updateVbo(); + updateVBO(); } } /* m3d */ diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index 2744e0c..d8b13b0 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -258,7 +258,7 @@ namespace m3d { } // protected methods - void Mesh::updateVbo() { + void Mesh::updateVBO() { linearFree(m_vbo); m_vbo = static_cast(linearAlloc(m_vertices.size() * sizeof(m3d::Mesh::Polygon::Vertex))); diff --git a/m3dialib/source/graphics/model.cpp b/m3dialib/source/graphics/model.cpp index 10ab1ac..ad2230a 100644 --- a/m3dialib/source/graphics/model.cpp +++ b/m3dialib/source/graphics/model.cpp @@ -56,7 +56,7 @@ namespace m3d { } } - updateVbo(); + updateVBO(); return true; } From 2b500ce8f671e834bb0d775886860fe6640ca239 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 21:37:21 +0200 Subject: [PATCH 098/114] Add core private --- m3dialib/includes/m3d/private/core.hpp | 18 ++++++++++++++++++ m3dialib/source/private/core.cpp | 10 ++++++++++ 2 files changed, 28 insertions(+) create mode 100644 m3dialib/includes/m3d/private/core.hpp create mode 100644 m3dialib/source/private/core.cpp diff --git a/m3dialib/includes/m3d/private/core.hpp b/m3dialib/includes/m3d/private/core.hpp new file mode 100644 index 0000000..73b08f5 --- /dev/null +++ b/m3dialib/includes/m3d/private/core.hpp @@ -0,0 +1,18 @@ +#ifndef CORE_PRIVATE_H +#define CORE_PRIVATE_H + +#pragma once +#include <3ds.h> +#include + +namespace m3d { + namespace priv { + namespace core { + extern std::atomic ledPatternRunning; + extern Handle ptmsysmHandle; + } /* core */ + } /* priv */ +} /* m3d */ + + +#endif /* end of include guard: CORE_PRIVATE_H */ diff --git a/m3dialib/source/private/core.cpp b/m3dialib/source/private/core.cpp new file mode 100644 index 0000000..9bbb4a4 --- /dev/null +++ b/m3dialib/source/private/core.cpp @@ -0,0 +1,10 @@ +#include "m3d/private/core.hpp" + +namespace m3d { + namespace priv { + namespace core { + std::atomic ledPatternRunning(false); + Handle ptmsysmHandle = 0; + } /* core */ + } /* priv */ +} /* m3d */ From a33019307db10855560e61b318348e26583d35e1 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 21:37:32 +0200 Subject: [PATCH 099/114] Add and implement LEDPattern-class --- m3dialib/includes/m3d/core/ledPattern.hpp | 68 +++++++++++ m3dialib/source/core/ledPattern.cpp | 139 ++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 m3dialib/includes/m3d/core/ledPattern.hpp create mode 100644 m3dialib/source/core/ledPattern.cpp diff --git a/m3dialib/includes/m3d/core/ledPattern.hpp b/m3dialib/includes/m3d/core/ledPattern.hpp new file mode 100644 index 0000000..6f06af9 --- /dev/null +++ b/m3dialib/includes/m3d/core/ledPattern.hpp @@ -0,0 +1,68 @@ +/** + * @file ledPattern.hpp + * @brief Defines the LEDPattern class + */ +/* + * Credits for a lot of the internal code to https://github.com/mariohackandglitch/ctr-led-brary + */ +#ifndef LEDPATTERN_H +#define LEDPATTERN_H + +#pragma once +#include <3ds.h> +#include +#include +#include "m3d/graphics/color.hpp" +#include "m3d/private/core.hpp" + +namespace m3d { + /** + * @brief The LEDPattern class, used for manipulating the notifications LED + */ + class LEDPattern { + public: + LEDPattern(); + + LEDPattern(m3d::Color t_color); + + void addKeyFrame(int t_sample, m3d::Color t_color, bool t_hold = false); + + void deleteKeyframe(int t_sample); + + void clearKeyframes(); + + void setTime(float t_time); + + float getTime(); + + void setDelay(float t_delay); + + float getDelay(); + + void play(); + + static bool isPlaying(); + + static void stop(); + + private: + struct Pattern + { + u8 delay; + u8 smooth; + u8 loop_delay; + u8 unknown1; + u8 r[32]; + u8 g[32]; + u8 b[32]; + }; + + /* data */ + std::map> m_keyFrames; + float m_time, m_delay; + + }; +} /* m3d */ + + +#endif /* end of include guard: LEDPATTERN_H */ diff --git a/m3dialib/source/core/ledPattern.cpp b/m3dialib/source/core/ledPattern.cpp new file mode 100644 index 0000000..0b634c1 --- /dev/null +++ b/m3dialib/source/core/ledPattern.cpp @@ -0,0 +1,139 @@ +#include +#include +#include "m3d/core/ledPattern.hpp" + +namespace m3d { + LEDPattern::LEDPattern() : + m_time(0), + m_delay(0) { + addKeyFrame(0, m3d::Color(0, 0, 0)); + } + + LEDPattern::LEDPattern(m3d::Color t_color) : + m_time(0), + m_delay(0) { + addKeyFrame(0, t_color); + } + + void LEDPattern::addKeyFrame(int t_sample, m3d::Color t_color, bool t_hold) { + if (t_sample > 31 || t_sample < 0) return; + m_keyFrames[t_sample] = std::make_pair(t_color, t_hold); + } + + void LEDPattern::deleteKeyframe(int t_sample) { + m_keyFrames.erase(t_sample); + } + + void LEDPattern::clearKeyframes() { + m_keyFrames.clear(); + } + + void LEDPattern::setTime(float t_time) { + m_time = t_time; + } + + float LEDPattern::getTime() { + return m_time; + } + + void LEDPattern::setDelay(float t_delay) { + m_delay = t_delay; + } + + float LEDPattern::getDelay() { + return m_delay; + } + + void LEDPattern::play() { + if (m3d::priv::core::ptmsysmHandle != 0) { + m3d::LEDPattern::Pattern pat; + + std::map>::iterator it; + + for (it = m_keyFrames.begin(); it != m_keyFrames.end(); it++) { + m3d::Color col1, col2; + int sample1, sample2; + bool hold; + + if (std::next(it) == m_keyFrames.end()) { + col1 = it->second.first; + col2 = it->second.first; + sample1 = it->first; + sample2 = 31; + hold = true; + } else { + col1 = it->second.first; + sample1 = it->first; + + auto next = std::next(it); + col2 = next->second.first; + sample2 = next->first; + hold = next->second.second; + } + + int length = sample2 - sample1; + int stepRed = (int) std::floor((col2.getRed() - col1.getRed()) / length); + int stepGreen = (int) std::floor((col2.getGreen() - col1.getGreen()) / length); + int stepBlue = (int) std::floor((col2.getBlue() - col1.getBlue()) / length); + int red = col1.getRed(), green = col1.getGreen(), blue = col2.getBlue(); + + for (int i = sample1; i <= sample2; i++) { + if (i != sample2) { + if (!hold) { + pat.r[i] = red; + pat.g[i] = green; + pat.b[i] = blue; + + red += stepRed; + green += stepGreen; + blue += stepBlue; + } else { + pat.r[i] = red; + pat.g[i] = green; + pat.b[i] = blue; + } + } else { + pat.r[i] = col2.getRed(); + pat.g[i] = col2.getGreen(); + pat.b[i] = col2.getBlue(); + } + } + } + + pat.unknown1 = 0; + float tempVal = m_time * 0x10; + if (tempVal >= 0x100) tempVal = 0xFF; + pat.delay = (u8)tempVal; + + pat.smooth = (u8) 0x00; + + tempVal = m_delay * 0x10; + if (tempVal >= 0x100) tempVal = 0xFF; + pat.loop_delay = (u8)tempVal; + + u32* ipc = getThreadCommandBuffer(); + ipc[0] = 0x8010640; + memcpy(&ipc[1], &pat, 0x64); + Result ret = svcSendSyncRequest(m3d::priv::core::ptmsysmHandle); + + if (ret >= 0) { + m3d::priv::core::ledPatternRunning = true; + } + } + } + + bool LEDPattern::isPlaying() { + return m3d::priv::core::ledPatternRunning; + } + + void LEDPattern::stop() { + if (!m3d::priv::core::ledPatternRunning || m3d::priv::core::ptmsysmHandle == 0) return; + + m3d::LEDPattern::Pattern pat = {0}; + u32* ipc = getThreadCommandBuffer(); + ipc[0] = 0x8010640; + memcpy(&ipc[1], &pat, 0x64); + svcSendSyncRequest(m3d::priv::core::ptmsysmHandle); + m3d::priv::core::ledPatternRunning = false; + } +} /* m3d */ From 5bbbfa911bf6efbef7ceba6ddf6b64dda2619d6c Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 21:37:47 +0200 Subject: [PATCH 100/114] Get PTM-handle --- m3dialib/source/core/applet.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/m3dialib/source/core/applet.cpp b/m3dialib/source/core/applet.cpp index 906bebb..c4d9395 100644 --- a/m3dialib/source/core/applet.cpp +++ b/m3dialib/source/core/applet.cpp @@ -1,6 +1,8 @@ #include <3ds.h> #include #include "m3d/core/applet.hpp" +#include "m3d/core/ledPattern.hpp" +#include "m3d/private/core.hpp" #include "m3d/private/ndsp.hpp" namespace m3d { @@ -20,12 +22,17 @@ namespace m3d { m3d::priv::ndsp::initialized = true; } + srvInit(); + srvGetServiceHandle(&m3d::priv::core::ptmsysmHandle, "ptm:sysm"); + srvExit(); + if (isNew3ds()) { osSetSpeedupEnable(true); } } Applet::~Applet() { + m3d::LEDPattern::stop(); if (m3d::priv::ndsp::initialized) ndspExit(); sdmcExit(); romfsExit(); From 0cf2e112ecbc0638d0f888bdc6875ef251e58be9 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 21:37:57 +0200 Subject: [PATCH 101/114] Add led pattern include --- m3dialib/includes/m3d/core/core.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/m3dialib/includes/m3d/core/core.hpp b/m3dialib/includes/m3d/core/core.hpp index bc6004d..a7966b4 100644 --- a/m3dialib/includes/m3d/core/core.hpp +++ b/m3dialib/includes/m3d/core/core.hpp @@ -10,6 +10,7 @@ #include "applet.hpp" #include "clock.hpp" #include "error.hpp" +#include "ledPattern.hpp" #include "thread.hpp" #include "time.hpp" From 17bb1fe4d87ab5129278b24e041e4c8362142d45 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Wed, 26 Sep 2018 21:38:05 +0200 Subject: [PATCH 102/114] Add credit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d2d25ea..937b353 100644 --- a/README.md +++ b/README.md @@ -128,3 +128,4 @@ To compile a m3diaLib-app, you need the following dependencies installed (instal * [citro3d](https://github.com/fincs/citro3d) (zLib) * [citro2d](https://github.com/devkitPro/citro2d) (zLib) * [OBJ-Loader](https://github.com/Bly7/OBJ-Loader) (MIT) + * [ctr-led-brary](https://github.com/mariohackandglitch/ctr-led-brary) From 72103a6671ff57b3942e95a5dcd9478c4fb969a3 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 08:36:36 +0200 Subject: [PATCH 103/114] Add size checks and default keyframe --- m3dialib/source/core/ledPattern.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/m3dialib/source/core/ledPattern.cpp b/m3dialib/source/core/ledPattern.cpp index 0b634c1..df82844 100644 --- a/m3dialib/source/core/ledPattern.cpp +++ b/m3dialib/source/core/ledPattern.cpp @@ -26,10 +26,13 @@ namespace m3d { void LEDPattern::clearKeyframes() { m_keyFrames.clear(); + addKeyFrame(0, m3d::Color(0, 0, 0)); } void LEDPattern::setTime(float t_time) { - m_time = t_time; + if (t_time < 0.25f) m_time = 0.25f; + else if (t_time > 16.f) m_time = 16.f; + else m_time = t_time; } float LEDPattern::getTime() { @@ -37,7 +40,7 @@ namespace m3d { } void LEDPattern::setDelay(float t_delay) { - m_delay = t_delay; + m_delay = (t_delay >= 0 ? t_delay : 0.f); } float LEDPattern::getDelay() { From 923e0745a3e6e72b09d7aead65c2f83e003a5925 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 08:36:44 +0200 Subject: [PATCH 104/114] Add documentation --- m3dialib/includes/m3d/core/ledPattern.hpp | 47 +++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/m3dialib/includes/m3d/core/ledPattern.hpp b/m3dialib/includes/m3d/core/ledPattern.hpp index 6f06af9..3052d9b 100644 --- a/m3dialib/includes/m3d/core/ledPattern.hpp +++ b/m3dialib/includes/m3d/core/ledPattern.hpp @@ -21,28 +21,75 @@ namespace m3d { */ class LEDPattern { public: + /** + * @brief Constructs the LED pattern + */ LEDPattern(); + /** + * @brief Initializes the LED pattern with a constant color + * @param t_color The color + */ LEDPattern(m3d::Color t_color); + /** + * @brief Adds a keyframe to the pattern + * @param t_sample The sample-position of the keyframe + * @param t_color The color of the keyframe + * @param t_hold Whether to hold the value of the last keyframe until this one or not + */ void addKeyFrame(int t_sample, m3d::Color t_color, bool t_hold = false); + /** + * @brief Deletes the keyframe at the given sample-position + * @param t_sample The sample-position + */ void deleteKeyframe(int t_sample); + /** + * @brief Clears all keyframes + */ void clearKeyframes(); + /** + * @brief Sets the time the pattern should play until it starts again + * @param t_time The time in seconds (ranging from 0.25 to 16.0) + */ void setTime(float t_time); + /** + * @brief Returns the time the pattern plays until it starts again + * @return The time in seconds + */ float getTime(); + /** + * @brief Sets the time the pattern should wait before it starts again + * @param t_time The time in seconds (ranging from 0 to 16) + * @note When a time >16 is set, the pattern won't loop but will instead keep displaying the last color until it is either stopped or a different pattern is played + */ void setDelay(float t_delay); + /** + * @brief Returns the time the pattern waits before it starts again + * @return The time in seconds + */ float getDelay(); + /** + * @brief Plays the pattern + */ void play(); + /** + * @brief Returns whether a pattern is currently playing or not + * @return `true` if there is an LED pattern playing, `false` otherwise + */ static bool isPlaying(); + /** + * @brief Stops any LED pattern that's currently active + */ static void stop(); private: From 8e0421390a4b9c377621f028fe0eb9082a7a7292 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 09:35:49 +0200 Subject: [PATCH 105/114] Add circlepad support --- m3dialib/includes/m3d/input/circlepad.hpp | 40 +++++++++++++++++++ m3dialib/source/input/circlepad.cpp | 47 +++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 m3dialib/includes/m3d/input/circlepad.hpp create mode 100644 m3dialib/source/input/circlepad.cpp diff --git a/m3dialib/includes/m3d/input/circlepad.hpp b/m3dialib/includes/m3d/input/circlepad.hpp new file mode 100644 index 0000000..516d82a --- /dev/null +++ b/m3dialib/includes/m3d/input/circlepad.hpp @@ -0,0 +1,40 @@ +/** + * @file circlepad.hpp + * @brief Implements support for circlepad input + */ +#ifndef CIRCLEPAD_H +#define CIRCLEPAD_H + +#pragma once +#include <3ds.h> +#include "m3d/graphics/vertex.hpp" + +namespace m3d { + /** + * @brief Namespace for everything circlepad related + */ + namespace circlepad { + /** + * @brief Returns the current circlepad x position (ranging from -155 for completely to the left to +155 for completely to the right) + * @return The curent x position of the circlepad + */ + int getXPosition(); + + /** + * @brief Returns the current circlepad y position (ranging from -155 for completely at the top to +155 for completely at the bottom) + * @return The curent y position of the circlepad + */ + int getYPosition(); + + /** + * @brief Returns the position of the circle pad as a direction vector (i.e. polar coordinates) + * @brief t_useRadians Whether to use radians instead of degrees + * @return The vector representing the position of the circlepad + * @note The first component of the vector represents the angle, the second component represents the length (ranging from 0.f to 1.f) + */ + m3d::Vector2f getDirectionVector(bool t_useRadians = false); + } /* circlepad */ +} /* m3d */ + + +#endif /* end of include guard: CIRCLEPAD_H */ diff --git a/m3dialib/source/input/circlepad.cpp b/m3dialib/source/input/circlepad.cpp new file mode 100644 index 0000000..23218f1 --- /dev/null +++ b/m3dialib/source/input/circlepad.cpp @@ -0,0 +1,47 @@ +#include +#include "m3d/input/circlepad.hpp" + +namespace m3d { + namespace circlepad { + int getXPosition() { + circlePosition circle; + hidCircleRead(&circle); + + return circle.dx; + } + + int getYPosition() { + circlePosition circle; + hidCircleRead(&circle); + + return circle.dy; + } + + m3d::Vector2f getDirectionVector(bool t_useRadians) { + circlePosition circle; + hidCircleRead(&circle); + + float posX = (float) circle.dx / 155.f, + posY = (float) circle.dy / 155.f; + + m3d::Vector2f ret; + if (posX == 0.f && posY > 0.f) { + ret.u = 1.5708f * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); + } else if (posX == 0.f && posY < 0.f) { + ret.u = 4.71239f * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); + } else if (posY == 0.f && posX > 0.f) { + ret.u = 0.f; + } else if (posY == 0.f && posX < 0.f) { + ret.u = 3.14159f * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); + } else if (posX == 0 && posY == 0) { + ret.u = 0.f; + } else { + ret.u = atan(posY / posX) * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); + } + + ret.v = sqrt((pow(posX, 2)) + (pow(posY, 2))); + + return ret; + } + } /* circle */ +} /* m3d */ From 8062c8fd2f2beab630c8940b8a8cf43276018fe1 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 09:36:06 +0200 Subject: [PATCH 106/114] Add circlepad include --- m3dialib/includes/m3d/input/input.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/m3dialib/includes/m3d/input/input.hpp b/m3dialib/includes/m3d/input/input.hpp index 07edcef..1d09294 100644 --- a/m3dialib/includes/m3d/input/input.hpp +++ b/m3dialib/includes/m3d/input/input.hpp @@ -7,8 +7,9 @@ #pragma once -#include "softwareKeyboard.hpp" #include "buttons.hpp" +#include "circlepad.hpp" +#include "softwareKeyboard.hpp" #include "touch.hpp" From c2dca2dfd0fac97565b7a487ad73fc7684a0ea35 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 12:13:39 +0200 Subject: [PATCH 107/114] Add and implement SoftwareKeyboard-class --- .../includes/m3d/input/softwareKeyboard.hpp | 166 +++++++++++- m3dialib/source/input/keyboardEvent.cpp | 35 +++ m3dialib/source/input/softwareKeyboard.cpp | 256 ++++++++++++++++++ 3 files changed, 448 insertions(+), 9 deletions(-) create mode 100644 m3dialib/source/input/keyboardEvent.cpp create mode 100644 m3dialib/source/input/softwareKeyboard.cpp diff --git a/m3dialib/includes/m3d/input/softwareKeyboard.hpp b/m3dialib/includes/m3d/input/softwareKeyboard.hpp index 39f6f3a..67d61ce 100644 --- a/m3dialib/includes/m3d/input/softwareKeyboard.hpp +++ b/m3dialib/includes/m3d/input/softwareKeyboard.hpp @@ -1,21 +1,169 @@ /** * @file softwareKeyboard.hpp - * @brief Defines the m3d::SoftwareKeyboard class + * @brief Defines the SoftwareKeyboard class */ #ifndef SOFTWAREKEYBOARD_H #define SOFTWAREKEYBOARD_H #pragma once +#include <3ds.h> +#include +#include +#include namespace m3d { - /** - * @brief Defines which type of keyboard to show - */ - enum class KeyboardType { - Normal, ///< Normal keyboard with several pages (QWERTY/accents/symbol/mobile) - Qwerty, ///< QWERTY keyboard only - Numpad, ///< Number pad - Western ///< On JPN systems, a text keyboard without Japanese input capabilities, otherwise same as KEYBOARD_TYPE_NORMAL + class SoftwareKeyboard { + public: + /** + * @brief Defines which type of keyboard to show + */ + enum class KeyboardType { + Normal, ///< Normal keyboard with several pages (QWERTY/accents/symbol/mobile) + Qwerty, ///< QWERTY keyboard only + Numpad, ///< Number pad + Western ///< On Japanese systems, a text keyboard without Japanese input capabilities, otherwise same as `Normal` + }; + + /** + * @brief Defines the three keyboard buttons + */ + enum class Button { + Left, ///< Left button (usually displays "Cancel") + Middle, ///< Middle button (usually displays "I forgot") + Right, ///< Right button (usually displays "OK") + None ///< No button (shouldn't happen in most cases) + }; + + /** + * @brief Defines the keyboard's password modes + */ + enum class PasswordMode { + None, ///< Doesn't hide the characters + Hide, ///< Hides the characters immediatley + Delay ///< Hides the characters after a second + }; + + /** + * @brief A keyboard event which will get passed to a validator + */ + class KeyboardEvent { + public: + /** + * @brief Constructs the KeyboardEvent with the given text + * @param t_text The text + */ + KeyboardEvent(const std::string t_text); + + /** + * @brief Displays an error message and then continues the text input + * @param t_message The message to display + */ + void error(const std::string t_message); + + /** + * @brief Displays an error message and then closes the text input + * @param t_message The message to display + */ + void close(const std::string t_message); + + /** + * @brief Marks the input as valid and closes the text input + */ + void valid(); + + /** + * @brief Returns the text entered by the user + * @return The text + */ + std::string getText(); + + #ifndef DOXYGEN_SKIP + SwkbdCallbackResult getResult(); + std::string getMessage(); + #endif + + private: + /* data */ + std::string m_text, m_message; + SwkbdCallbackResult m_callbackResult; + }; + + SoftwareKeyboard(); + + void setValidator(std::function t_validator); + + void setButtonNumber(int t_number); + + int getButtonNumber(); + + void allowEmpty(bool t_allow); + + bool getAllowEmpty(); + + void allowBlank(bool t_allow); + + bool getAllowBlank(); + + void setPredictive(bool t_enable); + + bool isPredictive(); + + void enableMultiline(bool t_enable); + + bool isMultiline(); + + void darkenTop(bool t_enable); + + bool getDarkenTop(); + + void allowHome(bool t_allow); + + bool getAllowHome(); + + void setButtonSubmit(bool t_submit, m3d::SoftwareKeyboard::Button t_button); + + bool getButtonSubmit(m3d::SoftwareKeyboard::Button t_button); + + void setHintText(const std::string& t_text); + + std::string getHintText(); + + void setInitialText(const std::string& t_text); + + std::string getInitialText(); + + void setButtonText(const std::string& t_text, m3d::SoftwareKeyboard::Button t_button); + + std::string getButtonText(m3d::SoftwareKeyboard::Button t_button); + + void setKeyboardType(m3d::SoftwareKeyboard::KeyboardType t_keyboardType); + + m3d::SoftwareKeyboard::KeyboardType getKeyboardType(); + + void setPasswordMode(m3d::SoftwareKeyboard::PasswordMode t_passwordMode); + + m3d::SoftwareKeyboard::PasswordMode getPasswordMode(); + + void display(); + + std::string getLastInput(); + + m3d::SoftwareKeyboard::Button getLastButton(); + + private: + static SwkbdCallbackResult callback(void* t_user, const char** t_ppMessage, const char* t_text, size_t t_textlen); + + /* data */ + int m_numButtons; + bool m_allowEmpty, m_allowBlank, m_predictive, m_multiline, m_darkenTop, m_allowHome, m_leftButtonSubmit, m_middleButtonSubmit, m_rightButtonSubmit; + std::string m_initialText, m_hintText, m_buttonLeftText, m_buttonMiddleText, m_buttonRightText; + m3d::SoftwareKeyboard::KeyboardType m_keyboardType; + m3d::SoftwareKeyboard::PasswordMode m_passwordMode; + std::function m_validator; + + // last input + std::string m_lastText; + m3d::SoftwareKeyboard::Button m_lastButton; }; } /* m3d */ diff --git a/m3dialib/source/input/keyboardEvent.cpp b/m3dialib/source/input/keyboardEvent.cpp new file mode 100644 index 0000000..a30000b --- /dev/null +++ b/m3dialib/source/input/keyboardEvent.cpp @@ -0,0 +1,35 @@ +#include "m3d/input/softwareKeyboard.hpp" + +namespace m3d { + SoftwareKeyboard::KeyboardEvent::KeyboardEvent(const std::string t_text) : + m_text(t_text), + m_message(""), + m_callbackResult(SWKBD_CALLBACK_OK) { /* do nothing */ } + + void SoftwareKeyboard::KeyboardEvent::error(const std::string t_message) { + m_message = t_message; + m_callbackResult = SWKBD_CALLBACK_CONTINUE; + } + + void SoftwareKeyboard::KeyboardEvent::close(const std::string t_message) { + m_message = t_message; + m_callbackResult = SWKBD_CALLBACK_CLOSE; + } + + void SoftwareKeyboard::KeyboardEvent::valid() { + m_message = ""; + m_callbackResult = SWKBD_CALLBACK_OK; + } + + std::string SoftwareKeyboard::KeyboardEvent::getText() { + return m_text; + } + + SwkbdCallbackResult SoftwareKeyboard::KeyboardEvent::getResult() { + return m_callbackResult; + } + + std::string SoftwareKeyboard::KeyboardEvent::getMessage() { + return m_message; + } +} /* m3d */ diff --git a/m3dialib/source/input/softwareKeyboard.cpp b/m3dialib/source/input/softwareKeyboard.cpp new file mode 100644 index 0000000..6b4d6f2 --- /dev/null +++ b/m3dialib/source/input/softwareKeyboard.cpp @@ -0,0 +1,256 @@ +#include "m3d/input/softwareKeyboard.hpp" +#include "m3d/private/input.hpp" +#include "stdio.h" + +namespace m3d { + SoftwareKeyboard::SoftwareKeyboard() : + m_numButtons(3), + m_allowEmpty(true), + m_allowBlank(true), + m_predictive(false), + m_multiline(false), + m_darkenTop(false), + m_leftButtonSubmit(false), + m_middleButtonSubmit(false), + m_rightButtonSubmit(true), + m_initialText(""), + m_hintText(""), + m_buttonLeftText("Cancel"), + m_buttonMiddleText("I forgot"), + m_buttonRightText("OK"), + m_keyboardType(m3d::SoftwareKeyboard::KeyboardType::Normal), + m_passwordMode(m3d::SoftwareKeyboard::PasswordMode::None), + m_validator([](m3d::SoftwareKeyboard::KeyboardEvent& evt){evt.valid();}), + m_lastText(""), + m_lastButton(m3d::SoftwareKeyboard::Button::None) { /* do nothing */ } + + void SoftwareKeyboard::setValidator(std::function t_validator) { + m_validator = t_validator; + } + + void SoftwareKeyboard::setButtonNumber(int t_number) { + m_numButtons = t_number; + } + + int SoftwareKeyboard::getButtonNumber() { + return m_numButtons; + } + + void SoftwareKeyboard::allowEmpty(bool t_allow) { + m_allowEmpty = t_allow; + } + + bool SoftwareKeyboard::getAllowEmpty() { + return m_allowEmpty; + } + + void SoftwareKeyboard::allowBlank(bool t_allow) { + m_allowBlank = t_allow; + } + + bool SoftwareKeyboard::getAllowBlank() { + return m_allowBlank; + } + + void SoftwareKeyboard::setPredictive(bool t_enable) { + m_predictive = t_enable; + } + + bool SoftwareKeyboard::isPredictive() { + return m_predictive; + } + + void SoftwareKeyboard::enableMultiline(bool t_enable) { + m_multiline = t_enable; + } + + bool SoftwareKeyboard::isMultiline() { + return m_multiline; + } + + void SoftwareKeyboard::darkenTop(bool t_enable) { + m_darkenTop = t_enable; + } + + bool SoftwareKeyboard::getDarkenTop() { + return m_darkenTop; + } + + void SoftwareKeyboard::allowHome(bool t_allow) { + m_allowHome = t_allow; + } + + bool SoftwareKeyboard::getAllowHome() { + return m_allowHome; + } + + void SoftwareKeyboard::setButtonSubmit(bool t_submit, m3d::SoftwareKeyboard::Button t_button) { + switch (t_button) { + case m3d::SoftwareKeyboard::Button::Left: + m_leftButtonSubmit = t_submit; + break; + case m3d::SoftwareKeyboard::Button::Middle: + m_middleButtonSubmit = t_submit; + break; + case m3d::SoftwareKeyboard::Button::Right: + m_rightButtonSubmit = t_submit; + default: + return; + } + } + + bool SoftwareKeyboard::getButtonSubmit(m3d::SoftwareKeyboard::Button t_button) { + switch (t_button) { + case m3d::SoftwareKeyboard::Button::Left: + return m_leftButtonSubmit; + break; + case m3d::SoftwareKeyboard::Button::Middle: + return m_middleButtonSubmit; + break; + case m3d::SoftwareKeyboard::Button::Right: + return m_rightButtonSubmit; + break; + default: + return false; + } + } + + void SoftwareKeyboard::setHintText(const std::string& t_text) { + m_hintText = t_text; + } + + std::string SoftwareKeyboard::getHintText() { + return m_hintText; + } + + void SoftwareKeyboard::setInitialText(const std::string& t_text) { + m_initialText = t_text; + } + + std::string SoftwareKeyboard::getInitialText() { + return m_initialText; + } + + void SoftwareKeyboard::setButtonText(const std::string& t_text, m3d::SoftwareKeyboard::Button t_button) { + switch (t_button) { + case m3d::SoftwareKeyboard::Button::Left: + m_buttonLeftText = t_text; + break; + case m3d::SoftwareKeyboard::Button::Middle: + m_buttonMiddleText = t_text; + break; + case m3d::SoftwareKeyboard::Button::Right: + m_buttonRightText = t_text; + default: + return; + } + } + + std::string SoftwareKeyboard::getButtonText(m3d::SoftwareKeyboard::Button t_button) { + switch (t_button) { + case m3d::SoftwareKeyboard::Button::Left: + return m_buttonLeftText; + break; + case m3d::SoftwareKeyboard::Button::Middle: + return m_buttonMiddleText; + break; + case m3d::SoftwareKeyboard::Button::Right: + return m_buttonRightText; + break; + default: + return ""; + } + } + + void SoftwareKeyboard::setKeyboardType(m3d::SoftwareKeyboard::KeyboardType t_keyboardType) { + m_keyboardType = t_keyboardType; + } + + m3d::SoftwareKeyboard::KeyboardType SoftwareKeyboard::getKeyboardType() { + return m_keyboardType; + } + + void SoftwareKeyboard::setPasswordMode(m3d::SoftwareKeyboard::PasswordMode t_passwordMode) { + m_passwordMode = t_passwordMode; + } + + m3d::SoftwareKeyboard::PasswordMode SoftwareKeyboard::getPasswordMode() { + return m_passwordMode; + } + + void SoftwareKeyboard::display() { + m3d::priv::input::keyboardValidator = m_validator; + + SwkbdState swkbd; + char buffer[2048]; + + swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 3, -1); + swkbdSetHintText(&swkbd, m_hintText.c_str()); + swkbdSetInitialText(&swkbd, m_initialText.c_str()); + + swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, m_buttonLeftText.c_str(), m_leftButtonSubmit); + swkbdSetButton(&swkbd, SWKBD_BUTTON_MIDDLE, m_buttonMiddleText.c_str(), m_middleButtonSubmit); + swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, m_buttonRightText.c_str(), m_rightButtonSubmit); + + swkbdSetFeatures(&swkbd, + (m_predictive ? SWKBD_PREDICTIVE_INPUT : 0) | + (m_darkenTop ? SWKBD_DARKEN_TOP_SCREEN : 0) | + (m_multiline ? SWKBD_MULTILINE : 0) | + (m_allowHome ? SWKBD_ALLOW_HOME : 0) + ); + + if (!m_allowBlank && !m_allowEmpty) { + swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY_NOTBLANK, 0, 2048); + } else if (!m_allowBlank) { + swkbdSetValidation(&swkbd, SWKBD_NOTBLANK, 0, 2048); + } else if (!m_allowEmpty) { + swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY, 0, 2048); + } + + switch (m_passwordMode) { + case m3d::SoftwareKeyboard::PasswordMode::Hide: + swkbdSetPasswordMode(&swkbd, SWKBD_PASSWORD_HIDE); + break; + case m3d::SoftwareKeyboard::PasswordMode::Delay: + swkbdSetPasswordMode(&swkbd, SWKBD_PASSWORD_HIDE_DELAY); + break; + default: + swkbdSetPasswordMode(&swkbd, SWKBD_PASSWORD_NONE); + } + + swkbdSetFilterCallback(&swkbd, &m3d::SoftwareKeyboard::callback, NULL); + SwkbdButton button = swkbdInputText(&swkbd, buffer, sizeof(buffer)); + + m_lastText = buffer; + + switch (button) { + case SWKBD_BUTTON_LEFT: + m_lastButton = m3d::SoftwareKeyboard::Button::Left; + break; + case SWKBD_BUTTON_MIDDLE: + m_lastButton = m3d::SoftwareKeyboard::Button::Middle; + break; + case SWKBD_BUTTON_RIGHT: + m_lastButton = m3d::SoftwareKeyboard::Button::Right; + break; + default: + m_lastButton = m3d::SoftwareKeyboard::Button::None; + } + } + + std::string SoftwareKeyboard::getLastInput() { + return m_lastText; + } + + m3d::SoftwareKeyboard::Button SoftwareKeyboard::getLastButton() { + return m_lastButton; + } + + SwkbdCallbackResult SoftwareKeyboard::callback(void* t_user, const char** t_ppMessage, const char* t_text, size_t t_textlen) { + m3d::SoftwareKeyboard::KeyboardEvent evt(t_text); + m3d::priv::input::keyboardValidator(evt); + *t_ppMessage = evt.getMessage().c_str(); + printf("Result: %s\n", evt.getResult() == SWKBD_CALLBACK_OK ? "OK" : (evt.getResult() == SWKBD_CALLBACK_CONTINUE ? "Continue" : "Close")); + return evt.getResult(); + } +} /* m3d */ From 1cf76d953a8fb9355658b47416862526ef99705f Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 12:13:51 +0200 Subject: [PATCH 108/114] Add input private --- m3dialib/includes/m3d/private/input.hpp | 18 ++++++++++++++++++ m3dialib/source/private/input.cpp | 9 +++++++++ 2 files changed, 27 insertions(+) create mode 100644 m3dialib/includes/m3d/private/input.hpp create mode 100644 m3dialib/source/private/input.cpp diff --git a/m3dialib/includes/m3d/private/input.hpp b/m3dialib/includes/m3d/private/input.hpp new file mode 100644 index 0000000..73ce5f2 --- /dev/null +++ b/m3dialib/includes/m3d/private/input.hpp @@ -0,0 +1,18 @@ +#ifndef INPUT_PRIVATE_H +#define INPUT_PRIVATE_H + +#pragma once +#include <3ds.h> +#include +#include "m3d/input/softwareKeyboard.hpp" + +namespace m3d { + namespace priv { + namespace input { + extern std::function keyboardValidator; + } /* input */ + } /* priv */ +} /* m3d */ + + +#endif /* end of include guard: INPUT_PRIVATE_H */ diff --git a/m3dialib/source/private/input.cpp b/m3dialib/source/private/input.cpp new file mode 100644 index 0000000..f40f387 --- /dev/null +++ b/m3dialib/source/private/input.cpp @@ -0,0 +1,9 @@ +#include "m3d/private/input.hpp" + +namespace m3d { + namespace priv { + namespace input { + std::function keyboardValidator = [](m3d::SoftwareKeyboard::KeyboardEvent& evt){evt.valid();}; + } /* input */ + } /* priv */ +} /* m3d */ From 7b2b909903c9cd8fa5b00e57c85ee022ccd109a3 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 13:40:36 +0200 Subject: [PATCH 109/114] Use const char* instead of strings --- m3dialib/includes/m3d/input/softwareKeyboard.hpp | 15 ++++++++++----- m3dialib/source/input/keyboardEvent.cpp | 7 ++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/m3dialib/includes/m3d/input/softwareKeyboard.hpp b/m3dialib/includes/m3d/input/softwareKeyboard.hpp index 67d61ce..12d8c99 100644 --- a/m3dialib/includes/m3d/input/softwareKeyboard.hpp +++ b/m3dialib/includes/m3d/input/softwareKeyboard.hpp @@ -58,13 +58,13 @@ namespace m3d { * @brief Displays an error message and then continues the text input * @param t_message The message to display */ - void error(const std::string t_message); + void error(const char* t_message); /** * @brief Displays an error message and then closes the text input * @param t_message The message to display */ - void close(const std::string t_message); + void close(const char* t_message); /** * @brief Marks the input as valid and closes the text input @@ -79,12 +79,13 @@ namespace m3d { #ifndef DOXYGEN_SKIP SwkbdCallbackResult getResult(); - std::string getMessage(); + const char* getMessage(); #endif private: /* data */ - std::string m_text, m_message; + std::string m_text; + const char* m_message; SwkbdCallbackResult m_callbackResult; }; @@ -96,6 +97,10 @@ namespace m3d { int getButtonNumber(); + void setFixedLength(int t_length); + + int getFixedLength(); + void allowEmpty(bool t_allow); bool getAllowEmpty(); @@ -154,7 +159,7 @@ namespace m3d { static SwkbdCallbackResult callback(void* t_user, const char** t_ppMessage, const char* t_text, size_t t_textlen); /* data */ - int m_numButtons; + int m_numButtons, m_fixedLength; bool m_allowEmpty, m_allowBlank, m_predictive, m_multiline, m_darkenTop, m_allowHome, m_leftButtonSubmit, m_middleButtonSubmit, m_rightButtonSubmit; std::string m_initialText, m_hintText, m_buttonLeftText, m_buttonMiddleText, m_buttonRightText; m3d::SoftwareKeyboard::KeyboardType m_keyboardType; diff --git a/m3dialib/source/input/keyboardEvent.cpp b/m3dialib/source/input/keyboardEvent.cpp index a30000b..75d7ef5 100644 --- a/m3dialib/source/input/keyboardEvent.cpp +++ b/m3dialib/source/input/keyboardEvent.cpp @@ -6,12 +6,12 @@ namespace m3d { m_message(""), m_callbackResult(SWKBD_CALLBACK_OK) { /* do nothing */ } - void SoftwareKeyboard::KeyboardEvent::error(const std::string t_message) { + void SoftwareKeyboard::KeyboardEvent::error(const char* t_message) { m_message = t_message; m_callbackResult = SWKBD_CALLBACK_CONTINUE; } - void SoftwareKeyboard::KeyboardEvent::close(const std::string t_message) { + void SoftwareKeyboard::KeyboardEvent::close(const char* t_message) { m_message = t_message; m_callbackResult = SWKBD_CALLBACK_CLOSE; } @@ -25,11 +25,12 @@ namespace m3d { return m_text; } + // undocumented methods SwkbdCallbackResult SoftwareKeyboard::KeyboardEvent::getResult() { return m_callbackResult; } - std::string SoftwareKeyboard::KeyboardEvent::getMessage() { + const char* SoftwareKeyboard::KeyboardEvent::getMessage() { return m_message; } } /* m3d */ From 041a22d437c6fe1f2f8c8e0a1615fe9c535a66ca Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 13:40:42 +0200 Subject: [PATCH 110/114] Add fixed length --- m3dialib/source/input/softwareKeyboard.cpp | 31 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/m3dialib/source/input/softwareKeyboard.cpp b/m3dialib/source/input/softwareKeyboard.cpp index 6b4d6f2..de8736d 100644 --- a/m3dialib/source/input/softwareKeyboard.cpp +++ b/m3dialib/source/input/softwareKeyboard.cpp @@ -5,6 +5,7 @@ namespace m3d { SoftwareKeyboard::SoftwareKeyboard() : m_numButtons(3), + m_fixedLength(-1), m_allowEmpty(true), m_allowBlank(true), m_predictive(false), @@ -36,6 +37,14 @@ namespace m3d { return m_numButtons; } + void SoftwareKeyboard::setFixedLength(int t_length) { + m_fixedLength = t_length; + } + + int SoftwareKeyboard::getFixedLength() { + return m_fixedLength; + } + void SoftwareKeyboard::allowEmpty(bool t_allow) { m_allowEmpty = t_allow; } @@ -184,7 +193,21 @@ namespace m3d { SwkbdState swkbd; char buffer[2048]; - swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 3, -1); + switch (m_keyboardType) { + case m3d::SoftwareKeyboard::KeyboardType::Normal: + swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, m_numButtons, m_fixedLength); + break; + case m3d::SoftwareKeyboard::KeyboardType::Qwerty: + swkbdInit(&swkbd, SWKBD_TYPE_QWERTY, m_numButtons, m_fixedLength); + break; + case m3d::SoftwareKeyboard::KeyboardType::Western: + swkbdInit(&swkbd, SWKBD_TYPE_WESTERN, m_numButtons, m_fixedLength); + break; + case m3d::SoftwareKeyboard::KeyboardType::Numpad: + swkbdInit(&swkbd, SWKBD_TYPE_NUMPAD, m_numButtons, m_fixedLength); + break; + } + swkbdSetHintText(&swkbd, m_hintText.c_str()); swkbdSetInitialText(&swkbd, m_initialText.c_str()); @@ -196,7 +219,8 @@ namespace m3d { (m_predictive ? SWKBD_PREDICTIVE_INPUT : 0) | (m_darkenTop ? SWKBD_DARKEN_TOP_SCREEN : 0) | (m_multiline ? SWKBD_MULTILINE : 0) | - (m_allowHome ? SWKBD_ALLOW_HOME : 0) + (m_allowHome ? SWKBD_ALLOW_HOME : 0) | + (m_fixedLength > 0 ? SWKBD_FIXED_WIDTH : 0) ); if (!m_allowBlank && !m_allowEmpty) { @@ -249,8 +273,7 @@ namespace m3d { SwkbdCallbackResult SoftwareKeyboard::callback(void* t_user, const char** t_ppMessage, const char* t_text, size_t t_textlen) { m3d::SoftwareKeyboard::KeyboardEvent evt(t_text); m3d::priv::input::keyboardValidator(evt); - *t_ppMessage = evt.getMessage().c_str(); - printf("Result: %s\n", evt.getResult() == SWKBD_CALLBACK_OK ? "OK" : (evt.getResult() == SWKBD_CALLBACK_CONTINUE ? "Continue" : "Close")); + *t_ppMessage = evt.getMessage(); return evt.getResult(); } } /* m3d */ From 630fef263b60ede1c13a992ab3d8a2e3f3e83c65 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 13:56:33 +0200 Subject: [PATCH 111/114] Remove direction vector method --- m3dialib/includes/m3d/input/circlepad.hpp | 8 ------- m3dialib/source/input/circlepad.cpp | 27 ----------------------- 2 files changed, 35 deletions(-) diff --git a/m3dialib/includes/m3d/input/circlepad.hpp b/m3dialib/includes/m3d/input/circlepad.hpp index 516d82a..af21c10 100644 --- a/m3dialib/includes/m3d/input/circlepad.hpp +++ b/m3dialib/includes/m3d/input/circlepad.hpp @@ -25,14 +25,6 @@ namespace m3d { * @return The curent y position of the circlepad */ int getYPosition(); - - /** - * @brief Returns the position of the circle pad as a direction vector (i.e. polar coordinates) - * @brief t_useRadians Whether to use radians instead of degrees - * @return The vector representing the position of the circlepad - * @note The first component of the vector represents the angle, the second component represents the length (ranging from 0.f to 1.f) - */ - m3d::Vector2f getDirectionVector(bool t_useRadians = false); } /* circlepad */ } /* m3d */ diff --git a/m3dialib/source/input/circlepad.cpp b/m3dialib/source/input/circlepad.cpp index 23218f1..a1483a3 100644 --- a/m3dialib/source/input/circlepad.cpp +++ b/m3dialib/source/input/circlepad.cpp @@ -16,32 +16,5 @@ namespace m3d { return circle.dy; } - - m3d::Vector2f getDirectionVector(bool t_useRadians) { - circlePosition circle; - hidCircleRead(&circle); - - float posX = (float) circle.dx / 155.f, - posY = (float) circle.dy / 155.f; - - m3d::Vector2f ret; - if (posX == 0.f && posY > 0.f) { - ret.u = 1.5708f * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); - } else if (posX == 0.f && posY < 0.f) { - ret.u = 4.71239f * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); - } else if (posY == 0.f && posX > 0.f) { - ret.u = 0.f; - } else if (posY == 0.f && posX < 0.f) { - ret.u = 3.14159f * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); - } else if (posX == 0 && posY == 0) { - ret.u = 0.f; - } else { - ret.u = atan(posY / posX) * (t_useRadians ? 1 : (180.0/3.141592653589793238463)); - } - - ret.v = sqrt((pow(posX, 2)) + (pow(posY, 2))); - - return ret; - } } /* circle */ } /* m3d */ From c34961b4b38cbbfb48a962fc17c71602b40de639 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 16:36:34 +0200 Subject: [PATCH 112/114] Fix depth-testing --- m3dialib/source/graphics/screen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/m3dialib/source/graphics/screen.cpp b/m3dialib/source/graphics/screen.cpp index 030aa00..1508e87 100644 --- a/m3dialib/source/graphics/screen.cpp +++ b/m3dialib/source/graphics/screen.cpp @@ -193,6 +193,7 @@ namespace m3d { // draw 3d if(m_drawStackTop3d.size() > 0 || m_drawStackBottom3d.size() > 0) { prepare(); + C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); Mtx_PerspStereoTilt(&m_projection, C3D_AngleFromDegrees(40.0f), C3D_AspectRatioBot, 0.01f, 1000.0f, 0, 2.0f, false); C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, m_projectionUniform, &m_projection); From 5cf036338f94c787cb52f14fd578525ab9959723 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 16:36:45 +0200 Subject: [PATCH 113/114] Fix packages --- travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis.yml b/travis.yml index 9b69df3..c1c4f39 100644 --- a/travis.yml +++ b/travis.yml @@ -7,7 +7,7 @@ os: before_install: - wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb - sudo dpkg -i devkitpro-pacman.deb - - dkp-pacman -S devkitARM picasso tex3ds 3dstools devkit-env libctru citro3d citro2d 3ds-zlib 3ds-tinyxml2 3ds-mpg123 3ds-libpng + - dkp-pacman -S devkitARM picasso tex3ds general-tools 3dstools devkit-env libctru citro3d citro2d 3ds-zlib 3ds-tinyxml2 3ds-mpg123 3ds-libpng script: - make -C m3dialib/ branches: From 37b227fd343c5d86e8c436621fe5543c2af41195 Mon Sep 17 00:00:00 2001 From: Liam Minopulos Date: Thu, 27 Sep 2018 16:59:12 +0200 Subject: [PATCH 114/114] Fix texture setting --- m3dialib/includes/m3d/graphics/drawables/mesh.hpp | 2 +- m3dialib/source/graphics/mesh.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp index b43994b..3418d82 100644 --- a/m3dialib/includes/m3d/graphics/drawables/mesh.hpp +++ b/m3dialib/includes/m3d/graphics/drawables/mesh.hpp @@ -289,7 +289,7 @@ namespace m3d { * @brief Sets the material of the mesh * @param t_material The material */ - void setMaterial(m3d::Material t_material); + void setMaterial(m3d::Material& t_material); /** * @brief Returns the material of the mesh diff --git a/m3dialib/source/graphics/mesh.cpp b/m3dialib/source/graphics/mesh.cpp index d8b13b0..c3d482a 100644 --- a/m3dialib/source/graphics/mesh.cpp +++ b/m3dialib/source/graphics/mesh.cpp @@ -185,7 +185,7 @@ namespace m3d { m_scaleZ += t_delta; } - void Mesh::setMaterial(m3d::Material t_material) { + void Mesh::setMaterial(m3d::Material& t_material) { m_material = t_material; }