Revert floating point determinism attempt
This commit is contained in:
parent
a935c48e13
commit
51b10e4925
3 changed files with 117 additions and 140 deletions
|
|
@ -12,10 +12,6 @@ template <typename S, typename T> S convert_vec2(const T& t) {
|
|||
return S{t[0], t[1]};
|
||||
}
|
||||
|
||||
template <typename S, typename T> S convert_vec2_narrow_double_to_float(const T& t) {
|
||||
return S{static_cast<float>(t[0]), static_cast<float>(t[1])};
|
||||
}
|
||||
|
||||
template <typename S, typename T> S convert_vec3(const T& t) {
|
||||
return S{t[0], t[1], t[2]};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include <limits>
|
||||
#include <Eigen/Geometry>
|
||||
#include "Eigen/Core"
|
||||
#include "Helpers/ConvertVec.hpp"
|
||||
#include "Helpers/MathExtras.hpp"
|
||||
#include "../TimePoint.hpp"
|
||||
#include <include/core/SkVertices.h>
|
||||
|
|
@ -17,12 +16,6 @@
|
|||
#define AABB_PRECHECK_BVH_LEVELS 2
|
||||
#define DEFAULT_SMOOTHNESS 5
|
||||
|
||||
BrushStrokeCanvasComponentPointDouble::BrushStrokeCanvasComponentPointDouble() {}
|
||||
BrushStrokeCanvasComponentPointDouble::BrushStrokeCanvasComponentPointDouble(const BrushStrokeCanvasComponentPoint& p):
|
||||
pos(p.pos.cast<double>()),
|
||||
width(p.width)
|
||||
{}
|
||||
|
||||
void BrushStrokeCanvasComponent::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(*d.points, d.color, d.hasRoundCaps);
|
||||
}
|
||||
|
|
@ -82,7 +75,7 @@ void BrushStrokeCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData
|
|||
}
|
||||
|
||||
std::shared_ptr<void> BrushStrokeCanvasComponent::get_predraw_data_accurate(const DrawData& drawData, const CoordSpaceHelper& coords) const {
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
std::vector<BrushStrokeCanvasComponentPoint> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
|
||||
SCollision::AABB<float> viewGenerousColliderInObjSpace = coords.world_collider_to_coords<SCollision::AABB<float>>(drawData.cam.viewingAreaGenerousCollider);
|
||||
viewGenerousColliderInObjSpace.min -= Vector2f{1.0f, 1.0f};
|
||||
|
|
@ -90,8 +83,8 @@ std::shared_ptr<void> BrushStrokeCanvasComponent::get_predraw_data_accurate(cons
|
|||
|
||||
std::vector<std::array<SkPoint, 3>> finalTrianglePoints;
|
||||
|
||||
auto triangleFunc = [&](Vector2d a, Vector2d b, Vector2d c) {
|
||||
SCollision::Triangle<float> triCollider = {a.cast<float>(), b.cast<float>(), c.cast<float>()};
|
||||
auto triangleFunc = [&](Vector2f a, Vector2f b, Vector2f c) {
|
||||
SCollision::Triangle<float> triCollider = {a, b, c};
|
||||
|
||||
if(SCollision::collide(triCollider.bounds, viewGenerousColliderInObjSpace)) {
|
||||
auto clipListFunc = [](const std::vector<std::array<WorldVec, 3>>& clipList, const std::array<WorldVec, 2>& axisLineSegment, const std::function<bool(const WorldVec&)>& isInClippingAreaFunc) {
|
||||
|
|
@ -102,7 +95,7 @@ std::shared_ptr<void> BrushStrokeCanvasComponent::get_predraw_data_accurate(cons
|
|||
};
|
||||
|
||||
std::vector<std::array<WorldVec, 3>> clipList;
|
||||
clipList.emplace_back(std::array<WorldVec, 3>{coords.from_space(triCollider.p[0]), coords.from_space(triCollider.p[1]), coords.from_space(triCollider.p[2])});
|
||||
clipList.emplace_back(std::array<WorldVec, 3>{coords.from_space(a), coords.from_space(b), coords.from_space(c)});
|
||||
clipList = clipListFunc(clipList, {drawData.cam.viewingAreaGenerousCollider.min, drawData.cam.viewingAreaGenerousCollider.top_right()}, [&](const WorldVec& p) {
|
||||
return p.y() > drawData.cam.viewingAreaGenerousCollider.min.y();
|
||||
});
|
||||
|
|
@ -199,8 +192,8 @@ void BrushStrokeCanvasComponent::set_data_from(const CanvasComponent& other) {
|
|||
|
||||
void BrushStrokeCanvasComponent::initialize_draw_data(DrawingProgram& drawP) {
|
||||
if(!d.points->empty()) {
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
auto triangleFunc = [&](Vector2d a, Vector2d b, Vector2d c) {
|
||||
std::vector<BrushStrokeCanvasComponentPoint> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
auto triangleFunc = [&](Vector2f a, Vector2f b, Vector2f c) {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
@ -219,37 +212,35 @@ void BrushStrokeCanvasComponent::initialize_draw_data(DrawingProgram& drawP) {
|
|||
create_collider();
|
||||
}
|
||||
|
||||
std::vector<size_t> BrushStrokeCanvasComponent::get_wedge_indices(const std::vector<BrushStrokeCanvasComponentPointDouble>& points) const {
|
||||
std::vector<size_t> BrushStrokeCanvasComponent::get_wedge_indices(const std::vector<BrushStrokeCanvasComponentPoint>& points) const {
|
||||
if(points.size() < 2)
|
||||
return {};
|
||||
std::vector<size_t> toRet;
|
||||
toRet.emplace_back(0);
|
||||
for(size_t i = 1; i < points.size() - 1; i++) {
|
||||
Vector2d v1Norm = (points[i - 1].pos - points[i].pos).normalized();
|
||||
Vector2d v2Norm = (points[i + 1].pos - points[i].pos).normalized();
|
||||
if(v1Norm.dot(v2Norm) > -0.6)
|
||||
Vector2f v1Norm = (points[i - 1].pos - points[i].pos).normalized();
|
||||
Vector2f v2Norm = (points[i + 1].pos - points[i].pos).normalized();
|
||||
if(v1Norm.dot(v2Norm) > -0.6f)
|
||||
toRet.emplace_back(i);
|
||||
}
|
||||
toRet.emplace_back(points.size() - 1);
|
||||
return toRet;
|
||||
}
|
||||
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> BrushStrokeCanvasComponent::smooth_points(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const {
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> points;// = *d.points;
|
||||
for(auto& p : *d.points)
|
||||
points.emplace_back(p);
|
||||
std::vector<BrushStrokeCanvasComponentPoint> BrushStrokeCanvasComponent::smooth_points(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const {
|
||||
std::vector<BrushStrokeCanvasComponentPoint>& points = *d.points;
|
||||
|
||||
size_t pointsSize = endIndex - beginIndex + 1;
|
||||
if(pointsSize < 2)
|
||||
return {points[beginIndex], points[endIndex]};
|
||||
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> toRet;
|
||||
std::vector<BrushStrokeCanvasComponentPoint> toRet;
|
||||
|
||||
BrushStrokeCanvasComponentPointDouble p0 = points[beginIndex];
|
||||
BrushStrokeCanvasComponentPoint p0 = points[beginIndex];
|
||||
p0.pos = p0.pos + p0.width * (p0.pos - points[beginIndex + 1].pos).normalized() * DRAW_MINIMUM_LIMIT;
|
||||
BrushStrokeCanvasComponentPointDouble p1 = points[beginIndex];
|
||||
BrushStrokeCanvasComponentPointDouble p2 = points[beginIndex + 1];
|
||||
BrushStrokeCanvasComponentPointDouble p3;
|
||||
BrushStrokeCanvasComponentPoint p1 = points[beginIndex];
|
||||
BrushStrokeCanvasComponentPoint p2 = points[beginIndex + 1];
|
||||
BrushStrokeCanvasComponentPoint p3;
|
||||
|
||||
for(size_t i = beginIndex; i < endIndex; i++) {
|
||||
|
||||
|
|
@ -262,10 +253,10 @@ std::vector<BrushStrokeCanvasComponentPointDouble> BrushStrokeCanvasComponent::s
|
|||
|
||||
toRet.emplace_back(p1);
|
||||
|
||||
double tMove = 1.0 / static_cast<double>(numOfDivisions);
|
||||
float tMove = 1.0 / static_cast<float>(numOfDivisions);
|
||||
for(unsigned d = 1; d < numOfDivisions; d++) {
|
||||
double t = tMove * static_cast<double>(d);
|
||||
BrushStrokeCanvasComponentPointDouble pToAdd;
|
||||
float t = tMove * static_cast<float>(d);
|
||||
BrushStrokeCanvasComponentPoint pToAdd;
|
||||
pToAdd.pos = catmull_rom(p0.pos, p1.pos, p2.pos, p3.pos, t);
|
||||
pToAdd.width = std::lerp(p1.width, p2.width, t);
|
||||
if(!(std::isnan(pToAdd.pos.x()) || std::isnan(pToAdd.pos.y()))) // Don't add NAN values
|
||||
|
|
@ -280,39 +271,39 @@ std::vector<BrushStrokeCanvasComponentPointDouble> BrushStrokeCanvasComponent::s
|
|||
return toRet;
|
||||
}
|
||||
|
||||
//std::vector<BrushStrokeCanvasComponentPoint> BrushStrokeCanvasComponent::smooth_points_avg(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const {
|
||||
// std::vector<BrushStrokeCanvasComponentPoint>& points = *d.points;
|
||||
//
|
||||
// size_t pointsSize = endIndex - beginIndex + 1;
|
||||
// if(pointsSize < 2)
|
||||
// return {points[beginIndex], points[endIndex]};
|
||||
//
|
||||
// std::vector<BrushStrokeCanvasComponentPoint> toRet;
|
||||
//
|
||||
// for(size_t i = beginIndex; i < endIndex; i++) {
|
||||
// const BrushStrokeCanvasComponentPoint& p1 = points[i];
|
||||
// const BrushStrokeCanvasComponentPoint& p2 = points[i + 1];
|
||||
//
|
||||
// float tMove = 1.0 / static_cast<float>(numOfDivisions);
|
||||
// for(unsigned d = 0; d < numOfDivisions; d++) {
|
||||
// float t = tMove * static_cast<float>(d);
|
||||
// BrushStrokeCanvasComponentPoint pToAdd;
|
||||
// pToAdd.pos = lerp_vec(p1.pos, p2.pos, t);
|
||||
// pToAdd.width = std::lerp(p1.width, p2.width, t);
|
||||
// if(!(std::isnan(pToAdd.pos.x()) || std::isnan(pToAdd.pos.y()))) // Don't add NAN values
|
||||
// toRet.emplace_back(pToAdd);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// toRet.emplace_back(points[endIndex]);
|
||||
//
|
||||
// return toRet;
|
||||
//}
|
||||
std::vector<BrushStrokeCanvasComponentPoint> BrushStrokeCanvasComponent::smooth_points_avg(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const {
|
||||
std::vector<BrushStrokeCanvasComponentPoint>& points = *d.points;
|
||||
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> BrushStrokeCanvasComponent::every_nth_point_include_front_and_back(const std::vector<BrushStrokeCanvasComponentPointDouble>& pts, size_t n) const {
|
||||
size_t pointsSize = endIndex - beginIndex + 1;
|
||||
if(pointsSize < 2)
|
||||
return {points[beginIndex], points[endIndex]};
|
||||
|
||||
std::vector<BrushStrokeCanvasComponentPoint> toRet;
|
||||
|
||||
for(size_t i = beginIndex; i < endIndex; i++) {
|
||||
const BrushStrokeCanvasComponentPoint& p1 = points[i];
|
||||
const BrushStrokeCanvasComponentPoint& p2 = points[i + 1];
|
||||
|
||||
float tMove = 1.0 / static_cast<float>(numOfDivisions);
|
||||
for(unsigned d = 0; d < numOfDivisions; d++) {
|
||||
float t = tMove * static_cast<float>(d);
|
||||
BrushStrokeCanvasComponentPoint pToAdd;
|
||||
pToAdd.pos = lerp_vec(p1.pos, p2.pos, t);
|
||||
pToAdd.width = std::lerp(p1.width, p2.width, t);
|
||||
if(!(std::isnan(pToAdd.pos.x()) || std::isnan(pToAdd.pos.y()))) // Don't add NAN values
|
||||
toRet.emplace_back(pToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
toRet.emplace_back(points[endIndex]);
|
||||
|
||||
return toRet;
|
||||
}
|
||||
|
||||
std::vector<BrushStrokeCanvasComponentPoint> BrushStrokeCanvasComponent::every_nth_point_include_front_and_back(const std::vector<BrushStrokeCanvasComponentPoint>& pts, size_t n) const {
|
||||
if(pts.size() <= 3 || n == 0)
|
||||
return pts;
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> toRet;
|
||||
std::vector<BrushStrokeCanvasComponentPoint> toRet;
|
||||
toRet.emplace_back(pts.front());
|
||||
for(size_t i = n; i < pts.size() - 1; i += n)
|
||||
toRet.emplace_back(pts[i]);
|
||||
|
|
@ -320,25 +311,22 @@ std::vector<BrushStrokeCanvasComponentPointDouble> BrushStrokeCanvasComponent::e
|
|||
return toRet;
|
||||
}
|
||||
|
||||
void BrushStrokeCanvasComponent::create_triangles(const std::function<bool(Vector2d, Vector2d, Vector2d)>& passTriangleFunc, const std::vector<BrushStrokeCanvasComponentPointDouble>& smoothedPoints, size_t skipVertexCount, std::shared_ptr<SkPathBuilder> bPathBuilder) const {
|
||||
void BrushStrokeCanvasComponent::create_triangles(const std::function<bool(Vector2f, Vector2f, Vector2f)>& passTriangleFunc, const std::vector<BrushStrokeCanvasComponentPoint>& smoothedPoints, size_t skipVertexCount, std::shared_ptr<SkPathBuilder> bPathBuilder) const {
|
||||
const int ARC_SMOOTHNESS = 10;
|
||||
const int CIRCLE_SMOOTHNESS = 20;
|
||||
const std::vector<BrushStrokeCanvasComponentPoint>& pointsN = *d.points;
|
||||
std::vector<SkPoint> topPoints;
|
||||
std::vector<SkPoint> bottomPoints;
|
||||
|
||||
if((*d.points).size() == 1 && d.hasRoundCaps) {
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> pointsN;
|
||||
for(auto& c : *d.points)
|
||||
pointsN.emplace_back(c);
|
||||
|
||||
std::vector<Vector2d> circlePoints = gen_circle_points(pointsN.front().pos, pointsN.front().width / 2.0, CIRCLE_SMOOTHNESS);
|
||||
if(pointsN.size() == 1 && d.hasRoundCaps) {
|
||||
std::vector<Vector2f> circlePoints = gen_circle_points(pointsN.front().pos, pointsN.front().width / 2.0f, CIRCLE_SMOOTHNESS);
|
||||
for(size_t i = 0; i < circlePoints.size(); i++) {
|
||||
if(passTriangleFunc(pointsN.front().pos, circlePoints[i], circlePoints[(i + 1) % circlePoints.size()])) return;
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(circlePoints[i]));
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(circlePoints[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if((*d.points).size() < 2) {
|
||||
if(pointsN.size() < 2) {
|
||||
if(bPathBuilder && !topPoints.empty())
|
||||
bPathBuilder->addPolygon({topPoints.data(), topPoints.size()}, false);
|
||||
return;
|
||||
|
|
@ -352,39 +340,39 @@ void BrushStrokeCanvasComponent::create_triangles(const std::function<bool(Vecto
|
|||
size_t pointsBegin = wedgeIndices[i];
|
||||
size_t pointsEnd = wedgeIndices[i + 1];
|
||||
|
||||
std::array<Vector2d, 3> vertArray;
|
||||
std::array<Vector2f, 3> vertArray;
|
||||
size_t newIndex = 0;
|
||||
|
||||
Vector2d perpPrev = perpendicular_vec2((points[pointsBegin + 1].pos - points[pointsBegin].pos).eval());
|
||||
Vector2f perpPrev = perpendicular_vec2((points[pointsBegin + 1].pos - points[pointsBegin].pos).eval());
|
||||
perpPrev.normalize();
|
||||
|
||||
vertArray[0] = points[pointsBegin].pos + perpPrev * points[pointsBegin].width * 0.5;
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(vertArray[0]));
|
||||
vertArray[1] = points[pointsBegin].pos - perpPrev * points[pointsBegin].width * 0.5;
|
||||
bottomPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(vertArray[1]));
|
||||
vertArray[0] = points[pointsBegin].pos + perpPrev * points[pointsBegin].width * 0.5f;
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(vertArray[0]));
|
||||
vertArray[1] = points[pointsBegin].pos - perpPrev * points[pointsBegin].width * 0.5f;
|
||||
bottomPoints.emplace_back(convert_vec2<SkPoint>(vertArray[1]));
|
||||
newIndex = 2;
|
||||
|
||||
if(d.hasRoundCaps && pointsBegin == 0) {
|
||||
Vector2d arcDirStart = (vertArray[0] - points[0].pos).normalized();
|
||||
Vector2d arcDirEnd = (vertArray[1] - points[0].pos).normalized();
|
||||
Vector2d arcDirCenter = (points[0].pos - points[1].pos).normalized();
|
||||
std::vector<Vector2d> arcPoints = arc_vec<double>(points[0].pos, arcDirStart, arcDirEnd, arcDirCenter, points[0].width * 0.5, ARC_SMOOTHNESS);
|
||||
arcPoints.emplace(arcPoints.begin(), vertArray[0]);
|
||||
arcPoints.emplace_back(vertArray[1]);
|
||||
Vector2f arcDirStart = (convert_vec2<Vector2f>(vertArray[0]) - points[0].pos).normalized();
|
||||
Vector2f arcDirEnd = (convert_vec2<Vector2f>(vertArray[1]) - points[0].pos).normalized();
|
||||
Vector2f arcDirCenter = (points[0].pos - points[1].pos).normalized();
|
||||
std::vector<Vector2f> arcPoints = arc_vec<float>(points[0].pos, arcDirStart, arcDirEnd, arcDirCenter, points[0].width * 0.5f, ARC_SMOOTHNESS);
|
||||
arcPoints.emplace(arcPoints.begin(), convert_vec2<Vector2f>(vertArray[0]));
|
||||
arcPoints.emplace_back(convert_vec2<Vector2f>(vertArray[1]));
|
||||
for(size_t i = 0; i < arcPoints.size() - 1; i++) {
|
||||
if(passTriangleFunc(points[0].pos, arcPoints[i], arcPoints[i + 1])) return;
|
||||
bottomPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints[i]));
|
||||
bottomPoints.emplace_back(convert_vec2<SkPoint>(arcPoints[i]));
|
||||
}
|
||||
bottomPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints.back()));
|
||||
bottomPoints.emplace_back(convert_vec2<SkPoint>(arcPoints.back()));
|
||||
}
|
||||
|
||||
for(size_t j = pointsBegin + 1; j < pointsEnd; j++) {
|
||||
if(j >= pointsEnd)
|
||||
j = pointsEnd - 1;
|
||||
|
||||
Vector2d v1 = points[j - 1].pos - points[j].pos;
|
||||
Vector2d v2 = points[j].pos - points[j + 1].pos;
|
||||
Vector2d perp = perpendicular_vec2((v1 + v2).eval()).normalized();
|
||||
Vector2f v1 = points[j - 1].pos - points[j].pos;
|
||||
Vector2f v2 = points[j].pos - points[j + 1].pos;
|
||||
Vector2f perp = perpendicular_vec2((v1 + v2).eval()).normalized();
|
||||
if(std::isnan(perp.dot(perpPrev))) {
|
||||
std::cout << "NAN FOUND" << std::endl;
|
||||
std::cout << v1 << std::endl;
|
||||
|
|
@ -396,57 +384,57 @@ void BrushStrokeCanvasComponent::create_triangles(const std::function<bool(Vecto
|
|||
if(perp.dot(perpPrev) < 0.0)
|
||||
perp = -perp;
|
||||
|
||||
vertArray[newIndex] = points[j].pos + perp * 0.5 * points[j].width;
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(vertArray[newIndex]));
|
||||
vertArray[newIndex] = points[j].pos + perp * 0.5f * points[j].width;
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(vertArray[newIndex]));
|
||||
newIndex = (newIndex + 1) % 3;
|
||||
if(passTriangleFunc(vertArray[0], vertArray[1], vertArray[2])) return;
|
||||
|
||||
vertArray[newIndex] = points[j].pos - perp * 0.5 * points[j].width;
|
||||
bottomPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(vertArray[newIndex]));
|
||||
vertArray[newIndex] = points[j].pos - perp * 0.5f * points[j].width;
|
||||
bottomPoints.emplace_back(convert_vec2<SkPoint>(vertArray[newIndex]));
|
||||
newIndex = (newIndex + 1) % 3;
|
||||
if(passTriangleFunc(vertArray[0], vertArray[1], vertArray[2])) return;
|
||||
|
||||
perpPrev = perp;
|
||||
}
|
||||
|
||||
Vector2d rectDir = points[pointsEnd - 1].pos - points[pointsEnd].pos;
|
||||
Vector2f rectDir = points[pointsEnd - 1].pos - points[pointsEnd].pos;
|
||||
rectDir.normalize();
|
||||
Vector2d perp = perpendicular_vec2(rectDir);
|
||||
Vector2f perp = perpendicular_vec2(rectDir);
|
||||
if(perp.dot(perpPrev) < 0.0)
|
||||
perp = -perp;
|
||||
vertArray[newIndex] = points[pointsEnd].pos + perp * points[pointsEnd].width * 0.5;
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(vertArray[newIndex]));
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(vertArray[newIndex]));
|
||||
newIndex = (newIndex + 1) % 3;
|
||||
if(passTriangleFunc(vertArray[0], vertArray[1], vertArray[2])) return;
|
||||
|
||||
vertArray[newIndex] = points[pointsEnd].pos - perp * points[pointsEnd].width * 0.5;
|
||||
bottomPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(vertArray[newIndex]));
|
||||
bottomPoints.emplace_back(convert_vec2<SkPoint>(vertArray[newIndex]));
|
||||
newIndex = (newIndex + 1) % 3;
|
||||
if(passTriangleFunc(vertArray[0], vertArray[1], vertArray[2])) return;
|
||||
|
||||
// Render wedge
|
||||
if(pointsEnd != points.size() - 1) {
|
||||
// Find 4 points involved in intersection
|
||||
Vector2d currentP1 = points[pointsEnd].pos - perp * points[pointsEnd].width * 0.5;
|
||||
Vector2d currentP2 = points[pointsEnd].pos + perp * points[pointsEnd].width * 0.5;
|
||||
Vector2d nextRectDir = points[pointsEnd + 1].pos - points[pointsEnd].pos;
|
||||
Vector2f currentP1 = points[pointsEnd].pos - perp * points[pointsEnd].width * 0.5;
|
||||
Vector2f currentP2 = points[pointsEnd].pos + perp * points[pointsEnd].width * 0.5;
|
||||
Vector2f nextRectDir = points[pointsEnd + 1].pos - points[pointsEnd].pos;
|
||||
nextRectDir.normalize();
|
||||
Vector2d nextPerp = perpendicular_vec2(nextRectDir);
|
||||
Vector2d nextP1 = points[pointsEnd].pos - nextPerp * points[pointsEnd].width * 0.5;
|
||||
Vector2d nextP2 = points[pointsEnd].pos + nextPerp * points[pointsEnd].width * 0.5;
|
||||
Vector2f nextPerp = perpendicular_vec2(nextRectDir);
|
||||
Vector2f nextP1 = points[pointsEnd].pos - nextPerp * points[pointsEnd].width * 0.5;
|
||||
Vector2f nextP2 = points[pointsEnd].pos + nextPerp * points[pointsEnd].width * 0.5;
|
||||
|
||||
// Find center of wedge
|
||||
Vector2d wedgeCenter = line_line_intersection(currentP1, currentP2, nextP1, nextP2);
|
||||
Vector2f wedgeCenter = line_line_intersection(currentP1, currentP2, nextP1, nextP2);
|
||||
|
||||
Vector2d wedgeP1 = ((currentP1 - currentP2).dot(nextRectDir)) <= 0.0 ? currentP1 : currentP2;
|
||||
Vector2d wedgeP2 = ((nextP1 - nextP2).dot(rectDir)) <= 0.0 ? nextP1 : nextP2;
|
||||
bool isTopWedge = convert_vec2_narrow_double_to_float<SkPoint>(wedgeP1) == topPoints.back();
|
||||
Vector2f wedgeP1 = ((currentP1 - currentP2).dot(nextRectDir)) <= 0.0 ? currentP1 : currentP2;
|
||||
Vector2f wedgeP2 = ((nextP1 - nextP2).dot(rectDir)) <= 0.0 ? nextP1 : nextP2;
|
||||
bool isTopWedge = wedgeP1 == convert_vec2<Vector2f>(topPoints.back());
|
||||
|
||||
double arcRadius;
|
||||
float arcRadius;
|
||||
|
||||
std::vector<Vector2d> arcPoints;
|
||||
std::vector<Vector2f> arcPoints;
|
||||
|
||||
if(wedgeCenter.x() == std::numeric_limits<double>::max()) {
|
||||
if(wedgeCenter.x() == std::numeric_limits<float>::max()) {
|
||||
wedgeCenter = (currentP1 + currentP2) * 0.5;
|
||||
wedgeP1 = currentP1;
|
||||
wedgeP2 = currentP2;
|
||||
|
|
@ -463,27 +451,27 @@ void BrushStrokeCanvasComponent::create_triangles(const std::function<bool(Vecto
|
|||
for(size_t i = 0; i < arcPoints.size() - 1; i++) {
|
||||
if(passTriangleFunc(wedgeCenter, arcPoints[i], arcPoints[i + 1])) return;
|
||||
if(isTopWedge)
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints[i]));
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(arcPoints[i]));
|
||||
else
|
||||
bottomPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints[i]));
|
||||
bottomPoints.emplace_back(convert_vec2<SkPoint>(arcPoints[i]));
|
||||
}
|
||||
if(isTopWedge)
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints.back()));
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(arcPoints.back()));
|
||||
else
|
||||
bottomPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints.back()));
|
||||
bottomPoints.emplace_back(convert_vec2<SkPoint>(arcPoints.back()));
|
||||
}
|
||||
else if(d.hasRoundCaps) { // It's the last point, cap it off
|
||||
Vector2d arcDirStart = (vertArray[(newIndex + 1) % 3] - points.back().pos).normalized();
|
||||
Vector2d arcDirEnd = (vertArray[(newIndex + 2) % 3] - points.back().pos).normalized();
|
||||
Vector2d arcDirCenter = -rectDir;
|
||||
std::vector<Vector2d> arcPoints = arc_vec(points.back().pos, arcDirStart, arcDirEnd, arcDirCenter, points.back().width * 0.5, ARC_SMOOTHNESS);
|
||||
arcPoints.emplace(arcPoints.begin(), vertArray[(newIndex + 1) % 3]);
|
||||
arcPoints.emplace_back(vertArray[(newIndex + 2) % 3]);
|
||||
Vector2f arcDirStart = (convert_vec2<Vector2f>(vertArray[(newIndex + 1) % 3]) - points.back().pos).normalized();
|
||||
Vector2f arcDirEnd = (convert_vec2<Vector2f>(vertArray[(newIndex + 2) % 3]) - points.back().pos).normalized();
|
||||
Vector2f arcDirCenter = -rectDir;
|
||||
std::vector<Vector2f> arcPoints = arc_vec<float>(points.back().pos, arcDirStart, arcDirEnd, arcDirCenter, points.back().width * 0.5f, ARC_SMOOTHNESS);
|
||||
arcPoints.emplace(arcPoints.begin(), convert_vec2<Vector2f>(vertArray[(newIndex + 1) % 3]));
|
||||
arcPoints.emplace_back(convert_vec2<Vector2f>(vertArray[(newIndex + 2) % 3]));
|
||||
for(size_t i = 0; i < arcPoints.size() - 1; i++) {
|
||||
if(passTriangleFunc(points.back().pos, arcPoints[i], arcPoints[i + 1])) return;
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints[i]));
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(arcPoints[i]));
|
||||
}
|
||||
topPoints.emplace_back(convert_vec2_narrow_double_to_float<SkPoint>(arcPoints.back()));
|
||||
topPoints.emplace_back(convert_vec2<SkPoint>(arcPoints.back()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -498,9 +486,9 @@ void BrushStrokeCanvasComponent::create_collider() {
|
|||
if(d.points->empty())
|
||||
return;
|
||||
ColliderCollection<float> strokeObjects;
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
create_triangles([&](Vector2d a, Vector2d b, Vector2d c) {
|
||||
strokeObjects.triangle.emplace_back(a.cast<float>(), b.cast<float>(), c.cast<float>());
|
||||
std::vector<BrushStrokeCanvasComponentPoint> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
create_triangles([&](Vector2f a, Vector2f b, Vector2f c) {
|
||||
strokeObjects.triangle.emplace_back(a, b, c);
|
||||
return false;
|
||||
}, points, 0, nullptr);
|
||||
strokeObjects.recalculate_bounds();
|
||||
|
|
@ -538,9 +526,9 @@ bool BrushStrokeCanvasComponent::collides_within_coords(const SCollision::Collid
|
|||
return false;
|
||||
|
||||
bool toRet = false;
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
create_triangles([&](Vector2d a, Vector2d b, Vector2d c) {
|
||||
toRet = SCollision::collide(checkAgainst, SCollision::Triangle<float>{a.cast<float>(), b.cast<float>(), c.cast<float>()});
|
||||
std::vector<BrushStrokeCanvasComponentPoint> points = smooth_points(0, d.points->size() - 1, DEFAULT_SMOOTHNESS);
|
||||
create_triangles([&](Vector2f a, Vector2f b, Vector2f c) {
|
||||
toRet = SCollision::collide(checkAgainst, SCollision::Triangle<float>{a, b, c});
|
||||
return toRet;
|
||||
}, points, 0, nullptr);
|
||||
return toRet;
|
||||
|
|
|
|||
|
|
@ -13,13 +13,6 @@ struct BrushStrokeCanvasComponentPoint {
|
|||
}
|
||||
};
|
||||
|
||||
struct BrushStrokeCanvasComponentPointDouble {
|
||||
BrushStrokeCanvasComponentPointDouble();
|
||||
BrushStrokeCanvasComponentPointDouble(const BrushStrokeCanvasComponentPoint& p);
|
||||
Vector2d pos;
|
||||
double width;
|
||||
};
|
||||
|
||||
class BrushStrokeCanvasComponent : public CanvasComponent {
|
||||
public:
|
||||
constexpr static float DRAW_MINIMUM_LIMIT = 0.3;
|
||||
|
|
@ -57,13 +50,13 @@ class BrushStrokeCanvasComponent : public CanvasComponent {
|
|||
|
||||
std::array<std::shared_ptr<SkPath>, 2> brushPathLOD;
|
||||
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> every_nth_point_include_front_and_back(const std::vector<BrushStrokeCanvasComponentPointDouble>& pts, size_t n) const;
|
||||
std::vector<BrushStrokeCanvasComponentPoint> every_nth_point_include_front_and_back(const std::vector<BrushStrokeCanvasComponentPoint>& pts, size_t n) const;
|
||||
|
||||
void add_precheck_aabb_level(size_t level, const std::vector<SCollision::BVHContainer<float>>& levelArray);
|
||||
std::vector<SCollision::AABB<float>> precheckAABBLevels;
|
||||
void create_triangles(const std::function<bool(Vector2d, Vector2d, Vector2d)>& passTriangleFunc, const std::vector<BrushStrokeCanvasComponentPointDouble>& smoothedPoints, size_t skipVertexCount, std::shared_ptr<SkPathBuilder> bPath) const;
|
||||
std::vector<size_t> get_wedge_indices(const std::vector<BrushStrokeCanvasComponentPointDouble>& points) const;
|
||||
std::vector<BrushStrokeCanvasComponentPointDouble> smooth_points(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const;
|
||||
//std::vector<BrushStrokeCanvasComponentPoint> smooth_points_avg(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const;
|
||||
void create_triangles(const std::function<bool(Vector2f, Vector2f, Vector2f)>& passTriangleFunc, const std::vector<BrushStrokeCanvasComponentPoint>& smoothedPoints, size_t skipVertexCount, std::shared_ptr<SkPathBuilder> bPath) const;
|
||||
std::vector<size_t> get_wedge_indices(const std::vector<BrushStrokeCanvasComponentPoint>& points) const;
|
||||
std::vector<BrushStrokeCanvasComponentPoint> smooth_points(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const;
|
||||
std::vector<BrushStrokeCanvasComponentPoint> smooth_points_avg(size_t beginIndex, size_t endIndex, unsigned numOfDivisions) const;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue