Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ target_link_libraries(hexgrid mathplot_examples)
add_executable(hexgrid_transforms hexgrid_transforms.cpp)
target_link_libraries(hexgrid_transforms mathplot_examples)

add_executable(hexgrid_boundary hexgrid_boundary.cpp)
target_link_libraries(hexgrid_boundary mathplot_examples)

add_executable(hexgrid_fft hexgrid_fft.cpp)
target_link_libraries(hexgrid_fft mathplot_examples)

Expand Down
72 changes: 72 additions & 0 deletions examples/hexgrid_boundary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* An example mplot::Visual scene, containing hexgrid with boundary shown
*/

#include <iostream>
#include <memory>
#include <vector>
#include <cmath>

import sm.vec;
import sm.hexgrid;

import mplot.visual;
import mplot.visualdatamodel;
import mplot.hexgridvisual;

int main()
{
// Contructor args are width, height, title
mplot::Visual<mplot::gl::version_4_1> v(1600, 1000, "mplot::HexGridVisual");
v.fov = 15;
//v.rotateAboutNearest (true);

sm::hexgrid<float, sm::hexalign::point_up> hg1(0.01f, 0.205f, 0.0f);
hg1.set_circular_boundary (0.1f);
//hg1.set_boundary_on_outer_edge();

// Make some dummy data (a sine wave) to make an interesting surface
std::vector<float> data1(hg1.num(), 0.0f);
for (unsigned int ri = 0; ri < hg1.num(); ++ri) {
data1[ri] = 0.05f + 0.05f * std::sin (20.0f * hg1.d_x[ri]) * std::sin (10.0f * hg1.d_y[ri]) ; // Range 0->1
}

// sm::HexVisMode::HexInterp to see the hexagons or sm::HexVisMode::Triangles for a smoother surface plot
const mplot::HexVisMode visMode = mplot::HexVisMode::HexInterp;

sm::vec<float, 3> offset = { 0.0f, -0.05f, 0.0f };
auto hgv1 = std::make_unique<mplot::HexGridVisual<float, sm::hexalign::point_up, mplot::gl::version_4_1>>(&hg1, offset);
hgv1->set_parent (v.get_id());
hgv1->cm.setType (mplot::ColourMapType::Ice);
hgv1->showboundary = true;
hgv1->setScalarData (&data1);
hgv1->hexVisMode = visMode;
hgv1->zScale.null_scaling();
hgv1->addLabel ("Boundary of hexalign::point_up", sm::vec<>{ -hg1.width()/2.1f, -hg1.width()/1.6f }, mplot::TextFeatures(0.02f));
hgv1->finalize();
v.addVisualModel (hgv1);

sm::hexgrid<float, sm::hexalign::point_up> hg2(0.01f, 0.205f, 0.0f);
hg2.set_circular_boundary (0.1f);

sm::mat<float, 2> rotn;
rotn.rotate (sm::mathconst<float>::pi_over_4);

hg2.transform (rotn);

offset[0] += 0.3f;
auto hgv2 = std::make_unique<mplot::HexGridVisual<float, sm::hexalign::point_up, mplot::gl::version_4_1>>(&hg2, offset);
hgv2->set_parent (v.get_id());
hgv2->cm.setType (mplot::ColourMapType::Plasma);
hgv2->showboundary = true;
hgv2->setScalarData (&data1);
hgv2->hexVisMode = visMode;
hgv2->zScale.null_scaling();
hgv2->addLabel ("Boundary of transformed hexgrid", sm::vec<>{ -hg2.width()/2.1f, -hg2.width()/1.6f }, mplot::TextFeatures(0.02f));
hgv2->finalize();
v.addVisualModel (hgv2);

v.keepOpen();

return 0;
}
1 change: 1 addition & 0 deletions examples/hexgrid_image_fft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <iostream>
#include <string>
#include <complex>
#include <cstdint>

import sm.vec;
import sm.vvec;
Expand Down
1 change: 1 addition & 0 deletions examples/obb_collisions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <stdexcept>
#include <string>
#include <memory>
#include <cstdint>

import sm.vec;
import sm.quaternion;
Expand Down
2 changes: 1 addition & 1 deletion maths
94 changes: 69 additions & 25 deletions mplot/HexGridVisual.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,6 @@ export namespace mplot
//! something, so that it is visible.
void markHex (std::uint32_t hi) { this->markedHexes.insert(hi); }

