Compare commits

...

43 Commits

Author SHA1 Message Date
122644a013 Update repositories
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m3s
2024-12-04 14:25:48 -05:00
Redacted
641f2de8d0 Update CMakeLists.txt
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m22s
2024-12-04 11:16:20 -05:00
6618aa5e6b just pushing what I have
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m20s
2024-12-01 11:00:48 -05:00
3970aa2718 Update GLAD
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m22s
2024-11-25 16:53:20 -05:00
fb5ca55fda Alpha masked sprite.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m44s
2024-11-22 07:46:48 -05:00
bcca6285af J2D DottedLine & DashedLine
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m41s
2024-11-20 18:04:21 -05:00
f8395726cd Improve performance of single-pixel blit.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m5s
2024-11-20 09:23:09 -05:00
ca7abb3044 DrawPartialRenderTarget
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m57s
2024-11-19 19:55:08 -05:00
14c45ab0f1 Merge branch 'master' of https://git.redacted.cc/Josh/JGL
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m34s
2024-11-14 18:19:42 -05:00
1ca5e5a694 Fix for Windows. 2024-11-14 18:22:28 -05:00
25fc3f8698 Fix for Windows.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-11-14 18:20:57 -05:00
a836fc7b32 More batching & performance optimization.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m56s
2024-11-14 16:14:18 -05:00
e6dcc9d61e Reformatting
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m56s
2024-11-14 10:57:00 -05:00
6dff2f97c1 BatchWireframeAABB
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m54s
2024-11-13 21:07:21 -05:00
dbcc3e11e1 Update CMakeLists.txt
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m23s
2024-11-13 15:16:29 -05:00
b2bc1170df Blit single pixel onto target RenderTarget (cave-game)
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m25s
2024-11-13 11:51:20 -05:00
5d7fe84bd0 BatchWireframeRevoSphere
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m11s
2024-11-13 10:04:32 -05:00
627a047a9b Batching for WireframeSphere.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m48s
2024-11-12 22:50:18 -05:00
f0e2cd151f cleanup
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m43s
2024-11-12 21:41:42 -05:00
bf60c14d5e Improve thread safety.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m42s
2024-11-12 14:31:43 -05:00
83a9baea34 Cleanup
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m9s
2024-11-12 11:31:18 -05:00
Redacted
95de887499 Update README.md
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m48s
2024-11-01 15:13:02 -04:00
81ebc175e2 Structures for skeletons
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m57s
2024-11-01 13:09:32 -04:00
82669b43bc Wireframe OBB + VertexArray
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m47s
2024-10-31 12:50:56 -04:00
779f212a29 Implemented J3D::DrawCubicBezierCurve
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m42s
2024-10-25 13:17:07 -04:00
0cc18cfdad J3D Framework Progress
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m19s
2024-10-25 11:35:31 -04:00
da35075735 Work-in-progress documentation for J3D x2
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m21s
2024-10-24 13:33:32 -04:00
d29ea018c3 Work-in-progress documentation for J3D
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 3m55s
2024-10-24 13:22:51 -04:00
72c256f907 FillSphere is completely fucked.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m46s
2024-10-24 12:42:38 -04:00
7687c0d873 fix winding order
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m51s
2024-10-24 12:23:55 -04:00
ad34e9ffc0 Implement FillAABB
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m1s
2024-10-24 12:09:59 -04:00
5a9716af02 Implementation of WireframeAABB (Still validating?)
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 7m1s
2024-10-24 11:24:25 -04:00
ce5c4d4eb1 Sending up work
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m44s
2024-10-23 14:16:33 -04:00
0302c43f5d Merge branch 'master' of https://git.redacted.cc/Josh/JGL
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m41s
2024-10-22 22:32:27 -04:00
9a5554e447 Update README.md 2024-10-22 22:32:21 -04:00
7dada0e51f This Dick
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m47s
2024-10-22 20:32:32 -04:00
807eef59bc a word
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m47s
2024-10-22 19:04:49 -04:00
4d97c6dead Make it go faster
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-10-22 19:02:01 -04:00
686a4be0c9 Visible Wireframe Sphere, need some camera rotation to see it properly though.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 6m44s
2024-10-22 13:46:59 -04:00
68ba438433 Fix Prior issue with circle render.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m17s
2024-10-22 13:30:52 -04:00
e4a4f01b28 Un-commenting Line 166 stops all rendering, also, it appears circles are gone?
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Has been cancelled
2024-10-22 13:26:04 -04:00
aa4a29961c Implement FillEllipse and OutlineEllipse
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 4m30s
2024-10-22 12:26:40 -04:00
55b67ab850 Update RenderTarget.cpp
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m38s
crash related to making a render target with a color attachment 0x0
2024-10-22 10:49:56 -04:00
25 changed files with 2436 additions and 544 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
/cmake-build-debug
/.idea
/assets/test_files

View File

@@ -22,17 +22,17 @@ CPMAddPackage(
CPMAddPackage(
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/Release-3.2.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(
@@ -89,23 +89,23 @@ target_include_directories(JGL PUBLIC
${ReImage_SOURCE_DIR}/include
${mcolor_SOURCE_DIR}/include
${J3ML_SOURCE_DIR}/include
${glad_SOURCE_DIR}/include
${jlog_SOURCE_DIR}/include
${glad_SOURCE_DIR}/include
)
add_executable(JGL_Demo main.cpp)
#set_target_properties(JGL_Demo PROPERTIES LINK_FLAGS "-Wl,-rpath,./lib")
if (UNIX AND NOT APPLE)
target_include_directories(JGL PRIVATE ${FREETYPE_INCLUDE_DIRS})
target_include_directories(JGL PRIVATE ${FREETYPE_INCLUDE_DIRS} )
target_link_libraries(JGL PRIVATE ${FREETYPE_LIBRARIES})
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML glad jlog ReImage)
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML jlog ReImage 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)
target_link_libraries(JGL PUBLIC ${OPENGL_LIBRARIES} mcolor J3ML glad jlog ReImage glad)
endif()
target_link_libraries(JGL_Demo PUBLIC JGL ReWindowLibrary Event)
target_link_libraries(JGL_Demo PUBLIC JGL ReWindowLibrary Event glad)

175
Doxyfile
View File

@@ -1,4 +1,4 @@
# Doxyfile 1.9.6
# Doxyfile 1.9.4
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -19,8 +19,7 @@
# configuration file:
# doxygen -x [configFile]
# Use doxygen to compare the used configuration file with the template
# configuration file without replacing the environment variables or CMake type
# replacement variables:
# configuration file without replacing the environment variables:
# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
@@ -42,7 +41,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = JGL
PROJECT_NAME = "Josh's Graphics Library"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
@@ -54,21 +53,21 @@ PROJECT_NUMBER =
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "Linear Algebra, Geometry, and Algorithms in C++"
PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO = logo_light_small.png
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = .
OUTPUT_DIRECTORY = "../../JGL DOXY"
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# sub-directories (in 2 levels) under the output directory of each output format
@@ -79,14 +78,14 @@ OUTPUT_DIRECTORY = .
# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
CREATE_SUBDIRS = YES
# Controls the number of sub-directories that will be created when
# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
# level increment doubles the number of directories, resulting in 4096
# directories at level 8 which is the default and also the maximum value. The
# sub-directories are organized in 2 levels, the first level always has a fixed
# number of 16 directories.
# numer of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8.
# This tag requires that the tag CREATE_SUBDIRS is set to YES.
@@ -568,8 +567,7 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# will also hide undocumented C++ concepts if enabled. This option has no effect
# if EXTRACT_ALL is enabled.
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
@@ -607,10 +605,9 @@ INTERNAL_DOCS = NO
# Windows (including Cygwin) and MacOS, users should typically set this option
# to NO, whereas on Linux or other Unix flavors it should typically be set to
# YES.
# Possible values are: SYSTEM, NO and YES.
# The default value is: SYSTEM.
# The default value is: system dependent.
CASE_SENSE_NAMES = SYSTEM
CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the
@@ -860,14 +857,6 @@ WARN_IF_INCOMPLETE_DOC = YES
WARN_NO_PARAMDOC = NO
# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
# undocumented enumeration values. If set to NO, doxygen will accept
# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: NO.
WARN_IF_UNDOC_ENUM_VAL = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
@@ -926,21 +915,10 @@ INPUT = include \
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see:
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# This tag can be used to specify the character encoding of the source files
# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
# character encoding on a per file pattern basis. Doxygen will compare the file
# name with each pattern and apply the encoding instead of the default
# INPUT_ENCODING) if there is a match. The character encodings are a list of the
# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
# "INPUT_ENCODING" for further information on supported encodings.
INPUT_FILE_ENCODING =
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
@@ -1089,11 +1067,6 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that doxygen will use the data processed and written to standard output
# for further processing, therefore nothing else, like debug statements or used
# commands (so in case of a Windows batch file always use @echo OFF), should be
# written to standard output.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
@@ -1135,15 +1108,6 @@ FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
# The Fortran standard specifies that for fixed formatted Fortran code all
# characters from position 72 are to be considered as comment. A common
# extension is to allow longer lines before the automatic comment starts. The
# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
# be processed before the automatic comment starts.
# Minimum value: 7, maximum value: 10000, default value: 72.
FORTRAN_COMMENT_AFTER = 72
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
@@ -1281,11 +1245,10 @@ CLANG_DATABASE_PATH =
ALPHABETICAL_INDEX = YES
# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
# that should be ignored while generating the index headers. The IGNORE_PREFIX
# tag works for classes, function and member names. The entity will be placed in
# the alphabetical list under the first letter of the entity name that remains
# after removing the prefix.
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
@@ -1364,15 +1327,10 @@ HTML_STYLESHEET =
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list).
# Note: Since the styling of scrollbars can currently not be overruled in
# Webkit/Chromium, the styling will be left out of the default doxygen.css if
# one or more extra stylesheets have been specified. So if scrollbar
# customization is desired it has to be added explicitly. For an example see the
# documentation.
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_STYLESHEET = ../../doxygen_theme_flat_design/src/doxygen-style.css
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@@ -1382,20 +1340,11 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
# should be rendered with a dark or light theme.
# Possible values are: LIGHT always generate light mode output, DARK always
# generate dark mode output, AUTO_LIGHT automatically set the mode according to
# the user preference, use light mode if no preference is set (the default),
# AUTO_DARK automatically set the mode according to the user preference, use
# dark mode if no preference is set and TOGGLE allow to user to switch between
# light and dark mode via a button.
# The default value is: AUTO_LIGHT.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE = AUTO_DARK
HTML_EXTRA_FILES = ../../doxygen_theme_flat_design/src/img/opened-folder.png \
../../doxygen_theme_flat_design/src/img/on_sync.png \
../../doxygen_theme_flat_design/src/img/off_sync.png \
../../doxygen_theme_flat_design/src/img/document.png \
../../doxygen_theme_flat_design/src/img/closed-folder.png
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
@@ -1406,7 +1355,7 @@ HTML_COLORSTYLE = AUTO_DARK
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_HUE = 337
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use gray-scales only. A
@@ -1414,7 +1363,7 @@ HTML_COLORSTYLE_HUE = 220
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_SAT = 15
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
@@ -1425,7 +1374,7 @@ HTML_COLORSTYLE_SAT = 100
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
HTML_COLORSTYLE_GAMMA = 169
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
@@ -1695,7 +1644,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = YES
GENERATE_TREEVIEW = NO
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
@@ -1760,6 +1709,17 @@ HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details.
@@ -1859,7 +1819,7 @@ MATHJAX_CODEFILE =
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using JavaScript. There
@@ -2465,7 +2425,7 @@ HIDE_UNDOC_RELATIONS = YES
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
# The default value is: YES.
HAVE_DOT = YES
@@ -2479,38 +2439,26 @@ HAVE_DOT = YES
DOT_NUM_THREADS = 0
# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
# subgraphs. When you want a differently looking font in the dot files that
# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
# Edge and Graph Attributes specification</a> You need to make sure dot is able
# to find the font, which can be done by putting it in a standard location or by
# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font. Default graphviz fontsize is 14.
# The default value is: fontname=Helvetica,fontsize=10.
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
DOT_FONTNAME = Helvetica
# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
# arrows shapes.</a>
# The default value is: labelfontname=Helvetica,labelfontsize=10.
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
DOT_FONTSIZE = 10
# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
# around nodes set 'shape=plain' or 'shape=plaintext' <a
# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
# The default value is: shape=box,height=0.2,width=0.4.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
# You can set the path where dot can find font specified with fontname in
# DOT_COMMON_ATTR and others dot attributes.
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
@@ -2666,8 +2614,9 @@ DIR_GRAPH_MAX_DEPTH = 1
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# Possible values are: png, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd,
# gif, gif:cairo, gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd,
# png:cairo, png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
@@ -2753,6 +2702,18 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support

View File

