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