Skip to content

Commit

Permalink
Change the Mesh and Line APIs to support localization of geometry, mi…
Browse files Browse the repository at this point in the history
…tigating precision jitter
  • Loading branch information
gwaldron committed Oct 23, 2024
1 parent 38f707c commit 9fdb53e
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 174 deletions.
30 changes: 16 additions & 14 deletions src/apps/rocky_demo/Demo_Line.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,28 @@ auto Demo_Line_Absolute = [](Application& app)
// Attach a new Line component to the entity:
auto& line = app.entities.emplace<Line>(entity);

// Build the line's geometry:
auto xform = rocky::SRS::WGS84.to(app.mapNode->worldSRS());
const double alt = 125000;
// Set a reference point. This should be near your geometry, and will
// act as an anchor point for localizing geometry.
// Use the returned SRSOperation to transform points for use in your line.
GeoPoint refPoint(SRS::WGS84, -90.0, -20.0);
auto xform = line.setReferencePoint(refPoint);

const double alt = 10;
std::vector<glm::dvec3> points;
for (double lon = -180.0; lon <= 0.0; lon += 2.5)
for (double lon = -180; lon <= 0.0; lon += 0.25)
{
glm::dvec3 ecef;
if (xform(glm::dvec3(lon, -20.0, alt), ecef))
points.push_back(ecef);
glm::dvec3 point;
if (xform(glm::dvec3(lon, -20.0, alt), point))
points.emplace_back(point);
}
line.push(points.begin(), points.end());

// Create a style that we can change dynamically:
line.style = LineStyle{
{ 1,1,0,1 }, // color
3.0f, // width
0xffff, // stipple pattern (16 bit)
4 }; // stipple factor

// Write to the depth buffer:
line.style = LineStyle();
line.style->color = vsg::vec4{ 1,1,0,1 };
line.style->width = 3.0f;
line.style->stipple_pattern = 0xffff;
line.style->stipple_factor = 1;
line.write_depth = true;
}

Expand Down
19 changes: 13 additions & 6 deletions src/apps/rocky_demo/Demo_Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ auto Demo_Mesh_Absolute = [](Application& app)
auto& mesh = app.entities.emplace<Mesh>(entity);

// Make some geometry in ECEF coordinates
auto xform = SRS::WGS84.to(app.mapNode->worldSRS()); // SRS::WGS84.geocentricSRS());
//auto xform = SRS::WGS84.to(app.mapNode->worldSRS());
const double step = 2.5;
const double alt = 0.0;
const double alt = 0.0;
const double min_lon = 0.0, max_lon = 35.0;
const double min_lat = 15.0, max_lat = 35.0;

// A reference point will prevent local precision jitter.
auto xform = mesh.setReferencePoint(GeoPoint(
SRS::WGS84, (min_lon + max_lon) * 0.5, (min_lat + max_lat) * 0.5, alt));

for (double lon = 0.0; lon < 35.0; lon += step)
{
for(double lat = 15.0; lat < 35.0; lat += step)
Expand Down Expand Up @@ -87,8 +94,8 @@ auto Demo_Mesh_Relative = [](Application& app)
mesh.name = "Relative Mesh";

// Make some geometry that will be relative to a geolocation:
const float s = 250000.0;
vsg::vec3 verts[8] = {
const double s = 250000.0;
vsg::dvec3 verts[8] = {
{ -s, -s, -s },
{ s, -s, -s },
{ s, s, -s },
Expand Down Expand Up @@ -164,8 +171,8 @@ auto Demo_Mesh_Multi = [](Application& app)
Mesh& mesh = app.entities.emplace<Mesh>(entity);
mesh.name = "Relative Mesh";

const float s = 250000.0;
vsg::vec3 verts[8] = {
const double s = 250000.0;
vsg::dvec3 verts[8] = {
{ -s, -s, -s },
{ s, -s, -s },
{ s, s, -s },
Expand Down
4 changes: 2 additions & 2 deletions src/apps/rocky_demo/Demo_Tethering.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ auto Demo_Tethering = [](Application& app)
return;
}

const float s = 20.0;
const double s = 20.0;

// Make an entity to tether to.
if (entity == entt::null)
Expand All @@ -55,7 +55,7 @@ auto Demo_Tethering = [](Application& app)

// add a mesh plane:
auto& mesh = app.entities.emplace<Mesh>(entity);
vsg::vec3 verts[4] = { { -s, -s, 0 }, { s, -s, 0 }, { s, s, 0 }, { -s, s, 0 } };
vsg::dvec3 verts[4] = { { -s, -s, 0 }, { s, -s, 0 }, { s, s, 0 }, { -s, s, 0 } };
unsigned indices[6] = { 0,1,2, 0,2,3 };
vsg::vec4 color{ 1, 1, 0, 0.55f };
for (unsigned i = 0; i < 6; ) {
Expand Down
26 changes: 26 additions & 0 deletions src/rocky/vsg/ECS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,32 @@ ECS::Component::to_json() const
return j.dump();
}

SRSOperation
ECS::NodeComponent::setReferencePoint(const GeoPoint& point)
{
SRS worldSRS = point.srs;

if (point.srs.valid())
{
if (point.srs.isGeodetic())
{
worldSRS = point.srs.geocentricSRS();

GeoPoint world;
if (point.transform(worldSRS, world))
{
refPoint = vsg::dvec3{ world.x, world.y, world.z };
}
}
else
{
refPoint = vsg::dvec3{ point.x, point.y, point.z };
}
}

return SRSOperation(point.srs, worldSRS);
}

void
ECS::SystemsManager::update(ECS::time_point time)
{
Expand Down
9 changes: 9 additions & 0 deletions src/rocky/vsg/ECS.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ namespace ROCKY_NAMESPACE
class ROCKY_EXPORT NodeComponent : public Component
{
public:
//! Set a reference point for geometry. For preventing precision jitter.
//! @param p The reference point
//! @return The operation that can transform data from the reference point's
//! SRS into mesh vertices you can add to a geometry attached to this component.
SRSOperation setReferencePoint(const GeoPoint& p);

/**
* Component initialization parameters for VSG objects
*/
Expand Down Expand Up @@ -221,6 +227,9 @@ namespace ROCKY_NAMESPACE
{
nodeDirty = true;
}

protected:
vsg::dvec3 refPoint;
};


Expand Down
2 changes: 1 addition & 1 deletion src/rocky/vsg/FeatureView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ namespace
styles.mesh.has_value() ? styles.mesh->depth_offset :
0.0f;

Triangle32 temp = {
Triangle temp = {
{}, // we'll fill in the verts below
{color, color, color},
{}, // uvs - don't need them
Expand Down
41 changes: 31 additions & 10 deletions src/rocky/vsg/Line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <vsg/nodes/StateGroup.h>

using namespace ROCKY_NAMESPACE;
using namespace ROCKY_NAMESPACE::detail;

Line::Line()
{
Expand All @@ -36,6 +37,8 @@ Line::initializeNode(const ECS::NodeComponent::Params& params)
{
auto cull = vsg::CullNode::create();

vsg::ref_ptr<vsg::Group> geom_parent;

if (style.has_value())
{
bindCommand = BindLineDescriptors::create();
Expand All @@ -44,20 +47,38 @@ Line::initializeNode(const ECS::NodeComponent::Params& params)

auto sg = vsg::StateGroup::create();
sg->stateCommands.push_back(bindCommand);
for (auto& g : geometries)
sg->addChild(g);
cull->child = sg;
geom_parent = sg;

if (refPoint != vsg::dvec3())
{
auto localizer = vsg::MatrixTransform::create(vsg::translate(refPoint));
localizer->addChild(sg);
cull->child = localizer;
}
else
{
cull->child = sg;
}
}
else if (geometries.size() == 1)
else
{
cull->child = geometries[0];
if (refPoint != vsg::dvec3())
{
auto localizer = vsg::MatrixTransform::create(vsg::translate(refPoint));
cull->child = localizer;
geom_parent = localizer;
}
else
{
auto group = vsg::Group::create();
cull->child = group;
geom_parent = group;
}
}
else

for (auto& geom : geometries)
{
auto group = vsg::Group::create();
for (auto& g : geometries)
group->addChild(g);
cull->child = group;
geom_parent->addChild(geom);
}

vsg::ComputeBounds cb;
Expand Down
125 changes: 67 additions & 58 deletions src/rocky/vsg/Line.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
#pragma once
#include <rocky/vsg/ECS.h>
#include <rocky/SRS.h>
#include <vsg/nodes/Geometry.h>
#include <vsg/commands/DrawIndexed.h>
#include <vsg/state/BindDescriptorSet.h>
Expand All @@ -25,57 +26,60 @@ namespace ROCKY_NAMESPACE
float depth_offset = 0.0f; // meters
};

/**
* Renders a line or linestring geometry.
*/
class ROCKY_EXPORT LineGeometry : public vsg::Inherit<vsg::Geometry, LineGeometry>
namespace detail
{
public:
//! Construct a new line string geometry node
LineGeometry();

//! Adds a vertex to the end of the line string
void push_back(const vsg::vec3& vert);

//! Number of verts comprising this line string
unsigned numVerts() const;

//! The first vertex in the line string to render
void setFirst(unsigned value);

//! Number of vertices in the line string to render
void setCount(unsigned value);

//! Recompile the geometry after making changes.
//! TODO: just make it dynamic instead
void compile(vsg::Context&) override;

protected:
vsg::vec4 _defaultColor = { 1,1,1,1 };
std::vector<vsg::vec3> _current;
std::vector<vsg::vec3> _previous;
std::vector<vsg::vec3> _next;
std::vector<vsg::vec4> _colors;
vsg::ref_ptr<vsg::DrawIndexed> _drawCommand;
};

/**
* Applies a line style.
*/
class ROCKY_EXPORT BindLineDescriptors : public vsg::Inherit<vsg::BindDescriptorSet, BindLineDescriptors>
{
public:
//! Construct a line style node
BindLineDescriptors();

//! Initialize this command with the associated layout
void init(vsg::ref_ptr<vsg::PipelineLayout> layout);

//! Refresh the data buffer contents on the GPU
void updateStyle(const LineStyle&);

vsg::ref_ptr<vsg::ubyteArray> _styleData;
};
/**
* Renders a line or linestring geometry.
*/
class ROCKY_EXPORT LineGeometry : public vsg::Inherit<vsg::Geometry, LineGeometry>
{
public:
//! Construct a new line string geometry node
LineGeometry();

//! Adds a vertex to the end of the line string
void push_back(const vsg::vec3& vert);

//! Number of verts comprising this line string
unsigned numVerts() const;

//! The first vertex in the line string to render
void setFirst(unsigned value);

//! Number of vertices in the line string to render
void setCount(unsigned value);

//! Recompile the geometry after making changes.
//! TODO: just make it dynamic instead
void compile(vsg::Context&) override;

protected:
vsg::vec4 _defaultColor = { 1,1,1,1 };
std::vector<vsg::vec3> _current;
std::vector<vsg::vec3> _previous;
std::vector<vsg::vec3> _next;
std::vector<vsg::vec4> _colors;
vsg::ref_ptr<vsg::DrawIndexed> _drawCommand;
};

/**
* Applies a line style.
*/
class ROCKY_EXPORT BindLineDescriptors : public vsg::Inherit<vsg::BindDescriptorSet, BindLineDescriptors>
{
public:
//! Construct a line style node
BindLineDescriptors();

//! Initialize this command with the associated layout
void init(vsg::ref_ptr<vsg::PipelineLayout> layout);

//! Refresh the data buffer contents on the GPU
void updateStyle(const LineStyle&);

vsg::ref_ptr<vsg::ubyteArray> _styleData;
};
}

/**
* LineString component - holds one or more separate line string geometries
Expand All @@ -96,8 +100,8 @@ namespace ROCKY_NAMESPACE
//! Pushes a new sub-geometry along with its range of points.
//! @param begin Iterator of first point to add to the new sub-geometry
//! @param end Iterator past the final point to add to the new sub-geometry
template<class VEC3_ITER>
inline void push(VEC3_ITER begin, VEC3_ITER end);
template<class DVEC3_ITER>
inline void push(DVEC3_ITER begin, DVEC3_ITER end);

//! Applies changes to the dynanmic "style"
void dirty();
Expand All @@ -112,16 +116,21 @@ namespace ROCKY_NAMESPACE
int featureMask() const override;

private:
vsg::ref_ptr<BindLineDescriptors> bindCommand;
std::vector<vsg::ref_ptr<LineGeometry>> geometries;
vsg::ref_ptr<detail::BindLineDescriptors> bindCommand;
std::vector<vsg::ref_ptr<detail::LineGeometry>> geometries;
vsg::dvec3 refPoint;
friend class LineSystem;
};

// inline implementations
template<class VEC3_ITER> void Line::push(VEC3_ITER begin, VEC3_ITER end) {
auto geom = LineGeometry::create();
for (VEC3_ITER i = begin; i != end; ++i)
geom->push_back({ (float)i->x, (float)i->y, (float)i->z });
template<class DVEC3_ITER> void Line::push(DVEC3_ITER begin, DVEC3_ITER end)
{
auto geom = detail::LineGeometry::create();
for (DVEC3_ITER i = begin; i != end; ++i)
{
auto local = vsg::dvec3(i->x, i->y, i->z) - refPoint;
geom->push_back(vsg::vec3(local));
}
geometries.push_back(geom);
}
}
Loading

0 comments on commit 9fdb53e

Please sign in to comment.