@@ -1,30 +1,31 @@
# Josh Graphics Library
# Josh's Graphics Library
Yet Another C++ Rendering Toolkit
![Static Badge](https://img.shields.io/badge/Lit-Based-%20)
[![License: Unlicense](https://img.shields.io/badge/license-Unlicense-blue.svg)](http://unlicense.org/) ![Static Badge](https://img.shields.io/badge/Lit-Based-%20)
## Features
* Modern C++ (20)
* Provides single-function-calls to render various graphics primitives in 2D and 3D.
* Integrates directly with our other toolkits (ReWindow, J3ML)
* Quick Rendering of Debug Text, Geometric Widgets, Textures, and so forth.
* Little-to-no overhead.
* Modern C++ (20).
* Cross Platform (Linux & Windows 10 1909 or newer).
* Provides single-function-calls to render various graphics in 2D and 3D.
* Integrates right into an existing OpenGL rendering system.
* Quick Rendering of Text, Shapes, Sprites / Textures, etc.
* High-performance text rendering.
* Little-to-no overhead.
## API Overview
### J2D
* DrawPoint
* DrawLine / DrawGradientLine
* DrawSprite
* DrawSprite / DrawPartialSprite
* OutlineRect / FillRect / FillGradientRect / FillRoundedRect
* OutlineCircle / FillCircle
* OutlineTriangle / FillTriangle
* DrawString
### J3D
* DrawLine
* DrawString
@@ -33,27 +34,44 @@ Yet Another C++ Rendering Toolkit
* DrawQuaternionGizmo (WIP)
### Types
* RenderTarget
* VRamList
* Texture
* Font
* Sprite
* Color4/Color3
* Gradient
## Usage
```cpp
// Makes sure the glViewport will be the correct size.
// Typically done once per frame.
JGL::Update(window_size);
Install instructions and code samples coming soon :tm: !
JGL::J2D::Begin();
JGL::J2D::FillRect(Colors::Blue, {0,0}, {16,16});
JGL::J2D::End();
// See the example program in main.cpp for more in-depth usage.
```
## Requirements
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
* AMD ✓
* NVIDIA ✓
* Intel ✓
* Zink (OpenGL-on-Vulkan) ✓
* GL4ES ✓
## Documentation
Documentation is (sic: will be) automatically generated from latest commit and is hosted at https://doc.redacted.cc/jgl .
Documentation is available [here](https://doc.redacted.cc/JGL/d3/dcc/md__r_e_a_d_m_e.html).
## Contributing
Contributions to JGL are welcome! If you find a bug, have a feature request, or would like to contribute code, please submit an issue or pull request to our repository!
## License
JGL is licensed under the Public Domain. See the LICENSE file for details.
## Acknowledgements
JGL is developed and maintained by Josh O'Leary @ Co from Redacted Software and contributors. Special thanks to Redacted.

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -7,7 +7,7 @@
/// @file JGL.h
/// @desc All JGL usable functions are defined here. This is the public API.
/// @edit 2024-07-16
/// @edit 2024-10-24
#pragma once
@@ -26,6 +26,8 @@
#include <J3ML/Geometry/Sphere.hpp>
#include <J3ML/Geometry/Capsule.hpp>
#include <J3ML/Geometry/Triangle2D.hpp>
#include <J3ML/J3ML.hpp>
#include <JGL/types/Font.h>
/// OpenGL Wrapper for rendering 2D & 3D graphics in both a 2D and 3D context.
namespace JGL {
@@ -33,316 +35,634 @@ namespace JGL {
using namespace J3ML::Geometry;
[[nodiscard]] bool Init(const Vector2& window_size, float fovY, float far_plane);
/// @param window_size
void Update(const Vector2& window_size);
inline void PurgeFontCache() { JGL::fontCache.purgeCache(); }
std::array<GLfloat, 16> OpenGLPerspectiveProjectionRH(float fovY, float aspect, float z_near, float z_far);
/// Returns true if the graphics driver meets the requirements (GL Version & Extensions).
bool MeetsRequirements();
/// Drawing functions for primitive 2D Shapes.
namespace J2D {
/// Open a 2-D rendering context with the underlying graphics system (In this case& by default OpenGL).
/// @note This call may not strictly be necessary on some setups, but is provided to keep the API constant.
/// It is recommended to always open a JGL 2D context to render your content, then close when completed.
/// This keeps our code from, say, clobbering the OpenGL rendering context driving 3D content in between our calls.
/// @param render_target
/// @param clear_buffers
void Begin(RenderTarget* render_target = nullptr, bool clear_buffers = false);
/// Closes a 2-D rendering context with the underlying graphics system (In this case& by default OpenGL).
/// @see Begin().
void End();
/// Provide a list of lights to be used in 2D space. Typically directly after J2D::Begin();
/// 8 lights maximum for now. Some kind of light sorting will eventually be needed per j2d element.
void LightArray(Light*, size_t size);
void LightArray(std::vector<Light> lights);
}
/// Plots a single pixel on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param coordinates The pixel-point on-screen at which to plot the pixel.
/// @param radius The size of the point to plot. By default, a single pixel.
void DrawPoint(const Color4& color, const Vector2& coordinates, float radius = 1.f);
void DrawPoint(const Color4& color, float x, float y, float radius = 1.f);
namespace JGL::J2D {
/// Open a 2-D rendering context with the underlying graphics system (In this case& by default OpenGL).
/// @note This call may not strictly be necessary on some setups, but is provided to keep the API constant.
/// It is recommended to always open a JGL 2D context to render your content, then close when completed.
/// This keeps our code from, say, clobbering the OpenGL rendering context driving 3D content in between our calls.
/// @param render_target
/// @param clear_buffers
void Begin(RenderTarget* render_target = nullptr, bool clear_buffers = false);
/// Plots a series of pixel-points on the screen, in a batch.
/// @note This is more performant for multiple points than plotting them individually.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param points A set of x,y points to render.
/// @param radius The size of the point to plot. By default, a single pixel.
void DrawPoints(const Color4& color, const Vector2* points, int num_points, float radius = 1.f);
/// Closes a 2-D rendering context with the underlying graphics system (In this case& by default OpenGL).
/// @see Begin().
void End();
/// Plots a line (segment) on the screen.
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4.
/// @param A The starting point of the line segment.
/// @param B The end point of the line segment.
/// @param thickness The width at which to render the line.
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);
/// Provide a list of lights to be used in 2D space. Typically directly after J2D::Begin();
/// 8 lights maximum for now. Some kind of light sorting will eventually be needed per j2d element.
void LightArray(LightBase*, size_t light_count);
/// Draws a line with a color gradient that transitions across it.
/// @param color_a A 3-or-4 channel color value. @see class Color3, class Color4
/// @param color_b A 3-or-4 channel color value. @see class Color3, class Color4
/// @param A The starting point of the line segment.
/// @param B The end point of the line segment.
/// @param thickness The width at which to render the line.
void DrawGradientLine(const Color4& color_a, const Color4& color_b, const Vector2& A, const Vector2& B, float thickness = 1);
void DrawGradientLine(const Color4& color_a, const Color4& color_b, float x, float y, float w, float h, float thickness = 1);
/// Plots a single pixel on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param coordinates The pixel-point on-screen at which to plot the pixel.
/// @param radius The size of the point to plot. By default, a single pixel.
void DrawPoint(const Color4& color, const Vector2& coordinates, float radius = 1.f);
void DrawPoint(const Color4& color, float x, float y, float radius = 1.f);
/// Draws an outline of a rectangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param thickness The width at which to render the lines.
void OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness = 1);
/// Plots a series of pixel-points on the screen, in a batch.
/// @note This is more performant for multiple points than plotting them individually.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param points A set of x,y points to render.
/// @param radius The size of the point to plot. By default, a single pixel.
void DrawPoints(const Color4& color, const Vector2* points, int point_count, float radius = 1.f);
/// Draws an outline of a rectangle with rounded corners onto the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
/// @param thickness The width at which to render the lines.
void OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, float thickness = 1);
/// Plots a line (segment) on the screen.
/// @param color A 3-or-4 channel color value. @see classes Color3, Color4.
/// @param A The starting point of the line segment.
/// @param B The end point of the line segment.
/// @param thickness The width at which to render the line.
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);
/// Draws an outline of a rectangle with chamfered corners onto the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
/// @param thickness The width at which to render the lines.
void OutlineChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, 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.
/// @param B The end point of the line segment.
/// @param spacing The distance between each point (px)
/// @param thickness The width at which to render the line.
/// @note With diagonal lines, the distance between points can differ by one px.
void DrawDottedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing = 1.f, float thickness = 1.f);
void DrawDottedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing = 1.f, float thickness = 1.f);
/// Draws a filled rectangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @see FillRoundedRect, FillGradientRect, FillChamferRect.
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
/// 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.
/// @param B The end point of the line segment.
/// @param spacing The distance between each point (px)
/// @param dash_length The length of each dash making up the line.
/// @param thickness The width at which to render the line.
/// @note With diagonal lines, the distance between dashes can differ by one px.
void DrawDashedLine(const Color4& color, const Vector2& A, const Vector2& B, float spacing = 4.f, float dash_length = 6.f, float thickness = 1.f);
void DrawDashedLine(const Color4& color, float x1, float y1, float x2, float y2, float spacing = 4.f, float dash_length = 6.f, float thickness = 1.f);
/// Draws a filled rectangle where the color transitions across it.
/// @param color1 A 3-or-4 channel color value. @see class Color3, class Color4
/// @param color2 A 3-or-4 channel color value. @see class Color3, class Color4
/// @param gradient See enum Direction
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
void FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size);
/// Draws a line with a color gradient that transitions across it.
/// @param color_a A 3-or-4 channel color value. @see class Color3, class Color4
/// @param color_b A 3-or-4 channel color value. @see class Color3, class Color4
/// @param A The starting point of the line segment.
/// @param B The end point of the line segment.
/// @param thickness The width at which to render the line.
void DrawGradientLine(const Color4& color_a, const Color4& color_b, const Vector2& A, const Vector2& B, float thickness = 1);
void DrawGradientLine(const Color4& color_a, const Color4& color_b, float x1, float y1, float x2, float y2, float thickness = 1);
/// Draws a filled rectangle with rounded corners on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
/// @param subdivisions The amount of sub-divisions (and calculations) to be performed per-arc rounding corner.
void FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, unsigned int subdivisions = 8);
/// Draws an outline of a rectangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param thickness The width at which to render the lines.
void OutlineRect(const Color4& color, const Vector2& pos, const Vector2& size, float thickness = 1);
/// Draws a filled rectangle with chamfered (beveled) corners on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
void FillChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5);
/// Draws an outline of a rectangle with rounded corners onto the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
/// @param thickness The width at which to render the lines.
void OutlineRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, float thickness = 1);
/// Draws an outline of a rectangle with chamfered corners onto the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
/// @param thickness The width at which to render the lines.
void OutlineChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, float thickness = 1);
/// Draws a filled rectangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @see FillRoundedRect, FillGradientRect, FillChamferRect.
void FillRect(const Color4& color, const Vector2& pos, const Vector2& size);
/// Draws a filled rectangle where the color transitions across it.
/// @param color1 A 3-or-4 channel color value. @see class Color3, class Color4
/// @param color2 A 3-or-4 channel color value. @see class Color3, class Color4
/// @param gradient See enum Direction
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
void FillGradientRect(const Color4& color1, const Color4& color2, const Direction& gradient, const Vector2& pos, const Vector2& size);
/// Draws a filled rectangle with rounded corners on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
/// @param subdivisions The amount of sub-divisions (and calculations) to be performed per-arc rounding corner.
void FillRoundedRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5, unsigned int subdivisions = 8);
/// Draws a filled rectangle with chamfered (beveled) corners on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The top-left corner of the rectangle.
/// @param size The width and height of the rectangle.
/// @param radius The corner-rounding radius (in radians).
void FillChamferRect(const Color4& color, const Vector2& pos, const Vector2& size, float radius = 5);
/// Draws a render-target (runtime-modifiable texture) to the screen.
/// @param render_target A RenderTarget instance to be displayed.
/// @param position The position at which to render this object from it's center-point, defined by the origin parameter.
/// @param rad_rotation The amount of radians to rotate this render-target about it's center-point.
/// @param origin The center-point in the image to use for rendering, rotation, and scaling. Top-left is {0,0} and bottom right is {1, 1}.
/// @param scale The amount (in both x, and y axis) to scale the image, with {1,1} being default scaling.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
void DrawRenderTarget(const RenderTarget& render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawRenderTarget(const RenderTarget* render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialRenderTarget(const RenderTarget&, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation = 0,
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialRenderTarget(const RenderTarget*, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation = 0,
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a sprite (technically, actually a render target) to the screen.
/// @note This similar overload exists because we expect someone will be an idiot and turn all of their sprites into RenderTargets. ~william
/// @param render_target A RenderTarget instance to be displayed.
/// @param position The position at which to render this object from it's center-point, defined by the origin parameter.
/// @param rad_rotation The amount of radians to rotate this render-target about it's center-point.
/// @param origin The center-point in the image to use for rendering, rotation, and scaling. Top-left is {0,0} and bottom right is {1, 1}.
/// @param scale The amount (in both x, and y axis) to scale the image, with {1,1} being default scaling.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
/// @see DrawSprite
void DrawSprite(const RenderTarget& render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const RenderTarget* render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a sprite to the screen by passing a G̶L̶u̶i̶n̶t̶ JGL Texture that represents a handle to a loaded texture.
/// @param texture A texture instance to be displayed.
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param origin The center point around which the image should have all transformations applied to it.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param rad_rotation A float representing the rotation of the sprite where 0 is no rotation and 1 is the maximum rotation (would look the same as 0).
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
/// @see class Texture
void DrawSprite(const Texture& texture, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture& texture, float positionX, float positionY, float rad_rotation = 0, float originX = 0, float originY = 0,
float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, float positionX, float positionY, float rad_rotation = 0,
float originX = 0, float originY = 0,float scaleX = 1, float scaleY = 1,
const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a sprite to the screen by passing a G̶L̶u̶i̶n̶t̶ JGL Texture that represents a handle to a loaded texture.
/// @param texture A texture instance to be displayed.
/// @param alpha_mask A texture which determines how much of the sprite you can see. Grayscale image exported as "8bpc RGBA".
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param origin The center point around which the image should have all transformations applied to it.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param rad_rotation A float representing the rotation of the sprite where 0 is no rotation and 1 is the maximum rotation (would look the same as 0).
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
/// @see class Texture
void DrawSprite(const Texture& texture, const Texture& alpha_mask, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, const Texture* alpha_mask, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture& texture, const Texture& alpha_mask, float positionX, float positionY, float rad_rotation = 0, float originX = 0, float originY = 0,
float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, const Texture* alpha_mask, float positionX, float positionY, float rad_rotation = 0, float originX = 0, float originY = 0,
float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a render-target (runtime-modifiable texture) to the screen.
/// @param render_target A RenderTarget instance to be displayed.
/// @param position The position at which to render this object from it's center-point, defined by the origin parameter.
/// @param rad_rotation The amount of radians to rotate this render-target about it's center-point.
/// @param origin The center-point in the image to use for rendering, rotation, and scaling. Top-left is {0,0} and bottom right is {1, 1}.
/// @param scale The amount (in both x, and y axis) to scale the image, with {1,1} being default scaling.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
void DrawRenderTarget(const RenderTarget& render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawRenderTarget(const RenderTarget* render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a piece of a sprite to the screen, similar to DrawSprite.
/// @param texture A texture instance to be displayed.
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param sub_texture_position The top left corner of the sub-texture to be drawn.
/// @param sub_texture_size The size of the sub-texture in px.
/// @param origin The center point around which the image should have all transformations applied to it.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
void DrawPartialSprite(const Texture& texture, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation = 0,
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialSprite(const Texture* texture, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation = 0,
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialSprite(const Texture& texture, float positionX, float positionY, float sub_texture_positionX, float sub_texture_positionY, unsigned int sub_texture_sizeX, unsigned int sub_texture_sizeY,
float rad_rotation = 0, float originX = 0, float originY = 0, float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialSprite(const Texture* texture, float positionX, float positionY, float sub_texture_positionX, float sub_texture_positionY, unsigned int sub_texture_sizeX, unsigned int sub_texture_sizeY,
float rad_rotation = 0, float originX = 0, float originY = 0, float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
/// To save v-ram, Use if a sprite would be identical if mirrored horizontally, vertically, or both. For example, a circle.
/// Assumes the input texture is the top left quadrant. You can use "SoftwareTexture" to invert it correctly so that's the case.
/// @param texture A texture instance to be displayed.
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param mirror_axis The axes to mirror across, Vertical and Horizontal or both only.
/// @param rad_rotation The rotation of the final result.
/// @param origin The point at which transformations are done about.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
void DrawMirrorSprite(const Texture& texture, const Vector2& position, Direction mirror_axis = Direction::Horizontal | Direction::Vertical, float rad_rotation = 0, const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White);
void DrawMirrorSprite(const Texture* texture, const Vector2& position, Direction mirror_axis = Direction::Horizontal | Direction::Vertical, float rad_rotation = 0, const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White);
/// Draws an outline of a circle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param center The point in cartesian space at which to draw the circle. This will by-definition be the centroid of this circle.
/// @param radius The radius of the circle to be drawn. AKA Half the diameter.
/// @param subdivisions The accuracy of the approximation of the circle, measured in iteration steps taken.
/// @param thickness The line-width of the circle to be rendered at.
void OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions = 16, float thickness = 1);
/// Draws a filled circle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param center The point in cartesian space at which to draw the circle. This will by-definition be the centroid of this circle.
/// @param radius The radius of the circle to be drawn. AKA Half the diameter.
/// @param subdivisions The accuracy of the approximation of the circle, measured in iteration steps taken.
void FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions = 8);
/// Draws an outline of a triangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param tri The triangle defined by its vertices (A, B, and C).
/// @param thickness The line-width of the triangle to be rendered at.
void OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness = 1);
void OutlineTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC, float thickness = 1);
/// Draws a filled triangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param tri The triangle defined by its vertices (A, B, and C).
void FillTriangle(const Color4& color, const Triangle2D& tri);
void FIllTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC);
/// Fills a triangle defined by the provided vertices with a gradient that transitions smoothly between the three specified colors at each corner.
/// @param a_color The color at vertex A of the triangle.
/// @param b_color The color at vertex B of the triangle.
/// @param c_color The color at vertex C of the triangle.
/// @param tri The triangle defined by its vertices (A, B, and C).
void FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Triangle2D& tri);
void 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);
/// Draws a smooth, curved line segment between two control points, with the curve controlled by the two inner points.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param controlA The first control point, which can be considered the start of the line.
/// @param pointA The first inner point, which controls the contour of the curve.
/// @param pointB The second inner point, which controls the contour of the curve.
/// @param controlB The second control point, which can be considered the end of the line.
/// @param subdivisions The accuracy of the approximation of the curve, measured in iteration steps taken.
/// @param thickness The line-width to draw the curve with.
/// @see J3ML::Algorithm::Bezier
void DrawCubicBezierCurve(const Color4& color, const Vector2& controlA, const Vector2& pointA, const Vector2& pointB, const Vector2& controlB,
int subdivisions = 10, float thickness = 1);
/// Draws a series of points where the last point always connects to the first point.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param points The array of vector2's to draw as a polygon.
/// @param point_count The number of points
/// @param thickness The line-width of the polygon
void OutlinePolygon(const Color4& color, const Vector2* points, int point_count, float thickness = 1);
/// Draws a text string on the screen with a given point-size and font.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param text The text to be rendered.
/// @param x The position on the screen at which to draw the text, from the top-left.
/// @param y The position on the screen at which to draw the text, from the top-left.
/// @param scale The value (in both axes) to scale the text by. Defaults to {1,1}.
/// @param size The point-size at which to render the font out. Re-using the same point-size allows efficient glyph caching.
/// @param font The font to use for rendering. @see Font.
void DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font);
/// Draws a sprite (technically, actually a render target) to the screen.
/// @note This similar overload exists because we expect someone will be an idiot and turn all of their sprites into RenderTargets. ~william
/// @param render_target A RenderTarget instance to be displayed.
/// @param position The position at which to render this object from it's center-point, defined by the origin parameter.
/// @param rad_rotation The amount of radians to rotate this render-target about it's center-point.
/// @param origin The center-point in the image to use for rendering, rotation, and scaling. Top-left is {0,0} and bottom right is {1, 1}.
/// @param scale The amount (in both x, and y axis) to scale the image, with {1,1} being default scaling.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
/// @see DrawSprite
void DrawSprite(const RenderTarget& render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const RenderTarget* render_target, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0 , 0),
const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws an Arc (section of a circle) to the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param center The point in cartesian space at which to draw the arc. This will by-definition be the centroid of this partial circle.
/// @param radius The radius of the partial circle to be drawn. AKA Half the diameter.
/// @param arc_begin The point (0 - 2pi) around a unit-circle of which to start the arc.
/// @param arc_end The point (0 - 2pi) around a unit-circle of which to start the arc.
/// @param subdivisions The accuracy of the approximation of the circle, measured in iteration steps taken.
/// @param thickness The line-width to draw the arc with.
void DrawArc(const Color4& color, const Vector2& center, float radius, float arc_begin, float arc_end,
unsigned int subdivisions, float thickness);
/// Draws a sprite to the screen by passing a G̶L̶u̶i̶n̶t̶ JGL Texture that represents a handle to a loaded texture.
/// @param texture A texture instance to be displayed.
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param origin The center point around which the image should have all transformations applied to it.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param rad_rotation A float representing the rotation of the sprite where 0 is no rotation and 1 is the maximum rotation (would look the same as 0).
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
/// @see class Texture
void DrawSprite(const Texture& texture, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, const Vector2& position, float rad_rotation = 0, const Vector2& origin = Vector2(0,0),
const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture& texture, float positionX, float positionY, float rad_rotation = 0, float originX = 0, float originY = 0,
float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawSprite(const Texture* texture, float positionX, float positionY, float rad_rotation = 0,
float originX = 0, float originY = 0,float scaleX = 1, float scaleY = 1,
const Color4& color = Colors::White, Direction inversion = Direction::None);
/// Draws a piece of a sprite to the screen, similar to DrawSprite.
/// @param texture A texture instance to be displayed.
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param sub_texture_position The top left corner of the sub-texture to be drawn.
/// @param sub_texture_size The size of the sub-texture in px.
/// @param origin The center point around which the image should have all transformations applied to it.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param inversion @see Direction
void DrawPartialSprite(const Texture& texture, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation = 0,
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialSprite(const Texture* texture, const Vector2& position, const Vector2& sub_texture_position, const Vector2& sub_texture_size, float rad_rotation = 0,
const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1, 1), const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialSprite(const Texture& texture, float positionX, float positionY, float sub_texture_positionX, float sub_texture_positionY, unsigned int sub_texture_sizeX, unsigned int sub_texture_sizeY,
float rad_rotation = 0, float originX = 0, float originY = 0, float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
void DrawPartialSprite(const Texture* texture, float positionX, float positionY, float sub_texture_positionX, float sub_texture_positionY, unsigned int sub_texture_sizeX, unsigned int sub_texture_sizeY,
float rad_rotation = 0, float originX = 0, float originY = 0, float scaleX = 1, float scaleY = 1, const Color4& color = Colors::White, Direction inversion = Direction::None);
/// TODO Implement the following. These ones are going to be extremely annoying.
void FillPolygon(const Color4& color, const std::vector<Vector2>& points);
void OutlineEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, float thickness = 1, int subdivisions = 8);
void FillEllipse(const Color4& color, const Vector2& position, float radius_x, float radius_y, int subdivisions = 8);
}
/// To save v-ram, Use if a sprite would be identical if mirrored horizontally, vertically, or both. For example, a circle.
/// Assumes the input texture is the top left quadrant. You can use "SoftwareTexture" to invert it correctly so that's the case.
/// @param texture A texture instance to be displayed.
/// @param position The point at which to draw the sprite (from the top-left down).
/// @param mirror_axis The axes to mirror across, Vertical and Horizontal or both only.
/// @param rad_rotation The rotation of the final result.
/// @param origin The point at which transformations are done about.
/// @param scale The scale transformation for the image. X and Y axis are independently-scalable.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
void DrawMirrorSprite(const Texture& texture, const Vector2& position, Direction mirror_axis = Direction::Horizontal | Direction::Vertical, float rad_rotation = 0, const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White);
void DrawMirrorSprite(const Texture* texture, const Vector2& position, Direction mirror_axis = Direction::Horizontal | Direction::Vertical, float rad_rotation = 0, const Vector2& origin = Vector2(0,0), const Vector2& scale = Vector2(1,1), const Color4& color = Colors::White);
/// Drawing functions for primitive 3D Shapes.
namespace JGL::J3D {
/// A light for this 3D render that should never be culled out. up-to 8.
/// The more you put here, The less we will solve for if you're also using LightArray.
/// @note More than 8 lights will cause an error to be printed.
void RequiredLight(const LightBase* light);
/// Draws an outline of a circle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param center The point in cartesian space at which to draw the circle. This will by-definition be the centroid of this circle.
/// @param radius The radius of the circle to be drawn. AKA Half the diameter.
/// @param subdivisions The accuracy of the approximation of the circle, measured in iteration steps taken.
/// @param thickness The line-width of the circle to be rendered at.
void OutlineCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions = 16, float thickness = 1);
/// When each 3D object is drawn, We'll do our best to determine which lights would effect it the most and use those ones.
void LightArray(const LightBase** lights, const size_t& light_count);
/// Draws a filled circle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param center The point in cartesian space at which to draw the circle. This will by-definition be the centroid of this circle.
/// @param radius The radius of the circle to be drawn. AKA Half the diameter.
/// @param subdivisions The accuracy of the approximation of the circle, measured in iteration steps taken.
void FillCircle(const Color4& color, const Vector2& center, float radius, unsigned int subdivisions = 8);
/// Helper function to conveniently change the Field-Of-View.
void ChangeFOV(float fov);
/// Draws an outline of a triangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param tri The triangle structure / set of 3 points in cartesian space used to draw the triangle.
/// @param thickness The line-width of the triangle to be rendered at.
void OutlineTriangle(const Color4& color, const Triangle2D& tri, float thickness = 1);
void OutlineTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC, float thickness = 1);
/// Helper function to change the far-plane, which is the cutoff distance for rendering.
void ChangeFarPlane(float far_plane);
/// Draws a filled triangle on the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param tri The triangle structure / set of 3 points in cartesian space used to draw the triangle.
void FillTriangle(const Color4& color, const Triangle2D& tri);
void FIllTriangle(const Color4& color, const Vector2& triA, const Vector2& triB, const Vector2& triC);
/// Open a 3-D rendering context with the underlying graphics system (In this case& by default OpenGL).
/// @note This call may not strictly be necessary on some setups, but is provided to keep the API constant.
/// It is recommended to always open a JGL 3D context to render your content, then close when completed.
/// This keeps our code from, say, clobbering the OpenGL rendering context driving 2D content in between our calls.
void Begin();
/// Draws a triangle where each corner is defined by a given color, Smoothly transitioning between them.
/// @param a_color
/// @param b_color
/// @param c_color
/// @param tri
void FillGradientTriangle(const Color4& a_color, const Color4& b_color, const Color4& c_color, const Triangle2D& tri);
/// Closes a 3-D rendering context with the underlying graphics system (In this case& by default OpenGL).
/// @see Begin().
void End();
/// Draws a smooth, curved line segment between two control points, with the curve controlled by the two inner points.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param controlA The first control point, which can be considered the start of the line.
/// @param pointA The first inner point, which controls the contour of the curve.
/// @param pointB The second inner point, which controls the contour of the curve.
/// @param controlB The second control point, which can be considered the end of the line.
/// @see J3ML::Algorithm::Bezier
void DrawCubicBezierCurve(const Color4& color, const Vector2& controlA, const Vector2& pointA, const Vector2& pointB, const Vector2& controlB,
void SetMatrix(const std::vector<GLfloat>& matrix, const Vector2& window_size);
/// Draws a line in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param A The start-point of the line segment.
/// @param B The end-point of the line segment.
/// @param thickness The line-width to draw the line segment with.
void DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness = 1.f);
/// Draws a smooth, curved line segment between two control points, with the curve controlled by the two inner points.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param controlA The first control point, which can be considered the start of the line.
/// @param pointA The first inner point, which controls the contour of the curve.
/// @param pointB The second inner point, which controls the contour of the curve.
/// @param controlB The second control point, which can be considered the end of the line.
/// @param subdivisions The accuracy of the approximation of the curve, measured in iteration steps taken.
/// @param thickness The line-width to draw the curve with.
/// @see J3ML::Algorithm::Bezier
void DrawCubicBezierCurve(const Color4& color, const Vector3& controlA, const Vector3& pointA, const Vector3& pointB, const Vector3& controlB,
int subdivisions = 10, float thickness = 1);
/// Draws the outline of an Icosahedron in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Icosahedron.
/// @param radius The size to draw the Icosahedron at.
/// @param thickness The line-width to draw the Icosahedron outline with.
void WireframeIcosahedron(const Color4& color, const Vector3& position, float radius, float thickness = 1.f);
// TODO: Implement OutlinePolygon overload which takes a std::vector of points as well.
/// Draws a solid Icosahedron in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Icosahedron.
/// @param radius The size to draw the Icosahedron at.
void FillIcosahedron(const Color4& color, const Vector3& position, float radius);
/// Draws a series of points where the last point always connects to the first point.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param points The array of vector2's to draw as a polygon.
/// @param points_size The length of the array of vector2's.
/// @param thickness The line-width of the polygon
void OutlinePolygon(const Color4& color, const Vector2* points, int points_size, float thickness = 1);
/// Draws the outline of a Sphere in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Sphere.
/// @param radius The size to draw the Sphere at.
/// @param thickness The line-width to draw the Icosahedron outline with.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param stacks The amount of longitudinal subdivisions to perform when computing the sphere.
void WireframeSphere(const Color4& color, const Vector3& position, float radius, float thickness = 1.f, unsigned int sectors = 10, unsigned int stacks = 10);
/// Draws a text string on the screen with a given point-size and font.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param text The text to be rendered.
/// @param x The position on the screen at which to draw the text, from the top-left.
/// @param y The position on the screen at which to draw the text, from the top-left.
/// @param scale The value (in both axes) to scale the text by. Defaults to {1,1}.
/// @param size The point-size at which to render the font out. Re-using the same point-size allows efficient glyph caching.
/// @param font The font to use for rendering. @see Font.
void DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font);
/// Draws the outline of a Sphere in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param sphere The mathematically-defined sphere object to be rendered.
/// @param thickness The line-width to draw the Icosahedron outline with.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param stacks The amount of longitudinal subdivisions to perform when computing the sphere.
void WireframeSphere(const Color4& color, const Sphere& sphere, float thickness = 1.f, unsigned int sectors = 10, unsigned int stacks = 10);
/// Draws outlines of multiple spheres in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param spheres The mathematically-defined sphere objects to be rendered.
/// @param sphere_count The number of spheres.
/// @param thickness The line-width to draw the Icosahedron outline with.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param stacks The amount of longitudinal subdivisions to perform when computing the sphere.
/// @note The "Position" of the spheres is expected to be in world space.
void BatchWireframeSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness = 1.f, unsigned int sectors = 10, unsigned int stacks = 10);
/// Draws an Arc (section of a circle) to the screen.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param center The point in cartesian space at which to draw the arc. This will by-definition be the centroid of this partial circle.
/// @param radius The radius of the partial circle to be drawn. AKA Half the diameter.
/// @param arc_begin The point (0 - 2pi) around a unit-circle of which to start the arc.
/// @param arc_end The point (0 - 2pi) around a unit-circle of which to start the arc.
/// @param subdivisions The accuracy of the approximation of the circle, measured in iteration steps taken.
/// @param thickness The line-width to draw the arc with.
void DrawArc(const Color4& color, const Vector2& center, float radius, float arc_begin, float arc_end,
unsigned int subdivisions, float thickness);
/// Draws outlines of a sphere in 3D space. Calculates a cross section and revolves it around the center.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Sphere.
/// @param radius The size to draw the Sphere at.
/// @param thickness The line-width to draw the Icosahedron outline with.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param revolutions The number of times to revolve the cross section about the center.
/// @param draw_stacks Whether or not to draw the stacks of the sphere.
void WireframeRevoSphere(const Color4& color, const Vector3& position, float radius, float thickness = 1.f, unsigned int sectors = 10, unsigned int revolutions = 10, bool draw_stacks = false);
/// Draws the outline of a Sphere in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param sphere The mathematically-defined sphere object to be rendered.
/// @param thickness The line-width to draw the Icosahedron outline with.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param revolutions The number of times to revolve the cross section about the center.
/// @param draw_stacks Whether or not to draw the stacks of the sphere.
void WireframeRevoSphere(const Color4& color, const Sphere& sphere, float thickness = 1.f, unsigned int sectors = 10, unsigned int revolutions = 10, bool draw_stacks = false);
/// TODO Implement the following. These ones are going to be extremely annoying.
void FillPolygon(const Color4& color, const std::vector<Vector2>& points);
void FillTexturedPolygon();
void FillTexturedTriangle();
}
/// Draws outlines of multiple spheres in 3D space. Calculates a cross section and revolves it around the center.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param spheres The mathematically-defined sphere objects to be rendered.
/// @param sphere_count The number of spheres.
/// @param thickness The line-width to draw the Icosahedron outline with.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param revolutions The number of times to revolve the cross section about the center.
/// @param draw_stacks Whether or not to draw the stacks of the sphere.
/// @note The "Position" of the spheres is expected to be in world space.
/// @note This method of drawing a sphere is *probably* the fastest out of all of them.
void BatchWireframeRevoSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, float thickness = 1.f, unsigned int sectors = 10, unsigned int revolutions = 10, bool draw_stacks = false);
/// Drawing functions for primitive 3D Shapes.
namespace J3D {
void Init(const Vector2& window_size, float fov, float far_plane);
void ChangeFOV(float fov);
void ChangeFarPlane(float far_plane);
void Begin();
void End();
void SetMatrix(const std::vector<GLfloat>& matrix, const Vector2& window_size);
void DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness = 1);
void FillSphere(const Color3& color, const Sphere& sphere);
void WireframeSphere(const Color3& color, const Sphere& sphere, float thickness = 1);
void FillOBB(const Color3& color, const OBB& obb);
void WireframeOBB(const Color3& color, const OBB& obb, float thickness = 1);
void FillCapsule(const Color3& color, const Capsule& capsule);
void WireframeCapsule(const Color3& color, const Capsule& cap, float thickness = 1);
void FillTriangleMesh(const Color3& color, const TriangleMesh& mesh);
void WireframeTriangleMesh(const Color3& color, const TriangleMesh& mesh, float thickness = 1);
/// Draws the outline of an Icosphere in 3D space.
/// @note An Icosphere is an approximation of a sphere that is generated by recursively subdividing an Icosahedron.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Sphere.
/// @param radius The size to draw the Sphere at.
/// @param thickness The line-width to draw the Icosahedron outline with.
/// @param subdivisions The accuracy of the approximation of the Icosphere, measured in iteration steps taken.
void WireframeIcosphere(const Color4& color, const Vector3& position, float radius, float thickness = 1.f, unsigned int subdivisions = 10);
/// Draws a string of text in 3D space, with an arbitrary rotation.
/// @param color
/// @param text
/// @param pos
/// @param scale
/// @param size
/// @param font
/// @param angle
/// @param draw_back_face
void DrawString(const Color4& color, const std::string& text, const Vector3& pos, float scale, u32 size, const Font& font, const EulerAngle& angle = {0, 0, 0}, bool draw_back_face = false);
/// Draws the outline of an Icosphere in 3D space.
/// @note An Icosphere is an approximation of a sphere that is generated by recursively subdividing an Icosahedron.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param sphere The mathematically-defined sphere object to be rendered.
/// @param thickness The line-width to draw the Icosphere outline with.
/// @param subdivisions The accuracy of the approximation of the Icosphere, measured in iteration steps taken.
void WireframeIcosphere(const Color4& color, const Sphere& sphere, float thickness = 1.f, unsigned int subdivisions = 10);
/// Draws a string of text in 3D space that is always facing the exact direction of the camera projection.
void DrawBillboardString();
/// Draws the outline of a Cubesphere in 3D space.
/// @note A Cubesphere is an approximation of a sphere that is generated by recursively subdividing a Cube.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Sphere.
/// @param radius The size to draw the Sphere at.
/// @param thickness The line-width to draw the Cubesphere outline with.
/// @param subdivisions The accuracy of the approximation of the Cubesphere, measured in iteration steps taken.
void WireframeCubesphere(const Color4& color, const Vector3& position, float radius, float thickness = 1.f, unsigned int subdivisions = 10);
/// Draws a texture sprite in 3D space that is always facing the exact direction of the camera projection.
void DrawBillboardSprite();
/// Draws the outline of a Cubesphere in 3D space.
/// @note A Cubesphere is an approximation of a sphere that is generated by recursively subdividing a Cube.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param sphere The mathematically-defined sphere object to be rendered.
/// @param thickness The line-width to draw the Cubesphere outline with.
/// @param subdivisions The accuracy of the approximation of the Cubesphere, measured in iteration steps taken.
void WireframeCubesphere(const Color4& color, const Sphere& sphere, float thickness = 1.f, unsigned int subdivisions = 10);
void DrawSprite();
void DrawMatrixGizmo (const Matrix3x3&, const Vector3&);
void DrawMatrixGizmo (const Matrix4x4&);
void DrawAxisAngleGizmo (const AxisAngle&, const Vector3&);
void DrawQuaternionGizmo (const Quaternion&, const Vector3&);
}
/// Draws a solid Sphere in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Sphere.
/// @param radius The size to draw the Sphere at.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param stacks The amount of longitudinal subdivisions to perform when computing the sphere.
void FillSphere(const Color4& color, const Vector3& position, float radius, unsigned int sectors = 10, unsigned int stacks = 10);
/// Draws a solid Sphere in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param sphere The mathematically-defined sphere object to be rendered.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param stacks The amount of longitudinal subdivisions to perform when computing the sphere.
void FillSphere(const Color4& color, const Sphere& sphere, unsigned int sectors = 10, unsigned int stacks = 10);
/// Draws multiple solid Spheres in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param spheres The mathematically-defined sphere objects to be rendered.
/// @param sphere_count The number of spheres to be rendered.
/// @param sectors The amount of latitudinal subdivisions to perform when computing the sphere.
/// @param stacks The amount of longitudinal subdivisions to perform when computing the sphere.
void BatchFillSphere(const Color4& color, const Sphere* spheres, const size_t& sphere_count, unsigned int sectors = 10, unsigned int stacks = 10);
/// Draws a solid Icosphere in 3D space.
/// @note An Icosphere is an approximation of a sphere that is generated by recursively subdividing an Icosahedron.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Sphere.
/// @param radius The size to draw the Sphere at.
/// @param subdivisions The accuracy of the approximation of the Cubesphere, measured in iteration steps taken.
void FillIcosphere(const Color4& color, const Vector3& position, float radius, unsigned int subdivisions = 10);
/// Draws a solid Icosphere in 3D space.
/// @note An Icosphere is an approximation of a sphere that is generated by recursively subdividing an Icosahedron.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param sphere The mathematically-defined sphere object to be rendered.
/// @param subdivisions The accuracy of the approximation of the Cubesphere, measured in iteration steps taken.
void FillIcosphere(const Color4& color, const Sphere& sphere, unsigned int subdivisions = 10);
/// Draws a solid Cubesphere in 3D space.
/// @note A Cubesphere is an approximation of a sphere that is generated by recursively subdividing a Cube.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space at which to draw the Sphere.
/// @param radius The size to draw the Sphere at.
/// @param subdivisions The accuracy of the approximation of the Cubesphere, measured in iteration steps taken.
void FillCubesphere(const Color4& color, const Vector3& position, float radius, unsigned int subdivisions = 10);
/// Draws a solid Cubesphere in 3D space.
/// @note A Cubesphere is an approximation of a sphere that is generated by recursively subdividing a Cube.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param sphere The mathematically-defined sphere object to be rendered.
/// @param subdivisions The accuracy of the approximation of the Cubesphere, measured in iteration steps taken.
void FillCubesphere(const Color4& color, const Sphere& sphere, unsigned int subdivisions = 10);
/// Draws an outline of an axis-aligned bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The point in 3D space that is the center of the AABB.
/// @param radii The radii along x,y,z axes to size the bounding box.
/// @param thickness The line-width to draw the Icosphere outline with.
void WireframeAABB(const Color4& color, const Vector3& pos, const Vector3& radii, float thickness = 1.f);
/// Draws an outline of an axis-aligned bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param aabb The AABB object to render.
/// @param thickness The line-width to draw the Icosphere outline with.
void WireframeAABB(const Color4& color, const AABB& aabb, float thickness = 1.f);
/// Draws outlines of multiple axis-aligned bounding-boxes in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param boxes The boxes to be drawn.
/// @param box_count The number of boxes to be drawn.
/// @param thickness The line-width to draw the Icosahedron outline with.
void BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_t& box_count, float thickness = 1.f);
/// Draws a solid axis-aligned bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param pos The point in 3D space that is the center of the AABB.
/// @param radii The radii along x,y,z axes to size the bounding box.
void FillAABB(const Color4& color, const Vector3& pos, const Vector3& radii);
/// Draws a solid axis-aligned bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param aabb The AABB object to visualize.
void FillAABB(const Color4& color, const AABB& aabb);
/// Draws solid axis-aligned bounding boxes in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param aabb The AABB objects to visualize.
/// @param box_count The number of AABBs to draw.
void BatchFillAABB(const Color4& color, const AABB* boxes, const size_t& box_count);
/// Draws an outline of an oriented bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The point in 3D space that is the center of the AABB.
/// @param radii The radii along x,y,z axes to size the bounding box.
/// @param orientation The rotation in 3D space of the OBB.
/// @param thickness The line-width to draw the OBB outline with.
void WireframeOBB(const Color4& color, const Vector3& position, const Vector3& radii, const Matrix3x3& orientation, float thickness = 1.f);
/// Draws an outline of an oriented bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param obb The OBB object to visualize.
/// @param thickness The line-width to draw the OBB outline with.
void WireframeOBB(const Color4& color, const OBB& obb, float thickness = 1.f);
void BatchWireframeOBB(const Color4& color, const OBB* boxes, const size_t& box_count, float thickness = 1.f);
/// Draws a solid oriented bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param position The center-position of the oriented bounding box.
/// @param radii The radii along x,y,z axes to size the bounding box.
/// @param orientation The rotation in 3D space of the OBB.
void FillOBB(const Color4& color, const Vector3& position, const Vector3& radii, const EulerAngleXYZ& orientation);
/// Draws a solid oriented bounding box in 3D space.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param obb The oriented-bounding-box object to visualize.
void FillOBB(const Color4& color, const OBB& obb);
void WireframeCylinder();
void FillCylinder();
void WireframePrism();
void FillPrism();
void WireframePipe();
void FillPipe();
void WireframeCone();
void FillCone();
void WireframeTorus();
void FillTorus();
void FillCapsule(const Color3& color, const Capsule& capsule);
void WireframeCapsule(const Color3& color, const Capsule& cap, float thickness = 1.f);
void FillTriangleMesh(const Color3& color, const TriangleMesh& mesh);
void WireframeTriangleMesh(const Color3& color, const TriangleMesh& mesh, float thickness = 1.f);
/// Draws a string of text in 3D space, with an arbitrary rotation.
/// @param color A 3-or-4 channel color value. @see class Color3, class Color4
/// @param text The content to display on the screen.
/// @param pos The position in 3D space to display the text.
/// @param scale The scaling factor to render the text with, 1 being default. TODO: Vector2 scaling?
/// @param size The pixel size to rasterize the font with.
/// @param font The font object to use when drawing.
/// @param angle The orientation in 3D space.
/// @param draw_back_face
void DrawString(const Color4& color, const std::string& text, const Vector3& pos, float scale, u32 size, const Font& font, const EulerAngleXYZ& angle = {0, 0, 0}, bool draw_back_face = false);
/// Draws a string of text in 3D space that is always facing the exact direction of the camera projection.
void DrawBillboardString();
/// Draws a texture sprite in 3D space that is always facing the exact direction of the camera projection.
void DrawBillboardSprite();
void DrawSprite();
void DrawMatrixGizmo (const Matrix3x3&, const Vector3&);
void DrawMatrixGizmo (const Matrix4x4&);
void DrawAxisAngleGizmo (const AxisAngle&, const Vector3&);
void DrawQuaternionGizmo (const Quaternion&, const Vector3&);
}

