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
2 changes: 1 addition & 1 deletion maths
Submodule maths updated 1 files
+8 −0 sm/quaternion
33 changes: 33 additions & 0 deletions mplot/VisualCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,41 @@
#include <stdexcept>
#include <iostream>
#include <cstring>
#include <string>
#include <array>
#include <sm/vec>
#include <sm/range>
#include <sm/vvec>
#include <sm/mat44>
#include <mplot/tools.h>
#include <mplot/colour.h>

namespace mplot
{
// A very simple mesh struct. No textures, materials or owt
struct meshgroup
{
std::string name;
sm::mat44<float> transform;
sm::vvec<uint32_t> indices;
sm::vvec<sm::vec<float>> positions;
sm::vvec<sm::vec<float>> normals;
sm::vvec<sm::vec<float>> colours;
sm::range<sm::vec<float>> object_aabb;
sm::range<sm::vec<float>> world_aabb;
// Single colour is used if colours is empty
std::array<float, 3> single_colour = mplot::colour::grey50;
void validate() const
{
if (this->positions.size() != this->normals.size()) {
throw std::runtime_error ("meshgroup has different numbers of positions and normals");
}
if (!this->colours.empty() && this->colours.size() != this->positions.size()) {
throw std::runtime_error ("meshgroup has different numbers of positions and colours");
}
}
};
}

