实现解析svg path

dev-VirtualTexture
wuyize 2022-10-07 00:01:19 +08:00
parent e849479236
commit 4f9611c385
14 changed files with 149 additions and 61 deletions

View File

@ -58,6 +58,16 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="Configuration">
<ClCompile>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
@ -97,6 +107,7 @@
<ClCompile Include="RendererWidget.cpp" />
<ClCompile Include="ShortCutTree.cpp" />
<ClCompile Include="StraightLine.cpp" />
<ClCompile Include="SvgParser.cpp" />
<QtRcc Include="MainWindow.qrc" />
<QtUic Include="MainWindow.ui" />
<QtMoc Include="MainWindow.h" />
@ -137,6 +148,7 @@
<ClInclude Include="PaintingMesh.h" />
<ClInclude Include="ShortCutTree.h" />
<ClInclude Include="StraightLine.h" />
<ClInclude Include="SvgParser.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">

View File

@ -79,6 +79,9 @@
<ClCompile Include="StraightLine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SvgParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="RendererWidget.h">
@ -172,5 +175,8 @@
<ClInclude Include="StraightLine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SvgParser.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -10,7 +10,7 @@
#include <vector>
#include <cmath>
using std::tr1::shared_ptr;
using std::shared_ptr;
struct BvhTreeData {
QVector4D bound;
@ -59,7 +59,7 @@ struct BvhNode {
~BvhNode() {}
};
typedef std::tr1::shared_ptr<BvhNode> BvhPtr;
typedef std::shared_ptr<BvhNode> BvhPtr;
class BvhTree
{

View File

@ -8,11 +8,11 @@ float CubicBezier::getLineValueByT(float t, bool isY) {
return pt * pt * pt * p[0] + 3 * t * pt * pt * p[1] + 3 * t * t * pt * p[2] + t * t * t * p[3];
}
point CubicBezier::getPointByT(point a, point b, float t) {
Point CubicBezier::getPointByT(Point a, Point b, float t) {
return { a.x * (1 - t) + b.x * t, a.y * (1 - t) + b.y * t };
}
point CubicBezier::calculateControlPoint(point a, point b) {
Point CubicBezier::calculateControlPoint(Point a, Point b) {
return {
a.x + 2 * (b.x - a.x) / 3,
a.y + 2 * (b.y - a.y) / 3
@ -47,7 +47,7 @@ void CubicBezier::findPointsOfDivison(vector<float> &p, vector<float>& res) {
void CubicBezier::transformToCubic() {
if (siz == 4) return;
point p[3] = {
Point p[3] = {
getPointByIndex(0),
getPointByIndex(1),
getPointByIndex(2)
@ -61,10 +61,10 @@ void CubicBezier::transformToCubic() {
void CubicBezier::splitBezierCubic(float t, vector<LinePtr>& res) {
LinePtr Lf(new CubicBezier());
float pt = 1 - t;
point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) };
point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t);
point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t);
point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t);
Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) };
Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t);
Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t);
Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t);
Lf->push_back(getPointByIndex(0));
Lf->push_back(pointF);
Lf->push_back(getPointByT(pointF, pointG, t));

View File

@ -6,8 +6,8 @@ class CubicBezier : public Line
{
using Line::Line;
private:
static point getPointByT(point a, point b, float t);
static point calculateControlPoint(point a, point b);
static Point getPointByT(Point a, Point b, float t);
static Point calculateControlPoint(Point a, Point b);
static void findPointsOfDivison(vector<float> &p, vector<float>& res);
void splitBezierCubic(float t, vector<LinePtr>& res);
public:

View File

@ -1,8 +1,8 @@
#include "Line.h"
Line::Line(vector<point> Vp) {
Line::Line(vector<Point> Vp) {
siz = Vp.size();
for (point now : Vp) {
for (Point now : Vp) {
vX.push_back(now.x);
vY.push_back(now.y);
}
@ -12,23 +12,23 @@ int Line::size() {
return siz;
}
vector<point> Line::toPointVector() const {
vector<point> vL;
vector<Point> Line::toPointVector() const {
vector<Point> vL;
for (int i = 0; i < siz; i++) {
vL.push_back({vX[i], vY[i]});
}
return vL;
}
point Line::operator[](int index) const {
Point Line::operator[](int index) const {
return { vX[index], vY[index] };
}
point Line::getPointByIndex(int index) const {
Point Line::getPointByIndex(int index) const {
return operator[](index);
}
void Line::setPointByIndex(int index, point now) {
void Line::setPointByIndex(int index, Point now) {
vX[index] = now.x;
vY[index] = now.y;
}
@ -38,7 +38,7 @@ void Line::clear() {
vY.clear();
}
void Line::push_back(point now) {
void Line::push_back(Point now) {
siz++;
vX.push_back(now.x);
vY.push_back(now.y);
@ -52,11 +52,11 @@ bool Line::isLineContained(QVector4D bound) {
else return false;
}
point Line::getBegin() {
Point Line::getBegin() {
return { *vX.begin(), *vY.begin() };
}
point Line::getEnd() {
Point Line::getEnd() {
return { *vX.rbegin(), *vY.rbegin() };
}

View File

@ -12,20 +12,20 @@ using std::pair;
using std::min;
using std::max;
using std::sort;
using std::tr1::shared_ptr;
using std::tr1::make_shared;
using std::shared_ptr;
using std::make_shared;
using std::swap;
const float eps = 1e-6;
struct point {
struct Point {
float x, y;
point operator - (const point a) { return { x - a.x, y - a.y }; }
float operator * (const point a) { return x * a.y - y * a.x; }
bool operator== (const point& a) const {
Point operator - (const Point a) { return { x - a.x, y - a.y }; }
float operator * (const Point a) { return x * a.y - y * a.x; }
bool operator== (const Point& a) const {
return fabs(x - a.x) <= eps && fabs(y - a.y) <= eps;
}
bool operator< (const point& a) const {
bool operator< (const Point& a) const {
return fabs(x - a.x) <= eps ? y < a.y : x < a.x;
}
void show() {
@ -41,22 +41,22 @@ protected:
public:
typedef shared_ptr<Line> LinePtr;
Line() :siz(0) {}
Line(vector<point> Vp);
Line(vector<Point> Vp);
int size();
void clear();
point getBegin();
point getEnd();
Point getBegin();
Point getEnd();
int direction(bool isY);
virtual float getLineValueByT(float t, bool isY) = 0;
virtual void monotonization(vector <LinePtr>& res) = 0;
virtual int judgeBoundIntersection(float xy, float l, float r, bool isY) = 0;
virtual bool judgeIntersection(QVector4D bound);
bool isLineContained(QVector4D bound);
point operator[](int index) const;
point getPointByIndex(int index) const;
vector<point> toPointVector() const;
void setPointByIndex(int index, point now);
void push_back(point now);
Point operator[](int index) const;
Point getPointByIndex(int index) const;
vector<Point> toPointVector() const;
void setPointByIndex(int index, Point now);
void push_back(Point now);
virtual ~Line() {}
};

View File

@ -8,6 +8,7 @@
#include <QtMath>
#include "BvhTree.h"
#include "ShortCutTree.h"
#include "SvgParser.h"
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
: context(context)
@ -186,11 +187,20 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
initBound.push_back(QVector4D(-0.8, 0.7, -0.7, 0.8));
initBound.push_back(QVector4D(0.7, -0.8, 0.8, -0.7));
initBound.push_back(QVector4D(0.7, 0.7, 0.8, 0.8));*/
//bvhTree.buildBvhTree(initBound.data(), initBound.size());
//vector<vector<point>> lineSet = { {point{-1,-1}, point{1,-1}},{point{1,-1}, point{1,1}}, {point{1,1}, point{-1,1}},{point{-1,1}, point{-1,-1}} };
vector<vector<point>> lineSet = { {point{-1,-1}, point{1,-1}},{point{1,-1}, point{1,1}}, {point{1,1}, point{-1,1}},{point{-1,1}, point{-1,-1}} };
ShortCutTree shortCutTree;
//bvhTree.buildBvhTree(initBound.data(), initBound.size());
vector<vector<Point>> lineSet = SvgParser::parse("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100,100);
for (vector<Point> line : lineSet)
{
for (Point p : line)
p.show();
std::cout << std::endl;
}
//vector<vector<Point>> lineSet = { {Point{-1,-1}, Point{1,-1}},{Point{1,-1}, Point{1,1}}, {Point{1,1}, Point{-1,1}},{Point{-1,1}, Point{-1,-1}} };
//vector<vector<Point>> lineSet = { {Point{-1,-1}, Point{1,-1}},{Point{1,-1}, Point{1,1}}, {Point{1,1}, Point{-1,1}},{Point{-1,1}, Point{-1,-1}} };
ShortCutTree shortCutTree(5);
shortCutTree.buildShortCutTree(lineSet);
vector<float> pointVector;
vector<GLuint> lineVector;
@ -296,7 +306,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
3, 0,2,3,
//element1
//lines
0,1,1,2
0,1,1,2
};
std::vector<GLfloat> elementData0 = {

View File

@ -8,7 +8,7 @@ void ShortCutTree::init() {
numLine = numPoint = 0;
}
int ShortCutTree::getPointIndex(point nowPoint) {
int ShortCutTree::getPointIndex(Point nowPoint) {
auto iter = pointMap.find(nowPoint);
if (iter != pointMap.end()) {
return iter->second;
@ -44,7 +44,7 @@ void ShortCutTree::monotonization(vector<PointVector>& inL, vector<LinePtr>& out
}
void ShortCutTree::generateShortCutsegmentement(ShortCutNode& nowTreeNode) {
point p = {0, 0};
Point p = {0, 0};
vector<int> v;
for (int & lineIndex : nowTreeNode.lineSet) {
int type = allLine[lineIndex]->judgeBoundIntersection(nowTreeNode.bound.z(), nowTreeNode.bound.y(), nowTreeNode.bound.w(), false), be, en;
@ -112,7 +112,7 @@ void ShortCutTree::simplifyLineVector() {
numLine = allLine.size();
for (auto& nowLine : allLine) {
PointVector pointVector = nowLine->toPointVector();
for (point& p : pointVector) {
for (Point& p : pointVector) {
int pointIndex = getPointIndex(p);
lineIndexs.push_back(pointIndex);
if (pointVector.size() == 2)
@ -216,7 +216,10 @@ void ShortCutTree::buildShortCutTree(vector<PointVector>& lineSet) {
}
vector<BvhTreeData> ShortCutTree::getPointLineAndBvhTree(vector<float>& resPoints, vector<GLuint>& resLines) {
vector<pair<GLuint, point> > tmpPoints; tmpPoints.clear();
vector<pair<GLuint, Point> > tmpPoints; tmpPoints.clear();
for (auto& now : restOfTreeNodes) {
std::cout << now.windingIncrement << ' ';
}
for (auto& mapIter : pointMap) {
tmpPoints.push_back({ mapIter.second , mapIter.first});
}

View File

@ -9,7 +9,7 @@ using std::map;
using std::for_each;
struct ShortCutNode {
typedef vector<point> vectorPoint;
typedef vector<Point> vectorPoint;
int windingIncrement;
bool divided;
/* type 代表进入广度优先搜索队列的节点种类:
@ -27,16 +27,16 @@ struct ShortCutNode {
};
class ShortCutTree
{
typedef vector<point> PointVector;
typedef vector<Point> PointVector;
typedef vector<int> PointIndexVector;
private:
vector<ShortCutNode> restOfTreeNodes;
vector<LinePtr> allLine;
int RequiredLineMin, numPoint, numLine;
map<point, int> pointMap;
map<Point, int> pointMap;
vector<int> lineIndexs;
int getPointIndex(point nowPoint);
int getPointIndex(Point nowPoint);
void generateShortCutsegmentement(ShortCutNode& nowTreeNode);
bool handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNode, float yValue, vector<ShortCutNode>& v, int& sumIncrement);
void spliteToShortCutTree();
@ -48,7 +48,7 @@ public:
//lineMin最小线数目即划分终止条件
ShortCutTree(int lineMin = 3)
:RequiredLineMin(lineMin), numPoint(0), numLine(0) {}
// 传入一个vector<vector<point> > 作为所有输入的线
// 传入一个vector<vector<Point> > 作为所有输入的线
void buildShortCutTree(vector<PointVector>& lineSet);
// 获得点集合和线集合 返回输入BvhTree的数据集合
vector<BvhTreeData> getPointLineAndBvhTree(vector<float> &pointSet, vector<GLuint> &lineSet);

View File

@ -14,7 +14,7 @@ float StraightLine::getLineValueByT(float t, bool isY) {
}
float StraightLine::findTByValue(float value, bool isY) {
point be = getPointByIndex(0), en = getPointByIndex(1);
Point be = getPointByIndex(0), en = getPointByIndex(1);
if (!isY) {
if(fabs(be.x - en.x) <= eps) return 0;
return (value - be.x) / (en.x - be.x);
@ -26,7 +26,7 @@ float StraightLine::findTByValue(float value, bool isY) {
}
int StraightLine::judgeBoundIntersection(float xy, float l, float r, bool isY) {
point be = getBegin(), en = getEnd();
Point be = getBegin(), en = getEnd();
if (isY) {
swap(be.x, be.y);
swap(en.x, en.y);

View File

@ -0,0 +1,44 @@
#include "SvgParser.h"
#include <algorithm>
vector<vector<Point>> SvgParser::parse(const std::string path, float width, float height)
{
std::string tmp;
vector<float> point;
vector<Point> line;
vector<vector<Point>> lines;
for (char c : path.substr(1))
{
if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+')
{
tmp += c;
}
else
{
if (tmp != "")
{
point.push_back(std::stof(tmp));
tmp = "";
if (point.size() == 2)
{
line.push_back(Point{ std::clamp(point[0] / width * 2 - 1, -1.f, 1.f) , std::clamp(1 - point[1] / height * 2 , -1.f, 1.f)});
point.clear();
}
}
if (c != ',' && c != ' ')
{
lines.push_back(line);
line.erase(line.begin(), line.end() - 1);
if (c == 'Z')
{
line.push_back(lines[0][0]);
lines.push_back(line);
break;
}
}
}
}
lines.erase(lines.begin());
return lines;
}

View File

@ -0,0 +1,10 @@
#pragma once
#include <string>
#include "Line.h"
class SvgParser
{
public:
static vector<vector<Point>> parse(const std::string path, float width, float height);
};

View File

@ -1,17 +1,20 @@
# ArchitectureColoredPainting
vs2022项目 qt5.15.2 msvc 2019 64-bit
古建筑彩绘计算机辅助设计系统
采用pbr材质现在有一个随时间变化的方向光并添加了阴影
## 依赖
把一块布替换成了待完成的彩绘管线见PaintingMesh类以及painting着色器
- Qt 5.15.2 (MSVC 2019 64-bit)
- Assimp (x64-windows)
TODO
## 构建
- [x] 改用延迟渲染
使用 Visual Studio 2022 打开项目编译运行。
- [x] 指定一块材质使用独立管线进行纹理采样
## 进度
- [ ] 彩绘的表示、读取、采样...
采用 PBR (金属度-粗糙度) 材质模型,场景中存在一个方向光,可拖动滑动条调整光源方向观察材质效果。
- [x] PCF Shadow Map
已实现BVH加速结构的建立
基本实现单图元的拆分,即划分网格并生成快捷段和缠绕增量,尚未验证正确性