Compare commits

...

17 Commits

Author SHA1 Message Date
db7a37d647 Allow the user to have J2D states inside of J2D states.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m23s
2025-02-03 15:30:05 -05:00
26600915db Update Texture.cpp
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2025-02-02 21:21:33 -05:00
7bc87d00ef Cleanup & remove ReImage
Some checks are pending
Run ReCI Build Test / Explore-Gitea-Actions (push) Waiting to run
2025-02-02 06:12:56 -05:00
5e65f17a90 Update RenderTarget.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m14s
fix case where it was possible to create a 0x0 RenderTarget.
2025-01-31 00:08:55 -05:00
426498d53c Performance optimization
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m49s
2025-01-30 23:16:30 -05:00
28bdc7f667 Fix GL error 1280 on windoze.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m11s
2025-01-30 14:18:42 -05:00
Redacted
e8bfa7b6f0 Update .gitea/workflows/buildtest.yml
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m13s
2025-01-29 19:17:12 -05:00
d60620ef7c Update J2D.cpp
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 2m11s
Fix a case that would sometimes cause Render Targets to appear strange due to being drawn at a sub-pixel position.
2025-01-28 19:06:17 -05:00
8cb470ad1c Update ReWindow & don't link to OpenGL.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 4m57s
2025-01-27 11:57:55 -05:00
575a4a0f9b 🤷
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m20s
Removed the specific need for a RenderTarget's texture to have to be square because apparently the problem magically went away.
2025-01-20 20:42:19 -05:00
e9bdaf54b6 Update CMakeLists.txt
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m11s
Latest J3ML
2025-01-20 16:34:09 -05:00
7b2f7de032 Small restructure.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2025-01-20 16:32:09 -05:00
e8245c4442 Latest ReWindow
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m51s
2025-01-15 23:47:58 -05:00
bd918aa351 Creating a texture atlas from multiple small textures.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m57s
2025-01-10 20:51:28 -05:00
a0cc8524d9 J2D DrawLines
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m59s
2025-01-05 12:18:18 -05:00
1964aeae86 Bugfix
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m44s
Fixed a bug that would sometimes cause rendering text after rendering an alpha-masked sprite to be invisible.
2025-01-03 22:22:37 -05:00
b84e2ee2c5 Just pushing what I have.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 14s
2025-01-03 22:16:27 -05:00
23 changed files with 8929 additions and 678 deletions

View File

@@ -17,6 +17,6 @@ jobs:
- run: echo "The ${{ gitea.repository }} repository has been cloned to the runner."
- run: echo "The workflow is now ready to run your tests on the runner."
- run: echo "Install toolchain and run ReCI build test"
- run: apt-get update && apt-get install -y lua5.3 git libxrandr-dev && git clone $RECI_GIT $RECI
- run: apt-get update && apt-get install -y lua5.3 git libxrandr-dev libvulkan-dev && git clone $RECI_GIT $RECI
- run: lua $RECI/reci.lua -f $RECI/scripts/buildtools.reci -f reci/scripts/builddeps.reci -f $RECI/scripts/buildtest.reci
- run: echo "This job's status is ${{ job.status }}."

View File

