Replace invalid use of memcpy in curveplot

- Vertex is not trivially copyable, therefore memcpy is not allowed.
- Put local classes and functions into unnamed namespace.
- Remove using namespace std, using namespace Eigen.
- Prefer C++-style casts.
- Use C++17 std::clamp where appropriate.
- Use logger for debugging
pull/1277/head
Andrew Tribick 2021-12-28 21:34:38 +01:00 committed by ajtribick
parent 2069f1ce68
commit 657604c69a
2 changed files with 140 additions and 139 deletions

View File

@ -34,22 +34,24 @@
#define USE_VERTEX_BUFFER 1
#endif
#include "glsupport.h"
#include "curveplot.h"
#include "shadermanager.h"
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
using namespace std;
using namespace Eigen;
static const unsigned int SubdivisionFactor = 8;
static const double InvSubdivisionFactor = 1.0 / (double) SubdivisionFactor;
#if DEBUG_ADAPTIVE_SPLINE
static float SplineColors[10][3] = {
#include <celutil/logger.h>
#endif
#include "curveplot.h"
#include "glsupport.h"
#include "shadermanager.h"
namespace {
constexpr unsigned int SubdivisionFactor = 8;
constexpr double InvSubdivisionFactor = 1.0 / static_cast<double>(SubdivisionFactor);
#if DEBUG_ADAPTIVE_SPLINE
constexpr float SplineColors[10][3] = {
{ 0, 0, 1 },
{ 0, 1, 1 },
{ 0, 1, 0 },
@ -62,24 +64,21 @@ static float SplineColors[10][3] = {
{ 1.0f, 1.0f, 0.5f },
};
static unsigned int SegmentCounts[32];
#endif
#ifndef EIGEN_VECTORIZE
// Vectorization should be enabled for improved performance.
unsigned int SegmentCounts[32];
#endif
// Convert a 3-vector to a 4-vector by adding a zero
static inline Vector4d zeroExtend(const Vector3d& v)
inline Eigen::Vector4d
zeroExtend(const Eigen::Vector3d& v)
{
return Vector4d(v.x(), v.y(), v.z(), 0.0);
return Eigen::Vector4d(v.x(), v.y(), v.z(), 0.0);
}
class HighPrec_Frustum
{
public:
HighPrec_Frustum(double nearZ, double farZ, const Vector3d planeNormals[]) :
HighPrec_Frustum(double nearZ, double farZ, const Eigen::Vector3d planeNormals[]) :
m_nearZ(nearZ),
m_farZ(farZ)
{
@ -89,7 +88,7 @@ public:
}
}
inline bool cullSphere(const Vector3d& center,
inline bool cullSphere(const Eigen::Vector3d& center,
double radius) const
{
return (center.z() - radius > m_nearZ ||
@ -100,7 +99,7 @@ public:
center.dot(m_planeNormals[3].head(3)) < -radius);
}
inline bool cullSphere(const Vector4d& center,
inline bool cullSphere(const Eigen::Vector4d& center,
double radius) const
{
return (center.z() - radius > m_nearZ ||
@ -117,16 +116,17 @@ public:
private:
double m_nearZ;
double m_farZ;
Vector4d m_planeNormals[4];
Eigen::Vector4d m_planeNormals[4];
};
static inline Matrix4d cubicHermiteCoefficients(const Vector4d& p0,
const Vector4d& p1,
const Vector4d& v0,
const Vector4d& v1)
inline Eigen::Matrix4d
cubicHermiteCoefficients(const Eigen::Vector4d& p0,
const Eigen::Vector4d& p1,
const Eigen::Vector4d& v0,
const Eigen::Vector4d& v1)
{
Matrix4d coeff;
Eigen::Matrix4d coeff;
coeff.col(0) = p0;
coeff.col(1) = v0;
coeff.col(2) = 3.0 * (p1 - p0) - (2.0 * v0 + v1);
@ -136,25 +136,6 @@ static inline Matrix4d cubicHermiteCoefficients(const Vector4d& p0,
}
// Test a point to see if it lies within the frustum defined by
// planes z=nearZ, z=farZ, and the four side planes with specified
// normals.
#if 0
static inline bool frustumCull(const Vector4d& curvePoint,
double curveBoundingRadius,
double nearZ, double farZ,
const Vector4d viewFrustumPlaneNormals[])
{
return (curvePoint.z() - curveBoundingRadius > nearZ ||
curvePoint.z() + curveBoundingRadius < farZ ||
curvePoint.dot(viewFrustumPlaneNormals[0]) < -curveBoundingRadius ||
curvePoint.dot(viewFrustumPlaneNormals[1]) < -curveBoundingRadius ||
curvePoint.dot(viewFrustumPlaneNormals[2]) < -curveBoundingRadius ||
curvePoint.dot(viewFrustumPlaneNormals[3]) < -curveBoundingRadius);
}
#endif
class HighPrec_VertexBuffer
{
public:
@ -189,26 +170,33 @@ public:
glEnableVertexAttribArray(CelestiaGLProgram::VertexCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ColorAttributeIndex);
int stride = lineAsTriangles ? sizeof(Vertex) : sizeof(Vertex) * 2;
int stride = lineAsTriangles ? sizeof(Vertex) : sizeof(Vertex) * 2;
Vector4f* vertexBase = vbobj ? (Vector4f*) offsetof(Vertex, position) : &data[0].position;
const Eigen::Vector4f* vertexBase = vbobj
? reinterpret_cast<const Eigen::Vector4f*>(offsetof(Vertex, position))
: &data[0].position;
glVertexAttribPointer(CelestiaGLProgram::VertexCoordAttributeIndex,
3, GL_FLOAT, GL_FALSE, stride, vertexBase);
Vector4f* colorBase = vbobj ? (Vector4f*) offsetof(Vertex, color) : &data[0].color;
const Eigen::Vector4f* colorBase = vbobj
? reinterpret_cast<const Eigen::Vector4f*>(offsetof(Vertex, color))
: &data[0].color;
glVertexAttribPointer(CelestiaGLProgram::ColorAttributeIndex,
4, GL_FLOAT, GL_FALSE, stride, colorBase);
if (lineAsTriangles)
{
glEnableVertexAttribArray(CelestiaGLProgram::NextVCoordAttributeIndex);
glEnableVertexAttribArray(CelestiaGLProgram::ScaleFactorAttributeIndex);
float* scaleBase = vbobj ? (float*) offsetof(Vertex, scale) : &data[0].scale;
const float* scaleBase = vbobj
? reinterpret_cast<const float*>(offsetof(Vertex, scale))
: &data[0].scale;
glVertexAttribPointer(CelestiaGLProgram::ScaleFactorAttributeIndex,
1, GL_FLOAT, GL_FALSE, stride, scaleBase);
Vector4f* nextVertexBase = vbobj ? (Vector4f*) (offsetof(Vertex, position) + (2 * sizeof(Vertex))) : &data[2].position;
const Eigen::Vector4f* nextVertexBase = vbobj
? reinterpret_cast<const Eigen::Vector4f*>(offsetof(Vertex, position) + (2 * sizeof(Vertex)))
: &data[2].position;
glVertexAttribPointer(CelestiaGLProgram::NextVCoordAttributeIndex,
4, GL_FLOAT, GL_FALSE, stride, nextVertexBase);
}
@ -230,10 +218,10 @@ public:
#endif
}
inline void vertex(const Vector3d& v)
inline void vertex(const Eigen::Vector3d& v)
{
#if USE_VERTEX_BUFFER
Vector3f pos = v.cast<float>();
Eigen::Vector3f pos = v.cast<float>();
int index = currentPosition * 2;
data[index].position.segment<3>(0) = pos;
data[index].color = color;
@ -261,15 +249,15 @@ public:
#endif
}
inline void vertex(const Vector4d& v)
inline void vertex(const Eigen::Vector4d& v)
{
vertex(v, color);
}
inline void vertex(const Vector4d& v, const Vector4f& color)
inline void vertex(const Eigen::Vector4d& v, const Eigen::Vector4f& color)
{
#if USE_VERTEX_BUFFER
Vector4f pos = v.cast<float>();
Eigen::Vector4f pos = v.cast<float>();
int index = currentPosition * 2;
data[index].position = pos;
data[index].color = color;
@ -311,7 +299,8 @@ public:
if (currentStripLength > 1)
{
int index = currentPosition * 2;
memcpy(&data[index], &data[index - 4], 2 * sizeof(Vertex));
data[index] = data[index - 4];
data[index + 1] = data[index - 3];
currentPosition += 1;
stripLengths.push_back(currentStripLength);
}
@ -340,9 +329,8 @@ public:
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * currentPosition * 2, data);
unsigned int startIndex = 0;
for (vector<unsigned int>::const_iterator iter = stripLengths.begin(); iter != stripLengths.end(); ++iter)
for (unsigned int lineCount : stripLengths)
{
int lineCount = *iter;
if (lineAsTriangles)
glDrawArrays(GL_TRIANGLE_STRIP, startIndex * 2, lineCount * 2);
else
@ -373,7 +361,7 @@ public:
#endif
}
void setColor(const Vector4f &aColor)
void setColor(const Eigen::Vector4f &aColor)
{
#if USE_VERTEX_BUFFER
color = aColor;
@ -387,15 +375,16 @@ private:
unsigned int capacity;
struct Vertex
{
Vector4f position;
Vector4f color;
Eigen::Vector4f position;
Eigen::Vector4f color;
float scale;
};
Vertex* data;
GLuint vbobj;
unsigned int currentStripLength;
vector<unsigned int> stripLengths;
Vector4f color;
std::vector<unsigned int> stripLengths;
Eigen::Vector4f color;
bool lineAsTriangles;
};
@ -424,7 +413,7 @@ public:
// curve was culled and we need to start a new primitive sequence
// with glBegin().
bool renderCubic(bool restartCurve,
const Matrix4d& coeff,
const Eigen::Matrix4d& coeff,
double t0, double t1,
double curveBoundingRadius,
int depth) const
@ -440,14 +429,14 @@ public:
}
#endif
Vector4d lastP = coeff * Vector4d(1.0, t0, t0 * t0, t0 * t0 * t0);
Eigen::Vector4d lastP = coeff * Eigen::Vector4d(1.0, t0, t0 * t0, t0 * t0 * t0);
for (unsigned int i = 1; i <= SubdivisionFactor; i++)
{
double t = t0 + dt * i;
Vector4d p = coeff * Vector4d(1.0, t, t * t, t * t * t);
Eigen::Vector4d p = coeff * Eigen::Vector4d(1.0, t, t * t, t * t * t);
double minDistance = max(-m_viewFrustum.nearZ(), abs(p.z()) - segmentBoundingRadius);
double minDistance = std::max(-m_viewFrustum.nearZ(), std::abs(p.z()) - segmentBoundingRadius);
if (segmentBoundingRadius >= m_subdivisionThreshold * minDistance)
{
@ -494,9 +483,9 @@ public:
// curve was culled and we need to start a new primitive sequence
// with glBegin().
bool renderCubicFaded(bool restartCurve,
const Matrix4d& coeff,
const Eigen::Matrix4d& coeff,
double t0, double t1,
const Vector4f& color,
const Eigen::Vector4f& color,
double fadeStart, double fadeRate,
double curveBoundingRadius,
int depth) const
@ -512,18 +501,18 @@ public:
}
#endif
Vector4d lastP = coeff * Vector4d(1.0, t0, t0 * t0, t0 * t0 * t0);
Eigen::Vector4d lastP = coeff * Eigen::Vector4d(1.0, t0, t0 * t0, t0 * t0 * t0);
double lastOpacity = (t0 - fadeStart) * fadeRate;
lastOpacity = max(0.0, min(1.0, lastOpacity)); // clamp
lastOpacity = std::clamp(lastOpacity, 0.0, 1.0);
for (unsigned int i = 1; i <= SubdivisionFactor; i++)
{
double t = t0 + dt * i;
Vector4d p = coeff * Vector4d(1.0, t, t * t, t * t * t);
Eigen::Vector4d p = coeff * Eigen::Vector4d(1.0, t, t * t, t * t * t);
double opacity = (t - fadeStart) * fadeRate;
opacity = max(0.0, min(1.0, opacity)); // clamp
opacity = std::clamp(opacity, 0.0, 1.0);
double minDistance = max(-m_viewFrustum.nearZ(), abs(p.z()) - segmentBoundingRadius);
double minDistance = std::max(-m_viewFrustum.nearZ(), std::abs(p.z()) - segmentBoundingRadius);
if (segmentBoundingRadius >= m_subdivisionThreshold * minDistance)
{
@ -557,11 +546,11 @@ public:
if (restartCurve)
{
m_vbuf.begin();
m_vbuf.vertex(lastP, Vector4f(color.x(), color.y(), color.z(), color.w() * float(lastOpacity)));
m_vbuf.vertex(lastP, Eigen::Vector4f(color.x(), color.y(), color.z(), color.w() * float(lastOpacity)));
restartCurve = false;
}
m_vbuf.vertex(p, Vector4f(color.x(), color.y(), color.z(), color.w() * float(opacity)));
m_vbuf.vertex(p, Eigen::Vector4f(color.x(), color.y(), color.z(), color.w() * float(opacity)));
}
lastP = p;
lastOpacity = opacity;
@ -577,8 +566,12 @@ private:
};
HighPrec_VertexBuffer vbuf;
static HighPrec_VertexBuffer vbuf;
} // end unnamed namespace
CurvePlot::CurvePlot()
@ -623,22 +616,24 @@ CurvePlot::addSample(const CurvePlotSample& sample)
{
const CurvePlotSample& lastSample = m_samples[m_samples.size() - 2];
double dt = sample.t - lastSample.t;
Matrix4d coeff = cubicHermiteCoefficients(zeroExtend(lastSample.position),
zeroExtend(sample.position),
zeroExtend(lastSample.velocity * dt),
zeroExtend(sample.velocity * dt));
Vector4d extents = coeff.cwiseAbs() * Vector4d(0.0, 1.0, 1.0, 1.0);
Eigen::Matrix4d coeff = cubicHermiteCoefficients(
zeroExtend(lastSample.position),
zeroExtend(sample.position),
zeroExtend(lastSample.velocity * dt),
zeroExtend(sample.velocity * dt));
Eigen::Vector4d extents = coeff.cwiseAbs() * Eigen::Vector4d(0.0, 1.0, 1.0, 1.0);
m_samples[m_samples.size() - 1].boundingRadius = extents.norm();
}
else
{
const CurvePlotSample& nextSample = m_samples[1];
double dt = nextSample.t - sample.t;
Matrix4d coeff = cubicHermiteCoefficients(zeroExtend(sample.position),
zeroExtend(nextSample.position),
zeroExtend(sample.velocity * dt),
zeroExtend(nextSample.velocity * dt));
Vector4d extents = coeff.cwiseAbs() * Vector4d(0.0, 1.0, 1.0, 1.0);
Eigen::Matrix4d coeff = cubicHermiteCoefficients(
zeroExtend(sample.position),
zeroExtend(nextSample.position),
zeroExtend(sample.velocity * dt),
zeroExtend(nextSample.velocity * dt));
Eigen::Vector4d extents = coeff.cwiseAbs() * Eigen::Vector4d(0.0, 1.0, 1.0, 1.0);
m_samples[1].boundingRadius = extents.norm();
}
}
@ -688,21 +683,21 @@ CurvePlot::setDuration(double duration)
* @param subdivisionThreshold the threashhold for subdivision
*/
void
CurvePlot::render(const Affine3d& modelview,
CurvePlot::render(const Eigen::Affine3d& modelview,
double nearZ,
double farZ,
const Vector3d viewFrustumPlaneNormals[],
const Eigen::Vector3d viewFrustumPlaneNormals[],
double subdivisionThreshold,
const Vector4f& color,
const Eigen::Vector4f& color,
bool lineAsTriangles) const
{
// Flag to indicate whether we need to issue a glBegin()
bool restartCurve = true;
const Vector3d& p0_ = m_samples[0].position;
const Vector3d& v0_ = m_samples[0].velocity;
Vector4d p0 = modelview * Vector4d(p0_.x(), p0_.y(), p0_.z(), 1.0);
Vector4d v0 = modelview * Vector4d(v0_.x(), v0_.y(), v0_.z(), 0.0);
const Eigen::Vector3d& p0_ = m_samples[0].position;
const Eigen::Vector3d& v0_ = m_samples[0].velocity;
Eigen::Vector4d p0 = modelview * Eigen::Vector4d(p0_.x(), p0_.y(), p0_.z(), 1.0);
Eigen::Vector4d v0 = modelview * Eigen::Vector4d(v0_.x(), v0_.y(), v0_.z(), 0.0);
HighPrec_Frustum viewFrustum(nearZ, farZ, viewFrustumPlaneNormals);
HighPrec_RenderContext rc(vbuf, viewFrustum, subdivisionThreshold);
@ -719,10 +714,10 @@ CurvePlot::render(const Affine3d& modelview,
for (unsigned int i = 1; i < m_samples.size(); i++)
{
// Transform the points into camera space.
const Vector3d& p1_ = m_samples[i].position;
const Vector3d& v1_ = m_samples[i].velocity;
Vector4d p1 = modelview * Vector4d(p1_.x(), p1_.y(), p1_.z(), 1.0);
Vector4d v1 = modelview * Vector4d(v1_.x(), v1_.y(), v1_.z(), 0.0);
const Eigen::Vector3d& p1_ = m_samples[i].position;
const Eigen::Vector3d& v1_ = m_samples[i].velocity;
Eigen::Vector4d p1 = modelview * Eigen::Vector4d(p1_.x(), p1_.y(), p1_.z(), 1.0);
Eigen::Vector4d v1 = modelview * Eigen::Vector4d(v1_.x(), v1_.y(), v1_.z(), 0.0);
// O(t) is an approximating function for this segment of
// the orbit, with 0 <= t <= 1
@ -738,7 +733,7 @@ CurvePlot::render(const Affine3d& modelview,
// render it. Otherwise, it should be a performance win
// to do a sphere-frustum cull test before subdividing and
// rendering segment.
double minDistance = abs(p0.z()) - curveBoundingRadius;
double minDistance = std::abs(p0.z()) - curveBoundingRadius;
// Render close segments as splines with adaptive subdivision. The
// subdivisions eliminates kinks between line segments and also
@ -763,7 +758,7 @@ CurvePlot::render(const Affine3d& modelview,
else
{
double dt = m_samples[i].t - m_samples[i - 1].t;
Matrix4d coeff = cubicHermiteCoefficients(p0, p1, v0 * dt, v1 * dt);
Eigen::Matrix4d coeff = cubicHermiteCoefficients(p0, p1, v0 * dt, v1 * dt);
restartCurve = rc.renderCubic(restartCurve, coeff, 0.0, 1.0, curveBoundingRadius, 1);
}
@ -810,12 +805,12 @@ CurvePlot::render(const Affine3d& modelview,
vbuf.flush();
vbuf.finish();
#if DEBUG_ADAPTIVE_SPLINE3
#if DEBUG_ADAPTIVE_SPLINE
for (unsigned int i = 0; SegmentCounts[i] != 0 || i < 3; i++)
{
clog << i << ":" << SegmentCounts[i] << ", ";
celestia::util::GetLogger()->debug("{}: {}, ", i, SegmentCounts[i]);
}
clog << endl;
celestia::util::GetLogger()->debug("\n");
#endif
}
@ -831,14 +826,14 @@ CurvePlot::render(const Affine3d& modelview,
* @param endTime the end of the time interval
*/
void
CurvePlot::render(const Affine3d& modelview,
CurvePlot::render(const Eigen::Affine3d& modelview,
double nearZ,
double farZ,
const Vector3d viewFrustumPlaneNormals[],
const Eigen::Vector3d viewFrustumPlaneNormals[],
double subdivisionThreshold,
double startTime,
double endTime,
const Vector4f& color,
const Eigen::Vector4f& color,
bool lineAsTriangles) const
{
// Flag to indicate whether we need to issue a glBegin()
@ -856,10 +851,10 @@ CurvePlot::render(const Affine3d& modelview,
if (startSample > 0)
startSample--;
const Vector3d& p0_ = m_samples[startSample].position;
const Vector3d& v0_ = m_samples[startSample].velocity;
Vector4d p0 = modelview * Vector4d(p0_.x(), p0_.y(), p0_.z(), 1.0);
Vector4d v0 = modelview * Vector4d(v0_.x(), v0_.y(), v0_.z(), 0.0);
const Eigen::Vector3d& p0_ = m_samples[startSample].position;
const Eigen::Vector3d& v0_ = m_samples[startSample].velocity;
Eigen::Vector4d p0 = modelview * Eigen::Vector4d(p0_.x(), p0_.y(), p0_.z(), 1.0);
Eigen::Vector4d v0 = modelview * Eigen::Vector4d(v0_.x(), v0_.y(), v0_.z(), 0.0);
HighPrec_Frustum viewFrustum(nearZ, farZ, viewFrustumPlaneNormals);
HighPrec_RenderContext rc(vbuf, viewFrustum, subdivisionThreshold);
@ -874,10 +869,10 @@ CurvePlot::render(const Affine3d& modelview,
for (unsigned int i = startSample + 1; i < m_samples.size() && !lastSegment; i++)
{
// Transform the points into camera space.
const Vector3d& p1_ = m_samples[i].position;
const Vector3d& v1_ = m_samples[i].velocity;
Vector4d p1 = modelview * Vector4d(p1_.x(), p1_.y(), p1_.z(), 1.0);
Vector4d v1 = modelview * Vector4d(v1_.x(), v1_.y(), v1_.z(), 0.0);
const Eigen::Vector3d& p1_ = m_samples[i].position;
const Eigen::Vector3d& v1_ = m_samples[i].velocity;
Eigen::Vector4d p1 = modelview * Eigen::Vector4d(p1_.x(), p1_.y(), p1_.z(), 1.0);
Eigen::Vector4d v1 = modelview * Eigen::Vector4d(v1_.x(), v1_.y(), v1_.z(), 0.0);
if (endTime <= m_samples[i].t)
{
@ -926,7 +921,7 @@ CurvePlot::render(const Affine3d& modelview,
if (firstSegment)
{
t0 = (startTime - m_samples[i - 1].t) / dt;
t0 = std::max(0.0, std::min(1.0, t0));
t0 = std::clamp(t0, 0.0, 1.0);
firstSegment = false;
}
@ -935,7 +930,7 @@ CurvePlot::render(const Affine3d& modelview,
t1 = (endTime - m_samples[i - 1].t) / dt;
}
Matrix4d coeff = cubicHermiteCoefficients(p0, p1, v0 * dt, v1 * dt);
Eigen::Matrix4d coeff = cubicHermiteCoefficients(p0, p1, v0 * dt, v1 * dt);
restartCurve = rc.renderCubic(restartCurve, coeff, t0, t1, curveBoundingRadius, 1);
}
}
@ -1005,7 +1000,7 @@ CurvePlot::renderFaded(const Eigen::Affine3d& modelview,
double subdivisionThreshold,
double startTime,
double endTime,
const Vector4f& color,
const Eigen::Vector4f& color,
double fadeStartTime,
double fadeEndTime,
bool lineAsTriangles) const
@ -1028,12 +1023,12 @@ CurvePlot::renderFaded(const Eigen::Affine3d& modelview,
double fadeDuration = fadeEndTime - fadeStartTime;
double fadeRate = 1.0 / fadeDuration;
const Vector3d& p0_ = m_samples[startSample].position;
const Vector3d& v0_ = m_samples[startSample].velocity;
Vector4d p0 = modelview * Vector4d(p0_.x(), p0_.y(), p0_.z(), 1.0);
Vector4d v0 = modelview * Vector4d(v0_.x(), v0_.y(), v0_.z(), 0.0);
const Eigen::Vector3d& p0_ = m_samples[startSample].position;
const Eigen::Vector3d& v0_ = m_samples[startSample].velocity;
Eigen::Vector4d p0 = modelview * Eigen::Vector4d(p0_.x(), p0_.y(), p0_.z(), 1.0);
Eigen::Vector4d v0 = modelview * Eigen::Vector4d(v0_.x(), v0_.y(), v0_.z(), 0.0);
double opacity0 = (m_samples[startSample].t - fadeStartTime) * fadeRate;
opacity0 = max(0.0, min(1.0, opacity0));
opacity0 = std::clamp(opacity0, 0.0, 1.0);
HighPrec_Frustum viewFrustum(nearZ, farZ, viewFrustumPlaneNormals);
HighPrec_RenderContext rc(vbuf, viewFrustum, subdivisionThreshold);
@ -1047,12 +1042,12 @@ CurvePlot::renderFaded(const Eigen::Affine3d& modelview,
for (unsigned int i = startSample + 1; i < m_samples.size() && !lastSegment; i++)
{
// Transform the points into camera space.
const Vector3d& p1_ = m_samples[i].position;
const Vector3d& v1_ = m_samples[i].velocity;
Vector4d p1 = modelview * Vector4d(p1_.x(), p1_.y(), p1_.z(), 1.0);
Vector4d v1 = modelview * Vector4d(v1_.x(), v1_.y(), v1_.z(), 0.0);
const Eigen::Vector3d& p1_ = m_samples[i].position;
const Eigen::Vector3d& v1_ = m_samples[i].velocity;
Eigen::Vector4d p1 = modelview * Eigen::Vector4d(p1_.x(), p1_.y(), p1_.z(), 1.0);
Eigen::Vector4d v1 = modelview * Eigen::Vector4d(v1_.x(), v1_.y(), v1_.z(), 0.0);
double opacity1 = (m_samples[i].t - fadeStartTime) * fadeRate;
opacity1 = max(0.0, min(1.0, opacity1));
opacity1 = std::clamp(opacity1, 0.0, 1.0);
if (endTime <= m_samples[i].t)
{
@ -1073,7 +1068,7 @@ CurvePlot::renderFaded(const Eigen::Affine3d& modelview,
// render it. Otherwise, it should be a performance win
// to do a sphere-frustum cull test before subdividing and
// rendering segment.
double minDistance = abs(p0.z()) - curveBoundingRadius;
double minDistance = std::abs(p0.z()) - curveBoundingRadius;
// Render close segments as splines with adaptive subdivision. The
// subdivisions eliminates kinks between line segments and also
@ -1101,7 +1096,7 @@ CurvePlot::renderFaded(const Eigen::Affine3d& modelview,
if (firstSegment)
{
t0 = (startTime - m_samples[i - 1].t) / dt;
t0 = std::max(0.0, std::min(1.0, t0));
t0 = std::clamp(t0, 0.0, 1.0);
firstSegment = false;
}
@ -1110,7 +1105,7 @@ CurvePlot::renderFaded(const Eigen::Affine3d& modelview,
t1 = (endTime - m_samples[i - 1].t) / dt;
}
Matrix4d coeff = cubicHermiteCoefficients(p0, p1, v0 * dt, v1 * dt);
Eigen::Matrix4d coeff = cubicHermiteCoefficients(p0, p1, v0 * dt, v1 * dt);
restartCurve = rc.renderCubicFaded(restartCurve, coeff,
t0, t1,
color,
@ -1139,10 +1134,16 @@ CurvePlot::renderFaded(const Eigen::Affine3d& modelview,
if (restartCurve)
{
vbuf.begin();
vbuf.vertex(p0, Vector4f(color.x(), color.y(), color.z(), color.w() * float(opacity0)));
vbuf.vertex(p0, Eigen::Vector4f(color.x(),
color.y(),
color.z(),
color.w() * static_cast<float>(opacity0)));
restartCurve = false;
}
vbuf.vertex(p1, Vector4f(color.x(), color.y(), color.z(), color.w() * float(opacity1)));
vbuf.vertex(p1, Eigen::Vector4f(color.x(),
color.y(),
color.z(),
color.w() * static_cast<float>(opacity1)));
}
}

View File

@ -30,11 +30,11 @@
#pragma once
#include <deque>
#include <Eigen/Core>
#include <Eigen/Geometry>
class HighPrec_Frustum;
class CurvePlotSample
{
public:
@ -110,7 +110,7 @@ class CurvePlot
private:
std::deque<CurvePlotSample> m_samples;
double m_duration{ 0.0 };
unsigned int m_lastUsed{ 0 };