void set_zoom (const float factor)
{
this->tfm = (sm::mat<float, 3>::identity() * factor) * this->tfm;
}

void reflect_lr()
{
this->tfm = sm::mat<float, 3>::reflection(sm::vec<float>::ux()) * this->tfm;
}

//! scalar 'zoom' has been replaced with a transform matrix to allow zoom, but also flip or rotate
sm::mat<float, 3> tfm;

//! Show a set of hexes at the zero?
bool zerogrid = false;

Expand Down Expand Up @@ -257,15 +244,15 @@ export namespace mplot
// mapping of the 2D hexgrid onto a 3D manifold.
if (this->dataCoords == nullptr) {
sm::vec<T, 3> crd = { this->hg->d_x[hi], this->hg->d_y[hi], this->dcopy[hi] };
sm::vec<float, 3> p = this->tfm * crd.template as<float>();
sm::vec<float, 3> p = crd.template as<float>();
if (update == false) {
this->vertexPositions[hi * 3] = p[0];
this->vertexPositions[hi * 3 + 1] = p[1];
}
this->vertexPositions[hi * 3 + 2] = p[2];

} else { // Otherwise use the positions directly in the hexgrid:
sm::vec<float, 3> p = this->tfm * (*this->dataCoords)[hi]; // sm::vec<float, 3>{ (*this->dataCoords)[hi][0], (*this->dataCoords)[hi][1], (*this->dataCoords)[hi][2] };
const sm::vec<float, 3> p = (*this->dataCoords)[hi];
if (update == false) {
this->vertexPositions[hi * 3] = p[0];
this->vertexPositions[hi * 3 + 1] = p[1];
Expand Down Expand Up @@ -310,6 +297,9 @@ export namespace mplot
}
}
this->idx = nhex;

// Boundary can be drawn on non-update
if (this->showboundary == true) { this->computeHexgridBoundary(); }
}
}

Expand All @@ -321,13 +311,70 @@ export namespace mplot
if (this->showhexes == true) {
this->computeHexes();
}
// Boundary
if (this->showboundary == true) {
this->computeHexgridBoundary();
}
// Optionally show a Flat surface for the zero plane
if (this->zerogrid == true) {
this->computeZerogridIndices();
}
// End trial grid
}

// Draw carefully around the boundary with tubes or lines or quads
void computeHexgridBoundary()
{
constexpr std::array<float, 3> clr = {};
constexpr std::array<float, 3> clr0 = {.1f,.1f,.1f};
sm::mat<float, 3> lt (this->hg->tfm.template as<float>());
//std::cout << "lt:\n" << lt << std::endl;

for (auto hptr : this->hg->bhexen) {
std::uint32_t hi = hptr->vi;
// Look at each possible neighbour direction and see if we need a tube
for (std::uint32_t i = 0; i < 6; ++i) {
if (this->hg->has_neighbour (hi, i) == false) {
// There's no neighbour, so we need a tube. The logic is made complex by the
// need to angle the ends of the tubes correctly depending on the shape of
// the boundary
std::uint32_t i0 = (i + 5u) % 6u;
sm::vec<float, 3> c0 = lt * hptr->get_vertex_coord (i0).template as<float>().plus_one_dim (0.0f);
sm::vec<float, 3> c = lt * hptr->get_vertex_coord (i).template as<float>().plus_one_dim (0.0f);

sm::vec<float, 3> u0 = {}; // tube end normal for c0
sm::vec<float, 3> u = {}; // tube end normal for c
sm::vec<float> v = {};

std::uint32_t di = 0u; // direction to corner neighbour
std::uint32_t vi = 0u; // vector to cross with uz depends on if corner neighbour exists or not

di = (i + 5u) % 6u;
if (this->hg->has_neighbour (hi, di) == false) {
vi = (i + 5u) % 6u;
} else {
vi = i;
}
v = hptr->get_vertex (vi).template as<float>().plus_one_dim();
v.renormalize();
u0 = lt * v.cross (sm::vec<float>::uz());

di = (i + 1u) % 6u;
if (this->hg->has_neighbour (hi, di) == false) {
vi = i;
} else {
vi = (i + 5u) % 6u;
}
v = hptr->get_vertex (vi).template as<float>().plus_one_dim();
v.renormalize();
u = lt * v.cross (-sm::vec<float>::uz());

this->computeOpenFlaredTube (c0, c, u0, u, clr0, clr, this->hg->d / 12.0f, this->hg->d / 12.0f);
}
}
}
}

