Compare commits
17 Commits
Prerelease
...
Prerelease
Author | SHA1 | Date | |
---|---|---|---|
a22a83d2f8 | |||
76cd48c9b7 | |||
38bb1b22ce | |||
122644a013 | |||
|
641f2de8d0 | ||
6618aa5e6b | |||
3970aa2718 | |||
fb5ca55fda | |||
bcca6285af | |||
f8395726cd | |||
ca7abb3044 | |||
14c45ab0f1 | |||
1ca5e5a694 | |||
25fc3f8698 | |||
a836fc7b32 | |||
e6dcc9d61e | |||
6dff2f97c1 |
@@ -22,17 +22,17 @@ CPMAddPackage(
|
||||
|
||||
CPMAddPackage(
|
||||
NAME J3ML
|
||||
URL https://git.redacted.cc/josh/j3ml/archive/Release-3.4.zip
|
||||
URL https://git.redacted.cc/josh/j3ml/archive/3.4.3.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME ReWindow
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-21.zip
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-26.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME GLAD
|
||||
URL https://git.redacted.cc/Redacted/glad/archive/v2.1ext_fboV2.zip
|
||||
URL https://git.redacted.cc/Redacted/glad/archive/v2.1ext_fbo_depthtexture_shadow.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
|
@@ -53,7 +53,7 @@ JGL::J2D::End();
|
||||
```
|
||||
## Requirements
|
||||
|
||||
An OpenGL 2.1 or newer accelerator that supports the `GL_ARB_framebuffer_object` extension or
|
||||
An OpenGL 2.1 or newer accelerator with at-least two texture mappers that supports the `GL_ARB_framebuffer_object` extension or
|
||||
an implementation that can provide those features through alternative means (common on ArmSoC and Risc-V).
|
||||
|
||||
## Compatability
|
||||
|
Binary file not shown.
BIN
assets/sprites/alpha_mask.png
Normal file
BIN
assets/sprites/alpha_mask.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 942 B |
BIN
assets/sprites/alpha_mask_2.png
Normal file
BIN
assets/sprites/alpha_mask_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
1066
include/JGL/JGL.h
1066
include/JGL/JGL.h
File diff suppressed because it is too large
Load Diff
@@ -13,8 +13,6 @@ extern "C" typedef struct FT_LibraryRec_* FT_Library;
|
||||
|
||||
namespace JGL
|
||||
{
|
||||
|
||||
//bool Init();
|
||||
bool InitTextEngine();
|
||||
|
||||
/// A Font class implementation.
|
||||
@@ -23,7 +21,8 @@ namespace JGL
|
||||
public:
|
||||
/// Default constructor does not initialize any members
|
||||
Font() = default;
|
||||
Font(const std::filesystem::path& path);
|
||||
explicit Font(const std::filesystem::path& path);
|
||||
Font(const unsigned char* data, const size_t& size);
|
||||
/// Destructor handles freeing of the underlying asset handle.
|
||||
~Font();
|
||||
static Font LoadTTF(const std::filesystem::path& filepath);
|
||||
@@ -35,6 +34,6 @@ namespace JGL
|
||||
Vector2 MeasureString(const std::string& text, unsigned int ptSize);
|
||||
public:
|
||||
int index = 0;
|
||||
FT_Face face;
|
||||
FT_Face face = nullptr;
|
||||
};
|
||||
}
|
@@ -1,30 +1,65 @@
|
||||
#pragma once
|
||||
#include <J3ML/LinearAlgebra/Vector4.hpp>
|
||||
#include <J3ML/LinearAlgebra/Vector3.hpp>
|
||||
#include <J3ML/LinearAlgebra/DirectionVector.hpp>
|
||||
#include <J3ML/Geometry/Frustum.hpp>
|
||||
#include <Color4.hpp>
|
||||
|
||||
namespace JGL {
|
||||
class Light;
|
||||
class OmnidirectionalLight2D;
|
||||
class PointLight2D;
|
||||
class LightBase;
|
||||
class PointLight;
|
||||
class SpotLight;
|
||||
}
|
||||
|
||||
class JGL::Light {
|
||||
private:
|
||||
/// W in position seems to determine whether or not the light is omni-directional. 1 = omni 0 = point.
|
||||
/// Position is un-normalized screen space. For ex 500, 500, 1 for a light coming from where you're sitting.
|
||||
class JGL::LightBase {
|
||||
protected:
|
||||
Vector4 position = {0, 0, 0, 1};
|
||||
Color4 ambient = {0, 0, 0, 0};
|
||||
Color4 diffuse = {0, 0, 0, 0};
|
||||
Color4 specular = {0, 0, 0, 0};
|
||||
|
||||
float constant_attenuation;
|
||||
float linear_attenuation;
|
||||
float quadratic_attenuation;
|
||||
public:
|
||||
Light(const Vector3& position, const Color4& ambient, const Color4& diffuse, const Color4& specular);
|
||||
Vector3 GetNormalizedSceenSpaceCoordinates() const;
|
||||
[[nodiscard]] Vector3 GetPosition() const;
|
||||
[[nodiscard]] Color4 GetAmbient() const;
|
||||
[[nodiscard]] Color4 GetDiffuse() const;
|
||||
[[nodiscard]] Color4 GetSpecular() const;
|
||||
|
||||
[[nodiscard]] float GetConstantAttenuation() const;
|
||||
[[nodiscard]] float GetLinearAttenuation() const;
|
||||
[[nodiscard]] float GetQuadraticAttenuation() const;
|
||||
public:
|
||||
/// Runs a calculation to determine the lights influence on a given point in 3D space.
|
||||
/// @note 0 would be no impact, 1 would be the light is at the same position.
|
||||
[[nodiscard]] virtual float GetAttenuationAtPosition(const Vector3& pos) const { return 0; }
|
||||
public:
|
||||
virtual ~LightBase() = default;
|
||||
};
|
||||
|
||||
class JGL::OmnidirectionalLight2D {
|
||||
private:
|
||||
/// Omni-directional lights.
|
||||
class JGL::PointLight : public LightBase {
|
||||
public:
|
||||
OmnidirectionalLight2D(const Vector3& position, const Color4& ambient, const Color4& diffuse, const Color4& specular);
|
||||
|
||||
[[nodiscard]] float GetAttenuationAtPosition(const Vector3& pos) const override;
|
||||
public:
|
||||
PointLight(const Vector3& position, const Color4& ambient, const Color4& diffuse, const Color4& specular, float constant_attenuation = 1, float linear_attenuation = 0, float quadratic_attenuation = 0);
|
||||
};
|
||||
|
||||
/// Lights which only effect things in a given cone.
|
||||
class JGL::SpotLight : public LightBase {
|
||||
protected:
|
||||
Matrix3x3 orientation;
|
||||
float exponent;
|
||||
float cut;
|
||||
public:
|
||||
/// Create a spotlight in 3D space.
|
||||
/// @param position The position of the light in 3D space.
|
||||
/// @param ro_mat Orientation of the light in 3D space.
|
||||
/// @param cone_size_degrees The size of the cone.
|
||||
/// @param exponent How focused the beam should be, Higher is more focused, Lower is less.
|
||||
/// @param ambient How much this light should effect the ambient light of the scene.
|
||||
/// @param diffuse
|
||||
/// @param specular How much this light should effect specular highlights of objects being influenced by it.
|
||||
SpotLight(const Vector3& position, const Matrix3x3& ro_mat, float cone_size_degrees, float exponent, const Color4& ambient, const Color4& diffuse, const Color4& specular, float constant_attenuation = 1, float linear_attenuation = 0, float quadratic_attenuation = 0);
|
||||
};
|
18
include/JGL/types/ShadowMap.h
Normal file
18
include/JGL/types/ShadowMap.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <JGL/types/RenderTarget.h>
|
||||
#include <JGL/types/Light.h>
|
||||
|
||||
namespace JGL {
|
||||
class ShadowMap;
|
||||
}
|
||||
|
||||
/// You render your scene with all the static objects from the perspective of each static light to a ShadowMap.
|
||||
/// Then, for shadow casters which move. Or lights that move. You only redraw that object from the perspective of each light.
|
||||
/// Some of the approaches I saw for this were disgusting - Redacted.
|
||||
|
||||
class JGL::ShadowMap {
|
||||
private:
|
||||
RenderTarget shadow_map;
|
||||
private:
|
||||
void Create(const LightBase* Light);
|
||||
};
|
@@ -20,15 +20,15 @@ private:
|
||||
bool spin_lock = false;
|
||||
void load(const GLfloat* data, const long& size);
|
||||
void load(const GLuint* data, const long& size);
|
||||
void SetData(void* data, const long& length);
|
||||
void UpdateData(void* data, const long& offset, const long& length);
|
||||
void SetData(void* data, const long& count);
|
||||
void UpdateData(void* data, const long& offset, const long& count);
|
||||
void Erase();
|
||||
public:
|
||||
VRamList(const GLuint* data, const long& length);
|
||||
VRamList(const GLfloat* data, const long& length);
|
||||
VRamList(const Vector2* data, const long& length);
|
||||
VRamList(const Vector3* data, const long& length);
|
||||
VRamList(const Vector4* data, const long& length);
|
||||
VRamList(const GLuint* data, const long& count);
|
||||
VRamList(const GLfloat* data, const long& count);
|
||||
VRamList(const Vector2* data, const long& count);
|
||||
VRamList(const Vector3* data, const long& count);
|
||||
VRamList(const Vector4* data, const long& count);
|
||||
|
||||
~VRamList();
|
||||
/** Copying around the VBO data to a new VBO like this is slow.
|
||||
@@ -46,25 +46,23 @@ public:
|
||||
[[nodiscard]] std::vector<GLfloat> GetDataF() const;
|
||||
[[nodiscard]] std::vector<GLuint> GetDataUI() const;
|
||||
[[nodiscard]] bool IsFloatArray() const;
|
||||
/** Replace the data of an existing VBO in it's entirety. Must be same type.
|
||||
* "length" refers to the number of elements in data. Not the number of bytes. */
|
||||
void SetData(const GLfloat* data, const long& length);
|
||||
void SetData(const Vector2* data, const long& length);
|
||||
void SetData(const Vector3* data, const long& length);
|
||||
void SetData(const Vector4* data, const long& length);
|
||||
/** Replace the data of an existing VBO in it's entirety. Must be same type. */
|
||||
void SetData(const GLfloat* data, const long& count);
|
||||
void SetData(const Vector2* data, const long& count);
|
||||
void SetData(const Vector3* data, const long& count);
|
||||
void SetData(const Vector4* data, const long& count);
|
||||
|
||||
void SetData(const GLuint* data, const long& length);
|
||||
void SetData(const Vector2i* data, const long& length);
|
||||
void SetData(const GLuint* data, const long& count);
|
||||
void SetData(const Vector2i* data, const long& count);
|
||||
|
||||
/** Update only a portion of the data in a VBO. Must be same type.
|
||||
* "length" refers to the number of elements in data. Not the number of bytes.
|
||||
* "offset" refers the number of Typename T into the buffer the data you want to change is.
|
||||
* For ex, offset 0 and length of 1 overwrites the first value. Offset 1 the second etc */
|
||||
void UpdateData(const GLfloat* data, const long& offset, const long& length);
|
||||
void UpdateData(const Vector2* data, const long& offset, const long& length);
|
||||
void UpdateData(const Vector3* data, const long& offset, const long& length);
|
||||
void UpdateData(const Vector4* data, const long& offset, const long& length);
|
||||
void UpdateData(const GLfloat* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector2* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector3* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector4* data, const long& offset, const long& count);
|
||||
|
||||
void UpdateData(const GLuint* data, const long& offset, const long& length);
|
||||
void UpdateData(const Vector2i* data, const long& offset, const long& length);
|
||||
void UpdateData(const GLuint* data, const long& offset, const long& count);
|
||||
void UpdateData(const Vector2i* data, const long& offset, const long& count);
|
||||
};
|
105
main.cpp
105
main.cpp
@@ -4,12 +4,13 @@
|
||||
#include <chrono>
|
||||
#include <J3ML/LinearAlgebra/Vector2.hpp>
|
||||
#include <JGL/logger/logger.h>
|
||||
#include <J3ML/Geometry/AABB.hpp>
|
||||
|
||||
using J3ML::LinearAlgebra::Vector2;
|
||||
using namespace JGL::Fonts;
|
||||
using namespace JGL;
|
||||
|
||||
JGL::Font FreeSans;
|
||||
JGL::Font Jupiteroid;
|
||||
float fps = 0.0f;
|
||||
|
||||
class Gizmo
|
||||
@@ -97,9 +98,8 @@ Gizmo c({350, 300});
|
||||
Gizmo d({450, 250});
|
||||
|
||||
Texture* image;
|
||||
Texture* image2;
|
||||
Texture* image_mask;
|
||||
RenderTarget* j2d_render_target;
|
||||
RenderTarget* image2_render_target;
|
||||
|
||||
class JGLDemoWindow : public ReWindow::RWindow
|
||||
{
|
||||
@@ -107,28 +107,23 @@ public:
|
||||
void initGL() {
|
||||
camera = new Camera;
|
||||
|
||||
if (!JGL::Init(getSize(), 75, 100))
|
||||
if (!JGL::Init(GetSize(), 75, 100))
|
||||
Logger::Fatal("Initialization failed.");
|
||||
|
||||
FreeSans = JGL::Font("assets/fonts/FreeSans.ttf");
|
||||
Jupiteroid = JGL::Font("assets/fonts/Jupiteroid.ttf");
|
||||
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthMask(GL_TRUE);
|
||||
image = new Texture("assets/sprites/Re3D.png", TextureFilteringMode::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);
|
||||
image2 = image;
|
||||
image2_render_target = new RenderTarget(image2);
|
||||
|
||||
J2D::Begin(image2_render_target);
|
||||
J2D::DrawString(Colors::Red, "TEST", 0, 16, 1, 16, FreeSans);
|
||||
J2D::FillRect(Colors::Blue, {0,0}, {4,4});
|
||||
J2D::End();
|
||||
//Texture::MultiplyByAlphaMask(*image, *image_mask);
|
||||
}
|
||||
|
||||
Vector3 textAngle = {0,0,0};
|
||||
EulerAngleXYZ textAngle = {0,0,0};
|
||||
float fov = 90;
|
||||
float sprite_radians = 0;
|
||||
bool fov_increasing = true;
|
||||
@@ -136,8 +131,9 @@ public:
|
||||
|
||||
void display() {
|
||||
|
||||
float dt = 1.f / fps;
|
||||
JGL::Update(getSize());
|
||||
float dt = GetDeltaTime();
|
||||
|
||||
JGL::Update(GetSize());
|
||||
|
||||
if (fov_increasing)
|
||||
fov += 0.025;
|
||||
@@ -151,7 +147,7 @@ public:
|
||||
//J3D::ChangeFOV(fov);
|
||||
|
||||
sprite_radians += 0.005;
|
||||
textAngle.y += (5.f * delta_time);
|
||||
textAngle.yaw += 1;
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
@@ -159,17 +155,22 @@ public:
|
||||
camera->render();
|
||||
// All 3D elements of the scene and JGL elements *must* be rendered before the 2D stuff
|
||||
/* if rendering to screen space directly. */
|
||||
|
||||
// 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});
|
||||
J3D::DrawString(Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f}, 1.f, 32, FreeSans, textAngle * 100, true);
|
||||
J3D::DrawString(Colors::Red, "JGL Sample Text", {-0.33, -0.1, 1.0f}, 1.f, 32, FreeSans, textAngle, true);
|
||||
//J3D::WireframeSphere(Colors::Green, {0,0,0.5f}, 0.25f, 1, 128, 128);
|
||||
Sphere sphere[5] = {{{0,0, 0.5f}, 0.2125}, {{0,0, 0.5f}, 0.025},{{0,0, 0.5f}, 0.05},{{0,0, 0.5f}, 0.075},{{0,0, 0.5f}, 0.1}};
|
||||
J3D::BatchWireframeRevoSphere(Colors::Green, sphere, 1, 1, 16, 16, true);
|
||||
//J3D::FillAABB(Colors::Whites::AliceBlue, {0,0,0.5f}, {0.1f, 0.05f, 0.1f});
|
||||
//J3D::WireframeAABB(Colors::Gray, {0,0,0.5f}, {0.11f, 0.06f, 0.11f});
|
||||
Sphere sphere = {{0,0, 0.5f}, 0.2125};
|
||||
J3D::BatchWireframeRevoSphere(Colors::Green, &sphere, 1, 1, 16, 16, true);
|
||||
J3D::FillAABB(Colors::Whites::AliceBlue, {0,0,0.5f}, {0.1f, 0.1f, 0.1f});
|
||||
J3D::WireframeAABB(Colors::Gray, {0,0,0.5f}, {0.11f, 0.06f, 0.11f});
|
||||
|
||||
J3D::WireframeOBB(Colors::Red, {0, 0, 1.5f}, {0.40f, 0.10f, 0.10f}, {0,textAngle.y, 0});
|
||||
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);
|
||||
|
||||
@@ -178,7 +179,7 @@ public:
|
||||
|
||||
J2D::Begin(j2d_render_target, true);
|
||||
J2D::FillRect(Colors::Blue, {0,52}, {100,100});
|
||||
J2D::DrawSprite(image2, {300, 400}, sprite_radians * 0.10f, {0.5,0.5}, {1, 1}, Colors::White);
|
||||
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::FillRect(Colors::Pinks::HotPink, {68, 120}, {32, 32});
|
||||
@@ -221,26 +222,43 @@ public:
|
||||
//Draw the Render Target that we just drew all that stuff onto.
|
||||
|
||||
J2D::Begin();
|
||||
J2D::DrawSprite(j2d_render_target, {0, 0}, 0, {0.5, 0.5}, {1,1}, Colors::White);
|
||||
J2D::DrawSprite(image2_render_target, {300, 500}, 0, {0.5, 0.5}, {1,1}, Colors::White);
|
||||
J2D::DrawPartialRenderTarget(j2d_render_target, {0, 0}, {0,0}, {512, 512});
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
void OnRefresh(float elapsed) override {
|
||||
if (isKeyDown(Keys::RightArrow))
|
||||
|
||||
fps = GetRefreshRate();
|
||||
|
||||
if (IsKeyDown(Keys::RightArrow))
|
||||
camera->angle.y += 45.f * elapsed;
|
||||
if (isKeyDown(Keys::LeftArrow))
|
||||
if (IsKeyDown(Keys::LeftArrow))
|
||||
camera->angle.y -= 45.f * elapsed;
|
||||
if (isKeyDown(Keys::UpArrow))
|
||||
if (IsKeyDown(Keys::UpArrow))
|
||||
camera->angle.x -= 45.f * elapsed;
|
||||
if (isKeyDown(Keys::DownArrow))
|
||||
if (IsKeyDown(Keys::DownArrow))
|
||||
camera->angle.x += 45.f * elapsed;
|
||||
if (isKeyDown(Keys::Space))
|
||||
if (IsKeyDown(Keys::Space))
|
||||
camera->position.y += 1.f * elapsed;
|
||||
if (isKeyDown(Keys::LeftShift))
|
||||
if (IsKeyDown(Keys::LeftShift))
|
||||
camera->position.y -= 1.f * elapsed;
|
||||
|
||||
//This is wrong of course. Just for testing purposes.
|
||||
if (IsKeyDown(Keys::W))
|
||||
camera->position.z += 1.f * elapsed;
|
||||
if (IsKeyDown(Keys::S))
|
||||
camera->position.z -= 1.f * elapsed;
|
||||
if (IsKeyDown(Keys::A))
|
||||
camera->position.x += 1.f * elapsed;
|
||||
if (IsKeyDown(Keys::D))
|
||||
camera->position.x -= 1.f * elapsed;
|
||||
|
||||
|
||||
auto mouse = GetMouseCoordinates();
|
||||
a.Update(mouse);
|
||||
b.Update(mouse);
|
||||
@@ -250,11 +268,11 @@ public:
|
||||
int glError = glGetError();
|
||||
if (glError != GL_NO_ERROR)
|
||||
std::cout << glError << std::endl;
|
||||
glSwapBuffers();
|
||||
GLSwapBuffers();
|
||||
}
|
||||
|
||||
|
||||
void OnMouseButtonDown(const ReWindow::WindowEvents::MouseButtonDownEvent & ev) override
|
||||
void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent & ev) override
|
||||
{
|
||||
RWindow::OnMouseButtonDown(ev);
|
||||
a.Grab();
|
||||
@@ -263,7 +281,7 @@ public:
|
||||
d.Grab();
|
||||
}
|
||||
|
||||
void OnMouseButtonUp(const ReWindow::WindowEvents::MouseButtonUpEvent & ev) override
|
||||
void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent & ev) override
|
||||
{
|
||||
RWindow::OnMouseButtonUp(ev);
|
||||
a.Release();
|
||||
@@ -279,19 +297,20 @@ public:
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
auto* window = new JGLDemoWindow("JGL Demo Window", 1280, 720);
|
||||
window->setRenderer(RenderingAPI::OPENGL);
|
||||
window->SetRenderer(RenderingAPI::OPENGL);
|
||||
window->Open();
|
||||
window->initGL();
|
||||
window->setResizable(true);
|
||||
window->setVsyncEnabled(false);
|
||||
window->SetResizable(true);
|
||||
window->SetVsyncEnabled(false);
|
||||
|
||||
while (window->isAlive()) {
|
||||
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
|
||||
window->pollEvents();
|
||||
window->refresh();
|
||||
std::chrono::high_resolution_clock::time_point stop = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<float> frame_time = stop - start;
|
||||
fps = 1.0f / frame_time.count();
|
||||
while (window->IsAlive()) {
|
||||
window->ManagedRefresh();
|
||||
//std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
|
||||
//window->PollEvents();
|
||||
//window->Refresh();
|
||||
//std::chrono::high_resolution_clock::time_point stop = std::chrono::high_resolution_clock::now();
|
||||
//std::chrono::duration<float> frame_time = stop - start;
|
||||
//fps = 1.0f / frame_time.count();
|
||||
}
|
||||
return 0;
|
||||
}
|
8671
src/Fonts.cpp
Normal file
8671
src/Fonts.cpp
Normal file
File diff suppressed because it is too large
Load Diff
622
src/JGL.cpp
622
src/JGL.cpp
@@ -31,6 +31,9 @@ bool wasBlendEnabled = false;
|
||||
bool wasColorArrayEnabled = false;
|
||||
GLint activeTextureUnit = 0;
|
||||
|
||||
std::array<const JGL::LightBase*, 8> J3D_Empty_Light_Array{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
std::array<const JGL::LightBase*, 8> J3D_Required_Lights{};
|
||||
std::vector<const JGL::LightBase*> J3D_Light_Array{};
|
||||
float j3d_far_plane = 0;
|
||||
float j3d_fov = 0;
|
||||
Vector2 wS;
|
||||
@@ -46,6 +49,8 @@ namespace JGL {
|
||||
}
|
||||
|
||||
InitTextEngine();
|
||||
Fonts::Init();
|
||||
ShapeCache::Init();
|
||||
wS = window_size;
|
||||
j3d_fov = fovY;
|
||||
j3d_far_plane = far_plane;
|
||||
@@ -62,6 +67,10 @@ namespace JGL {
|
||||
return false;
|
||||
if (!GLAD_GL_ARB_framebuffer_object)
|
||||
return false;
|
||||
if (!GLAD_GL_ARB_depth_texture)
|
||||
return false;
|
||||
if (!GLAD_GL_ARB_shadow)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -99,8 +108,10 @@ namespace JGL {
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureUnit);
|
||||
activeTextureUnit = activeTextureUnit - GL_TEXTURE0;
|
||||
|
||||
if (activeTextureUnit != 0)
|
||||
if (activeTextureUnit != 0) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
if (glIsEnabled(GL_DEPTH_TEST))
|
||||
wasDepthTestEnabled = true,
|
||||
@@ -171,6 +182,10 @@ namespace JGL {
|
||||
if (!wasBlendEnabled)
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
//Select whatever texture mapper was selected before.
|
||||
glActiveTexture(GL_TEXTURE0 + activeTextureUnit);
|
||||
glClientActiveTexture(GL_TEXTURE0 + activeTextureUnit);
|
||||
|
||||
if (wasTexture2DEnabled)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
@@ -180,9 +195,6 @@ namespace JGL {
|
||||
if (wasColorArrayEnabled)
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
//Select whatever texture_handle unit was selected before.
|
||||
glActiveTexture(GL_TEXTURE0 + activeTextureUnit);
|
||||
|
||||
//Put the draw color back how it was before.
|
||||
glColor4fv(oldColor);
|
||||
|
||||
@@ -226,6 +238,55 @@ namespace JGL {
|
||||
J2D::DrawLine(color, {x, y}, {w, h}, thickness);
|
||||
}
|
||||
|
||||
void 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();
|
||||
|
||||
unsigned int point_count = distance / spacing;
|
||||
std::vector<Vector2> points(point_count);
|
||||
|
||||
if (spacing > distance)
|
||||
Logger::Error("Drawing a dotted line that would have no dots?");
|
||||
|
||||
for (unsigned int i = 0; i < point_count; ++i)
|
||||
points[i] = A + direction * (i * spacing);
|
||||
|
||||
return J2D::DrawPoints(color, points.data(), points.size(), thickness);
|
||||
}
|
||||
|
||||
void J2D::DrawDottedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float thickness) {
|
||||
return J2D::DrawDottedLine(color, {x1, y1}, {x2, y2}, spacing, thickness);
|
||||
}
|
||||
|
||||
void J2D::DrawDashedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing, float dash_length, float thickness) {
|
||||
float distance = Vector2::Distance(A, B);
|
||||
Vector2 direction = (B - A).Normalized();
|
||||
float length_of_dash_and_gap = dash_length + spacing;
|
||||
unsigned int dash_count = distance / length_of_dash_and_gap;
|
||||
|
||||
if (spacing > distance)
|
||||
Logger::Error("Drawing a dashed line that would have no dashes?");
|
||||
|
||||
Vector2 A_current, B_current;
|
||||
for (unsigned int i = 0; i < dash_count; i++) {
|
||||
A_current = A + direction * (i * length_of_dash_and_gap);
|
||||
B_current = A_current + (direction * dash_length);
|
||||
J2D::DrawLine(color, A_current, B_current, thickness);
|
||||
}
|
||||
|
||||
// For the little piece at the end.
|
||||
float distance_left = distance - (dash_count * length_of_dash_and_gap);
|
||||
if (distance_left > 0) {
|
||||
A_current = A + direction * (dash_count * length_of_dash_and_gap);
|
||||
B_current = A_current + direction * std::min(dash_length, distance_left);
|
||||
J2D::DrawLine(color, A_current, B_current, thickness);
|
||||
}
|
||||
}
|
||||
|
||||
void J2D::DrawDashedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing, float dash_length, float thickness) {
|
||||
return J2D::DrawDashedLine(color, {x1, y1}, {x2, y2}, spacing, dash_length, thickness);
|
||||
}
|
||||
|
||||
void J2D::DrawGradientLine(const Color4& color1, const Color4& color2, const Vector2& A, const Vector2& B, float thickness) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
@@ -390,6 +451,147 @@ namespace JGL {
|
||||
if (rt.TextureCreatedByRenderTarget())
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void 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)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
if (texture.GetDimensions() != alpha_mask.GetDimensions())
|
||||
Logger::Warning("The alpha mask and the texture are not the same size.");
|
||||
|
||||
const Vector2 size = texture.GetDimensions();
|
||||
|
||||
std::array<Vector2, 4> textureCoordinates{};
|
||||
if (texture.GetFlags() & INVERT_Y)
|
||||
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.
|
||||
// i.e. to render at 2x size, from the center, at coords XY, use {2, 2} scale, and {0.5, 0.5} offset.
|
||||
const Vector2 offset = origin * size;
|
||||
Vector2 pos2 = position;
|
||||
Vector2 scaled_size = scale * size;
|
||||
Vector2 size2 = scaled_size;
|
||||
float cos_theta = std::cos(rad_rotation);
|
||||
float sin_theta = std::sin(rad_rotation);
|
||||
|
||||
std::array<Vector2, 4> vertices =
|
||||
{
|
||||
pos2, // Top-left vertex
|
||||
{pos2.x, pos2.y + size2.y}, // Bottom-left
|
||||
{pos2.x + size2.x, pos2.y + size2.y}, // Bottom-right
|
||||
{pos2.x + size2.x, pos2.y} // Top-right
|
||||
};
|
||||
|
||||
//Rotate the vertices about the origin by float rad_rotation.
|
||||
if (rad_rotation != 0)
|
||||
for (auto& v: vertices)
|
||||
v = {(v.x - pos2.x - offset.x * scale.x) * cos_theta - (v.y - pos2.y - offset.y * scale.y) * sin_theta +
|
||||
pos2.x + offset.x * scale.x,
|
||||
(v.x - pos2.x - offset.x * scale.x) * sin_theta + (v.y - pos2.y - offset.y * scale.y) * cos_theta +
|
||||
pos2.y + offset.y * scale.y
|
||||
};
|
||||
|
||||
if (inversion == Direction::Vertical)
|
||||
std::swap(textureCoordinates[0], textureCoordinates[1]),
|
||||
std::swap(textureCoordinates[3], textureCoordinates[2]);
|
||||
if (inversion == Direction::Horizontal)
|
||||
std::swap(textureCoordinates[0], textureCoordinates[3]),
|
||||
std::swap(textureCoordinates[1], textureCoordinates[2]);
|
||||
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
// Texture 0.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glBindTexture(GL_TEXTURE_2D, texture.GetGLTextureHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
|
||||
// Texture 1.
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, alpha_mask.GetGLTextureHandle());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), textureCoordinates.data());
|
||||
|
||||
// Draw.
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
// Reset Texture 1.
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
// Reset Texture 0.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, const Vector2& position, float rad_rotation,
|
||||
const Vector2& origin, const Vector2& scale,const Color4& color, Direction inversion) {
|
||||
DrawSprite(*texture, *alpha_mask, position, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawSprite(const Texture& texture, const Texture& alpha_mask, float positionX, float positionY, float rad_rotation,
|
||||
float originX, float originY,float scaleX, float scaleY,const Color4& color, Direction inversion) {
|
||||
DrawSprite(texture, alpha_mask, {positionX, positionY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawSprite(const Texture* texture, const Texture* alpha_mask, float positionX, float positionY, float rad_rotation,
|
||||
float originX, float originY,float scaleX, float scaleY,const Color4& color, Direction inversion) {
|
||||
DrawSprite(*texture, *alpha_mask, {positionX, positionY}, rad_rotation, {originX, originY}, {scaleX, scaleY}, color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawPartialRenderTarget(const JGL::RenderTarget& rt, 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, JGL::Direction inversion) {
|
||||
|
||||
//Correct for the render-target being upside-down.
|
||||
Direction d{};
|
||||
if (inversion == Direction::None && !(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
|
||||
d = Direction::Vertical;
|
||||
|
||||
else if (inversion == Direction::Horizontal) {
|
||||
d = Direction::Horizontal;
|
||||
if (!(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
|
||||
d = Direction::Horizontal | Direction::Vertical;
|
||||
}
|
||||
else if (inversion& Direction::Horizontal && inversion& Direction::Vertical) {
|
||||
d = Direction::Horizontal;
|
||||
if (!(rt.GetJGLTexture()->GetFlags() & INVERT_Y))
|
||||
d = Direction::Horizontal | Direction::Vertical;
|
||||
}
|
||||
|
||||
//Change the blending mode such that the alpha doesn't get multiplied again.
|
||||
if (rt.TextureCreatedByRenderTarget())
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
J2D::DrawPartialSprite(*rt.GetJGLTexture(), position, sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, d);
|
||||
|
||||
if (rt.TextureCreatedByRenderTarget())
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void J2D::DrawPartialRenderTarget(const JGL::RenderTarget* rt, 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) {
|
||||
DrawPartialRenderTarget(*rt, position, sub_texture_position, sub_texture_size, rad_rotation, origin, scale, color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawSprite(const Texture& texture, const Vector2& pos, float rad_rotation, const Vector2& origin,
|
||||
const Vector2& scale, const Color4& color, Direction inversion) {
|
||||
if (!inJ2D)
|
||||
@@ -462,7 +664,7 @@ namespace JGL {
|
||||
color, inversion);
|
||||
}
|
||||
|
||||
void J2D::DrawPartialSprite(const Texture& texture, const Vector2 &position, const Vector2& sub_texture_position,
|
||||
void 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)
|
||||
@@ -731,7 +933,7 @@ namespace JGL {
|
||||
}
|
||||
|
||||
//TODO render all in once pass with GL_LINE_LOOP instead of separate lines.
|
||||
void J2D::DrawCubicBezierCurve(const Color4 &color, const Vector2& controlA, const Vector2& pointA, const Vector2& pointB, const Vector2& controlB,
|
||||
void J2D::DrawCubicBezierCurve(const Color4& color, const Vector2& controlA, const Vector2& pointA, const Vector2& pointB, const Vector2& controlB,
|
||||
int subdivisions, float thickness) {
|
||||
|
||||
|
||||
@@ -763,7 +965,7 @@ namespace JGL {
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::DrawGradientLine(const Color4 &color_a, const Color4 &color_b, float x, float y, float w, float h,
|
||||
void J2D::DrawGradientLine(const Color4& color_a, const Color4& color_b, float x, float y, float w, float h,
|
||||
float thickness) {
|
||||
DrawGradientLine(color_a, color_b, {x, y}, {w, h}, thickness);
|
||||
}
|
||||
@@ -801,7 +1003,7 @@ namespace JGL {
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J2D::OutlineRoundedRect(const Color4 &color, const Vector2 &pos, const Vector2 &size, float radius, float thickness)
|
||||
void J2D::OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius, float thickness)
|
||||
{
|
||||
// A rounded rectangle of size 2a x 2b with rounding radius r is given by
|
||||
// f(x; a, r) + f(y; b, r) = 1
|
||||
@@ -865,7 +1067,7 @@ namespace JGL {
|
||||
|
||||
}
|
||||
|
||||
void J2D::FillChamferRect(const Color4 &color, const Vector2 &pos, const Vector2 &size, float radius) {
|
||||
void J2D::FillChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius) {
|
||||
FillRoundedRect(color, pos, size, radius, 4);
|
||||
}
|
||||
|
||||
@@ -900,14 +1102,12 @@ namespace JGL {
|
||||
FillTriangle(color, {triA, triB, triC});
|
||||
}
|
||||
|
||||
void
|
||||
J2D::FillGradientTriangle(const Color4 &a_color, const Color4 &b_color, const Color4 &c_color, const Vector2 &tri_a,
|
||||
const Vector2 &tri_b, const Vector2 &tri_c) {
|
||||
void J2D::FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Vector2& tri_a,
|
||||
const Vector2& tri_b, const Vector2& tri_c) {
|
||||
FillGradientTriangle(a_color, b_color, c_color, {tri_a, tri_b, tri_c});
|
||||
}
|
||||
|
||||
void
|
||||
J2D::OutlineEllipse(const Color4 &color, const Vector2 &position, float radius_x, float radius_y, float thickness,
|
||||
void J2D::OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness,
|
||||
int subdivisions) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
@@ -934,8 +1134,7 @@ namespace JGL {
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void
|
||||
J2D::FillEllipse(const Color4 &color, const Vector2 &position, float radius_x, float radius_y, int subdivisions) {
|
||||
void J2D::FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions) {
|
||||
if (!inJ2D)
|
||||
Logger::Error("Drawing J2D element before J2D begin.");
|
||||
|
||||
@@ -965,7 +1164,18 @@ namespace JGL {
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// TODO We're going to need two-pass rendering for occlusion queries and for determining what lights to use for what object.
|
||||
// We'll do a pre-render pass where we render a *very* simple scene where each object is replaced by an AABB.
|
||||
// Then, For each object we get a result on whether it was actually visible or not.
|
||||
// For lights, We can get the closest point on the AABB to each light and see how much it would influence that point.
|
||||
// Finally, we decide what lights to have enabled for the objects which were not occluded based on influence and distance from the camera.
|
||||
// For objects that are *extremely* big, Like base level geometry, I'll have to use its collision map for this to look right. - Redacted.
|
||||
|
||||
#pragma region J3D
|
||||
|
||||
#pragma region internal_drawables
|
||||
#pragma endregion
|
||||
|
||||
std::array<GLfloat, 16> OpenGLPerspectiveProjectionRH(float fovY, float aspect, float z_near, float z_far) {
|
||||
std::array<GLfloat, 16> result{};
|
||||
GLfloat f = 1.0f / std::tan(fovY * 0.5f * Math::Pi / 180.0f);
|
||||
@@ -977,6 +1187,14 @@ namespace JGL {
|
||||
return result;
|
||||
}
|
||||
|
||||
float EffectOfLightOnPointIn3DSpace(const PointLight* light, const Vector3& position) {
|
||||
Vector3 light_pos = light->GetPosition();
|
||||
Vector3 vector_to_position = position - light_pos;
|
||||
float distance = vector_to_position.Length();
|
||||
|
||||
return 1.0f / (light->GetConstantAttenuation() + light->GetLinearAttenuation() * distance + light->GetQuadraticAttenuation() * distance * distance);
|
||||
}
|
||||
|
||||
void J3D::ChangeFOV(float fov) {
|
||||
j3d_fov = fov;
|
||||
}
|
||||
@@ -985,6 +1203,17 @@ namespace JGL {
|
||||
j3d_far_plane = far_plane;
|
||||
}
|
||||
|
||||
void J3D::RequiredLight(const JGL::LightBase* light) {
|
||||
for (auto* i : J3D_Required_Lights)
|
||||
if (i == nullptr)
|
||||
i = light;
|
||||
}
|
||||
|
||||
void J3D::LightArray(const JGL::LightBase** lights, const size_t& light_count) {
|
||||
for (size_t i = 0; i < light_count; i++)
|
||||
J3D_Light_Array.push_back(lights[i]);
|
||||
}
|
||||
|
||||
void J3D::Begin() {
|
||||
|
||||
auto aspect = (float) wS.x / (float) wS.y;
|
||||
@@ -997,10 +1226,11 @@ namespace JGL {
|
||||
glGetFloatv(GL_CURRENT_COLOR, oldColor);
|
||||
glColor4fv(baseColor);
|
||||
|
||||
wasDepthTestEnabled = false;
|
||||
if (glIsEnabled(GL_DEPTH_TEST))
|
||||
wasDepthTestEnabled = true,
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
if (!glIsEnabled(GL_DEPTH_TEST))
|
||||
wasDepthTestEnabled = false,
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
else
|
||||
wasDepthTestEnabled = true;
|
||||
|
||||
wasVertexArraysEnabled = false;
|
||||
if (!glIsEnabled(GL_VERTEX_ARRAY))
|
||||
@@ -1027,6 +1257,12 @@ namespace JGL {
|
||||
else
|
||||
wasBlendEnabled = true;
|
||||
|
||||
// Reset the lights.
|
||||
J3D_Required_Lights = J3D_Empty_Light_Array;
|
||||
J3D_Light_Array = {};
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if (!inJ2D)
|
||||
inJ3D = true;
|
||||
else
|
||||
@@ -1034,8 +1270,8 @@ namespace JGL {
|
||||
}
|
||||
|
||||
void J3D::End() {
|
||||
if (wasDepthTestEnabled)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if (!wasDepthTestEnabled)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if (!wasVertexArraysEnabled)
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
@@ -1052,6 +1288,21 @@ namespace JGL {
|
||||
if (wasTextureCoordArrayEnabled)
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
if (glIsEnabled(GL_LIGHTING)) {
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_LIGHT0);
|
||||
glDisable(GL_LIGHT1);
|
||||
glDisable(GL_LIGHT2);
|
||||
glDisable(GL_LIGHT3);
|
||||
glDisable(GL_LIGHT4);
|
||||
glDisable(GL_LIGHT5);
|
||||
glDisable(GL_LIGHT6);
|
||||
glDisable(GL_LIGHT7);
|
||||
}
|
||||
|
||||
J3D_Required_Lights = J3D_Empty_Light_Array;
|
||||
J3D_Light_Array = {};
|
||||
|
||||
//Put the draw color back how it was before.
|
||||
glColor4fv(oldColor);
|
||||
inJ3D = false;
|
||||
@@ -1070,16 +1321,16 @@ namespace JGL {
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J3D::WireframeSphere(const Color4& color, const Vector3& position, float radius, float thickness, uint sectors, uint stacks) {
|
||||
void J3D::WireframeSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
Sphere sphere = {position, radius};
|
||||
BatchWireframeSphere(color, &sphere, 1, thickness, sectors, stacks);
|
||||
BatchWireframeSphere(color,& sphere, 1, thickness, sectors, stacks);
|
||||
}
|
||||
|
||||
void J3D::WireframeSphere(const Color4& color, const Sphere& sphere, float thickness, uint sectors, uint stacks) {
|
||||
BatchWireframeSphere(color, &sphere, 1, thickness, sectors, stacks);
|
||||
void J3D::WireframeSphere(const Color4& color, const Sphere& sphere, float thickness, unsigned int sectors, unsigned int stacks) {
|
||||
BatchWireframeSphere(color,& sphere, 1, thickness, sectors, stacks);
|
||||
}
|
||||
|
||||
void J3D::BatchWireframeSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, uint sectors, uint stacks) {
|
||||
void 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.");
|
||||
|
||||
@@ -1089,7 +1340,7 @@ namespace JGL {
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i <= sectors; i++) {
|
||||
float lat = M_PI * (-0.5 + (float) i / sectors);
|
||||
float lat = J3ML::Math::Pi * (-0.5 + (float) i / sectors);
|
||||
float z = J3ML::Math::Sin(lat);
|
||||
float zr = J3ML::Math::Cos(lat);
|
||||
|
||||
@@ -1121,23 +1372,23 @@ namespace JGL {
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J3D::WireframeRevoSphere(const Color4& color, const Vector3& position, float radius, float thickness, uint sectors, uint revolutions, bool draw_stacks) {
|
||||
void J3D::WireframeRevoSphere(const Color4& color, const Vector3& position, float radius, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
Sphere sphere = {position, radius};
|
||||
BatchWireframeRevoSphere(color, &sphere, 1, thickness, sectors, revolutions, draw_stacks);
|
||||
BatchWireframeRevoSphere(color,& sphere, 1, thickness, sectors, revolutions, draw_stacks);
|
||||
}
|
||||
|
||||
void J3D::WireframeRevoSphere(const Color4& color, const Sphere& sphere, float thickness, uint sectors, uint revolutions, bool draw_stacks) {
|
||||
BatchWireframeRevoSphere(color, &sphere, 1, thickness, sectors, revolutions, draw_stacks);
|
||||
void J3D::WireframeRevoSphere(const Color4& color, const Sphere& sphere, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
BatchWireframeRevoSphere(color,& sphere, 1, thickness, sectors, revolutions, draw_stacks);
|
||||
}
|
||||
|
||||
void J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, uint sectors, uint revolutions, bool draw_stacks) {
|
||||
void J3D::BatchWireframeRevoSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness, unsigned int sectors, unsigned int revolutions, bool draw_stacks) {
|
||||
float r = 1;
|
||||
std::vector<Vector3> vertices;
|
||||
vertices.reserve((sectors + 1) * (revolutions + 1));
|
||||
|
||||
std::vector<Vector3> cross_section(sectors + 1);
|
||||
for (int i = 0; i <= sectors; i++) {
|
||||
float lat = M_PI * (-0.5 + (float)i / sectors);
|
||||
float lat = J3ML::Math::Pi * (-0.5 + (float)i / sectors);
|
||||
float z = J3ML::Math::Sin(lat);
|
||||
float zr = J3ML::Math::Cos(lat);
|
||||
cross_section[i] = Vector3(0, zr * r, z * r);
|
||||
@@ -1145,7 +1396,7 @@ namespace JGL {
|
||||
|
||||
// Revolve
|
||||
for (int j = 0; j <= revolutions; j++) {
|
||||
float lng = 2 * M_PI * (float)j / revolutions;
|
||||
float lng = 2 * J3ML::Math::Pi * (float)j / revolutions;
|
||||
float cosLng = J3ML::Math::Cos(lng);
|
||||
float sinLng = J3ML::Math::Sin(lng);
|
||||
|
||||
@@ -1160,19 +1411,23 @@ namespace JGL {
|
||||
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
|
||||
|
||||
VRamList vertex_data(vertices.data(), vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_data.GetHandle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
|
||||
// Render each sphere in the batch at their given position and radius.
|
||||
for(size_t i = 0; i < sphere_count; i++) {
|
||||
glPushMatrix();
|
||||
glTranslatef(spheres[i].Position.x, spheres[i].Position.y, spheres[i].Position.z);
|
||||
glScalef(spheres[i].Radius, spheres[i].Radius, spheres[i].Radius);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
|
||||
if (draw_stacks)
|
||||
glRotatef(90, 0, 1, 0),
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
|
||||
glTranslatef(spheres[i].Position.x, spheres[i].Position.y, spheres[i].Position.z);
|
||||
glScalef(spheres[i].Radius, spheres[i].Radius, spheres[i].Radius);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertex_data.GetLength());
|
||||
if (draw_stacks)
|
||||
glRotatef(90, 0, 1, 0),
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertex_data.GetLength());
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
@@ -1250,8 +1505,7 @@ namespace JGL {
|
||||
}
|
||||
}
|
||||
|
||||
void J3D::WireframeIcosahedron(const Color4 &color, const Vector3 &position, float radius, float thickness) {
|
||||
|
||||
void J3D::WireframeIcosahedron(const Color4& color, const Vector3& position, float radius, float thickness) {
|
||||
if (!inJ3D)
|
||||
Logger::Error("Drawing J3D element before J3D begin.");
|
||||
|
||||
@@ -1296,220 +1550,170 @@ namespace JGL {
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness) {
|
||||
|
||||
if (!inJ3D)
|
||||
Logger::Error("Drawing J3D element before J3D begin.");
|
||||
|
||||
|
||||
// Top of cube
|
||||
Vector3 top_right_top = pos + Vector3(radii.x, radii.y, -radii.z);
|
||||
Vector3 top_left_top = pos + Vector3(-radii.x, radii.y, -radii.z);
|
||||
Vector3 bottom_left_top = pos - radii;
|
||||
Vector3 bottom_right_top = pos + Vector3(radii.x, radii.y, radii.z);
|
||||
|
||||
// Bottom of cube
|
||||
Vector3 top_right_bottom = pos + Vector3(radii.x, -radii.y, radii.z);
|
||||
Vector3 top_left_bottom = pos + Vector3(-radii.x, -radii.y, radii.z);
|
||||
Vector3 bottom_left_bottom = pos - radii;
|
||||
Vector3 bottom_right_bottom = pos + Vector3(radii.x, -radii.y, -radii.z);
|
||||
|
||||
// front of cube
|
||||
Vector3 top_right_front = pos + radii;
|
||||
Vector3 top_left_front = pos + Vector3(-radii.x, radii.y, radii.z);
|
||||
Vector3 bottom_left_front = pos + Vector3(-radii.x, -radii.y, radii.z);
|
||||
Vector3 bottom_right_front = pos + Vector3(radii.x, -radii.y, radii.z);
|
||||
|
||||
// back of cube
|
||||
Vector3 top_right_back = pos + Vector3(radii.x, -radii.y, -radii.z);
|
||||
Vector3 top_left_back = pos - radii;
|
||||
Vector3 bottom_left_back = pos + Vector3(-radii.x, radii.y, -radii.z);
|
||||
Vector3 bottom_right_back = pos + Vector3(radii.x, radii.y, -radii.z);
|
||||
|
||||
// left of cube
|
||||
Vector3 top_right_left = pos + Vector3(-radii.x, radii.y, radii.z);
|
||||
Vector3 top_left_left = pos + Vector3(-radii.x, radii.y, -radii.z);
|
||||
Vector3 bottom_left_left = pos - radii;
|
||||
Vector3 bottom_right_left = pos + Vector3(-radii.x, -radii.y, radii.z);
|
||||
|
||||
// right of cube
|
||||
Vector3 top_right_right = pos + Vector3(radii.x, radii.y, -radii.z);
|
||||
Vector3 top_left_right = pos + radii;
|
||||
Vector3 bottom_left_right = pos + Vector3(radii.x, -radii.y, radii.z);
|
||||
Vector3 bottom_right_right = pos + Vector3(radii.x, -radii.y, -radii.z);
|
||||
|
||||
std::vector<Vector3> vertices
|
||||
{
|
||||
top_right_top, top_left_top, bottom_left_top, bottom_right_top,
|
||||
top_right_bottom, top_left_bottom, bottom_left_bottom, bottom_right_bottom,
|
||||
top_right_front, top_left_front, bottom_left_front, bottom_right_front,
|
||||
top_right_back, top_left_back, bottom_left_back, bottom_right_back,
|
||||
top_right_left, top_left_left, bottom_left_left, bottom_right_left,
|
||||
top_right_right, top_left_right, bottom_left_right, bottom_right_right
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
void J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_t& box_count, float thickness) {
|
||||
glColor4ubv(color.ptr());
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
//glBindBuffer(GL_ARRAY_BUFFER, vertices.size());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
|
||||
glDrawArrays(GL_LINE_LOOP, 0, vertices.size());
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->GetHandle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
|
||||
for (size_t i = 0; i < box_count; i++) {
|
||||
Vector3 delta = (boxes[i].maxPoint - boxes[i].minPoint) / 2;
|
||||
Vector3 center = boxes[i].Centroid();
|
||||
glPushMatrix();
|
||||
glTranslatef(center.x, center.y, center.z);
|
||||
glScalef(delta.x, delta.y, delta.z);
|
||||
glDrawArrays(GL_LINES, 0, ShapeCache::cube_vertex_data->GetLength());
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glColor4fv(baseColor);
|
||||
}
|
||||
|
||||
void J3D::FillAABB(const Color4 &color, const Vector3 &pos, const Vector3 &radii) {
|
||||
void J3D::WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness) {
|
||||
AABB aabb = {Vector3(pos.x - radii.x, pos.y - radii.y, pos.z - radii.z), Vector3(pos.x + radii.x, pos.y + radii.y, pos.z + radii.z)};
|
||||
BatchWireframeAABB(color, &aabb, 1, thickness);
|
||||
}
|
||||
|
||||
void J3D::BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& box_count) {
|
||||
if (!inJ3D)
|
||||
Logger::Error("Drawing J3D element before J3D begin.");
|
||||
|
||||
// Top of cube
|
||||
Vector3 top_right_top = pos + Vector3(radii.x, radii.y, -radii.z);
|
||||
Vector3 bottom_right_top = pos + Vector3(radii.x, radii.y, radii.z);
|
||||
Vector3 bottom_left_top = pos + Vector3(-radii.x, radii.y, radii.z);
|
||||
Vector3 top_left_top = pos + Vector3(-radii.x, radii.y, -radii.z);
|
||||
|
||||
// Bottom of cube
|
||||
Vector3 top_right_bottom = pos + Vector3(radii.x, -radii.y, radii.z);
|
||||
Vector3 bottom_right_bottom = pos + Vector3(radii.x, -radii.y, -radii.z);
|
||||
Vector3 bottom_left_bottom = pos + Vector3(-radii.x, -radii.y, -radii.z);
|
||||
Vector3 top_left_bottom = pos + Vector3(-radii.x, -radii.y, radii.z);
|
||||
|
||||
// front of cube
|
||||
Vector3 top_right_front = pos + Vector3(radii.x, radii.y, radii.z);
|
||||
Vector3 bottom_right_front = pos + Vector3(radii.x, -radii.y, radii.z);
|
||||
Vector3 bottom_left_front = pos + Vector3(-radii.x, -radii.y, radii.z);
|
||||
Vector3 top_left_front = pos + Vector3(-radii.x, radii.y, radii.z);
|
||||
|
||||
// back of cube
|
||||
Vector3 top_right_back = pos + Vector3(radii.x, radii.y, -radii.z);
|
||||
Vector3 bottom_right_back = pos + Vector3(radii.x, -radii.y, -radii.z);
|
||||
Vector3 bottom_left_back = pos + Vector3(-radii.x, -radii.y, -radii.z);
|
||||
Vector3 top_left_back = pos + Vector3(-radii.x, radii.y, -radii.z);
|
||||
|
||||
// left of cube
|
||||
Vector3 top_right_left = pos + Vector3(-radii.x, radii.y, radii.z);
|
||||
Vector3 bottom_right_left = pos + Vector3(-radii.x, -radii.y, radii.z);
|
||||
Vector3 bottom_left_left = pos + Vector3(-radii.x, -radii.y, -radii.z);
|
||||
Vector3 top_left_left = pos + Vector3(-radii.x, radii.y, -radii.z);
|
||||
|
||||
// right of cube
|
||||
Vector3 top_right_right = pos + Vector3(radii.x, radii.y, -radii.z);
|
||||
Vector3 bottom_right_right = pos + Vector3(radii.x, -radii.y, -radii.z);
|
||||
Vector3 bottom_left_right = pos + Vector3(radii.x, -radii.y, radii.z);
|
||||
Vector3 top_left_right = pos + Vector3(radii.x, radii.y, radii.z);
|
||||
|
||||
std::vector<Vector3> vertices
|
||||
{
|
||||
top_right_top, bottom_right_top, bottom_left_top, top_left_top,
|
||||
top_right_bottom, bottom_right_bottom, bottom_left_bottom, top_left_bottom,
|
||||
top_right_front, bottom_right_front, bottom_left_front, top_left_front,
|
||||
top_right_back, bottom_right_back, bottom_left_back, top_left_back,
|
||||
top_right_left, bottom_right_left, bottom_left_left, top_left_left,
|
||||
top_right_right, bottom_right_right, bottom_left_right, top_left_right
|
||||
};
|
||||
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glColor4ubv(color.ptr());
|
||||
//glBindBuffer(GL_ARRAY_BUFFER, vertices.size());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
|
||||
glDrawArrays(GL_QUADS, 0, vertices.size());
|
||||
glColor4fv(baseColor);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ShapeCache::cube_vertex_data->GetHandle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
|
||||
for (size_t i = 0; i < box_count; i++) {
|
||||
Vector3 delta = (boxes[i].maxPoint - boxes[i].minPoint) / 2;
|
||||
Vector3 center = boxes[i].Centroid();
|
||||
glPushMatrix();
|
||||
glTranslatef(center.x, center.y, center.z);
|
||||
glScalef(delta.x, delta.y, delta.z);
|
||||
glDrawArrays(GL_QUAD_STRIP, 0, ShapeCache::cube_vertex_data->GetLength());
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4fv(oldColor);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
void J3D::FillAABB(const Color4& color, const Vector3& pos, const Vector3& radii) {
|
||||
AABB box = {pos - radii, pos + radii};
|
||||
BatchFillAABB(color, &box, 1);
|
||||
}
|
||||
|
||||
void J3D::FillAABB(const Color4 &color, const AABB &aabb) {
|
||||
FillAABB(color, aabb.Centroid(), aabb.Size());
|
||||
void J3D::FillAABB(const Color4& color, const AABB& aabb) {
|
||||
BatchFillAABB(color, &aabb, 1);
|
||||
}
|
||||
|
||||
void J3D::FillSphere(const Color4 &color, const Vector3& position, float radius, uint sectors, uint stacks) {
|
||||
void J3D::FillSphere(const Color4& color, const Sphere& sphere, unsigned int sectors, unsigned int stacks) {
|
||||
BatchFillSphere(color, &sphere, 1, sectors, stacks);
|
||||
}
|
||||
|
||||
void 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);
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
unsigned int lats = sectors;
|
||||
unsigned int longs = stacks;
|
||||
|
||||
float r = radius;
|
||||
std::vector<Vector3> vertices((lats + 1) * (longs + 1));
|
||||
|
||||
float two_pi = 2 * J3ML::Math::Pi;
|
||||
int index = 0;
|
||||
for (int i = 0; i <= lats; i++) {
|
||||
float lat = M_PI * (-0.5 + (float) i / lats);
|
||||
for (int i = 0; i <= sectors; i++) {
|
||||
float lat = J3ML::Math::Pi * (-0.5 + (float) i / sectors);
|
||||
float z = J3ML::Math::Sin(lat);
|
||||
float zr = J3ML::Math::Cos(lat);
|
||||
|
||||
for (int j = 0; j <= longs; j++) {
|
||||
float lng = 2 * J3ML::Math::Pi * (float) (j - 1) / longs;
|
||||
for (int j = 0; j <= stacks; j++) {
|
||||
float lng = two_pi * (float) (j - 1) / stacks;
|
||||
float x = J3ML::Math::Cos(lng);
|
||||
float y = J3ML::Math::Sin(lng);
|
||||
|
||||
float pos_x = r * x * zr;
|
||||
float pos_y = r * y * zr;
|
||||
float pos_z = r * z;
|
||||
|
||||
pos_x += position.x;
|
||||
pos_y += position.y;
|
||||
pos_z += position.z;
|
||||
|
||||
vertices[index++] = Vector3(pos_x, pos_y, pos_z);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < sectors; i++) {
|
||||
for (int j = 0; j < stacks; j++) {
|
||||
int first_index = i * (stacks + 1) + j;
|
||||
int second_index = first_index + stacks + 1;
|
||||
|
||||
indices.push_back(first_index);
|
||||
indices.push_back(second_index);
|
||||
indices.push_back(first_index + 1);
|
||||
|
||||
indices.push_back(second_index);
|
||||
indices.push_back(second_index + 1);
|
||||
indices.push_back(first_index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
VRamList vertex_data(vertices.data(), vertices.size());
|
||||
VRamList index_data(indices.data(), indices.size());
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()); // TODO: Make it render correctingly!
|
||||
glColor4fv(baseColor);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_data.GetHandle());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_data.GetHandle());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), nullptr);
|
||||
|
||||
for (size_t i = 0; i < sphere_count; i++) {
|
||||
const Vector3 position = spheres[i].Position;
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glScalef(spheres[i].Radius, spheres[i].Radius, spheres[i].Radius);
|
||||
glDrawElements(GL_TRIANGLES, index_data.GetLength(), GL_UNSIGNED_INT, nullptr);
|
||||
glPopMatrix();
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glColor4fv(oldColor);
|
||||
}
|
||||
|
||||
void J3D::WireframeAABB(const Color4 &color, const AABB &aabb, float thickness) {
|
||||
WireframeAABB(color, aabb.Centroid(), aabb.Size(), thickness);
|
||||
void J3D::FillSphere(const Color4& color, const Vector3& position, float radius, unsigned int sectors, unsigned int stacks) {
|
||||
Sphere sphere = {position, radius};
|
||||
BatchFillSphere(color, &sphere, 1, sectors, stacks);
|
||||
}
|
||||
|
||||
// Why is this here?
|
||||
float ComputeBinomial(int n, int k)
|
||||
{
|
||||
float value = 1.f;
|
||||
|
||||
for (int i = 1; i <= k; i++)
|
||||
value = value * ((n + 1 - i) / i);
|
||||
|
||||
if (n == k)
|
||||
value = 1;
|
||||
|
||||
return value;
|
||||
void J3D::WireframeAABB(const Color4& color, const AABB& aabb, float thickness) {
|
||||
BatchWireframeAABB(color, &aabb, 1, thickness);
|
||||
}
|
||||
|
||||
void J3D::WireframeOBB(const Color4& color, const J3ML::Geometry::OBB& obb, float thickness) {
|
||||
// TODO Make it work the same as AABB batching. I couldn't get rotation to do anything more than twitch in place :(.
|
||||
void J3D::BatchWireframeOBB(const Color4& color, const OBB* boxes, const size_t& box_count, float thickness) {
|
||||
std::array<Vector3, 8> corner_points;
|
||||
obb.GetCornerPoints(corner_points.data());
|
||||
|
||||
std::array<GLuint, 24> indices =
|
||||
{
|
||||
0, 1, 1, 2, 2, 3, 3, 0,
|
||||
4, 5, 5, 6, 6, 7, 7, 4,
|
||||
0, 4, 1, 5, 2, 6, 3, 7
|
||||
0, 1, 1, 2, 2, 3, 3, 0,
|
||||
4, 5, 5, 6, 6, 7, 7, 4,
|
||||
0, 4, 1, 5, 2, 6, 3, 7
|
||||
};
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(obb.pos.x, obb.pos.y, obb.pos.z);
|
||||
|
||||
glLineWidth(thickness);
|
||||
glColor4ubv(color.ptr());
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), corner_points.data());
|
||||
glDrawElements(GL_LINES, indices.size(), GL_UNSIGNED_INT, indices.data());
|
||||
glColor4fv(baseColor);
|
||||
glPopMatrix();
|
||||
|
||||
for (size_t i = 0; i < box_count; i++) {
|
||||
boxes[i].GetCornerPoints(corner_points.data());
|
||||
glPushMatrix();
|
||||
glTranslatef(boxes[i].pos.x, boxes[i].pos.y, boxes[i].pos.z);
|
||||
glDrawElements(GL_LINES, indices.size(), GL_UNSIGNED_INT, indices.data());
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4fv(oldColor);
|
||||
}
|
||||
|
||||
void J3D::WireframeOBB(const Color4& color, const J3ML::LinearAlgebra::Vector3& position, const J3ML::LinearAlgebra::Vector3& radii,
|
||||
const J3ML::LinearAlgebra::EulerAngle& orientation, float thickness) {
|
||||
Matrix3x3 rotation = orientation.ToQuaternion().ToMatrix3x3();
|
||||
WireframeOBB(color, OBB(position, radii, rotation * Vector3::UnitX, rotation * Vector3::UnitY, rotation * Vector3::UnitZ), thickness);
|
||||
void J3D::WireframeOBB(const Color4& color, const OBB& obb, float thickness) {
|
||||
BatchWireframeOBB(color, &obb, 1, thickness);
|
||||
}
|
||||
|
||||
/*
|
||||
void J3D::WireframeOBB(const Color4& color, const Vector3& position, const Vector3& radii, const Matrix3x3& orientation, float thickness) {
|
||||
WireframeOBB(color, OBB(position, radii, orientation. * Vector3::UnitX, rotation * Vector3::UnitY, rotation * Vector3::UnitZ), thickness);
|
||||
}
|
||||
*/
|
||||
|
||||
void J3D::DrawCubicBezierCurve(const Color4& color, const Vector3& controlA, const Vector3& pointA,
|
||||
const Vector3& pointB, const Vector3& controlB, int subdivisions, float thickness) {
|
||||
Vector3 last = controlA;
|
||||
|
38
src/ShapeCache.cpp
Normal file
38
src/ShapeCache.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <JGL/JGL.h>
|
||||
|
||||
void JGL::ShapeCache::Init() {
|
||||
if (!cube_vertex_data) {
|
||||
std::array<Vector3, 24> vertices {
|
||||
Vector3(-1, 1, -1), Vector3(1, 1, -1),
|
||||
Vector3(1, 1, -1), Vector3(1, 1, 1),
|
||||
Vector3(1, 1, 1), Vector3(-1, 1, 1),
|
||||
Vector3(-1, 1, 1), Vector3(-1, 1, -1),
|
||||
Vector3(-1, -1, -1), Vector3(1, -1, -1),
|
||||
Vector3(1, -1, -1), Vector3(1, -1, 1),
|
||||
Vector3(1, -1, 1), Vector3(-1, -1, 1),
|
||||
Vector3(-1, -1, 1), Vector3(-1, -1, -1),
|
||||
Vector3(-1, -1, -1), Vector3(-1, 1, -1),
|
||||
Vector3(1, -1, -1), Vector3(1, 1, -1),
|
||||
Vector3(1, -1, 1), Vector3(1, 1, 1),
|
||||
Vector3(-1, -1, 1), Vector3(-1, 1, 1)
|
||||
};
|
||||
cube_vertex_data = new VRamList(vertices.data(), vertices.size());
|
||||
}
|
||||
|
||||
if (!cube_index_data) {
|
||||
std::array<GLuint, 36> indices {
|
||||
0, 1, 3, 0, 3, 5,
|
||||
|
||||
8, 9, 11, 8, 11, 13,
|
||||
|
||||
5, 3, 11, 5, 11, 13,
|
||||
|
||||
0, 1, 9, 0, 9, 8,
|
||||
|
||||
0, 5, 13, 0, 13, 8,
|
||||
|
||||
1, 3, 11, 1, 11, 9
|
||||
};
|
||||
cube_index_data = new VRamList(indices.data(), indices.size());
|
||||
}
|
||||
}
|
@@ -162,7 +162,7 @@ namespace JGL {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void J3D::DrawString(const Color4& color, const std::string& text, const Vector3& pos, float scale, u32 size, const Font& font, const EulerAngle& angle, bool draw_back_face) {
|
||||
void J3D::DrawString(const Color4& color, const std::string& text, const Vector3& pos, float scale, u32 size, const Font& font, const EulerAngleXYZ& angle, bool draw_back_face) {
|
||||
// TODO: Determine the proper scale factor mathematically
|
||||
// This number was arrived at holistically.
|
||||
scale = scale * 0.002f;
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <iostream>
|
||||
#include <glad/glad.h>
|
||||
#include <JGL/logger/logger.h>
|
||||
#include <JGL/JGL.h>
|
||||
|
||||
#if __linux__
|
||||
#include <freetype2/ft2build.h>
|
||||
@@ -58,25 +59,38 @@ namespace JGL {
|
||||
return Detail::InitTextEngine();
|
||||
}
|
||||
|
||||
Font::Font(const unsigned char* data, const size_t& size) {
|
||||
if (Detail::ft == nullptr)
|
||||
throw std::runtime_error("Error::FREETYPE: FT_Library was not initialized before attempting to load a font!");
|
||||
|
||||
if (FT_New_Memory_Face(Detail::ft, data, size, 0, &face))
|
||||
throw std::runtime_error("Error::FREETYPE: Failed to load font!");
|
||||
|
||||
unsigned int new_index = 0;
|
||||
for (const auto& f : Detail::fonts)
|
||||
if (f.index >= new_index)
|
||||
new_index = f.index + 1;
|
||||
index = new_index;
|
||||
|
||||
Detail::fonts.push_back(*this);
|
||||
std::cout << "Loaded font from memory at " << static_cast<const void*>(data) << " with index " << new_index << std::endl;
|
||||
}
|
||||
|
||||
Font::Font(const std::filesystem::path& path) {
|
||||
if (Detail::ft == nullptr)
|
||||
throw std::runtime_error("Error::FREETYPE: FT_Library was not initialized before attempting to load a font!");
|
||||
|
||||
Font font;
|
||||
if (FT_New_Face(Detail::ft, path.string().c_str(), 0, &face)) {
|
||||
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
|
||||
if (FT_New_Face(Detail::ft, path.string().c_str(), 0, &face))
|
||||
throw std::runtime_error("Error::FREETYPE: Failed to load font!");
|
||||
//return -1;
|
||||
}
|
||||
unsigned int newIndex = 0;
|
||||
for (const auto& f : Detail::fonts)
|
||||
if (f.index >= newIndex)
|
||||
newIndex = f.index + 1;
|
||||
|
||||
index = newIndex;
|
||||
Detail::fonts.push_back(font);
|
||||
std::cout << "Loaded font from " << path << " with index " << newIndex << std::endl;
|
||||
//return newIndex;
|
||||
unsigned int new_index = 0;
|
||||
for (const auto& f : Detail::fonts)
|
||||
if (f.index >= new_index)
|
||||
new_index = f.index + 1;
|
||||
|
||||
index = new_index;
|
||||
Detail::fonts.push_back(*this);
|
||||
std::cout << "Loaded font from " << path << " with index " << new_index << std::endl;
|
||||
}
|
||||
|
||||
Font::~Font() {
|
||||
@@ -119,14 +133,14 @@ namespace JGL {
|
||||
return extents;
|
||||
}
|
||||
|
||||
jlog::Warning("Measuring a font size that is not cached, This is *super* slow.");
|
||||
FT_Set_Pixel_Sizes(this->face, ptSize, ptSize);
|
||||
jlog::Warning("Measuring a font size that is not cached, Defaulting to Jupiteroid.");
|
||||
FT_Set_Pixel_Sizes(Fonts::Jupiteroid.face, ptSize, ptSize);
|
||||
|
||||
for (const char& c : text) {
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
auto glyph_index = FT_Get_Char_Index(this->face, c);
|
||||
FT_GlyphSlot slot = Fonts::Jupiteroid.face->glyph;
|
||||
auto glyph_index = FT_Get_Char_Index(Fonts::Jupiteroid.face, c);
|
||||
|
||||
auto error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||
auto error = FT_Load_Glyph(Fonts::Jupiteroid.face, glyph_index, FT_LOAD_DEFAULT);
|
||||
|
||||
if (error)
|
||||
continue;
|
||||
@@ -146,9 +160,6 @@ namespace JGL {
|
||||
if (extents.y < ptSize)
|
||||
extents.y = ptSize;
|
||||
}
|
||||
|
||||
return extents;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,19 +1,64 @@
|
||||
#include <JGL/types/Light.h>
|
||||
#include <glad/glad.h>
|
||||
|
||||
JGL::Light::Light(const Vector3& position, const Color4& ambient, const Color4& diffuse, const Color4& specular) {
|
||||
JGL::PointLight::PointLight(const Vector3& position, const Color4& ambient, const Color4& diffuse, const Color4& specular, float constant_attenuation, float linear_attenuation, float quadratic_attenuation) {
|
||||
this->position = Vector4(position, 1.0f);
|
||||
this->ambient = ambient;
|
||||
this->diffuse = diffuse;
|
||||
this->specular = specular;
|
||||
this->constant_attenuation = constant_attenuation;
|
||||
this->linear_attenuation = linear_attenuation;
|
||||
this->quadratic_attenuation = quadratic_attenuation;
|
||||
}
|
||||
|
||||
Vector3 JGL::Light::GetNormalizedSceenSpaceCoordinates() const {
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
float JGL::PointLight::GetAttenuationAtPosition(const Vector3& pos) const {
|
||||
Vector3 light_pos = {position.x, position.y, position.z};
|
||||
Vector3 vector_to_position = pos - light_pos;
|
||||
float distance = vector_to_position.Length();
|
||||
|
||||
float normalized_x = 2.0f * (position.x - viewport[0]) / viewport[2] - 1.0f;
|
||||
float normalized_y = 2.0f * (position.y - viewport[1]) / viewport[3] - 1.0f;
|
||||
|
||||
return {normalized_x, normalized_y, position.z};
|
||||
return 1.0f / (GetConstantAttenuation() + GetLinearAttenuation() * distance + GetQuadraticAttenuation() * distance * distance);
|
||||
}
|
||||
|
||||
JGL::SpotLight::SpotLight(const Vector3& position, const Matrix3x3& ro_mat, float cone_size_degrees, float exponent, const Color4& ambient, const Color4& diffuse, const Color4& specular,
|
||||
float constant_attenuation, float linear_attenuation, float quadratic_attenuation) {
|
||||
this->position = Vector4(position, 1);
|
||||
//TODO RotationMatrix to "Normalized direction vector."
|
||||
orientation = ro_mat;
|
||||
this->cut = cone_size_degrees;
|
||||
this->exponent = exponent;
|
||||
this->ambient = ambient;
|
||||
this->diffuse = diffuse;
|
||||
this->specular = specular;
|
||||
this->constant_attenuation = constant_attenuation;
|
||||
this->linear_attenuation = linear_attenuation;
|
||||
this->quadratic_attenuation = quadratic_attenuation;
|
||||
}
|
||||
|
||||
Vector3 JGL::LightBase::GetPosition() const {
|
||||
return {position.x, position.y, position.z};
|
||||
}
|
||||
|
||||
Color4 JGL::LightBase::GetAmbient() const {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
Color4 JGL::LightBase::GetDiffuse() const {
|
||||
return diffuse;
|
||||
}
|
||||
|
||||
Color4 JGL::LightBase::GetSpecular() const {
|
||||
return specular;
|
||||
}
|
||||
|
||||
float JGL::LightBase::GetConstantAttenuation() const {
|
||||
return constant_attenuation;
|
||||
}
|
||||
|
||||
float JGL::LightBase::GetLinearAttenuation() const {
|
||||
return linear_attenuation;
|
||||
}
|
||||
|
||||
float JGL::LightBase::GetQuadraticAttenuation() const {
|
||||
return quadratic_attenuation;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -331,12 +331,14 @@ void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget*
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
|
||||
}
|
||||
|
||||
// To avoid repeatedly allocating and deallocating.
|
||||
JGL::RenderTarget* pixel = nullptr;
|
||||
void JGL::RenderTarget::Blit(const Color4& color, const Vector2& position, JGL::RenderTarget* destination) {
|
||||
if (position.x > destination->size.x || position.y > destination->size.y)
|
||||
Logger::Warning("Blitting outside of the renderable area of the destination.");
|
||||
|
||||
Texture texture(Vector2(1,1));
|
||||
RenderTarget source(&texture,color);
|
||||
if (pixel == nullptr)
|
||||
pixel = new RenderTarget({1,1});
|
||||
|
||||
GLint current_draw_fbo = 0;
|
||||
GLint current_read_fbo = 0;
|
||||
@@ -348,13 +350,14 @@ void JGL::RenderTarget::Blit(const Color4& color, const Vector2& position, JGL::
|
||||
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, ¤t_read_fbo);
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_draw_fbo);
|
||||
|
||||
SetActiveGLRenderTarget(source);
|
||||
SetActiveGLRenderTarget(*pixel);
|
||||
glClearColor(color.RedChannelNormalized(), color.GreenChannelNormalized(), color.BlueChannelNormalized(), color.AlphaChannelNormalized());
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Invert so it's relative to the top left corner.
|
||||
int target_y = destination->size.y - position.y - 1;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.framebuffer_object);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, pixel->framebuffer_object);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination->framebuffer_object);
|
||||
glBlitFramebuffer(0, 0, 1, 1, position.x, target_y, position.x + 1, target_y + 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
|
Reference in New Issue
Block a user