mirror of https://github.com/vitalif/openscad
Added CSGTextCache for experimenting with cache-tree organization
parent
e8e213b3c9
commit
1caf80e561
|
@ -1,7 +1,6 @@
|
|||
#include "CGALRenderer.h"
|
||||
#include "visitor.h"
|
||||
#include "state.h"
|
||||
#include "nodecache.h"
|
||||
#include "module.h" // FIXME: Temporarily for ModuleInstantiation
|
||||
#include "printutils.h"
|
||||
|
||||
|
@ -29,12 +28,12 @@ CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractNode &node)
|
|||
render.execute();
|
||||
assert(isCached(node));
|
||||
}
|
||||
return this->cache[this->dumpcache[node]];
|
||||
return this->cache[this->tree.getString(node)];
|
||||
}
|
||||
|
||||
bool CGALRenderer::isCached(const AbstractNode &node) const
|
||||
{
|
||||
return this->cache.contains(this->dumpcache[node]);
|
||||
return this->cache.contains(this->tree.getString(node));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -94,7 +93,7 @@ void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp
|
|||
iter != this->visitedchildren[node.index()].end();
|
||||
iter++) {
|
||||
const AbstractNode *chnode = iter->first;
|
||||
const QString &chcacheid = iter->second;
|
||||
const string &chcacheid = iter->second;
|
||||
// FIXME: Don't use deep access to modinst members
|
||||
if (chnode->modinst->tag_background) continue;
|
||||
assert(isCached(*chnode));
|
||||
|
@ -109,7 +108,7 @@ void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp
|
|||
chnode->progress_report();
|
||||
}
|
||||
}
|
||||
this->cache.insert(this->dumpcache[node], N);
|
||||
this->cache.insert(this->tree.getString(node), N);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -172,7 +171,7 @@ Response CGALRenderer::visit(const State &state, const TransformNode &node)
|
|||
applyToChildren(node, UNION);
|
||||
|
||||
// Then apply transform
|
||||
CGAL_Nef_polyhedron N = this->cache[this->dumpcache[node]];
|
||||
CGAL_Nef_polyhedron N = this->cache[this->tree.getString(node)];
|
||||
assert(N.dim >= 2 && N.dim <= 3);
|
||||
if (N.dim == 2) {
|
||||
// Unfortunately CGAL provides no transform method for CGAL_Nef_polyhedron2
|
||||
|
@ -205,7 +204,7 @@ Response CGALRenderer::visit(const State &state, const TransformNode &node)
|
|||
node.m[2], node.m[6], node.m[10], node.m[14], node.m[15]);
|
||||
N.p3.transform(t);
|
||||
}
|
||||
this->cache.insert(cacheid, N);
|
||||
this->cache.insert(this->tree.getString(node), N);
|
||||
}
|
||||
addToParent(state, node);
|
||||
}
|
||||
|
@ -237,7 +236,7 @@ Response CGALRenderer::visit(const State &state, const AbstractPolyNode &node)
|
|||
node.progress_report();
|
||||
|
||||
ps->unlink();
|
||||
this->cache.insert(this->dumpcache[node], N);
|
||||
this->cache.insert(this->tree.getString(node), N);
|
||||
}
|
||||
catch (...) { // Don't leak the PolySet on ProgressCancelException
|
||||
ps->unlink();
|
||||
|
@ -258,7 +257,7 @@ void CGALRenderer::addToParent(const State &state, const AbstractNode &node)
|
|||
assert(state.isPostfix());
|
||||
this->visitedchildren.erase(node.index());
|
||||
if (state.parent()) {
|
||||
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->dumpcache[node]));
|
||||
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->tree.getString(node)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#ifndef CGALRENDERER_H_
|
||||
#define CGALRENDERER_H_
|
||||
|
||||
#include "myqhash.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "visitor.h"
|
||||
#include "nodecache.h"
|
||||
#include "Tree.h"
|
||||
#include "cgal.h"
|
||||
|
||||
#ifdef ENABLE_CGAL
|
||||
|
@ -23,7 +25,7 @@ class CGALRenderer : public Visitor
|
|||
public:
|
||||
enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI};
|
||||
// FIXME: If a cache is not given, we need to fix this ourselves
|
||||
CGALRenderer(QHash<QString, CGAL_Nef_polyhedron> &cache, const NodeCache<string> &dumpcache) : cache(cache), dumpcache(dumpcache) {}
|
||||
CGALRenderer(QHash<string, CGAL_Nef_polyhedron> &cache, const Tree &tree) : cache(cache), tree(tree) {}
|
||||
virtual ~CGALRenderer() {}
|
||||
|
||||
virtual Response visit(const State &state, const AbstractNode &node);
|
||||
|
@ -38,16 +40,15 @@ public:
|
|||
private:
|
||||
void addToParent(const State &state, const AbstractNode &node);
|
||||
bool isCached(const AbstractNode &node) const;
|
||||
QString mk_cache_id(const AbstractNode &node) const;
|
||||
void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CGALRenderer::CsgOp op);
|
||||
void applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp op);
|
||||
|
||||
string currindent;
|
||||
typedef list<pair<const AbstractNode *, QString> > ChildList;
|
||||
typedef list<pair<const AbstractNode *, string> > ChildList;
|
||||
map<int, ChildList> visitedchildren;
|
||||
|
||||
QHash<QString, CGAL_Nef_polyhedron> &cache;
|
||||
const NodeCache<string> &dumpcache;
|
||||
QHash<string, CGAL_Nef_polyhedron> &cache;
|
||||
const Tree &tree;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define POLYSETCGALRENDERER_H_
|
||||
|
||||
#include "PolySetRenderer.h"
|
||||
#include <QHash>
|
||||
#include "CGALRenderer.h"
|
||||
|
||||
/*!
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#define TREE_H_
|
||||
|
||||
#include "nodecache.h"
|
||||
//#include "cgal.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
@ -19,7 +18,6 @@ public:
|
|||
|
||||
// FIXME: Really return a reference?
|
||||
const string &getString(const AbstractNode &node) const;
|
||||
// CGAL_Nef_polyhedron getCGALMesh(const AbstractNode &node) const;
|
||||
|
||||
private:
|
||||
const AbstractNode *root_node;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef GRID_H_
|
||||
#define GRID_H_
|
||||
|
||||
#include <QHash>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <QHash>
|
||||
|
||||
const double GRID_COARSE = 0.001;
|
||||
const double GRID_FINE = 0.000001;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef OPENSCAD_QHASH_H_
|
||||
#define OPENSCAD_QHASH_H_
|
||||
|
||||
#include <qglobal.h>
|
||||
#include <string>
|
||||
extern uint qHash(const std::string &);
|
||||
#include <QHash>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
#include "myqhash.h"
|
||||
|
||||
static uint hash(const uchar *p, int n)
|
||||
{
|
||||
uint h = 0;
|
||||
uint g;
|
||||
|
||||
while (n--) {
|
||||
h = (h << 4) + *p++;
|
||||
if ((g = (h & 0xf0000000)) != 0)
|
||||
h ^= g >> 23;
|
||||
h &= ~g;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
uint qHash(const std::string &str) {
|
||||
return hash(reinterpret_cast<const uchar *>(str.c_str()), str.length());
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#include "CSGTextCache.h"
|
||||
|
||||
bool CSGTextCache::contains(const AbstractNode &node) const
|
||||
{
|
||||
return this->cache.contains(this->tree.getString(node));
|
||||
}
|
||||
|
||||
// We cannot return a reference since the [] operator returns a temporary value
|
||||
string CSGTextCache::operator[](const AbstractNode &node) const
|
||||
{
|
||||
return this->cache[this->tree.getString(node)];
|
||||
}
|
||||
|
||||
void CSGTextCache::insert(const class AbstractNode &node, const string & value)
|
||||
{
|
||||
this->cache.insert(this->tree.getString(node), value);
|
||||
}
|
||||
|
||||
void CSGTextCache::remove(const class AbstractNode &node)
|
||||
{
|
||||
this->cache.remove(this->tree.getString(node));
|
||||
}
|
||||
|
||||
void CSGTextCache::clear()
|
||||
{
|
||||
this->cache.clear();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef CSGTEXTCACHE_H_
|
||||
#define CSGTEXTCACHE_H_
|
||||
|
||||
#include "myqhash.h"
|
||||
#include "Tree.h"
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
class CSGTextCache
|
||||
{
|
||||
public:
|
||||
CSGTextCache(const Tree &tree) : tree(tree) {}
|
||||
~CSGTextCache() {}
|
||||
|
||||
bool contains(const AbstractNode &node) const;
|
||||
string operator[](const AbstractNode &node) const;
|
||||
void insert(const class AbstractNode &node, const string & value);
|
||||
void remove(const class AbstractNode &node);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QHash<string, string> cache;
|
||||
const Tree &tree;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
bool CSGTextRenderer::isCached(const AbstractNode &node)
|
||||
{
|
||||
return this->cache.contains(this->tree.getString(node));
|
||||
return this->cache.contains(node);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -47,49 +47,6 @@ CSGTextRenderer::process(string &target, const string &src, CSGTextRenderer::Csg
|
|||
}
|
||||
}
|
||||
|
||||
// /*!
|
||||
// Modifies target by applying op to target and src:
|
||||
// target = target [op] src
|
||||
// */
|
||||
// void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CsgOp op)
|
||||
// {
|
||||
// if (target.dim == 2) {
|
||||
// switch (op) {
|
||||
// case UNION:
|
||||
// target.p2 += src.p2;
|
||||
// break;
|
||||
// case INTERSECTION:
|
||||
// target.p2 *= src.p2;
|
||||
// break;
|
||||
// case DIFFERENCE:
|
||||
// target.p2 -= src.p2;
|
||||
// break;
|
||||
// case MINKOWSKI:
|
||||
// target.p2 = minkowski2(target.p2, src.p2);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// else if (target.dim == 3) {
|
||||
// switch (op) {
|
||||
// case UNION:
|
||||
// target.p3 += src.p3;
|
||||
// break;
|
||||
// case INTERSECTION:
|
||||
// target.p3 *= src.p3;
|
||||
// break;
|
||||
// case DIFFERENCE:
|
||||
// target.p3 -= src.p3;
|
||||
// break;
|
||||
// case MINKOWSKI:
|
||||
// target.p3 = minkowski3(target.p3, src.p3);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// assert(false && "Dimention of Nef polyhedron must be 2 or 3");
|
||||
// }
|
||||
// }
|
||||
|
||||
void CSGTextRenderer::applyToChildren(const AbstractNode &node, CSGTextRenderer::CsgOp op)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
@ -99,26 +56,25 @@ void CSGTextRenderer::applyToChildren(const AbstractNode &node, CSGTextRenderer:
|
|||
if (this->visitedchildren[node.index()].size() > 0) {
|
||||
// FIXME: assert that cache contains nodes in code below
|
||||
bool first = true;
|
||||
// CGAL_Nef_polyhedron N;
|
||||
for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin();
|
||||
iter != this->visitedchildren[node.index()].end();
|
||||
iter++) {
|
||||
const AbstractNode *chnode = iter->first;
|
||||
const string &chcacheid = iter->second;
|
||||
const AbstractNode *chnode = *iter;
|
||||
assert(this->cache.contains(*chnode));
|
||||
// FIXME: Don't use deep access to modinst members
|
||||
if (chnode->modinst->tag_background) continue;
|
||||
if (first) {
|
||||
N += "(" + this->cache[chcacheid];
|
||||
N += "(" + this->cache[*chnode];
|
||||
// if (N.dim != 0) first = false; // FIXME: when can this happen?
|
||||
first = false;
|
||||
} else {
|
||||
process(N, this->cache[chcacheid], op);
|
||||
process(N, this->cache[*chnode], op);
|
||||
}
|
||||
chnode->progress_report();
|
||||
}
|
||||
N += ")";
|
||||
}
|
||||
this->cache.insert(this->tree.getString(node), N);
|
||||
this->cache.insert(node, N);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -204,23 +160,8 @@ Response CSGTextRenderer::visit(const State &state, const AbstractPolyNode &node
|
|||
// FIXME: Manage caching
|
||||
// FIXME: Will generate one single Nef polyhedron (no csg ops necessary)
|
||||
|
||||
// PolySet *ps = render_polyset(RENDER_CGAL);
|
||||
// try {
|
||||
// CGAL_Nef_polyhedron N = ps->renderCSGMesh();
|
||||
// cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());
|
||||
// print_messages_pop();
|
||||
// progress_report();
|
||||
|
||||
// ps->unlink();
|
||||
// return N;
|
||||
// }
|
||||
// catch (...) { // Don't leak the PolySet on ProgressCancelException
|
||||
// ps->unlink();
|
||||
// throw;
|
||||
// }
|
||||
|
||||
string N = typeid(node).name();
|
||||
this->cache.insert(this->tree.getString(node), N);
|
||||
this->cache.insert(node, N);
|
||||
|
||||
// std::cout << "Insert: " << N << "\n";
|
||||
// std::cout << "Node: " << cacheid.toStdString() << "\n\n";
|
||||
|
@ -240,26 +181,6 @@ void CSGTextRenderer::addToParent(const State &state, const AbstractNode &node)
|
|||
assert(state.isPostfix());
|
||||
this->visitedchildren.erase(node.index());
|
||||
if (state.parent()) {
|
||||
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->tree.getString(node)));
|
||||
this->visitedchildren[state.parent()->index()].push_back(&node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint hash(const uchar *p, int n)
|
||||
{
|
||||
uint h = 0;
|
||||
uint g;
|
||||
|
||||
while (n--) {
|
||||
h = (h << 4) + *p++;
|
||||
if ((g = (h & 0xf0000000)) != 0)
|
||||
h ^= g >> 23;
|
||||
h &= ~g;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
uint qHash(const string &str) {
|
||||
return hash(reinterpret_cast<const uchar *>(str.c_str()), str.length());
|
||||
}
|
||||
|
|
|
@ -1,26 +1,20 @@
|
|||
#ifndef CSGTEXTRENDERER_H_
|
||||
#define CSGTEXTRENDERER_H_
|
||||
|
||||
#include <qglobal.h>
|
||||
#include <string>
|
||||
extern uint qHash(const std::string &);
|
||||
#include "visitor.h"
|
||||
#include "CSGTextCache.h"
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <QHash>
|
||||
#include "visitor.h"
|
||||
#include "Tree.h"
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::list;
|
||||
using std::pair;
|
||||
|
||||
class CSGTextRenderer : public Visitor
|
||||
{
|
||||
public:
|
||||
CSGTextRenderer(QHash<string, string> &cache, const Tree &tree) :
|
||||
cache(cache), tree(tree) {}
|
||||
CSGTextRenderer(CSGTextCache &cache) : cache(cache) {}
|
||||
virtual ~CSGTextRenderer() {}
|
||||
|
||||
virtual Response visit(const State &state, const AbstractNode &node);
|
||||
|
@ -37,11 +31,10 @@ private:
|
|||
void applyToChildren(const AbstractNode &node, CSGTextRenderer::CsgOp op);
|
||||
|
||||
string currindent;
|
||||
typedef list<pair<const AbstractNode *, string> > ChildList;
|
||||
typedef list<const AbstractNode *> ChildList;
|
||||
map<int, ChildList> visitedchildren;
|
||||
|
||||
QHash<string, string> &cache;
|
||||
const Tree &tree;
|
||||
CSGTextCache &cache;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "myqhash.h"
|
||||
#include "openscad.h"
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
|
@ -30,10 +31,9 @@
|
|||
#include "value.h"
|
||||
#include "export.h"
|
||||
#include "builtin.h"
|
||||
#include "nodedumper.h"
|
||||
#include "Tree.h"
|
||||
#include "CGALRenderer.h"
|
||||
#include "PolySetCGALRenderer.h"
|
||||
#include "Tree.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
|
@ -49,6 +49,8 @@ QString currentdir;
|
|||
QString examplesdir;
|
||||
QString librarydir;
|
||||
|
||||
using std::string;
|
||||
|
||||
void handle_dep(QString filename)
|
||||
{
|
||||
if (filename.startsWith("/"))
|
||||
|
@ -63,20 +65,14 @@ void handle_dep(QString filename)
|
|||
}
|
||||
|
||||
// FIXME: enforce some maximum cache size (old version had 100K vertices as limit)
|
||||
QHash<string, CGAL_Nef_polyhedron> cache;
|
||||
QHash<std::string, CGAL_Nef_polyhedron> cache;
|
||||
|
||||
void cgalTree(Tree &tree)
|
||||
{
|
||||
const AbstractNode *root = tree.root();
|
||||
assert(root);
|
||||
NodeCache<string> &cache = tree.cache();
|
||||
NodeDumper dumper(cache, false);
|
||||
Traverser trav(dumper, *root, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
assert(!cache[*root].empty());
|
||||
assert(tree.root());
|
||||
|
||||
CSGTextRenderer renderer(csgcache, cache);
|
||||
Traverser render(renderer, *root, Traverser::PRE_AND_POSTFIX);
|
||||
CGALRenderer renderer(cache, tree);
|
||||
Traverser render(renderer, *tree.root(), Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
}
|
||||
|
||||
|
@ -170,16 +166,13 @@ int main(int argc, char **argv)
|
|||
|
||||
cgalTree(tree);
|
||||
|
||||
std::cout << cache[tree.cache()[*root_node]] << "\n";
|
||||
std::cout << tree.getString(*root_node) << "\n";
|
||||
|
||||
CGALRenderer cgalrenderer(dumper.getCache());
|
||||
PolySetCGALRenderer psrenderer(cgalrenderer);
|
||||
PolySetRenderer::setRenderer(&psrenderer);
|
||||
// CGALRenderer cgalrenderer(dumper.getCache());
|
||||
// PolySetCGALRenderer psrenderer(cgalrenderer);
|
||||
// PolySetRenderer::setRenderer(&psrenderer);
|
||||
|
||||
// This is done in renderCGALMesh() for convenience, but can be overridden here
|
||||
// Traverser render(cgalrenderer, *root_node, Traverser::PRE_AND_POSTFIX);
|
||||
// render.execute();
|
||||
CGAL_Nef_polyhedron N = cgalrenderer.renderCGALMesh(*root_node);
|
||||
CGAL_Nef_polyhedron N = cache[tree.getString(*root_node)];
|
||||
|
||||
QDir::setCurrent(original_path.absolutePath());
|
||||
export_stl(&N, fileInfo.baseName() + ".stl", NULL);
|
||||
|
|
|
@ -62,6 +62,7 @@ HEADERS += ../src/builtin.h \
|
|||
../src/state.h \
|
||||
../src/PolySetRenderer.h \
|
||||
../src/PolySetCGALRenderer.h \
|
||||
../src/myqhash.h \
|
||||
../src/Tree.h
|
||||
|
||||
SOURCES += cgaltest.cc \
|
||||
|
@ -100,4 +101,5 @@ SOURCES += cgaltest.cc \
|
|||
../src/traverser.cc \
|
||||
../src/PolySetRenderer.cc \
|
||||
../src/PolySetCGALRenderer.cc \
|
||||
../src/qhash.cc \
|
||||
../src/Tree.cc
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include "CSGTextRenderer.h"
|
||||
#include "CSGTextCache.h"
|
||||
#include "openscad.h"
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
|
@ -61,14 +62,10 @@ void handle_dep(QString filename)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
QHash<string, string> csgcache;
|
||||
void csgTree(Tree &tree)
|
||||
void csgTree(CSGTextCache &cache, const AbstractNode &root)
|
||||
{
|
||||
assert(tree.root());
|
||||
|
||||
CSGTextRenderer renderer(csgcache, tree);
|
||||
Traverser render(renderer, *tree.root(), Traverser::PRE_AND_POSTFIX);
|
||||
CSGTextRenderer renderer(cache);
|
||||
Traverser render(renderer, root, Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
}
|
||||
|
||||
|
@ -159,11 +156,12 @@ int main(int argc, char **argv)
|
|||
|
||||
Tree tree;
|
||||
tree.setRoot(root_node);
|
||||
CSGTextCache csgcache(tree);
|
||||
|
||||
csgTree(tree);
|
||||
csgTree(csgcache, *root_node);
|
||||
std::cout << tree.getString(*root_node) << "\n";
|
||||
|
||||
std::cout << csgcache[tree.getString(*root_node)] << "\n";
|
||||
std::cout << csgcache[*root_node] << "\n";
|
||||
|
||||
destroy_builtin_functions();
|
||||
destroy_builtin_modules();
|
||||
|
|
|
@ -66,7 +66,9 @@ HEADERS += ../src/builtin.h \
|
|||
../src/state.h \
|
||||
../src/PolySetRenderer.h \
|
||||
../src/Tree.h \
|
||||
CSGTextRenderer.h
|
||||
../src/myqhash.h \
|
||||
CSGTextRenderer.h \
|
||||
CSGTextCache.h
|
||||
|
||||
SOURCES += csgtexttest.cc \
|
||||
../src/export.cc \
|
||||
|
@ -100,4 +102,6 @@ SOURCES += csgtexttest.cc \
|
|||
../src/traverser.cc \
|
||||
../src/PolySetRenderer.cc \
|
||||
../src/Tree.cc \
|
||||
CSGTextRenderer.cc
|
||||
../src/qhash.cc \
|
||||
CSGTextRenderer.cc \
|
||||
CSGTextCache.cc
|
||||
|
|
Loading…
Reference in New Issue