9
include/JGL/ShapeCache.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <JGL/types/VRamList.h>
#include <array>
namespace JGL::ShapeCache {
inline VRamList* cube_vertex_data = nullptr;
inline VRamList* cube_index_data = nullptr;
void Init();
}

View File

@@ -14,7 +14,7 @@ extern "C" typedef struct FT_LibraryRec_* FT_Library;
namespace JGL
{
/// Initializes FreeType engine. Remember to call this during program initialization.
//bool Init();
bool InitTextEngine();
/// A Font class implementation.

View File

@@ -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);
};

View File

@@ -40,6 +40,12 @@ public:
/// Blit a render target onto another. Will break if they're not the same size.
static void Blit(const RenderTarget& source, RenderTarget* destination);
/// Blit a single pixel onto a Render Target.
/// @param color The color to render.
/// @param position The position in the destination to draw the pixel.
/// @param destination The destination RenderTarget.
static void Blit(const Color4& color, const Vector2& position, RenderTarget* destination);
[[nodiscard]] bool TextureCreatedByRenderTarget() const;
public:
[[nodiscard]] Vector2 GetDimensions() const;

View 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);
};

View File

@@ -0,0 +1,124 @@
#pragma once
#include <vector>
#include <array>
#include <J3ML/LinearAlgebra/Vector3.hpp>
#include <J3ML/LinearAlgebra/Matrix4x4.hpp>
#include <unordered_map>
namespace JGL {
class Bone;
class SkeletalVertexAttribute;
class Skeleton;
class KeyFrame;
class Animation;
class AnimationState;
}
class JGL::SkeletalVertexAttribute {
private:
std::array<int, 4> bone_ids = { 0, 0, 0, 0 };
std::array<float, 4> bone_weights = { 0, 0, 0, 0 };
public:
[[nodiscard]] std::array<int, 4> GetAffectingBoneIDs() const;
[[nodiscard]] std::array<float, 4> GetAffectingBoneWeights() const;
public:
SkeletalVertexAttribute() = default;
/// These cannpt be longer than 4.
SkeletalVertexAttribute(const std::vector<int>& ids, const std::vector<float>& weights);
};
class JGL::Bone {
private:
int id = 0;
// Not every gltf2 model includes names, but I'll still include it.
std::string name;
Matrix4x4 inverse_bind_matrix = Matrix4x4::Identity;
Matrix4x4 offset_matrix = Matrix4x4::Identity;
Matrix4x4 final_transform = Matrix4x4::Identity;
int parent_id = -1;
std::vector<int> children{};
public:
[[nodiscard]] int GetID() const;
[[nodiscard]] std::string GetName() const;
[[nodiscard]] Matrix4x4 GetInverseBindMatrix() const;
[[nodiscard]] Matrix4x4 GetOffsetMatrix() const;
[[nodiscard]] Matrix4x4 GetFinalTransform() const;
[[nodiscard]] bool IsRootBone() const;
public:
[[nodiscard]] int GetParentID() const;
[[nodiscard]] std::vector<int> GetChildren() const;
public:
void SetParent(int parent_id);
void AppendChild(int new_child);
void SetID(int numeric_id);
void SetName(const std::string& string_id);
void SetInverseBindMatrix(const Matrix4x4& inverse_bind);
void SetOffsetMatrix(const Matrix4x4& offset);
void SetFinalTransformMatrix(const Matrix4x4& final);
public:
~Bone() = default;
Bone() = default;
explicit Bone(int numeric_id, const std::string& string_id = "", int parent_id = -1, const std::vector<int>& children_ids = {},
const Matrix4x4& inverse_bind = Matrix4x4::Identity, const Matrix4x4& offset = Matrix4x4::Identity, const Matrix4x4& final = Matrix4x4::Identity);
};
class JGL::Skeleton {
private:
Bone root;
std::vector<Bone> bones;
public:
[[nodiscard]] Bone* GetRootBone();
[[nodiscard]] Bone* FindBone(int id);
[[nodiscard]] Bone* FindBone(const std::string& string_id);
public:
void AppendBone(const Bone& bone);
public:
explicit Skeleton(const Bone& root_bone, const std::vector<Bone>& children = {});
~Skeleton() = default;
Skeleton() = default;
};
class JGL::KeyFrame {
private:
float time_stamp = 0;
Skeleton pose;
public:
[[nodiscard]] float GetTimeStamp() const;
[[nodiscard]] Skeleton GetSkeleton() const;
public:
KeyFrame(const Skeleton& pose, float time_stamp);
};
class JGL::Animation {
private:
int id = -1;
// Not all animations have names.
std::string name;
float length = 0;
std::vector<KeyFrame> key_frames;
std::vector<SkeletalVertexAttribute> vertex_attributes{};
public:
[[nodiscard]] float GetDuratrion() const;
[[nodiscard]] std::vector<KeyFrame> GetKeyFrames() const;
[[nodiscard]] int GetID() const;
[[nodiscard]] std::string GetName() const;
[[nodiscard]] std::vector<SkeletalVertexAttribute> GetSkeletalVertexAttributes() const;
public:
void AppendKeyFrame(const KeyFrame& new_key);
void SetDuration(float duration);
void SetID(int identifier);
void SetName(const std::string& name_id);
public:
~Animation() = default;
Animation(int id, float duration, const std::vector<KeyFrame>& key_frames, const std::vector<SkeletalVertexAttribute>& skeletal_vertex_attributes,
const std::string& name = "");
};
class JGL::AnimationState {
private:
int animation_id = -1;
float animation_time = 0;
public:
};