@@ -22,12 +22,12 @@ CPMAddPackage(
CPMAddPackage(
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/3.4.3.zip
URL https://git.redacted.cc/josh/j3ml/archive/3.4.5.zip
)
CPMAddPackage(
NAME ReWindow
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-26.zip
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-32.zip
)
CPMAddPackage(
@@ -40,17 +40,7 @@ CPMAddPackage(
URL https://git.redacted.cc/josh/jlog/Prerelease-16.zip
)
CPMAddPackage(
NAME ReImage
URL https://git.redacted.cc/Redacted/ReImage/archive/Release-2.0.zip
)
if (WIN32)
#CPMAddPackage(
#NAME harfbuzz
#URL https://github.com/harfbuzz/harfbuzz/archive/refs/tags/9.0.0.zip
#)
CPMAddPackage(
NAME freetype
URL https://github.com/freetype/freetype/archive/refs/tags/VER-2-13-2.zip
@@ -62,9 +52,7 @@ endif()
file(COPY "assets" DESTINATION "${PROJECT_BINARY_DIR}")
file(GLOB_RECURSE ASSETS "assets/*")
file(GLOB_RECURSE HEADERS "include/*.h" "include/*.hpp" )
file(GLOB_RECURSE SOURCES "src/*.c" "src/*.cpp" "src/internals/*.h")
find_package(OpenGL REQUIRED)
file(GLOB_RECURSE SOURCES "src/*.c" "src/*.cpp" "src/*.h")
if (UNIX AND NOT APPLE)
find_package(Freetype REQUIRED)
@@ -85,8 +73,6 @@ include_directories(
target_include_directories(JGL PUBLIC
${PROJECT_SOURCE_DIR}/include
${OPENGL_INCLUDE_DIRS}
${ReImage_SOURCE_DIR}/include
${mcolor_SOURCE_DIR}/include
${J3ML_SOURCE_DIR}/include
${jlog_SOURCE_DIR}/include
@@ -99,13 +85,13 @@ add_executable(JGL_Demo main.cpp)
if (UNIX AND NOT APPLE)
target_include_directories(JGL PRIVATE ${FREETYPE_INCLUDE_DIRS} )
target_link_libraries(JGL PRIVATE ${FREETYPE_LIBRARIES})
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML jlog ReImage glad)
target_link_libraries(JGL PUBLIC mcolor J3ML jlog glad)
endif()
if (WIN32)
target_include_directories(JGL PRIVATE ${freetype_SOURCE_DIR}/include)
target_link_libraries(JGL PRIVATE freetype)
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML glad jlog ReImage glad)
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML glad jlog glad)
endif()
target_link_libraries(JGL_Demo PUBLIC JGL ReWindowLibrary Event glad)
target_link_libraries(JGL_Demo PUBLIC JGL ReWindow Event glad)

46
assets/models/cube.amo Normal file
View File

@@ -0,0 +1,46 @@
ao Cube 1
v 8
1.000000 1.000000 1.000000
1.000000 1.000000 -1.000000
1.000000 -1.000000 1.000000
1.000000 -1.000000 -1.000000
-1.000000 1.000000 1.000000
-1.000000 1.000000 -1.000000
-1.000000 -1.000000 1.000000
-1.000000 -1.000000 -1.000000
vt 14
0.625000 0.500000
0.875000 0.500000
0.875000 0.750000
0.625000 0.750000
0.375000 0.750000
0.625000 1.000000
0.375000 1.000000
0.375000 0.000000
0.625000 0.000000
0.625000 0.250000
0.375000 0.250000
0.125000 0.500000
0.375000 0.500000
0.125000 0.750000
vn 6
0.000000 0.000000 1.000000
0.000000 -1.000000 0.000000
-1.000000 0.000000 0.000000
0.000000 0.000000 -1.000000
1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
f 12
2 0 0 0 1 0 4 2 0
7 3 1 3 4 1 2 3 1
5 5 2 7 6 2 6 7 2
7 8 3 5 9 3 1 10 3
3 11 4 1 12 4 0 4 4
1 13 5 5 12 5 4 0 5
2 0 0 4 1 0 6 2 0
7 3 1 2 4 1 6 3 1
5 5 2 6 6 2 4 7 2
7 8 3 1 9 3 3 10 3
3 11 4 0 12 4 2 4 4
1 13 5 4 12 5 0 0 5
end

View File

@@ -44,6 +44,7 @@ namespace JGL::ShapeCache {
inline VRamList* cube_normal_data = nullptr;
// Facing straight out.
inline VRamList* j2d_default_normal_data = nullptr;
inline VRamList* square_origin_topleft_vertex_data = nullptr;
void Init();
}
@@ -52,8 +53,8 @@ namespace JGL {
using namespace J3ML::LinearAlgebra;
using namespace J3ML::Geometry;
[[nodiscard]] bool Init(const Vector2& window_size, float fovY, float far_plane);
void Update(const Vector2& window_size);
[[nodiscard]] bool Init(const Vector2i& window_size, float fovY, float far_plane);
void Update(const Vector2i& window_size);
inline void PurgeFontCache() { JGL::fontCache.purgeCache(); }
@@ -106,6 +107,13 @@ namespace JGL::J2D {
void DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness = 1);
void DrawLine(const Color4& color, float x1, float y1, float x2, float y2, float thickness = 1);
/// Plots several line segments defined by a series of points to be connected together.
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4.
/// @param points pointer to the first point in the list.
/// @param point_count the number of points to draw.
/// @param thickness The width at which to render the line.
void DrawLines(const Color4& color, const Vector2* points, const size_t& point_count, float thickness = 1);
/// Plots a line segment using a series of points separated by a given distance.
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4.
/// @param A The starting point of the line segment.

View File

@@ -49,7 +49,7 @@ public:
/// Copy one Render Target onto another. Will break if they're not the same size.
// TODO support different sizes. If the destination is too small fix it for them but log a warning.
static void Blit(const RenderTarget& source, RenderTarget* destination);
static void Blit(const RenderTarget& source, RenderTarget* destination, const Vector2i& position = {0, 0});
/// Plots a single pixel onto a Render Target.
/// @param color The color to render.
@@ -57,6 +57,12 @@ public:
/// @param destination The destination RenderTarget.
static void Blit(const Color4& color, const Vector2i& position, RenderTarget* destination);
/// Blit an input texture onto this render target at the given position.
/// @param source Source texture.
/// @param destination Render Target to draw on.
/// @param position Where in the destination to draw.
static void Blit(const Texture* source, RenderTarget* destination, const Vector2i& position = {0, 0});
/// @returns Whether or not this Render Target created it's Texture.
[[nodiscard]] bool OwnsTexture() const;
public:
@@ -70,10 +76,10 @@ public:
[[nodiscard]] bool MSAAEnabled() const;
/// @returns The JGL texture this Render Target draws on.
[[nodiscard]] const Texture* GetJGLTexture() const;
[[nodiscard]] const Texture* GetTexture() const;
/// @returns The OpenGL handle for the texture this Render Target draws on.
[[nodiscard]] GLuint GetGLTextureHandle() const;
[[nodiscard]] GLuint GetTextureHandle() const;
/// @returns The OpenGL handle for this Render Target.
[[nodiscard]] GLuint GetGLFramebufferObjectHandle() const;
@@ -113,4 +119,5 @@ public:
/** @note If this Render Target was made with a Texture that already existed
* the Texture will not be deleted. */
~RenderTarget();
};

View File

@@ -1,13 +1,14 @@
#pragma once
#include <ReImage/Image.h>
#include <J3ML/LinearAlgebra.hpp>
#include<vector>
#include <filesystem>
#include <J3ML/LinearAlgebra/Vector2i.hpp>
#include <Color3.hpp>
#include <Color4.hpp>
#include <glad/glad.h>
namespace JGL {
using namespace ReImage;
enum class TextureFilteringMode : u8 {
using J3ML::LinearAlgebra::Vector2i;
enum class FilteringMode : u8 {
NEAREST = 0, // Fastest for 2D, Sometimes causes graphical issues.
BILINEAR = 1, // Fast and pretty, The best for 2D.
@@ -16,42 +17,59 @@ namespace JGL {
MIPMAP_TRILINEAR = 4 // The prettiest. Still decent speed. Uses more vram.
};
enum class TextureWrappingMode : u8 {
enum class WrappingMode : u8 {
REPEAT = 0,
MIRRORED_REPEAT = 1,
CLAMP_TO_EDGE = 2,
CLAMP_TO_BORDER = 3 // Effectively the same as clamp_to_edge
};
enum class ColorFormat : bool { RGB = false, RGBA = true };
class Texture;
}
/// Represents texture data loaded on the GPU. Contains a handle that can be passed to OpenGL draw calls.
class Texture {
private:
void Erase();
protected:
GLuint texture_handle = 0;
Vector2 texture_size = {0, 0};
ReImage::TextureFlag texture_flags;
ReImage::TextureFormat texture_format;
TextureFilteringMode texture_filtering_mode;
TextureWrappingMode texture_wrapping_mode;
void load(Image* software_texture, const Vector2& size, const TextureFormat& format, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode);
public:
/// Load a texture from a file,
explicit Texture(const std::string& file, TextureFilteringMode filtering_mode = TextureFilteringMode::BILINEAR, TextureWrappingMode wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE, const TextureFlag& flags = TextureFlag::INVERT_Y);
Texture(Image* software_texture, const Vector2& size, const TextureFormat& format, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode);
/* Initialize a texture filled with trash data
this is primarily for the RenderTarget */
explicit Texture(const Vector2& size);
Texture(const Texture& rhs);
~Texture();
public:
[[nodiscard]] GLuint GetGLTextureHandle() const;
[[nodiscard]] Vector2 GetDimensions() const;
[[nodiscard]] TextureFilteringMode GetFilteringMode() const;
[[nodiscard]] TextureWrappingMode GetWrappingMode() const;
[[nodiscard]] TextureFlag GetFlags() const;
[[nodiscard]] TextureFormat GetFormat() const;
[[nodiscard]] std::vector<Color4> GetPixelData() const;
};
/// TODO handle the case of a texture being loaded that exceeds the max texture size.
/// Represents texture data loaded on the GPU. Contains a handle that can be passed to OpenGL draw calls.
class JGL::Texture {
protected:
unsigned int texture_handle = 0;
bool invert_y = false;
Vector2i size = {0, 0};
ColorFormat format = ColorFormat::RGBA;
FilteringMode filtering_mode;
WrappingMode wrapping_mode;
void load(const unsigned char* pixels);
std::vector<unsigned char> png(const std::filesystem::path& file);
std::vector<unsigned char> bmp(const std::filesystem::path& file);
public:
/// @returns A handle used to identify this texture.
[[nodiscard]] unsigned int GetHandle() const;
/// @returns The size of this texture.
[[nodiscard]] Vector2i GetDimensions() const;
/// @returns The filtering mode this texture is using.
[[nodiscard]] FilteringMode GetFilteringMode() const;
/// @returns The way this texture behaves when used on geometry of different sizes.
[[nodiscard]] WrappingMode GetWrappingMode() const;
/// @returns The orientation of this texture in v-ram.
/// @note true is right-side-up because OpenGL defaults to upside-down.
[[nodiscard]] bool Inverted() const;
[[nodiscard]] ColorFormat GetFormat() const;
/// @returns The raw pixels this texture is made up of.
/// @note This will read-back from the GPU. Slow.
[[nodiscard]] std::vector<Color4> GetPixelData() const;
public:
/// Load a texture from a file,
explicit Texture(const std::filesystem::path& file, FilteringMode filtering_mode = FilteringMode::BILINEAR, WrappingMode wrapping_mode = WrappingMode::CLAMP_TO_EDGE, bool invert_y = true);
/// Load a texture from raw pixels.
Texture(const Color4* pixels, const Vector2i& size, const ColorFormat& format, FilteringMode filtering_mode, WrappingMode wrapping_mode);
/// Load a texture from raw pixels.
Texture(const Color3* pixels, const Vector2i& size, const ColorFormat& format, FilteringMode filtering_mode, WrappingMode wrapping_mode);
/// Construct a Texture Atlas from many different textures.
/// @note THIS IS UNFINISHED.
Texture(const Texture* textures, const size_t& texture_count);
/// Initialize a texture filled with trash data.
/// @see RenderTarget
explicit Texture(const Vector2i& size);
}
Texture(const Texture& rhs);
~Texture();
};

View File

@@ -93,6 +93,7 @@ public:
const std::vector<Normal>& vertex_normals = {}, const std::vector<TextureCoordinate>& texture_coordinates = {});
static VertexArray LoadWavefrontOBJ(const std::string& file_text);
static VertexArray LoadAMO(const std::string& file_text);
};

View File

@@ -1,16 +1,17 @@
#include <JGL/JGL.h>
#include <rewindow/types/window.h>
#include <ReWindow/types/Window.h>
#include <Colors.hpp>
#include <chrono>
#include <J3ML/LinearAlgebra/Vector2.hpp>
#include <JGL/logger/logger.h>
#include <J3ML/Geometry/AABB.hpp>
#include <rewindow/logger/logger.h>
#include <ReWindow/Logger.h>
#include <JGL/types/VertexArray.h>
using J3ML::LinearAlgebra::Vector2;
using namespace JGL::Fonts;
using namespace JGL;
using JGL::Font;
float fps = 0.0f;
@@ -111,13 +112,13 @@ Texture* image;
Texture* image_mask;
RenderTarget* j2d_render_target;
class JGLDemoWindow : public ReWindow::RWindow
class JGLDemoWindow : public ReWindow::OpenGLWindow
{
public:
void initGL() {
camera = new Camera;
if (!JGL::Init(GetSize(), 75, 100))
if (!JGL::Init({ GetSize().x, GetSize().y}, 75, 100))
Logger::Fatal("Initialization failed.");
// Load a custom font.
@@ -127,9 +128,9 @@ public:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
image = new Texture("assets/sprites/Re3D.png", TextureFilteringMode::BILINEAR);
image = new Texture("assets/sprites/Re3D.png", FilteringMode::BILINEAR);
image_mask = new Texture("assets/sprites/alpha_mask_2.png");
j2d_render_target = new RenderTarget({540, 540}, {0,0,0,0}, false, MSAA_SAMPLE_RATE::MSAA_NONE);
j2d_render_target = new RenderTarget({540, 500}, {0,0,0,0}, false, MSAA_SAMPLE_RATE::MSAA_NONE);
//Texture::MultiplyByAlphaMask(*image, *image_mask);
}
@@ -145,7 +146,7 @@ public:
pulse++;
float dt = GetDeltaTime();
JGL::Update(GetSize());
JGL::Update({ GetSize().x, GetSize().y });
if (fov_increasing)
fov += 0.025;
@@ -169,6 +170,7 @@ public:
/* if rendering to screen space directly. */
auto test_light = PointLight({2,1,2}, {pulse,pulse,pulse, 255}, {pulse, pulse, pulse, 255}, {0,0,0}, 1, 0.1, 0.01);
// If a 3D object has transparency. The things you'd like to see through it must be drawn before.
J3D::Begin();
J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-1,-0.125,1});
J3D::DrawLine(Colors::Red, {-0.33,-0.125,1}, {-0.33,0.25,1});
@@ -182,19 +184,13 @@ public:
AABB boxes[1] = {{Vector3(-0.2125, -0.2125,0.28750), Vector3(0.2125,0.2125,0.7125)}};
J3D::BatchWireframeAABB(Colors::Yellow, boxes, 1, 1);
//J3D::WireframeOBB(Colors::Red, {0, 0, 1.5f}, {0.40f, 0.10f, 0.10f}, {0,textAngle.y, 0});
//J3D::FillSphere({0,255,0,120}, sphere);
//J3D::DrawCubicBezierCurve(Colors::Blue, {0,0,0.3}, {0,0,0.5}, {0.2,0,0.3}, {0.2, 0.3, 0.1}, 30);
//J3D::WireframeIcosahedron(Colors::Green, {0,0,0.5f}, 0.125f, 1.f);
J3D::End();
J2D::Begin(j2d_render_target, true);
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
J2D::DrawSprite(image, {300, 400}, sprite_radians * 0.10f, {0.5,0.5}, {1, 1}, Colors::White);
J2D::DrawMirrorSprite(image, {400, 300}, Direction::Horizontal | Direction::Vertical, sprite_radians, {0.5,0.5}, {1, 1}, Colors::White);
J2D::DrawPartialSprite(image, {225, 300}, image->GetDimensions() * 0.25, image->GetDimensions() * 0.75, sprite_radians, {0.5, 0.5}, {1,1}, Colors::White);
J2D::DrawPartialSprite(image, Vector2(225, 300), Vector2(image->GetDimensions()) * 0.25, Vector2(image->GetDimensions()) * 0.75, sprite_radians, {0.5, 0.5}, {1,1}, Colors::White);
J2D::FillRect(Colors::Pinks::HotPink, {68, 120}, {32, 32});
J2D::FillGradientRect(Colors::Red, Colors::Blue, Direction::Diagonal_SWNE, {100,52}, {100,100});
J2D::FillRoundedRect(Colors::Red, {200, 52}, {100, 100}, 8, 8);
@@ -210,14 +206,12 @@ public:
J2D::DrawGradientLine(Colors::Red, Colors::Blue, {105, 375}, {200, 275}, 2);
auto result = Jupiteroid.MeasureString("Jupiteroid Font", 16);
//J2D::FillRect(Colors::Gray, {0, 0}, result);
J2D::DrawString(Colors::Green, "Jupteroid Font", 0.f, 0, 1.f, 16, Jupiteroid);
J2D::DrawString(Colors::White, "Position: " + std::to_string(camera->position.x) + " " + std::to_string(camera->position.y) + " " + std::to_string(camera->position.z), 0, 16, 1,16, Jupiteroid);
J2D::DrawString(Colors::White, "ViewAngle: " + std::to_string(camera->angle.x) + " " + std::to_string(camera->angle.y) + " " + std::to_string(camera->angle.z), 0, 33, 1,16, Jupiteroid);
J2D::DrawString(Colors::White, "Framerate: " + std::to_string((int) fps), 0, 48, 1, 16, Jupiteroid);
std::array<Vector2, 5> polygon = {Vector2(200, 400), {220, 420}, {220, 430}, {230, 410}, {200, 400}};
J2D::OutlinePolygon(Colors::White, polygon.data(), polygon.size());
//J2D::FillPolygon(Colors::White, {{200, 400}, {220, 420}, {220, 430}, {230, 410}, {200, 400}});
J2D::DrawCubicBezierCurve(Colors::Blues::CornflowerBlue,
a.position,
b.position,
@@ -230,16 +224,10 @@ public:
c.Draw();
d.Draw();
J2D::End();
RenderTarget::Blit(Colors::Red, {0, 0}, j2d_render_target);
//Draw the Render Target that we just drew all that stuff onto.
J2D::Begin();
J2D::DrawPartialRenderTarget(j2d_render_target, {0, 0}, {0,0}, {512, 512});
J2D::DrawRenderTarget(j2d_render_target, {0, 0});
J2D::DrawSprite(image, image_mask, {0, 0}, 0.25, {0.5, 0.5}, {1,1});
//J2D::DrawSprite(, {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White);
//J2D::DrawSprite( {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White);
J2D::End();
}
@@ -273,15 +261,15 @@ public:
auto mouse = GetMouseCoordinates();
a.Update(mouse);
b.Update(mouse);
c.Update(mouse);
d.Update(mouse);
a.Update({(float) mouse.x, (float) mouse.y});
b.Update({(float) mouse.x, (float) mouse.y});
c.Update({(float) mouse.x, (float) mouse.y});
d.Update({(float) mouse.x, (float) mouse.y});
display();
int glError = glGetError();
if (glError != GL_NO_ERROR)
std::cout << glError << std::endl;
GLSwapBuffers();
SwapBuffers();
}
@@ -304,39 +292,37 @@ public:
}
bool OnResizeRequest(const ReWindow::WindowResizeRequestEvent& e) override {return true;}
JGLDemoWindow() : ReWindow::RWindow() {}
JGLDemoWindow(const std::string& title, int width, int height) : ReWindow::RWindow(title, width, height) {}
JGLDemoWindow(const std::string& title, int width, int height) : ReWindow::OpenGLWindow(title, width, height, 2, 1) {}
};
int main(int argc, char** argv) {
auto* window = new JGLDemoWindow("JGL Demo Window", 1280, 720);
window->SetRenderer(RenderingAPI::OPENGL);
window->Open();
if (!window->Open())
exit(-1);
window->initGL();
window->SetResizable(true);
window->SetVsyncEnabled(true);
window->SetVsyncEnabled(false);
std::ifstream file("assets/models/cube.obj");
std::ifstream file("assets/models/cube.amo");
if (!file.is_open())
return -1;
/*
std::stringstream buffer;
buffer << file.rdbuf();
std::string file_text = buffer.str();
file.close();
//std::cout << "File contents:\n" << file_text << std::endl;
std::cout << file_text << std::endl;
auto result = VertexArray::LoadWavefrontOBJ(file_text);
auto result = VertexArray::LoadAMO(file_text);
*/
ReWindow::Logger::Error.EnableConsole(false);
ReWindow::Logger::Warning.EnableConsole(false);
ReWindow::Logger::Debug.EnableConsole(false);
//ReWindow::Logger::Error.EnableConsole(false);
//ReWindow::Logger::Warning.EnableConsole(false);
//ReWindow::Logger::Debug.EnableConsole(false);
while (window->IsAlive())
window->ManagedRefresh();
return 0;
//for (const auto& v3 : result)
//std::cout << v3.x << " " << v3.y << " " << v3.z << std::endl;
}