// Compute vertices for the patchwork quilt of hexes
void computeHexes()
{
Expand Down Expand Up @@ -407,9 +454,6 @@ export namespace mplot
// Use a single colour for each hex, even though hex z positions are
// interpolated. Do the _colour_ scaling:
std::array<float, 3> clr = this->setColour (hi);
if (this->showboundary && (this->hg->vhexen[hi])->boundary_hex() == true) {
this->markHex (hi);
}
if (this->showcentre && _x == 0.0f && _y == 0.0f) {
this->markHex (hi);
}
Expand All @@ -419,7 +463,7 @@ export namespace mplot

// Use the centre position as the first location for finding the normal vector
vtx_0 = this->dataCoords == nullptr ? sm::vec<float>{ _x, _y, datumC } : coordC;
this->vertex_push ((this->tfm * vtx_0), this->vertexPositions);
this->vertex_push (vtx_0, this->vertexPositions);

// A hexagon corner/vertex position
sm::vec<float> crnr = {};
Expand Down Expand Up @@ -460,7 +504,7 @@ export namespace mplot
vtx_1 = coordC;
}
}
this->vertex_push (this->tfm * vtx_1, this->vertexPositions);
this->vertex_push (vtx_1, this->vertexPositions);


// SE vertex
Expand Down Expand Up @@ -495,7 +539,7 @@ export namespace mplot
vtx_2 = coordC;
}
}
this->vertex_push (this->tfm * vtx_2, this->vertexPositions);
this->vertex_push (vtx_2, this->vertexPositions);


// S
Expand Down Expand Up @@ -530,7 +574,7 @@ export namespace mplot
vtx_tmp = coordC;
}
}
this->vertex_push (this->tfm * vtx_tmp, this->vertexPositions);
this->vertex_push (vtx_tmp, this->vertexPositions);

// SW
if (this->dataCoords == nullptr) {
Expand Down Expand Up @@ -564,7 +608,7 @@ export namespace mplot
vtx_tmp = coordC;
}
}
this->vertex_push (this->tfm * vtx_tmp, this->vertexPositions);
this->vertex_push (vtx_tmp, this->vertexPositions);

// NW
if (this->dataCoords == nullptr) {
Expand Down Expand Up @@ -598,7 +642,7 @@ export namespace mplot
vtx_tmp = coordC;
}
}
this->vertex_push (this->tfm * vtx_tmp, this->vertexPositions);
this->vertex_push (vtx_tmp, this->vertexPositions);

// N
if (this->dataCoords == nullptr) {
Expand Down Expand Up @@ -632,7 +676,7 @@ export namespace mplot
vtx_tmp = coordC;
}
}
this->vertex_push (this->tfm * vtx_tmp, this->vertexPositions);
this->vertex_push (vtx_tmp, this->vertexPositions);

// From vtx_0,1,2 compute normal. This sets the correct normal, but note
// that there is only one 'layer' of vertices; the back of the
Expand Down
21 changes: 21 additions & 0 deletions mplot/VisualModel.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -836,8 +836,29 @@ export namespace mplot
void postmultViewMatrix (const sm::mat<float, 4>& m) { this->viewmatrix = this->viewmatrix * m; }
void premultViewMatrix (const sm::mat<float, 4>& m) { this->viewmatrix = m * this->viewmatrix; }

//! Scale the viewmatrix (this allows you to 'zoom' your model)
void scaleViewMatrix (const float by) { this->viewmatrix.scale (by); }

//! An alias for scaleViewMatrix
void set_zoom (const float factor) { this->viewmatrix.scale (factor); }

//! Reflect your model left to right (across the y-z plane through the origin)
void reflect_x()
{
this->postmultViewMatrix (sm::mat<float, 4>::reflection (sm::vec<float, 3>{}, sm::vec<float, 3>::ux()));
}

//! Reflect your model up/down (across the x-z plane through the origin)
void reflect_y()
{
this->postmultViewMatrix (sm::mat<float, 4>::reflection (sm::vec<float, 3>{}, sm::vec<float, 3>::uy()));
}

void reflect_z()
{
this->postmultViewMatrix (sm::mat<float, 4>::reflection (sm::vec<float, 3>{}, sm::vec<float, 3>::uz()));
}

//! When setting the scene matrix, also have to set the text's scene matrices.
void setSceneMatrix (const sm::mat<float, 4>& sv)
{
Expand Down
Loading