add exception checks to Texture::bind and GLObject::id, make collision info storage a std::optional object
This commit is contained in:
parent
c0b55752e1
commit
12e5a15d1c
57
src/Box.cpp
57
src/Box.cpp
|
@ -10,9 +10,6 @@
|
||||||
|
|
||||||
#include "Box.hpp"
|
#include "Box.hpp"
|
||||||
|
|
||||||
/* Construct a Box by giving a corner coordinate (top left if Y-axis is not inverted, bottom left otherwise) and
|
|
||||||
* size (as width, height). The invert_y argument indicates that the Y-coordinate increases from the bottom of
|
|
||||||
* the screen to the top rather than the default case where it increases from the top to the bottom. */
|
|
||||||
Box::Box(const glm::vec2& corner, const glm::vec2& size, bool invert_y)
|
Box::Box(const glm::vec2& corner, const glm::vec2& size, bool invert_y)
|
||||||
{
|
{
|
||||||
x = corner.x;
|
x = corner.x;
|
||||||
|
@ -22,11 +19,8 @@ Box::Box(const glm::vec2& corner, const glm::vec2& size, bool invert_y)
|
||||||
this->invert_y(invert_y);
|
this->invert_y(invert_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct a Box from float arguments: x, y, width, height. If invert_y is set, the Y-axis increases from bottom to
|
|
||||||
* top instead of top to bottom. */
|
|
||||||
Box::Box(float x, float y, float width, float height, bool invert_y) : Box({x, y}, {width, height}, invert_y) {}
|
Box::Box(float x, float y, float width, float height, bool invert_y) : Box({x, y}, {width, height}, invert_y) {}
|
||||||
|
|
||||||
/* Construct a Box by passing an SDL_Rect struct, which is of the form {x, y, w, h} and limited to int arguments. */
|
|
||||||
Box::Box(const SDL_Rect& rect, bool invert_y) : Box({rect.x, rect.y}, {rect.w, rect.h}, invert_y) {}
|
Box::Box(const SDL_Rect& rect, bool invert_y) : Box({rect.x, rect.y}, {rect.w, rect.h}, invert_y) {}
|
||||||
|
|
||||||
/* Set inverted Y mode to true, meaning the Y-coordinate increases from the bottom to the top, or false, meaning the
|
/* Set inverted Y mode to true, meaning the Y-coordinate increases from the bottom to the top, or false, meaning the
|
||||||
|
@ -67,13 +61,11 @@ void Box::height(float height)
|
||||||
h = std::max(height, 0.0f);
|
h = std::max(height, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the size as a vector {width, height} */
|
|
||||||
glm::vec2 Box::size() const
|
glm::vec2 Box::size() const
|
||||||
{
|
{
|
||||||
return {width(), height()};
|
return {width(), height()};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the size. Negative values will be clamped to zero. */
|
|
||||||
void Box::size(const glm::vec2& size, bool preserve_center)
|
void Box::size(const glm::vec2& size, bool preserve_center)
|
||||||
{
|
{
|
||||||
glm::vec2 center = this->center();
|
glm::vec2 center = this->center();
|
||||||
|
@ -514,36 +506,28 @@ void Box::crop(const Box& area)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if point is inside the box, false otherwise. Includes the edges, so points equal to the edges
|
|
||||||
* will return true. */
|
|
||||||
bool Box::collide(const glm::vec2& point) const
|
bool Box::collide(const glm::vec2& point) const
|
||||||
{
|
{
|
||||||
return point.x >= left() && point.x <= right() && point.y >= (inverted_y() ? bottom() : top()) && point.y <= (inverted_y() ? top() : bottom());
|
return point.x >= left() && point.x <= right() && point.y >= (inverted_y() ? bottom() : top()) && point.y <= (inverted_y() ? top() : bottom());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if the line segment intersects the box, false otherwise. If intersection is passed and there is a
|
bool Box::collide(const Segment& segment, std::optional<std::reference_wrapper<glm::vec2>> intersection) const
|
||||||
* collision, intersection will be filled with the coordinates of the first intersection found unless the segment
|
|
||||||
* is fully within the box not touching any edges. */
|
|
||||||
bool Box::collide(const Segment& segment, glm::vec2* intersection) const
|
|
||||||
{
|
{
|
||||||
/* do the faster check of whether the square represented by the segment diagonal collides to determine
|
/* Do the faster check of whether the square represented by the segment diagonal collides to determine whether to look more closely. */
|
||||||
* if we should look more closely */
|
|
||||||
if (collide(segment.box()))
|
if (collide(segment.box()))
|
||||||
{
|
{
|
||||||
/* check if segment intersects any edges, storing the intersection point if so */
|
/* Check if segment intersects any edges, storing the intersection point if so. */
|
||||||
if (segment.intersect({nw(), ne()}, intersection) ||
|
if (segment.intersect({nw(), ne()}, intersection) || segment.intersect({ne(), se()}, intersection) ||
|
||||||
segment.intersect({ne(), se()}, intersection) ||
|
segment.intersect({sw(), se()}, intersection) || segment.intersect({nw(), sw()}, intersection))
|
||||||
segment.intersect({sw(), se()}, intersection) ||
|
|
||||||
segment.intersect({nw(), sw()}, intersection))
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* check if segment is fully inside the box */
|
/* Check if segment is fully inside the box. */
|
||||||
else if (collide(segment.start()) && collide(segment.end()))
|
else if (collide(segment.start()) && collide(segment.end()))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* otherwise, segment must be outside the box even though its box has collided */
|
/* Otherwise, segment must be outside the box even though its box has collided. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -555,15 +539,7 @@ bool Box::collide(const Segment& segment, glm::vec2* intersection) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do segment collision with intersection specified by reference rather than pointer */
|
bool Box::collide(const Box& box, std::optional<std::reference_wrapper<Box>> overlap) const
|
||||||
bool Box::collide(const Segment& segment, glm::vec2& intersection) const
|
|
||||||
{
|
|
||||||
return collide(segment, &intersection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return true if box collides with the passed box, false otherwise. If overlap is passed, it is set to
|
|
||||||
* the box representing the area where the two boxes overlap. */
|
|
||||||
bool Box::collide(const Box& box, Box* overlap) const
|
|
||||||
{
|
{
|
||||||
float top, bottom, h;
|
float top, bottom, h;
|
||||||
if (inverted_y())
|
if (inverted_y())
|
||||||
|
@ -582,22 +558,17 @@ bool Box::collide(const Box& box, Box* overlap) const
|
||||||
float left = std::max(this->left(), box.left());
|
float left = std::max(this->left(), box.left());
|
||||||
float w = right - left;
|
float w = right - left;
|
||||||
bool collide = w > 0 && h > 0;
|
bool collide = w > 0 && h > 0;
|
||||||
if (collide && overlap != nullptr)
|
if (collide && overlap.has_value())
|
||||||
{
|
{
|
||||||
overlap->left(left);
|
Box& overlap_box = overlap.value();
|
||||||
overlap->top(top);
|
overlap_box.left(left);
|
||||||
overlap->width(w);
|
overlap_box.top(top);
|
||||||
overlap->height(h);
|
overlap_box.width(w);
|
||||||
|
overlap_box.height(h);
|
||||||
}
|
}
|
||||||
return collide;
|
return collide;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do a box to box collision test with overlap passed by reference instead of pointer */
|
|
||||||
bool Box::collide(const Box& box, Box& overlap) const
|
|
||||||
{
|
|
||||||
return collide(box, &overlap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the string representation of a Box "{left, top, width, height}" */
|
/* Return the string representation of a Box "{left, top, width, height}" */
|
||||||
std::string Box::string() const
|
std::string Box::string() const
|
||||||
{
|
{
|
||||||
|
|
120
src/Box.hpp
120
src/Box.hpp
|
@ -1,18 +1,20 @@
|
||||||
/* /\ +--------------------------------------------------------------+
|
/* +------------------------------------------------------+
|
||||||
____/ \____ /| - zlib/MIT/Unlicenced game framework licensed to freely use, |
|
____/ \____ /| - Open source game framework licensed to freely use, |
|
||||||
\ / / | copy, and modify without restriction |
|
\ / / | copy, modify and sell without restriction |
|
||||||
+--\ ^__^ /--+ | |
|
+--\ ^__^ /--+ | |
|
||||||
| ~/ \~ | | - originally created at [http://nugget.fun] |
|
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
|
||||||
| ~~~~~~~~~~~~ | +--------------------------------------------------------------+
|
| ~~~~~~~~~~~~ | +------------------------------------------------------+
|
||||||
| SPACE ~~~~~ | /
|
| SPACE ~~~~~ | /
|
||||||
| ~~~~~~~ BOX |/
|
| ~~~~~~~ BOX |/
|
||||||
+-------------*/
|
+-------------*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
|
|
||||||
|
@ -22,6 +24,12 @@
|
||||||
|
|
||||||
class Segment;
|
class Segment;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A ::Box object represents a rectangle, a two-dimensional four-sided polygon with two parallel sides.
|
||||||
|
*
|
||||||
|
* Rotating by three dimensions into the Z-dimension is not currently supported and must be implemented by the user,
|
||||||
|
* but 3D transformation is planned to be added in a future update.
|
||||||
|
*/
|
||||||
class Box : public SDL_FRect
|
class Box : public SDL_FRect
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -31,21 +39,66 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0}, bool = false);
|
/*!
|
||||||
Box(float, float, float, float, bool = false);
|
* Construct a Box object by giving a corner coordinate (top left if Y-axis is not inverted, bottom left otherwise) and
|
||||||
Box(const SDL_Rect&, bool = false);
|
* size (as width, height). The invert_y argument indicates that the Y-coordinate increases from the bottom of the screen
|
||||||
|
* to the top rather than the default case where it increases from the top to the bottom.
|
||||||
|
*
|
||||||
|
* @param corner top left coordinate in the x, y axis
|
||||||
|
* @param size size of the box in width and height
|
||||||
|
* @param invert_y if true, y-coordinates increase as they move up on the screen, rather than decrease
|
||||||
|
*/
|
||||||
|
Box(const glm::vec2& corner = {0, 0}, const glm::vec2& size = {0, 0}, bool invert_y = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Construct a Box object lfrom float arguments: x, y, width, height. If invert_y is set, the Y-axis increases from bottom to
|
||||||
|
* top instead of top to bottom.
|
||||||
|
*
|
||||||
|
* @see Box::Box(const glm::vec2&, const glm::vec2&, bool)
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @param width size of the x-dimension
|
||||||
|
* @param height size of the y-dimension
|
||||||
|
* @param invert_y if true, y-coordinates increase as they move up on the screen, rather than decrease
|
||||||
|
*/
|
||||||
|
Box(float x, float y, float width, float height, bool invert_y = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Construct a ::Box object by passing an SDL_Rect struct, which is of the form {x, y, w, h} and limited to int arguments.
|
||||||
|
*
|
||||||
|
* @param rect see SDL's rect documentation http://doc.here/sdlwiki/SDL_FRect.html
|
||||||
|
* @param invert_y if true, y-coordinates increase as they move up on the screen, rather than decrease
|
||||||
|
*/
|
||||||
|
Box(const SDL_Rect& rect, bool invert_y = false);
|
||||||
|
|
||||||
void invert_y(bool);
|
void invert_y(bool);
|
||||||
bool inverted_y() const;
|
bool inverted_y() const;
|
||||||
float width() const;
|
float width() const;
|
||||||
void width(float);
|
void width(float);
|
||||||
float height() const;
|
float height() const;
|
||||||
void height(float);
|
void height(float);
|
||||||
glm::vec2 size() const;
|
|
||||||
void size(const glm::vec2&, bool = false);
|
|
||||||
|
|
||||||
/* If the flag is not set, this will return width divided by height. Otherwise, it will check which side is longer and return the longer side
|
/*!
|
||||||
* divided by the shorter side. */
|
* @return the size as a vector `{width, height}`
|
||||||
float aspect(bool = false) const;
|
*/
|
||||||
|
glm::vec2 size() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Set the size. Negative values will be clamped to zero.
|
||||||
|
*
|
||||||
|
* @param size new size in width, height
|
||||||
|
* @param preserve_center if true, expand or contract the box from the center, leaving its center value unchanged
|
||||||
|
*/
|
||||||
|
void size(const glm::vec2& size, bool preserve_center = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* If the flag is not set, this will return width divided by height. Otherwise, it will check which side is longer and return the longer side
|
||||||
|
* divided by the shorter side.
|
||||||
|
*
|
||||||
|
* @param larger_ratio if true, divide by the shorter side, causing the result to always be 1.0 or greater
|
||||||
|
*/
|
||||||
|
float aspect(bool larger_ratio = false) const;
|
||||||
|
|
||||||
float area() const;
|
float area() const;
|
||||||
float top() const;
|
float top() const;
|
||||||
|
@ -92,12 +145,33 @@ public:
|
||||||
Box stamp(const glm::vec2&) const;
|
Box stamp(const glm::vec2&) const;
|
||||||
bool fits(const Box&) const;
|
bool fits(const Box&) const;
|
||||||
void crop(const Box&);
|
void crop(const Box&);
|
||||||
bool collide(const glm::vec2&) const;
|
|
||||||
bool collide(const Segment&, glm::vec2* = nullptr) const;
|
/*!
|
||||||
bool collide(const Segment&, glm::vec2&) const;
|
* Collide a 2D point with the box. Includes the edges, so points on the edges will return `true`.
|
||||||
bool collide(const Box&, Box* = nullptr) const;
|
*
|
||||||
bool collide(const Box&, Box&) const;
|
* @return `true` if point is inside the box, `false` otherwise
|
||||||
virtual std::string class_name() const { return "Box"; }
|
*/
|
||||||
|
bool collide(const glm::vec2& point) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Collide a line segment with the box. If intersection is passed and there is a collision, intersection will be filled with
|
||||||
|
* the coordinates of the first intersection found unless the segment is fully within the box not touching any edges.
|
||||||
|
*
|
||||||
|
* @param segment line segment to collide with the box
|
||||||
|
* @param intersection optional reference to 2D vector to fill with the first intersection point
|
||||||
|
* @return `true` if segment collides with the box, `false` otherwies
|
||||||
|
*/
|
||||||
|
bool collide(const Segment& segment, std::optional<std::reference_wrapper<glm::vec2>> intersection = std::nullopt) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Collide with another box object. If overlap is passed, it is set to the box representing the area where the two boxes overlap.
|
||||||
|
*
|
||||||
|
* @param box another box object to collide with
|
||||||
|
* @param overlap optional reference to a box object to be filled with the overlapping area
|
||||||
|
* @return `true` if box collides with the passed box, `false` otherwise
|
||||||
|
*/
|
||||||
|
bool collide(const Box& box, std::optional<std::reference_wrapper<Box>> overlap = std::nullopt) const;
|
||||||
|
|
||||||
std::string string() const;
|
std::string string() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -61,7 +61,14 @@ void GLObject::id(GLuint id)
|
||||||
/* Return the GL ID that was set for this object */
|
/* Return the GL ID that was set for this object */
|
||||||
GLuint GLObject::id() const
|
GLuint GLObject::id() const
|
||||||
{
|
{
|
||||||
return *object_id;
|
if (generated())
|
||||||
|
{
|
||||||
|
return *object_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot get ID for GL object that has no ID set yet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if an ID has been generated */
|
/* Returns true if an ID has been generated */
|
||||||
|
|
|
@ -129,6 +129,14 @@ void sb::Model::texture(const sb::Texture& texture)
|
||||||
textures().push_back(texture);
|
textures().push_back(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sb::Model::load()
|
||||||
|
{
|
||||||
|
for (sb::Texture& texture : textures())
|
||||||
|
{
|
||||||
|
texture.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const glm::mat4& sb::Model::transformation() const
|
const glm::mat4& sb::Model::transformation() const
|
||||||
{
|
{
|
||||||
return _transformation;
|
return _transformation;
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace sb
|
||||||
std::vector<sb::Texture>& textures();
|
std::vector<sb::Texture>& textures();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Get a constant refernce to the texture at the given index. If no index is given, get the texture at index 0. If
|
* Get a constant reference to the texture at the given index. If no index is given, get the texture at index 0. If
|
||||||
* there are no textures, an exception will be thrown.
|
* there are no textures, an exception will be thrown.
|
||||||
*
|
*
|
||||||
* @param index index of texture to get
|
* @param index index of texture to get
|
||||||
|
@ -180,6 +180,14 @@ namespace sb
|
||||||
*/
|
*/
|
||||||
void texture(const sb::Texture& texture);
|
void texture(const sb::Texture& texture);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Call the load method with no arguments on all textures attached to the model, causing them to load the image data they have
|
||||||
|
* associated with the paths previously set on them. If no textures are attached, this does nothing.
|
||||||
|
*
|
||||||
|
* @see sb::Texture::load()
|
||||||
|
*/
|
||||||
|
void load();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @return a constanst reference to the model's transformation matrix
|
* @return a constanst reference to the model's transformation matrix
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -35,8 +35,7 @@ void Segment::end(const glm::vec2& end)
|
||||||
end_ = end;
|
end_ = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
// taken from http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c
|
bool Segment::intersect(const Segment& segment, std::optional<std::reference_wrapper<glm::vec2>> intersection) const
|
||||||
bool Segment::intersect(const Segment& segment, glm::vec2* intersection) const
|
|
||||||
{
|
{
|
||||||
float x1 = start_.x, y1 = start_.y, x2 = end_.x, y2 = end_.y, x3 = segment.start_.x,
|
float x1 = start_.x, y1 = start_.y, x2 = end_.x, y2 = end_.y, x3 = segment.start_.x,
|
||||||
y3 = segment.start_.y, x4 = segment.end_.x, y4 = segment.end_.y;
|
y3 = segment.start_.y, x4 = segment.end_.x, y4 = segment.end_.y;
|
||||||
|
@ -85,24 +84,19 @@ bool Segment::intersect(const Segment& segment, glm::vec2* intersection) const
|
||||||
}
|
}
|
||||||
|
|
||||||
num = b1 * c2 - b2 * c1;
|
num = b1 * c2 - b2 * c1;
|
||||||
if (intersection != NULL)
|
if (intersection.has_value())
|
||||||
{
|
{
|
||||||
intersection->x = num / denom;
|
intersection.value().get().x = num / denom;
|
||||||
}
|
}
|
||||||
num = a2 * c1 - a1 * c2;
|
num = a2 * c1 - a1 * c2;
|
||||||
if (intersection != NULL)
|
if (intersection.has_value())
|
||||||
{
|
{
|
||||||
intersection->y = num / denom;
|
intersection.value().get().y = num / denom;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Segment::intersect(const Segment& segment, glm::vec2& intersection) const
|
|
||||||
{
|
|
||||||
return intersect(segment, &intersection);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Segment::dx() const
|
float Segment::dx() const
|
||||||
{
|
{
|
||||||
return end_.x - start_.x;
|
return end_.x - start_.x;
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "glm/vec2.hpp"
|
#include "glm/vec2.hpp"
|
||||||
|
|
||||||
|
@ -36,8 +38,19 @@ public:
|
||||||
void start(const glm::vec2&);
|
void start(const glm::vec2&);
|
||||||
glm::vec2 end() const;
|
glm::vec2 end() const;
|
||||||
void end(const glm::vec2&);
|
void end(const glm::vec2&);
|
||||||
bool intersect(const Segment&, glm::vec2* = nullptr) const;
|
|
||||||
bool intersect(const Segment&, glm::vec2&) const;
|
/*!
|
||||||
|
* Check for an intersection with another segment object. If the intersection argument is given a reference to a 2D vector,
|
||||||
|
* it will be filled with the point of intersection.
|
||||||
|
*
|
||||||
|
* Original source: http://www.realtimerendering.com/resources/GraphicsGems/gemsii/xlines.c
|
||||||
|
*
|
||||||
|
* @param segment segment to collide with
|
||||||
|
* @param intersection optional reference to a 2D vector to fill with the intersection point
|
||||||
|
* @return `true` if the two segments intersect, `false` otherwise
|
||||||
|
*/
|
||||||
|
bool intersect(const Segment& segment, std::optional<std::reference_wrapper<glm::vec2>> intersection = std::nullopt) const;
|
||||||
|
|
||||||
float dx() const;
|
float dx() const;
|
||||||
float dy() const;
|
float dy() const;
|
||||||
float length() const;
|
float length() const;
|
||||||
|
|
|
@ -11,10 +11,8 @@
|
||||||
#include "Texture.hpp"
|
#include "Texture.hpp"
|
||||||
using namespace sb;
|
using namespace sb;
|
||||||
|
|
||||||
/* Have to pass our deleter to abstract base class at instantiation */
|
|
||||||
Texture::Texture() : GLObject(texture_deleter) {}
|
Texture::Texture() : GLObject(texture_deleter) {}
|
||||||
|
|
||||||
/* If an image path is passed at creation, the path will be stored in the class for later loading */
|
|
||||||
Texture::Texture(fs::path path) : Texture()
|
Texture::Texture(fs::path path) : Texture()
|
||||||
{
|
{
|
||||||
associate(path);
|
associate(path);
|
||||||
|
@ -127,20 +125,27 @@ void Texture::load(void* pixels, glm::vec2 size, GLenum format, GLenum type)
|
||||||
|
|
||||||
void Texture::bind() const
|
void Texture::bind() const
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, this->id());
|
if (generated())
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->id());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot bind texture that has not been generated yet.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* glGetTexlevelparameteriv is not available in OpenGL ES 3.0 */
|
/* glGetTexlevelparameteriv is not available in OpenGL ES 3.0 */
|
||||||
#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(ANDROID)
|
#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !defined(ANDROID)
|
||||||
void Texture::load(void* pixels, GLenum format, GLenum type)
|
void Texture::load(void* pixels, GLenum format, GLenum type)
|
||||||
{
|
{
|
||||||
if (!generated())
|
if (generated())
|
||||||
{
|
{
|
||||||
throw std::invalid_argument("This texture has not been generated and has no size property, so a size must be provided");
|
load(pixels, size(), format, type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
load(pixels, size(), format, type);
|
throw std::invalid_argument("This texture has not been generated and has no size property, so a size must be provided");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,17 @@ namespace sb
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Construct an empty Texture. The deleter will be passed to the base sb::GLObject class.
|
||||||
|
*/
|
||||||
Texture();
|
Texture();
|
||||||
Texture(fs::path);
|
|
||||||
|
/*!
|
||||||
|
* If an image path is passed at creation, the path will be stored in the class for later loading.
|
||||||
|
*
|
||||||
|
* @param path path to an image to be used as the default texture, which will be loaded later with Texture::load()
|
||||||
|
*/
|
||||||
|
Texture(fs::path path);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Store an image path as a member variable for loading later. Each texture should have one image
|
* Store an image path as a member variable for loading later. Each texture should have one image
|
||||||
|
|
Loading…
Reference in New Issue