kopia lustrzana https://github.com/jameshball/osci-render
Various optimisations to improve obj file performance
rodzic
d8256ac812
commit
56eaa48bb1
|
@ -18,9 +18,7 @@ bool Connected(const Graph & G)
|
||||||
visited[u] = true;
|
visited[u] = true;
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
for(list<int>::const_iterator it = G.AdjList(u).begin(); it != G.AdjList(u).end(); it++)
|
for(int v : G.AdjList(u)) {
|
||||||
{
|
|
||||||
int v = *it;
|
|
||||||
L.push_back(v);
|
L.push_back(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +39,7 @@ pair< list<int>, double > ChinesePostman(const Graph& G, const vector<double>& c
|
||||||
throw "Error: Graph is not connected";
|
throw "Error: Graph is not connected";
|
||||||
|
|
||||||
//Build adjacency lists using edges in the graph
|
//Build adjacency lists using edges in the graph
|
||||||
vector< list<int> > A(G.GetNumVertices(), list<int>());
|
vector<vector<int>> A(G.GetNumVertices(), vector<int>());
|
||||||
for(int u = 0; u < G.GetNumVertices(); u++)
|
for(int u = 0; u < G.GetNumVertices(); u++)
|
||||||
A[u] = G.AdjList(u);
|
A[u] = G.AdjList(u);
|
||||||
|
|
||||||
|
@ -105,10 +103,7 @@ pair< list<int>, double > ChinesePostman(const Graph& G, const vector<double>& c
|
||||||
vector<int> traversed(G.GetNumEdges(), 0);
|
vector<int> traversed(G.GetNumEdges(), 0);
|
||||||
for(int u = 0; u < G.GetNumVertices(); u++)
|
for(int u = 0; u < G.GetNumVertices(); u++)
|
||||||
{
|
{
|
||||||
for(list<int>::iterator it = A[u].begin(); it != A[u].end(); it++)
|
for(int v : A[u]) {
|
||||||
{
|
|
||||||
int v = *it;
|
|
||||||
|
|
||||||
//we do this so that the edge is not counted twice
|
//we do this so that the edge is not counted twice
|
||||||
if(v < u) continue;
|
if(v < u) continue;
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,7 @@ pair< vector<int>, vector<double> > Dijkstra(const Graph & G, int origin, const
|
||||||
permanent[u] = true;
|
permanent[u] = true;
|
||||||
|
|
||||||
//Update the heap with vertices adjacent to u
|
//Update the heap with vertices adjacent to u
|
||||||
for(list<int>::const_iterator it = G.AdjList(u).begin(); it != G.AdjList(u).end(); it++)
|
for (int v : G.AdjList(u)) {
|
||||||
{
|
|
||||||
int v = *it;
|
|
||||||
|
|
||||||
if(permanent[v])
|
if(permanent[v])
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -19,21 +19,11 @@ Graph::Graph(int n, const list< pair<int, int> > & edges):
|
||||||
|
|
||||||
pair<int, int> Graph::GetEdge(int e) const
|
pair<int, int> Graph::GetEdge(int e) const
|
||||||
{
|
{
|
||||||
if(e > (int)edges.size())
|
|
||||||
throw "Error: edge does not exist";
|
|
||||||
|
|
||||||
return edges[e];
|
return edges[e];
|
||||||
}
|
}
|
||||||
|
|
||||||
int Graph::GetEdgeIndex(int u, int v) const
|
int Graph::GetEdgeIndex(int u, int v) const
|
||||||
{
|
{
|
||||||
if( u > n or
|
|
||||||
v > n )
|
|
||||||
throw "Error: vertex does not exist";
|
|
||||||
|
|
||||||
if(edgeIndex[u][v] == -1)
|
|
||||||
throw "Error: edge does not exist";
|
|
||||||
|
|
||||||
return edgeIndex[u][v];
|
return edgeIndex[u][v];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,15 +37,11 @@ void Graph::AddVertex()
|
||||||
n++;
|
n++;
|
||||||
adjMat.push_back( vector<bool>(n, false) );
|
adjMat.push_back( vector<bool>(n, false) );
|
||||||
edgeIndex.push_back( vector<int>(n, -1) );
|
edgeIndex.push_back( vector<int>(n, -1) );
|
||||||
adjList.push_back( list<int>() );
|
adjList.push_back( vector<int>() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graph::AddEdge(int u, int v)
|
void Graph::AddEdge(int u, int v)
|
||||||
{
|
{
|
||||||
if( u > n or
|
|
||||||
v > n )
|
|
||||||
throw "Error: vertex does not exist";
|
|
||||||
|
|
||||||
if(adjMat[u][v]) return;
|
if(adjMat[u][v]) return;
|
||||||
|
|
||||||
adjMat[u][v] = adjMat[v][u] = true;
|
adjMat[u][v] = adjMat[v][u] = true;
|
||||||
|
@ -66,7 +52,7 @@ void Graph::AddEdge(int u, int v)
|
||||||
edgeIndex[u][v] = edgeIndex[v][u] = m++;
|
edgeIndex[u][v] = edgeIndex[v][u] = m++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const list<int> & Graph::AdjList(int v) const
|
const vector<int>& Graph::AdjList(int v) const
|
||||||
{
|
{
|
||||||
if(v > n)
|
if(v > n)
|
||||||
throw "Error: vertex does not exist";
|
throw "Error: vertex does not exist";
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
void AddEdge(int u, int v);
|
void AddEdge(int u, int v);
|
||||||
|
|
||||||
//Returns the adjacency list of a vertex
|
//Returns the adjacency list of a vertex
|
||||||
const list<int> & AdjList(int v) const;
|
const vector<int>& AdjList(int v) const;
|
||||||
|
|
||||||
//Returns the graph's adjacency matrix
|
//Returns the graph's adjacency matrix
|
||||||
const vector< vector<bool> > & AdjMat() const;
|
const vector< vector<bool> > & AdjMat() const;
|
||||||
|
@ -44,11 +44,11 @@ private:
|
||||||
vector< vector<bool> > adjMat;
|
vector< vector<bool> > adjMat;
|
||||||
|
|
||||||
//Adjacency lists
|
//Adjacency lists
|
||||||
vector< list<int> > adjList;
|
vector<vector<int> > adjList;
|
||||||
|
|
||||||
//Array of edges
|
//Array of edges
|
||||||
vector< pair<int, int> > edges;
|
vector<pair<int, int> > edges;
|
||||||
|
|
||||||
//Indices of the edges
|
//Indices of the edges
|
||||||
vector< vector<int> > edgeIndex;
|
vector<vector<int> > edgeIndex;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include "Matching.h"
|
#include "Matching.h"
|
||||||
|
#include <deque>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
Matching::Matching(const Graph & G):
|
Matching::Matching(const Graph & G):
|
||||||
G(G),
|
G(G),
|
||||||
|
@ -33,14 +35,10 @@ void Matching::Grow()
|
||||||
|
|
||||||
//w might be a blossom
|
//w might be a blossom
|
||||||
//we have to explore all the connections from vertices inside the blossom to other vertices
|
//we have to explore all the connections from vertices inside the blossom to other vertices
|
||||||
for(list<int>::iterator it = deep[w].begin(); it != deep[w].end(); it++)
|
for(int u : deep[w]) {
|
||||||
{
|
|
||||||
int u = *it;
|
|
||||||
|
|
||||||
int cont = false;
|
int cont = false;
|
||||||
for(list<int>::const_iterator jt = G.AdjList(u).begin(); jt != G.AdjList(u).end(); jt++)
|
for(int v : G.AdjList(u)) {
|
||||||
{
|
|
||||||
int v = *jt;
|
|
||||||
|
|
||||||
if(IsEdgeBlocked(u, v)) continue;
|
if(IsEdgeBlocked(u, v)) continue;
|
||||||
|
|
||||||
|
@ -143,10 +141,7 @@ void Matching::Heuristic()
|
||||||
if(mate[outer[u]] == -1)
|
if(mate[outer[u]] == -1)
|
||||||
{
|
{
|
||||||
int min = -1;
|
int min = -1;
|
||||||
for(list<int>::const_iterator it = G.AdjList(u).begin(); it != G.AdjList(u).end(); it++)
|
for (int v : G.AdjList(u)) {
|
||||||
{
|
|
||||||
int v = *it;
|
|
||||||
|
|
||||||
if(IsEdgeBlocked(u, v) or
|
if(IsEdgeBlocked(u, v) or
|
||||||
(outer[u] == outer[v]) or
|
(outer[u] == outer[v]) or
|
||||||
(mate[outer[v]] != -1) )
|
(mate[outer[v]] != -1) )
|
||||||
|
@ -170,12 +165,10 @@ void Matching::DestroyBlossom(int t)
|
||||||
if((t < n) or
|
if((t < n) or
|
||||||
(blocked[t] and GREATER(dual[t], 0))) return;
|
(blocked[t] and GREATER(dual[t], 0))) return;
|
||||||
|
|
||||||
for(list<int>::iterator it = shallow[t].begin(); it != shallow[t].end(); it++)
|
for(int s : shallow[t]) {
|
||||||
{
|
|
||||||
int s = *it;
|
|
||||||
outer[s] = s;
|
outer[s] = s;
|
||||||
for(list<int>::iterator jt = deep[s].begin(); jt != deep[s].end(); jt++)
|
for(int d : deep[s])
|
||||||
outer[*jt] = s;
|
outer[d] = s;
|
||||||
|
|
||||||
DestroyBlossom(s);
|
DestroyBlossom(s);
|
||||||
}
|
}
|
||||||
|
@ -186,82 +179,84 @@ void Matching::DestroyBlossom(int t)
|
||||||
mate[t] = -1;
|
mate[t] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matching::Expand(int u, bool expandBlocked = false)
|
void Matching::Expand(int start, bool expandBlocked = false)
|
||||||
{
|
{
|
||||||
int v = outer[mate[u]];
|
std::stack<int> Q;
|
||||||
|
Q.push(start);
|
||||||
|
|
||||||
int index = m;
|
while (!Q.empty()) {
|
||||||
int p = -1, q = -1;
|
int u = Q.top();
|
||||||
//Find the regular edge {p,q} of minimum index connecting u and its mate
|
Q.pop();
|
||||||
//We use the minimum index to grant that the two possible blossoms u and v will use the same edge for a mate
|
int v = outer[mate[u]];
|
||||||
for(list<int>::iterator it = deep[u].begin(); it != deep[u].end(); it++)
|
|
||||||
{
|
int index = m;
|
||||||
int di = *it;
|
int p = -1, q = -1;
|
||||||
for(list<int>::iterator jt = deep[v].begin(); jt != deep[v].end(); jt++)
|
//Find the regular edge {p,q} of minimum index connecting u and its mate
|
||||||
{
|
//We use the minimum index to grant that the two possible blossoms u and v will use the same edge for a mate
|
||||||
int dj = *jt;
|
for (int di : deep[u]) {
|
||||||
if(IsAdjacent(di, dj) and G.GetEdgeIndex(di, dj) < index)
|
for (int dj : deep[v]) {
|
||||||
{
|
if (IsAdjacent(di, dj) and G.GetEdgeIndex(di, dj) < index)
|
||||||
index = G.GetEdgeIndex(di, dj);
|
{
|
||||||
p = di;
|
index = G.GetEdgeIndex(di, dj);
|
||||||
q = dj;
|
p = di;
|
||||||
|
q = dj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mate[u] = q;
|
|
||||||
mate[v] = p;
|
|
||||||
//If u is a regular vertex, we are done
|
|
||||||
if(u < n or (blocked[u] and not expandBlocked)) return;
|
|
||||||
|
|
||||||
bool found = false;
|
mate[u] = q;
|
||||||
//Find the position t of the new tip of the blossom
|
mate[v] = p;
|
||||||
for(list<int>::iterator it = shallow[u].begin(); it != shallow[u].end() and not found; )
|
//If u is a regular vertex, we are done
|
||||||
{
|
if (u < n or (blocked[u] and not expandBlocked)) continue;
|
||||||
int si = *it;
|
|
||||||
for(list<int>::iterator jt = deep[si].begin(); jt != deep[si].end() and not found; jt++)
|
bool found = false;
|
||||||
|
//Find the position t of the new tip of the blossom
|
||||||
|
for (list<int>::iterator it = shallow[u].begin(); it != shallow[u].end() and not found; )
|
||||||
{
|
{
|
||||||
if(*jt == p )
|
int si = *it;
|
||||||
found = true;
|
for (vector<int>::iterator jt = deep[si].begin(); jt != deep[si].end() and not found; jt++)
|
||||||
|
{
|
||||||
|
if (*jt == p)
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
it++;
|
||||||
|
if (not found)
|
||||||
|
{
|
||||||
|
shallow[u].push_back(si);
|
||||||
|
shallow[u].pop_front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list<int>::iterator it = shallow[u].begin();
|
||||||
|
//Adjust the mate of the tip
|
||||||
|
mate[*it] = mate[u];
|
||||||
it++;
|
it++;
|
||||||
if(not found)
|
//
|
||||||
|
//Now we go through the odd circuit adjusting the new mates
|
||||||
|
while (it != shallow[u].end())
|
||||||
{
|
{
|
||||||
shallow[u].push_back(si);
|
list<int>::iterator itnext = it;
|
||||||
shallow[u].pop_front();
|
itnext++;
|
||||||
|
mate[*it] = *itnext;
|
||||||
|
mate[*itnext] = *it;
|
||||||
|
itnext++;
|
||||||
|
it = itnext;
|
||||||
|
}
|
||||||
|
|
||||||
|
//We update the sets blossom, shallow, and outer since this blossom is being deactivated
|
||||||
|
for (int s : shallow[u]) {
|
||||||
|
outer[s] = s;
|
||||||
|
for (int d : deep[s])
|
||||||
|
outer[d] = s;
|
||||||
|
}
|
||||||
|
active[u] = false;
|
||||||
|
AddFreeBlossomIndex(u);
|
||||||
|
|
||||||
|
//Expand the vertices in the blossom
|
||||||
|
for (int s : shallow[u]) {
|
||||||
|
Q.push(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list<int>::iterator it = shallow[u].begin();
|
|
||||||
//Adjust the mate of the tip
|
|
||||||
mate[*it] = mate[u];
|
|
||||||
it++;
|
|
||||||
//
|
|
||||||
//Now we go through the odd circuit adjusting the new mates
|
|
||||||
while(it != shallow[u].end())
|
|
||||||
{
|
|
||||||
list<int>::iterator itnext = it;
|
|
||||||
itnext++;
|
|
||||||
mate[*it] = *itnext;
|
|
||||||
mate[*itnext] = *it;
|
|
||||||
itnext++;
|
|
||||||
it = itnext;
|
|
||||||
}
|
|
||||||
|
|
||||||
//We update the sets blossom, shallow, and outer since this blossom is being deactivated
|
|
||||||
for(list<int>::iterator it = shallow[u].begin(); it != shallow[u].end(); it++)
|
|
||||||
{
|
|
||||||
int s = *it;
|
|
||||||
outer[s] = s;
|
|
||||||
for(list<int>::iterator jt = deep[s].begin(); jt != deep[s].end(); jt++)
|
|
||||||
outer[*jt] = s;
|
|
||||||
}
|
|
||||||
active[u] = false;
|
|
||||||
AddFreeBlossomIndex(u);
|
|
||||||
|
|
||||||
//Expand the vertices in the blossom
|
|
||||||
for(list<int>::iterator it = shallow[u].begin(); it != shallow[u].end(); it++)
|
|
||||||
Expand(*it, expandBlocked);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,14 +391,11 @@ int Matching::Blossom(int u, int v)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now we construct deep and update outer
|
//Now we construct deep and update outer
|
||||||
for(list<int>::iterator it = shallow[t].begin(); it != shallow[t].end(); it++)
|
for(int u_ : shallow[t]) {
|
||||||
{
|
|
||||||
u_ = *it;
|
|
||||||
outer[u_] = t;
|
outer[u_] = t;
|
||||||
for(list<int>::iterator jt = deep[u_].begin(); jt != deep[u_].end(); jt++)
|
for(int d : deep[u_]) {
|
||||||
{
|
deep[t].push_back(d);
|
||||||
deep[t].push_back(*jt);
|
outer[d] = t;
|
||||||
outer[*jt] = t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,10 +415,16 @@ void Matching::UpdateDualCosts()
|
||||||
int inite1 = false, inite2 = false, inite3 = false;
|
int inite1 = false, inite2 = false, inite3 = false;
|
||||||
for(int i = 0; i < m; i++)
|
for(int i = 0; i < m; i++)
|
||||||
{
|
{
|
||||||
int u = G.GetEdge(i).first,
|
auto edge = G.GetEdge(i);
|
||||||
v = G.GetEdge(i).second;
|
int u = edge.first,
|
||||||
|
v = edge.second;
|
||||||
|
|
||||||
if( (type[outer[u]] == EVEN and type[outer[v]] == UNLABELED) or (type[outer[v]] == EVEN and type[outer[u]] == UNLABELED) )
|
int outer_u = outer[u];
|
||||||
|
int outer_v = outer[v];
|
||||||
|
int type_u = type[outer_u];
|
||||||
|
int type_v = type[outer_v];
|
||||||
|
|
||||||
|
if( (type_u == EVEN and type_v == UNLABELED) or (type_v == EVEN and type_u == UNLABELED) )
|
||||||
{
|
{
|
||||||
if(!inite1 or GREATER(e1, slack[i]))
|
if(!inite1 or GREATER(e1, slack[i]))
|
||||||
{
|
{
|
||||||
|
@ -434,7 +432,7 @@ void Matching::UpdateDualCosts()
|
||||||
inite1 = true;
|
inite1 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( (outer[u] != outer[v]) and type[outer[u]] == EVEN and type[outer[v]] == EVEN )
|
else if( (outer_u != outer_v) and type_u == EVEN and type_v == EVEN )
|
||||||
{
|
{
|
||||||
if(!inite2 or GREATER(e2, slack[i]))
|
if(!inite2 or GREATER(e2, slack[i]))
|
||||||
{
|
{
|
||||||
|
@ -477,18 +475,24 @@ void Matching::UpdateDualCosts()
|
||||||
|
|
||||||
for(int i = 0; i < m; i++)
|
for(int i = 0; i < m; i++)
|
||||||
{
|
{
|
||||||
int u = G.GetEdge(i).first,
|
auto edge = G.GetEdge(i);
|
||||||
v = G.GetEdge(i).second;
|
int u = edge.first,
|
||||||
|
v = edge.second;
|
||||||
|
|
||||||
if(outer[u] != outer[v])
|
int outer_u = outer[u];
|
||||||
|
int outer_v = outer[v];
|
||||||
|
int type_u = type[outer_u];
|
||||||
|
int type_v = type[outer_v];
|
||||||
|
|
||||||
|
if(outer_u != outer_v)
|
||||||
{
|
{
|
||||||
if(type[outer[u]] == EVEN and type[outer[v]] == EVEN)
|
if(type_u == EVEN and type_v == EVEN)
|
||||||
slack[i] -= 2.0*e;
|
slack[i] -= 2.0*e;
|
||||||
else if(type[outer[u]] == ODD and type[outer[v]] == ODD)
|
else if(type_u == ODD and type_v == ODD)
|
||||||
slack[i] += 2.0*e;
|
slack[i] += 2.0*e;
|
||||||
else if( (type[outer[v]] == UNLABELED and type[outer[u]] == EVEN) or (type[outer[u]] == UNLABELED and type[outer[v]] == EVEN) )
|
else if( (type_v == UNLABELED and type_u == EVEN) or (type_u == UNLABELED and type_v == EVEN) )
|
||||||
slack[i] -= e;
|
slack[i] -= e;
|
||||||
else if( (type[outer[v]] == UNLABELED and type[outer[u]] == ODD) or (type[outer[u]] == UNLABELED and type[outer[v]] == ODD) )
|
else if( (type_v == UNLABELED and type_u == ODD) or (type_u == UNLABELED and type_v == ODD) )
|
||||||
slack[i] += e;
|
slack[i] += e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ private:
|
||||||
list<int> free;//List of free blossom indices
|
list<int> free;//List of free blossom indices
|
||||||
|
|
||||||
vector<int> outer;//outer[v] gives the index of the outermost blossom that contains v, outer[v] = v if v is not contained in any blossom
|
vector<int> outer;//outer[v] gives the index of the outermost blossom that contains v, outer[v] = v if v is not contained in any blossom
|
||||||
vector< list<int> > deep;//deep[v] is a list of all the original vertices contained inside v, deep[v] = v if v is an original vertex
|
vector< vector<int> > deep;//deep[v] is a list of all the original vertices contained inside v, deep[v] = v if v is an original vertex
|
||||||
vector< list<int> > shallow;//shallow[v] is a list of the vertices immediately contained inside v, shallow[v] is empty is the default
|
vector< list<int> > shallow;//shallow[v] is a list of the vertices immediately contained inside v, shallow[v] is empty is the default
|
||||||
vector<int> tip;//tip[v] is the tip of blossom v
|
vector<int> tip;//tip[v] is the tip of blossom v
|
||||||
vector<bool> active;//true if a blossom is being used
|
vector<bool> active;//true if a blossom is being used
|
||||||
|
|
|
@ -8,10 +8,14 @@ struct pair_hash {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// returns all vertex indices in all connected sub-components of the graph
|
||||||
|
//
|
||||||
std::vector<std::vector<int>> ConnectedComponents(const Graph& G) {
|
std::vector<std::vector<int>> ConnectedComponents(const Graph& G) {
|
||||||
std::vector<std::vector<int>> components;
|
std::vector<std::vector<int>> components;
|
||||||
std::vector<bool> visited(G.GetNumVertices(), false);
|
std::vector<bool> visited(G.GetNumVertices(), false);
|
||||||
list<int> L;
|
std::list<int> L;
|
||||||
|
|
||||||
for (int i = 0; i < visited.size(); i++) {
|
for (int i = 0; i < visited.size(); i++) {
|
||||||
// if condition should only be true for the first element in
|
// if condition should only be true for the first element in
|
||||||
|
@ -38,18 +42,20 @@ std::vector<std::vector<int>> ConnectedComponents(const Graph& G) {
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldObject::WorldObject(juce::InputStream& stream) {
|
WorldObject::WorldObject(std::string obj_string) {
|
||||||
tinyobj::ObjReaderConfig reader_config;
|
tinyobj::ObjReaderConfig reader_config;
|
||||||
tinyobj::ObjReader reader;
|
tinyobj::ObjReader reader;
|
||||||
|
|
||||||
reader.ParseFromString(stream.readEntireStreamAsString().toStdString(), "", reader_config);
|
reader.ParseFromString(obj_string, "", reader_config);
|
||||||
|
|
||||||
vs = reader.GetAttrib().vertices;
|
vs = reader.GetAttrib().vertices;
|
||||||
numVertices = vs.size() / 3;
|
numVertices = vs.size() / 3;
|
||||||
|
|
||||||
|
//
|
||||||
|
// normalising object vertices
|
||||||
|
//
|
||||||
double x = 0.0, y = 0.0, z = 0.0;
|
double x = 0.0, y = 0.0, z = 0.0;
|
||||||
double max = 0.0;
|
double max = 0.0;
|
||||||
|
|
||||||
for (int i = 0; i < numVertices; i++) {
|
for (int i = 0; i < numVertices; i++) {
|
||||||
x += vs[i * 3];
|
x += vs[i * 3];
|
||||||
y += vs[i * 3 + 1];
|
y += vs[i * 3 + 1];
|
||||||
|
@ -74,14 +80,19 @@ WorldObject::WorldObject(juce::InputStream& stream) {
|
||||||
vs[i * 3 + 2] = (vs[i * 3 + 2] - z) / max;
|
vs[i * 3 + 2] = (vs[i * 3 + 2] - z) / max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// getting edges from obj file
|
||||||
|
//
|
||||||
std::vector<tinyobj::shape_t> shapes = reader.GetShapes();
|
std::vector<tinyobj::shape_t> shapes = reader.GetShapes();
|
||||||
|
|
||||||
std::unordered_set<std::pair<int, int>, pair_hash> edge_set;
|
std::unordered_set<std::pair<int, int>, pair_hash> edge_set;
|
||||||
|
|
||||||
for (auto& shape : shapes) {
|
for (auto& shape : shapes) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int face = 0;
|
int face = 0;
|
||||||
while (i < shape.mesh.indices.size()) {
|
while (i < shape.mesh.indices.size()) {
|
||||||
int prevVertex = -1;
|
int prevVertex = -1;
|
||||||
|
// num_face_vertices stores the number of vertices per face, used to
|
||||||
|
// iterate through mesh.indices and know when a face starts/ends
|
||||||
for (int j = 0; j < shape.mesh.num_face_vertices[face]; j++) {
|
for (int j = 0; j < shape.mesh.num_face_vertices[face]; j++) {
|
||||||
int vertex = shape.mesh.indices[i].vertex_index;
|
int vertex = shape.mesh.indices[i].vertex_index;
|
||||||
if (prevVertex != -1) {
|
if (prevVertex != -1) {
|
||||||
|
@ -101,10 +112,19 @@ WorldObject::WorldObject(juce::InputStream& stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Graph graph(numVertices, edge_list);
|
Graph graph(numVertices, edge_list);
|
||||||
|
|
||||||
std::vector<std::vector<int>> connected_components = ConnectedComponents(graph);
|
std::vector<std::vector<int>> connected_components = ConnectedComponents(graph);
|
||||||
|
|
||||||
|
// perform chinese postman on all connected sub-components of graph
|
||||||
for (auto& connected_component : connected_components) {
|
for (auto& connected_component : connected_components) {
|
||||||
|
// TODO: make this parallel: https://stackoverflow.com/questions/36246300/parallel-loops-in-c
|
||||||
|
|
||||||
|
//
|
||||||
|
// get a mapping to graph vertices that doesn't skip over
|
||||||
|
// any numbers, allowing the Graph class to be used
|
||||||
|
//
|
||||||
|
// we also need a mapping back to the obj vertices so that
|
||||||
|
// we can construct the path at the end
|
||||||
|
//
|
||||||
std::vector<bool> present_vertices(graph.GetNumVertices(), false);
|
std::vector<bool> present_vertices(graph.GetNumVertices(), false);
|
||||||
|
|
||||||
for (int vertex : connected_component) {
|
for (int vertex : connected_component) {
|
||||||
|
@ -124,6 +144,8 @@ WorldObject::WorldObject(juce::InputStream& stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate all edges in sub-component using the vertex
|
||||||
|
// maps and parent Graph's adjacency list
|
||||||
std::list<std::pair<int, int>> sub_edge_list;
|
std::list<std::pair<int, int>> sub_edge_list;
|
||||||
|
|
||||||
for (int obj_start : connected_component) {
|
for (int obj_start : connected_component) {
|
||||||
|
@ -135,9 +157,22 @@ WorldObject::WorldObject(juce::InputStream& stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Graph subgraph(connected_component.size(), sub_edge_list);
|
Graph subgraph(connected_component.size(), sub_edge_list);
|
||||||
pair<list<int>, double> solution = ChinesePostman(subgraph);
|
|
||||||
|
std::vector<double> cost(subgraph.GetNumEdges());
|
||||||
|
for (auto& edge : sub_edge_list) {
|
||||||
|
int obj_start = graph_to_obj_vertex[edge.first];
|
||||||
|
int obj_end = graph_to_obj_vertex[edge.second];
|
||||||
|
double deltax = vs[3 * obj_start] - vs[3 * obj_end];
|
||||||
|
double deltay = vs[3 * obj_start + 1] - vs[3 * obj_end + 1];
|
||||||
|
double deltaz = vs[3 * obj_start + 2] - vs[3 * obj_end + 2];
|
||||||
|
double c = std::sqrt(deltax * deltax + deltay * deltay + deltaz * deltaz);
|
||||||
|
cost[subgraph.GetEdgeIndex(edge.first, edge.second)] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<list<int>, double> solution = ChinesePostman(subgraph, cost);
|
||||||
list<int>& path = solution.first;
|
list<int>& path = solution.first;
|
||||||
|
|
||||||
|
// traverse CP solution, converting back to obj vertices
|
||||||
int prevVertex = -1;
|
int prevVertex = -1;
|
||||||
for (auto& graph_vertex : path) {
|
for (auto& graph_vertex : path) {
|
||||||
int vertex = graph_to_obj_vertex[graph_vertex];
|
int vertex = graph_to_obj_vertex[graph_vertex];
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <JuceHeader.h>
|
|
||||||
#include "Line3D.h"
|
#include "Line3D.h"
|
||||||
|
|
||||||
class WorldObject {
|
class WorldObject {
|
||||||
public:
|
public:
|
||||||
WorldObject(juce::InputStream&);
|
WorldObject(std::string);
|
||||||
|
|
||||||
double rotateX = 0.0, rotateY = 0.0, rotateZ = 0.0;
|
double rotateX = 0.0, rotateY = 0.0, rotateZ = 0.0;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ FileParser::FileParser() {}
|
||||||
|
|
||||||
void FileParser::parse(juce::String extension, std::unique_ptr<juce::InputStream> stream) {
|
void FileParser::parse(juce::String extension, std::unique_ptr<juce::InputStream> stream) {
|
||||||
if (extension == ".obj") {
|
if (extension == ".obj") {
|
||||||
object = std::make_unique<WorldObject>(*stream);
|
object = std::make_unique<WorldObject>(stream->readEntireStreamAsString().toStdString());
|
||||||
camera = std::make_unique<Camera>(1.0, 0, 0, 0.0);
|
camera = std::make_unique<Camera>(1.0, 0, 0, 0.0);
|
||||||
camera->findZPos(*object);
|
camera->findZPos(*object);
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue