mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 03:29:44 -06:00
Add the ability to specify longitude and latitude subdivisions in RenderableSphericalGrid (closes #3494)
This commit is contained in:
@@ -43,12 +43,37 @@ namespace {
|
||||
openspace::properties::Property::Visibility::NoviceUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LongSegmentsInfo = {
|
||||
"LongSegments",
|
||||
"Number of Longitudinal Segments",
|
||||
"The number of longitudinal segments the sphere is split into. Determines the "
|
||||
"resolution of the rendered sphere in a left/right direction when looking "
|
||||
"straight at the equator. Should be an even value (if an odd value is provided, "
|
||||
"the value will be set to the new value minus one). If the `Segments` value is "
|
||||
"provided as well, it will have precedence over this value",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LatSegmentsInfo = {
|
||||
"LatSegments",
|
||||
"Number of Latitudinal Segments",
|
||||
"The number of latitudinal segments the sphere is split into. Determines the "
|
||||
"resolution of the rendered sphere in a up/down direction when looking "
|
||||
"straight at the equator. Should be an even value (if an odd value is provided, "
|
||||
"the value will be set to the new value minus one). If the `Segments` value is "
|
||||
"provided as well, it will have precedence over this value",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo SegmentsInfo = {
|
||||
"Segments",
|
||||
"Number of Segments",
|
||||
"The number of segments the sphere is split into. Determines the resolution "
|
||||
"of the rendered sphere. Should be an even value (if an odd value is provided, "
|
||||
"the value will be set to the new value minus one).",
|
||||
"the value will be set to the new value minus one). Setting this value is equal "
|
||||
"to setting `LongSegments` and `LatSegments` to the same value. If this value is "
|
||||
"specified, it will overwrite the values provided in `LongSegments` and "
|
||||
"`LatSegments`.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
@@ -69,6 +94,12 @@ namespace {
|
||||
// [[codegen::verbatim(ColorInfo.description)]]
|
||||
std::optional<glm::vec3> color [[codegen::color()]];
|
||||
|
||||
// [[codegen::verbatim(LongSegmentsInfo.description)]]
|
||||
std::optional<int> longSegments;
|
||||
|
||||
// [[codegen::verbatim(LatSegmentsInfo.description)]]
|
||||
std::optional<int> latSegments;
|
||||
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
std::optional<int> segments;
|
||||
|
||||
@@ -92,7 +123,8 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
|
||||
: Renderable(dictionary)
|
||||
, _gridProgram(nullptr)
|
||||
, _color(ColorInfo, glm::vec3(0.5f), glm::vec3(0.f), glm::vec3(1.f))
|
||||
, _segments(SegmentsInfo, 36, 4, 200)
|
||||
, _longSegments(LongSegmentsInfo, 36, 4, 200)
|
||||
, _latSegments(LatSegmentsInfo, 36, 4, 200)
|
||||
, _lineWidth(LineWidthInfo, 0.5f, 1.f, 20.f)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
@@ -103,14 +135,19 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
|
||||
_color.setViewOption(properties::Property::ViewOptions::Color);
|
||||
addProperty(_color);
|
||||
|
||||
_segments = p.segments.value_or(_segments);
|
||||
_segments.onChange([this]() {
|
||||
if (_segments.value() % 2 == 1) {
|
||||
_segments = _segments - 1;
|
||||
auto gridDirty = [this]() {
|
||||
if (_longSegments.value() % 2 == 1) {
|
||||
_longSegments = _longSegments - 1;
|
||||
}
|
||||
_gridIsDirty = true;
|
||||
});
|
||||
addProperty(_segments);
|
||||
};
|
||||
_longSegments = p.segments.value_or(p.longSegments.value_or(_longSegments));
|
||||
_longSegments.onChange(gridDirty);
|
||||
addProperty(_longSegments);
|
||||
|
||||
_latSegments = p.segments.value_or(p.latSegments.value_or(_latSegments));
|
||||
_latSegments.onChange(gridDirty);
|
||||
addProperty(_latSegments);
|
||||
|
||||
_lineWidth = p.lineWidth.value_or(_lineWidth);
|
||||
addProperty(_lineWidth);
|
||||
@@ -193,9 +230,10 @@ void RenderableSphericalGrid::render(const RenderData& data, RendererTasks&) {
|
||||
// Change GL state:
|
||||
#ifndef __APPLE__
|
||||
glLineWidth(_lineWidth);
|
||||
#else
|
||||
#else // ^^^^ __APPLE__ // !__APPLE__ vvvv
|
||||
glLineWidth(1.f);
|
||||
#endif
|
||||
#endif // __APPLE__
|
||||
|
||||
glEnablei(GL_BLEND, 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
@@ -203,7 +241,7 @@ void RenderableSphericalGrid::render(const RenderData& data, RendererTasks&) {
|
||||
|
||||
glBindVertexArray(_vaoID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
|
||||
glDrawElements(_mode, _isize, GL_UNSIGNED_INT, nullptr);
|
||||
glDrawElements(GL_LINES, 6 * _longSegments * _latSegments, GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
|
||||
_gridProgram->deactivate();
|
||||
@@ -222,14 +260,14 @@ void RenderableSphericalGrid::render(const RenderData& data, RendererTasks&) {
|
||||
|
||||
const glm::dmat4 worldToModelTransform = glm::inverse(modelTransform);
|
||||
glm::vec3 orthoRight = glm::normalize(
|
||||
glm::vec3(worldToModelTransform * glm::vec4(right, 0.0))
|
||||
glm::vec3(worldToModelTransform * glm::vec4(right, 0.f))
|
||||
);
|
||||
|
||||
if (orthoRight == glm::vec3(0.0)) {
|
||||
if (orthoRight == glm::vec3(0.f)) {
|
||||
const glm::vec3 otherVector = glm::vec3(lookup.y, lookup.x, lookup.z);
|
||||
right = glm::cross(viewDirection, otherVector);
|
||||
orthoRight = glm::normalize(
|
||||
glm::vec3(worldToModelTransform * glm::vec4(right, 0.0))
|
||||
glm::vec3(worldToModelTransform * glm::vec4(right, 0.f))
|
||||
);
|
||||
}
|
||||
const glm::vec3 orthoUp = glm::normalize(
|
||||
@@ -244,28 +282,21 @@ void RenderableSphericalGrid::update(const UpdateData&) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isize = 6 * _segments * _segments;
|
||||
_vsize = (_segments + 1) * (_segments + 1);
|
||||
_varray.resize(_vsize);
|
||||
constexpr Vertex v = { 0.f, 0.f, 0.f };
|
||||
std::fill(_varray.begin(), _varray.end(), v);
|
||||
_iarray.resize(_isize);
|
||||
std::fill(_iarray.begin(), _iarray.end(), 0);
|
||||
unsigned int vertSize = (_longSegments + 1) * (_latSegments + 1);
|
||||
std::vector<Vertex> vert = std::vector<Vertex>(vertSize, { 0.f, 0.f, 0.f });
|
||||
unsigned int idxSize = 6 * _longSegments * _latSegments;
|
||||
std::vector<int> idx = std::vector<int>(idxSize, 0);
|
||||
|
||||
int nr = 0;
|
||||
const float fsegments = static_cast<float>(_segments);
|
||||
|
||||
for (int nSegment = 0; nSegment <= _segments; ++nSegment) {
|
||||
for (int lat = 0; lat <= _latSegments; ++lat) {
|
||||
// define an extra vertex around the y-axis due to texture mapping
|
||||
for (int j = 0; j <= _segments; j++) {
|
||||
const float fi = static_cast<float>(nSegment);
|
||||
const float fj = static_cast<float>(j);
|
||||
|
||||
for (int lng = 0; lng <= _longSegments; lng++) {
|
||||
// inclination angle (north to south)
|
||||
const float theta = fi * glm::pi<float>() / fsegments * 2.f; // 0 -> PI
|
||||
const float theta = lat * glm::pi<float>() / _latSegments * 2.f; // 0 -> PI
|
||||
|
||||
// azimuth angle (east to west)
|
||||
const float phi = fj * glm::pi<float>() * 2.0f / fsegments; // 0 -> 2*PI
|
||||
const float phi = lng * 2.f * glm::pi<float>() / _longSegments; // 0 -> 2*PI
|
||||
|
||||
const float x = std::sin(phi) * std::sin(theta); //
|
||||
const float y = std::cos(theta); // up
|
||||
@@ -276,7 +307,7 @@ void RenderableSphericalGrid::update(const UpdateData&) {
|
||||
normal = glm::normalize(normal);
|
||||
}
|
||||
|
||||
glm::vec4 tmp(x, y, z, 1.f);
|
||||
glm::vec4 tmp = glm::vec4(x, y, z, 1.f);
|
||||
const glm::mat4 rot = glm::rotate(
|
||||
glm::mat4(1.f),
|
||||
glm::half_pi<float>(),
|
||||
@@ -285,41 +316,35 @@ void RenderableSphericalGrid::update(const UpdateData&) {
|
||||
tmp = glm::vec4(glm::dmat4(rot) * glm::dvec4(tmp));
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
_varray[nr].location[i] = tmp[i];
|
||||
vert[nr].location[i] = tmp[i];
|
||||
}
|
||||
++nr;
|
||||
}
|
||||
}
|
||||
|
||||
nr = 0;
|
||||
// define indices for all triangles
|
||||
for (int i = 1; i <= _segments; i++) {
|
||||
for (int j = 0; j < _segments; j++) {
|
||||
const int t = _segments + 1;
|
||||
_iarray[nr] = t * (i - 1) + j + 0; ++nr;
|
||||
_iarray[nr] = t * (i + 0) + j + 0; ++nr;
|
||||
_iarray[nr] = t * (i + 0) + j + 1; ++nr;
|
||||
_iarray[nr] = t * (i - 1) + j + 1; ++nr;
|
||||
_iarray[nr] = t * (i - 1) + j + 0; ++nr;
|
||||
for (int i = 1; i <= _latSegments; i++) {
|
||||
for (int j = 0; j < _longSegments; j++) {
|
||||
const int t = _longSegments + 1;
|
||||
idx[nr] = t * (i - 1) + j + 0; ++nr;
|
||||
idx[nr] = t * (i + 0) + j + 0; ++nr;
|
||||
idx[nr] = t * (i + 0) + j + 1; ++nr;
|
||||
idx[nr] = t * (i - 1) + j + 1; ++nr;
|
||||
idx[nr] = t * (i - 1) + j + 0; ++nr;
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(_vaoID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
_vsize * sizeof(Vertex),
|
||||
_varray.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, vertSize * sizeof(Vertex), vert.data(), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
|
||||
glBufferData(
|
||||
GL_ELEMENT_ARRAY_BUFFER,
|
||||
_isize * sizeof(int),
|
||||
_iarray.data(),
|
||||
GL_STATIC_DRAW
|
||||
idxSize * sizeof(int),
|
||||
idx.data(), GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
_gridIsDirty = false;
|
||||
|
||||
Reference in New Issue
Block a user