diff options
author | Marius Kintel <marius@kintel.net> | 2010-07-15 00:48:00 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2010-10-31 00:42:38 (GMT) |
commit | f0b49ee9e93c92982fe9a160c3e9aa7da17b581e (patch) | |
tree | 28056348e28bca5274e3bf7f48174fd42fb6ce94 | |
parent | f2323c78b381c24d2924c6cea7c9230416542a17 (diff) |
Started refactoring of render_csg_term() into a visitor
-rw-r--r-- | src/CSGTermRenderer.cc | 335 | ||||
-rw-r--r-- | src/CSGTermRenderer.h | 43 | ||||
-rw-r--r-- | src/cgaladv.cc | 27 | ||||
-rw-r--r-- | src/csgnode.h | 2 | ||||
-rw-r--r-- | src/csgops.cc | 26 | ||||
-rw-r--r-- | src/node.cc | 51 | ||||
-rw-r--r-- | src/node.h | 7 | ||||
-rw-r--r-- | src/render.cc | 126 | ||||
-rw-r--r-- | src/rendernode.h | 1 | ||||
-rw-r--r-- | src/transform.cc | 35 | ||||
-rw-r--r-- | src/transformnode.h | 1 | ||||
-rw-r--r-- | test-code/csgtermtest.cc | 167 | ||||
-rw-r--r-- | test-code/csgtermtest.pro | 105 |
13 files changed, 650 insertions, 276 deletions
diff --git a/src/CSGTermRenderer.cc b/src/CSGTermRenderer.cc new file mode 100644 index 0000000..513ac6b --- /dev/null +++ b/src/CSGTermRenderer.cc @@ -0,0 +1,335 @@ +#include "CSGTermRenderer.h" +#include "visitor.h" +#include "state.h" +#include "csgterm.h" +#include "module.h" +#include "csgnode.h" +#include "transformnode.h" +#include "rendernode.h" +#include "printutils.h" + +#include <string> +#include <map> +#include <list> +#include <sstream> +#include <iostream> +#include <assert.h> + +/*! + \class CSGTermRenderer + + A visitor responsible for creating a tree of CSGTerm nodes used for rendering + with OpenCSG. +*/ + +void CSGTermRenderer::applyToChildren(const AbstractNode &node, CSGTermRenderer::CsgOp op) +{ + if (this->visitedchildren[node.index()].size() == 0) return; + + CSGTerm *t1 = NULL; + for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin(); + iter != this->visitedchildren[node.index()].end(); + iter++) { + const AbstractNode *chnode = *iter; + CSGTerm *t2 = this->stored_term[chnode->index()]; + this->stored_term.erase(chnode->index()); + if (t2 && !t1) { + t1 = t2; + } else if (t2 && t1) { + if (op == UNION) { + t1 = new CSGTerm(CSGTerm::TYPE_UNION, t1, t2); + } else if (op == DIFFERENCE) { + t1 = new CSGTerm(CSGTerm::TYPE_DIFFERENCE, t1, t2); + } else if (op == INTERSECTION) { + t1 = new CSGTerm(CSGTerm::TYPE_INTERSECTION, t1, t2); + } + } + } + if (t1 && node.modinst->tag_highlight && this->highlights) { + this->highlights->push_back(t1->link()); + } + if (t1 && node.modinst->tag_background && this->background) { + this->background->push_back(t1); +// FIXME: don't store in stored_term? return NULL; + } + this->stored_term[node.index()] = t1; +} + +Response CSGTermRenderer::visit(const State &state, const AbstractNode &node) +{ + if (state.isPostfix()) { + applyToChildren(node, UNION); + addToParent(state, node); + } + return ContinueTraversal; +} + +Response CSGTermRenderer::visit(const State &state, const AbstractIntersectionNode &node) +{ + if (state.isPostfix()) { + applyToChildren(node, INTERSECTION); + addToParent(state, node); + } + return ContinueTraversal; +} + +static CSGTerm *render_csg_term_from_ps(double m[20], + QVector<CSGTerm*> *highlights, + QVector<CSGTerm*> *background, + PolySet *ps, + const ModuleInstantiation *modinst, + int idx) +{ + CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx)); + if (modinst->tag_highlight && highlights) + highlights->push_back(t->link()); + if (modinst->tag_background && background) { + background->push_back(t); + return NULL; + } + return t; +} + +Response CSGTermRenderer::visit(const State &state, const AbstractPolyNode &node) +{ + if (state.isPostfix()) { + PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_OPENCSG); + CSGTerm *t1 = render_csg_term_from_ps(m, this->highlights, this->background, ps, node.modinst, node.index()); + this->stored_term[node.index()] = t1; + addToParent(state, node); + } + return ContinueTraversal; +} + +Response CSGTermRenderer::visit(const State &state, const CsgNode &node) +{ + if (state.isPostfix()) { + CsgOp op; + switch (node.type) { + case CSG_TYPE_UNION: + op = UNION; + break; + case CSG_TYPE_DIFFERENCE: + op = DIFFERENCE; + break; + case CSG_TYPE_INTERSECTION: + op = INTERSECTION; + break; + } + applyToChildren(node, op); + addToParent(state, node); + } + return ContinueTraversal; +} + +Response CSGTermRenderer::visit(const State &state, const TransformNode &node) +{ + if (state.isPostfix()) { + double x[20]; + + for (int i = 0; i < 16; i++) + { + int c_row = i%4; + int m_col = i/4; + x[i] = 0; + for (int j = 0; j < 4; j++) + x[i] += c[c_row + j*4] * m[m_col*4 + j]; + } + + for (int i = 16; i < 20; i++) + x[i] = m[i] < 0 ? c[i] : m[i]; + + // FIXME: Apply the x matrix. + // FIXME: Look into how bottom-up vs. top down affects matrix handling + + applyToChildren(node, UNION); + addToParent(state, node); + } + return ContinueTraversal; +} + +// FIXME: Find out how to best call into CGAL from this visitor +Response CSGTermRenderer::visit(const State &state, const RenderNode &node) +{ + PRINT("WARNING: Found render() statement but compiled without CGAL support!"); + if (state.isPostfix()) { + applyToChildren(node, UNION); + addToParent(state, node); + } + return ContinueTraversal; +} + +/*! + Adds ourself to out parent's list of traversed children. + Call this for _every_ node which affects output during the postfix traversal. +*/ +void CSGTermRenderer::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(&node); + } +} + + +#if 0 + +// FIXME: #ifdef ENABLE_CGAL +#if 0 +CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const +{ + if (type == MINKOWSKI) + return render_csg_term_from_nef(m, highlights, background, "minkowski", this->convexity); + + if (type == GLIDE) + return render_csg_term_from_nef(m, highlights, background, "glide", this->convexity); + + if (type == SUBDIV) + return render_csg_term_from_nef(m, highlights, background, "subdiv", this->convexity); + + return NULL; +} + +#else // ENABLE_CGAL + +CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const +{ + PRINT("WARNING: Found minkowski(), glide() or subdiv() statement but compiled without CGAL support!"); + return NULL; +} + +#endif // ENABLE_CGAL + + + +// FIXME: #ifdef ENABLE_CGAL +#if 0 +CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const +{ + QString key = mk_cache_id(); + if (PolySet::ps_cache.contains(key)) { + PRINT(PolySet::ps_cache[key]->msg); + return AbstractPolyNode::render_csg_term_from_ps(m, highlights, background, + PolySet::ps_cache[key]->ps->link(), modinst, idx); + } + + print_messages_push(); + CGAL_Nef_polyhedron N; + + QString cache_id = mk_cache_id(); + if (cgal_nef_cache.contains(cache_id)) + { + PRINT(cgal_nef_cache[cache_id]->msg); + N = cgal_nef_cache[cache_id]->N; + } + else + { + PRINTF_NOCACHE("Processing uncached %s statement...", statement); + // PRINTA("Cache ID: %1", cache_id); + QApplication::processEvents(); + + QTime t; + t.start(); + + N = this->renderCSGMesh(); + + int s = t.elapsed() / 1000; + PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60); + } + + PolySet *ps = NULL; + + if (N.dim == 2) + { + DxfData dd(N); + ps = new PolySet(); + ps->is2d = true; + dxf_tesselate(ps, &dd, 0, true, false, 0); + dxf_border_to_ps(ps, &dd); + } + + if (N.dim == 3) + { + if (!N.p3.is_simple()) { + PRINTF("WARNING: Result of %s() isn't valid 2-manifold! Modify your design..", statement); + return NULL; + } + + ps = new PolySet(); + + CGAL_Polyhedron P; + N.p3.convert_to_Polyhedron(P); + + typedef CGAL_Polyhedron::Vertex Vertex; + typedef CGAL_Polyhedron::Vertex_const_iterator VCI; + typedef CGAL_Polyhedron::Facet_const_iterator FCI; + typedef CGAL_Polyhedron::Halfedge_around_facet_const_circulator HFCC; + + for (FCI fi = P.facets_begin(); fi != P.facets_end(); ++fi) { + HFCC hc = fi->facet_begin(); + HFCC hc_end = hc; + ps->append_poly(); + do { + Vertex v = *VCI((hc++)->vertex()); + double x = CGAL::to_double(v.point().x()); + double y = CGAL::to_double(v.point().y()); + double z = CGAL::to_double(v.point().z()); + ps->append_vertex(x, y, z); + } while (hc != hc_end); + } + } + + if (ps) + { + ps->convexity = convexity; + PolySet::ps_cache.insert(key, new PolySet::ps_cache_entry(ps->link())); + + CSGTerm *term = new CSGTerm(ps, m, QString("n%1").arg(idx)); + if (modinst->tag_highlight && highlights) + highlights->push_back(term->link()); + if (modinst->tag_background && background) { + background->push_back(term); + return NULL; + } + return term; + } + print_messages_pop(); + + return NULL; +} + +CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const +{ + return render_csg_term_from_nef(m, highlights, background, "render", this->convexity); +} + +#else + +CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const +{ + CSGTerm *t1 = NULL; + PRINT("WARNING: Found render() statement but compiled without CGAL support!"); + foreach(AbstractNode * v, children) { + CSGTerm *t2 = v->render_csg_term(m, highlights, background); + if (t2 && !t1) { + t1 = t2; + } else if (t2 && t1) { + t1 = new CSGTerm(CSGTerm::TYPE_UNION, t1, t2); + } + } + if (modinst->tag_highlight && highlights) + highlights->push_back(t1->link()); + if (t1 && modinst->tag_background && background) { + background->push_back(t1); + return NULL; + } + return t1; +} + +#endif + + + +#endif + diff --git a/src/CSGTermRenderer.h b/src/CSGTermRenderer.h new file mode 100644 index 0000000..1905faf --- /dev/null +++ b/src/CSGTermRenderer.h @@ -0,0 +1,43 @@ +#ifndef CSGTERMRENDERER_H_ +#define CSGTERMRENDERER_H_ + +#include <string> +#include <map> +#include <list> +#include <vector> +#include "visitor.h" +#include "node.h" + +using std::string; +using std::map; +using std::list; +using std::vector; + +class CSGTermRenderer : public Visitor +{ +public: + CSGTermRenderer() {} + virtual ~CSGTermRenderer() {} + + virtual Response visit(const State &state, const AbstractNode &node); + virtual Response visit(const State &state, const AbstractIntersectionNode &node); + virtual Response visit(const State &state, const AbstractPolyNode &node); + virtual Response visit(const State &state, const CsgNode &node); + virtual Response visit(const State &state, const TransformNode &node); + virtual Response visit(const State &state, const RenderNode &node); + +private: + enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI}; + void addToParent(const State &state, const AbstractNode &node); + void applyToChildren(const AbstractNode &node, CSGTermRenderer::CsgOp op); + + const AbstractNode *root; + typedef list<const AbstractNode *> ChildList; + map<int, ChildList> visitedchildren; + map<int, class CSGTerm*> stored_term; + + vector<CSGTerm*> *highlights; + vector<CSGTerm*> *background; +}; + +#endif diff --git a/src/cgaladv.cc b/src/cgaladv.cc index 114620f..e79a57e 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -68,7 +68,6 @@ public: QString subdiv_type; int convexity, level; cgaladv_type_e type; - virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; }; AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const @@ -131,32 +130,6 @@ void register_builtin_cgaladv() builtin_modules["subdiv"] = new CgaladvModule(SUBDIV); } -// FIXME: #ifdef ENABLE_CGAL -#if 0 -CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - if (type == MINKOWSKI) - return render_csg_term_from_nef(m, highlights, background, "minkowski", this->convexity); - - if (type == GLIDE) - return render_csg_term_from_nef(m, highlights, background, "glide", this->convexity); - - if (type == SUBDIV) - return render_csg_term_from_nef(m, highlights, background, "subdiv", this->convexity); - - return NULL; -} - -#else // ENABLE_CGAL - -CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - PRINT("WARNING: Found minkowski(), glide() or subdiv() statement but compiled without CGAL support!"); - return NULL; -} - -#endif // ENABLE_CGAL - std::string CgaladvNode::toString() const { std::stringstream stream; diff --git a/src/csgnode.h b/src/csgnode.h index 02039e9..28aa0f6 100644 --- a/src/csgnode.h +++ b/src/csgnode.h @@ -19,8 +19,6 @@ public: return visitor.visit(state, *this); } virtual std::string toString() const; - - CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; }; #endif diff --git a/src/csgops.cc b/src/csgops.cc index d814e87..bddb5a0 100644 --- a/src/csgops.cc +++ b/src/csgops.cc @@ -51,32 +51,6 @@ AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *ins return node; } -CSGTerm *CsgNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - CSGTerm *t1 = NULL; - foreach (AbstractNode *v, children) { - CSGTerm *t2 = v->render_csg_term(m, highlights, background); - if (t2 && !t1) { - t1 = t2; - } else if (t2 && t1) { - if (type == CSG_TYPE_UNION) { - t1 = new CSGTerm(CSGTerm::TYPE_UNION, t1, t2); - } else if (type == CSG_TYPE_DIFFERENCE) { - t1 = new CSGTerm(CSGTerm::TYPE_DIFFERENCE, t1, t2); - } else if (type == CSG_TYPE_INTERSECTION) { - t1 = new CSGTerm(CSGTerm::TYPE_INTERSECTION, t1, t2); - } - } - } - if (t1 && modinst->tag_highlight && highlights) - highlights->append(t1->link()); - if (t1 && modinst->tag_background && background) { - background->append(t1); - return NULL; - } - return t1; -} - std::string CsgNode::toString() const { std::stringstream stream; diff --git a/src/node.cc b/src/node.cc index 69c0692..16030a5 100644 --- a/src/node.cc +++ b/src/node.cc @@ -90,57 +90,6 @@ void AbstractNode::progress_report() const progress_update(this, this->progress_mark); } -static CSGTerm *render_csg_term_backend(const AbstractNode *that, bool intersect, double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) -{ - CSGTerm *t1 = NULL; - foreach(AbstractNode *v, that->children) { - CSGTerm *t2 = v->render_csg_term(m, highlights, background); - if (t2 && !t1) { - t1 = t2; - } else if (t2 && t1) { - if (intersect) - t1 = new CSGTerm(CSGTerm::TYPE_INTERSECTION, t1, t2); - else - t1 = new CSGTerm(CSGTerm::TYPE_UNION, t1, t2); - } - } - if (t1 && that->modinst->tag_highlight && highlights) - highlights->append(t1->link()); - if (t1 && that->modinst->tag_background && background) { - background->append(t1); - return NULL; - } - return t1; -} - -CSGTerm *AbstractNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - return render_csg_term_backend(this, false, m, highlights, background); -} - -CSGTerm *AbstractIntersectionNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - return render_csg_term_backend(this, true, m, highlights, background); -} - -CSGTerm *AbstractPolyNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - PolySet *ps = render_polyset(RENDER_OPENCSG); - return render_csg_term_from_ps(m, highlights, background, ps, modinst, idx); -} - -CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx) -{ - CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx)); - if (modinst->tag_highlight && highlights) - highlights->append(t->link()); - if (modinst->tag_background && background) { - background->append(t); - return NULL; - } - return t; -} - std::ostream &operator<<(std::ostream &stream, const QString &str) { stream << str.toStdString(); @@ -52,9 +52,6 @@ public: int idx; // Node index (unique per tree) // FIXME: Rewrite to visitor - virtual class CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; - - // FIXME: Rewrite to visitor #ifdef ENABLE_CGAL class CSGTerm *render_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const; #endif @@ -67,8 +64,6 @@ public: virtual ~AbstractIntersectionNode() { }; virtual Response accept(const class State &state, class Visitor &visitor) const; virtual std::string toString() const; - - virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; }; class AbstractPolyNode : public AbstractNode @@ -86,8 +81,6 @@ public: empty PolySet if smth. is wrong, but don't return NULL unless we change the calling strategy for this method. */ virtual class PolySet *render_polyset(render_mode_e mode) const = 0; - virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; - static CSGTerm *render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx); }; std::ostream &operator<<(std::ostream &stream, const AbstractNode &node); diff --git a/src/render.cc b/src/render.cc index 92ec88c..54eb9c7 100644 --- a/src/render.cc +++ b/src/render.cc @@ -77,132 +77,6 @@ void register_builtin_render() builtin_modules["render"] = new RenderModule(); } -// FIXME: #ifdef ENABLE_CGAL -#if 0 -CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const -{ - QString key = mk_cache_id(); - if (PolySet::ps_cache.contains(key)) { - PRINT(PolySet::ps_cache[key]->msg); - return AbstractPolyNode::render_csg_term_from_ps(m, highlights, background, - PolySet::ps_cache[key]->ps->link(), modinst, idx); - } - - print_messages_push(); - CGAL_Nef_polyhedron N; - - QString cache_id = mk_cache_id(); - if (cgal_nef_cache.contains(cache_id)) - { - PRINT(cgal_nef_cache[cache_id]->msg); - N = cgal_nef_cache[cache_id]->N; - } - else - { - PRINTF_NOCACHE("Processing uncached %s statement...", statement); - // PRINTA("Cache ID: %1", cache_id); - QApplication::processEvents(); - - QTime t; - t.start(); - - N = this->renderCSGMesh(); - - int s = t.elapsed() / 1000; - PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60); - } - - PolySet *ps = NULL; - - if (N.dim == 2) - { - DxfData dd(N); - ps = new PolySet(); - ps->is2d = true; - dxf_tesselate(ps, &dd, 0, true, false, 0); - dxf_border_to_ps(ps, &dd); - } - - if (N.dim == 3) - { - if (!N.p3.is_simple()) { - PRINTF("WARNING: Result of %s() isn't valid 2-manifold! Modify your design..", statement); - return NULL; - } - - ps = new PolySet(); - - CGAL_Polyhedron P; - N.p3.convert_to_Polyhedron(P); - - typedef CGAL_Polyhedron::Vertex Vertex; - typedef CGAL_Polyhedron::Vertex_const_iterator VCI; - typedef CGAL_Polyhedron::Facet_const_iterator FCI; - typedef CGAL_Polyhedron::Halfedge_around_facet_const_circulator HFCC; - - for (FCI fi = P.facets_begin(); fi != P.facets_end(); ++fi) { - HFCC hc = fi->facet_begin(); - HFCC hc_end = hc; - ps->append_poly(); - do { - Vertex v = *VCI((hc++)->vertex()); - double x = CGAL::to_double(v.point().x()); - double y = CGAL::to_double(v.point().y()); - double z = CGAL::to_double(v.point().z()); - ps->append_vertex(x, y, z); - } while (hc != hc_end); - } - } - - if (ps) - { - ps->convexity = convexity; - PolySet::ps_cache.insert(key, new PolySet::ps_cache_entry(ps->link())); - - CSGTerm *term = new CSGTerm(ps, m, QString("n%1").arg(idx)); - if (modinst->tag_highlight && highlights) - highlights->append(term->link()); - if (modinst->tag_background && background) { - background->append(term); - return NULL; - } - return term; - } - print_messages_pop(); - - return NULL; -} - -CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - return render_csg_term_from_nef(m, highlights, background, "render", this->convexity); -} - -#else - -CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - CSGTerm *t1 = NULL; - PRINT("WARNING: Found render() statement but compiled without CGAL support!"); - foreach(AbstractNode * v, children) { - CSGTerm *t2 = v->render_csg_term(m, highlights, background); - if (t2 && !t1) { - t1 = t2; - } else if (t2 && t1) { - t1 = new CSGTerm(CSGTerm::TYPE_UNION, t1, t2); - } - } - if (modinst->tag_highlight && highlights) - highlights->append(t1->link()); - if (t1 && modinst->tag_background && background) { - background->append(t1); - return NULL; - } - return t1; -} - -#endif - std::string RenderNode::toString() const { std::stringstream stream; diff --git a/src/rendernode.h b/src/rendernode.h index 3df797e..0dcc551 100644 --- a/src/rendernode.h +++ b/src/rendernode.h @@ -14,7 +14,6 @@ public: virtual std::string toString() const; int convexity; - CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; }; #endif diff --git a/src/transform.cc b/src/transform.cc index 82e5659..3e24748 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -228,41 +228,6 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti return node; } -CSGTerm *TransformNode::render_csg_term(double c[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const -{ - double x[20]; - - for (int i = 0; i < 16; i++) - { - int c_row = i%4; - int m_col = i/4; - x[i] = 0; - for (int j = 0; j < 4; j++) - x[i] += c[c_row + j*4] * m[m_col*4 + j]; - } - - for (int i = 16; i < 20; i++) - x[i] = m[i] < 0 ? c[i] : m[i]; - - CSGTerm *t1 = NULL; - foreach(AbstractNode *v, children) - { - CSGTerm *t2 = v->render_csg_term(x, highlights, background); - if (t2 && !t1) { - t1 = t2; - } else if (t2 && t1) { - t1 = new CSGTerm(CSGTerm::TYPE_UNION, t1, t2); - } - } - if (t1 && modinst->tag_highlight && highlights) - highlights->append(t1->link()); - if (t1 && modinst->tag_background && background) { - background->append(t1); - return NULL; - } - return t1; -} - std::string TransformNode::toString() const { std::stringstream stream; diff --git a/src/transformnode.h b/src/transformnode.h index 33efa63..d7687a1 100644 --- a/src/transformnode.h +++ b/src/transformnode.h @@ -14,7 +14,6 @@ public: virtual std::string toString() const; double m[20]; - virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const; }; #endif diff --git a/test-code/csgtermtest.cc b/test-code/csgtermtest.cc new file mode 100644 index 0000000..a793d09 --- /dev/null +++ b/test-code/csgtermtest.cc @@ -0,0 +1,167 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * As a special exception, you have permission to link this program + * with the CGAL library and distribute executables, as long as you + * follow the requirements of the GNU GPL in regard to all of the + * software in the executable aside from CGAL. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "CSGTextRenderer.h" +#include "CSGTextCache.h" +#include "openscad.h" +#include "node.h" +#include "module.h" +#include "context.h" +#include "value.h" +#include "export.h" +#include "builtin.h" +#include "Tree.h" + +#include <QApplication> +#include <QFile> +#include <QDir> +#include <QSet> +#include <getopt.h> +#include <assert.h> +#include <iostream> + +QString commandline_commands; +const char *make_command = NULL; +QSet<QString> dependencies; +QString currentdir; +QString examplesdir; +QString librarydir; + +void handle_dep(QString filename) +{ + if (filename.startsWith("/")) + dependencies.insert(filename); + else + dependencies.insert(QDir::currentPath() + QString("/") + filename); + if (!QFile(filename).exists() && make_command) { + char buffer[4096]; + snprintf(buffer, 4096, "%s '%s'", make_command, filename.replace("'", "'\\''").toUtf8().data()); + system(buffer); // FIXME: Handle error + } +} + +void csgTree(CSGTextCache &cache, const AbstractNode &root) +{ + CSGTextRenderer renderer(cache); + Traverser render(renderer, root, Traverser::PRE_AND_POSTFIX); + render.execute(); +} + +int main(int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]); + exit(1); + } + + const char *filename = argv[1]; + + int rc = 0; + + initialize_builtin_functions(); + initialize_builtin_modules(); + + QApplication app(argc, argv, false); + QDir original_path = QDir::current(); + + currentdir = QDir::currentPath(); + + QDir libdir(QApplication::instance()->applicationDirPath()); +#ifdef Q_WS_MAC + libdir.cd("../Resources"); // Libraries can be bundled + if (!libdir.exists("libraries")) libdir.cd("../../.."); +#elif defined(Q_OS_UNIX) + if (libdir.cd("../share/openscad/libraries")) { + librarydir = libdir.path(); + } else + if (libdir.cd("../../share/openscad/libraries")) { + librarydir = libdir.path(); + } else + if (libdir.cd("../../libraries")) { + librarydir = libdir.path(); + } else +#endif + if (libdir.cd("libraries")) { + librarydir = libdir.path(); + } + + Context root_ctx; + root_ctx.functions_p = &builtin_functions; + root_ctx.modules_p = &builtin_modules; + root_ctx.set_variable("$fn", Value(0.0)); + root_ctx.set_variable("$fs", Value(1.0)); + root_ctx.set_variable("$fa", Value(12.0)); + root_ctx.set_variable("$t", Value(0.0)); + + Value zero3; + zero3.type = Value::VECTOR; + zero3.vec.append(new Value(0.0)); + zero3.vec.append(new Value(0.0)); + zero3.vec.append(new Value(0.0)); + root_ctx.set_variable("$vpt", zero3); + root_ctx.set_variable("$vpr", zero3); + + + AbstractModule *root_module; + ModuleInstantiation root_inst; + AbstractNode *root_node; + + QFileInfo fileInfo(filename); + handle_dep(filename); + FILE *fp = fopen(filename, "rt"); + if (!fp) { + fprintf(stderr, "Can't open input file `%s'!\n", filename); + exit(1); + } else { + QString text; + char buffer[513]; + int ret; + while ((ret = fread(buffer, 1, 512, fp)) > 0) { + buffer[ret] = 0; + text += buffer; + } + fclose(fp); + root_module = parse((text+commandline_commands).toAscii().data(), fileInfo.absolutePath().toLocal8Bit(), false); + if (!root_module) { + exit(1); + } + } + + QDir::setCurrent(fileInfo.absolutePath()); + + AbstractNode::resetIndexCounter(); + root_node = root_module->evaluate(&root_ctx, &root_inst); + + Tree tree; + tree.setRoot(root_node); + + + + + destroy_builtin_functions(); + destroy_builtin_modules(); + + return rc; +} diff --git a/test-code/csgtermtest.pro b/test-code/csgtermtest.pro new file mode 100644 index 0000000..72d39c9 --- /dev/null +++ b/test-code/csgtermtest.pro @@ -0,0 +1,105 @@ +DEFINES += OPENSCAD_VERSION=test +TEMPLATE = app + +OBJECTS_DIR = objects +MOC_DIR = objects +UI_DIR = objects +RCC_DIR = objects +INCLUDEPATH += ../src + +macx { + CONFIG -= app_bundle + LIBS += -framework Carbon +} + +CONFIG += qt +QT += opengl + +# Optionally specify location of Eigen2 using the +# EIGEN2DIR env. variable +EIGEN2_DIR = $$(EIGEN2DIR) +!isEmpty(EIGEN2_DIR) { + INCLUDEPATH += $$EIGEN2_DIR +} +else { + macx { + INCLUDEPATH += /opt/local/include/eigen2 + } + else { + INCLUDEPATH += /usr/include/eigen2 + } +} + +LEXSOURCES += ../src/lexer.l +YACCSOURCES += ../src/parser.y + +HEADERS += ../src/builtin.h \ + ../src/context.h \ + ../src/csgterm.h \ + ../src/dxfdata.h \ + ../src/dxfdim.h \ + ../src/dxftess.h \ + ../src/export.h \ + ../src/expression.h \ + ../src/function.h \ + ../src/grid.h \ + ../src/module.h \ + ../src/node.h \ + ../src/dxflinextrudenode.h \ + ../src/dxfrotextrudenode.h \ + ../src/projectionnode.h \ + ../src/importnode.h \ + ../src/csgnode.h \ + ../src/transformnode.h \ + ../src/rendernode.h \ + ../src/openscad.h \ + ../src/polyset.h \ + ../src/printutils.h \ + ../src/value.h \ + ../src/progress.h \ + ../src/traverser.h \ + ../src/csgnode.h \ + ../src/visitor.h \ + ../src/nodedumper.h \ + ../src/nodecache.h \ + ../src/importnode.h \ + ../src/state.h \ + ../src/PolySetRenderer.h \ + ../src/Tree.h \ + ../src/myqhash.h \ + ../src/CSGTermRenderer.h + +SOURCES += csgtexttest.cc \ + ../src/export.cc \ + ../src/value.cc \ + ../src/expr.cc \ + ../src/func.cc \ + ../src/module.cc \ + ../src/node.cc \ + ../src/context.cc \ + ../src/csgterm.cc \ + ../src/polyset.cc \ + ../src/csgops.cc \ + ../src/transform.cc \ + ../src/primitives.cc \ + ../src/projection.cc \ + ../src/cgaladv.cc \ + ../src/surface.cc \ + ../src/control.cc \ + ../src/render.cc \ + ../src/import.cc \ + ../src/dxfdata.cc \ + ../src/dxftess.cc \ + ../src/dxftess-glu.cc \ + ../src/dxftess-cgal.cc \ + ../src/dxfdim.cc \ + ../src/dxflinextrude.cc \ + ../src/dxfrotextrude.cc \ + ../src/printutils.cc \ + ../src/progress.cc \ + ../src/nodedumper.cc \ + ../src/traverser.cc \ + ../src/PolySetRenderer.cc \ + ../src/Tree.cc \ + ../src/qhash.cc \ + ../src/CSGTermRenderer.cc |