View File

@@ -1,4 +1,4 @@
#include "JGL/JGL.h"
#include <JGL/JGL.h>
namespace JGL::Data {
unsigned char Jupiteroid_Data[] = {

View File

@@ -5,12 +5,12 @@
#include <glad/glad.h>
#include <JGL/JGL.h>
#include <JGL/logger/logger.h>
#include "internals/include/internals.h"
#include "renderer/OpenGL/internals/internals.h"
namespace JGL {
using namespace J3ML;
bool Init(const Vector2& window_size, float fovY, float far_plane) {
bool Init(const Vector2i& ws, float fovY, float far_plane) {
gladLoadGL();
if (!MeetsRequirements()) {
Logger::Fatal("The graphics driver does not meet the minimum requirements to run this program.");
@@ -20,15 +20,18 @@ namespace JGL {
InitTextEngine();
Fonts::Init();
ShapeCache::Init();
OpenGLState::window_size = window_size;
JGL::window_size = ws;
J3D::fov = fovY;
J3D::far_plane = far_plane;
return true;
}
void Update(const Vector2& window_size) {
OpenGLState::window_size = window_size;
glViewport(0, 0, (int) window_size.x, (int) window_size.y);
void Update(const Vector2i& ws) {
if (state_stack.Size())
Logger::Error("You shouldn't be running JGL::Update while inside a J2D or J3D context.");
JGL::window_size = ws;
glViewport(0, 0, window_size.x, window_size.y);
}
bool MeetsRequirements() {

View File

@@ -43,10 +43,13 @@ void JGL::ShapeCache::Init() {
if (!cube_index_data)
cube_index_data = new VRamList(indices.data(), indices.size());
if (!cube_normal_data) {
if (!cube_normal_data)
cube_normal_data = new VRamList(vertex_normals.data(), vertex_normals.size());
}
if (!square_origin_topleft_vertex_data) {
std::array<Vector2, 4> square_vertices = { Vector2(0, 0), {1, 0}, {1, -1}, {0, -1} };
square_origin_topleft_vertex_data = new VRamList(square_vertices.data(), square_vertices.size());
}
if (!j2d_default_normal_data) {
std::array<GLfloat, 3> normal {0, 0, 1};
j2d_default_normal_data = new VRamList(normal.data(), normal.size());

View File

@@ -1,7 +0,0 @@
#pragma once
#include <string>
namespace JGL {
class VertexArray;
VertexArray LoadWavefrontOBJ(const std::string& file_text);
}

View File

@@ -1,59 +0,0 @@
/// Things used in J2D and J3D that should not be exposed to the user of the library.
#pragma once
#include "glad/glad.h"
#include <array>
#include <vector>
#include "J3ML/LinearAlgebra/Vector2.hpp"
#include "JGL/types/RenderTarget.h"
#include "JGL/types/Light.h"
#include "JGL/logger/logger.h"
namespace JGL {
inline constexpr std::array<const LightBase*, 8> empty_light_array = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
inline bool inJ2D = false;
inline bool inJ3D = false;
std::vector<Vector3> TriangleMeshVertexNormals(const Vector3* vertices, const size_t& vertex_count, const unsigned int* indices, const size_t& index_count);
}
namespace JGL::OpenGLState {
inline JGL::RenderTarget* render_target = nullptr;
inline Vector2 window_size;
inline GLfloat oldColor[4] = {0, 0, 0, 1};
inline GLfloat baseColor[4] = {1, 1, 1, 1};
inline GLuint current_fbo = 0;
inline GLint viewport[4] = {0, 0, 0, 0};
inline bool wasTexture2DEnabled = false;
inline bool wasTextureCoordArrayEnabled = false;
inline bool wasNormalArrayEnabled = false;
inline bool wasDepthTestEnabled = false;
inline bool wasVertexArraysEnabled = false;
inline bool wasCullFaceEnabled = false;
inline bool wasBlendEnabled = false;
inline bool wasColorArrayEnabled = false;
inline GLint activeTextureUnit = 0;
}
namespace JGL::J2D {
inline std::array<const LightBase*, 8> required_lights;
inline std::vector<const LightBase*> light_array;
}
namespace JGL::J3D {
// List of lights required for each objects in the scene. up-to 8. For example, the sun. Or a flash-light.
inline std::array<const LightBase*, 8> required_lights;
// List of all lights in the scene.
inline std::vector<const LightBase*> optional_lights;
inline float far_plane = 0;
inline float fov = 0;
// Enables lighting and selects the correct lights to use.
void SelectLights(const Vector3& position);
// Resets the GL lights to default and disables them. Then, disables lighting.
void ResetLights();
[[nodiscard]] bool UsingLighting();
}

View File

@@ -1,176 +1,72 @@
#include <JGL/JGL.h>
#include <JGL/logger/logger.h>
#include <J3ML/Algorithm/Bezier.hpp>
#include "../internals/include/internals.h"
#include "internals/internals.h"
void JGL::J2D::Begin(RenderTarget* rt, bool clear_buffers) {
GLfloat old_clear_color[4];
if (rt != nullptr) {
OpenGLState::render_target = rt;
glGetFloatv(GL_COLOR_CLEAR_VALUE, old_clear_color);
glGetIntegerv(GL_VIEWPORT, OpenGLState::viewport);
OpenGLState::current_fbo = JGL::RenderTarget::GetActiveGLFramebufferHandle();
JGL::RenderTarget::SetActiveGLRenderTarget(*rt);
if (!(rt->GetJGLTexture()->GetFlags() & INVERT_Y))
Logger::Warning("You're rendering onto a texture that is upside-down. Your draw commands won't work how you'd expect.");
}
void JGL::J2D::Begin(RenderTarget* render_target, bool clear_buffers) {
State current_state = default_state;
state_stack.Push(State::SaveState());
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
if (rt == nullptr)
glViewport(0, 0, (int) OpenGLState::window_size.x, (int) OpenGLState::window_size.y),
glOrtho(0, OpenGLState::window_size.x, OpenGLState::window_size.y, 0, -1, 1);
else
glOrtho(0, rt->GetDimensions().x, rt->GetDimensions().y, 0, -1, 1);
if (render_target) {
if (!render_target->GetTexture()->Inverted())
Logger::Warning("You're rendering onto a texture that is upside-down. Your draw commands won't work how you'd expect.");
current_state.current_fbo = render_target->GetGLFramebufferObjectHandle();
current_state.viewport[2] = render_target->GetDimensions().x;
current_state.viewport[3] = render_target->GetDimensions().y;
current_state.clear_color[0] = render_target->GetClearColor().RN();
current_state.clear_color[1] = render_target->GetClearColor().GN();
current_state.clear_color[2] = render_target->GetClearColor().BN();
current_state.clear_color[3] = render_target->GetClearColor().AN();
}
else {
current_state.viewport[2] = window_size.x;
current_state.viewport[3] = window_size.y;
}
State::RestoreState(current_state);
if (render_target != nullptr && clear_buffers) {
glClearColor(render_target->GetClearColor().RedChannelNormalized(), render_target->GetClearColor().GreenChannelNormalized(), render_target->GetClearColor().BlueChannelNormalized(), render_target->GetClearColor().AlphaChannelNormalized());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
glOrtho(0, current_state.viewport[2], current_state.viewport[3], 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
//Get what the draw color was before we did anything.
glGetFloatv(GL_CURRENT_COLOR, OpenGLState::oldColor);
glColor4fv(OpenGLState::baseColor);
glGetIntegerv(GL_ACTIVE_TEXTURE, &OpenGLState::activeTextureUnit);
OpenGLState::activeTextureUnit = OpenGLState::activeTextureUnit - GL_TEXTURE0;
if (OpenGLState::activeTextureUnit != 0) {
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
}
if (glIsEnabled(GL_DEPTH_TEST))
OpenGLState::wasDepthTestEnabled = true,
glDisable(GL_DEPTH_TEST);
else
OpenGLState::wasDepthTestEnabled = false;
if (!glIsEnabled(GL_VERTEX_ARRAY))
OpenGLState::wasVertexArraysEnabled = false,
glEnableClientState(GL_VERTEX_ARRAY);
else
OpenGLState::wasVertexArraysEnabled = true;
if (glIsEnabled(GL_NORMAL_ARRAY))
OpenGLState::wasNormalArrayEnabled = true,
glDisableClientState(GL_NORMAL_ARRAY);
else
OpenGLState::wasNormalArrayEnabled = false;
if (!glIsEnabled(GL_CULL_FACE))
OpenGLState::wasCullFaceEnabled = false,
glEnable(GL_CULL_FACE),
glCullFace(GL_BACK);
else
OpenGLState::wasCullFaceEnabled = true;
if (!glIsEnabled(GL_BLEND))
OpenGLState::wasBlendEnabled = false,
glEnable(GL_BLEND),
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else
OpenGLState::wasBlendEnabled = true;
if (glIsEnabled(GL_TEXTURE_2D))
OpenGLState::wasTexture2DEnabled = true,
glDisable(GL_TEXTURE_2D);
if (glIsEnabled(GL_TEXTURE_COORD_ARRAY))
OpenGLState::wasTextureCoordArrayEnabled = true;
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (glIsEnabled(GL_COLOR_ARRAY))
OpenGLState::wasColorArrayEnabled = true,
glDisableClientState(GL_COLOR_ARRAY);
else
OpenGLState::wasColorArrayEnabled = false;
if (!inJ3D)
inJ2D = true;
else { Logger::Error("Beginning J2D context inside of J3D context?"); }
if (rt != nullptr && clear_buffers) {
glClearColor(rt->GetClearColor().RedChannelNormalized(), rt->GetClearColor().GreenChannelNormalized(), rt->GetClearColor().BlueChannelNormalized(), rt->GetClearColor().AlphaChannelNormalized());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]);
}
}
void JGL::J2D::End() {
//Change back to the previous projection (The 3D one in Re3D's case.)
//Change back to the previous projection.
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
if (OpenGLState::wasDepthTestEnabled)
glEnable(GL_DEPTH_TEST);
if (!OpenGLState::wasVertexArraysEnabled)
glDisableClientState(GL_VERTEX_ARRAY);
auto previous_state = state_stack.PreviousState();
if (!previous_state)
Logger::Fatal("Calling J2D::End before J2D::Begin.");
if (!OpenGLState::wasCullFaceEnabled)
glDisable(GL_CULL_FACE);
if (!OpenGLState::wasBlendEnabled)
glDisable(GL_BLEND);
//Select whatever texture mapper was selected before.
glActiveTexture(GL_TEXTURE0 + OpenGLState::activeTextureUnit);
glClientActiveTexture(GL_TEXTURE0 + OpenGLState::activeTextureUnit);
if (OpenGLState::wasTexture2DEnabled)
glEnable(GL_TEXTURE_2D);
if (OpenGLState::wasTextureCoordArrayEnabled)
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (OpenGLState::wasNormalArrayEnabled)
glEnableClientState(GL_NORMAL_ARRAY);
if (OpenGLState::wasColorArrayEnabled)
glEnableClientState(GL_COLOR_ARRAY);
//Put the draw color back how it was before.
glColor4fv(OpenGLState::oldColor);
if (OpenGLState::render_target != nullptr) {
OpenGLState::render_target->MSAABlit();
OpenGLState::render_target = nullptr;
glBindFramebuffer(GL_FRAMEBUFFER, OpenGLState::current_fbo);
glViewport(OpenGLState::viewport[0], OpenGLState::viewport[1], OpenGLState::viewport[2], OpenGLState::viewport[3]);
}
inJ2D = false;
}
void JGL::J2D::RequiredLight(const JGL::LightBase* light) {
bool success = false;
for (auto& item : required_lights)
if (item == nullptr) {
item = light;
success = true;
break;
}
if (!success)
Logger::Error("You cannot specify more than 8 required lights.");
}
void JGL::J2D::OptionalLights(const LightBase** lights, const size_t& light_count) {
for (size_t i = 0; i < light_count; i++)
light_array.push_back(lights[i]);
State::RestoreState(*previous_state);
state_stack.Pop();
}
void JGL::J2D::DrawPoint(const Color4& color, const Vector2& coordinates, float radius) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
glPointSize(radius);
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), coordinates.ptr());
glDrawArrays(GL_POINTS, 0, 1);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::DrawPoint(const Color4& color, float x, float y, float radius) {
@@ -178,7 +74,7 @@ void JGL::J2D::DrawPoint(const Color4& color, float x, float y, float radius) {
}
void JGL::J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B, float thickness) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {A, B};
@@ -186,13 +82,24 @@ void JGL::J2D::DrawLine(const Color4& color, const Vector2& A, const Vector2& B,
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINES, 0, 2);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::DrawLine(const Color4& color, float x, float y, float w, float h, float thickness) {
JGL::J2D::DrawLine(color, {x, y}, {w, h}, thickness);
}
void J2D::DrawLines(const Color4& color, const Vector2* points, const size_t& point_count, float thickness) {
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
glLineWidth(thickness);
glColor3ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points);
glDrawArrays(GL_LINE_STRIP, 0, point_count);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::DrawDottedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing, float thickness) {
float distance = Vector2::Distance(A, B);
Vector2 direction = (B - A).Normalized();
@@ -243,7 +150,7 @@ void JGL::J2D::DrawDashedLine(const Color4& color, float x1, float y1, float x2,
}
void JGL::J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {A, B};
@@ -256,7 +163,7 @@ void JGL::J2D::DrawGradientLine(const Color4& color1, const Color4& color2, cons
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_COLOR_ARRAY);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float y, float w, float h, float thickness) {
@@ -264,7 +171,7 @@ void DrawGradientLine(const Color4& color1, const Color4& color2, float x, float
}
void JGL::J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
@@ -273,22 +180,28 @@ void JGL::J2D::OutlineRect(const Color4& color, const Vector2& pos, const Vector
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINE_LOOP, 0, 4);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FillRect(const Color4& color, const Vector2& pos, const Vector2& size) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_QUADS, 0, 4);
glColor4fv(OpenGLState::baseColor);
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::square_origin_topleft_vertex_data->GetHandle());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), nullptr);
glPushMatrix();
glTranslatef(pos.x, pos.y + size.y, 0);
glScalef(size.x, size.y, 1);
glDrawArrays(GL_QUADS, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glPopMatrix();
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {{pos.x, pos.y}, {pos.x, pos.y + size.y}, {pos.x + size.x, pos.y + size.y}, {pos.x + size.x, pos.y}};
@@ -317,11 +230,11 @@ void JGL::J2D::FillGradientRect(const Color4& color1, const Color4& color2, cons
glColorPointer(4, GL_FLOAT, 0, colors.data());
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_COLOR_ARRAY);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, unsigned int subdivisions) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
JGL::J2D::FillRect(color, {pos.x + radius, pos.y}, {size.x - 2 * radius, size.y});
@@ -384,16 +297,16 @@ void JGL::J2D::DrawSprite(const JGL::RenderTarget& rt, const Vector2& position,
//Correct for the render-target being upside-down.
Direction d{};
if (inversion == Direction::None && !(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
if (inversion == Direction::None && !rt.GetTexture()->Inverted())
d = Direction::Vertical;
else if (inversion == Direction::Horizontal) {
d = Direction::Horizontal;
if (!(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
if (!rt.GetTexture()->Inverted())
d = Direction::Horizontal | Direction::Vertical;
}
else if (inversion& Direction::Horizontal && inversion& Direction::Vertical) {
d = Direction::Horizontal;
if (!(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
if (!rt.GetTexture()->Inverted())
d = Direction::Horizontal | Direction::Vertical;
}
@@ -401,15 +314,16 @@ void JGL::J2D::DrawSprite(const JGL::RenderTarget& rt, const Vector2& position,
if (rt.OwnsTexture())
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
JGL::J2D::DrawPartialSprite(*rt.GetJGLTexture(), position, {0, 0}, Vector2(rt.GetDimensions()), rad_rotation, origin, scale, color, d);
auto r_position = Vector2(Math::Floor(position.x), Math::Floor(position.y));
JGL::J2D::DrawPartialSprite(*rt.GetTexture(), r_position, {0, 0}, Vector2(rt.GetDimensions()), rad_rotation, origin, scale, color, d);
if (rt.OwnsTexture())
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void JGL::J2D::DrawSprite(const Texture& texture, const Texture &alpha_mask, const Vector2& position, float rad_rotation,
void JGL::J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, const Vector2& position, float rad_rotation,
const Vector2& origin, const Vector2& scale,const Color4& color, JGL::Direction inversion) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
if (texture.GetDimensions() != alpha_mask.GetDimensions())
@@ -417,11 +331,9 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Texture &alpha_mask, con
const Vector2 size = Vector2(texture.GetDimensions());
std::array<Vector2, 4> textureCoordinates{};
if (texture.GetFlags() & INVERT_Y)
std::array<Vector2, 4> textureCoordinates = { Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0) };
if (texture.Inverted())
textureCoordinates = {Vector2(0, 1), Vector2(0, 0), Vector2(1, 0), Vector2(1, 1)};
else
textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0)};
// TODO: Kind of a mess, refactor to be more sensible later.
// Factors in scaling and origin correctly.
@@ -463,7 +375,7 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Texture &alpha_mask, con
// Texture 0.
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
glBindTexture(GL_TEXTURE_2D, texture.GetHandle());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
@@ -475,7 +387,7 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Texture &alpha_mask, con
glEnableClientState(GL_VERTEX_ARRAY);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, alpha_mask.GetGLTextureHandle());
glBindTexture(GL_TEXTURE_2D, alpha_mask.GetHandle());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
@@ -485,7 +397,6 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Texture &alpha_mask, con
// Reset Texture 1.
glBindTexture(GL_TEXTURE_2D, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_TEXTURE_2D);
// Reset Texture 0.
@@ -495,7 +406,7 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Texture &alpha_mask, con
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, const Vector2& position, float rad_rotation,
@@ -518,17 +429,17 @@ void JGL::J2D::DrawPartialRenderTarget(const JGL::RenderTarget& rt, const Vector
//Correct for the render-target being upside-down.
Direction d{};
if (inversion == Direction::None && !(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
if (inversion == Direction::None && !rt.GetTexture()->Inverted())
d = Direction::Vertical;
else if (inversion == Direction::Horizontal) {
d = Direction::Horizontal;
if (!(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
if (!rt.GetTexture()->Inverted())
d = Direction::Horizontal | Direction::Vertical;
}
else if (inversion& Direction::Horizontal && inversion& Direction::Vertical) {
d = Direction::Horizontal;
if (!(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
if (!rt.GetTexture()->Inverted())
d = Direction::Horizontal | Direction::Vertical;
}
@@ -536,7 +447,10 @@ void JGL::J2D::DrawPartialRenderTarget(const JGL::RenderTarget& rt, const Vector
if (rt.OwnsTexture())
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
JGL::J2D::DrawPartialSprite(*rt.GetJGLTexture(), position, sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, d);
auto r_position = Vector2(Math::Floor(position.x), Math::Floor(position.y));
auto r_sub_texture_position = Vector2(Math::Floor(sub_texture_position.x), Math::Floor(sub_texture_position.y));
JGL::J2D::DrawPartialSprite(*rt.GetTexture(), r_position, r_sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, d);
if (rt.OwnsTexture())
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -549,14 +463,14 @@ void JGL::J2D::DrawPartialRenderTarget(const JGL::RenderTarget* rt, const Vector
void JGL::J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotation, const Vector2& origin,
const Vector2& scale, const Color4& color, Direction inversion) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
const Vector2 size = Vector2(texture.GetDimensions());
std::array<Vector2, 4> textureCoordinates{};
if (texture.GetFlags() & INVERT_Y)
if (texture.Inverted())
textureCoordinates = {Vector2(0, 1), Vector2(0, 0), Vector2(1, 0), Vector2(1, 1)};
else
textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0)};
@@ -598,12 +512,12 @@ void JGL::J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glColor4ubv(color.ptr());
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
glBindTexture(GL_TEXTURE_2D, texture.GetHandle());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
glDrawArrays(GL_QUADS, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
@@ -622,13 +536,13 @@ void JGL::J2D::DrawSprite(const Texture& texture, float positionX, float positio
void JGL::J2D::DrawPartialSprite(const Texture& texture, const Vector2& position, const Vector2& sub_texture_position,
const Vector2& sub_texture_size, float rad_rotation, const Vector2& origin,
const Vector2& scale, const Color4& color, Direction inversion) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
const Vector2 textureSize = Vector2(texture.GetDimensions());
std::array<GLfloat, 8> textureCoordinates{};
// Calculate texture coordinates (relative to the whole texture)
if (!(texture.GetFlags() & INVERT_Y))
if (!texture.Inverted())
textureCoordinates = {
sub_texture_position.x / textureSize.x,
sub_texture_position.y / textureSize.y,
@@ -687,12 +601,12 @@ void JGL::J2D::DrawPartialSprite(const Texture& texture, const Vector2& position
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glColor4ubv(color.ptr());
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
glBindTexture(GL_TEXTURE_2D, texture.GetHandle());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates.data());
glDrawArrays(GL_QUADS, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
@@ -708,20 +622,20 @@ void JGL::J2D::DrawPartialSprite(const JGL::Texture& texture, float positionX, f
}
void JGL::J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position, Direction mirror_axis, float rad_rotation, const Vector2& origin, const Vector2& scale, const Color4& color) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
if (mirror_axis == Direction::None)
Logger::Warning("Drawing non-mirrored sprite with JGL::J2D::DrawMirrorSprite?");
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
glBindTexture(GL_TEXTURE_2D, texture.GetHandle());
Vector2 size = Vector2(texture.GetDimensions());
std::array<Vector2, 4> textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 0)};
if (mirror_axis == Direction::Horizontal) {
size.x *= 2;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
if (texture.GetFlags() & INVERT_Y)
if (texture.Inverted())
textureCoordinates = {Vector2(0, 1), Vector2(0, 0), Vector2(2, 0), Vector2(2, 1)};
else
textureCoordinates = {Vector2(0, 0), Vector2(0, 1), Vector2(2, 1), Vector2(2, 0)};
@@ -730,7 +644,7 @@ void JGL::J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position,
else if (mirror_axis == Direction::Vertical) {
size.y *= 2;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
if (texture.GetFlags() & INVERT_Y)
if (texture.Inverted())
textureCoordinates = {Vector2(0, 2), Vector2(0, 0), Vector2(1, 0), Vector2(1, 2)};
else
textureCoordinates = {Vector2(0, 0), Vector2(0, 2), Vector2(1, 2), Vector2(1, 0)};
@@ -740,7 +654,7 @@ void JGL::J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
size *= 2;
if (texture.GetFlags() & INVERT_Y)
if (texture.Inverted())
textureCoordinates = {Vector2(0, 2), Vector2(0, 0), Vector2(2, 0), Vector2(2, 2)};
else
textureCoordinates = {Vector2(0, 0), Vector2(0, 2), Vector2(2, 2), Vector2(2, 0)};
@@ -775,23 +689,24 @@ void JGL::J2D::DrawMirrorSprite(const Texture& texture, const Vector2& position,
glDrawArrays(GL_QUADS, 0, 4);
//Reset the wrapping mode.
if (texture.GetWrappingMode() == TextureWrappingMode::CLAMP_TO_EDGE)
if (texture.GetWrappingMode() == WrappingMode::CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
else if (texture.GetWrappingMode() == TextureWrappingMode::REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
else if (texture.GetWrappingMode() == WrappingMode::REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
else if (texture.GetWrappingMode() == TextureWrappingMode::CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
else if (texture.GetWrappingMode() == WrappingMode::CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glBindTexture(GL_TEXTURE_2D, 0);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
void JGL::J2D::OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions, float thickness) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
float step = (2.f * Math::Pi) / (float) subdivisions;
@@ -814,11 +729,11 @@ void JGL::J2D::OutlineCircle(const Color4& color, const Vector2& center, float r
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_LINE_LOOP, 0, (int) vertices.size());
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
GLfloat angle, x, y;
@@ -842,11 +757,11 @@ void JGL::J2D::FillCircle(const Color4& color, const Vector2& center, float radi
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}};
@@ -855,11 +770,11 @@ void JGL::J2D::OutlineTriangle(const Color4& color, const Triangle2D& tri, float
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINE_LOOP, 0, 3);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FillTriangle(const Color4& color, const Triangle2D& tri) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}};
@@ -867,11 +782,11 @@ void JGL::J2D::FillTriangle(const Color4& color, const Triangle2D& tri) {
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Triangle2D& tri) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
Vector2 vertices[] = {{tri.A.x, tri.A.y}, {tri.B.x, tri.B.y}, {tri.C.x, tri.C.y}};
@@ -884,7 +799,7 @@ void JGL::J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_COLOR_ARRAY);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
//TODO render all in once pass with GL_LINE_LOOP instead of separate lines.
@@ -907,7 +822,7 @@ void JGL::J2D::DrawCubicBezierCurve(const Color4& color, const Vector2& controlA
}
void JGL::J2D::OutlinePolygon(const Color4& color, const Vector2* points, int points_size, float thickness) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
if (points[0] != points[points_size -1])
@@ -917,7 +832,7 @@ void JGL::J2D::OutlinePolygon(const Color4& color, const Vector2* points, int po
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points);
glDrawArrays(GL_LINE_LOOP, 0, points_size);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::DrawGradientLine(const Color4& color_a, const Color4& color_b, float x, float y, float w, float h,
@@ -927,7 +842,7 @@ void JGL::J2D::DrawGradientLine(const Color4& color_a, const Color4& color_b, fl
void JGL::J2D::DrawArc(const Color4& color, const Vector2& center, float radius, float arc_begin, float arc_end, unsigned int subdivisions, float thickness)
{
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
if (arc_begin == arc_end)
@@ -955,7 +870,7 @@ void JGL::J2D::DrawArc(const Color4& color, const Vector2& center, float radius,
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_LINE_STRIP, 0, (int) vertices.size());
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, float thickness)
@@ -1042,7 +957,7 @@ void JGL::J2D::OutlineChamferRect(const Color4& color, const Vector2& pos, const
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices);
glDrawArrays(GL_LINE_LOOP, 0, 8);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::DrawPoints(const Color4& color, const Vector2* points, int num_points, float radius) {
@@ -1050,7 +965,7 @@ void JGL::J2D::DrawPoints(const Color4& color, const Vector2* points, int num_po
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), points);
glDrawArrays(GL_POINTS, 0, num_points);
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FIllTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC) {
@@ -1064,7 +979,7 @@ void JGL::J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color
void JGL::J2D::OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness,
int subdivisions) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
float step = (2.f * Math::Pi) / (float) subdivisions;
@@ -1086,11 +1001,11 @@ void JGL::J2D::OutlineEllipse(const Color4& color, const Vector2& position, floa
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_LINE_LOOP, 0, (int) vertices.size());
glColor4fv(OpenGLState::baseColor);
glColor4fv(default_state.draw_color);
}
void JGL::J2D::FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions) {
if (!inJ2D)
if (!state_stack.Size())
Logger::Error("Drawing J2D element before J2D begin.");
GLfloat angle, x, y;
@@ -1114,5 +1029,5 @@ void JGL::J2D::FillEllipse(const Color4& color, const Vector2& position, float r
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
glColor4fv(OpenGLState::baseColor);
}
glColor4fv(default_state.draw_color);
}

View File

@@ -4,7 +4,7 @@
#include <J3ML/Geometry/OBB.hpp>
#include <J3ML/Algorithm/Bezier.hpp>
#include <JGL/types/Light.h>
#include "../internals/include/internals.h"
#include "internals/internals.h"
std::array<GLfloat, 16> JGL::OpenGLPerspectiveProjectionRH(float fovY, float aspect, float z_near, float z_far) {
@@ -28,7 +28,7 @@ void JGL::J3D::ChangeFarPlane(float far_plane) {
void JGL::J3D::RequiredLight(const JGL::LightBase* light) {
bool success = false;
for (auto& i : required_lights)
for (auto& i : current_state.required_lights)
if (i == nullptr) {
i = light;
success = true;
@@ -41,86 +41,82 @@ void JGL::J3D::RequiredLight(const JGL::LightBase* light) {
void JGL::J3D::OptionalLights(const JGL::LightBase** lights, const size_t& light_count) {
for (size_t i = 0; i < light_count; i++)
optional_lights.push_back(lights[i]);
current_state.optional_lights.push_back(lights[i]);
}
void JGL::J3D::Begin(bool two_pass) {
auto aspect = (float) OpenGLState::window_size.x / (float) OpenGLState::window_size.y;
auto aspect = (float) window_size.x / (float) window_size.y;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf(OpenGLPerspectiveProjectionRH(fov, aspect, 0.001, far_plane).data());
glMatrixMode(GL_MODELVIEW);
//Get what the draw color was before we did anything.
glGetFloatv(GL_CURRENT_COLOR, OpenGLState::oldColor);
glColor4fv(OpenGLState::baseColor);
glGetFloatv(GL_CURRENT_COLOR, current_state.draw_color);
glColor4fv(current_state.draw_color);
if (!glIsEnabled(GL_DEPTH_TEST))
OpenGLState::wasDepthTestEnabled = false,
current_state.depth_test = false,
glEnable(GL_DEPTH_TEST);
else
OpenGLState::wasDepthTestEnabled = true;
current_state.depth_test = true;
OpenGLState::wasVertexArraysEnabled = false;
current_state.vertex_array = false;
if (!glIsEnabled(GL_VERTEX_ARRAY))
OpenGLState::wasVertexArraysEnabled = false,
current_state.vertex_array = false,
glEnableClientState(GL_VERTEX_ARRAY);
if (glIsEnabled(GL_NORMAL_ARRAY))
OpenGLState::wasNormalArrayEnabled = true,
current_state.normal_array = true,
glDisableClientState(GL_NORMAL_ARRAY);
if (glIsEnabled(GL_TEXTURE_COORD_ARRAY))
OpenGLState::wasTextureCoordArrayEnabled = true,
current_state.texture_coordinate_array = true,
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (glIsEnabled(GL_TEXTURE_2D))
OpenGLState::wasTexture2DEnabled = true,
current_state.texture_2D = true,
glDisable(GL_TEXTURE_2D);
OpenGLState::wasCullFaceEnabled = false;
current_state.cull_face = false;
if (glIsEnabled(GL_CULL_FACE))
OpenGLState::wasCullFaceEnabled = true,
current_state.cull_face = true,
glDisable(GL_CULL_FACE);
if (!glIsEnabled(GL_BLEND))
OpenGLState::wasBlendEnabled = false,
current_state.blend = false,
glEnable(GL_BLEND),
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else
OpenGLState::wasBlendEnabled = true;
current_state.blend = true;
// Reset the lights.
required_lights = empty_light_array;
optional_lights = {};
current_state.required_lights = empty_light_array;
current_state.optional_lights = {};
glDisable(GL_LIGHTING);
if (!inJ2D)
inJ3D = true;
else
Logger::Error("Beginning J3D context inside of J2D context?");
}
void JGL::J3D::End() {
if (!OpenGLState::wasDepthTestEnabled)
if (!current_state.depth_test)
glDisable(GL_DEPTH_TEST);
if (!OpenGLState::wasVertexArraysEnabled)
if (!current_state.vertex_array)
glDisableClientState(GL_VERTEX_ARRAY);
if (OpenGLState::wasTexture2DEnabled)
if (current_state.texture_2D)
glEnable(GL_TEXTURE_2D);
if (!OpenGLState::wasBlendEnabled)
if (!current_state.blend)
glDisable(GL_BLEND);
if (OpenGLState::wasCullFaceEnabled)
if (current_state.cull_face)
glEnable(GL_CULL_FACE);
if (OpenGLState::wasNormalArrayEnabled)
if (current_state.normal_array)
glEnableClientState(GL_NORMAL_ARRAY);
if (OpenGLState::wasTextureCoordArrayEnabled)
if (current_state.texture_coordinate_array)
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (glIsEnabled(GL_LIGHTING)) {
@@ -135,25 +131,21 @@ void JGL::J3D::End() {
glDisable(GL_LIGHT7);
}
required_lights = empty_light_array;
optional_lights = {};
current_state.required_lights = empty_light_array;
current_state.optional_lights = {};
//Put the draw color back how it was before.
glColor4fv(OpenGLState::oldColor);
inJ3D = false;
glColor4fv(current_state.draw_color);
}
void JGL::J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
Vector3 vertices[] = {A, B};
glLineWidth(thickness);
glColor4ubv(color.ptr());
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices);
glDrawArrays(GL_LINES, 0, 2);
glColor4fv(OpenGLState::baseColor);
glColor4fv(current_state.draw_color);
}
void JGL::J3D::WireframeSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int stacks) {
@@ -166,9 +158,6 @@ void JGL::J3D::WireframeSphere(const Color4& color, const Sphere& sphere, float
}
void JGL::J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, unsigned int sectors, unsigned int stacks) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
// Create one sphere with a radius of 1 about 0, 0.
float r = 1;
std::vector<Vector3> vertices((sectors + 1) * (stacks + 1));
@@ -204,7 +193,7 @@ void JGL::J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres,
glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
glPopMatrix();
}
glColor4fv(OpenGLState::baseColor);
glColor4fv(current_state.draw_color);
}
void JGL::J3D::WireframeRevoSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
@@ -263,14 +252,10 @@ void JGL::J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spher
glPopMatrix();
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glColor4fv(OpenGLState::baseColor);
glColor4fv(current_state.draw_color);
}
void JGL::J3D::WireframeIcosphere(const Color4& color, const Vector3& position, float radius, float thickness,
unsigned int subdivisions) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
void JGL::J3D::WireframeIcosphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int subdivisions) {
// NOTE2SELF: Code i'm borrowing this from uses float-packed-arrays rather than discrete Vectors
// working on translating that correctly...
@@ -341,9 +326,6 @@ void JGL::J3D::WireframeIcosphere(const Color4& color, const Vector3& position,
}
void JGL::J3D::WireframeIcosahedron(const Color4& color, const Vector3& position, float radius, float thickness) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
// TODO: Revise this once J3ML::Geometry::Icosahedron is implemented.
const float h_angle = J3ML::Math::Pi / 180.f * 72.f; // 72 degree = 360 / 5;
const float v_angle = J3ML::Math::Atan(1.0f / 2.f); // elevation = 26.565;
@@ -382,7 +364,7 @@ void JGL::J3D::WireframeIcosahedron(const Color4& color, const Vector3& position
//glBindBuffer(GL_ARRAY_BUFFER, vertices.size());
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());
glColor4fv(OpenGLState::baseColor);
glColor4fv(current_state.draw_color);
}
void JGL::J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_t& box_count, float thickness) {
@@ -402,7 +384,7 @@ void JGL::J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const
glPopMatrix();
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glColor4fv(OpenGLState::baseColor);
glColor4fv(current_state.draw_color);
}
void JGL::J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness) {
@@ -411,8 +393,6 @@ void JGL::J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vect
}
void JGL::J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& box_count) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
glColor4ubv(color.ptr());
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->GetHandle());
@@ -444,9 +424,9 @@ void JGL::J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_
glPopMatrix();
}
glColor4fv(OpenGLState::oldColor);
glColor4fv(current_state.draw_color);
if (using_lights)
glDisable(GL_NORMAL_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisable(GL_CULL_FACE);
}
void JGL::J3D::FillAABB(const Color4& color, const Vector3& pos, const Vector3& radii) {
@@ -463,9 +443,6 @@ void JGL::J3D::FillSphere(const Color4& color, const Sphere& sphere, unsigned in
}
void JGL::J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, unsigned int sectors, unsigned int stacks) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
float r = 1;
std::vector<Vector3> vertices((sectors + 1) * (stacks + 1));
std::vector<unsigned int> indices; indices.reserve(sectors * stacks * 6);
@@ -522,7 +499,7 @@ void JGL::J3D::BatchFillSphere(const Color4& color, const Sphere* spheres, const
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glColor4fv(OpenGLState::oldColor);
glColor4fv(current_state.draw_color);
}
void JGL::J3D::FillSphere(const Color4& color, const Vector3& position, float radius, unsigned int sectors, unsigned int stacks) {
@@ -555,7 +532,7 @@ void JGL::J3D::BatchWireframeOBB(const Color4& color, const OBB* boxes, const si
glDrawElements(GL_LINES, indices.size(), GL_UNSIGNED_INT, indices.data());
glPopMatrix();
}
glColor4fv(OpenGLState::oldColor);
glColor4fv(current_state.draw_color);
}
void JGL::J3D::WireframeOBB(const Color4& color, const OBB& obb, float thickness) {
@@ -585,8 +562,6 @@ void JGL::J3D::DrawCubicBezierCurve(const Color4& color, const Vector3& controlA
}
void JGL::J3D::DrawVertexArray(const Color4& color, const VertexArray& vertex_array, const Vector3& position) {
if (!inJ3D)
Logger::Error("Drawing J3D element before J3D begin.");
glColor4ubv(color.ptr());
glEnableClientState(GL_VERTEX_ARRAY);
@@ -601,7 +576,7 @@ void JGL::J3D::DrawVertexArray(const Color4& color, const VertexArray& vertex_ar
//glDrawElements(GL_LINES, vertex_array.GetIndices()->GetLength(), GL_UNSIGNED_INT, nullptr);
//std::cout << vertex_array.GetVertices()->GetLength() << std::endl;
glColor4fv(OpenGLState::oldColor);
glColor4fv(current_state.draw_color);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

View File

@@ -1,5 +1,5 @@
#include <JGL/JGL.h>
#include "../internals/include/internals.h"
#include "internals/internals.h"
#if __linux__
@@ -158,7 +158,7 @@ namespace JGL {
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), texcoords.data());
glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6);
glBindTexture(GL_TEXTURE_2D, 0);
glColor4fv(OpenGLState::oldColor);
glColor4fv(default_state.draw_color);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
@@ -244,7 +244,7 @@ namespace JGL {
glDisable(GL_CULL_FACE);
glBindTexture(GL_TEXTURE_2D, 0);
glColor4fv(OpenGLState::oldColor);
glColor4fv(current_state.draw_color);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glPopMatrix();

View File

@@ -1,22 +1,22 @@
#include "../include/internals.h"
#include "J3ML/LinearAlgebra/Vector4.hpp"
#include "JGL/types/Light.h"
#include "internals.h"
#include <J3ML/LinearAlgebra/Vector4.hpp>
#include <JGL/types/Light.h>
// TODO handle the case that a required light is in the list of optional lights.
void JGL::J3D::SelectLights(const Vector3& position) {
std::array<const LightBase*, 8> result = required_lights;
std::array<const LightBase*, 8> result = current_state.required_lights;
unsigned int required_light_count = 0;
for (const auto& i : result)
if (i) required_light_count++;
// If there is optional lights.
if (!optional_lights.empty()) {
if (!current_state.optional_lights.empty()) {
// The number of lights we need to solve for
unsigned int remaining_lights = 8 - required_light_count;
std::vector<std::pair<float, const LightBase*>> light_influence;
for (const auto* light: optional_lights)
for (const auto* light: current_state.optional_lights)
light_influence.emplace_back(light->GetAttenuationAtPosition(position), light);
// Sort by biggest influence.
@@ -82,11 +82,11 @@ void JGL::J3D::ResetLights() {
}
bool JGL::J3D::UsingLighting() {
if (!optional_lights.empty())
if (!current_state.optional_lights.empty())
return true;
for (unsigned int i = 0; i < required_lights.size(); i++)
if (required_lights[i])
for (unsigned int i = 0; i < current_state.required_lights.size(); i++)
if (current_state.required_lights[i])
return true;
return false;
}
@@ -117,3 +117,94 @@ std::vector<Vector3> JGL::TriangleMeshVertexNormals(const Vector3* vertices, con
return normals;
}
void JGL::StateStack::Push(const JGL::State& state) {
states.push_back(state);
}
void JGL::StateStack::Pop() {
states.pop_back();
}
JGL::State* JGL::StateStack::PreviousState() {
if (states.empty())
return nullptr;
return &states.back();
}
JGL::State JGL::State::SaveState() {
State result;
result.depth_test = glIsEnabled(GL_DEPTH_TEST);
result.vertex_array = glIsEnabled(GL_VERTEX_ARRAY);
result.normal_array = glIsEnabled(GL_NORMAL_ARRAY);
result.cull_face = glIsEnabled(GL_CULL_FACE);
result.blend = glIsEnabled(GL_BLEND);
result.texture_2D = glIsEnabled(GL_TEXTURE_2D);
result.texture_coordinate_array = glIsEnabled(GL_TEXTURE_COORD_ARRAY);
result.color_array = glIsEnabled(GL_COLOR_ARRAY);
glGetIntegerv(GL_ACTIVE_TEXTURE, &result.selected_texture_unit);
result.selected_texture_unit -= GL_TEXTURE0;
glGetFloatv(GL_COLOR_CLEAR_VALUE, result.clear_color);
glGetFloatv(GL_CURRENT_COLOR, result.draw_color);
glGetIntegerv(GL_VIEWPORT, result.viewport);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&result.current_fbo);
glGetIntegerv(GL_BLEND_SRC, &result.blend_func[0]);
glGetIntegerv(GL_BLEND_DST, &result.blend_func[1]);
return result;
}
void JGL::State::RestoreState(const State& state) {
if (state.depth_test)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
if (state.vertex_array)
glEnableClientState(GL_VERTEX_ARRAY);
else
glDisableClientState(GL_VERTEX_ARRAY);
if (state.normal_array)
glEnableClientState(GL_NORMAL_ARRAY);
else
glDisableClientState(GL_NORMAL_ARRAY);
if (state.cull_face)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
if (state.blend)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
glActiveTexture(GL_TEXTURE0 + state.selected_texture_unit);
glClientActiveTexture(GL_TEXTURE0 + state.selected_texture_unit);
if (state.texture_2D)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
if (state.texture_coordinate_array)
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (state.color_array)
glEnable(GL_COLOR_ARRAY);
else
glDisable(GL_COLOR_ARRAY);
glBindFramebuffer(GL_FRAMEBUFFER, state.current_fbo);
glViewport(state.viewport[0], state.viewport[1], state.viewport[2], state.viewport[3]);
glClearColor(state.clear_color[0], state.clear_color[1], state.clear_color[2], state.clear_color[3]);
glColor4f(state.draw_color[0], state.draw_color[1], state.draw_color[2], state.draw_color[3]);
glBlendFunc(state.blend_func[0], state.blend_func[1]);
}

View File

@@ -0,0 +1,86 @@
#pragma once
#include <glad/glad.h>
#include <array>
#include <vector>
#include <J3ML/LinearAlgebra/Vector2.hpp>
#include <JGL/types/RenderTarget.h>
#include <JGL/types/Light.h>
#include <JGL/logger/logger.h>
namespace JGL {
class State;
class StateStack;
}
class JGL::State {
public:
GLfloat clear_color[4] = {0, 0, 0, 1};
GLfloat draw_color[4] = {1, 1, 1, 1};
GLint viewport[4] = {0, 0, 0, 0};
GLint blend_func[2];
GLuint current_fbo = 0;
bool texture_2D = false;
bool texture_coordinate_array = false;
bool normal_array = false;
bool depth_test = false;
bool vertex_array = false;
bool cull_face = false;
bool blend = false;
bool color_array = false;
GLint selected_texture_unit = 0;
// List of lights required for each object in the scene. up-to 8. For example, the sun. Or a flash-light.
std::array<const LightBase*, 8> required_lights{};
// List of all lights in the scene.
std::vector<const LightBase*> optional_lights{};
public:
static State SaveState();
static void RestoreState(const State& state);
};
class JGL::StateStack {
private:
std::vector<State> states{};
public:
size_t Size() { return states.size(); }
void Push(const State& state);
void Pop();
State* PreviousState();
public:
StateStack() = default;
~StateStack() = default;
};
namespace JGL {
inline constexpr std::array<const LightBase*, 8> empty_light_array = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
std::vector<Vector3> TriangleMeshVertexNormals(const Vector3* vertices, const size_t& vertex_count, const unsigned int* indices, const size_t& index_count);
inline StateStack state_stack;
inline Vector2i window_size;
//inline State current_state;
}
namespace JGL::J2D {
inline State default_state
{
{0, 0, 0, 1},
{1, 1, 1, 1},
{0, 0, 0, 0},
{GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA},
0, false, false,
false, false, true, true,
true, false, 0,
{}, {}
};
}
namespace JGL::J3D {
inline State current_state;
inline float far_plane = 0;
inline float fov = 0;
// Enables lighting and selects the correct lights to use.
void SelectLights(const Vector3& position);
// Resets the GL lights to default and disables them. Then, disables lighting.
void ResetLights();
[[nodiscard]] bool UsingLighting();
}

View File

@@ -3,12 +3,12 @@
#include <JGL/logger/logger.h>
#include <stdexcept>
const JGL::Texture* JGL::RenderTarget::GetJGLTexture() const {
const JGL::Texture* JGL::RenderTarget::GetTexture() const {
return texture;
}
GLuint JGL::RenderTarget::GetGLTextureHandle() const {
return texture->GetGLTextureHandle();
GLuint JGL::RenderTarget::GetTextureHandle() const {
return texture->GetHandle();
}
GLuint JGL::RenderTarget::GetGLFramebufferObjectHandle() const {
@@ -56,6 +56,7 @@ JGL::RenderTarget::RenderTarget(const JGL::Texture* texture, const Color4& clear
if (texture->GetDimensions().x < 1 || texture->GetDimensions().y < 1)
Logger::Fatal("Creating a render target where the color attachment is empty?");
this->size = { static_cast<int>(texture->GetDimensions().x), static_cast<int>(texture->GetDimensions().y) };
GLuint current_fbo = GetActiveGLFramebufferHandle();
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv(GL_VIEWPORT, viewport);
@@ -63,7 +64,7 @@ JGL::RenderTarget::RenderTarget(const JGL::Texture* texture, const Color4& clear
glGenFramebuffers(1, &framebuffer_object);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);
glViewport(0,0, size.x, size.y);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetGLTextureHandle(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetHandle(), 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
throw std::runtime_error("A new framebuffer could not be allocated.");
@@ -71,7 +72,6 @@ JGL::RenderTarget::RenderTarget(const JGL::Texture* texture, const Color4& clear
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
this->clear_color = clear_color;
this->size = {(int) size.x, (int) size.y};
this->texture = texture;
texture_created_by_us = false;
}
@@ -84,22 +84,18 @@ JGL::RenderTarget::RenderTarget(const Vector2i& size, const Color4& clear_color,
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv(GL_VIEWPORT, viewport);
//Textures behave strangely if they're not square aaaaaaaaaaaaa.
unsigned int biggest;
if (size.x >= size.y)
biggest = size.x;
else biggest = size.y;
texture = new Texture(Vector2(biggest, biggest));
texture = new Texture(size);
glGenFramebuffers(1, &framebuffer_object);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);
glViewport(0,0, size.x, size.y);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetGLTextureHandle(), 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetHandle(), 0);
if (use_depth) {
GLuint depthBuffer;
glGenRenderbuffers(1, &depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, biggest, biggest);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.x, size.y);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
glClear(GL_DEPTH_BUFFER_BIT);
using_depth = true;
@@ -171,18 +167,12 @@ void JGL::RenderTarget::Resize(const Vector2i& new_size) {
// Erase it.
delete texture;
unsigned int biggest;
if (new_size.x >= new_size.y)
biggest = new_size.x;
else
biggest = new_size.y;
auto cc = GetClearColor();
glClearColor(cc.RedChannelNormalized(), cc.GreenChannelNormalized(), cc.BlueChannelNormalized(), cc.AlphaChannelNormalized());
glViewport(0,0, size.x, size.y);
texture = new Texture(Vector2(biggest, biggest));
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetGLTextureHandle(), 0);
texture = new Texture(new_size);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->GetHandle(), 0);
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]);
@@ -295,22 +285,22 @@ void JGL::RenderTarget::MSAABlit() const {
}
// Fixes using render targets on a texture that has mipmaps.
if (GetJGLTexture()->GetFilteringMode() == TextureFilteringMode::MIPMAP_NEAREST
|| GetJGLTexture()->GetFilteringMode() == TextureFilteringMode::MIPMAP_BILINEAR ||
GetJGLTexture()->GetFilteringMode() == TextureFilteringMode::MIPMAP_TRILINEAR) {
if (GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_NEAREST
|| GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_BILINEAR ||
GetTexture()->GetFilteringMode() == FilteringMode::MIPMAP_TRILINEAR) {
GLint current_texture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
glBindTexture(GL_TEXTURE_2D, GetJGLTexture()->GetGLTextureHandle());
glBindTexture(GL_TEXTURE_2D, GetTexture()->GetHandle());
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, current_texture);
}
}
void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget* destination) {
if (source.size != destination->size)
Logger::Warning("Blitting a render target but they're not the same size?");
void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget* destination, const Vector2i& position) {
if (source.GetDimensions().x > destination->GetDimensions().x || source.GetDimensions().y > destination->GetDimensions().y)
Logger::Warning("Blitting a Render Target onto another Render Target but the destination Render Target is too small?");
// Save the GL state.
GLuint current_fbo = GetActiveGLFramebufferHandle();
@@ -322,7 +312,7 @@ void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget*
// Draw the contents of one into the other.
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.framebuffer_object);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination->framebuffer_object);
glBlitFramebuffer(0, 0, source.size.x, source.size.y, 0, 0, source.size.x, source.size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBlitFramebuffer(0, 0, source.size.x, source.size.y, position.x, position.y, position.x + source.size.x, position.y + source.size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Put the GL state back.
glBindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo);
@@ -330,6 +320,12 @@ void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget*
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
}
void JGL::RenderTarget::Blit(const Texture* source, RenderTarget* destination, const Vector2i& position) {
auto temp = new RenderTarget(source);
Blit(*temp, destination);
delete temp;
}
// To avoid repeatedly allocating and deallocating.
JGL::RenderTarget* pixel = nullptr;
void JGL::RenderTarget::Blit(const Color4& color, const Vector2i& position, JGL::RenderTarget* destination) {

View File

@@ -1,192 +1,274 @@
#include <JGL/types/Texture.h>
#include <iostream>
#include <JGL/types/RenderTarget.h>
#include <JGL/logger/logger.h>
#include <glad/glad.h>
#include <fstream>
using namespace ReImage;
#define STB_IMAGE_IMPLEMENTATION
#include "internals/stb_image.h"
namespace JGL
{
Texture::Texture(const std::string& file, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode, const TextureFlag& flags)
{
auto* t = new ReImage::Image(file, flags);
GLuint previous_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
using namespace JGL;
load(t, {(float) t->getWidth(), (float) t->getHeight()}, t->getTextureFormat(), filtering_mode, wrapping_mode);
texture_flags = flags;
Texture::Texture(const std::filesystem::path& file, FilteringMode filtering_mode, WrappingMode wrapping_mode, bool invert_y) :
invert_y(invert_y), filtering_mode(filtering_mode), wrapping_mode(wrapping_mode) {
std::vector<unsigned char> pixels{};
delete t;
std::ifstream ifStream(file, std::ios::in | std::ios::binary);
if (!ifStream.is_open())
Logger::Fatal("Trying to load a texture from: " + file.string() + "but we couldn't read the file.");
unsigned char bmpFileHeader[14];
ifStream.read(reinterpret_cast<char*>(bmpFileHeader), 14);
if (bmpFileHeader[0] == 'B' && bmpFileHeader[1] == 'M')
pixels = bmp(file);
//TODO determine if it's a PNG using the file header instead.
else if (file.string().ends_with(".png"))
pixels = png(file);
ifStream.close();
if (invert_y) {
unsigned int row_size = size.x * 4;;
if (format == ColorFormat::RGB)
row_size = size.x * 3;
std::vector<unsigned char> temp(row_size);
for (unsigned int y = 0; y < size.y / 2; ++y) {
unsigned char *topRow = &pixels[y * row_size];
unsigned char *bottomRow = &pixels[(size.y - y - 1) * row_size];
std::copy(bottomRow, bottomRow + row_size, temp.begin());
std::copy(topRow, topRow + row_size, bottomRow);
std::copy(temp.begin(), temp.end(), topRow);
}
}
Texture::Texture(const Vector2& size) {
GLuint previous_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
load(pixels.data());
}
glGenTextures(1, &texture_handle);
glBindTexture(GL_TEXTURE_2D, texture_handle);
//NEAREST
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//Clamp
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
std::vector<unsigned char> Texture::png(const std::filesystem::path& file) {
std::vector<unsigned char> result{};
int channels;
unsigned char* image_data = stbi_load(file.c_str(), &size.x, &size.y, &channels, 0);
if (!image_data)
Logger::Fatal("Trying to load a texture from: " + file.string() + "but we couldn't read the file.");
if (channels == 4)
format = ColorFormat::RGBA;
else if (channels == 3)
format = ColorFormat::RGB;
if (image_data)
result.assign(image_data, image_data + size.x * size.y * channels);
stbi_image_free(image_data);
return result;
}
std::vector<unsigned char> Texture::bmp(const std::filesystem::path& file) {
std::vector<unsigned char> result{};
std::ifstream bmp_file(file, std::ios::in | std::ios::binary);
unsigned char bmpFileHeader[14];
unsigned char bmpInfoHeader[40];
bmp_file.read(reinterpret_cast<char *>(bmpFileHeader), 14);
bmp_file.read(reinterpret_cast<char *>(bmpInfoHeader), 40);
size.x = bmpInfoHeader[4] + (bmpInfoHeader[5] << 8) + (bmpInfoHeader[6] << 16) + (bmpInfoHeader[7] << 24);
size.y = bmpInfoHeader[8] + (bmpInfoHeader[9] << 8) + (bmpInfoHeader[10] << 16) + (bmpInfoHeader[11] << 24);
int row_padded = (size.x * 3 + 3) & (~3);
result.resize(size.x * size.y * 3);
std::vector<unsigned char> rowData(row_padded);
for (int y = size.y - 1; y >= 0; --y) {
bmp_file.read(reinterpret_cast<char *>(rowData.data()), row_padded);
for (int x = 0; x < size.x; ++x) {
result[(y * size.x + x) * 3 + 2] = rowData[x * 3 + 0];
result[(y * size.x + x) * 3 + 1] = rowData[x * 3 + 1];
result[(y * size.x + x) * 3 + 0] = rowData[x * 3 + 2];
}
}
bmp_file.close();
format = ColorFormat::RGB;
return result;
}
Texture::Texture(const Vector2i& size) : invert_y(true), format(ColorFormat::RGBA), size(size), filtering_mode(FilteringMode::NEAREST), wrapping_mode(WrappingMode::CLAMP_TO_EDGE) {
GLuint previous_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
glGenTextures(1, &texture_handle);
glBindTexture(GL_TEXTURE_2D, texture_handle);
//NEAREST
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//Clamp
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glBindTexture(GL_TEXTURE_2D, previous_texture);
}
void Texture::load(const unsigned char* pixels) {
GLuint previous_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
glGenTextures(1, &texture_handle);
glBindTexture(GL_TEXTURE_2D, texture_handle);
if (format == ColorFormat::RGBA)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
else if (format == ColorFormat::RGB)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.x, size.y, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
if (wrapping_mode == WrappingMode::CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int) size.x, (int) size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
else if (wrapping_mode == WrappingMode::REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
texture_format = TextureFormat::RGBA;
texture_size = size;
texture_filtering_mode = TextureFilteringMode::NEAREST;
texture_wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE;
// Because in vram it'll be right side up.
texture_flags = TextureFlag::INVERT_Y;
else if (wrapping_mode == WrappingMode::MIRRORED_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glBindTexture(GL_TEXTURE_2D, previous_texture);
else if (wrapping_mode == WrappingMode::CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
if (filtering_mode == FilteringMode::NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else if (filtering_mode == FilteringMode::BILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
else if (filtering_mode == FilteringMode::MIPMAP_NEAREST ||
filtering_mode == FilteringMode::MIPMAP_BILINEAR ||
filtering_mode == FilteringMode::MIPMAP_TRILINEAR) {
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
if (filtering_mode == FilteringMode::MIPMAP_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else if (filtering_mode == FilteringMode::MIPMAP_BILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
else if (filtering_mode == FilteringMode::MIPMAP_TRILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
glBindTexture(GL_TEXTURE_2D, previous_texture);
}
void Texture::load(Image* software_texture, const Vector2& size, const TextureFormat& format,
TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode) {
std::vector<Color4> JGL::Texture::GetPixelData() const {
GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
GLuint previous_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*) &previous_texture);
glGenTextures(1, &texture_handle);
glBindTexture(GL_TEXTURE_2D, texture_handle);
if (format == TextureFormat::RGBA)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int) size.x, (int) size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
software_texture->pixel_data.data());
else if (format == TextureFormat::RGB)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (int) size.x, (int) size.y, 0, GL_RGB, GL_UNSIGNED_BYTE,
software_texture->pixel_data.data());
if (wrapping_mode == TextureWrappingMode::CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
else if (wrapping_mode == TextureWrappingMode::REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
else if (wrapping_mode == TextureWrappingMode::MIRRORED_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
else if (wrapping_mode == TextureWrappingMode::CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
if (filtering_mode == TextureFilteringMode::NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else if (filtering_mode == TextureFilteringMode::BILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
else if (filtering_mode == TextureFilteringMode::MIPMAP_NEAREST ||
filtering_mode == TextureFilteringMode::MIPMAP_BILINEAR ||
filtering_mode == TextureFilteringMode::MIPMAP_TRILINEAR) {
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
if (filtering_mode == TextureFilteringMode::MIPMAP_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else if (filtering_mode == TextureFilteringMode::MIPMAP_BILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
else if (filtering_mode == TextureFilteringMode::MIPMAP_TRILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
texture_size = size;
texture_format = format;
texture_filtering_mode = filtering_mode;
glBindTexture(GL_TEXTURE_2D, previous_texture);
}
std::vector<Color4> JGL::Texture::GetPixelData() const {
GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
std::vector<Color4> result((size_t) (texture_size.x * texture_size.y));
glBindTexture(GL_TEXTURE_2D, texture_handle);
if (texture_format == TextureFormat::RGBA) {
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, result.data());
glBindTexture(GL_TEXTURE_2D, current_texture);
return result;
}
//if RGB
std::vector<Color3> color3((size_t) (texture_size.x * texture_size.y));
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, color3.data());
for (const auto &c: color3)
result.emplace_back(c);
std::vector<Color4> result((size_t) (size.x * size.y));
glBindTexture(GL_TEXTURE_2D, texture_handle);
if (format == ColorFormat::RGBA) {
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, result.data());
glBindTexture(GL_TEXTURE_2D, current_texture);
return result;
}
void Texture::Erase() {
if (texture_handle != 0)
glDeleteTextures(1, &texture_handle);
texture_handle = 0;
//if RGB
std::vector<Color3> color3((size_t) (size.x * size.y));
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, color3.data());
for (const auto &c: color3)
result.emplace_back(c);
glBindTexture(GL_TEXTURE_2D, current_texture);
return result;
}
GLuint Texture::GetHandle() const {
return texture_handle;
}
Vector2i Texture::GetDimensions() const {
return size;
}
bool Texture::Inverted() const {
return invert_y;
}
ColorFormat Texture::GetFormat() const {
return format;
}
FilteringMode Texture::GetFilteringMode() const {
return filtering_mode;
}
WrappingMode Texture::GetWrappingMode() const {
return wrapping_mode;
}
Texture::Texture(const Color4* pixels, const Vector2i& size, const ColorFormat& format, FilteringMode filtering_mode, WrappingMode wrapping_mode) :
size(size), format(format), filtering_mode(filtering_mode), wrapping_mode(wrapping_mode) {
load((unsigned char*) pixels);
}
Texture::Texture(const Color3* pixels, const Vector2i& size, const ColorFormat& format, FilteringMode filtering_mode, WrappingMode wrapping_mode) :
size(size), format(format), filtering_mode(filtering_mode), wrapping_mode(wrapping_mode) {
load((unsigned char*) pixels);
}
Texture::~Texture() {
if (texture_handle != 0)
glDeleteTextures(1, &texture_handle);
texture_handle = 0;
}
Texture::Texture(const Texture& rhs) {
auto* this_texture = new Texture(rhs.GetDimensions());
auto this_render_target = RenderTarget(this_texture);
auto rhs_render_target = RenderTarget(&rhs);
RenderTarget::Blit(rhs_render_target, &this_render_target);
this->texture_handle = this_texture->texture_handle;
this->size = this_texture->size;
this->invert_y = this_texture->invert_y;
this->format = this_texture->format;
this->filtering_mode = this_texture->filtering_mode;
this->wrapping_mode = this_texture->wrapping_mode;
operator delete(this_texture);
}
Texture::Texture(const Texture* textures, const size_t& texture_count) {
int length = 0;
int biggest_y = 0;
for (int i = 0; i < texture_count; i++) {
if (biggest_y < textures[i].size.y)
biggest_y = textures[i].size.y;
length += textures[i].size.x;
}
GLuint Texture::GetGLTextureHandle() const {
return texture_handle;
auto* result = new Texture(Vector2i(length, biggest_y));
auto render_target = RenderTarget(result);
int next_x = 0;
for (int i = 0; i < texture_count; i++) {
RenderTarget::Blit(&textures[i], &render_target, Vector2i(next_x, 0));
next_x += textures[i].GetDimensions().x;
}
Vector2 Texture::GetDimensions() const {
return texture_size;
}
TextureFlag Texture::GetFlags() const {
return texture_flags;
}
TextureFormat Texture::GetFormat() const {
return texture_format;
}
TextureFilteringMode Texture::GetFilteringMode() const {
return texture_filtering_mode;
}
TextureWrappingMode Texture::GetWrappingMode() const {
return texture_wrapping_mode;
}
Texture::Texture(Image* software_texture, const Vector2& size, const TextureFormat& format,
TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode) {
load(software_texture, size, format, filtering_mode, wrapping_mode);
}
Texture::~Texture() {
Erase();
}
Texture::Texture(const Texture& rhs) {
auto* this_texture = new Texture(rhs.GetDimensions());
auto this_render_target = RenderTarget(this);
auto rhs_render_target = RenderTarget(&rhs);
RenderTarget::Blit(rhs_render_target, &this_render_target);
this->texture_handle = this_texture->texture_handle;
this->texture_size = this_texture->texture_size;
this->texture_flags = this_texture->texture_flags;
this->texture_format = this_texture->texture_format;
this->texture_filtering_mode = this_texture->texture_filtering_mode;
this->texture_wrapping_mode = this_texture->texture_wrapping_mode;
// Free the memory of "this_texture" without calling the destructor.
// In 99% of cases you wouldn't want this. But in this scenario we do.
operator delete(this_texture);
}
}
}

View File

@@ -1,6 +1,5 @@
#include <JGL/types/VertexArray.h>
#include <JGL/logger/logger.h>
#include "../internals/include/WavefrontOBJ.h"
using namespace JGL;
@@ -178,7 +177,3 @@ VertexArray::VertexArray(const std::vector<Vertex>& vertex_positions, const std:
bool VertexArray::Static() {
return animations.empty();
}
VertexArray VertexArray::LoadWavefrontOBJ(const std::string& file_text) {
return JGL::LoadWavefrontOBJ(file_text);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,3 @@
#include "../include/WavefrontOBJ.h"
#include <JGL/types/VertexArray.h>
#include <JGL/logger/logger.h>
@@ -61,7 +60,19 @@ std::pair<Vector3, unsigned long> ParseVector3(const std::string& file_text, con
return {Vector3(x_result.first, y_result.first, z_result.first), z_result.second + 1};
}
std::pair<std::array<Vector3, 3>, unsigned long> ParseFaceData(const std::string& file_text, const unsigned long& offset) {
std::pair<Vector4, unsigned long> ParseVector4(const std::string& file_text, const unsigned long& offset) {
auto x_result = ParseNumber(file_text, offset);
auto y_result = ParseNumber(file_text, x_result.second + 1);
auto z_result = ParseNumber(file_text, y_result.second + 1);
auto w_result = ParseNumber(file_text, z_result.second + 1);
if (x_result.second == offset || y_result.second == x_result.second || z_result.second == y_result.second || w_result.second == z_result.second)
return {Vector4(0, 0, 0, 0), offset};
return {Vector4(x_result.first, y_result.first, z_result.first, w_result.first), w_result.second + 1};
}
std::pair<std::array<Vector3, 3>, unsigned long> ParseWavefrontFaceData(const std::string& file_text, const unsigned long& offset) {
unsigned long new_offset = offset;
std::array<Vector3, 3> face_data;
@@ -103,7 +114,7 @@ std::pair<std::array<Vector3, 3>, unsigned long> ParseFaceData(const std::string
return {face_data, new_offset};
}
VertexArray JGL::LoadWavefrontOBJ(const std::string &file_text) {
VertexArray VertexArray::LoadWavefrontOBJ(const std::string &file_text) {
std::vector<std::array<Vector3, 3>> faceline_data;
std::vector<TextureCoordinate> temp_uvs;
@@ -111,7 +122,6 @@ VertexArray JGL::LoadWavefrontOBJ(const std::string &file_text) {
std::vector<Vertex> temp_vertices;
unsigned long offset = 0;
while (offset < file_text.size()) {
char c = file_text[offset];
@@ -161,7 +171,7 @@ VertexArray JGL::LoadWavefrontOBJ(const std::string &file_text) {
else if (c == 'f' && offset + 1 < file_text.size() && file_text[offset + 1] == ' ') {
offset += 2;
auto faceline_result = ParseFaceData(file_text, offset);
auto faceline_result = ParseWavefrontFaceData(file_text, offset);
if (faceline_result.second != offset) {
faceline_data.push_back(faceline_result.first);
offset = faceline_result.second;
@@ -200,4 +210,125 @@ VertexArray JGL::LoadWavefrontOBJ(const std::string &file_text) {
final_indices.data(), final_indices.size(),
final_normals.data(), final_normals.size(),
final_uvs.data(), final_uvs.size());
}
}
/*
VertexArray JGL::LoadAMO(const std::string& file_text) {
std::vector<Vector3> temp_vertices;
std::vector<Vector3> temp_normals;
std::vector<Vector2> temp_uvs;
std::vector<std::array<Vector3, 3>> faceline_data;
std::string name;
unsigned long offset = 0;
while (offset < file_text.size()) {
char c = file_text[offset];
// If we've dropped on a newline character somehow then just skip passed it.
if (c == '\n' || c == '\r') {
offset++; continue;
}
// File name.
else if (offset + 2 < file_text.size() && c == 'a' && file_text[offset + 1] == 'o' && file_text[offset + 2] == ' ') {
offset += 3;
while (offset < file_text.size()) {
if (file_text[offset] != '\n' && file_text[offset] != '\r')
name.push_back(file_text[offset]), offset++;
else
break;
}
}
// Vertices
else if (offset + 1 < file_text.size() && c == 'v' && file_text[offset + 1] == ' ') {
offset += 2; auto parsed_number = ParseNumber(file_text, offset);
if (parsed_number.second == offset)
Logger::Fatal("We couldn't interpret the Vertex count at: " + std::to_string(offset));
unsigned long vertex_count = parsed_number.first;
offset = parsed_number.second;
for (unsigned long i = 0; i < vertex_count; i++) {
// Skip by newlines.
while (file_text[offset] == '\n' || file_text[offset] == '\r')
offset++;
auto parsed_vector3 = ParseVector3(file_text, offset);
if (parsed_vector3.second == offset)
Logger::Fatal("We couldn't interpret the Vertex at: " + std::to_string(offset));
temp_vertices.push_back(parsed_vector3.first);
offset = parsed_vector3.second;
}
}
// UVs
else if (offset + 2 < file_text.size() && c == 'v' && file_text[offset + 1] == 't' && file_text[offset + 2] == ' ') {
offset += 3; auto parsed_number = ParseNumber(file_text, offset);
if (parsed_number.second == offset)
Logger::Fatal("We couldn't interpret the UV count at: " + std::to_string(offset));
unsigned long uv_count = parsed_number.first;
offset = parsed_number.second;
for (unsigned long i = 0; i < uv_count; i++) {
// Skip by newlines.
while (file_text[offset] == '\n' || file_text[offset] == '\r')
offset++;
auto parsed_vector2 = ParseVector2(file_text, offset);
if (parsed_vector2.second == offset)
Logger::Fatal("We couldn't interpret the UV at: " + std::to_string(offset));
temp_uvs.push_back(parsed_vector2.first);
offset = parsed_vector2.second;
}
}
// Normals
else if (offset + 2 < file_text.size() && c == 'v' && file_text[offset + 1] == 'n' && file_text[offset + 2] == ' ') {
offset += 3; auto parsed_number = ParseNumber(file_text, offset);
if (parsed_number.second == offset)
Logger::Fatal("We couldn't interpret the Normal count at: " + std::to_string(offset));
unsigned long uv_count = parsed_number.first;
offset = parsed_number.second;
for (unsigned long i = 0; i < uv_count; i++) {
// Skip by newlines.
while (file_text[offset] == '\n' || file_text[offset] == '\r')
offset++;
auto parsed_vector3 = ParseVector3(file_text, offset);
if (parsed_vector3.second == offset)
Logger::Fatal("We couldn't interpret the Normal at: " + std::to_string(offset));
temp_normals.push_back(parsed_vector3.first);
offset = parsed_vector3.second;
}
}
// Face Lines
else if (offset + 1 < file_text.size() && c == 'f' && file_text[offset + 1] == ' ') {
offset += 2; auto parsed_number = ParseNumber(file_text, offset);
if (parsed_number.second == offset)
Logger::Fatal("We couldn't interpret the Face Line count at: " + std::to_string(offset));
unsigned long faceline_count = parsed_number.first;
for (unsigned long i = 0; i < faceline_count; i++) {
// Skip by newlines.
while (file_text[offset] == '\n' || file_text[offset] == '\r')
offset++;
}
}
}
}
*/