update math and misc functions
This commit is contained in:
@@ -42,21 +42,22 @@ namespace math
|
||||
{
|
||||
}
|
||||
|
||||
aabb::aabb(std::vector<glm::vec3> points)
|
||||
aabb::aabb(std::vector<glm::vec3> const& points)
|
||||
: aabb(min_per_dimension(points), max_per_dimension(points))
|
||||
{
|
||||
assert(!points.empty());
|
||||
}
|
||||
|
||||
//! \todo Optimize: iterate lazily.
|
||||
std::vector<glm::vec3> aabb::all_corners() const
|
||||
std::array<glm::vec3, 8> aabb::all_corners() const
|
||||
{
|
||||
return box_points(min, max);
|
||||
}
|
||||
|
||||
|
||||
std::vector<glm::vec3> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max)
|
||||
std::array<glm::vec3, 8> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max)
|
||||
{
|
||||
return std::vector<glm::vec3> {
|
||||
return std::array<glm::vec3, 8> {
|
||||
glm::vec3(box_max.x, box_max.y, box_max.z),
|
||||
glm::vec3(box_max.x, box_max.y, box_min.z),
|
||||
glm::vec3(box_max.x, box_min.y, box_max.z),
|
||||
@@ -67,4 +68,25 @@ namespace math
|
||||
glm::vec3(box_min.x, box_min.y, box_min.z)
|
||||
};
|
||||
}
|
||||
|
||||
aabb_2d::aabb_2d(std::vector<glm::vec2> const& points)
|
||||
{
|
||||
assert(!points.empty());
|
||||
|
||||
min = glm::vec2(
|
||||
std::numeric_limits<float>::max(),
|
||||
std::numeric_limits<float>::max()
|
||||
);
|
||||
|
||||
max = glm::vec2(
|
||||
std::numeric_limits<float>::lowest(),
|
||||
std::numeric_limits<float>::lowest()
|
||||
);
|
||||
|
||||
for (auto const& point : points)
|
||||
{
|
||||
min = glm::min(min, point);
|
||||
max = glm::max(max, point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,20 +3,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
namespace math
|
||||
{
|
||||
struct aabb
|
||||
{
|
||||
aabb(glm::vec3 const& min_, glm::vec3 const& max_);
|
||||
aabb(std::vector<glm::vec3> points);
|
||||
aabb(std::vector<glm::vec3> const& points);
|
||||
|
||||
std::vector<glm::vec3> all_corners() const;
|
||||
std::array<glm::vec3, 8> all_corners() const;
|
||||
|
||||
glm::vec3 min;
|
||||
glm::vec3 max;
|
||||
};
|
||||
|
||||
std::vector<glm::vec3> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max);
|
||||
std::array<glm::vec3, 8> box_points(glm::vec3 const& box_min, glm::vec3 const& box_max);
|
||||
|
||||
// 2d bounding box, aka square
|
||||
struct aabb_2d
|
||||
{
|
||||
aabb_2d(std::vector<glm::vec2> const& points);
|
||||
|
||||
// std::array<glm::vec2, 4> all_corners() const;
|
||||
|
||||
glm::vec2 min;
|
||||
glm::vec2 max;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
|
||||
#include "coordinates.hpp"
|
||||
|
||||
#include <noggit/MapHeaders.h>
|
||||
|
||||
namespace math
|
||||
{
|
||||
void to_client(glm::vec3& vector)
|
||||
{
|
||||
float x = vector.x;
|
||||
vector.x = -vector.y + ZEROPOINT;
|
||||
vector.y = vector.z;
|
||||
vector.z = -x + ZEROPOINT;
|
||||
}
|
||||
|
||||
void to_client(float vector[3])
|
||||
{
|
||||
float x = vector[0];
|
||||
vector[0] = -vector[1] + ZEROPOINT;
|
||||
vector[1] = vector[2];
|
||||
vector[2] = -x + ZEROPOINT;
|
||||
}
|
||||
|
||||
void to_server(glm::vec3& vector)
|
||||
{
|
||||
float x = vector.x;
|
||||
vector.x = ZEROPOINT - vector.z;
|
||||
vector.z = vector.y;
|
||||
vector.y = ZEROPOINT - x;
|
||||
}
|
||||
|
||||
void to_server(float vector[3])
|
||||
{
|
||||
float x = vector[0];
|
||||
vector[0] = ZEROPOINT - vector[2];
|
||||
vector[2] = vector[1];
|
||||
vector[1] = ZEROPOINT - x;
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
#include <noggit/MapHeaders.h>
|
||||
|
||||
namespace math
|
||||
{
|
||||
void to_client(glm::vec3& vector);
|
||||
void to_client(float vector[3]);
|
||||
|
||||
void to_server(glm::vec3& vector);
|
||||
void to_server(float vector[3]);
|
||||
inline void to_client(glm::vec3& vector)
|
||||
{
|
||||
float x = vector.x;
|
||||
vector.x = -vector.y + ZEROPOINT;
|
||||
vector.y = vector.z;
|
||||
vector.z = -x + ZEROPOINT;
|
||||
}
|
||||
|
||||
inline void to_client(float vector[3])
|
||||
{
|
||||
float x = vector[0];
|
||||
vector[0] = -vector[1] + ZEROPOINT;
|
||||
vector[1] = vector[2];
|
||||
vector[2] = -x + ZEROPOINT;
|
||||
}
|
||||
|
||||
inline void to_server(glm::vec3& vector)
|
||||
{
|
||||
float x = vector.x;
|
||||
vector.x = ZEROPOINT - vector.z;
|
||||
vector.z = vector.y;
|
||||
vector.y = ZEROPOINT - x;
|
||||
}
|
||||
|
||||
inline void to_server(float vector[3])
|
||||
{
|
||||
float x = vector[0];
|
||||
vector[0] = ZEROPOINT - vector[2];
|
||||
vector[2] = vector[1];
|
||||
vector[1] = ZEROPOINT - x;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <glm/common.hpp>
|
||||
#include <glm/trigonometric.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/ext/scalar_constants.hpp>
|
||||
|
||||
namespace math
|
||||
@@ -82,10 +84,60 @@ namespace math
|
||||
*y = xa * glm::sin(angle._) + ya * glm::cos(angle._) + y0;
|
||||
}
|
||||
|
||||
inline bool is_inside_of(const glm::vec3& pos, const glm::vec3& a, const glm::vec3& b)
|
||||
// inside of axis aligned box
|
||||
inline bool is_inside_of_aabb(const glm::vec3& pos, const glm::vec3& a, const glm::vec3& b)
|
||||
{
|
||||
return a.x < pos.x&& b.x > pos.x
|
||||
&& a.y < pos.y&& b.y > pos.y
|
||||
&& a.z < pos.z&& b.z > pos.z;
|
||||
}
|
||||
|
||||
// if a point is in a rectangle in 2D space
|
||||
inline bool is_inside_of_aabb_2d(const glm::vec2& pos, const glm::vec2& a, const glm::vec2& b)
|
||||
{
|
||||
return a.x < pos.x && b.x > pos.x
|
||||
&& a.y < pos.y && b.y > pos.y;
|
||||
}
|
||||
|
||||
// check if a rectangle intersects with another in 2D space
|
||||
inline bool boxIntersects(const glm::vec2& minA, const glm::vec2& maxA, const glm::vec2& minB, const glm::vec2& maxB)
|
||||
{
|
||||
// Check if one box is to the left or right of the other
|
||||
if (minA.x > maxB.x || minB.x > maxA.x)
|
||||
return false;
|
||||
|
||||
// Check if one box is above or below the other
|
||||
if (minA.y > maxB.y || minB.y > maxA.y)
|
||||
return false;
|
||||
|
||||
// The boxes intersect
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_inside_of_polygon(const glm::vec2& pos, const std::vector<glm::vec2>& polygon);
|
||||
|
||||
// bool is_inside_of_polygon(const glm::vec2& pos, const std::vector<glm::vec2>& polygon) {
|
||||
// int n = polygon.size();
|
||||
// bool inside = false;
|
||||
//
|
||||
// // Iterate through each edge of the polygon
|
||||
// for (int i = 0; i < n; ++i) {
|
||||
// // Get the current vertex and the next vertex (looping back to the start)
|
||||
// glm::vec2 v1 = polygon[i];
|
||||
// glm::vec2 v2 = polygon[(i + 1) % n];
|
||||
//
|
||||
// // Check if the point is within the y-bounds of the edge
|
||||
// if ((v1.y > pos.y) != (v2.y > pos.y)) {
|
||||
// // Compute the x-coordinate of the intersection point
|
||||
// float intersectX = (pos.y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y) + v1.x;
|
||||
//
|
||||
// // Check if the intersection point is to the right of the point
|
||||
// if (pos.x < intersectX) {
|
||||
// inside = !inside;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return inside;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Noggit
|
||||
, _roll (0.0f)
|
||||
, _yaw (0.f)
|
||||
, _pitch (0.f)
|
||||
, _fov (math::degrees (54.f))
|
||||
, _fov (math::degrees (54.f)) // this seems to be vertical FOV. 60 degrees vertical FOV equals 91.49 horizontal FOV in 16:9
|
||||
{
|
||||
//! \note ensure ranges
|
||||
yaw (yaw_);
|
||||
|
||||
@@ -398,12 +398,12 @@ bool MapTile::isTile(int pX, int pZ)
|
||||
|
||||
float MapTile::getMaxHeight()
|
||||
{
|
||||
return _extents[1].y;
|
||||
return getExtents()[1].y;
|
||||
}
|
||||
|
||||
float MapTile::getMinHeight()
|
||||
{
|
||||
return _extents[0].y;
|
||||
return getExtents()[0].y;
|
||||
}
|
||||
|
||||
void MapTile::forceRecalcExtents()
|
||||
|
||||
@@ -160,8 +160,8 @@ public:
|
||||
void recalcExtents();
|
||||
void recalcObjectInstanceExtents();
|
||||
void recalcCombinedExtents();
|
||||
std::array<glm::vec3, 2>& getExtents() { return _extents; };
|
||||
std::array<glm::vec3, 2>& getCombinedExtents() { return _combined_extents; };
|
||||
std::array<glm::vec3, 2>& getExtents() { recalcExtents(); return _extents; };
|
||||
std::array<glm::vec3, 2>& getCombinedExtents() { recalcCombinedExtents(); return _combined_extents; };
|
||||
|
||||
World* getWorld() { return _world; };
|
||||
|
||||
|
||||
@@ -4231,12 +4231,28 @@ void MapView::onSettingsSave()
|
||||
_camera.fov(math::degrees(_settings->value("fov", 54.f).toFloat()));
|
||||
_debug_cam.fov(math::degrees(_settings->value("fov", 54.f).toFloat()));
|
||||
|
||||
int _fps_limit = _settings->value("fps_limit", 60).toInt();
|
||||
int _frametime = static_cast<int>((1.f / static_cast<float>(_fps_limit)) * 1000.f);
|
||||
// _update_every_event_loop.start(_frametime);
|
||||
_update_every_event_loop.setInterval(_frametime);
|
||||
|
||||
bool vsync = _settings->value("vsync", false).toBool();
|
||||
format().setSwapInterval(vsync ? 1
|
||||
: Noggit::Application::NoggitApplication::instance()->getConfiguration()->GraphicsConfiguration.SwapChainInternal);
|
||||
|
||||
bool doAntiAliasing = _settings->value("anti_aliasing", false).toBool();
|
||||
format().setSamples(doAntiAliasing ? 4
|
||||
: Noggit::Application::NoggitApplication::instance()->getConfiguration()->GraphicsConfiguration.SamplesCount);
|
||||
|
||||
// force updating rendering
|
||||
_camera_moved_since_last_draw = true;
|
||||
|
||||
}
|
||||
|
||||
void MapView::ShowContextMenu(QPoint pos)
|
||||
{
|
||||
// QApplication::startDragDistance() is 10
|
||||
auto mouse_moved = (QApplication::startDragDistance() / 5) < (_right_click_pos - pos).manhattanLength();
|
||||
bool mouse_moved = (QApplication::startDragDistance() / 5) < (_right_click_pos - pos).manhattanLength();
|
||||
|
||||
// don't show context menu if dragging mouse
|
||||
if (mouse_moved || ImGuizmo::IsUsing())
|
||||
|
||||
@@ -27,6 +27,80 @@ namespace misc
|
||||
point.x <= extents[1].x && point.y <= extents[1].y;
|
||||
}
|
||||
|
||||
// project 3D point to 2d screen space.
|
||||
// Note : When working with noggit 3D coords, need to swap Y and Z !
|
||||
glm::vec4 projectPointToScreen(const glm::vec3& point, const glm::mat4& VPmatrix, float viewport_width, float viewport_height, bool& valid)
|
||||
{
|
||||
glm::vec4 clipSpacePos = VPmatrix * glm::vec4(point, 1.0f);
|
||||
|
||||
if (clipSpacePos.w <= 0.0f)
|
||||
{
|
||||
valid = false; // not valid, point is behind camera
|
||||
return clipSpacePos;
|
||||
}
|
||||
|
||||
// Perspective division to move to normalized device coordinates (NDC)
|
||||
float ndcX = clipSpacePos.x / clipSpacePos.w;
|
||||
float ndcY = clipSpacePos.y / clipSpacePos.w;
|
||||
float ndcZ = clipSpacePos.z / clipSpacePos.w;
|
||||
|
||||
// If the point is out of the normalized device coordinates range, it's off-screen
|
||||
if (ndcX < -1.0f || ndcX > 1.0f || ndcY < -1.0f || ndcY > 1.0f)
|
||||
{
|
||||
valid = false;
|
||||
return glm::vec4(-1.0f, -1.0f, -1.0f, -1.0f);
|
||||
}
|
||||
|
||||
// Convert NDC to screen space coordinates
|
||||
clipSpacePos.x = (ndcX + 1.0f) * 0.5f * viewport_width;
|
||||
clipSpacePos.y = (1.0f - (ndcY + 1.0f) * 0.5f) * viewport_height;
|
||||
|
||||
valid = true;
|
||||
return clipSpacePos;
|
||||
}
|
||||
|
||||
std::array<glm::vec2, 2> getAABBScreenBounds(const std::array<glm::vec3, 2>& extents
|
||||
, const glm::mat4& VPmatrix
|
||||
, float viewport_width
|
||||
, float viewport_height
|
||||
, bool& valid
|
||||
, float scale)
|
||||
{
|
||||
math::aabb obj_aabb(extents[0], extents[1]);
|
||||
auto corners = obj_aabb.all_corners();
|
||||
|
||||
glm::vec2 minScreen = glm::vec2(std::numeric_limits<float>::max());
|
||||
glm::vec2 maxScreen = glm::vec2(std::numeric_limits<float>::lowest());
|
||||
|
||||
for (const auto& corner : corners)
|
||||
{
|
||||
bool point_valid;
|
||||
const glm::vec4 screenPos = projectPointToScreen(corner, VPmatrix, viewport_width, viewport_height, point_valid);
|
||||
|
||||
if (!point_valid)
|
||||
{
|
||||
valid = false; // one point was outside of screen space
|
||||
return { glm::vec2(0.0f), glm::vec2(0.0f) };
|
||||
}
|
||||
|
||||
// Update min and max screen bounds if the point is valid (within screen space)
|
||||
minScreen = glm::min(minScreen, glm::vec2(screenPos.x, screenPos.y));
|
||||
maxScreen = glm::max(maxScreen, glm::vec2(screenPos.x, screenPos.y));
|
||||
}
|
||||
valid = true;
|
||||
|
||||
if (scale != 1.0f)
|
||||
{
|
||||
glm::vec2 center = (minScreen + maxScreen) * 0.5f;
|
||||
glm::vec2 halfSize = (maxScreen - minScreen) * 0.5f * scale;
|
||||
|
||||
minScreen = center - halfSize;
|
||||
maxScreen = center + halfSize;
|
||||
}
|
||||
|
||||
return { minScreen, maxScreen };
|
||||
}
|
||||
|
||||
void minmax(glm::vec3* a, glm::vec3* b)
|
||||
{
|
||||
if (a->x > b->x)
|
||||
|
||||
@@ -56,6 +56,15 @@ namespace misc
|
||||
bool vec3d_equals(glm::vec3 const& v1, glm::vec3 const& v2);
|
||||
bool deg_vec3d_equals(math::degrees::vec3 const& v1, math::degrees::vec3 const& v2);
|
||||
|
||||
glm::vec4 projectPointToScreen(const glm::vec3& point, const glm::mat4& VPmatrix, float viewport_width, float viewport_height, bool& valid);
|
||||
|
||||
std::array<glm::vec2, 2> getAABBScreenBounds(const std::array<glm::vec3, 2>& extents
|
||||
, const glm::mat4& VPmatrix
|
||||
, float viewport_width
|
||||
, float viewport_height
|
||||
, bool& valid
|
||||
, float scale = 1.0f);
|
||||
|
||||
bool pointInside(glm::vec3 point, std::array<glm::vec3, 2> const& extents);
|
||||
bool pointInside(glm::vec2 point, std::array<glm::vec2, 2> const& extents);
|
||||
void minmax(glm::vec3* a, glm::vec3* b);
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
void setType(int type, size_t layer);
|
||||
int getType(size_t layer);
|
||||
|
||||
std::array<glm::vec3, 2>& getExtents() { return _extents; };
|
||||
std::array<glm::vec3, 2>& getExtents() { if (needsUpdate()){ recalcExtents(); } return _extents; };
|
||||
|
||||
[[nodiscard]]
|
||||
bool isVisible(const math::frustum& frustum) const;
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Noggit::Rendering
|
||||
GLuint const& _box_vbo = _buffers[2];
|
||||
|
||||
GLuint _bone_matrices_buf_tex;
|
||||
std::vector<glm::vec3> _vertex_box_points;
|
||||
std::array<glm::vec3, 8> _vertex_box_points;
|
||||
std::vector<ModelRenderPass> _render_passes;
|
||||
|
||||
bool _uploaded = false;
|
||||
|
||||
@@ -447,7 +447,7 @@ void TileRender::doTileOcclusionQuery(OpenGL::Scoped::use_program& occlusion_sha
|
||||
|
||||
_tile_occlusion_query_in_use = true;
|
||||
gl.beginQuery(GL_ANY_SAMPLES_PASSED, _tile_occlusion_query);
|
||||
occlusion_shader.uniform("aabb", _map_tile->_combined_extents.data(), _map_tile->_combined_extents.size());
|
||||
occlusion_shader.uniform("aabb", _map_tile->getCombinedExtents().data(), _map_tile->getCombinedExtents().size());
|
||||
gl.drawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, nullptr);
|
||||
gl.endQuery(GL_ANY_SAMPLES_PASSED);
|
||||
}
|
||||
@@ -465,7 +465,7 @@ bool TileRender::getTileOcclusionQueryResult(glm::vec3 const& camera)
|
||||
if (!_uploaded)
|
||||
return !_tile_occluded;
|
||||
|
||||
if (misc::pointInside(camera, _map_tile->_combined_extents))
|
||||
if (misc::pointInside(camera, _map_tile->getCombinedExtents()))
|
||||
{
|
||||
_tile_occlusion_query_in_use = false;
|
||||
return true;
|
||||
|
||||
@@ -115,7 +115,7 @@ bool WMORender::drawSkybox(const glm::mat4x4& model_view, const glm::vec3& camer
|
||||
glm::vec3 aabb_max,
|
||||
const std::map<int, std::pair<glm::vec3, glm::vec3>>& group_extents) const
|
||||
{
|
||||
if (!_wmo->skybox || !math::is_inside_of(camera_pos,aabb_min, aabb_max))
|
||||
if (!_wmo->skybox || !math::is_inside_of_aabb(camera_pos,aabb_min, aabb_max))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -131,7 +131,7 @@ bool WMORender::drawSkybox(const glm::mat4x4& model_view, const glm::vec3& camer
|
||||
|
||||
auto& extent(group_extents.at(i));
|
||||
|
||||
if (math::is_inside_of(camera_pos, extent.first, extent.second))
|
||||
if (math::is_inside_of_aabb(camera_pos, extent.first, extent.second))
|
||||
{
|
||||
ModelInstance sky(_wmo->skybox.value()->file_key().filepath(), _wmo->_context);
|
||||
sky.pos = camera_pos;
|
||||
|
||||
@@ -1457,7 +1457,7 @@ void TextureSet::updateDoodadMapping()
|
||||
int higher_count = 0;
|
||||
int lower_count = 0;
|
||||
std::array<std::array<std::uint8_t, 8>, 8> blizzard_mapping_readable;
|
||||
bool debug_test = true;
|
||||
bool debug_test = false;
|
||||
if (debug_test)
|
||||
blizzard_mapping_readable = getDoodadMappingReadable();
|
||||
|
||||
|
||||
@@ -417,11 +417,11 @@ void AssetBrowserWidget::updateModelData()
|
||||
{
|
||||
_model->clear();
|
||||
Model::TreeManager tree_mgr = Model::TreeManager(_model);
|
||||
for (auto& key_pair : Noggit::Application::NoggitApplication::instance()->clientData()->listfile()->pathToFileDataIDMap())
|
||||
for (auto const& key_pair : Noggit::Application::NoggitApplication::instance()->clientData()->listfile()->pathToFileDataIDMap())
|
||||
{
|
||||
std::string const& filename = key_pair.first;
|
||||
// std::string const& filename = key_pair.first;
|
||||
|
||||
QString q_path = QString(filename.c_str());
|
||||
QString const q_path = QString(key_pair.first.c_str());
|
||||
|
||||
if (!( (ui->checkBox_WMOs->isChecked() && q_path.endsWith(".wmo") && !_wmo_group_and_lod_regex.match(q_path).hasMatch())
|
||||
|| (ui->checkBox_M2s->isChecked() && q_path.endsWith(".m2"))
|
||||
@@ -431,7 +431,7 @@ void AssetBrowserWidget::updateModelData()
|
||||
if (!validateBrowseMode(q_path))
|
||||
continue;
|
||||
|
||||
tree_mgr.addItem(filename.c_str());
|
||||
tree_mgr.addItem(q_path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -278,6 +278,14 @@ namespace OpenGL
|
||||
|
||||
gl.uniform3fv (loc, static_cast<GLsizei>(value.size()), glm::value_ptr(value[0]));
|
||||
}
|
||||
void use_program::uniform(std::string const& name, std::array<glm::vec3, 8> const& value)
|
||||
{
|
||||
GLuint loc = uniform_location(name);
|
||||
if (loc < 0)
|
||||
return;
|
||||
|
||||
gl.uniform3fv(loc, static_cast<GLsizei>(8), glm::value_ptr(value[0]));
|
||||
}
|
||||
void use_program::uniform(std::string const& name, std::vector<glm::vec4> const& value)
|
||||
{
|
||||
GLuint loc = uniform_location(name);
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace OpenGL
|
||||
void uniform (std::string const& name, bool);
|
||||
void uniform (GLint pos, bool);
|
||||
void uniform (std::string const& name, std::vector<glm::vec3> const& value);
|
||||
void uniform(std::string const& name, std::array<glm::vec3, 8> const& value);
|
||||
void uniform (GLint pos, std::vector<glm::vec3> const& value);
|
||||
void uniform(std::string const& name, std::vector<glm::vec4> const& value);
|
||||
void uniform(GLint pos, std::vector<glm::vec4> const& value);
|
||||
|
||||
Reference in New Issue
Block a user