View File

@@ -16,53 +16,53 @@ private:
GLuint list_handle = 0;
long num_elements = 0;
bool element_array_buffer = false;
/// "Spin Locking" fix for multi-threading.
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(Vector2* data, const long& length);
VRamList(Vector3* data, const long& length);
VRamList(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.
* Pass to function by const reference or pointer always. */
VRamList(const VRamList& rhs);
VRamList() = default;
public:
[[nodiscard]] GLuint GetHandle() const;
/// Returns the number of elements in the list.
[[nodiscard]] long GetLength() const;
/// Returns the size of the data in bytes.
[[nodiscard]] size_t GetSize() const;
[[nodiscard]] size_t GetDataSize() const;
/** Get VBO data back from the GPU. This is *bad* because the CPU is going to wait
* for the transfer to finish. Has limited use other than testing. */
[[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);
};

View File

@@ -0,0 +1,98 @@
#pragma once
#include <vector>
#include <JGL/types/VRamList.h>
#include <JGL/types/Skeleton.h>
#include <J3ML/LinearAlgebra/Vector3.hpp>
#include <J3ML/Geometry/Sphere.hpp>
#include <J3ML/Geometry/AABB.hpp>
#include <J3ML/Geometry/OBB.hpp>
namespace JGL {
/// A point that is part of an object in 3D space.
typedef Vector3 Vertex;
/// A direction vector which describes which way a triangle is facing.
typedef Vector3 Normal;
/// 2D positions that describe how a texture is to be wrapped around a 3D object.
typedef Vector2 TextureCoordinate;
/// Container for storing 3D models in v-ram, system memory, or both.
class VertexArray;
}
class JGL::VertexArray {
private:
Sphere me_sphere;
OBB me_obb;
protected:
virtual void CreateMESphere();
virtual void CreateMEOBB();
protected:
std::vector<Animation> animations{};
protected:
VRamList vertices;
VRamList indices;
VRamList normals;
VRamList texture_coordinates;
protected:
/** For models which are not animated, This is intended for a low quality version in
* system memory for calculations to be done on the CPU. For models that are, the default pose of the model is here.
*/
std::vector<Vertex> local_vertices{};
std::vector<unsigned int> local_indices{};
std::vector<TextureCoordinate> local_texture_coordinates{};
std::vector<Normal> local_normals{};
public:
/** Don't use these for anything other than drawing because the GPU is gonna spin during read-back */
[[nodiscard]] VRamList GetVertices() const;
[[nodiscard]] VRamList GetIndices() const;
[[nodiscard]] VRamList GetNormals() const;
[[nodiscard]] VRamList GetTextureCoordinates() const;
/** These are for cpu side calculations */
[[nodiscard]] std::vector<Vertex> GetLocalVertices() const;
[[nodiscard]] std::vector<unsigned int> GetLocalIndices() const;
[[nodiscard]] std::vector<TextureCoordinate> GetLocalTextureCoordinates() const;
[[nodiscard]] std::vector<Normal> GetLocalNormals() const;
public:
/// Returns true if the VertexArray does not have any animations.
bool Static();
public:
/// Provides the minimally enclosing bounding sphere of the vertex array given information from the instance.
/// @param scale The scale of the instance.
/// @param translate_part The center of the sphere would be shifted in 3D space by this. Primarily for world space.
[[nodiscard]] Sphere GetMESphere(const Vector3& scale = Vector3::One, const Vector3& translate_part = Vector3::Zero) const;
/// Provides the minimally enclosing bounding sphere of the vertex array given information from the instance.
/// @param instance_matrix A Matrix4x4 which contains scale, rotation, and translation.
/// @param translate Whether or not to translate to world space by the translate part of the Matrix.
[[nodiscard]] Sphere GetMESphere(const Matrix4x4& instance_matrix, bool translate = false) const;
/// Provides the minimally enclosing oriented bounding box of the vertex array given information from the instance.
/// @param rotation_matrix A Matrix3x3 representing rotation in 3D space.
/// @param scale The scale of the instance.
/// @param translate_part The center of the box would be shifted in 3D space by this. Primarily for world space.
[[nodiscard]] OBB GetMEOBB(const Matrix3x3& rotation_matrix, const Vector3& scale = Vector3::One, const Vector3& translate_part = Vector3::Zero) const;
/// Provides the minimally enclosing oriented bounding box of the vertex array given information from the instance.
/// @param instance_matrix A Matrix4x4 which contains scale, rotation, and translation.
/// @param translate Whether or not to translate to world space by the translate part of the Matrix.
[[nodiscard]] OBB GetMEOBB(const Matrix4x4& instance_matrix, bool translate = false) const;
/// Provides the minimally enclosing axis-aligned bounding box of the vertex array given information from the instance.
/// @param rotation_matrix A Matrix3x3 representing rotation in 3D space.
/// @param scale The scale of the instance.
/// @param translate_part The center of the box would be shifted in 3D space by this. Primarily for world space.
[[nodiscard]] AABB GetMEAABB(const Matrix3x3& rotation_matrix, const Vector3& scale = Vector3::One, const Vector3& translate_part = Vector3::Zero) const;
[[nodiscard]] AABB GetMEAABB(const Matrix4x4& instance_matrix, bool translate = false) const;
public:
/// Vertices are required, Everything else is optional.
VertexArray(const Vertex* vertex_positions, const long& vp_length, const unsigned int* vertex_indices = nullptr, const long& vi_length = 0,
const Normal* vertex_normals = nullptr, const long& vn_length = 0, const TextureCoordinate* texture_coordinates = nullptr, const long& vt_length = 0);
/// Vertices are required, Everything else is optional.
explicit VertexArray(const std::vector<Vertex>& vertex_positions, const std::vector<unsigned int>& vertex_indices = {},
const std::vector<Normal>& vertex_normals = {}, const std::vector<TextureCoordinate>& texture_coordinates = {});
};
using namespace JGL;
static VertexArray Animate(int animation_id, float animation_time);
static VertexArray Animate(const AnimationState& anim_state);

108
main.cpp
View File

@@ -4,6 +4,7 @@
#include <chrono>
#include <J3ML/LinearAlgebra/Vector2.hpp>
#include <JGL/logger/logger.h>
#include <J3ML/Geometry/AABB.hpp>
using J3ML::LinearAlgebra::Vector2;
using namespace JGL;
@@ -97,22 +98,18 @@ 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
{
public:
void initGL() {
camera = new Camera;
gladLoadGL();
if (!JGL::MeetsRequirements())
Logger::Warning("The graphics driver does not meet the minimum requirements to run this program.");
JGL::InitTextEngine();
JGL::Update(getSize());
J3D::Init(getSize(), 90, 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");
@@ -121,36 +118,36 @@ public:
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;
int blit_pos = 0;
void display() {
JGL::Update(getSize());
float dt = 1.f / fps;
JGL::Update(GetSize());
if (fov_increasing)
fov += 0.25;
fov += 0.025;
else
fov -= 0.50;
fov -= 0.050;
if (fov >= 120)
fov_increasing = false;
else if (fov <= 75)
fov_increasing = true;
J3D::ChangeFOV(fov);
//J3D::ChangeFOV(fov);
sprite_radians += 0.05;
textAngle.y += 2.0f;
sprite_radians += 0.005;
textAngle.yaw += 1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@@ -159,15 +156,30 @@ public:
// 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, true);
//J3D::WireframeSphere(Colors::Green, {0,0,0.5f}, 0.25f, 1, 128, 128);
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});
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(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});
@@ -185,7 +197,7 @@ 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::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);
@@ -205,17 +217,45 @@ 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::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))
camera->angle.y += 45.f * elapsed;
if (IsKeyDown(Keys::LeftArrow))
camera->angle.y -= 45.f * elapsed;
if (IsKeyDown(Keys::UpArrow))
camera->angle.x -= 45.f * elapsed;
if (IsKeyDown(Keys::DownArrow))
camera->angle.x += 45.f * elapsed;
if (IsKeyDown(Keys::Space))
camera->position.y += 1.f * elapsed;
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);
@@ -225,11 +265,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();
@@ -238,7 +278,7 @@ public:
d.Grab();
}
void OnMouseButtonUp(const ReWindow::WindowEvents::MouseButtonUpEvent & ev) override
void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent & ev) override
{
RWindow::OnMouseButtonUp(ev);
a.Release();
@@ -254,16 +294,16 @@ 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()) {
while (window->IsAlive()) {
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
window->pollEvents();
window->refresh();
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();

View File

@@ -6,6 +6,12 @@
#include <glad/glad.h>
#include <J3ML/Algorithm/Bezier.hpp>
#include <JGL/logger/logger.h>
#include <J3ML/Geometry/AABB.hpp>
#include <J3ML/Geometry/Sphere.hpp>
#include <J3ML/Geometry/OBB.hpp>
#include <JGL/types/VRamList.h>
#include <JGL/types/Font.h>
#include <JGL/ShapeCache.h>
JGL::RenderTarget* render_target = nullptr;
GLfloat oldColor[4] = {0, 0, 0, 1};
@@ -26,9 +32,30 @@ 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;
namespace JGL {
using namespace J3ML;
Vector2 wS;
bool Init(const Vector2& window_size, float fovY, float far_plane) {
gladLoadGL();
if (!MeetsRequirements()) {
Logger::Fatal("The graphics driver does not meet the minimum requirements to run this program.");
return false;
}
InitTextEngine();
ShapeCache::Init();
wS = window_size;
j3d_fov = fovY;
j3d_far_plane = far_plane;
return true;
}
void Update(const Vector2& window_size) {
wS = window_size;
@@ -40,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;
}
@@ -77,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,
@@ -125,7 +158,7 @@ namespace JGL {
else { Logger::Error("Beginning J2D context inside of J3D context?"); }
if (rt != nullptr && clear_buffers) {
glClearColor(rt->GetClearColor().R(), rt->GetClearColor().G(), rt->GetClearColor().B(), rt->GetClearColor().A());
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]);
}
@@ -149,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);
@@ -158,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);
@@ -204,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.");
@@ -368,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)
@@ -440,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)
@@ -620,7 +844,8 @@ namespace JGL {
GLfloat angle, x, y;
int i = 0;
for (angle = 0.0f; angle < (2.f * Math::Pi); angle += step) {
for (angle = 0.0f; angle < (2.f * Math::Pi); angle += step)
{
x = radius * std::sin(angle) + center.x;
y = radius * std::cos(angle) + center.y;
if (i < subdivisions)
@@ -708,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) {
@@ -740,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);
}
@@ -762,7 +987,7 @@ namespace JGL {
int i = 0;
for (angle = arc_begin; angle <= arc_end; angle += step) {
x = center.x + (radius * std::cos(angle));
x = center.x + (radius * std::cos(angle)); // TODO: Why is it fine here, but must be x,y flipped for sin,cos in Circle code?
y = center.y + (radius * std::sin(angle));
if (i < subdivisions)
vertices[i] = {x, y};
@@ -778,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
@@ -842,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);
}
@@ -877,9 +1102,80 @@ 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) {
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,
int subdivisions) {
if (!inJ2D)
Logger::Error("Drawing J2D element before J2D begin.");
float step = (2.f * Math::Pi) / (float) subdivisions;
std::vector<Vector2> vertices(subdivisions);
GLfloat angle, x, y;
int i = 0;
for (angle = 0.0f; angle < (2.f * Math::Pi); angle += step) {
x = radius_x * std::sin(angle) + position.x;
y = radius_y * std::cos(angle) + position.y;
if (i < subdivisions)
vertices[i] = {x, y};
else
vertices.emplace_back(x, y);
i++;
}
glLineWidth(thickness);
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_LINE_LOOP, 0, (int) vertices.size());
glColor4fv(baseColor);
}
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.");
GLfloat angle, x, y;
float step = (2.f * Math::Pi) / (float) subdivisions;
std::vector<Vector2> vertices(subdivisions);
/* Most of the time the vector "vertices" is either the same size or size + 1 of the number of subdivisions.
* Because a float is a decimal, It'd take too long to get rid of the emplace-back making us
* wait around for the container to resize. This gets rid of it for what we can guarantee. */
int i = 0;
for (angle = 0.0f; angle < (2.f * Math::Pi); angle += step) {
x = radius_x * std::sin(angle) + position.x;
y = radius_y * std::cos(angle) + position.y;
if (i < subdivisions)
vertices[i] = {x, y};
else
vertices.emplace_back(x, y);
i++;
}
glColor4ubv(color.ptr());
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
glDrawArrays(GL_TRIANGLE_FAN, 0, (int) vertices.size());
glColor4fv(baseColor);
}
#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);
@@ -891,15 +1187,12 @@ namespace JGL {
return result;
}
bool j3d_initialized = false;
float j3d_far_plane = 0;
float j3d_fov = 0;
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();
void J3D::Init(const J3ML::LinearAlgebra::Vector2& window_size, float fov, float far_plane) {
wS = window_size;
j3d_far_plane = far_plane;
j3d_fov = fov;
j3d_initialized = true;
return 1.0f / (light->GetConstantAttenuation() + light->GetLinearAttenuation() * distance + light->GetQuadraticAttenuation() * distance * distance);
}
void J3D::ChangeFOV(float fov) {
@@ -910,9 +1203,18 @@ 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() {
if (!j3d_initialized)
throw std::runtime_error("You have to run J3D::Init before rendering 3D elements.");
auto aspect = (float) wS.x / (float) wS.y;
glMatrixMode(GL_PROJECTION);
@@ -924,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))
@@ -954,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
@@ -961,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);
@@ -979,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;
@@ -996,5 +1320,414 @@ namespace JGL {
glDrawArrays(GL_LINES, 0, 2);
glColor4fv(baseColor);
}
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);
}
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, 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));
int index = 0;
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 <= stacks; j++) {
float lng = 2 * J3ML::Math::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;
vertices[index++] = Vector3(pos_x, pos_y, pos_z);
}
}
glLineWidth(thickness);
glColor4ubv(color.ptr());
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
// 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());
glPopMatrix();
}
glColor4fv(baseColor);
}
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);
}
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, 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 = 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);
}
// Revolve
for (int j = 0; j <= revolutions; j++) {
float lng = 2 * J3ML::Math::Pi * (float)j / revolutions;
float cosLng = J3ML::Math::Cos(lng);
float sinLng = J3ML::Math::Sin(lng);
for (const auto& point : cross_section) {
float pos_x = point.y * cosLng;
float pos_y = point.y * sinLng;
float pos_z = point.z;
vertices.emplace_back(pos_x, pos_y, pos_z);
}
}
glLineWidth(thickness);
glColor4ubv(color.ptr());
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, 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);
}
void 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.");
// NOTE2SELF: Code i'm borrowing this from uses float-packed-arrays rather than discrete Vectors
// working on translating that correctly...
// 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;
std::vector<Vector3> vertices; // array of 12 vertices (x,y,z)
unsigned int index = 0; // indices
float z, xy; // coords
float hAngle1 = -Math::Pi / 2.f - h_angle / 2.f; // start from -126 at 1st row
float hAngle2 = -Math::Pi / 2.f; // start from -90 deg at 2nd row
// the first top vertex at (0,0,r)
vertices[0] = position + Vector3{0,0,radius};
// compute 10 vertices at 1st and 2nd rows
for (int i = 1; i <= 5; ++i)
{
z = radius * Math::Sin(v_angle); // elevation
xy = radius * Math::Cos(v_angle); // length on XY plane
vertices[index++] = position + Vector3{xy * Math::Cos(hAngle1), xy * Math::Sin(hAngle1), z} ;
vertices[index++] = position + Vector3{xy * Math::Cos(hAngle2), xy * Math::Sin(hAngle2), -z};
// next horizontal angles
hAngle1 += h_angle;
hAngle2 += h_angle;
}
// the last bottom vertex at (0, 0, -r)
vertices[11] = position + Vector3{0,0, -radius};
//glLineWidth(thickness);
//glColor4ubv(color.ptr());
//glBindBuffer(GL_ARRAY_BUFFER, vertices.size());
//glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
//glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());
//glColor4fv(baseColor);
std::vector<Vector3> tmpVertices;
std::vector<Vector3> tmpIndices;
std::vector<Vector2> newVs((subdivisions+1) * (subdivisions+2) / 2 * 3);
const Vector3 v1, v2, v3;
Vector3 newV1, newV2, newV3;
int i, j, k;
index = 0; // unsigned int
float a; // lerp alpha
unsigned int i1, i2; // indices
// copy prev arrays
tmpVertices = vertices;
//tmpIndices = indices;
// iterate each triangle of icosahedron
for (i = 0; i < tmpIndices.size(); i++)
{
//v1 = tmpVertices[tmpIndices[i]];
//v2 = tmpVertices[tmpIndices[i+1]];
//v3 = tmpVertices[tmpIndices[i+2]];
}
}
void 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;
std::array<Vector3, 12> vertices; // array of 12 vertices (x,y,z)
int index = 0; // indices
float z, xy; // coords
float hAngle1 = -Math::Pi / 2.f - h_angle / 2.f; // start from -126 at 1st row
float hAngle2 = -Math::Pi / 2.f; // start from -90 deg at 2nd row
// the first top vertex at (0,0,r)
vertices[0] = position + Vector3{0,0,radius};
// compute 10 vertices at 1st and 2nd rows
for (int i = 1; i <= 5; ++i)
{
z = radius * Math::Sin(v_angle); // elevation
xy = radius * Math::Cos(v_angle); // length on XY plane
vertices[index++] = position + Vector3{xy * Math::Cos(hAngle1), xy * Math::Sin(hAngle1), z} ;
vertices[index++] = position + Vector3{xy * Math::Cos(hAngle2), xy * Math::Sin(hAngle2), -z};
// next horizontal angles
hAngle1 += h_angle;
hAngle2 += h_angle;
}
// the last bottom vertex at (0, 0, -r)
vertices[11] = position + Vector3{0,0, -radius};
glLineWidth(thickness);
glColor4ubv(color.ptr());
//glBindBuffer(GL_ARRAY_BUFFER, vertices.size());
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size());
glColor4fv(baseColor);
}
void J3D::BatchWireframeAABB(const Color4& color, const AABB* boxes, const size_t& box_count, float thickness) {
glColor4ubv(color.ptr());
glLineWidth(thickness);
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::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.");
glColor4ubv(color.ptr());
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) {
BatchFillAABB(color, &aabb, 1);
}
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);
float two_pi = 2 * J3ML::Math::Pi;
int index = 0;
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 <= 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;
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());
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::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);
}
void J3D::WireframeAABB(const Color4& color, const AABB& aabb, float thickness) {
BatchWireframeAABB(color, &aabb, 1, 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;
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
};
glLineWidth(thickness);
glColor4ubv(color.ptr());
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), corner_points.data());
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 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;
const Vector3& first = controlB;
for (int i = 0; i < subdivisions; ++i)
{
float alpha = (float) i / (float) subdivisions;
Vector3 step = J3ML::Algorithm::Bezier(alpha, controlA, pointA, pointB, controlB);
DrawLine(color, last, step, thickness);
last = step;
}
// Have to manually draw the last segment of the curve.
DrawLine(color, last, first, thickness);
}
#pragma endregion
}