namespace mplot::visgl
{
Expand Down
45 changes: 39 additions & 6 deletions mplot/VisualModelBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -841,24 +841,57 @@ namespace mplot
//! Push three floats onto the vector of floats \a vp
void vertex_push (const float& x, const float& y, const float& z, std::vector<float>& vp)
{
sm::vec<float> vec = { x, y, z };
std::copy (vec.begin(), vec.end(), std::back_inserter (vp));
vp.emplace_back (x);
vp.emplace_back (y);
vp.emplace_back (z);
}
//! Push array of 3 floats onto the vector of floats \a vp
void vertex_push (const std::array<float, 3>& arr, std::vector<float>& vp)
template<std::size_t N = 3> requires (N == 3 || N == 4)
void vertex_push (const std::array<float, N>& arr, std::vector<float>& vp)
{
std::copy (arr.begin(), arr.end(), std::back_inserter (vp));
vp.emplace_back (arr[0]);
vp.emplace_back (arr[1]);
vp.emplace_back (arr[2]);
}
//! Push sm::vec of 3 floats onto the vector of floats \a vp
void vertex_push (const sm::vec<float>& vec, std::vector<float>& vp)
template<std::size_t N = 3> requires (N == 3 || N == 4)
void vertex_push (const sm::vec<float, N>& vec, std::vector<float>& vp)
{
std::copy (vec.begin(), vec.end(), std::back_inserter (vp));
vp.emplace_back (vec[0]);
vp.emplace_back (vec[1]);
vp.emplace_back (vec[2]);
}

//! Set up a vertex buffer object - bind, buffer and set vertex array object attribute
virtual void setupVBO (GLuint& buf, std::vector<float>& dat, unsigned int bufferAttribPosition) = 0;

protected:
/*!
* Add the given meshgroup to this VisualModel
*/
void computeMeshgroup (const mplot::meshgroup& mg)
{
mg.validate();

bool single_colr = mg.colours.empty();
for (uint32_t i = 0; i < mg.positions.size(); ++i) {
// We apply mg.transform *here*, rather than writing it into the viewmatrix. This is
// because other elements of this visual model may be added with the assumption of an
// identity viewmatrix.
this->vertex_push (mg.transform * mg.positions[i], this->vertexPositions);
this->vertex_push (mg.transform * mg.normals[i], this->vertexNormals);
if (single_colr) {
this->vertex_push (mg.single_colour, this->vertexColors);
} else {
this->vertex_push (mg.colours[i], this->vertexColors);
}
}
for (uint32_t i = 0; i < mg.indices.size(); ++i) {
this->indices.push_back (mg.indices[i] + this->idx);
}
this->idx += mg.positions.size();
}

/**
* START vertex/index computation code
*
Expand Down
31 changes: 24 additions & 7 deletions mplot/compoundray/EyeVisual.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,23 @@ namespace mplot::compoundray
//! Initialise with offset, start and end coordinates, radius and a single colour.
EyeVisual (const sm::vec<float, 3> _offset,
std::vector<std::array<float, 3>>* _ommData,
std::vector<mplot::compoundray::Ommatidium>* _ommatidia)
std::vector<mplot::compoundray::Ommatidium>* _ommatidia,
const mplot::meshgroup* _head_mesh = nullptr)
{
this->init (_offset, _ommData, _ommatidia);
this->init (_offset, _ommData, _ommatidia, _head_mesh);
}

~EyeVisual() {}

void init (const sm::vec<float, 3> _offset,
std::vector<std::array<float, 3>>* _ommData,
std::vector<mplot::compoundray::Ommatidium>* _ommatidia)
std::vector<mplot::compoundray::Ommatidium>* _ommatidia,
const mplot::meshgroup* _head_mesh = nullptr)
{
this->viewmatrix.translate (_offset);
this->ommData = _ommData;
this->ommatidia = _ommatidia;
this->head_mesh = _head_mesh;
}

void reinitColours()
Expand Down Expand Up @@ -311,10 +314,15 @@ namespace mplot::compoundray
this->computeTube (pos, pos + (0.05f * dw * dir), colour, colour, dw * 0.5f, tube_faces);

// This visualizes the optical cones
if (this->show_cones == true) {
if (this->show_cones == true && this->show_fov == false) {
float optical_radius = focal_point * std::tan (angle / 2.0f);
// Colour comes from ommData. ringoffset is 1.0f
this->computeCone (pos, ommatidial_detector_point, 0.0f, colour, optical_radius, tube_faces);
} else if (this->show_fov == true) {
// do a cone of angle 'acceptanceAngle' using user-supplied cone_length, starting FROM the disc to show field of view of the eye
sm::vec<float, 3> ommatidial_cone_pos = pos + dir * this->cone_length;
float radius = this->cone_length * std::tan (angle / 2.0f);
this->computeCone (ommatidial_cone_pos, pos, 0.0f, colour, radius, tube_faces);
}
}
} else if (show_3d && this->focal_point_sum <= 0.0f) {
Expand All @@ -333,7 +341,7 @@ namespace mplot::compoundray
float dw = min_dist_to_other[i];
this->computeTube (pos, pos + (0.05f * dw * dir), colour, colour, dw * 0.5f, tube_faces);
// We don't have a focal length to show cones, but we can still show the acceptance angle
if (this->show_cones == true) {
if (this->show_fov == true) {
// do a cone of angle 'acceptanceAngle' using user-supplied cone_length
sm::vec<float, 3> ommatidial_cone_pos = pos + dir * this->cone_length;
float radius = this->cone_length * std::tan (angle / 2.0f);
Expand All @@ -342,6 +350,7 @@ namespace mplot::compoundray
}
}

// 2D projections
for (uint32_t pri = 0; pri < this->projections.size(); ++pri) {
this->omm2d.clear();
if (this->projections[pri].proj_type == projection_type::cylindrical) {
Expand Down Expand Up @@ -374,6 +383,7 @@ namespace mplot::compoundray
}
}

// Sphere and rays for finding a suitable 2D projection
for (uint32_t pri = 0; pri < this->projections.size(); ++pri) {

if (this->show_sphere) {
Expand Down Expand Up @@ -401,6 +411,9 @@ namespace mplot::compoundray
}
}
}

// Optional head
if (this->head_mesh != nullptr) { this->computeMeshgroup (*this->head_mesh); }
}

void voronoi2d (uint32_t pri)
Expand Down Expand Up @@ -474,13 +487,17 @@ namespace mplot::compoundray

// If false, hide 3D representation (the ommatidial cones and discs)
bool show_3d = true;
// Visualize in two modes "disc" mode, showing just a 2D disc for each ommatidium and
// disc+cone mode, where the acceptance angle/optical cone is displayed too. Runtime switchable.
// If true, show optical cones, if possible
bool show_cones = false;
// If true, show 'field of view' cones. Overrides show_cones. Control size of cones with
// this->cone_length
bool show_fov = false;
// The colours detected by each ommatidium
std::vector<std::array<float, 3>>* ommData = nullptr;
// The position and orientation of each ommatidium
std::vector<mplot::compoundray::Ommatidium>* ommatidia = nullptr;
// An optional head mesh
const mplot::meshgroup* head_mesh = nullptr;
// If sum is 0, then we have a special case for rendering the eye as we have no focal point
// offsets specified for this eye (and hence the optical radius of the ommatidium is not known)
float focal_point_sum = 0.0f;
Expand Down
Loading