summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDon Bright <hugh.m.bright@gmail.com>2013-05-27 05:08:31 (GMT)
committerDon Bright <hugh.m.bright@gmail.com>2013-05-27 05:08:31 (GMT)
commit37dc9342a14206f5862447eb9d3d5049ec67f638 (patch)
tree17e5a57dfa154821918094cab47476189771ce00
parent6742ad55f4cf335fc767ab65784aab81e06b61d0 (diff)
parent0967a26bff45951d7b86fe628e8b1156e6e40ede (diff)
Merge branch 'master' of github.com:openscad/openscad into issue125
-rw-r--r--examples/example024.scad32
-rwxr-xr-xscripts/uni-build-dependencies.sh17
-rw-r--r--src/CSGTermEvaluator.cc2
-rw-r--r--src/CsgInfo.h2
-rw-r--r--src/ModuleCache.cc26
-rw-r--r--src/OpenCSGRenderer.cc63
-rw-r--r--src/ThrownTogetherRenderer.cc82
-rw-r--r--src/cgalworker.cc1
-rw-r--r--src/csgterm.cc56
-rw-r--r--src/csgterm.h38
-rw-r--r--src/func.cc2
-rw-r--r--src/lexer.l87
-rw-r--r--src/mainwin.cc17
-rw-r--r--src/modcontext.cc9
-rw-r--r--src/module.cc45
-rw-r--r--src/module.h15
-rw-r--r--src/parsersettings.cc76
-rw-r--r--src/parsersettings.h6
-rw-r--r--src/renderer.cc73
-rw-r--r--src/renderer.h3
-rw-r--r--testdata/modulecache-tests/README.txt31
-rw-r--r--testdata/modulecache-tests/includemissing.scad2
-rw-r--r--testdata/modulecache-tests/includemissingsub.scad2
-rw-r--r--testdata/scad/features/background-modifier.scad5
-rw-r--r--testdata/scad/features/highlight-and-background-modifier.scad31
-rw-r--r--testdata/scad/features/highlight-modifier.scad5
-rw-r--r--testdata/scad/features/linear_extrude-scale-tests.scad17
-rw-r--r--testdata/scad/features/linear_extrude-scale-zero-tests.scad56
-rw-r--r--testdata/scad/features/linear_extrude-tests.scad11
-rw-r--r--tests/CMakeLists.txt14
-rw-r--r--tests/regression/cgalpngtest/example024-expected.pngbin0 -> 5797 bytes
-rw-r--r--tests/regression/cgalpngtest/highlight-modifier-expected.pngbin12436 -> 12437 bytes
-rw-r--r--tests/regression/cgalpngtest/linear_extrude-scale-zero-tests-expected.pngbin0 -> 16708 bytes
-rw-r--r--tests/regression/cgalpngtest/linear_extrude-tests-expected.pngbin10926 -> 10804 bytes
-rw-r--r--tests/regression/dumptest/background-modifier-expected.txt12
-rw-r--r--tests/regression/dumptest/example024-expected.txt1869
-rw-r--r--tests/regression/dumptest/highlight-and-background-modifier-expected.txt55
-rw-r--r--tests/regression/dumptest/highlight-modifier-expected.txt12
-rw-r--r--tests/regression/dumptest/linear_extrude-scale-zero-tests-expected.txt253
-rw-r--r--tests/regression/dumptest/linear_extrude-tests-expected.txt22
-rw-r--r--tests/regression/opencsgtest/background-modifier-expected.pngbin17797 -> 17763 bytes
-rw-r--r--tests/regression/opencsgtest/difference-tests-expected.pngbin11900 -> 11897 bytes
-rw-r--r--tests/regression/opencsgtest/example024-expected.pngbin0 -> 5031 bytes
-rw-r--r--tests/regression/opencsgtest/highlight-and-background-modifier-expected.pngbin22188 -> 25034 bytes
-rw-r--r--tests/regression/opencsgtest/highlight-modifier-expected.pngbin14172 -> 16507 bytes
-rw-r--r--tests/regression/opencsgtest/linear_extrude-scale-zero-tests-expected.pngbin0 -> 29795 bytes
-rw-r--r--tests/regression/opencsgtest/linear_extrude-tests-expected.pngbin11429 -> 11331 bytes
-rw-r--r--tests/regression/throwntogethertest/background-modifier-expected.pngbin17797 -> 17772 bytes
-rw-r--r--tests/regression/throwntogethertest/child-background-expected.pngbin0 -> 13893 bytes
-rw-r--r--tests/regression/throwntogethertest/difference-tests-expected.pngbin11762 -> 11748 bytes
-rw-r--r--tests/regression/throwntogethertest/example024-expected.pngbin0 -> 7158 bytes
-rw-r--r--tests/regression/throwntogethertest/highlight-and-background-modifier-expected.pngbin0 -> 28740 bytes
-rw-r--r--tests/regression/throwntogethertest/highlight-modifier-expected.pngbin13335 -> 17975 bytes
-rw-r--r--tests/regression/throwntogethertest/linear_extrude-scale-zero-tests-expected.pngbin0 -> 29795 bytes
-rw-r--r--tests/regression/throwntogethertest/linear_extrude-tests-expected.pngbin11439 -> 11331 bytes
55 files changed, 2774 insertions, 275 deletions
diff --git a/examples/example024.scad b/examples/example024.scad
new file mode 100644
index 0000000..1502ec7
--- /dev/null
+++ b/examples/example024.scad
@@ -0,0 +1,32 @@
+// Menger Sponge
+// By Nathan Hellweg, Emmett Lalish and Marius Kintel May 13, 2013
+// CC-BY-SA license
+
+// Size of edge of sponge
+D=100;
+// Fractal depth (number of iterations)
+n=3;
+
+module menger() {
+ difference() {
+ cube(D, center=true);
+ for (v=[[0,0,0], [0,0,90], [0,90,0]])
+ rotate(v) menger_negative(side=D, maxside=D, level=n);
+ }
+}
+
+module menger_negative(side=1, maxside=1, level=1) {
+ l=side/3;
+ cube([maxside*1.1, l, l], center=true);
+ if (level > 1) {
+ for (i=[-1:1], j=[-1:1])
+ if (i || j)
+ translate([0, i*l, j*l])
+ menger_negative(side=l, maxside=maxside, level=level-1);
+ }
+}
+
+difference() {
+ rotate([45, atan(1/sqrt(2)), 0]) menger();
+ translate([0,0,-D]) cube(2*D, center=true);
+}
diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh
index bfc830f..60dbb74 100755
--- a/scripts/uni-build-dependencies.sh
+++ b/scripts/uni-build-dependencies.sh
@@ -408,8 +408,21 @@ build_opencsg()
OPENCSG_QMAKE=qmake-qt4
elif [ "`command -v qmake4`" ]; then
OPENCSG_QMAKE=qmake4
- else
+ elif [ "`command -v qmake`" ]; then
OPENCSG_QMAKE=qmake
+ else
+ echo qmake not found... using standard OpenCSG makefiles
+ OPENCSG_QMAKE=make
+ cp Makefile Makefile.bak
+ cp src/Makefile src/Makefile.bak
+
+ cat Makefile.bak | sed s/example// |sed s/glew// > Makefile
+ cat src/Makefile.bak | sed s@^INCPATH.*@INCPATH\ =\ -I$BASEDIR/include\ -I../include\ -I..\ -I.@ > src/Makefile
+ cp src/Makefile src/Makefile.bak2
+ cat src/Makefile.bak2 | sed s@^LIBS.*@LIBS\ =\ -L$BASEDIR/lib\ -L/usr/X11R6/lib\ -lGLU\ -lGL@ > src/Makefile
+ tmp=$version
+ build_glu 9.0.0 # todo - autodetect the need for glu
+ version=$tmp
fi
cd $BASEDIR/src/OpenCSG-$version/src
@@ -562,7 +575,7 @@ fi
build_eigen 3.1.1
build_gmp 5.0.5
build_mpfr 3.1.1
-build_boost 1.49.0
+build_boost 1.53.0
# NB! For CGAL, also update the actual download URL in the function
build_cgal 4.1
build_glew 1.9.0
diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc
index 6b39c66..a6b654c 100644
--- a/src/CSGTermEvaluator.cc
+++ b/src/CSGTermEvaluator.cc
@@ -57,6 +57,7 @@ void CSGTermEvaluator::applyToChildren(const AbstractNode &node, CSGTermEvaluato
}
}
if (t1 && node.modinst->isHighlight()) {
+ t1->flag = CSGTerm::FLAG_HIGHLIGHT;
this->highlights.push_back(t1);
}
if (t1 && node.modinst->isBackground()) {
@@ -95,6 +96,7 @@ static shared_ptr<CSGTerm> evaluate_csg_term_from_ps(const State &state,
stream << node.name() << node.index();
shared_ptr<CSGTerm> t(new CSGTerm(ps, state.matrix(), state.color(), stream.str()));
if (modinst->isHighlight()) {
+ t->flag = CSGTerm::FLAG_HIGHLIGHT;
highlights.push_back(t);
}
if (modinst->isBackground()) {
diff --git a/src/CsgInfo.h b/src/CsgInfo.h
index fe953b5..774325b 100644
--- a/src/CsgInfo.h
+++ b/src/CsgInfo.h
@@ -57,7 +57,7 @@ public:
if (this->root_norm_term) {
this->root_chain = new CSGChain();
this->root_chain->import(this->root_norm_term);
- PRINTB("Normalized CSG tree has %d elements", int(this->root_chain->polysets.size()));
+ PRINTB("Normalized CSG tree has %d elements", int(this->root_chain->objects.size()));
}
else {
this->root_chain = NULL;
diff --git a/src/ModuleCache.cc b/src/ModuleCache.cc
index 4944495..505015e 100644
--- a/src/ModuleCache.cc
+++ b/src/ModuleCache.cc
@@ -14,32 +14,32 @@
#include <time.h>
#include <sys/stat.h>
+//#include "parsersettings.h"
/*!
FIXME: Implement an LRU scheme to avoid having an ever-growing module cache
*/
ModuleCache *ModuleCache::inst = NULL;
-static bool is_modified(const std::string &filename, const time_t &mtime)
-{
- struct stat st;
- memset(&st, 0, sizeof(struct stat));
- stat(filename.c_str(), &st);
- return (st.st_mtime > mtime);
-}
+/*!
+ Reevaluate the given file and recompile if necessary.
+ Returns NULL on any error (e.g. compile error or file not found)
+ If the given filename is relative, it means that the module hasn't been
+ previously located.
+*/
FileModule *ModuleCache::evaluate(const std::string &filename)
{
FileModule *lib_mod = NULL;
- // Create cache ID
+ // Create cache ID
struct stat st;
memset(&st, 0, sizeof(struct stat));
stat(filename.c_str(), &st);
std::string cache_id = str(boost::format("%x.%x") % st.st_mtime % st.st_size);
- // Lookup in cache
+ // Lookup in cache
if (this->entries.find(filename) != this->entries.end() &&
this->entries[filename].cache_id == cache_id) {
#ifdef DEBUG
@@ -48,15 +48,15 @@ FileModule *ModuleCache::evaluate(const std::string &filename)
#endif
lib_mod = &(*this->entries[filename].module);
- BOOST_FOREACH(const FileModule::IncludeContainer::value_type &item, lib_mod->includes) {
- if (is_modified(item.first, item.second)) {
+ BOOST_FOREACH(const FileModule::IncludeContainer::value_type &include, lib_mod->includes) {
+ if (lib_mod->include_modified(include.second)) {
lib_mod = NULL;
break;
}
}
}
- // If cache lookup failed (non-existing or old timestamp), compile module
+ // If cache lookup failed (non-existing or old timestamp), compile module
if (!lib_mod) {
#ifdef DEBUG
if (this->entries.find(filename) != this->entries.end()) {
@@ -91,7 +91,7 @@ FileModule *ModuleCache::evaluate(const std::string &filename)
if (lib_mod) {
// We defer deletion so we can ensure that the new module won't
- // have the same address as the old
+ // have the same address as the old
delete oldmodule;
this->entries[filename].module = lib_mod;
} else {
diff --git a/src/OpenCSGRenderer.cc b/src/OpenCSGRenderer.cc
index eb66687..b4acf82 100644
--- a/src/OpenCSGRenderer.cc
+++ b/src/OpenCSGRenderer.cc
@@ -77,35 +77,50 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
std::vector<OpenCSG::Primitive*> primitives;
size_t j = 0;
for (size_t i = 0;; i++) {
- bool last = i == chain->polysets.size();
- if (last || chain->types[i] == CSGTerm::TYPE_UNION) {
+ const CSGChainObject &i_obj = chain->objects[i];
+ bool last = i == chain->objects.size();
+ if (last || i_obj.type == CSGTerm::TYPE_UNION) {
if (j+1 != i) {
OpenCSG::render(primitives);
glDepthFunc(GL_EQUAL);
}
if (shaderinfo) glUseProgram(shaderinfo[0]);
for (; j < i; j++) {
- const Transform3d &m = chain->matrices[j];
- const Color4f &c = chain->colors[j];
+ const CSGChainObject &j_obj = chain->objects[j];
+ const Color4f &c = j_obj.color;
glPushMatrix();
- glMultMatrixd(m.data());
- PolySet::csgmode_e csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
- if (highlight) {
- setColor(COLORMODE_HIGHLIGHT, shaderinfo);
- csgmode = PolySet::csgmode_e(csgmode + 20);
- }
- else if (background) {
- setColor(COLORMODE_BACKGROUND, shaderinfo);
+ glMultMatrixd(j_obj.matrix.data());
+ PolySet::csgmode_e csgmode = j_obj.type == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
+ ColorMode colormode = COLORMODE_NONE;
+ if (background) {
+ if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
+ colormode = COLORMODE_HIGHLIGHT;
+ }
+ else {
+ colormode = COLORMODE_BACKGROUND;
+ }
csgmode = PolySet::csgmode_e(csgmode + 10);
- } else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
- // User-defined color or alpha from source
- setColor(c.data(), shaderinfo);
- } else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) {
- setColor(COLORMODE_CUTOUT, shaderinfo);
+ } else if (j_obj.type == CSGTerm::TYPE_DIFFERENCE) {
+ if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
+ colormode = COLORMODE_HIGHLIGHT;
+ csgmode = PolySet::csgmode_e(csgmode + 20);
+ }
+ else {
+ colormode = COLORMODE_CUTOUT;
+ }
} else {
- setColor(COLORMODE_MATERIAL, shaderinfo);
+ if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
+ colormode = COLORMODE_HIGHLIGHT;
+ csgmode = PolySet::csgmode_e(csgmode + 20);
+ }
+ else {
+ colormode = COLORMODE_MATERIAL;
+ }
}
- chain->polysets[j]->render_surface(csgmode, m, shaderinfo);
+
+ setColor(colormode, c.data(), shaderinfo);
+
+ j_obj.polyset->render_surface(csgmode, j_obj.matrix, shaderinfo);
glPopMatrix();
}
if (shaderinfo) glUseProgram(0);
@@ -118,11 +133,11 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
if (last) break;
- OpenCSGPrim *prim = new OpenCSGPrim(chain->types[i] == CSGTerm::TYPE_DIFFERENCE ?
- OpenCSG::Subtraction : OpenCSG::Intersection, chain->polysets[i]->convexity);
- prim->ps = chain->polysets[i];
- prim->m = chain->matrices[i];
- prim->csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
+ OpenCSGPrim *prim = new OpenCSGPrim(i_obj.type == CSGTerm::TYPE_DIFFERENCE ?
+ OpenCSG::Subtraction : OpenCSG::Intersection, i_obj.polyset->convexity);
+ prim->ps = i_obj.polyset;
+ prim->m = i_obj.matrix;
+ prim->csgmode = i_obj.type == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
if (highlight) prim->csgmode = PolySet::csgmode_e(prim->csgmode + 20);
else if (background) prim->csgmode = PolySet::csgmode_e(prim->csgmode + 10);
primitives.push_back(prim);
diff --git a/src/ThrownTogetherRenderer.cc b/src/ThrownTogetherRenderer.cc
index 146d2e1..6be30dc 100644
--- a/src/ThrownTogetherRenderer.cc
+++ b/src/ThrownTogetherRenderer.cc
@@ -31,6 +31,7 @@
#include "system-gl.h"
#include <boost/unordered_map.hpp>
+#include <boost/foreach.hpp>
ThrownTogetherRenderer::ThrownTogetherRenderer(CSGChain *root_chain,
CSGChain *highlights_chain,
@@ -52,9 +53,9 @@ void ThrownTogetherRenderer::draw(bool /*showfaces*/, bool showedges) const
glDisable(GL_CULL_FACE);
}
if (this->background_chain)
- renderCSGChain(this->background_chain, false, true, showedges, false);
+ renderCSGChain(this->background_chain, false, true, showedges, false);
if (this->highlights_chain)
- renderCSGChain(this->highlights_chain, true, false, showedges, false);
+ renderCSGChain(this->highlights_chain, true, false, showedges, false);
}
void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
@@ -62,58 +63,63 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
bool fberror) const
{
glDepthFunc(GL_LEQUAL);
- boost::unordered_map<std::pair<PolySet*,Transform3d*>,int> polySetVisitMark;
- for (size_t i = 0; i < chain->polysets.size(); i++) {
- if (polySetVisitMark[std::make_pair(chain->polysets[i].get(), &chain->matrices[i])]++ > 0)
+ boost::unordered_map<std::pair<PolySet*,const Transform3d*>,int> polySetVisitMark;
+ BOOST_FOREACH(const CSGChainObject &obj, chain->objects) {
+ if (polySetVisitMark[std::make_pair(obj.polyset.get(), &obj.matrix)]++ > 0)
continue;
- const Transform3d &m = chain->matrices[i];
- const Color4f &c = chain->colors[i];
+ const Transform3d &m = obj.matrix;
+ const Color4f &c = obj.color;
glPushMatrix();
glMultMatrixd(m.data());
- PolySet::csgmode_e csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
+ PolySet::csgmode_e csgmode = obj.type == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
+ ColorMode colormode = COLORMODE_NONE;
+ ColorMode edge_colormode = COLORMODE_NONE;
+
if (highlight) {
csgmode = PolySet::csgmode_e(csgmode + 20);
- setColor(COLORMODE_HIGHLIGHT);
- chain->polysets[i]->render_surface(csgmode, m);
- if (showedges) {
- setColor(COLORMODE_HIGHLIGHT_EDGES);
- chain->polysets[i]->render_edges(csgmode);
- }
+ colormode = COLORMODE_HIGHLIGHT;
+ edge_colormode = COLORMODE_HIGHLIGHT_EDGES;
} else if (background) {
- csgmode = PolySet::csgmode_e(csgmode + 10);
- setColor(COLORMODE_BACKGROUND);
- chain->polysets[i]->render_surface(csgmode, m);
- if (showedges) {
- setColor(COLORMODE_BACKGROUND_EDGES);
- chain->polysets[i]->render_edges(csgmode);
+ if (obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
+ colormode = COLORMODE_HIGHLIGHT;
+ }
+ else {
+ colormode = COLORMODE_BACKGROUND;
}
+ csgmode = PolySet::csgmode_e(csgmode + 10);
+ edge_colormode = COLORMODE_BACKGROUND_EDGES;
} else if (fberror) {
if (highlight) csgmode = PolySet::csgmode_e(csgmode + 20);
else if (background) csgmode = PolySet::csgmode_e(csgmode + 10);
else csgmode = PolySet::csgmode_e(csgmode);
- chain->polysets[i]->render_surface(csgmode, m);
- } else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
- setColor(c.data());
- chain->polysets[i]->render_surface(csgmode, m);
- if (showedges) {
- glColor4f((c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
- chain->polysets[i]->render_edges(csgmode);
+ } else if (obj.type == CSGTerm::TYPE_DIFFERENCE) {
+ if (obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
+ colormode = COLORMODE_HIGHLIGHT;
+ csgmode = PolySet::csgmode_e(csgmode + 20);
}
- } else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) {
- setColor(COLORMODE_CUTOUT);
- chain->polysets[i]->render_surface(csgmode, m);
- if (showedges) {
- setColor(COLORMODE_CUTOUT_EDGES);
- chain->polysets[i]->render_edges(csgmode);
+ else {
+ colormode = COLORMODE_CUTOUT;
}
+ edge_colormode = COLORMODE_CUTOUT_EDGES;
} else {
- setColor(COLORMODE_MATERIAL);
- chain->polysets[i]->render_surface(csgmode, m);
- if (showedges) {
- setColor(COLORMODE_MATERIAL_EDGES);
- chain->polysets[i]->render_edges(csgmode);
+ if (obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
+ colormode = COLORMODE_HIGHLIGHT;
+ csgmode = PolySet::csgmode_e(csgmode + 20);
+ }
+ else {
+ colormode = COLORMODE_MATERIAL;
}
+ edge_colormode = COLORMODE_MATERIAL_EDGES;
}
+
+ setColor(colormode, c.data());
+ obj.polyset->render_surface(csgmode, m);
+ if (showedges) {
+ // FIXME? glColor4f((c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
+ setColor(edge_colormode);
+ obj.polyset->render_edges(csgmode);
+ }
+
glPopMatrix();
}
}
diff --git a/src/cgalworker.cc b/src/cgalworker.cc
index 96fead9..f011262 100644
--- a/src/cgalworker.cc
+++ b/src/cgalworker.cc
@@ -9,6 +9,7 @@
CGALWorker::CGALWorker()
{
this->thread = new QThread();
+ if (this->thread->stackSize() < 1024*1024) this->thread->setStackSize(1024*1024);
connect(this->thread, SIGNAL(started()), this, SLOT(work()));
moveToThread(this->thread);
}
diff --git a/src/csgterm.cc b/src/csgterm.cc
index aed97b2..7852715 100644
--- a/src/csgterm.cc
+++ b/src/csgterm.cc
@@ -28,6 +28,7 @@
#include "polyset.h"
#include "linalg.h"
#include <sstream>
+#include <boost/foreach.hpp>
/*!
\class CSGTerm
@@ -103,19 +104,19 @@ shared_ptr<CSGTerm> CSGTerm::createCSGTerm(type_e type, CSGTerm *left, CSGTerm *
}
CSGTerm::CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const Color4f &color, const std::string &label)
- : type(TYPE_PRIMITIVE), polyset(polyset), label(label), m(matrix), color(color)
+ : type(TYPE_PRIMITIVE), polyset(polyset), label(label), flag(CSGTerm::FLAG_NONE), m(matrix), color(color)
{
initBoundingBox();
}
CSGTerm::CSGTerm(type_e type, shared_ptr<CSGTerm> left, shared_ptr<CSGTerm> right)
- : type(type), left(left), right(right), m(Transform3d::Identity())
+ : type(type), left(left), right(right), flag(CSGTerm::FLAG_NONE), m(Transform3d::Identity())
{
initBoundingBox();
}
CSGTerm::CSGTerm(type_e type, CSGTerm *left, CSGTerm *right)
- : type(type), left(left), right(right), m(Transform3d::Identity())
+ : type(type), left(left), right(right), flag(CSGTerm::FLAG_NONE), m(Transform3d::Identity())
{
initBoundingBox();
}
@@ -181,26 +182,14 @@ std::string CSGTerm::dump()
return dump.str();
}
-CSGChain::CSGChain()
-{
-}
-
-void CSGChain::add(const shared_ptr<PolySet> &polyset, const Transform3d &m, const Color4f &color, CSGTerm::type_e type, std::string label)
-{
- polysets.push_back(polyset);
- matrices.push_back(m);
- colors.push_back(color);
- types.push_back(type);
- labels.push_back(label);
-}
-
-void CSGChain::import(shared_ptr<CSGTerm> term, CSGTerm::type_e type)
+void CSGChain::import(shared_ptr<CSGTerm> term, CSGTerm::type_e type, CSGTerm::Flag flag)
{
+ CSGTerm::Flag newflag = (CSGTerm::Flag)(term->flag | flag);
if (term->type == CSGTerm::TYPE_PRIMITIVE) {
- add(term->polyset, term->m, term->color, type, term->label);
+ this->objects.push_back(CSGChainObject(term->polyset, term->m, term->color, type, term->label, newflag));
} else {
- import(term->left, type);
- import(term->right, term->type);
+ import(term->left, type, newflag);
+ import(term->right, term->type, newflag);
}
}
@@ -208,21 +197,20 @@ std::string CSGChain::dump(bool full)
{
std::stringstream dump;
- for (size_t i = 0; i < types.size(); i++)
- {
- if (types[i] == CSGTerm::TYPE_UNION) {
- if (i != 0) dump << "\n";
+ BOOST_FOREACH(const CSGChainObject &obj, this->objects) {
+ if (obj.type == CSGTerm::TYPE_UNION) {
+ if (&obj != &this->objects.front()) dump << "\n";
dump << "+";
}
- else if (types[i] == CSGTerm::TYPE_DIFFERENCE)
+ else if (obj.type == CSGTerm::TYPE_DIFFERENCE)
dump << " -";
- else if (types[i] == CSGTerm::TYPE_INTERSECTION)
+ else if (obj.type == CSGTerm::TYPE_INTERSECTION)
dump << " *";
- dump << labels[i];
+ dump << obj.label;
if (full) {
- dump << " polyset: \n" << polysets[i]->dump() << "\n";
- dump << " matrix: \n" << matrices[i].matrix() << "\n";
- dump << " color: \n" << colors[i] << "\n";
+ dump << " polyset: \n" << obj.polyset->dump() << "\n";
+ dump << " matrix: \n" << obj.matrix.matrix() << "\n";
+ dump << " color: \n" << obj.color << "\n";
}
}
dump << "\n";
@@ -232,11 +220,11 @@ std::string CSGChain::dump(bool full)
BoundingBox CSGChain::getBoundingBox() const
{
BoundingBox bbox;
- for (size_t i=0;i<polysets.size();i++) {
- if (types[i] != CSGTerm::TYPE_DIFFERENCE) {
- BoundingBox psbox = polysets[i]->getBoundingBox();
+ BOOST_FOREACH(const CSGChainObject &obj, this->objects) {
+ if (obj.type != CSGTerm::TYPE_DIFFERENCE) {
+ BoundingBox psbox = obj.polyset->getBoundingBox();
if (!psbox.isNull()) {
- bbox.extend(matrices[i] * psbox);
+ bbox.extend(obj.matrix * psbox);
}
}
}
diff --git a/src/csgterm.h b/src/csgterm.h
index 566ebc3..94878e5 100644
--- a/src/csgterm.h
+++ b/src/csgterm.h
@@ -18,6 +18,12 @@ public:
TYPE_DIFFERENCE
};
+ enum Flag {
+ FLAG_NONE = 0x00,
+ FLAG_BACKGROUND = 0x01,
+ FLAG_HIGHLIGHT = 0x03
+ };
+
static shared_ptr<CSGTerm> createCSGTerm(type_e type, shared_ptr<CSGTerm> left, shared_ptr<CSGTerm> right);
static shared_ptr<CSGTerm> createCSGTerm(type_e type, CSGTerm *left, CSGTerm *right);
@@ -27,6 +33,7 @@ public:
shared_ptr<CSGTerm> left;
shared_ptr<CSGTerm> right;
BoundingBox bbox;
+ Flag flag;
CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const Color4f &color, const std::string &label);
~CSGTerm();
@@ -46,19 +53,34 @@ private:
friend class CSGChain;
};
+class CSGChainObject
+{
+public:
+ CSGChainObject(shared_ptr<PolySet> polyset,
+ const Transform3d &matrix,
+ const Color4f &color,
+ CSGTerm::type_e type,
+ const std::string &label,
+ CSGTerm::Flag flag = CSGTerm::FLAG_NONE)
+ : polyset(polyset), matrix(matrix), color(color), type(type), label(label), flag(flag) {}
+
+ shared_ptr<PolySet> polyset;
+ Transform3d matrix;
+ Color4f color;
+ CSGTerm::type_e type;
+ std::string label;
+ CSGTerm::Flag flag;
+};
+
class CSGChain
{
public:
- std::vector<shared_ptr<PolySet> > polysets;
- std::vector<Transform3d> matrices;
- std::vector<Color4f> colors;
- std::vector<CSGTerm::type_e> types;
- std::vector<std::string> labels;
+ std::vector<CSGChainObject> objects;
- CSGChain();
+ CSGChain() {};
- void add(const shared_ptr<PolySet> &polyset, const Transform3d &m, const Color4f &color, CSGTerm::type_e type, std::string label);
- void import(shared_ptr<CSGTerm> term, CSGTerm::type_e type = CSGTerm::TYPE_UNION);
+ void import(shared_ptr<CSGTerm> term, CSGTerm::type_e type = CSGTerm::TYPE_UNION,
+ CSGTerm::Flag flag = CSGTerm::FLAG_NONE);
std::string dump(bool full = false);
BoundingBox getBoundingBox() const;
diff --git a/src/func.cc b/src/func.cc
index 18884b8..eaaae74 100644
--- a/src/func.cc
+++ b/src/func.cc
@@ -64,6 +64,7 @@ AbstractFunction::~AbstractFunction()
Value AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const
{
+ (void)evalctx; // unusued parameter
return Value();
}
@@ -500,6 +501,7 @@ Value builtin_search(const Context *, const EvalContext *evalctx)
Value builtin_version(const Context *, const EvalContext *evalctx)
{
+ (void)evalctx; // unusued parameter
Value::VectorType val;
val.push_back(Value(double(OPENSCAD_YEAR)));
val.push_back(Value(double(OPENSCAD_MONTH)));
diff --git a/src/lexer.l b/src/lexer.l
index 6dfe9bc..0b8048f 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -100,7 +100,7 @@ E [Ee][+-]?{D}+
%%
-include[ \t\r\n>]*"<" { BEGIN(cond_include); }
+include[ \t\r\n>]*"<" { BEGIN(cond_include); filepath = filename = "";}
<cond_include>{
[^\t\r\n>]*"/" { filepath = yytext; }
[^\t\r\n>/]+ { filename = yytext; }
@@ -113,29 +113,16 @@ use[ \t\r\n>]*"<" { BEGIN(cond_use); }
[^\t\r\n>]+ { filename = yytext; }
">" {
BEGIN(INITIAL);
- fs::path usepath;
- if (boosty::is_absolute(fs::path(filename))) {
- usepath = filename;
- }
- else {
- usepath = sourcepath() / filename;
- if (!fs::exists(usepath)) {
- usepath = locate_file(filename);
- }
- }
- /* Only accept regular files which exists */
- if (usepath.has_parent_path() && fs::exists(usepath) && !fs::is_directory(usepath)) {
- handle_dep(usepath.string());
- parserlval.text = strdup(usepath.string().c_str());
- return TOK_USE;
- } else {
- PRINTB("WARNING: Can't open 'use' file '%s'.", filename);
- if ( filename.size() == 0 )
- PRINT("WARNING: 'use' filename is blank");
- else if ( fs::is_directory( usepath ) )
- PRINTB("WARNING: 'use' file points to a directory: %s",filename);
- }
- }
+ fs::path fullpath = find_valid_path(sourcepath(), fs::path(filename), &openfilenames);
+ if (fullpath.empty()) {
+ PRINTB("WARNING: Can't open library '%s'.", filename);
+ parserlval.text = strdup(filename.c_str());
+ } else {
+ handle_dep(fullpath.string());
+ parserlval.text = strdup(fullpath.string().c_str());
+ }
+ return TOK_USE;
+ }
}
<<EOF>> {
@@ -206,55 +193,37 @@ fs::path sourcepath()
Rules for include <path/file>
1) include <sourcepath/path/file>
2) include <librarydir/path/file>
+
+ Globals used: filepath, sourcepath, filename
*/
void includefile()
{
- if (filename.empty()) return;
-
- fs::path dirinfo = sourcepath();
- if (!filepath.empty()) {
- if (boosty::is_absolute(fs::path(filepath))) {
- dirinfo = filepath;
- }
- else {
- dirinfo /= filepath;
- }
- }
-
- fs::path finfo = dirinfo / filename;
- if (!exists(finfo)) {
- finfo = locate_file((fs::path(filepath) / filename).string());
- }
-
- if (!exists(finfo) || finfo.empty()) {
- // deal with some unusual situations with is_absolute() and Wine
- fs::path fnp( fs::path(filepath) / filename );
- if (fs::exists( fnp ) && !fs::is_directory( fnp )) {
- finfo = fnp;
- }
- }
-
- if (finfo.empty()) {
- PRINTB("WARNING: Can't find 'include' file '%s'.", filename);
+ fs::path localpath = fs::path(filepath) / filename;
+ fs::path fullpath = find_valid_path(sourcepath(), localpath, &openfilenames);
+ if (!fullpath.empty()) {
+ rootmodule->registerInclude(boosty::stringy(localpath), boosty::stringy(fullpath));
}
+ else {
+ rootmodule->registerInclude(boosty::stringy(localpath), boosty::stringy(localpath));
+ PRINTB("WARNING: Can't open include file '%s'.", boosty::stringy(localpath));
+ if (path_stack.size() > 0) path_stack.pop_back();
+ return;
+ };
- std::string fullname = boosty::absolute(finfo).string();
- // Detect circular includes
- BOOST_FOREACH(std::string &s, openfilenames) {
- if (s == fullname) return;
- }
+ std::string fullname = boosty::stringy(fullpath);
filepath.clear();
- path_stack.push_back(finfo.parent_path());
+ path_stack.push_back(fullpath.parent_path());
handle_dep(fullname);
- rootmodule->registerInclude(fullname);
+
yyin = fopen(fullname.c_str(), "r");
if (!yyin) {
- PRINTB("WARNING: Can't open 'include' file '%s'.", filename);
+ PRINTB("WARNING: Can't open include file '%s'.", boosty::stringy(localpath));
path_stack.pop_back();
return;
}
+
openfiles.push_back(yyin);
openfilenames.push_back(fullname);
filename.clear();
diff --git a/src/mainwin.cc b/src/mainwin.cc
index 39af31c..08f0435 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -775,14 +775,14 @@ void MainWindow::compileCSG(bool procevents)
}
if (this->root_chain &&
- (this->root_chain->polysets.size() >
+ (this->root_chain->objects.size() >
Preferences::inst()->getValue("advanced/openCSGLimit").toUInt())) {
- PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->polysets.size());
+ PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->objects.size());
PRINT("WARNING: OpenCSG rendering has been disabled.");
}
else {
PRINTB("Normalized CSG tree has %d elements",
- (this->root_chain ? this->root_chain->polysets.size() : 0));
+ (this->root_chain ? this->root_chain->objects.size() : 0));
this->opencsgRenderer = new OpenCSGRenderer(this->root_chain,
this->highlights_chain,
this->background_chain,
@@ -1036,20 +1036,11 @@ bool MainWindow::fileChangedOnDisk()
return false;
}
-// FIXME: The following two methods are duplicated in ModuleCache.cc - refactor
-static bool is_modified(const std::string &filename, const time_t &mtime)
-{
- struct stat st;
- memset(&st, 0, sizeof(struct stat));
- stat(filename.c_str(), &st);
- return (st.st_mtime > mtime);
-}
-
bool MainWindow::includesChanged()
{
if (this->root_module) {
BOOST_FOREACH(const FileModule::IncludeContainer::value_type &item, this->root_module->includes) {
- if (is_modified(item.first, item.second)) return true;
+ if (this->root_module->include_modified(item.second)) return true;
}
}
return false;
diff --git a/src/modcontext.cc b/src/modcontext.cc
index 3879811..3b957fd 100644
--- a/src/modcontext.cc
+++ b/src/modcontext.cc
@@ -125,7 +125,9 @@ Value FileContext::evaluate_function(const std::string &name, const EvalContext
if (foundf) return foundf->evaluate(this, evalctx);
BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) {
- if (m.second->scope.functions.find(name) != m.second->scope.functions.end()) {
+ // m.second is NULL if the library wasn't be compiled (error or file-not-found)
+ if (m.second &&
+ m.second->scope.functions.find(name) != m.second->scope.functions.end()) {
FileContext ctx(*m.second, this->parent);
ctx.initializeModule(*m.second);
// FIXME: Set document path
@@ -146,8 +148,9 @@ AbstractNode *FileContext::instantiate_module(const ModuleInstantiation &inst, c
if (foundm) return foundm->instantiate(this, &inst, evalctx);
BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) {
- assert(m.second);
- if (m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) {
+ // m.second is NULL if the library wasn't be compiled (error or file-not-found)
+ if (m.second &&
+ m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) {
FileContext ctx(*m.second, this->parent);
ctx.initializeModule(*m.second);
// FIXME: Set document path
diff --git a/src/module.cc b/src/module.cc
index e853457..425403b 100644
--- a/src/module.cc
+++ b/src/module.cc
@@ -32,6 +32,7 @@
#include "expression.h"
#include "function.h"
#include "printutils.h"
+#include "parsersettings.h"
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
@@ -46,6 +47,8 @@ AbstractModule::~AbstractModule()
AbstractNode *AbstractModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
+ (void)ctx; // avoid unusued parameter warning
+
AbstractNode *node = new AbstractNode(inst);
node->children = inst->instantiateChildren(evalctx);
@@ -194,12 +197,14 @@ std::string Module::dump(const std::string &indent, const std::string &name) con
return dump.str();
}
-void FileModule::registerInclude(const std::string &filename)
+void FileModule::registerInclude(const std::string &localpath,
+ const std::string &fullpath)
{
struct stat st;
memset(&st, 0, sizeof(struct stat));
- stat(filename.c_str(), &st);
- this->includes[filename] = st.st_mtime;
+ bool valid = stat(fullpath.c_str(), &st) == 0;
+ IncludeFile inc = {fullpath, valid, st.st_mtime};
+ this->includes[localpath] = inc;
}
/*!
@@ -213,20 +218,32 @@ bool FileModule::handleDependencies()
bool changed = false;
// Iterating manually since we want to modify the container while iterating
+
+
+ // If a lib in usedlibs was previously missing, we need to relocate it
+ // by searching the applicable paths. We can identify a previously missing module
+ // as it will have a relative path.
FileModule::ModuleContainer::iterator iter = this->usedlibs.begin();
while (iter != this->usedlibs.end()) {
FileModule::ModuleContainer::iterator curr = iter++;
FileModule *oldmodule = curr->second;
- curr->second = ModuleCache::instance()->evaluate(curr->first);
+
+ // Get an absolute filename for the module
+ std::string filename = curr->first;
+ if (!boosty::is_absolute(filename)) {
+ fs::path fullpath = find_valid_path(this->path, filename);
+ if (!fullpath.empty()) filename = boosty::stringy(fullpath);
+ }
+
+ curr->second = ModuleCache::instance()->evaluate(filename);
if (curr->second != oldmodule) {
changed = true;
#ifdef DEBUG
- PRINTB_NOCACHE(" %s: %p", curr->first % curr->second);
+ PRINTB_NOCACHE(" %s: %p", filename % curr->second);
#endif
}
if (!curr->second) {
- PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", curr->first);
- this->usedlibs.erase(curr);
+ PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", filename);
}
}
@@ -250,3 +267,17 @@ AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiat
return node;
}
+
+bool FileModule::include_modified(IncludeFile inc)
+{
+ struct stat st;
+ memset(&st, 0, sizeof(struct stat));
+
+ fs::path fullpath = find_valid_path(this->path, inc.filename);
+ bool valid = !fullpath.empty() ? (stat(boosty::stringy(fullpath).c_str(), &st) == 0) : false;
+
+ if (valid != inc.valid) return true;
+ if (valid && st.st_mtime > inc.mtime) return true;
+
+ return false;
+}
diff --git a/src/module.h b/src/module.h
index 9f46d37..5dfb8c4 100644
--- a/src/module.h
+++ b/src/module.h
@@ -5,6 +5,9 @@
#include <vector>
#include <list>
#include <boost/unordered_map.hpp>
+#include <time.h>
+#include <sys/stat.h>
+
#include "value.h"
#include "typedefs.h"
#include "localscope.h"
@@ -74,6 +77,12 @@ public:
LocalScope scope;
};
+struct IncludeFile {
+ std::string filename;
+ bool valid;
+ time_t mtime;
+};
+
// FIXME: A FileModule doesn't have definition arguments, so we shouldn't really
// inherit from a Module
class FileModule : public Module
@@ -84,15 +93,15 @@ public:
void setModulePath(const std::string &path) { this->path = path; }
const std::string &modulePath() const { return this->path; }
- void registerInclude(const std::string &filename);
+ void registerInclude(const std::string &localpath, const std::string &fullpath);
bool handleDependencies();
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const;
typedef boost::unordered_map<std::string, class FileModule*> ModuleContainer;
ModuleContainer usedlibs;
- typedef boost::unordered_map<std::string, time_t> IncludeContainer;
+ typedef boost::unordered_map<std::string, struct IncludeFile> IncludeContainer;
IncludeContainer includes;
-
+ bool include_modified(struct IncludeFile inc);
private:
bool is_handling_dependencies;
std::string path;
diff --git a/src/parsersettings.cc b/src/parsersettings.cc
index 48a6cf8..8db33a8 100644
--- a/src/parsersettings.cc
+++ b/src/parsersettings.cc
@@ -18,13 +18,73 @@ void add_librarydir(const std::string &libdir)
Searces for the given file in library paths and returns the full path if found.
Returns an empty path if file cannot be found or filename is a directory.
*/
-std::string locate_file(const std::string &filename)
+fs::path search_libs(const fs::path &localpath)
{
BOOST_FOREACH(const std::string &dir, librarypath) {
- fs::path usepath = fs::path(dir) / filename;
- if (fs::exists(usepath) && !fs::is_directory(usepath)) return usepath.string();
+ fs::path usepath = fs::path(dir) / localpath;
+ if (fs::exists(usepath) && !fs::is_directory(usepath)) {
+ return usepath.string();
+ }
+ }
+ return fs::path();
+}
+
+// files must be 'ordinary' - they must exist and be non-directories
+static bool check_valid(const fs::path &p, const std::vector<std::string> *openfilenames)
+{
+ if (p.empty()) {
+ PRINTB("WARNING: File path is blank: %s",p);
+ return false;
+ }
+ if (!p.has_parent_path()) {
+ PRINTB("WARNING: No parent path: %s",p);
+ return false;
+ }
+ if (!fs::exists(p)) {
+ PRINTB("WARNING: File not found: %s",p);
+ // searched ===
+ return false;
+ }
+ if (fs::is_directory(p)) {
+ PRINTB("WARNING: %s invalid - points to a directory",p);
+ return false;
+ }
+ std::string fullname = boosty::stringy(p);
+ // Detect circular includes
+ if (openfilenames) {
+ BOOST_FOREACH(const std::string &s, *openfilenames) {
+ if (s == fullname) {
+ PRINTB("WARNING: circular include file %s", fullname);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/*!
+ Check if the given filename is valid.
+
+ If the given filename is absolute, do a simple check.
+ If not, search the applicable paths for a valid file.
+
+ Returns the absolute path to a valid file, or an empty path if no
+ valid files could be found.
+*/
+fs::path find_valid_path(const fs::path &sourcepath,
+ const fs::path &localpath,
+ const std::vector<std::string> *openfilenames)
+{
+ if (boosty::is_absolute(localpath)) {
+ if (check_valid(localpath, openfilenames)) return boosty::absolute(localpath);
+ }
+ else {
+ fs::path fpath = sourcepath / localpath;
+ if (check_valid(fpath, openfilenames)) return fpath;
+ fpath = search_libs(localpath);
+ if (!fpath.empty() && check_valid(fpath, openfilenames)) return fpath;
}
- return std::string();
+ return fs::path();
}
void parser_init(const std::string &applicationpath)
@@ -59,15 +119,15 @@ void parser_init(const std::string &applicationpath)
if (!is_directory(libdir / "libraries")) libdir /= "../../..";
#elif !defined(WIN32)
if (is_directory(tmpdir = libdir / "../share/openscad/libraries")) {
- librarydir = boosty::stringy( tmpdir );
+ librarydir = boosty::stringy(tmpdir);
} else if (is_directory(tmpdir = libdir / "../../share/openscad/libraries")) {
- librarydir = boosty::stringy( tmpdir );
+ librarydir = boosty::stringy(tmpdir);
} else if (is_directory(tmpdir = libdir / "../../libraries")) {
- librarydir = boosty::stringy( tmpdir );
+ librarydir = boosty::stringy(tmpdir);
} else
#endif
if (is_directory(tmpdir = libdir / "libraries")) {
- librarydir = boosty::stringy( tmpdir );
+ librarydir = boosty::stringy(tmpdir);
}
if (!librarydir.empty()) add_librarydir(librarydir);
}
diff --git a/src/parsersettings.h b/src/parsersettings.h
index 007aa9c..52172b6 100644
--- a/src/parsersettings.h
+++ b/src/parsersettings.h
@@ -2,11 +2,15 @@
#define PARSERSETTINGS_H_
#include <string>
+#include "boosty.h"
extern int parser_error_pos;
void parser_init(const std::string &applicationpath);
void add_librarydir(const std::string &libdir);
-std::string locate_file(const std::string &filename);
+fs::path search_libs(const fs::path &localpath);
+fs::path find_valid_path(const fs::path &sourcepath,
+ const fs::path &localpath,
+ const std::vector<std::string> *openfilenames = NULL);
#endif
diff --git a/src/renderer.cc b/src/renderer.cc
index 985b460..7c4f8d7 100644
--- a/src/renderer.cc
+++ b/src/renderer.cc
@@ -1,28 +1,11 @@
#include "renderer.h"
#include "rendersettings.h"
-#include "linalg.h"
-void Renderer::setColor(const float color[4], GLint *shaderinfo) const
-{
- Color4f col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
- float c[4] = {color[0], color[1], color[2], color[3]};
- if (c[0] < 0) c[0] = col[0];
- if (c[1] < 0) c[1] = col[1];
- if (c[2] < 0) c[2] = col[2];
- if (c[3] < 0) c[3] = col[3];
- glColor4fv(c);
- if (shaderinfo) {
- glUniform4f(shaderinfo[1], c[0], c[1], c[2], c[3]);
- glUniform4f(shaderinfo[2], (c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
- }
-}
-
-void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const
+bool Renderer::getColor(Renderer::ColorMode colormode, Color4f &col) const
{
- Color4f col;
switch (colormode) {
case COLORMODE_NONE:
- return;
+ return false;
break;
case COLORMODE_MATERIAL:
col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
@@ -31,7 +14,7 @@ void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const
col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_BACK_COLOR);
break;
case COLORMODE_HIGHLIGHT:
- col.setRgb(255, 157, 81, 128);
+ col.setRgb(255, 81, 81, 128);
break;
case COLORMODE_BACKGROUND:
col.setRgb(180, 180, 180, 128);
@@ -49,19 +32,51 @@ void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const
col.setRgb(150, 150, 150, 128);
break;
default:
- return;
+ return false;
break;
}
- float rgba[4];
- rgba[0] = col[0];
- rgba[1] = col[1];
- rgba[2] = col[2];
- rgba[3] = col[3];
- glColor4fv(rgba);
+ return true;
+}
+
+void Renderer::setColor(const float color[4], GLint *shaderinfo) const
+{
+ Color4f col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
+ float c[4] = {color[0], color[1], color[2], color[3]};
+ if (c[0] < 0) c[0] = col[0];
+ if (c[1] < 0) c[1] = col[1];
+ if (c[2] < 0) c[2] = col[2];
+ if (c[3] < 0) c[3] = col[3];
+ glColor4fv(c);
#ifdef ENABLE_OPENCSG
if (shaderinfo) {
- glUniform4f(shaderinfo[1], col[0], col[1], col[2], 1.0f);
- glUniform4f(shaderinfo[2], (col[0]+1)/2, (col[1]+1)/2, (col[2]+1)/2, 1.0f);
+ glUniform4f(shaderinfo[1], c[0], c[1], c[2], c[3]);
+ glUniform4f(shaderinfo[2], (c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
}
#endif
}
+
+void Renderer::setColor(ColorMode colormode, const float color[4], GLint *shaderinfo) const
+{
+ Color4f basecol;
+ if (getColor(colormode, basecol)) {
+ if (colormode == COLORMODE_BACKGROUND) {
+ basecol = Color4f(color[0] >= 0 ? color[0] : basecol[0],
+ color[1] >= 0 ? color[1] : basecol[1],
+ color[2] >= 0 ? color[2] : basecol[2],
+ color[3] >= 0 ? color[3] : basecol[3]);
+ }
+ else if (colormode != COLORMODE_HIGHLIGHT) {
+ basecol = Color4f(color[0] >= 0 ? color[0] : basecol[0],
+ color[1] >= 0 ? color[1] : basecol[1],
+ color[2] >= 0 ? color[2] : basecol[2],
+ color[3] >= 0 ? color[3] : basecol[3]);
+ }
+ setColor(basecol.data(), shaderinfo);
+ }
+}
+
+void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const
+{
+ float c[4] = {-1,-1,-1,-1};
+ setColor(colormode, c, shaderinfo);
+}
diff --git a/src/renderer.h b/src/renderer.h
index 2bc482d..f70b4e1 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -2,6 +2,7 @@
#define RENDERER_H_
#include "system-gl.h"
+#include "linalg.h"
#ifdef _MSC_VER // NULL
#include <cstdlib>
@@ -25,8 +26,10 @@ public:
COLORMODE_BACKGROUND_EDGES
};
+ virtual bool getColor(ColorMode colormode, Color4f &col) const;
virtual void setColor(const float color[4], GLint *shaderinfo = NULL) const;
virtual void setColor(ColorMode colormode, GLint *shaderinfo = NULL) const;
+ virtual void setColor(ColorMode colormode, const float color[4], GLint *shaderinfo = NULL) const;
};
#endif // RENDERER_H
diff --git a/testdata/modulecache-tests/README.txt b/testdata/modulecache-tests/README.txt
index 277cff8..ce341ca 100644
--- a/testdata/modulecache-tests/README.txt
+++ b/testdata/modulecache-tests/README.txt
@@ -72,10 +72,39 @@ o Compile (F5) - Verify that you get a circular disc
o Edit radius.scad: Change RADIUS
o Compile (F5) - Verify that the disc changed size
-Test9: Circular include
+Test10: Circular include
------
o Open circularincludemain.scad
o Compile (F5)
o Verify that OpenSCAD won't hang or crash
+Test11: Missing include file appears
+------
+o rm missing.scad
+o Open includemissing.scad
+o Compile (F5)
+o Verify that you get: WARNING: Can't open 'use' file 'missing.scad'.
+o echo "module missing() { sphere(10); }" > missing.scad
+o rm missing.scad
+o Reload and Compile (F4) - verify that the sphere is gone
+
+Test12: Missing include file in subpath appears
+------
+o rm subdir/missingsub.scad
+o Open includemissingsub.scad
+o Compile (F5)
+o Verify that you get: WARNING: Can't open include file 'subdir/missingsub.scad'.
+o echo "module missingsub() { sphere(10); }" > subdir/missingsub.scad
+o rm subdir/missingsub.scad
+o Reload and Compile (F4) - verify that the sphere is gone
+
+Test13: Missing library file appears
+-------
+o rm missing.scad
+o Open usemissing.scad
+o Compile (F5)
+o Verify that you get: WARNING: Can't open 'use' file 'missing.scad'.
+o echo "module missing() { sphere(10); }" > missing.scad
+o rm missing.scad
+o Compile (F5) - verify that the sphere is gone
diff --git a/testdata/modulecache-tests/includemissing.scad b/testdata/modulecache-tests/includemissing.scad
new file mode 100644
index 0000000..d8a165f
--- /dev/null
+++ b/testdata/modulecache-tests/includemissing.scad
@@ -0,0 +1,2 @@
+include <missing.scad>
+missing();
diff --git a/testdata/modulecache-tests/includemissingsub.scad b/testdata/modulecache-tests/includemissingsub.scad
new file mode 100644
index 0000000..50acffe
--- /dev/null
+++ b/testdata/modulecache-tests/includemissingsub.scad
@@ -0,0 +1,2 @@
+include <subdir/missingsub.scad>
+missingsub();
diff --git a/testdata/scad/features/background-modifier.scad b/testdata/scad/features/background-modifier.scad
index 5430472..d67270e 100644
--- a/testdata/scad/features/background-modifier.scad
+++ b/testdata/scad/features/background-modifier.scad
@@ -3,3 +3,8 @@ difference() {
%cylinder(h=30, r=6, center=true);
}
%if (true) cube([25,6,3], center=true);
+
+%translate([0,-9,0]) difference() {
+ color("green") cube([10,4,10], center=true);
+ color("red") translate([0,-2,0]) sphere(3);
+}
diff --git a/testdata/scad/features/highlight-and-background-modifier.scad b/testdata/scad/features/highlight-and-background-modifier.scad
index 5dca703..d97408b 100644
--- a/testdata/scad/features/highlight-and-background-modifier.scad
+++ b/testdata/scad/features/highlight-and-background-modifier.scad
@@ -1,10 +1,31 @@
difference() {
sphere(r=10);
%#cylinder(h=30, r=6, center=true);
- %#if (true) cube([6,25,3], center=true);
+ %#if (true) cube([25,6,3], center=true);
}
-translate([13,0,0]) difference() {
- sphere(r=10);
- #%cylinder(h=30, r=6, center=true);
- #%if (true) cube([6,25,3], center=true);
+%#translate([0,-9,0]) difference() {
+ color("green") cube([10,4,10], center=true);
+ color("red") translate([0,-2,0]) sphere(3);
+}
+%translate([13,0,0]){
+ difference() {
+ sphere(r=10);
+ cylinder(h=30, r=6, center=true);
+ if (true) cube([25,6,3], center=true);
+ }
+ #translate([0,-9,0]) difference() {
+ color("green") cube([10,4,10], center=true);
+ color("red") translate([0,-2,0]) sphere(3);
+ }
+}
+#translate([26,0,0]){
+ difference() {
+ sphere(r=10);
+ cylinder(h=30, r=6, center=true);
+ if (true) cube([25,6,3], center=true);
+ }
+ %translate([0,-9,0]) difference() {
+ color("green") cube([10,4,10], center=true);
+ color("red") translate([0,-2,0]) sphere(3);
+ }
}
diff --git a/testdata/scad/features/highlight-modifier.scad b/testdata/scad/features/highlight-modifier.scad
index f228d08..2141f58 100644
--- a/testdata/scad/features/highlight-modifier.scad
+++ b/testdata/scad/features/highlight-modifier.scad
@@ -3,3 +3,8 @@ difference() {
#cylinder(h=30, r=6, center=true);
}
#if (true) cube([25,6,3], center=true);
+
+#translate([0,-9,0]) difference() {
+ color("green") cube([10,4,10], center=true);
+ color("red") translate([0,-2,0]) sphere(3);
+}
diff --git a/testdata/scad/features/linear_extrude-scale-tests.scad b/testdata/scad/features/linear_extrude-scale-tests.scad
deleted file mode 100644
index 9a82c9d..0000000
--- a/testdata/scad/features/linear_extrude-scale-tests.scad
+++ /dev/null
@@ -1,17 +0,0 @@
-difference() {
- linear_extrude(height=40, scale=[0, 0]) {
- square(10, center=true);
- translate([10,0]) circle(10);
- }
- translate([0,0,35]) sphere(10);
-}
-
-/*
-Test case ideas:
-o off-center starting point
-o Concave polygon
-o Disjoint polygons
-o multi-rotation twist
-o zero scales, zero scales in only one axis (for the above cases)
-o boolean operations on scaled extrusion (including zero scale)
-*/
diff --git a/testdata/scad/features/linear_extrude-scale-zero-tests.scad b/testdata/scad/features/linear_extrude-scale-zero-tests.scad
new file mode 100644
index 0000000..8a85203
--- /dev/null
+++ b/testdata/scad/features/linear_extrude-scale-zero-tests.scad
@@ -0,0 +1,56 @@
+// test cases for linear extrude with scale
+// by TakeItAndRun 2013
+
+// syntax: linear_extrude(height=a, slices=b, twist=c, scale=[x,y])
+
+a=3;
+b=20;
+c=0;
+x=1;
+y=1;
+
+module linear_extrudes_of_different_shapes(a=a,b=b,c=c,x=x,y=y) {
+ translate(00*[4,0,0])
+ // linear_extrude of shape with hole
+ linear_extrude(height=a, slices=b, twist=c, scale=[x,y])
+ difference() {
+ square(2,true); square(1,true);
+ }
+
+ translate(01*[4,0,0])
+ // linear_extrude of disjoint polygons shapes
+ linear_extrude(height=a, slices=b, twist=c, scale=[x,y]) {
+ translate([1,0,0]) square(1,true);
+ translate([-1,0,0]) square(1,true);
+ }
+
+ translate(02*[4,0,0])
+ // linear_extrude with a coplanar face
+ linear_extrude(height=a, slices=b, twist=c, scale=[x,y]) {
+ translate([.5,0,0])square();
+ translate([-.5,0,0])square();
+ }
+
+ translate(03*[4,0,0])
+ // linear_extrude with internal hole and one coplanar edge
+ linear_extrude(height=a, slices=b, twist=c, scale=[x,y])
+ difference() {
+ square(2,true);
+ translate([-0.5,0,0]) square(1,true);
+ }
+}
+
+
+// Test varying parameters
+translate(00*[0,3,0])
+linear_extrudes_of_different_shapes(c=0,x=0,y=y);
+translate(01*[0,3,0])
+linear_extrudes_of_different_shapes(c=0,x=x,y=0);
+translate(02*[0,3,0])
+linear_extrudes_of_different_shapes(c=0,x=0,y=0);
+translate(03*[0,3,0])
+linear_extrudes_of_different_shapes(c=180,x=0,y=y);
+translate(04*[0,3,0])
+linear_extrudes_of_different_shapes(c=180,x=x,y=0);
+translate(05*[0,3,0])
+linear_extrudes_of_different_shapes(c=180,x=0,y=0);
diff --git a/testdata/scad/features/linear_extrude-tests.scad b/testdata/scad/features/linear_extrude-tests.scad
index 67d892f..528eea2 100644
--- a/testdata/scad/features/linear_extrude-tests.scad
+++ b/testdata/scad/features/linear_extrude-tests.scad
@@ -12,4 +12,13 @@ translate([31.5,2.5,0]) linear_extrude(height=10, twist=-45) polygon(points = [[
translate([0,20,0]) linear_extrude(height=20, twist=45, slices=2) square([10,10]);
translate([19,20,0]) linear_extrude(height=20, twist=45, slices=10) square([10,10]);
-translate([-15,0,0]) linear_extrude(5) square([10,10]);
+translate([0,-15,0]) linear_extrude(5) square([10,10]);
+
+// scale given as a scalar
+translate([-25,-10,0]) linear_extrude(height=10, scale=2) square(5, center=true);
+// scale given as a 3-dim vector
+translate([-15,20,0]) linear_extrude(height=20, scale=[4,5,6]) square(10);
+// scale is negative
+translate([-10,5,0]) linear_extrude(height=15, scale=-2) square(10, center=true);
+// scale given as undefined
+translate([-15,-15,0]) linear_extrude(height=10, scale=var_undef) square(10);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 9821d70..da0979c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -252,6 +252,18 @@ endif()
# OpenGL
find_package(OpenGL REQUIRED)
+if (NOT OPENGL_GLU_FOUND)
+ message(STATUS "GLU not found in system paths...searching $ENV{OPENSCAD_LIBRARIES} ")
+ find_library(OPENGL_glu_LIBRARY GLU HINTS $ENV{OPENSCAD_LIBRARIES}/lib)
+ if (NOT OPENGL_glu_LIBRARY)
+ message(FATAL "GLU library not found")
+ endif()
+ set(OPENGL_LIBRARIES ${OPENGL_glu_LIBRARY} ${OPENGL_LIBRARIES})
+ message(STATUS "OpenGL LIBRARIES: ")
+ foreach(GLLIB ${OPENGL_LIBRARIES})
+ message(STATUS " " ${GLLIB})
+ endforeach()
+endif()
# OpenCSG
if (NOT $ENV{OPENCSGDIR} STREQUAL "")
@@ -822,8 +834,6 @@ disable_tests(cgalpngtest_child-background
openscad-cgalpng_child-background
openscad-cgalpng_highlight-and-background-modifier
openscad-cgalpng_testcolornames
- throwntogethertest_child-background
- throwntogethertest_highlight-and-background-modifier
throwntogethertest_testcolornames)
# Test config handling
diff --git a/tests/regression/cgalpngtest/example024-expected.png b/tests/regression/cgalpngtest/example024-expected.png
new file mode 100644
index 0000000..8e69808
--- /dev/null
+++ b/tests/regression/cgalpngtest/example024-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/highlight-modifier-expected.png b/tests/regression/cgalpngtest/highlight-modifier-expected.png
index e220aa1..2fc7678 100644
--- a/tests/regression/cgalpngtest/highlight-modifier-expected.png
+++ b/tests/regression/cgalpngtest/highlight-modifier-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/linear_extrude-scale-zero-tests-expected.png b/tests/regression/cgalpngtest/linear_extrude-scale-zero-tests-expected.png
new file mode 100644
index 0000000..3b1c934
--- /dev/null
+++ b/tests/regression/cgalpngtest/linear_extrude-scale-zero-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png
index 7d3ea2c..c85142e 100644
--- a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png
+++ b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png
Binary files differ
diff --git a/tests/regression/dumptest/background-modifier-expected.txt b/tests/regression/dumptest/background-modifier-expected.txt
index ed769b3..5861bef 100644
--- a/tests/regression/dumptest/background-modifier-expected.txt
+++ b/tests/regression/dumptest/background-modifier-expected.txt
@@ -5,4 +5,16 @@
%group() {
cube(size = [25, 6, 3], center = true);
}
+ %multmatrix([[1, 0, 0, 0], [0, 1, 0, -9], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ color([0, 0.501961, 0, 1]) {
+ cube(size = [10, 4, 10], center = true);
+ }
+ color([1, 0, 0, 1]) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 2, r = 3);
+ }
+ }
+ }
+ }
diff --git a/tests/regression/dumptest/example024-expected.txt b/tests/regression/dumptest/example024-expected.txt
new file mode 100644
index 0000000..e7d6e8b
--- /dev/null
+++ b/tests/regression/dumptest/example024-expected.txt
@@ -0,0 +1,1869 @@
+ difference() {
+ multmatrix([[0.81649658092, 0.40824829046, 0.40824829046, 0], [0, 0.70710678118, -0.70710678118, 0], [-0.57735026919, 0.57735026919, 0.57735026919, 0], [0, 0, 0, 1]]) {
+ group() {
+ difference() {
+ cube(size = [100, 100, 100], center = true);
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 33.3333, 33.3333], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[0, -1, 0, 0], [1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 33.3333, 33.3333], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 33.3333, 33.3333], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -33.33333333333], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, -33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 33.33333333333], [0, 0, 1, 33.33333333333], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 11.1111, 11.1111], center = true);
+ group() {
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group();
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, -11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 11.11111111111], [0, 0, 1, 11.11111111111], [0, 0, 0, 1]]) {
+ group() {
+ cube(size = [110, 3.7037, 3.7037], center = true);
+ group();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -100], [0, 0, 0, 1]]) {
+ cube(size = [200, 200, 200], center = true);
+ }
+ }
+
diff --git a/tests/regression/dumptest/highlight-and-background-modifier-expected.txt b/tests/regression/dumptest/highlight-and-background-modifier-expected.txt
index 20c82cc..eb8931c 100644
--- a/tests/regression/dumptest/highlight-and-background-modifier-expected.txt
+++ b/tests/regression/dumptest/highlight-and-background-modifier-expected.txt
@@ -2,15 +2,60 @@
sphere($fn = 0, $fa = 12, $fs = 2, r = 10);
%cylinder($fn = 0, $fa = 12, $fs = 2, h = 30, r1 = 6, r2 = 6, center = true);
%group() {
- cube(size = [6, 25, 3], center = true);
+ cube(size = [25, 6, 3], center = true);
}
}
- multmatrix([[1, 0, 0, 13], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ %multmatrix([[1, 0, 0, 0], [0, 1, 0, -9], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ color([0, 0.501961, 0, 1]) {
+ cube(size = [10, 4, 10], center = true);
+ }
+ color([1, 0, 0, 1]) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 2, r = 3);
+ }
+ }
+ }
+ }
+ %multmatrix([[1, 0, 0, 13], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ sphere($fn = 0, $fa = 12, $fs = 2, r = 10);
+ cylinder($fn = 0, $fa = 12, $fs = 2, h = 30, r1 = 6, r2 = 6, center = true);
+ group() {
+ cube(size = [25, 6, 3], center = true);
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -9], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ color([0, 0.501961, 0, 1]) {
+ cube(size = [10, 4, 10], center = true);
+ }
+ color([1, 0, 0, 1]) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 2, r = 3);
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 26], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
difference() {
sphere($fn = 0, $fa = 12, $fs = 2, r = 10);
- %cylinder($fn = 0, $fa = 12, $fs = 2, h = 30, r1 = 6, r2 = 6, center = true);
- %group() {
- cube(size = [6, 25, 3], center = true);
+ cylinder($fn = 0, $fa = 12, $fs = 2, h = 30, r1 = 6, r2 = 6, center = true);
+ group() {
+ cube(size = [25, 6, 3], center = true);
+ }
+ }
+ %multmatrix([[1, 0, 0, 0], [0, 1, 0, -9], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ color([0, 0.501961, 0, 1]) {
+ cube(size = [10, 4, 10], center = true);
+ }
+ color([1, 0, 0, 1]) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 2, r = 3);
+ }
+ }
}
}
}
diff --git a/tests/regression/dumptest/highlight-modifier-expected.txt b/tests/regression/dumptest/highlight-modifier-expected.txt
index c6204bd..c0a29ad 100644
--- a/tests/regression/dumptest/highlight-modifier-expected.txt
+++ b/tests/regression/dumptest/highlight-modifier-expected.txt
@@ -5,4 +5,16 @@
group() {
cube(size = [25, 6, 3], center = true);
}
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -9], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ color([0, 0.501961, 0, 1]) {
+ cube(size = [10, 4, 10], center = true);
+ }
+ color([1, 0, 0, 1]) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 2, r = 3);
+ }
+ }
+ }
+ }
diff --git a/tests/regression/dumptest/linear_extrude-scale-zero-tests-expected.txt b/tests/regression/dumptest/linear_extrude-scale-zero-tests-expected.txt
new file mode 100644
index 0000000..950c724
--- /dev/null
+++ b/tests/regression/dumptest/linear_extrude-scale-zero-tests-expected.txt
@@ -0,0 +1,253 @@
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 3], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 6], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 0, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 9], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 1], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [1, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ multmatrix([[1, 0, 0, -1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 8], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 3, center = false, convexity = 1, twist = 180, slices = 20, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ difference() {
+ square(size = [2, 2], center = true);
+ multmatrix([[1, 0, 0, -0.5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [1, 1], center = true);
+ }
+ }
+ }
+ }
+ }
+ }
+
diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.txt b/tests/regression/dumptest/linear_extrude-tests-expected.txt
index c031ed8..c867388 100644
--- a/tests/regression/dumptest/linear_extrude-tests-expected.txt
+++ b/tests/regression/dumptest/linear_extrude-tests-expected.txt
@@ -29,9 +29,29 @@
square(size = [10, 10], center = false);
}
}
- multmatrix([[1, 0, 0, -15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -15], [0, 0, 1, 0], [0, 0, 0, 1]]) {
linear_extrude(height = 5, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) {
square(size = [10, 10], center = false);
}
}
+ multmatrix([[1, 0, 0, -25], [0, 1, 0, -10], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 10, center = false, convexity = 1, scale = [2, 2], $fn = 0, $fa = 12, $fs = 2) {
+ square(size = [5, 5], center = true);
+ }
+ }
+ multmatrix([[1, 0, 0, -15], [0, 1, 0, 20], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 20, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) {
+ square(size = [10, 10], center = false);
+ }
+ }
+ multmatrix([[1, 0, 0, -10], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 15, center = false, convexity = 1, scale = [0, 0], $fn = 0, $fa = 12, $fs = 2) {
+ square(size = [10, 10], center = true);
+ }
+ }
+ multmatrix([[1, 0, 0, -15], [0, 1, 0, -15], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(height = 10, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) {
+ square(size = [10, 10], center = false);
+ }
+ }
diff --git a/tests/regression/opencsgtest/background-modifier-expected.png b/tests/regression/opencsgtest/background-modifier-expected.png
index 2505331..9cf7db0 100644
--- a/tests/regression/opencsgtest/background-modifier-expected.png
+++ b/tests/regression/opencsgtest/background-modifier-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/difference-tests-expected.png b/tests/regression/opencsgtest/difference-tests-expected.png
index a6d863a..8db2742 100644
--- a/tests/regression/opencsgtest/difference-tests-expected.png
+++ b/tests/regression/opencsgtest/difference-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/example024-expected.png b/tests/regression/opencsgtest/example024-expected.png
new file mode 100644
index 0000000..dfbe847
--- /dev/null
+++ b/tests/regression/opencsgtest/example024-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/highlight-and-background-modifier-expected.png b/tests/regression/opencsgtest/highlight-and-background-modifier-expected.png
index 8febe76..c1c7313 100644
--- a/tests/regression/opencsgtest/highlight-and-background-modifier-expected.png
+++ b/tests/regression/opencsgtest/highlight-and-background-modifier-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/highlight-modifier-expected.png b/tests/regression/opencsgtest/highlight-modifier-expected.png
index af01e5b..1021c22 100644
--- a/tests/regression/opencsgtest/highlight-modifier-expected.png
+++ b/tests/regression/opencsgtest/highlight-modifier-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/linear_extrude-scale-zero-tests-expected.png b/tests/regression/opencsgtest/linear_extrude-scale-zero-tests-expected.png
new file mode 100644
index 0000000..22e94ad
--- /dev/null
+++ b/tests/regression/opencsgtest/linear_extrude-scale-zero-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/linear_extrude-tests-expected.png b/tests/regression/opencsgtest/linear_extrude-tests-expected.png
index b929d09..cbbdc11 100644
--- a/tests/regression/opencsgtest/linear_extrude-tests-expected.png
+++ b/tests/regression/opencsgtest/linear_extrude-tests-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/background-modifier-expected.png b/tests/regression/throwntogethertest/background-modifier-expected.png
index 2505331..499b92f 100644
--- a/tests/regression/throwntogethertest/background-modifier-expected.png
+++ b/tests/regression/throwntogethertest/background-modifier-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/child-background-expected.png b/tests/regression/throwntogethertest/child-background-expected.png
new file mode 100644
index 0000000..7540ee6
--- /dev/null
+++ b/tests/regression/throwntogethertest/child-background-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/difference-tests-expected.png b/tests/regression/throwntogethertest/difference-tests-expected.png
index 0a27c90..7a61f42 100644
--- a/tests/regression/throwntogethertest/difference-tests-expected.png
+++ b/tests/regression/throwntogethertest/difference-tests-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/example024-expected.png b/tests/regression/throwntogethertest/example024-expected.png
new file mode 100644
index 0000000..ffa2360
--- /dev/null
+++ b/tests/regression/throwntogethertest/example024-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/highlight-and-background-modifier-expected.png b/tests/regression/throwntogethertest/highlight-and-background-modifier-expected.png
new file mode 100644
index 0000000..e95f763
--- /dev/null
+++ b/tests/regression/throwntogethertest/highlight-and-background-modifier-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/highlight-modifier-expected.png b/tests/regression/throwntogethertest/highlight-modifier-expected.png
index 7973d82..e8d4e62 100644
--- a/tests/regression/throwntogethertest/highlight-modifier-expected.png
+++ b/tests/regression/throwntogethertest/highlight-modifier-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/linear_extrude-scale-zero-tests-expected.png b/tests/regression/throwntogethertest/linear_extrude-scale-zero-tests-expected.png
new file mode 100644
index 0000000..22e94ad
--- /dev/null
+++ b/tests/regression/throwntogethertest/linear_extrude-scale-zero-tests-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png
index fddeeb8..cbbdc11 100644
--- a/tests/regression/throwntogethertest/linear_extrude-tests-expected.png
+++ b/tests/regression/throwntogethertest/linear_extrude-tests-expected.png
Binary files differ
contact: Jan Huwald // Impressum