38
src/ShapeCache.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include <JGL/ShapeCache.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());
}
}

View File

@@ -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;

View File

@@ -3,7 +3,7 @@
#include <string>
#include <iostream>
#include <glad/glad.h>
#include <jlog/Logger.hpp>
#include <JGL/logger/logger.h>
#if __linux__
#include <freetype2/ft2build.h>
@@ -32,7 +32,7 @@ namespace JGL::Detail
// Keep note of this, might cause problems later?
if (ft != nullptr)
throw std::runtime_error("Error::FREETYPE: FT_Library was initialized but is already initialized.");
Logger::Fatal("Error::FREETYPE: FT_Library was initialized but is already initialized.");
if (FT_Init_FreeType(&ft))
return true;
@@ -52,23 +52,20 @@ namespace JGL::Detail
}
}
namespace JGL
{
namespace JGL {
bool InitTextEngine()
{
bool InitTextEngine() {
return Detail::InitTextEngine();
}
Font::Font(const std::filesystem::path& path)
{
Font::Font(const std::filesystem::path& path) {
if (Detail::ft == nullptr)
throw new std::runtime_error("Error::FREETYPE: FT_Library was not initialized before attempting to load a font!");
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;
throw new std::runtime_error("Error::FREETYPE: Failed to load font!");
throw std::runtime_error("Error::FREETYPE: Failed to load font!");
//return -1;
}
unsigned int newIndex = 0;

View File

@@ -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;
}

View File

@@ -53,6 +53,9 @@ Color4 JGL::RenderTarget::GetClearColor() const {
/// Idk why you'd ever want to clear it out if you're rendering onto a texture you passed in :shrug:.
JGL::RenderTarget::RenderTarget(const JGL::Texture* texture, const Color4& clear_color) {
if (texture->GetDimensions().x < 1 || texture->GetDimensions().y < 1)
Logger::Fatal("Creating a render target where the color attachment is empty?");
GLuint current_fbo = GetActiveGLFramebufferHandle();
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv(GL_VIEWPORT, viewport);
@@ -74,6 +77,9 @@ JGL::RenderTarget::RenderTarget(const JGL::Texture* texture, const Color4& clear
}
JGL::RenderTarget::RenderTarget(const Vector2& size, const Color4& clear_color, bool use_depth, MSAA_SAMPLE_RATE sample_rate) {
if (size.x < 1 || size.y < 1)
Logger::Fatal("Creating a render target where the color attachment is empty?");
GLuint current_fbo = GetActiveGLFramebufferHandle();
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv(GL_VIEWPORT, viewport);
@@ -207,7 +213,7 @@ JGL::MSAA_SAMPLE_RATE JGL::RenderTarget::GetMSAASampleRate() const {
}
bool JGL::RenderTarget::MSAAEnabled() const {
return msaa_sample_rate != MSAA_SAMPLE_RATE::MSAA_NONE;
return msaa_sample_rate != MSAA_SAMPLE_RATE::MSAA_NONE;
}
void JGL::RenderTarget::SetMSAAEnabled(JGL::MSAA_SAMPLE_RATE sample_rate) {
@@ -303,6 +309,7 @@ void JGL::RenderTarget::Blit() const {
}
void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget* destination) {
//TODO allow blitting onto an FBO that is bigger but not smaller.
if (source.size != destination->size)
Logger::Warning("Blitting a render target but they're not the same size?");
@@ -324,6 +331,43 @@ 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.");
if (pixel == nullptr)
pixel = new RenderTarget({1,1});
GLint current_draw_fbo = 0;
GLint current_read_fbo = 0;
GLint viewport[4];
GLfloat clear_color[4];
GLuint current_fbo = GetActiveGLFramebufferHandle();
glGetIntegerv(GL_VIEWPORT, viewport);
glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &current_read_fbo);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_draw_fbo);
SetActiveGLRenderTarget(*pixel);
glClearColor(color.RedChannelNormalized(), color.GreenChannelNormalized(), color.BlueChannelNormalized(), color.AlphaChannelNormalized());
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, 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);
glBindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_draw_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
}
JGL::RenderTarget::RenderTarget(const JGL::RenderTarget& rhs) {
auto* this_render_target = new RenderTarget(rhs.size, rhs.clear_color, rhs.using_depth, rhs.msaa_sample_rate);
RenderTarget::Blit(rhs, this_render_target);

186
src/types/Skeleton.cpp Normal file
View File

@@ -0,0 +1,186 @@
#include <JGL/types/Skeleton.h>
#include <JGL/logger/logger.h>
#include <cstring>
using namespace JGL;
std::array<int, 4> JGL::SkeletalVertexAttribute::GetAffectingBoneIDs() const {
return bone_ids;
}
std::array<float, 4> JGL::SkeletalVertexAttribute::GetAffectingBoneWeights() const {
return bone_weights;
}
JGL::SkeletalVertexAttribute::SkeletalVertexAttribute(const std::vector<int>& ids, const std::vector<float>& weights) {
if (bone_ids.size() > 4 || bone_weights.size() > 4)
Logger::Fatal("Initialization of a skeletal vertex that is effected by more than 4 bones.");
memcpy(this->bone_ids.data(), bone_ids.data(), sizeof(int) * 4);
memcpy(this->bone_weights.data(), bone_weights.data(), sizeof(float) * 4);
}
bool JGL::Bone::IsRootBone() const {
if (parent_id == -1)
return true;
return false;
}
int JGL::Bone::GetID() const {
return id;
}
std::string JGL::Bone::GetName() const {
return name;
}
Matrix4x4 JGL::Bone::GetInverseBindMatrix() const {
return inverse_bind_matrix;
}
Matrix4x4 JGL::Bone::GetOffsetMatrix() const {
return offset_matrix;
}
Matrix4x4 JGL::Bone::GetFinalTransform() const {
return final_transform;
}
std::vector<int> JGL::Bone::GetChildren() const {
return children;
}
void Bone::SetParent(int parent_identifier) {
parent_id = parent_identifier;
}
void Bone::AppendChild(int new_child) {
children.push_back(new_child);
}
void Bone::SetID(int numeric_id) {
id = numeric_id;
}
void Bone::SetName(const std::string& string_id) {
name = string_id;
}
void Bone::SetInverseBindMatrix(const Matrix4x4& inverse_bind) {
inverse_bind_matrix = inverse_bind;
}
void Bone::SetOffsetMatrix(const Matrix4x4& offset) {
offset_matrix = offset;
}
void Bone::SetFinalTransformMatrix(const Matrix4x4& final) {
final_transform = final;
}
int Bone::GetParentID() const {
return parent_id;
}
Bone::Bone(int numeric_id, const std::string& string_id, int parent_bone, const std::vector<int>& children_ids, const Matrix4x4& inverse_bind, const Matrix4x4& offset, const Matrix4x4& final) {
id = numeric_id;
name = string_id;
parent_id = parent_bone;
inverse_bind_matrix = inverse_bind;
offset_matrix = offset;
final_transform = final;
children = children_ids;
}
Bone* Skeleton::GetRootBone() {
return &root;
}
Bone* Skeleton::FindBone(int id) {
if (root.GetID() == id)
return &root;
for (auto& bone : bones)
if (bone.GetID() == id)
return &bone;
// If we couldn't find it.
return nullptr;
}
Bone* Skeleton::FindBone(const std::string& string_id) {
if (root.GetName() == string_id)
return &root;
for (auto& bone : bones)
if (bone.GetName() == string_id)
return &bone;
return nullptr;
}
void Skeleton::AppendBone(const Bone& new_bone) {
bones.push_back(new_bone);
}
Skeleton::Skeleton(const Bone& root_bone, const std::vector<Bone>& children) {
root = root_bone;
bones = children;
}
float KeyFrame::GetTimeStamp() const {
return time_stamp;
}
Skeleton KeyFrame::GetSkeleton() const {
return pose;
}
KeyFrame::KeyFrame(const Skeleton& pose, float time_stamp) {
this->pose = pose;
this->time_stamp = time_stamp;
}
Animation::Animation(int id, float duration, const std::vector<KeyFrame>& key_frames, const std::vector<SkeletalVertexAttribute>& skeletal_vertex_attributes,
const std::string& name) {
length = duration;
this->key_frames = key_frames;
this->id = id;
this->name = name;
this->vertex_attributes = skeletal_vertex_attributes;
}
float Animation::GetDuratrion() const {
return length;
}
std::vector<KeyFrame> Animation::GetKeyFrames() const {
return key_frames;
}
void Animation::AppendKeyFrame(const KeyFrame& new_key) {
key_frames.push_back(new_key);
}
void Animation::SetDuration(float duration) {
length = duration;
}
int Animation::GetID() const {
return id;
}
std::string Animation::GetName() const {
return name;
}
void Animation::SetID(int identifier) {
id = identifier;
}
void Animation::SetName(const std::string& name_id) {
name = name_id;
}
std::vector<SkeletalVertexAttribute> Animation::GetSkeletalVertexAttributes() const {
return vertex_attributes;
}

View File

@@ -3,6 +3,9 @@
#include <cstring>
void JGL::VRamList::load(const GLfloat* data, const long& size) {
while (spin_lock) {}
spin_lock = true;
GLint current_array_buffer = 0;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &current_array_buffer);
glGenBuffers(1, &list_handle);
@@ -11,9 +14,14 @@ void JGL::VRamList::load(const GLfloat* data, const long& size) {
glBindBuffer(GL_ARRAY_BUFFER, current_array_buffer);
element_array_buffer = false;
num_elements = size / sizeof(GLfloat);
spin_lock = false;
}
void JGL::VRamList::load(const GLuint* data, const long& size) {
while (spin_lock) {}
spin_lock = true;
GLint current_element_array_buffer = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &current_element_array_buffer);
glGenBuffers(1, &list_handle);
@@ -22,13 +30,16 @@ void JGL::VRamList::load(const GLuint* data, const long& size) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, current_element_array_buffer);
element_array_buffer = true;
num_elements = size / sizeof(GLuint);
spin_lock = false;
}
void JGL::VRamList::Erase() {
if (list_handle == 0) {
JGL::Logger::Warning("Erasing an uninitialized VRamList?");
if (list_handle == 0)
return;
}
while (spin_lock) {}
spin_lock = true;
GLint current_element_array_buffer = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &current_element_array_buffer);
@@ -43,6 +54,8 @@ void JGL::VRamList::Erase() {
glDeleteBuffers(1, &list_handle);
list_handle = 0;
spin_lock = false;
}
GLuint JGL::VRamList::GetHandle() const {
@@ -57,26 +70,26 @@ long JGL::VRamList::GetLength() const {
return num_elements;
}
size_t JGL::VRamList::GetSize() const {
size_t JGL::VRamList::GetDataSize() const {
if (element_array_buffer)
return sizeof(GLuint) * num_elements;
return sizeof(GLfloat) * num_elements;
}
void JGL::VRamList::SetData(void* data, const long& length) {
bool should_resize = (this->num_elements != length);
while (spin_lock) {}
spin_lock = true;
bool should_resize = (this->num_elements != length);
if (should_resize) {
glDeleteBuffers(1, &list_handle);
list_handle = 0;
if (!element_array_buffer)
load((GLfloat*) data, sizeof(GLfloat) * length);
else
load((GLuint*) data, sizeof(GLuint) * length);
spin_lock = false;
element_array_buffer ? load((GLuint*) data, sizeof(GLuint) * length) : load((GLfloat*) data, sizeof(GLfloat) * length);
return;
}
// if (!should resize)
GLint current_buffer = 0;
GLenum buffer_type = GL_ARRAY_BUFFER;
GLenum buffer_binding = GL_ARRAY_BUFFER_BINDING;
@@ -97,9 +110,13 @@ void JGL::VRamList::SetData(void* data, const long& length) {
JGL::Logger::Fatal("We couldn't unmap the buffer?");
glBindBuffer(buffer_type, current_buffer);
spin_lock = false;
}
void JGL::VRamList::UpdateData(void* data, const long& offset, const long& length) {
while (spin_lock) {}
spin_lock = true;
if (offset + length > num_elements) {
JGL::Logger::Warning("Using UpdateData to out-of-bounds write the VRamList? I'll resize it for you, But this is slow.");
@@ -109,14 +126,16 @@ void JGL::VRamList::UpdateData(void* data, const long& offset, const long& lengt
auto list_data = GetDataUI();
list_data.resize(list_data.size() + oob_delta);
memcpy(list_data.data() + (offset * sizeof(GLuint)), data, length * sizeof(GLuint));
SetData(list_data.data(), list_data.size());
}
else {
auto list_data = GetDataF();
list_data.resize(list_data.size() + oob_delta);
memcpy(list_data.data() + (offset * sizeof(GLfloat)), data, length * sizeof(GLfloat));
SetData(list_data.data(), list_data.size());
spin_lock = false; // This is going unlock and relock really fast, But this code fixes something considered wrong anyway - Redacted.
return SetData(list_data.data(), list_data.size());
}
// if (!element_array_buffer)
auto list_data = GetDataF();
list_data.resize(list_data.size() + oob_delta);
memcpy(list_data.data() + (offset * sizeof(GLfloat)), data, length * sizeof(GLfloat));
spin_lock = false;
return SetData(list_data.data(), list_data.size());
}
GLint current_buffer = 0;
@@ -141,9 +160,13 @@ void JGL::VRamList::UpdateData(void* data, const long& offset, const long& lengt
JGL::Logger::Fatal("We couldn't unmap the buffer?");
glBindBuffer(buffer_type, current_buffer);
spin_lock = false;
}
std::vector<GLfloat> JGL::VRamList::GetDataF() const {
while (spin_lock) {}
if (element_array_buffer)
JGL::Logger::Warning("Getting data as GLfloat but the buffer data is GLuint?");
@@ -165,6 +188,8 @@ std::vector<GLfloat> JGL::VRamList::GetDataF() const {
}
std::vector<GLuint> JGL::VRamList::GetDataUI() const {
while (spin_lock) {}
if (!element_array_buffer)
JGL::Logger::Warning("Getting data as GLuint but the buffer data is GLfloat?");
@@ -194,16 +219,16 @@ JGL::VRamList::VRamList(const GLuint* data, const long& length) {
load(data, (long) sizeof(GLuint) * length);
}
JGL::VRamList::VRamList(Vector2* data, const long& length) {
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector2) * length);
JGL::VRamList::VRamList(const Vector2* data, const long& length) {
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector2) * length);
}
JGL::VRamList::VRamList(Vector3* data, const long& length) {
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector3) * length);
JGL::VRamList::VRamList(const Vector3* data, const long& length) {
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector3) * length);
}
JGL::VRamList::VRamList(Vector4* data, const long& length) {
load(reinterpret_cast<GLfloat*>(data), (long) sizeof(Vector4) * length);
JGL::VRamList::VRamList(const Vector4* data, const long& length) {
load(reinterpret_cast<const GLfloat*>(data), (long) sizeof(Vector4) * length);
}
void JGL::VRamList::SetData(const GLfloat* data, const long& length) {
@@ -259,6 +284,8 @@ JGL::VRamList::~VRamList() {
}
JGL::VRamList::VRamList(const JGL::VRamList& rhs) {
while (rhs.spin_lock) {}
if (rhs.element_array_buffer) {
auto data_array = rhs.GetDataUI();
this->load(data_array.data(), data_array.size());

191
src/types/VertexArray.cpp Normal file
View File

@@ -0,0 +1,191 @@
#include <JGL/types/VertexArray.h>
using namespace JGL;
VRamList VertexArray::GetVertices() const {
return vertices;
}
VRamList VertexArray::GetIndices() const {
return indices;
}
JGL::VRamList VertexArray::GetNormals() const {
return normals;
}
VRamList VertexArray::GetTextureCoordinates() const {
return texture_coordinates;
}
std::vector<Vertex> VertexArray::GetLocalVertices() const {
return local_vertices;
}
std::vector<unsigned int> VertexArray::GetLocalIndices() const {
return local_indices;
}
std::vector<TextureCoordinate> VertexArray::GetLocalTextureCoordinates() const {
return local_texture_coordinates;
}
std::vector<Normal> VertexArray::GetLocalNormals() const {
return local_normals;
}
Sphere VertexArray::GetMESphere(const Vector3& scale, const Vector3& translate_part) const {
if (scale == Vector3::One)
return { me_sphere.Position + translate_part, me_sphere.Radius };
float scale_factor = 0;
if (scale.x > scale_factor)
scale_factor = scale.x;
if (scale.y > scale_factor)
scale_factor = scale.y;
if (scale.z > scale_factor)
scale_factor = scale.z;
return { me_sphere.Position + translate_part, me_sphere.Radius * scale_factor };
}
Sphere VertexArray::GetMESphere(const Matrix4x4& instance_matrix, bool translate) const {
Vector3 scale = instance_matrix.GetScale();
Vector3 origin = Vector3::Zero;
if (translate)
origin = instance_matrix.GetTranslatePart();
return GetMESphere(scale, origin);
}
void VertexArray::CreateMESphere() {
Sphere result = {Vector3::Zero, 0};
Vector3 minimum = {std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
Vector3 maximum = { std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest()};
for (const auto& vertex : local_vertices) {
if (vertex.x < minimum.x)
minimum.x = vertex.x;
if (vertex.x > maximum.x)
maximum.x = vertex.x;
if (vertex.y < minimum.y)
minimum.y = vertex.y;
if (vertex.y > maximum.y)
maximum.y = vertex.y;
if (vertex.z < minimum.z)
minimum.z = vertex.z;
if (vertex.z > maximum.z)
maximum.z = vertex.z;
}
result.Position = (minimum + maximum) * 0.5f;
for (const auto& vertex : local_vertices) {
float distance_squared = Vector3::DistanceSquared(result.Position, vertex);
if (distance_squared > result.Radius)
result.Radius = distance_squared;
}
result.Radius = std::sqrt(result.Radius);
me_sphere = result;
}
void VertexArray::CreateMEOBB() {
Vector3 minimum(std::numeric_limits<float>::max());
Vector3 maximum (std::numeric_limits<float>::min());
for (const auto& vertex : local_vertices) {
if (vertex.x < minimum.x)
minimum.x = vertex.x;
if (vertex.x > maximum.x)
maximum.x = vertex.x;
if (vertex.y < minimum.y)
minimum.y = vertex.y;
if (vertex.y > maximum.y)
maximum.y = vertex.y;
if (vertex.z < minimum.z)
minimum.z = vertex.z;
if (vertex.z > maximum.z)
maximum.z = vertex.z;
}
Vector3 position = (minimum + maximum) * 0.5f;
Vector3 half_extents = (maximum - minimum) * 0.5f;
me_obb = { position, half_extents, Vector3::UnitX, Vector3::UnitY, Vector3::UnitZ };
}
OBB VertexArray::GetMEOBB(const Matrix3x3& rotation_matrix, const Vector3& scale, const Vector3& translate_part) const {
Vector3 half_extents = me_obb.r.Mul(scale);
Vector3 axis0 = rotation_matrix * me_obb.axis[0];
Vector3 axis1 = rotation_matrix * me_obb.axis[1];
Vector3 axis2 = rotation_matrix * me_obb.axis[2];
Vector3 position = me_obb.pos + translate_part;
return { position, half_extents, axis0, axis1, axis2 };
}
OBB VertexArray::GetMEOBB(const Matrix4x4& instance_matrix, bool translate) const {
return GetMEOBB(instance_matrix.GetRotatePart(), instance_matrix.GetScale(), translate ? instance_matrix.GetTranslatePart() : Vector3::Zero);
}
AABB VertexArray::GetMEAABB(const Matrix3x3& rotation_matrix, const Vector3& scale, const Vector3& translate_part) const {
/* kind-of a cheat. It's faster to calculate the oriented bounding box and then put the axis-aligned one around that
* than to loop over the whole model like an idiot. You gain back all the speed with the simplicity of the physics anyways. - Redacted */
return GetMEOBB(rotation_matrix, scale, translate_part).MinimalEnclosingAABB();
}
AABB VertexArray::GetMEAABB(const Matrix4x4& instance_matrix, bool translate) const {
return GetMEAABB(instance_matrix.GetRotatePart(), instance_matrix.GetScale(), translate ? instance_matrix.GetTranslatePart() : Vector3::Zero);
}
VertexArray::VertexArray(const Vector3* vertex_positions, const long& vp_length, const unsigned int* vertex_indices, const long& vi_length,
const Normal* vertex_normals, const long& vn_length, const TextureCoordinate* texture_coordinates, const long& vt_length) {
// TODO decimator. This is a total waste of memory as it sits.
vertices = VRamList(vertex_positions, vp_length);
if (vertex_indices && vi_length) {
indices = VRamList(vertex_indices, vi_length);
local_indices.resize(vi_length);
memcpy(local_indices.data(), vertex_indices, sizeof(unsigned int) * vi_length);
}
if (vertex_normals && vn_length) {
normals = VRamList(vertex_normals, vn_length);
local_normals.resize(vn_length);
memcpy(local_normals.data(), vertex_indices, sizeof(Normal) * vn_length);
}
if (texture_coordinates && vt_length) {
this->texture_coordinates = VRamList(texture_coordinates, vt_length);
local_normals.resize(vt_length);
memcpy(local_texture_coordinates.data(), texture_coordinates, sizeof(TextureCoordinate) * vt_length);
}
}
VertexArray::VertexArray(const std::vector<Vertex>& vertex_positions, const std::vector<unsigned int>& vertex_indices,
const std::vector<Normal>& vertex_normals, const std::vector<TextureCoordinate>& texture_coordinates) {
vertices = VRamList(vertex_positions.data(), vertex_positions.size());
local_vertices = vertex_positions;
if (!vertex_indices.empty()) {
indices = VRamList(vertex_indices.data(), vertex_indices.size());
local_indices = vertex_indices;
}
if (!vertex_normals.empty()) {
normals = VRamList(vertex_normals.data(), vertex_normals.size());
local_normals = vertex_normals;
}
if (!texture_coordinates.empty()){
this->texture_coordinates = VRamList(texture_coordinates.data(), texture_coordinates.size());
local_texture_coordinates = texture_coordinates;
}
}
bool VertexArray::Static() {
return animations.empty();
}