|
@ -4,6 +4,10 @@ OpenSCAD 2012.XX
|
||||||
Features:
|
Features:
|
||||||
o Snappier GUI while performing CGAL computations (computations running in separate thread)
|
o Snappier GUI while performing CGAL computations (computations running in separate thread)
|
||||||
|
|
||||||
|
Deprecations:
|
||||||
|
o The old include syntax "<filename.scad>" without the include keyword is no
|
||||||
|
longer supported and will cause a syntax error.
|
||||||
|
|
||||||
OpenSCAD 2011.12
|
OpenSCAD 2011.12
|
||||||
================
|
================
|
||||||
|
|
||||||
|
@ -19,6 +23,7 @@ o New import() statement reads the correct file format based on the filename ext
|
||||||
(.stl, .dxf and .off is supported)
|
(.stl, .dxf and .off is supported)
|
||||||
o The color() statement now supports an alpha parameter, e.g. color(c=[1,0,0], alpha=0.4)
|
o The color() statement now supports an alpha parameter, e.g. color(c=[1,0,0], alpha=0.4)
|
||||||
o The color() statement now supports specifying colors as strings, e.g. color("Red")
|
o The color() statement now supports specifying colors as strings, e.g. color("Red")
|
||||||
|
o The color() statement now overrides colors specified further down in the tree
|
||||||
o if()/else() and the ternary operator can now take any value type as parameter. false, 0, empty string and empty vector or illegal value type will evaluate as false, everything else as true.
|
o if()/else() and the ternary operator can now take any value type as parameter. false, 0, empty string and empty vector or illegal value type will evaluate as false, everything else as true.
|
||||||
o Strings can now be lexographically compared using the <, <=, >, >= operators
|
o Strings can now be lexographically compared using the <, <=, >, >= operators
|
||||||
o Added PI constant.
|
o Added PI constant.
|
||||||
|
|
|
@ -22,6 +22,10 @@ unix:freebsd-g++ {
|
||||||
QMAKE_YACC = /usr/local/bin/bison
|
QMAKE_YACC = /usr/local/bin/bison
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unix:netbsd* {
|
||||||
|
QMAKE_YACC = /usr/pkg/bin/bison
|
||||||
|
}
|
||||||
|
|
||||||
unix:linux* {
|
unix:linux* {
|
||||||
exists(/usr/bin/bison) {
|
exists(/usr/bin/bison) {
|
||||||
QMAKE_YACC = /usr/bin/bison
|
QMAKE_YACC = /usr/bin/bison
|
||||||
|
|
68
boost.pri
|
@ -6,35 +6,65 @@ boost {
|
||||||
!isEmpty(BOOST_DIR) {
|
!isEmpty(BOOST_DIR) {
|
||||||
QMAKE_INCDIR += $$BOOST_DIR
|
QMAKE_INCDIR += $$BOOST_DIR
|
||||||
message("boost location: $$BOOST_DIR")
|
message("boost location: $$BOOST_DIR")
|
||||||
win32:QMAKE_LIBDIR += -L$$BOOST_DIR/lib
|
win32: QMAKE_LIBDIR += -L$$BOOST_DIR/lib
|
||||||
}
|
}
|
||||||
|
|
||||||
win32:!CONFIG(mingw-cross-env) {
|
|
||||||
LIBS += -llibboost_thread-vc90-mt-s-1_46_1 -llibboost_program_options-vc90-mt-s-1_46_1
|
|
||||||
}
|
|
||||||
|
|
||||||
CONFIG(mingw-cross-env) {
|
CONFIG(mingw-cross-env) {
|
||||||
DEFINES += BOOST_STATIC
|
DEFINES += BOOST_STATIC
|
||||||
DEFINES += BOOST_THREAD_USE_LIB
|
DEFINES += BOOST_THREAD_USE_LIB
|
||||||
DEFINES += Boost_USE_STATIC_LIBS
|
DEFINES += Boost_USE_STATIC_LIBS
|
||||||
LIBS += -lboost_thread_win32-mt -lboost_program_options-mt
|
BOOST_LINK_FLAGS = -lboost_thread_win32-mt -lboost_program_options-mt
|
||||||
}
|
}
|
||||||
|
|
||||||
unix {
|
isEmpty(BOOST_LINK_FLAGS):win32 {
|
||||||
BMT_TEST1 = /usr/lib64/libboost*thread-mt*
|
BOOST_LINK_FLAGS = -llibboost_thread-vc90-mt-s-1_46_1 -llibboost_program_options-vc90-mt-s-1_46_1
|
||||||
BMT_TEST2 = /usr/lib/libboost*thread-mt*
|
}
|
||||||
BMT_TEST3 = $$BOOST_DIR/lib/libboost*thread-mt*
|
|
||||||
|
|
||||||
exists($$BMT_TEST1)|exists($$BMT_TEST2)|exists($$BMT_TEST3) {
|
# check for OPENSCAD_LIBDIR + multithread
|
||||||
LIBS += -lboost_thread-mt -lboost_program_options-mt
|
isEmpty(BOOST_LINK_FLAGS) {
|
||||||
BOOST_IS_MT = true
|
OPENSCAD_LIBDIR = $$(OPENSCAD_LIBRARIES)
|
||||||
}
|
!isEmpty(OPENSCAD_LIBDIR) {
|
||||||
}
|
exists($$OPENSCAD_LIBDIR/lib/libboost*thread-mt*) {
|
||||||
|
BOOST_LINK_FLAGS = -lboost_thread-mt -lboost_program_options-mt
|
||||||
unix|macx {
|
} else {
|
||||||
isEmpty(BOOST_IS_MT) {
|
exists($$OPENSCAD_LIBDIR/lib/libboost*thread*) {
|
||||||
LIBS += -lboost_thread -lboost_program_options
|
BOOST_LINK_FLAGS = -lboost_thread -lboost_program_options
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check for BOOSTDIR + multithread
|
||||||
|
isEmpty(BOOST_LINK_FLAGS) {
|
||||||
|
BOOST_DIR = $$(BOOSTDIR)
|
||||||
|
!isEmpty(BOOST_DIR) {
|
||||||
|
exists($$BOOST_DIR/lib/libboost*thread-mt*) {
|
||||||
|
BOOST_LINK_FLAGS = -lboost_thread-mt -lboost_program_options-mt
|
||||||
|
} else {
|
||||||
|
exists($$BOOST_DIR/lib/libboost*thread*) {
|
||||||
|
BOOST_LINK_FLAGS = -lboost_thread -lboost_program_options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty(BOOST_LINK_FLAGS) {
|
||||||
|
unix {
|
||||||
|
BMT_TEST1 = /usr/lib64/libboost*thread-mt*
|
||||||
|
BMT_TEST2 = /usr/lib/libboost*thread-mt*
|
||||||
|
BMT_TEST3 = /usr/pkg/lib/libboost*thread-mt* # netbsd
|
||||||
|
exists($$BMT_TEST1)|exists($$BMT_TEST2)|exists($$BMT_TEST3) {
|
||||||
|
BOOST_LINK_FLAGS = -lboost_thread-mt -lboost_program_options-mt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty(BOOST_LINK_FLAGS) {
|
||||||
|
unix|macx {
|
||||||
|
BOOST_LINK_FLAGS = -lboost_thread -lboost_program_options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBS += $$BOOST_LINK_FLAGS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,7 +255,6 @@ o variants of module transparent() { %child(); }
|
||||||
o define modules
|
o define modules
|
||||||
o define functions
|
o define functions
|
||||||
o built-in variables and constants (builtin-tests.scad)
|
o built-in variables and constants (builtin-tests.scad)
|
||||||
o Write a regression test for the hexagonal cylinder orientation issue
|
|
||||||
o Caching
|
o Caching
|
||||||
- Test that caching is actually performed (speedup + same results)
|
- Test that caching is actually performed (speedup + same results)
|
||||||
- Test the modifier characters correctly influence the cache (also when
|
- Test the modifier characters correctly influence the cache (also when
|
||||||
|
|
|
@ -2,8 +2,8 @@ OpenSCAD Release Checklist
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
o Update version
|
o Update version
|
||||||
release-linux.sh
|
scripts/release-linux.sh
|
||||||
publish-macosx.sh
|
scripts/publish-macosx.sh
|
||||||
FIXME: Windows
|
FIXME: Windows
|
||||||
|
|
||||||
o Update RELEASE_NOTES
|
o Update RELEASE_NOTES
|
||||||
|
@ -12,7 +12,7 @@ o Tag release
|
||||||
git tag "openscad-2011.12"
|
git tag "openscad-2011.12"
|
||||||
|
|
||||||
o build source package
|
o build source package
|
||||||
git archive --format=tar openscad-2011.12 --prefix=openscad-2011.12/ | gzip > openscad-2011.12.src.tar.gz
|
scripts/git-archive-all.py --prefix=openscad-2011.12/ openscad-2011.12.src.tar.gz
|
||||||
|
|
||||||
o build binaries
|
o build binaries
|
||||||
tar xzf openscad-2011.12.src.tar.gz
|
tar xzf openscad-2011.12.src.tar.gz
|
||||||
|
|
|
@ -10,7 +10,7 @@ $ cd tests
|
||||||
$ cmake .
|
$ cmake .
|
||||||
$ make
|
$ make
|
||||||
|
|
||||||
Windows:
|
Windows + MSVC:
|
||||||
|
|
||||||
First, get a normal build working by following instructions at
|
First, get a normal build working by following instructions at
|
||||||
http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Building_on_Windows
|
http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Building_on_Windows
|
||||||
|
@ -22,6 +22,10 @@ Then, from the QT command prompt:
|
||||||
> cmake .
|
> cmake .
|
||||||
> nmake -f Makefile
|
> nmake -f Makefile
|
||||||
|
|
||||||
|
Cross compiling Linux->Win32:
|
||||||
|
|
||||||
|
Please see openscad/tests/CMingw-cross-env.cmake for instructions.
|
||||||
|
|
||||||
B) Running tests
|
B) Running tests
|
||||||
|
|
||||||
$ ctest Runs tests enabled by default
|
$ ctest Runs tests enabled by default
|
||||||
|
@ -50,55 +54,53 @@ Adding a new regression test:
|
||||||
Troubleshooting:
|
Troubleshooting:
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
0. Headless unix servers (no X11)
|
0. Headless unix servers
|
||||||
|
|
||||||
$ Xvfb :5 -screen 0 800x600x24 &
|
If you are attempting to run the tests on a unix-like system but only
|
||||||
|
have shell-console access, you may be able to run the tests by using a
|
||||||
|
virtual framebuffer program like Xvnc or Xvfb. For example:
|
||||||
|
|
||||||
|
$ Xvfb :5 -screen 0 800x600x24 &
|
||||||
$ DISPLAY=:5 ctest
|
$ DISPLAY=:5 ctest
|
||||||
|
|
||||||
1. Trouble finding libraries
|
Some versions of Xvfb may fail, however.
|
||||||
|
|
||||||
|
1. Trouble finding libraries on unix
|
||||||
|
|
||||||
To help CMAKE find eigen2, OpenCSG, CGAL, Boost, and GLEW, you can use
|
To help CMAKE find eigen2, OpenCSG, CGAL, Boost, and GLEW, you can use
|
||||||
environment variables, just like for the main qmake & openscad.pro. Examples:
|
environment variables, just like for the main qmake & openscad.pro. Examples:
|
||||||
|
|
||||||
OPENCSGDIR=~/OpenCSG-1.3.2 EIGEN2DIR=~/eigen2 cmake .
|
OPENSCAD_LIBRARIES=~ cmake .
|
||||||
|
CGALDIR=~/CGAL-3.9 BOOSTDIR=~/boost-1.47.0 cmake .
|
||||||
|
|
||||||
Valid variables are as follows (see CMakeLists.txt for more info):
|
Valid variables are as follows:
|
||||||
|
|
||||||
BOOSTDIR, CGALDIR, EIGEN2DIR, GLEWDIR, OPENCSGDIR, OPENSCAD_LIBRARIES
|
BOOSTDIR, CGALDIR, EIGEN2DIR, GLEWDIR, OPENCSGDIR, OPENSCAD_LIBRARIES
|
||||||
|
|
||||||
2. Logs
|
2. Location of logs
|
||||||
|
|
||||||
Logs of test runs are found in tests/build/Testing/Temporary
|
Logs of test runs are found in tests/build/Testing/Temporary
|
||||||
Pretty-printed index.html is in a subdir of tests/build/Testing/Temporary
|
A pretty-printed index.html is in a subdir of tests/build/Testing/Temporary
|
||||||
Expected results are found in tests/regression/*
|
Expected results are found in tests/regression/*
|
||||||
Actual results are found in tests/build/testname-output/*
|
Actual results are found in tests/build/testname-output/*
|
||||||
|
|
||||||
3. Cross-compiling
|
3. Image-based tests takes a long time, they fail, and the log says 'return -11'
|
||||||
|
|
||||||
Cross-compiling of tests has not been automated nor tested
|
Imagemagick may have crashed while comparing the expected images to the
|
||||||
|
test-run generated (actual) images. You can try using the alternate
|
||||||
|
ImageMagick comparison method by by erasing CMakeCache, and re-running
|
||||||
|
cmake with -DCOMPARATOR=ncc. This will enable the Normalized Cross
|
||||||
|
Comparison method.
|
||||||
|
|
||||||
4. Image-based tests takes a long time, they fail, and it says 'return -11'
|
4. Testing images fails with 'morphology not found" for ImageMagick in the log
|
||||||
|
|
||||||
Imagemagick may have crashed. You can try using the alternate IM comparator
|
|
||||||
based on Normalized Cross Correlation. Pass -DCOMPARATOR=ncc to cmake
|
|
||||||
|
|
||||||
5. Testing images fails with 'morphology' not found for ImageMagick
|
|
||||||
|
|
||||||
Your version of imagemagick is old. Upgrade, or pass -DCOMPARATOR=old to
|
Your version of imagemagick is old. Upgrade, or pass -DCOMPARATOR=old to
|
||||||
cmake. The comparison will be of lowered reliability.
|
cmake. The comparison will be of lowered reliability.
|
||||||
|
|
||||||
6. Unexplained or bizarre errors.
|
5. Other issues
|
||||||
|
|
||||||
This can happen on dynamic-library systems (linux) where you try to use
|
The OpenSCAD User Manual has a section on buildling. Please check there
|
||||||
your own version of a library while the system still has another version
|
for updates:
|
||||||
under the system paths. You can diagnose this by looking at your cmake
|
|
||||||
log as well as your sysinfo.txt file, as well as running 'ldd' against
|
|
||||||
your binaries, to make sure that the proper versions of libraries are
|
|
||||||
getting compiled and linked with the test binaries.
|
|
||||||
|
|
||||||
7. Other issues
|
|
||||||
|
|
||||||
The OpenSCAD User Manual has a section on buildling. Check there for updates:
|
|
||||||
|
|
||||||
http://en.wikibooks.org/wiki/OpenSCAD_User_Manual
|
http://en.wikibooks.org/wiki/OpenSCAD_User_Manual
|
||||||
|
|
||||||
|
|
39
eigen2.pri
|
@ -1,20 +1,37 @@
|
||||||
eigen2 {
|
eigen2 {
|
||||||
|
|
||||||
|
CONFIG(mingw-cross-env) {
|
||||||
|
EIGEN2_INCLUDEPATH = mingw-cross-env/include/eigen2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optionally specify location of Eigen2 using the
|
||||||
|
# OPENSCAD_LIBRARIES env. variable
|
||||||
|
isEmpty(EIGEN2_INCLUDEPATH) {
|
||||||
|
OPENSCAD_LIBRARIES_DIR = $$(OPENSCAD_LIBRARIES)
|
||||||
|
!isEmpty(OPENSCAD_LIBRARIES_DIR) {
|
||||||
|
exists($$OPENSCAD_LIBRARIES_DIR/include/eigen2) {
|
||||||
|
EIGEN2_INCLUDEPATH = $$OPENSCAD_LIBRARIES_DIR/include/eigen2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Optionally specify location of Eigen2 using the
|
# Optionally specify location of Eigen2 using the
|
||||||
# EIGEN2DIR env. variable
|
# EIGEN2DIR env. variable
|
||||||
EIGEN2_DIR = $$(EIGEN2DIR)
|
isEmpty(EIGEN2_INCLUDEPATH) {
|
||||||
!isEmpty(EIGEN2_DIR) {
|
EIGEN2_DIR = $$(EIGEN2DIR)
|
||||||
EIGEN2_INCLUDEPATH = $$EIGEN2_DIR
|
!isEmpty(EIGEN2_DIR) {
|
||||||
}
|
EIGEN2_INCLUDEPATH = $$EIGEN2_DIR
|
||||||
else {
|
message("EIGEN2 location: $$EIGEN2_INCLUDEPATH")
|
||||||
CONFIG(mingw-cross-env) {
|
|
||||||
EIGEN2_INCLUDEPATH = mingw-cross-env/include/eigen2
|
|
||||||
} else {
|
|
||||||
freebsd-g++: EIGEN2_INCLUDEPATH *= /usr/local/include/eigen2
|
|
||||||
macx: EIGEN2_INCLUDEPATH *= /opt/local/include/eigen2
|
|
||||||
!macx:!freebsd-g++:!win32:EIGEN2_INCLUDEPATH *= /usr/include/eigen2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEmpty(EIGEN2_INCLUDEPATH) {
|
||||||
|
freebsd-g++: EIGEN2_INCLUDEPATH = /usr/local/include/eigen2
|
||||||
|
macx: EIGEN2_INCLUDEPATH = /opt/local/include/eigen2
|
||||||
|
linux*: EIGEN2_INCLUDEPATH = /usr/include/eigen2
|
||||||
|
netbsd*: EIGEN2_INCLUDEPATH = /usr/pkg/include/eigen2
|
||||||
|
}
|
||||||
|
|
||||||
# eigen2 being under 'include/eigen2' needs special prepending
|
# eigen2 being under 'include/eigen2' needs special prepending
|
||||||
QMAKE_INCDIR_QT = $$EIGEN2_INCLUDEPATH $$QMAKE_INCDIR_QT
|
QMAKE_INCDIR_QT = $$EIGEN2_INCLUDEPATH $$QMAKE_INCDIR_QT
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,13 @@ difference()
|
||||||
|
|
||||||
intersection()
|
intersection()
|
||||||
{
|
{
|
||||||
translate([ -125, -25, -25])
|
translate([ -125, -25, -26])
|
||||||
linear_extrude(height = 50, convexity = 1)
|
linear_extrude(height = 52, convexity = 1)
|
||||||
import(file = "example008.dxf", layer = "X");
|
import(file = "example008.dxf", layer = "X");
|
||||||
|
|
||||||
rotate(90, [0, 1, 0])
|
rotate(90, [0, 1, 0])
|
||||||
translate([ -125, -25, -25])
|
translate([ -125, -25, -26])
|
||||||
linear_extrude(height = 50, convexity = 1)
|
linear_extrude(height = 52, convexity = 1)
|
||||||
import(file = "example008.dxf", layer = "X");
|
import(file = "example008.dxf", layer = "X");
|
||||||
}
|
}
|
||||||
}
|
}
|
4
flex.pri
|
@ -13,6 +13,10 @@ unix:freebsd-g++ {
|
||||||
QMAKE_LEX = /usr/local/bin/flex
|
QMAKE_LEX = /usr/local/bin/flex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unix:netbsd* {
|
||||||
|
QMAKE_LEX = /usr/pkg/bin/flex
|
||||||
|
}
|
||||||
|
|
||||||
unix:linux* {
|
unix:linux* {
|
||||||
exists(/usr/bin/flex) {
|
exists(/usr/bin/flex) {
|
||||||
QMAKE_LEX = /usr/bin/flex
|
QMAKE_LEX = /usr/bin/flex
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b7d9ec4c5e5939b2bffcda60b91f4623e9b3c625
|
Subproject commit f32906ae90b1326a2d7241994e18c6f796799a95
|
11
openscad.pro
|
@ -86,6 +86,15 @@ linux*:exists(/usr/lib64/libGLU*)|linux*:exists(/usr/lib/libGLU*) {
|
||||||
LIBS += -lGLU
|
LIBS += -lGLU
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netbsd* {
|
||||||
|
LIBS += -L/usr/X11R7/lib
|
||||||
|
QMAKE_LFLAGS += -Wl,-R/usr/X11R7/lib
|
||||||
|
QMAKE_LFLAGS += -Wl,-R/usr/pkg/lib
|
||||||
|
!isEmpty(OPENSCAD_LIBDIR) {
|
||||||
|
QMAKE_LFLAGS += -Wl,-R$$OPENSCAD_LIBDIR/lib
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs.
|
# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs.
|
||||||
*g++* {
|
*g++* {
|
||||||
QMAKE_CXXFLAGS *= -fno-strict-aliasing
|
QMAKE_CXXFLAGS *= -fno-strict-aliasing
|
||||||
|
@ -146,6 +155,7 @@ HEADERS += src/renderer.h \
|
||||||
src/builtin.h \
|
src/builtin.h \
|
||||||
src/context.h \
|
src/context.h \
|
||||||
src/csgterm.h \
|
src/csgterm.h \
|
||||||
|
src/csgtermnormalizer.h \
|
||||||
src/dxfdata.h \
|
src/dxfdata.h \
|
||||||
src/dxfdim.h \
|
src/dxfdim.h \
|
||||||
src/dxftess.h \
|
src/dxftess.h \
|
||||||
|
@ -197,6 +207,7 @@ SOURCES += src/mathc99.cc \
|
||||||
src/node.cc \
|
src/node.cc \
|
||||||
src/context.cc \
|
src/context.cc \
|
||||||
src/csgterm.cc \
|
src/csgterm.cc \
|
||||||
|
src/csgtermnormalizer.cc \
|
||||||
src/polyset.cc \
|
src/polyset.cc \
|
||||||
src/csgops.cc \
|
src/csgops.cc \
|
||||||
src/transform.cc \
|
src/transform.cc \
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
diff --git a/example/example.pro b/example/example.pro
|
||||||
|
index 8891a28..5cb5e81 100644
|
||||||
|
--- a/example/example.pro
|
||||||
|
+++ b/example/example.pro
|
||||||
|
@@ -2,9 +2,16 @@ TEMPLATE = app
|
||||||
|
TARGET = opencsgexample
|
||||||
|
|
||||||
|
CONFIG += opengl warn_on release
|
||||||
|
-INCLUDEPATH += ../glew/include ../include
|
||||||
|
-
|
||||||
|
-LIBS += -L../lib -lopencsg -lglut -L../glew/lib -lGLEW
|
||||||
|
+INCLUDEPATH += ../include
|
||||||
|
+LIBS += -L../lib -lopencsg -lGLEW
|
||||||
|
+macx {
|
||||||
|
+ INCLUDEPATH += /opt/local/include
|
||||||
|
+ LIBS += -framework GLUT -L/opt/local/lib
|
||||||
|
+}
|
||||||
|
+else {
|
||||||
|
+ INCLUDEPATH += ../glew/include
|
||||||
|
+ LIBS += -lglut -L../glew/lib
|
||||||
|
+}
|
||||||
|
|
||||||
|
HEADERS = displaylistPrimitive.h
|
||||||
|
SOURCES = displaylistPrimitive.cpp main.cpp
|
||||||
|
diff --git a/opencsg.pro b/opencsg.pro
|
||||||
|
index b56e622..5cf2d6d 100644
|
||||||
|
--- a/opencsg.pro
|
||||||
|
+++ b/opencsg.pro
|
||||||
|
@@ -1,2 +1,2 @@
|
||||||
|
TEMPLATE = subdirs
|
||||||
|
-SUBDIRS = src example
|
||||||
|
+SUBDIRS = src
|
||||||
|
diff --git a/src/src.pro b/src/src.pro
|
||||||
|
index 4843a12..04d3f4d 100644
|
||||||
|
--- a/src/src.pro
|
||||||
|
+++ b/src/src.pro
|
||||||
|
@@ -1,10 +1,31 @@
|
||||||
|
TEMPLATE = lib
|
||||||
|
TARGET = opencsg
|
||||||
|
VERSION = 1.3.2
|
||||||
|
-DESTDIR = ../lib
|
||||||
|
|
||||||
|
CONFIG += opengl warn_on release
|
||||||
|
-INCLUDEPATH += ../include ../glew/include ../
|
||||||
|
+INCLUDEPATH += ../include ../
|
||||||
|
+
|
||||||
|
+# Optionally specify deployment location using the
|
||||||
|
+# MACOSX_DEPLOY_DIR env. variable
|
||||||
|
+DEPLOYDIR = $$(MACOSX_DEPLOY_DIR)
|
||||||
|
+
|
||||||
|
+!isEmpty(DEPLOYDIR) {
|
||||||
|
+ message("Deploy")
|
||||||
|
+ INSTALLDIR = $$(MACOSX_DEPLOY_DIR)
|
||||||
|
+ INCLUDEPATH += $$(MACOSX_DEPLOY_DIR)/include
|
||||||
|
+ LIBS += -L$$(MACOSX_DEPLOY_DIR)/lib -lGLEW
|
||||||
|
+ CONFIG += absolute_library_soname
|
||||||
|
+ headers.files = ../include/opencsg.h
|
||||||
|
+ headers.path = $$INSTALLDIR/include
|
||||||
|
+ INSTALLS += target headers
|
||||||
|
+ target.path = $$INSTALLDIR/lib
|
||||||
|
+}
|
||||||
|
+else {
|
||||||
|
+ DESTDIR = ../lib
|
||||||
|
+ INCLUDEPATH += ../glew/include
|
||||||
|
+ INSTALLS += target
|
||||||
|
+ target.path = $$DESTDIR
|
||||||
|
+}
|
||||||
|
|
||||||
|
HEADERS = ../include/opencsg.h \
|
||||||
|
opencsgConfig.h \
|
|
@ -0,0 +1,171 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from os import path, chdir
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from sys import argv, stdout
|
||||||
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
|
|
||||||
|
class GitArchiver(object):
|
||||||
|
"""
|
||||||
|
GitArchiver
|
||||||
|
|
||||||
|
Scan a git repository and export all tracked files, and submodules.
|
||||||
|
Checks for .gitattributes files in each directory and uses 'export-ignore'
|
||||||
|
pattern entries for ignore files in the archive.
|
||||||
|
|
||||||
|
Automatically detects output format extension: zip, tar, bz2, or gz
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, prefix='', verbose=False, exclude=True, extra=[]):
|
||||||
|
self.prefix = prefix
|
||||||
|
self.verbose = verbose
|
||||||
|
self.exclude = exclude
|
||||||
|
self.extra = extra
|
||||||
|
|
||||||
|
self._excludes = []
|
||||||
|
|
||||||
|
|
||||||
|
def create(self, output_file):
|
||||||
|
"""
|
||||||
|
create(str output_file) -> None
|
||||||
|
|
||||||
|
Creates the archive, written to the given output_file
|
||||||
|
Filetype may be one of: gz, zip, bz2, tar
|
||||||
|
"""
|
||||||
|
#
|
||||||
|
# determine the format
|
||||||
|
#
|
||||||
|
_, _, format = output_file.rpartition(".")
|
||||||
|
|
||||||
|
if format.lower() == 'zip':
|
||||||
|
from zipfile import ZipFile, ZIP_DEFLATED
|
||||||
|
output_archive = ZipFile(path.abspath(output_file), 'w')
|
||||||
|
add = lambda name, arcname: output_archive.write(name, self.prefix + arcname, ZIP_DEFLATED)
|
||||||
|
|
||||||
|
elif format.lower() in ['tar', 'bz2', 'gz']:
|
||||||
|
import tarfile
|
||||||
|
t_mode = ('w:%s' % format) if format != 'tar' else 'w'
|
||||||
|
|
||||||
|
output_archive = tarfile.open(path.abspath(output_file), t_mode)
|
||||||
|
add = lambda name, arcname: output_archive.add(name, self.prefix + arcname)
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Unknown format: '%s'" % format)
|
||||||
|
|
||||||
|
#
|
||||||
|
# compress
|
||||||
|
#
|
||||||
|
|
||||||
|
# extra files first (we may change folder later)
|
||||||
|
for name in self.extra:
|
||||||
|
if self.verbose:
|
||||||
|
toPath = '=> %s%s' % (self.prefix, name) if self.prefix else ""
|
||||||
|
print 'Compressing %s %s ...' % (name, toPath)
|
||||||
|
add(name, name)
|
||||||
|
|
||||||
|
self._excludes = []
|
||||||
|
|
||||||
|
for name, arcname in self.listFiles(path.abspath('')):
|
||||||
|
if self.verbose:
|
||||||
|
toPath = '=> %s%s' % (self.prefix, arcname) if self.prefix else ""
|
||||||
|
print 'Compressing %s %s ...' % (arcname, toPath)
|
||||||
|
add(name, arcname)
|
||||||
|
|
||||||
|
output_archive.close()
|
||||||
|
|
||||||
|
|
||||||
|
def listFiles(self, git_repositary_path, baselevel=''):
|
||||||
|
"""
|
||||||
|
listFiles(str git_repository_path, str baselevel='') -> iterator
|
||||||
|
|
||||||
|
An iterator method that yields a tuple(filepath, fullpath)
|
||||||
|
for each file that should be included in the archive.
|
||||||
|
Skips those that match the exclusion patterns found in
|
||||||
|
any discovered .gitattributes files along the way.
|
||||||
|
|
||||||
|
Recurses into submodules as well.
|
||||||
|
"""
|
||||||
|
for filepath in self.runShell('git ls-files --cached --full-name --no-empty-directory'):
|
||||||
|
fullpath = path.join(baselevel, filepath)
|
||||||
|
filename = path.basename(filepath)
|
||||||
|
|
||||||
|
if self.exclude and filename == '.gitattributes':
|
||||||
|
self._excludes = []
|
||||||
|
fh = open(filepath, 'r')
|
||||||
|
for line in fh:
|
||||||
|
if not line: break
|
||||||
|
tokens = line.strip().split()
|
||||||
|
if 'export-ignore' in tokens[1:]:
|
||||||
|
self._excludes.append(tokens[0])
|
||||||
|
fh.close()
|
||||||
|
|
||||||
|
if not filename.startswith('.git') and not path.isdir(filepath):
|
||||||
|
|
||||||
|
# check the patterns first
|
||||||
|
ignore = False
|
||||||
|
for pattern in self._excludes:
|
||||||
|
if fnmatch(fullpath, pattern) or fnmatch(filename, pattern):
|
||||||
|
if self.verbose: print 'Exclude pattern matched (%s): %s' % (pattern, fullpath)
|
||||||
|
ignore = True
|
||||||
|
break
|
||||||
|
if ignore:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# baselevel is needed to tell the arhiver where it have to extract file
|
||||||
|
yield filepath, fullpath
|
||||||
|
|
||||||
|
# get paths for every submodule
|
||||||
|
for submodule in self.runShell("git submodule --quiet foreach 'pwd'"):
|
||||||
|
chdir(submodule)
|
||||||
|
# in order to get output path we need to exclude repository path from the submodule path
|
||||||
|
submodule = submodule[len(git_repositary_path)+1:]
|
||||||
|
# recursion allows us to process repositories with more than one level of submodules
|
||||||
|
for git_file in self.listFiles(git_repositary_path, submodule):
|
||||||
|
yield git_file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def runShell(cmd):
|
||||||
|
return Popen(cmd, shell=True, stdout=PIPE).stdout.read().splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
parser = OptionParser(usage="usage: %prog [-v] [--prefix PREFIX] [--no-exclude] OUTPUT_FILE", version="%prog 1.0")
|
||||||
|
|
||||||
|
parser.add_option('--prefix', type='string', dest='prefix',
|
||||||
|
default='', help="prepend PREFIX to each filename in the archive")
|
||||||
|
|
||||||
|
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='enable verbose mode')
|
||||||
|
|
||||||
|
parser.add_option('--no-exclude', action='store_false', dest='exclude',
|
||||||
|
default=True, help="Dont read .gitattributes files for patterns containing export-ignore attrib")
|
||||||
|
|
||||||
|
parser.add_option('--extra', action='append', dest='extra', default=[],
|
||||||
|
help="Any additional files to include in the archive.")
|
||||||
|
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
if len(args) != 1:
|
||||||
|
parser.error('You must specify exactly one output file')
|
||||||
|
|
||||||
|
outFile = args[0]
|
||||||
|
|
||||||
|
if path.isdir(outFile):
|
||||||
|
parser.error('You cannot use directory as output')
|
||||||
|
|
||||||
|
archiver = GitArchiver(options.prefix,
|
||||||
|
options.verbose,
|
||||||
|
options.exclude,
|
||||||
|
options.extra)
|
||||||
|
|
||||||
|
try:
|
||||||
|
archiver.create(outFile)
|
||||||
|
except Exception, e:
|
||||||
|
parser.exit(2, "%s\n" % e)
|
||||||
|
|
||||||
|
sys.exit(0)
|
|
@ -7,7 +7,9 @@ CGALCache *CGALCache::inst = NULL;
|
||||||
void CGALCache::insert(const std::string &id, const CGAL_Nef_polyhedron &N)
|
void CGALCache::insert(const std::string &id, const CGAL_Nef_polyhedron &N)
|
||||||
{
|
{
|
||||||
this->cache.insert(id, new CGAL_Nef_polyhedron(N), N.weight());
|
this->cache.insert(id, new CGAL_Nef_polyhedron(N), N.weight());
|
||||||
|
#ifdef DEBUG
|
||||||
PRINTF("CGAL Cache insert: %s (%d verts)", id.substr(0, 40).c_str(), N.weight());
|
PRINTF("CGAL Cache insert: %s (%d verts)", id.substr(0, 40).c_str(), N.weight());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGALCache::print()
|
void CGALCache::print()
|
||||||
|
|
|
@ -159,7 +159,7 @@ Response CSGTermEvaluator::visit(State &state, const TransformNode &node)
|
||||||
Response CSGTermEvaluator::visit(State &state, const ColorNode &node)
|
Response CSGTermEvaluator::visit(State &state, const ColorNode &node)
|
||||||
{
|
{
|
||||||
if (state.isPrefix()) {
|
if (state.isPrefix()) {
|
||||||
state.setColor(node.color);
|
if (!state.color().isValid()) state.setColor(node.color);
|
||||||
}
|
}
|
||||||
if (state.isPostfix()) {
|
if (state.isPostfix()) {
|
||||||
applyToChildren(node, CSGT_UNION);
|
applyToChildren(node, CSGT_UNION);
|
||||||
|
|
|
@ -86,7 +86,7 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
|
||||||
if (shaderinfo) glUseProgram(shaderinfo[0]);
|
if (shaderinfo) glUseProgram(shaderinfo[0]);
|
||||||
for (; j < i; j++) {
|
for (; j < i; j++) {
|
||||||
const Transform3d &m = chain->matrices[j];
|
const Transform3d &m = chain->matrices[j];
|
||||||
double *c = chain->colors[j];
|
const Color4f &c = chain->colors[j];
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glMultMatrixd(m.data());
|
glMultMatrixd(m.data());
|
||||||
PolySet::csgmode_e csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
|
PolySet::csgmode_e csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
|
||||||
|
@ -99,7 +99,7 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
|
||||||
csgmode = PolySet::csgmode_e(csgmode + 10);
|
csgmode = PolySet::csgmode_e(csgmode + 10);
|
||||||
} else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
|
} else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
|
||||||
// User-defined color or alpha from source
|
// User-defined color or alpha from source
|
||||||
setColor(c, shaderinfo);
|
setColor(c.data(), shaderinfo);
|
||||||
} else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) {
|
} else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) {
|
||||||
setColor(COLORMODE_CUTOUT, shaderinfo);
|
setColor(COLORMODE_CUTOUT, shaderinfo);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,6 +33,9 @@ p, li { white-space: pre-wrap; }
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable OpenCSG</string>
|
<string>Enable OpenCSG</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -47,10 +47,16 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent)
|
||||||
|
|
||||||
// Setup default settings
|
// Setup default settings
|
||||||
this->defaultmap["3dview/colorscheme"] = this->colorSchemeChooser->currentItem()->text();
|
this->defaultmap["3dview/colorscheme"] = this->colorSchemeChooser->currentItem()->text();
|
||||||
this->defaultmap["editor/fontfamily"] = this->fontChooser->currentText();
|
#ifdef Q_WS_X11
|
||||||
this->defaultmap["editor/fontsize"] = this->fontSize->currentText().toUInt();
|
this->defaultmap["editor/fontfamily"] = "Mono";
|
||||||
|
#elif defined (Q_WS_WIN)
|
||||||
|
this->defaultmap["editor/fontfamily"] = "Console";
|
||||||
|
#elif defined (Q_WS_MAC)
|
||||||
|
this->defaultmap["editor/fontfamily"] = "Monaco";
|
||||||
|
#endif
|
||||||
|
this->defaultmap["editor/fontsize"] = 12;
|
||||||
this->defaultmap["advanced/opencsg_show_warning"] = true;
|
this->defaultmap["advanced/opencsg_show_warning"] = true;
|
||||||
this->defaultmap["advanced/enable_opencsg_opengl1x"] = false;
|
this->defaultmap["advanced/enable_opencsg_opengl1x"] = true;
|
||||||
|
|
||||||
// Toolbar
|
// Toolbar
|
||||||
QActionGroup *group = new QActionGroup(this);
|
QActionGroup *group = new QActionGroup(this);
|
||||||
|
@ -212,7 +218,7 @@ void Preferences::updateGUI()
|
||||||
if (!found.isEmpty()) this->colorSchemeChooser->setCurrentItem(found.first());
|
if (!found.isEmpty()) this->colorSchemeChooser->setCurrentItem(found.first());
|
||||||
|
|
||||||
QString fontfamily = getValue("editor/fontfamily").toString();
|
QString fontfamily = getValue("editor/fontfamily").toString();
|
||||||
int fidx = this->fontChooser->findText(fontfamily);
|
int fidx = this->fontChooser->findText(fontfamily,Qt::MatchContains);
|
||||||
if (fidx >= 0) {
|
if (fidx >= 0) {
|
||||||
this->fontChooser->setCurrentIndex(fidx);
|
this->fontChooser->setCurrentIndex(fidx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
|
||||||
if (polySetVisitMark[std::make_pair(chain->polysets[i].get(), &chain->matrices[i])]++ > 0)
|
if (polySetVisitMark[std::make_pair(chain->polysets[i].get(), &chain->matrices[i])]++ > 0)
|
||||||
continue;
|
continue;
|
||||||
const Transform3d &m = chain->matrices[i];
|
const Transform3d &m = chain->matrices[i];
|
||||||
double *c = chain->colors[i];
|
const Color4f &c = chain->colors[i];
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glMultMatrixd(m.data());
|
glMultMatrixd(m.data());
|
||||||
PolySet::csgmode_e csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
|
PolySet::csgmode_e csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
|
||||||
|
@ -93,10 +93,10 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
|
||||||
else csgmode = PolySet::csgmode_e(csgmode);
|
else csgmode = PolySet::csgmode_e(csgmode);
|
||||||
chain->polysets[i]->render_surface(csgmode, m);
|
chain->polysets[i]->render_surface(csgmode, m);
|
||||||
} else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
|
} else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
|
||||||
setColor(c);
|
setColor(c.data());
|
||||||
chain->polysets[i]->render_surface(csgmode, m);
|
chain->polysets[i]->render_surface(csgmode, m);
|
||||||
if (showedges) {
|
if (showedges) {
|
||||||
glColor4d((c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
|
glColor4f((c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
|
||||||
chain->polysets[i]->render_edges(csgmode);
|
chain->polysets[i]->render_edges(csgmode);
|
||||||
}
|
}
|
||||||
} else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) {
|
} else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "visitor.h"
|
#include "visitor.h"
|
||||||
|
#include "linalg.h"
|
||||||
|
|
||||||
class ColorNode : public AbstractNode
|
class ColorNode : public AbstractNode
|
||||||
{
|
{
|
||||||
|
@ -14,7 +15,7 @@ public:
|
||||||
virtual std::string toString() const;
|
virtual std::string toString() const;
|
||||||
virtual std::string name() const;
|
virtual std::string name() const;
|
||||||
|
|
||||||
double color[4];
|
Color4f color;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
128
src/csgterm.cc
|
@ -89,10 +89,9 @@ shared_ptr<CSGTerm> CSGTerm::createCSGTerm(type_e type, CSGTerm *left, CSGTerm *
|
||||||
return createCSGTerm(type, shared_ptr<CSGTerm>(left), shared_ptr<CSGTerm>(right));
|
return createCSGTerm(type, shared_ptr<CSGTerm>(left), shared_ptr<CSGTerm>(right));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSGTerm::CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const double color[4], const std::string &label)
|
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)
|
: type(TYPE_PRIMITIVE), polyset(polyset), label(label), m(matrix), color(color)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++) this->color[i] = color[i];
|
|
||||||
initBoundingBox();
|
initBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,127 +139,6 @@ void CSGTerm::initBoundingBox()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<CSGTerm> CSGTerm::normalize(shared_ptr<CSGTerm> term)
|
|
||||||
{
|
|
||||||
// This function implements the CSG normalization
|
|
||||||
// Reference:
|
|
||||||
// Goldfeather, J., Molnar, S., Turk, G., and Fuchs, H. Near
|
|
||||||
// Realtime CSG Rendering Using Tree Normalization and Geometric
|
|
||||||
// Pruning. IEEE Computer Graphics and Applications, 9(3):20-28,
|
|
||||||
// 1989.
|
|
||||||
// http://www.cc.gatech.edu/~turk/my_papers/pxpl_csg.pdf
|
|
||||||
|
|
||||||
if (term->type == TYPE_PRIMITIVE) {
|
|
||||||
return term;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
while (term && normalize_tail(term)) { }
|
|
||||||
if (!term || term->type == TYPE_PRIMITIVE) return term;
|
|
||||||
term->left = normalize(term->left);
|
|
||||||
} while (term->type != TYPE_UNION &&
|
|
||||||
(term->right->type != TYPE_PRIMITIVE || term->left->type == TYPE_UNION));
|
|
||||||
term->right = normalize(term->right);
|
|
||||||
|
|
||||||
// FIXME: Do we need to take into account any transformation of item here?
|
|
||||||
if (!term->right) {
|
|
||||||
if (term->type == TYPE_UNION || term->type == TYPE_DIFFERENCE) return term->left;
|
|
||||||
else return term->right;
|
|
||||||
}
|
|
||||||
if (!term->left) {
|
|
||||||
if (term->type == TYPE_UNION) return term->right;
|
|
||||||
else return term->left;
|
|
||||||
}
|
|
||||||
|
|
||||||
return term;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSGTerm::normalize_tail(shared_ptr<CSGTerm> &term)
|
|
||||||
{
|
|
||||||
if (term->type == TYPE_UNION || term->type == TYPE_PRIMITIVE) return false;
|
|
||||||
|
|
||||||
// Part A: The 'x . (y . z)' expressions
|
|
||||||
|
|
||||||
shared_ptr<CSGTerm> x = term->left;
|
|
||||||
shared_ptr<CSGTerm> y = term->right->left;
|
|
||||||
shared_ptr<CSGTerm> z = term->right->right;
|
|
||||||
|
|
||||||
shared_ptr<CSGTerm> result = term;
|
|
||||||
|
|
||||||
// 1. x - (y + z) -> (x - y) - z
|
|
||||||
if (term->type == TYPE_DIFFERENCE && term->right->type == TYPE_UNION) {
|
|
||||||
term = createCSGTerm(TYPE_DIFFERENCE,
|
|
||||||
createCSGTerm(TYPE_DIFFERENCE, x, y),
|
|
||||||
z);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 2. x * (y + z) -> (x * y) + (x * z)
|
|
||||||
else if (term->type == TYPE_INTERSECTION && term->right->type == TYPE_UNION) {
|
|
||||||
term = createCSGTerm(TYPE_UNION,
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, x, y),
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, x, z));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 3. x - (y * z) -> (x - y) + (x - z)
|
|
||||||
else if (term->type == TYPE_DIFFERENCE && term->right->type == TYPE_INTERSECTION) {
|
|
||||||
term = createCSGTerm(TYPE_UNION,
|
|
||||||
createCSGTerm(TYPE_DIFFERENCE, x, y),
|
|
||||||
createCSGTerm(TYPE_DIFFERENCE, x, z));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 4. x * (y * z) -> (x * y) * z
|
|
||||||
else if (term->type == TYPE_INTERSECTION && term->right->type == TYPE_INTERSECTION) {
|
|
||||||
term = createCSGTerm(TYPE_INTERSECTION,
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, x, y),
|
|
||||||
z);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 5. x - (y - z) -> (x - y) + (x * z)
|
|
||||||
else if (term->type == TYPE_DIFFERENCE && term->right->type == TYPE_DIFFERENCE) {
|
|
||||||
term = createCSGTerm(TYPE_UNION,
|
|
||||||
createCSGTerm(TYPE_DIFFERENCE, x, y),
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, x, z));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 6. x * (y - z) -> (x * y) - z
|
|
||||||
else if (term->type == TYPE_INTERSECTION && term->right->type == TYPE_DIFFERENCE) {
|
|
||||||
term = createCSGTerm(TYPE_DIFFERENCE,
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, x, y),
|
|
||||||
z);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Part B: The '(x . y) . z' expressions
|
|
||||||
|
|
||||||
x = term->left->left;
|
|
||||||
y = term->left->right;
|
|
||||||
z = term->right;
|
|
||||||
|
|
||||||
// 7. (x - y) * z -> (x * z) - y
|
|
||||||
if (term->left->type == TYPE_DIFFERENCE && term->type == TYPE_INTERSECTION) {
|
|
||||||
term = createCSGTerm(TYPE_DIFFERENCE,
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, x, z),
|
|
||||||
y);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 8. (x + y) - z -> (x - z) + (y - z)
|
|
||||||
else if (term->left->type == TYPE_UNION && term->type == TYPE_DIFFERENCE) {
|
|
||||||
term = createCSGTerm(TYPE_UNION,
|
|
||||||
createCSGTerm(TYPE_DIFFERENCE, x, z),
|
|
||||||
createCSGTerm(TYPE_DIFFERENCE, y, z));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// 9. (x + y) * z -> (x * z) + (y * z)
|
|
||||||
else if (term->left->type == TYPE_UNION && term->type == TYPE_INTERSECTION) {
|
|
||||||
term = createCSGTerm(TYPE_UNION,
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, x, z),
|
|
||||||
createCSGTerm(TYPE_INTERSECTION, y, z));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSGTerm::dump()
|
std::string CSGTerm::dump()
|
||||||
{
|
{
|
||||||
std::stringstream dump;
|
std::stringstream dump;
|
||||||
|
@ -281,7 +159,7 @@ CSGChain::CSGChain()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSGChain::add(const shared_ptr<PolySet> &polyset, const Transform3d &m, double *color, CSGTerm::type_e type, std::string label)
|
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);
|
polysets.push_back(polyset);
|
||||||
matrices.push_back(m);
|
matrices.push_back(m);
|
||||||
|
|
|
@ -28,14 +28,11 @@ public:
|
||||||
shared_ptr<CSGTerm> right;
|
shared_ptr<CSGTerm> right;
|
||||||
BoundingBox bbox;
|
BoundingBox bbox;
|
||||||
|
|
||||||
CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const double color[4], const std::string &label);
|
CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const Color4f &color, const std::string &label);
|
||||||
~CSGTerm();
|
~CSGTerm();
|
||||||
|
|
||||||
const BoundingBox &getBoundingBox() const { return this->bbox; }
|
const BoundingBox &getBoundingBox() const { return this->bbox; }
|
||||||
|
|
||||||
static shared_ptr<CSGTerm> normalize(shared_ptr<CSGTerm> term);
|
|
||||||
static bool normalize_tail(shared_ptr<CSGTerm> &term);
|
|
||||||
|
|
||||||
std::string dump();
|
std::string dump();
|
||||||
private:
|
private:
|
||||||
CSGTerm(type_e type, shared_ptr<CSGTerm> left, shared_ptr<CSGTerm> right);
|
CSGTerm(type_e type, shared_ptr<CSGTerm> left, shared_ptr<CSGTerm> right);
|
||||||
|
@ -44,7 +41,7 @@ private:
|
||||||
void initBoundingBox();
|
void initBoundingBox();
|
||||||
|
|
||||||
Transform3d m;
|
Transform3d m;
|
||||||
double color[4];
|
Color4f color;
|
||||||
|
|
||||||
friend class CSGChain;
|
friend class CSGChain;
|
||||||
};
|
};
|
||||||
|
@ -54,13 +51,13 @@ class CSGChain
|
||||||
public:
|
public:
|
||||||
std::vector<shared_ptr<PolySet> > polysets;
|
std::vector<shared_ptr<PolySet> > polysets;
|
||||||
std::vector<Transform3d> matrices;
|
std::vector<Transform3d> matrices;
|
||||||
std::vector<double*> colors;
|
std::vector<Color4f> colors;
|
||||||
std::vector<CSGTerm::type_e> types;
|
std::vector<CSGTerm::type_e> types;
|
||||||
std::vector<std::string> labels;
|
std::vector<std::string> labels;
|
||||||
|
|
||||||
CSGChain();
|
CSGChain();
|
||||||
|
|
||||||
void add(const shared_ptr<PolySet> &polyset, const Transform3d &m, double *color, CSGTerm::type_e type, std::string label);
|
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);
|
||||||
std::string dump();
|
std::string dump();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
#include "csgtermnormalizer.h"
|
||||||
|
#include "csgterm.h"
|
||||||
|
#include "printutils.h"
|
||||||
|
|
||||||
|
shared_ptr<CSGTerm> CSGTermNormalizer::normalize(const shared_ptr<CSGTerm> &root)
|
||||||
|
{
|
||||||
|
shared_ptr<CSGTerm> temp = root;
|
||||||
|
while (1) {
|
||||||
|
shared_ptr<CSGTerm> n = normalizePass(temp);
|
||||||
|
if (temp == n) break;
|
||||||
|
temp = n;
|
||||||
|
|
||||||
|
int num = count(temp);
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRINTF("Normalize count: %d\n", num);
|
||||||
|
#endif
|
||||||
|
if (num > 5000) {
|
||||||
|
PRINTF("WARNING: Normalized tree is growing past 5000 elements. Aborting normalization.\n");
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<CSGTerm> CSGTermNormalizer::normalizePass(shared_ptr<CSGTerm> term)
|
||||||
|
{
|
||||||
|
// This function implements the CSG normalization
|
||||||
|
// Reference:
|
||||||
|
// Goldfeather, J., Molnar, S., Turk, G., and Fuchs, H. Near
|
||||||
|
// Realtime CSG Rendering Using Tree Normalization and Geometric
|
||||||
|
// Pruning. IEEE Computer Graphics and Applications, 9(3):20-28,
|
||||||
|
// 1989.
|
||||||
|
// http://www.cc.gatech.edu/~turk/my_papers/pxpl_csg.pdf
|
||||||
|
|
||||||
|
if (term->type == CSGTerm::TYPE_PRIMITIVE) {
|
||||||
|
return term;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
while (term && normalize_tail(term)) { }
|
||||||
|
if (!term || term->type == CSGTerm::TYPE_PRIMITIVE) return term;
|
||||||
|
term->left = normalizePass(term->left);
|
||||||
|
} while (term->type != CSGTerm::TYPE_UNION &&
|
||||||
|
(term->right->type != CSGTerm::TYPE_PRIMITIVE || term->left->type == CSGTerm::TYPE_UNION));
|
||||||
|
term->right = normalizePass(term->right);
|
||||||
|
|
||||||
|
// FIXME: Do we need to take into account any transformation of item here?
|
||||||
|
if (!term->right) {
|
||||||
|
if (term->type == CSGTerm::TYPE_UNION || term->type == CSGTerm::TYPE_DIFFERENCE) return term->left;
|
||||||
|
else return term->right;
|
||||||
|
}
|
||||||
|
if (!term->left) {
|
||||||
|
if (term->type == CSGTerm::TYPE_UNION) return term->right;
|
||||||
|
else return term->left;
|
||||||
|
}
|
||||||
|
|
||||||
|
return term;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSGTermNormalizer::normalize_tail(shared_ptr<CSGTerm> &term)
|
||||||
|
{
|
||||||
|
if (term->type == CSGTerm::TYPE_UNION || term->type == CSGTerm::TYPE_PRIMITIVE) return false;
|
||||||
|
|
||||||
|
// Part A: The 'x . (y . z)' expressions
|
||||||
|
|
||||||
|
shared_ptr<CSGTerm> x = term->left;
|
||||||
|
shared_ptr<CSGTerm> y = term->right->left;
|
||||||
|
shared_ptr<CSGTerm> z = term->right->right;
|
||||||
|
|
||||||
|
shared_ptr<CSGTerm> result = term;
|
||||||
|
|
||||||
|
// 1. x - (y + z) -> (x - y) - z
|
||||||
|
if (term->type == CSGTerm::TYPE_DIFFERENCE && term->right->type == CSGTerm::TYPE_UNION) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, y),
|
||||||
|
z);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 2. x * (y + z) -> (x * y) + (x * z)
|
||||||
|
else if (term->type == CSGTerm::TYPE_INTERSECTION && term->right->type == CSGTerm::TYPE_UNION) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, y),
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 3. x - (y * z) -> (x - y) + (x - z)
|
||||||
|
else if (term->type == CSGTerm::TYPE_DIFFERENCE && term->right->type == CSGTerm::TYPE_INTERSECTION) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, y),
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, z));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 4. x * (y * z) -> (x * y) * z
|
||||||
|
else if (term->type == CSGTerm::TYPE_INTERSECTION && term->right->type == CSGTerm::TYPE_INTERSECTION) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, y),
|
||||||
|
z);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 5. x - (y - z) -> (x - y) + (x * z)
|
||||||
|
else if (term->type == CSGTerm::TYPE_DIFFERENCE && term->right->type == CSGTerm::TYPE_DIFFERENCE) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, y),
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 6. x * (y - z) -> (x * y) - z
|
||||||
|
else if (term->type == CSGTerm::TYPE_INTERSECTION && term->right->type == CSGTerm::TYPE_DIFFERENCE) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, y),
|
||||||
|
z);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Part B: The '(x . y) . z' expressions
|
||||||
|
|
||||||
|
x = term->left->left;
|
||||||
|
y = term->left->right;
|
||||||
|
z = term->right;
|
||||||
|
|
||||||
|
// 7. (x - y) * z -> (x * z) - y
|
||||||
|
if (term->left->type == CSGTerm::TYPE_DIFFERENCE && term->type == CSGTerm::TYPE_INTERSECTION) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z),
|
||||||
|
y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 8. (x + y) - z -> (x - z) + (y - z)
|
||||||
|
else if (term->left->type == CSGTerm::TYPE_UNION && term->type == CSGTerm::TYPE_DIFFERENCE) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, z),
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, y, z));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 9. (x + y) * z -> (x * z) + (y * z)
|
||||||
|
else if (term->left->type == CSGTerm::TYPE_UNION && term->type == CSGTerm::TYPE_INTERSECTION) {
|
||||||
|
term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z),
|
||||||
|
CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, y, z));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSGTermNormalizer::count(const shared_ptr<CSGTerm> &term) const
|
||||||
|
{
|
||||||
|
if (!term) return 0;
|
||||||
|
return term->type == CSGTerm::TYPE_PRIMITIVE ? 1 : 0 + count(term->left) + count(term->right);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef CSGTERMNORMALIZER_H_
|
||||||
|
#define CSGTERMNORMALIZER_H_
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
class CSGTermNormalizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSGTermNormalizer() : counter(0) {}
|
||||||
|
~CSGTermNormalizer() {}
|
||||||
|
|
||||||
|
shared_ptr<class CSGTerm> normalize(const shared_ptr<CSGTerm> &term);
|
||||||
|
|
||||||
|
private:
|
||||||
|
shared_ptr<CSGTerm> normalizePass(shared_ptr<CSGTerm> term) ;
|
||||||
|
bool normalize_tail(shared_ptr<CSGTerm> &term);
|
||||||
|
int count(const shared_ptr<CSGTerm> &term) const;
|
||||||
|
|
||||||
|
int counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -84,31 +84,22 @@ void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output, QProgressDial
|
||||||
stream << x3 << " " << y3 << " " << z3;
|
stream << x3 << " " << y3 << " " << z3;
|
||||||
std::string vs3 = stream.str();
|
std::string vs3 = stream.str();
|
||||||
if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) {
|
if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) {
|
||||||
// The above condition ensures that vs1-vs2, vs1-vs3, and their cross
|
// The above condition ensures that there are 3 distinct vertices, but
|
||||||
// product are non-zero. Floating point arithmetic may however truncate
|
// they may be collinear. If they are, the unit normal is meaningless
|
||||||
// small values to 0. This can be avoided by first scaling the components
|
// so the default value of "1 0 0" can be used. If the vertices are not
|
||||||
// of vs1-vs2 and vs1-vs3. This has no effect on the resulting unit
|
// collinear then the unit normal must be calculated from the
|
||||||
// normal vector.
|
// components.
|
||||||
double dn[6] = { x1-x2, y1-y2, z1-z2, x1-x3, y1-y3, z1-z3 };
|
if (!CGAL::collinear(v1.point(),v2.point(),v3.point())) {
|
||||||
double maxdn = 0;
|
CGAL_Polyhedron::Traits::Vector_3 normal = CGAL::normal(v1.point(),v2.point(),v3.point());
|
||||||
int i;
|
output << " facet normal "
|
||||||
for (i = 0; i < 6; ++i) {
|
<< CGAL::sign(normal.x()) * sqrt(CGAL::to_double(normal.x()*normal.x()/normal.squared_length()))
|
||||||
double dx = dn[i];
|
<< " "
|
||||||
if (dx < 0) dx = -dx;
|
<< CGAL::sign(normal.y()) * sqrt(CGAL::to_double(normal.y()*normal.y()/normal.squared_length()))
|
||||||
if (dx > maxdn) maxdn = dx;
|
<< " "
|
||||||
|
<< CGAL::sign(normal.z()) * sqrt(CGAL::to_double(normal.z()*normal.z()/normal.squared_length()))
|
||||||
|
<< "\n";
|
||||||
}
|
}
|
||||||
for (i = 0; i < 6; ++i) dn[i] /= maxdn;
|
else output << " facet normal 1 0 0\n";
|
||||||
double nx = dn[1]*dn[5] - dn[2]*dn[4];
|
|
||||||
double ny = dn[2]*dn[3] - dn[0]*dn[5];
|
|
||||||
double nz = dn[0]*dn[4] - dn[1]*dn[3];
|
|
||||||
double nlength = sqrt(nx*nx + ny*ny + nz*nz);
|
|
||||||
// Avoid generating normals for polygons with zero area
|
|
||||||
double eps = 0.000001;
|
|
||||||
if (nlength < eps) nlength = 1.0;
|
|
||||||
output << " facet normal "
|
|
||||||
<< nx / nlength << " "
|
|
||||||
<< ny / nlength << " "
|
|
||||||
<< nz / nlength << "\n";
|
|
||||||
output << " outer loop\n";
|
output << " outer loop\n";
|
||||||
output << " vertex " << vs1 << "\n";
|
output << " vertex " << vs1 << "\n";
|
||||||
output << " vertex " << vs2 << "\n";
|
output << " vertex " << vs2 << "\n";
|
||||||
|
|
|
@ -154,9 +154,9 @@ void GLView::initializeGL()
|
||||||
"Extensions:\n"
|
"Extensions:\n"
|
||||||
"%s\n",
|
"%s\n",
|
||||||
glewGetString(GLEW_VERSION),
|
glewGetString(GLEW_VERSION),
|
||||||
|
glGetString(GL_VERSION),
|
||||||
glGetString(GL_RENDERER),
|
glGetString(GL_RENDERER),
|
||||||
glGetString(GL_VENDOR),
|
glGetString(GL_VENDOR),
|
||||||
glGetString(GL_VERSION),
|
|
||||||
rbits, gbits, bbits, abits, dbits, sbits,
|
rbits, gbits, bbits, abits, dbits, sbits,
|
||||||
glGetString(GL_EXTENSIONS));
|
glGetString(GL_EXTENSIONS));
|
||||||
// FIXME: glGetString(GL_EXTENSIONS) is deprecated in OpenGL 3.0.
|
// FIXME: glGetString(GL_EXTENSIONS) is deprecated in OpenGL 3.0.
|
||||||
|
@ -500,10 +500,11 @@ void GLView::paintGL()
|
||||||
|
|
||||||
// FIXME: This was an attempt to keep contrast with background, but is suboptimal
|
// FIXME: This was an attempt to keep contrast with background, but is suboptimal
|
||||||
// (e.g. nearly invisible against a gray background).
|
// (e.g. nearly invisible against a gray background).
|
||||||
int r,g,b;
|
// int r,g,b;
|
||||||
r=g=b=0;
|
// r=g=b=0;
|
||||||
// bgcol.getRgb(&r, &g, &b);
|
// bgcol.getRgb(&r, &g, &b);
|
||||||
glColor3d((255.0-r)/255.0, (255.0-g)/255.0, (255.0-b)/255.0);
|
// glColor3f((255.0f-r)/255.0f, (255.0f-g)/255.0f, (255.0f-b)/255.0f);
|
||||||
|
glColor3f(0.0f, 0.0f, 0.0f);
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
// X Label
|
// X Label
|
||||||
glVertex3d(xlabel_x-3, xlabel_y-3, 0); glVertex3d(xlabel_x+3, xlabel_y+3, 0);
|
glVertex3d(xlabel_x-3, xlabel_y-3, 0); glVertex3d(xlabel_x+3, xlabel_y+3, 0);
|
||||||
|
|
21
src/lexer.l
|
@ -114,27 +114,6 @@ use[ \t\r\n>]*"<"[^\t\r\n>]+">" {
|
||||||
return TOK_USE;
|
return TOK_USE;
|
||||||
}
|
}
|
||||||
|
|
||||||
"<"[^ \t\r\n>]+">" {
|
|
||||||
char *filename = strdup(yytext+1);
|
|
||||||
filename[strlen(filename)-1] = 0;
|
|
||||||
QFileInfo finfo(QDir(parser_source_path), filename);
|
|
||||||
if (!finfo.exists()) {
|
|
||||||
finfo = QFileInfo(QDir(librarydir), filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINTF("DEPRECATED: Support for implicit include will be removed in future releases. Use `include <filename>' instead.");
|
|
||||||
handle_dep(finfo.absoluteFilePath().toStdString());
|
|
||||||
yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r");
|
|
||||||
if (!yyin) {
|
|
||||||
PRINTF("WARNING: Can't open input file `%s'.", filename);
|
|
||||||
} else {
|
|
||||||
openfiles.append(yyin);
|
|
||||||
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
|
||||||
BEGIN(INITIAL);
|
|
||||||
}
|
|
||||||
free(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
<<EOF>> {
|
<<EOF>> {
|
||||||
if(!path_stack.empty())
|
if(!path_stack.empty())
|
||||||
path_stack.pop();
|
path_stack.pop();
|
||||||
|
|
|
@ -15,4 +15,10 @@ using Eigen::Transform3d;
|
||||||
|
|
||||||
BoundingBox operator*(const Transform3d &m, const BoundingBox &box);
|
BoundingBox operator*(const Transform3d &m, const BoundingBox &box);
|
||||||
|
|
||||||
|
class Color4f : public Eigen::Vector4f
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool isValid() const { return this->minCoeff() >= 0.0f; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "ProgressWidget.h"
|
#include "ProgressWidget.h"
|
||||||
#include "ThrownTogetherRenderer.h"
|
#include "ThrownTogetherRenderer.h"
|
||||||
|
#include "csgtermnormalizer.h"
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
|
@ -181,7 +182,6 @@ MainWindow::MainWindow(const QString &filename)
|
||||||
editor->setTabStopWidth(30);
|
editor->setTabStopWidth(30);
|
||||||
#endif
|
#endif
|
||||||
editor->setLineWrapping(true); // Not designable
|
editor->setLineWrapping(true); // Not designable
|
||||||
setFont("", 12); // Init default font
|
|
||||||
|
|
||||||
this->glview->statusLabel = new QLabel(this);
|
this->glview->statusLabel = new QLabel(this);
|
||||||
statusBar()->addWidget(this->glview->statusLabel);
|
statusBar()->addWidget(this->glview->statusLabel);
|
||||||
|
@ -765,15 +765,8 @@ void MainWindow::compileCSG(bool procevents)
|
||||||
if (procevents)
|
if (procevents)
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
|
|
||||||
this->root_norm_term = this->root_raw_term;
|
CSGTermNormalizer normalizer;
|
||||||
|
this->root_norm_term = normalizer.normalize(this->root_raw_term);
|
||||||
// CSG normalization
|
|
||||||
while (1) {
|
|
||||||
shared_ptr<CSGTerm> n = CSGTerm::normalize(this->root_norm_term);
|
|
||||||
if (this->root_norm_term == n) break;
|
|
||||||
this->root_norm_term = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(this->root_norm_term);
|
assert(this->root_norm_term);
|
||||||
|
|
||||||
root_chain = new CSGChain();
|
root_chain = new CSGChain();
|
||||||
|
@ -787,11 +780,7 @@ void MainWindow::compileCSG(bool procevents)
|
||||||
|
|
||||||
highlights_chain = new CSGChain();
|
highlights_chain = new CSGChain();
|
||||||
for (unsigned int i = 0; i < highlight_terms.size(); i++) {
|
for (unsigned int i = 0; i < highlight_terms.size(); i++) {
|
||||||
while (1) {
|
highlight_terms[i] = normalizer.normalize(highlight_terms[i]);
|
||||||
shared_ptr<CSGTerm> n = CSGTerm::normalize(highlight_terms[i]);
|
|
||||||
if (highlight_terms[i] == n) break;
|
|
||||||
highlight_terms[i] = n;
|
|
||||||
}
|
|
||||||
highlights_chain->import(highlight_terms[i]);
|
highlights_chain->import(highlight_terms[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,11 +793,7 @@ void MainWindow::compileCSG(bool procevents)
|
||||||
|
|
||||||
background_chain = new CSGChain();
|
background_chain = new CSGChain();
|
||||||
for (unsigned int i = 0; i < background_terms.size(); i++) {
|
for (unsigned int i = 0; i < background_terms.size(); i++) {
|
||||||
while (1) {
|
background_terms[i] = normalizer.normalize(background_terms[i]);
|
||||||
shared_ptr<CSGTerm> n = CSGTerm::normalize(background_terms[i]);
|
|
||||||
if (background_terms[i] == n) break;
|
|
||||||
background_terms[i] = n;
|
|
||||||
}
|
|
||||||
background_chain->import(background_terms[i]);
|
background_chain->import(background_terms[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1762,8 +1747,9 @@ MainWindow::preferences()
|
||||||
|
|
||||||
void MainWindow::setFont(const QString &family, uint size)
|
void MainWindow::setFont(const QString &family, uint size)
|
||||||
{
|
{
|
||||||
QFont font(editor->font());
|
QFont font;
|
||||||
if (!family.isEmpty()) font.setFamily(family);
|
if (!family.isEmpty()) font.setFamily(family);
|
||||||
|
else font.setFixedPitch(true);
|
||||||
if (size > 0) font.setPointSize(size);
|
if (size > 0) font.setPointSize(size);
|
||||||
font.setStyleHint(QFont::TypeWriter);
|
font.setStyleHint(QFont::TypeWriter);
|
||||||
editor->setFont(font);
|
editor->setFont(font);
|
||||||
|
|
|
@ -364,6 +364,10 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dxf_output_file) {
|
if (dxf_output_file) {
|
||||||
|
if (root_N.dim != 2) {
|
||||||
|
fprintf(stderr, "Current top level object is not a 2D object.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
std::ofstream fstream(dxf_output_file);
|
std::ofstream fstream(dxf_output_file);
|
||||||
if (!fstream.is_open()) {
|
if (!fstream.is_open()) {
|
||||||
PRINTF("Can't open file \"%s\" for export", dxf_output_file);
|
PRINTF("Can't open file \"%s\" for export", dxf_output_file);
|
||||||
|
|
15
src/parser.y
|
@ -588,12 +588,15 @@ AbstractModule *parse(const char *text, const char *path, int debug)
|
||||||
if (!module)
|
if (!module)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
BOOST_FOREACH(Module::ModuleContainer::value_type &m, module->usedlibs) {
|
// Iterating manually since we want to modify the container while iterating
|
||||||
module->usedlibs[m.first] = Module::compile_library(m.first);
|
Module::ModuleContainer::iterator iter = module->usedlibs.begin();
|
||||||
if (!module->usedlibs[m.first]) {
|
while (iter != module->usedlibs.end()) {
|
||||||
PRINTF("WARNING: Failed to compile library `%s'.", m.first.c_str());
|
Module::ModuleContainer::iterator curr = iter++;
|
||||||
module->usedlibs.erase(m.first);
|
curr->second = Module::compile_library(curr->first);
|
||||||
}
|
if (!curr->second) {
|
||||||
|
PRINTF("WARNING: Failed to compile library `%s'.", curr->first.c_str());
|
||||||
|
module->usedlibs.erase(curr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parser_error_pos = -1;
|
parser_error_pos = -1;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "rendersettings.h"
|
#include "rendersettings.h"
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
|
||||||
void Renderer::setColor(const double color[4], GLint *shaderinfo) const
|
void Renderer::setColor(const float color[4], GLint *shaderinfo) const
|
||||||
{
|
{
|
||||||
QColor col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
|
QColor col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
|
||||||
double c[4] = {color[0], color[1], color[2], color[3]};
|
double c[4] = {color[0], color[1], color[2], color[3]};
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
COLORMODE_BACKGROUND_EDGES
|
COLORMODE_BACKGROUND_EDGES
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void setColor(const double color[4], GLint *shaderinfo = NULL) 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, GLint *shaderinfo = NULL) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
16
src/state.h
|
@ -9,8 +9,8 @@ class State
|
||||||
public:
|
public:
|
||||||
State(const class AbstractNode *parent)
|
State(const class AbstractNode *parent)
|
||||||
: parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) {
|
: parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) {
|
||||||
m = Transform3d::Identity();
|
this->matrix_ = Transform3d::Identity();
|
||||||
for (int i=0;i<4;i++) this->c[i] = -1.0;
|
this->color_.fill(-1.0f);
|
||||||
}
|
}
|
||||||
virtual ~State() {}
|
virtual ~State() {}
|
||||||
|
|
||||||
|
@ -18,15 +18,15 @@ public:
|
||||||
void setPostfix(bool on) { this->ispostfix = on; }
|
void setPostfix(bool on) { this->ispostfix = on; }
|
||||||
void setNumChildren(unsigned int numc) { this->numchildren = numc; }
|
void setNumChildren(unsigned int numc) { this->numchildren = numc; }
|
||||||
void setParent(const AbstractNode *parent) { this->parentnode = parent; }
|
void setParent(const AbstractNode *parent) { this->parentnode = parent; }
|
||||||
void setMatrix(const Transform3d &m) { this->m = m; }
|
void setMatrix(const Transform3d &m) { this->matrix_ = m; }
|
||||||
void setColor(const double c[4]) { memcpy(this->c, c, 4*sizeof(double)); }
|
void setColor(const Color4f &c) { this->color_ = c; }
|
||||||
|
|
||||||
bool isPrefix() const { return this->isprefix; }
|
bool isPrefix() const { return this->isprefix; }
|
||||||
bool isPostfix() const { return this->ispostfix; }
|
bool isPostfix() const { return this->ispostfix; }
|
||||||
unsigned int numChildren() const { return this->numchildren; }
|
unsigned int numChildren() const { return this->numchildren; }
|
||||||
const AbstractNode *parent() const { return this->parentnode; }
|
const AbstractNode *parent() const { return this->parentnode; }
|
||||||
const Transform3d &matrix() const { return this->m; }
|
const Transform3d &matrix() const { return this->matrix_; }
|
||||||
const double *color() const { return this->c; }
|
const Color4f &color() const { return this->color_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const AbstractNode * parentnode;
|
const AbstractNode * parentnode;
|
||||||
|
@ -35,8 +35,8 @@ private:
|
||||||
unsigned int numchildren;
|
unsigned int numchildren;
|
||||||
|
|
||||||
// Transformation matrix and color. FIXME: Generalize such state variables?
|
// Transformation matrix and color. FIXME: Generalize such state variables?
|
||||||
Transform3d m;
|
Transform3d matrix_;
|
||||||
double c[4];
|
Color4f color_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,4 +12,9 @@ translate([22,-11,0]) cylinder(h=5, r=5, r1=0, center=true);
|
||||||
translate([22,0,0]) cylinder(h=5, r=5, r2=0);
|
translate([22,0,0]) cylinder(h=5, r=5, r2=0);
|
||||||
translate([22,11,0]) cylinder(h=15, r=5, r2=5);
|
translate([22,11,0]) cylinder(h=15, r=5, r2=5);
|
||||||
|
|
||||||
|
// This tests for hexagonal cylinder orientation, since people
|
||||||
|
// tend to "abuse" this for captured nut slots
|
||||||
|
translate([-10,0,0]) cylinder(h=2, r=3, $fn=6);
|
||||||
|
|
||||||
|
|
||||||
// FIXME: We could test $fs, $fa, $fn as well
|
// FIXME: We could test $fs, $fa, $fn as well
|
||||||
|
|
|
@ -7,7 +7,7 @@ include <non/existent/path/non-file>
|
||||||
//Test with empty path
|
//Test with empty path
|
||||||
include <include-test5.scad>
|
include <include-test5.scad>
|
||||||
|
|
||||||
//Test without preceeding space
|
//Test without preceding space
|
||||||
include<include-test5.scad>
|
include<include-test5.scad>
|
||||||
|
|
||||||
//Test with other strange character that is allowed
|
//Test with other strange character that is allowed
|
||||||
|
@ -34,7 +34,7 @@ module test1()
|
||||||
translate([-2,-2,0]) test6();
|
translate([-2,-2,0]) test6();
|
||||||
|
|
||||||
//Just to give a top level object
|
//Just to give a top level object
|
||||||
translate([0,-2,0]) sphere(0.7, $fn=16);
|
translate([0,-2,0]) sphere(test2_variable, $fn=16);
|
||||||
}
|
}
|
||||||
|
|
||||||
test1();
|
test1();
|
||||||
|
|
|
@ -22,7 +22,7 @@ translate([12,0,0]) intersection() {
|
||||||
|
|
||||||
translate([12,12,0]) intersection() {
|
translate([12,12,0]) intersection() {
|
||||||
cube([10,10,10], center=true);
|
cube([10,10,10], center=true);
|
||||||
translate([0,0,7]) cylinder(r=4, h=4, center=true);
|
translate([0,0,7.01]) cylinder(r=4, h=4, center=true);
|
||||||
}
|
}
|
||||||
|
|
||||||
translate([24,0,0]) intersection() {
|
translate([24,0,0]) intersection() {
|
||||||
|
|
|
@ -4,7 +4,9 @@ include <include-test3.scad>
|
||||||
//Test relative file location
|
//Test relative file location
|
||||||
include <../include-test4.scad>
|
include <../include-test4.scad>
|
||||||
|
|
||||||
module test2 ()
|
test2_variable = 0.7;
|
||||||
|
|
||||||
|
module test2()
|
||||||
{
|
{
|
||||||
cube(center=true);
|
cube(center=true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
//Test nested use
|
||||||
|
use <use-test3.scad>
|
||||||
|
|
||||||
|
//Test relative file location
|
||||||
|
use <../use-test4.scad>
|
||||||
|
|
||||||
|
test2_variable = 0.7;
|
||||||
|
|
||||||
|
module test2()
|
||||||
|
{
|
||||||
|
translate([2,0,0]) test3();
|
||||||
|
translate([2,-2,0]) test4();
|
||||||
|
cube(center=true);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
module test3()
|
||||||
|
{
|
||||||
|
cylinder(r1=0.7, r2=0.2, center=true);
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
module test4()
|
||||||
|
{
|
||||||
|
cylinder(r=0.5, $fn=10, center=true);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
module test6()
|
||||||
|
{
|
||||||
|
difference() {
|
||||||
|
cube(center=true);
|
||||||
|
cylinder(r=0.4, h=2, center=true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
module test5()
|
||||||
|
{
|
||||||
|
sphere(r=0.5, $fn=8);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
//Test that the entire path is pushed onto the stack upto the last '/'
|
||||||
|
use <sub1/sub2/sub3/sub4/use-test2.scad>
|
||||||
|
|
||||||
|
//Test that a non existent path/file doesn't screw things up
|
||||||
|
use <non/existent/path/non-file>
|
||||||
|
|
||||||
|
//Test with empty path
|
||||||
|
use <use-test5.scad>
|
||||||
|
|
||||||
|
//Test without preceding space
|
||||||
|
use<use-test5.scad>
|
||||||
|
|
||||||
|
//Test with other strange character that is allowed
|
||||||
|
use>>>>><use-test5.scad>
|
||||||
|
|
||||||
|
//Test that filenames with spaces work
|
||||||
|
use <use test6.scad>
|
||||||
|
|
||||||
|
//Test with empty file
|
||||||
|
use<test/>
|
||||||
|
|
||||||
|
//Test with empty path and file
|
||||||
|
use </>
|
||||||
|
|
||||||
|
module test1()
|
||||||
|
{
|
||||||
|
test2();
|
||||||
|
// test3() and test4() are not directly included and thus not imported into
|
||||||
|
// this scope
|
||||||
|
translate([4,0,0]) test3();
|
||||||
|
translate([4,-2,0]) test4();
|
||||||
|
translate([-2,0,0]) test5();
|
||||||
|
translate([-2,-2,0]) test6();
|
||||||
|
|
||||||
|
// test2_variable won't be visible
|
||||||
|
translate([0,-2,0]) sphere(test2_variable, $fn=16);
|
||||||
|
}
|
||||||
|
|
||||||
|
test1();
|
|
@ -19,4 +19,6 @@ out.png
|
||||||
/echotest
|
/echotest
|
||||||
/opencsgtest
|
/opencsgtest
|
||||||
/throwntogethertest
|
/throwntogethertest
|
||||||
/yee_compare
|
/cgalstlsanitytest
|
||||||
|
/sysinfo.txt
|
||||||
|
/CTestCustom.cmake
|
|
@ -13,6 +13,9 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
|
||||||
# Build debug build as default
|
# Build debug build as default
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -24,11 +27,11 @@ endif()
|
||||||
# Windows
|
# Windows
|
||||||
#
|
#
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32 AND MSVC)
|
||||||
set(WIN32_STATIC_BUILD "True")
|
set(WIN32_STATIC_BUILD "True")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32_STATIC_BUILD)
|
if(WIN32_STATIC_BUILD AND MSVC)
|
||||||
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
||||||
set(EMSG "\nTo build Win32 STATIC OpenSCAD please see doc/testing.txt")
|
set(EMSG "\nTo build Win32 STATIC OpenSCAD please see doc/testing.txt")
|
||||||
message(FATAL_ERROR ${EMSG})
|
message(FATAL_ERROR ${EMSG})
|
||||||
|
@ -36,7 +39,7 @@ if(WIN32_STATIC_BUILD)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Disable warnings
|
# Disable warnings
|
||||||
if(WIN32)
|
if(WIN32 AND MSVC)
|
||||||
# too long decorated names
|
# too long decorated names
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4503")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4503")
|
||||||
# int cast to bool in CGAL
|
# int cast to bool in CGAL
|
||||||
|
@ -52,7 +55,7 @@ if(WIN32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Debugging - if you uncomment, use nmake -f Makefile > log.txt (the log is big)
|
# Debugging - if you uncomment, use nmake -f Makefile > log.txt (the log is big)
|
||||||
if(WIN32)
|
if(WIN32 AND MSVC)
|
||||||
# Linker debugging
|
# Linker debugging
|
||||||
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -VERBOSE")
|
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -VERBOSE")
|
||||||
|
|
||||||
|
@ -60,26 +63,44 @@ if(WIN32)
|
||||||
# you have to pass -DCMAKE_VERBOSE_MAKEFILE=ON to cmake when you run it.
|
# you have to pass -DCMAKE_VERBOSE_MAKEFILE=ON to cmake when you run it.
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -frounding-math")
|
||||||
|
endif()
|
||||||
|
|
||||||
#
|
#
|
||||||
# Build test apps
|
# Build test apps
|
||||||
#
|
#
|
||||||
|
|
||||||
|
function(inclusion user_set_path found_paths)
|
||||||
|
# If user_set_path indicates an env. variable was specifically
|
||||||
|
# set by the user, then found_paths become an include priority (prepend);
|
||||||
|
# otherwise found_paths are stuck on the end of the include flags (append).
|
||||||
|
|
||||||
|
# message(STATUS "inclusion ${user_set_path} ${found_paths}")
|
||||||
|
# message(STATUS "inclusion ${${user_set_path}} ${${found_paths}}")
|
||||||
|
set( inclusion_match 0 )
|
||||||
|
foreach( found_path ${${found_paths}} )
|
||||||
|
if (${found_path} MATCHES ${${user_set_path}}.*)
|
||||||
|
set( inclusion_match 1 )
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
if (user_set_path AND inclusion_match)
|
||||||
|
include_directories(BEFORE ${${found_paths}})
|
||||||
|
# message(STATUS "inclusion prepend ${${found_paths}} for ${user_set_path}")
|
||||||
|
else()
|
||||||
|
include_directories(AFTER ${${found_paths}})
|
||||||
|
# message(STATUS "inclusion append ${${found_paths}} for ${user_set_path}")
|
||||||
|
endif()
|
||||||
|
set( inclusion_match 0 )
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# Boost
|
# Boost
|
||||||
if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
#
|
||||||
set(BOOST_ROOT "$ENV{OPENSCAD_LIBRARIES}")
|
# FindBoost.cmake has been included from Cmake's GIT circa the end of 2011
|
||||||
endif()
|
# because most existing installs of cmake had a buggy older version.
|
||||||
|
#
|
||||||
if (NOT $ENV{BOOSTDIR} STREQUAL "")
|
# Update this if FindBoost.cmake gets out of sync with the current boost release
|
||||||
set(BOOST_DIR "$ENV{BOOSTDIR}")
|
# set(Boost_ADDITIONAL_VERSIONS "1.47.0" "1.46.0")
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT ${BOOST_DIR} STREQUAL "")
|
|
||||||
set(BOOST_ROOT ${BOOST_DIR})
|
|
||||||
message(STATUS "BOOST_ROOT: " ${BOOST_ROOT})
|
|
||||||
set(Boost_NO_SYSTEM_PATHS "TRUE")
|
|
||||||
set(Boost_DEBUG TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(Boost_USE_STATIC_LIBS TRUE)
|
set(Boost_USE_STATIC_LIBS TRUE)
|
||||||
|
@ -87,21 +108,32 @@ if (WIN32)
|
||||||
set(BOOST_THREAD_USE_LIB TRUE)
|
set(BOOST_THREAD_USE_LIB TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Update this if FindBoost.cmake gets out of sync with the current boost release
|
if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
||||||
# set(Boost_ADDITIONAL_VERSIONS "1.47.0" "1.46.0")
|
set(BOOST_ROOT "$ENV{OPENSCAD_LIBRARIES}")
|
||||||
find_package( Boost 1.35.0 COMPONENTS thread program_options REQUIRED)
|
if (EXISTS ${BOOST_ROOT}/include/boost)
|
||||||
if(Boost_FOUND)
|
# if boost is under OPENSCAD_LIBRARIES, then
|
||||||
message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS})
|
# don't look in the system paths (workaround FindBoost.cmake bug)
|
||||||
message(STATUS "Boost libraries found:")
|
set(Boost_NO_SYSTEM_PATHS "TRUE")
|
||||||
foreach(boostlib ${Boost_LIBRARIES})
|
message(STATUS "BOOST_ROOT: " ${BOOST_ROOT})
|
||||||
message(STATUS " " ${boostlib})
|
endif()
|
||||||
endforeach()
|
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
|
||||||
else()
|
|
||||||
message(STATUS "BOOST_ROOT: ${BOOST_ROOT}")
|
|
||||||
message(FATAL_ERROR "Boost not found.")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT $ENV{BOOSTDIR} STREQUAL "")
|
||||||
|
set(BOOST_ROOT "$ENV{BOOSTDIR}")
|
||||||
|
set(Boost_NO_SYSTEM_PATHS "TRUE")
|
||||||
|
set(Boost_DEBUG TRUE)
|
||||||
|
message(STATUS "BOOST_ROOT: " ${BOOST_ROOT})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package( Boost 1.35.0 COMPONENTS thread program_options REQUIRED)
|
||||||
|
message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS})
|
||||||
|
message(STATUS "Boost libraries found:")
|
||||||
|
foreach(boostlib ${Boost_LIBRARIES})
|
||||||
|
message(STATUS " " ${boostlib})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
inclusion(BOOST_ROOT Boost_INCLUDE_DIRS)
|
||||||
|
|
||||||
# Mac OS X
|
# Mac OS X
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||||
FIND_LIBRARY(COCOA_LIBRARY Cocoa REQUIRED)
|
FIND_LIBRARY(COCOA_LIBRARY Cocoa REQUIRED)
|
||||||
|
@ -109,19 +141,21 @@ endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||||
|
|
||||||
# Qt4
|
# Qt4
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
|
||||||
# make /usr/local/include/qt4 come before /usr/local/include (QT4 vs QT3)
|
|
||||||
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)
|
|
||||||
include(${QT_USE_FILE})
|
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
if (MINGW_CROSS_ENV_DIR)
|
||||||
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE OFF)
|
mingw_cross_env_find_qt()
|
||||||
|
mingw_cross_env_info()
|
||||||
|
include_directories( ${QT_INCLUDE_DIRS} )
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QT_CFLAGS_OTHER}")
|
||||||
|
else()
|
||||||
|
find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)
|
||||||
|
include(${QT_USE_FILE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE OFF)
|
||||||
|
|
||||||
# Eigen2
|
# Eigen2
|
||||||
|
|
||||||
# Turn off Eigen SIMD optimization
|
# Turn off Eigen SIMD optimization
|
||||||
|
@ -131,24 +165,34 @@ if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT $ENV{EIGEN2DIR} STREQUAL "")
|
||||||
|
set(EIGEN2_DIR "$ENV{EIGEN2DIR}")
|
||||||
|
elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
||||||
|
set(EIGEN2_DIR "$ENV{OPENSCAD_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (NOT EIGEN2_INCLUDE_DIR)
|
if (NOT EIGEN2_INCLUDE_DIR)
|
||||||
|
if (EIGEN2_DIR)
|
||||||
|
set(EIGEN2_FIND_HINTS "${EIGEN2_DIR}/include/eigen2")
|
||||||
|
endif()
|
||||||
|
if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||||
|
set(EIGEN2_FIND_PATHS /usr/local/include/eigen2)
|
||||||
|
elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
|
||||||
|
set(EIGEN2_FIND_PATHS /usr/pkg/include/eigen2)
|
||||||
|
else()
|
||||||
|
set(EIGEN2_FIND_PATHS /opt/local/include/eigen2 /usr/include/eigen2)
|
||||||
|
endif()
|
||||||
find_path(EIGEN2_INCLUDE_DIR
|
find_path(EIGEN2_INCLUDE_DIR
|
||||||
Eigen/Core
|
Eigen/Core
|
||||||
HINTS $ENV{EIGEN2DIR}
|
HINTS ${EIGEN2_FIND_HINTS}
|
||||||
PATHS /opt/local/include/eigen2 /usr/include/eigen2)
|
PATHS ${EIGEN2_FIND_PATHS})
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
|
||||||
find_path(EIGEN2_INCLUDE_DIR
|
|
||||||
Eigen/Core
|
|
||||||
HINTS $ENV{EIGEN2DIR}
|
|
||||||
PATHS /usr/local/include/eigen2 )
|
|
||||||
endif()
|
|
||||||
if (NOT EIGEN2_INCLUDE_DIR)
|
if (NOT EIGEN2_INCLUDE_DIR)
|
||||||
message(FATAL_ERROR "Eigen2 not found")
|
message(FATAL_ERROR "Eigen2 not found")
|
||||||
else()
|
else()
|
||||||
message(STATUS "Eigen2 found in " ${EIGEN2_INCLUDE_DIR})
|
message(STATUS "Eigen2 found in " ${EIGEN2_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
include_directories(${EIGEN2_INCLUDE_DIR})
|
inclusion(EIGEN2_DIR EIGEN2_INCLUDE_DIR)
|
||||||
|
|
||||||
# OpenCSG
|
# OpenCSG
|
||||||
if (NOT $ENV{OPENCSGDIR} STREQUAL "")
|
if (NOT $ENV{OPENCSGDIR} STREQUAL "")
|
||||||
|
@ -171,10 +215,14 @@ if (NOT OPENCSG_INCLUDE_DIR)
|
||||||
message(STATUS "OpenCSG library found in " ${OPENCSG_LIBRARY})
|
message(STATUS "OpenCSG library found in " ${OPENCSG_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
include_directories(${OPENCSG_INCLUDE_DIR})
|
inclusion(OPENCSG_DIR OPENCSG_INCLUDE_DIR)
|
||||||
|
|
||||||
# GLEW
|
# GLEW
|
||||||
|
|
||||||
|
if(WIN32_STATIC_BUILD)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLEW_STATIC")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (NOT $ENV{GLEWDIR} STREQUAL "")
|
if (NOT $ENV{GLEWDIR} STREQUAL "")
|
||||||
set(GLEW_DIR "$ENV{GLEWDIR}")
|
set(GLEW_DIR "$ENV{GLEWDIR}")
|
||||||
elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
||||||
|
@ -182,11 +230,8 @@ elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(GLEW REQUIRED)
|
find_package(GLEW REQUIRED)
|
||||||
include_directories(${GLEW_INCLUDE_PATH})
|
|
||||||
|
|
||||||
if(WIN32_STATIC_BUILD)
|
inclusion( GLEW_DIR GLEW_INCLUDE_PATH )
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLEW_STATIC")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Flex/Bison
|
# Flex/Bison
|
||||||
find_package(BISON REQUIRED)
|
find_package(BISON REQUIRED)
|
||||||
|
@ -196,6 +241,11 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||||
set(FLEX_EXECUTABLE /usr/local/bin/flex)
|
set(FLEX_EXECUTABLE /usr/local/bin/flex)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
|
||||||
|
include_directories( /usr/pkg/include /usr/X11R7/include )
|
||||||
|
set(FLEX_EXECUTABLE /usr/pkg/bin/flex)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(FLEX REQUIRED)
|
find_package(FLEX REQUIRED)
|
||||||
# The COMPILE_FLAGS and forced C++ compiler is just to be compatible with qmake
|
# The COMPILE_FLAGS and forced C++ compiler is just to be compatible with qmake
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
@ -211,8 +261,13 @@ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES
|
||||||
if (NOT $ENV{CGALDIR} STREQUAL "")
|
if (NOT $ENV{CGALDIR} STREQUAL "")
|
||||||
set(CGAL_DIR "$ENV{CGALDIR}")
|
set(CGAL_DIR "$ENV{CGALDIR}")
|
||||||
elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
|
||||||
set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
|
if (EXISTS "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
|
||||||
set(CMAKE_MODULE_PATH "${CGAL_DIR}")
|
set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
|
||||||
|
set(CMAKE_MODULE_PATH "${CGAL_DIR}")
|
||||||
|
elseif (EXISTS "$ENV{OPENSCAD_LIBRARIES}/include/CGAL")
|
||||||
|
set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}")
|
||||||
|
set(CMAKE_MODULE_PATH "${CGAL_DIR}")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "CGAL_DIR: " ${CGAL_DIR})
|
message(STATUS "CGAL_DIR: " ${CGAL_DIR})
|
||||||
find_package(CGAL REQUIRED)
|
find_package(CGAL REQUIRED)
|
||||||
|
@ -224,15 +279,17 @@ message(STATUS "CGAL libraries found in " ${CGAL_LIBRARIES_DIR} )
|
||||||
if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)
|
if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)
|
||||||
message(FATAL_ERROR "CGAL >= 3.6 required")
|
message(FATAL_ERROR "CGAL >= 3.6 required")
|
||||||
endif()
|
endif()
|
||||||
include_directories(${CGAL_INCLUDE_DIRS})
|
inclusion(CGAL_DIR CGAL_INCLUDE_DIRS)
|
||||||
|
|
||||||
# Imagemagick
|
# Imagemagick
|
||||||
|
|
||||||
find_package(ImageMagick COMPONENTS convert)
|
if (NOT SKIP_IMAGEMAGICK)
|
||||||
if (ImageMagick_convert_FOUND)
|
find_package(ImageMagick COMPONENTS convert)
|
||||||
message(STATUS "ImageMagick convert executable found: " ${ImageMagick_convert_EXECUTABLE})
|
if (ImageMagick_convert_FOUND)
|
||||||
else()
|
message(STATUS "ImageMagick convert executable found: " ${ImageMagick_convert_EXECUTABLE})
|
||||||
message(FATAL_ERROR "Couldn't find imagemagick 'convert' program")
|
else()
|
||||||
|
message(FATAL_ERROR "Couldn't find imagemagick 'convert' program")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Internal includes
|
# Internal includes
|
||||||
|
@ -253,6 +310,7 @@ set(CORE_SOURCES
|
||||||
../src/node.cc
|
../src/node.cc
|
||||||
../src/context.cc
|
../src/context.cc
|
||||||
../src/csgterm.cc
|
../src/csgterm.cc
|
||||||
|
../src/csgtermnormalizer.cc
|
||||||
../src/polyset.cc
|
../src/polyset.cc
|
||||||
../src/csgops.cc
|
../src/csgops.cc
|
||||||
../src/transform.cc
|
../src/transform.cc
|
||||||
|
@ -319,6 +377,7 @@ set(OFFSCREEN_SOURCES
|
||||||
system-gl.cc)
|
system-gl.cc)
|
||||||
|
|
||||||
add_library(tests-core STATIC ${CORE_SOURCES})
|
add_library(tests-core STATIC ${CORE_SOURCES})
|
||||||
|
target_link_libraries(tests-core ${OPENGL_LIBRARY})
|
||||||
add_library(tests-common STATIC ${COMMON_SOURCES})
|
add_library(tests-common STATIC ${COMMON_SOURCES})
|
||||||
target_link_libraries(tests-common tests-core)
|
target_link_libraries(tests-common tests-core)
|
||||||
add_library(tests-cgal STATIC ${CGAL_SOURCES})
|
add_library(tests-cgal STATIC ${CGAL_SOURCES})
|
||||||
|
@ -453,8 +512,8 @@ endfunction()
|
||||||
# comparison method to use
|
# comparison method to use
|
||||||
if (NOT $ENV{COMPARATOR} STREQUAL "")
|
if (NOT $ENV{COMPARATOR} STREQUAL "")
|
||||||
set(COMPARATOR "$ENV{COMPARATOR}")
|
set(COMPARATOR "$ENV{COMPARATOR}")
|
||||||
|
message(STATUS "ImageMagick method modified with COMPARATOR: " ${COMPARATOR})
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "COMPARATOR: " ${COMPARATOR})
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# This functions adds cmd-line tests given files.
|
# This functions adds cmd-line tests given files.
|
||||||
|
@ -486,7 +545,10 @@ macro(add_cmdline_test TESTCMD TESTSUFFIX)
|
||||||
set(CONFARG CONFIGURATIONS)
|
set(CONFARG CONFIGURATIONS)
|
||||||
set(CONFVAL ${FOUNDCONFIGS})
|
set(CONFVAL ${FOUNDCONFIGS})
|
||||||
|
|
||||||
add_test(NAME ${TEST_FULLNAME} ${CONFARG} ${CONFVAL} COMMAND ${PYTHON_EXECUTABLE} ${tests_SOURCE_DIR}/test_cmdline_tool.py --comparator=${COMPARATOR} -c ${ImageMagick_convert_EXECUTABLE} -s ${TESTSUFFIX} ${CMAKE_BINARY_DIR}/${TESTCMD} "${SCADFILE}")
|
if (MINGW_CROSS_ENV_DIR)
|
||||||
|
set( MINGW_CROSS_ARG "--mingw-cross-env" )
|
||||||
|
endif()
|
||||||
|
add_test(NAME ${TEST_FULLNAME} ${CONFARG} ${CONFVAL} COMMAND ${PYTHON_EXECUTABLE} ${tests_SOURCE_DIR}/test_cmdline_tool.py ${MINGW_CROSS_ARG} --comparator=${COMPARATOR} -c ${ImageMagick_convert_EXECUTABLE} -s ${TESTSUFFIX} ${CMAKE_BINARY_DIR}/${TESTCMD} "${SCADFILE}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
@ -496,6 +558,9 @@ enable_testing()
|
||||||
# set up custom pretty printing of results
|
# set up custom pretty printing of results
|
||||||
|
|
||||||
set(INFOCMD "execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)")
|
set(INFOCMD "execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)")
|
||||||
|
if (MINGW_CROSS_ENV_DIR)
|
||||||
|
set(INFOCMD "execute_process(COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)")
|
||||||
|
endif()
|
||||||
set(PRETTYCMD "\"${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_pretty_print.py --builddir=${CMAKE_CURRENT_BINARY_DIR}\"")
|
set(PRETTYCMD "\"${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_pretty_print.py --builddir=${CMAKE_CURRENT_BINARY_DIR}\"")
|
||||||
set(CTEST_CUSTOM_FILE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)
|
set(CTEST_CUSTOM_FILE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)
|
||||||
set(CTEST_CUSTOM_TXT "\n
|
set(CTEST_CUSTOM_TXT "\n
|
||||||
|
@ -518,7 +583,9 @@ file(GLOB FEATURES_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/*.scad)
|
||||||
# Remove included files not to be used as tests
|
# Remove included files not to be used as tests
|
||||||
list(REMOVE_ITEM FEATURES_FILES
|
list(REMOVE_ITEM FEATURES_FILES
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/features/include\ test6.scad
|
${CMAKE_SOURCE_DIR}/../testdata/scad/features/include\ test6.scad
|
||||||
${CMAKE_SOURCE_DIR}/../testdata/scad/features/include-test5.scad)
|
${CMAKE_SOURCE_DIR}/../testdata/scad/features/include-test5.scad
|
||||||
|
${CMAKE_SOURCE_DIR}/../testdata/scad/features/use\ test6.scad
|
||||||
|
${CMAKE_SOURCE_DIR}/../testdata/scad/features/use-test5.scad)
|
||||||
file(GLOB BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/*.scad)
|
file(GLOB BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/*.scad)
|
||||||
file(GLOB SCAD_DXF_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/dxf/*.scad)
|
file(GLOB SCAD_DXF_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/dxf/*.scad)
|
||||||
file(GLOB FUNCTION_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/functions/*.scad)
|
file(GLOB FUNCTION_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/functions/*.scad)
|
||||||
|
@ -548,15 +615,20 @@ list(APPEND CGALSTLSANITYTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/no
|
||||||
# Once we're capable of comparing these across platforms, we can put these back in
|
# Once we're capable of comparing these across platforms, we can put these back in
|
||||||
disable_tests(dumptest_transform-tests
|
disable_tests(dumptest_transform-tests
|
||||||
dumptest_render-tests
|
dumptest_render-tests
|
||||||
|
dumptest_difference-tests
|
||||||
|
dumptest_intersection-tests
|
||||||
dumptest_example001
|
dumptest_example001
|
||||||
dumptest_example005
|
dumptest_example005
|
||||||
dumptest_example006
|
dumptest_example006
|
||||||
dumptest_example007
|
dumptest_example007
|
||||||
dumptest_example008
|
dumptest_example008
|
||||||
dumptest_example012
|
dumptest_example012
|
||||||
|
dumptest_example013
|
||||||
dumptest_example016
|
dumptest_example016
|
||||||
|
dumptest_example017
|
||||||
dumptest_example020
|
dumptest_example020
|
||||||
dumptest_example021)
|
dumptest_example021
|
||||||
|
dumptest_example022)
|
||||||
|
|
||||||
# FIXME: This test illustrates a weakness in child() combined with modifiers.
|
# FIXME: This test illustrates a weakness in child() combined with modifiers.
|
||||||
# Reenable it when this is improved
|
# Reenable it when this is improved
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
#
|
||||||
|
# CMake Toolchain file for cross compiling OpenSCAD tests linux->mingw-win32
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Prerequisites: mingw-cross-env, ImageMagick 6.5.9.3 or newer, wine
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# - follow Brad Pitcher's mingw-cross-env for OpenSCAD setup:
|
||||||
|
# http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Cross-compiling_for_Windows_on_Linux_or_Mac_OS_X
|
||||||
|
# - cross-compile openscad.exe, to verify your installation works properly.
|
||||||
|
# - cd openscad/tests && mkdir build-mingw32 && cd build-mingw32
|
||||||
|
# - cmake .. -DCMAKE_TOOLCHAIN_FILE=CMingw-cross-env.cmake \
|
||||||
|
# -DMINGW_CROSS_ENV_DIR=<where mingw-cross-env is installed>
|
||||||
|
# - make should proceed as normal.
|
||||||
|
# - now run 'ctest' on your *nix machine.
|
||||||
|
# The test .exe programs should run under Wine.
|
||||||
|
#
|
||||||
|
# See also:
|
||||||
|
#
|
||||||
|
# http://lists.gnu.org/archive/html/mingw-cross-env-list/2010-11/threads.html#00078
|
||||||
|
# (thread "Qt with Cmake")
|
||||||
|
# http://lists.gnu.org/archive/html/mingw-cross-env-list/2011-01/threads.html#00012
|
||||||
|
# (thread "Qt: pkg-config files?")
|
||||||
|
# http://mingw-cross-env.nongnu.org/#requirements
|
||||||
|
# http://www.vtk.org/Wiki/CMake_Cross_Compiling
|
||||||
|
# https://bitbucket.org/muellni/mingw-cross-env-cmake/src/2067fcf2d52e/src/cmake-1-toolchain-file.patch
|
||||||
|
# http://code.google.com/p/qtlobby/source/browse/trunk/toolchain-mingw.cmake
|
||||||
|
# http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Link-Options.html
|
||||||
|
# Makefile.Release generated by qmake
|
||||||
|
# cmake's FindQt4.cmake & Qt4ConfigDependentSettings.cmake files
|
||||||
|
# mingw-cross-env's qmake.conf and *.prl files
|
||||||
|
# mingw-cross-env's pkg-config files in usr/i686-pc-mingw32/lib/pkgconfig
|
||||||
|
# http://www.vtk.org/Wiki/CMake:How_To_Find_Libraries
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
#
|
||||||
|
# To debug the build process run "make VERBOSE=1". 'strace -f' is also useful.
|
||||||
|
#
|
||||||
|
# This file is actually called multiple times by cmake, so various 'if NOT set'
|
||||||
|
# guards are used to keep programs from running twice.
|
||||||
|
#
|
||||||
|
# The test will not currently run under win32 because the ctest harness
|
||||||
|
# is created by cmake on the machine that it is called on, not on the
|
||||||
|
# machine it is targeting.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Part 1. Find *nix-ImageMagick
|
||||||
|
#
|
||||||
|
# The tests run under Wine under *nix. Therefore we need to find the
|
||||||
|
# ImageMagick comparison program on the *nix machine. It must be
|
||||||
|
# searched before the 'cross-compile' environment is setup.
|
||||||
|
#
|
||||||
|
|
||||||
|
if (NOT imagemagick_cross_set)
|
||||||
|
find_package(ImageMagick COMPONENTS convert REQUIRED)
|
||||||
|
message(STATUS "ImageMagick convert executable found: " ${ImageMagick_convert_EXECUTABLE})
|
||||||
|
set( SKIP_IMAGEMAGICK TRUE )
|
||||||
|
set( imagemagick_cross_set )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Part 2. cross-compiler setup
|
||||||
|
#
|
||||||
|
|
||||||
|
set(MINGW_CROSS_ENV_DIR $ENV{MINGW_CROSS_ENV_DIR})
|
||||||
|
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
set(CMAKE_SYSTEM_NAME Windows)
|
||||||
|
set(MSYS 1)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH ${MINGW_CROSS_ENV_DIR}/usr/i686-pc-mingw32)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-g++)
|
||||||
|
set(QT_QMAKE_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-qmake)
|
||||||
|
set(PKG_CONFIG_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-pkg-config)
|
||||||
|
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Part 3. library settings for mingw-cross-env
|
||||||
|
#
|
||||||
|
|
||||||
|
set( Boost_USE_STATIC_LIBS ON )
|
||||||
|
set( Boost_USE_MULTITHREADED ON )
|
||||||
|
set( Boost_COMPILER "_win32" )
|
||||||
|
# set( Boost_DEBUG TRUE ) # for debugging cmake's FindBoost, not boost itself
|
||||||
|
|
||||||
|
set( OPENSCAD_LIBRARIES ${CMAKE_FIND_ROOT_PATH} )
|
||||||
|
set( EIGEN2_DIR ${CMAKE_FIND_ROOT_PATH} )
|
||||||
|
set( CGAL_DIR ${CMAKE_FIND_ROOT_PATH}/lib/CGAL )
|
||||||
|
set( GLEW_DIR ${CMAKE_FIND_ROOT_PATH} )
|
||||||
|
|
||||||
|
#
|
||||||
|
# Qt4
|
||||||
|
#
|
||||||
|
# To workaround problems with CMake's FindQt4.cmake when combined with
|
||||||
|
# mingw-cross-env (circa early 2012), we here instead use pkg-config. To
|
||||||
|
# workaround Cmake's insertion of -bdynamic, we stick 'static' on the
|
||||||
|
# end of QT_LIBRARIES
|
||||||
|
#
|
||||||
|
|
||||||
|
set(QT_QMAKE_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-qmake)
|
||||||
|
set(QT_MOC_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-moc)
|
||||||
|
set(QT_UIC_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-uic)
|
||||||
|
|
||||||
|
function(mingw_cross_env_find_qt)
|
||||||
|
# called from CMakeLists.txt
|
||||||
|
find_package( PkgConfig )
|
||||||
|
pkg_check_modules( QTCORE QtCore )
|
||||||
|
pkg_check_modules( QTGUI QtGui )
|
||||||
|
pkg_check_modules( QTOPENGL QtOpenGL )
|
||||||
|
|
||||||
|
set(QT_INCLUDE_DIRS ${QTCORE_INCLUDE_DIRS} ${QTGUI_INCLUDE_DIRS} ${QTOPENGL_INCLUDE_DIRS})
|
||||||
|
set(QT_CFLAGS_OTHER "${QTCORE_CFLAGS_OTHER} ${QTGUI_CFLAGS_OTHER} ${QTOPENGL_CFLAGS_OTHER}")
|
||||||
|
set(QT_LIBRARIES "${QTCORE_STATIC_LDFLAGS} ${QTGUI_STATIC_LDFLAGS} ${QTOPENGL_STATIC_LDFLAGS};-static")
|
||||||
|
|
||||||
|
set(QT_INCLUDE_DIRS ${QT_INCLUDE_DIRS} PARENT_SCOPE)
|
||||||
|
set(QT_CFLAGS_OTHER ${QT_CFLAGS_OTHER} PARENT_SCOPE)
|
||||||
|
set(QT_LIBRARIES ${QT_LIBRARIES} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(mingw_cross_env_info)
|
||||||
|
message(STATUS "QT INCLUDE_DIRS: ${QT_INCLUDE_DIRS}")
|
||||||
|
message(STATUS "QT LIBRARIES: ${QT_LIBRARIES}")
|
||||||
|
message(STATUS "QT_CFLAGS_OTHER: ${QT_CFLAGS_OTHER}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Part 4. -D definitions
|
||||||
|
#
|
||||||
|
|
||||||
|
if( NOT cross_defs_set )
|
||||||
|
add_definitions( -DGLEW_STATIC ) # FindGLEW.cmake needs this
|
||||||
|
add_definitions( -DBOOST_STATIC )
|
||||||
|
add_definitions( -DBOOST_THREAD_USE_LIB )
|
||||||
|
add_definitions( -DUNICODE ) # because qmake does it
|
||||||
|
set(cross_defs_set 1)
|
||||||
|
endif()
|
|
@ -11,13 +11,17 @@
|
||||||
# http://openlibraries.org/browser/trunk/FindGLEW.cmake?rev=1383
|
# http://openlibraries.org/browser/trunk/FindGLEW.cmake?rev=1383
|
||||||
|
|
||||||
|
|
||||||
IF (WIN32)
|
IF (WIN32 AND MSVC)
|
||||||
IF (WIN32_STATIC_BUILD) # passed from caller
|
IF (WIN32_STATIC_BUILD) # passed from caller
|
||||||
SET(GLEW_LIB_SEARCH_NAME glew32s.lib) # static, non-debug (Release)
|
SET(GLEW_LIB_SEARCH_NAME glew32s.lib) # static, non-debug (Release)
|
||||||
ELSE ()
|
ELSE ()
|
||||||
SET(GLEW_LIB_SEARCH_NAME glew32.lib) # other. untested with OpenSCAD
|
SET(GLEW_LIB_SEARCH_NAME glew32.lib) # other. untested with OpenSCAD
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
ELSE () # GCC
|
||||||
|
SET(GLEW_LIB_SEARCH_NAME "libglew32s.a")
|
||||||
|
ENDIF ()
|
||||||
|
|
||||||
|
IF (WIN32)
|
||||||
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
|
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
|
||||||
$ENV{PROGRAMFILES}/GLEW/include
|
$ENV{PROGRAMFILES}/GLEW/include
|
||||||
${PROJECT_SOURCE_DIR}/src/nvgl/glew/include
|
${PROJECT_SOURCE_DIR}/src/nvgl/glew/include
|
||||||
|
@ -33,13 +37,13 @@ ELSE (WIN32)
|
||||||
message(STATUS "GLEW_DIR: " ${GLEW_DIR})
|
message(STATUS "GLEW_DIR: " ${GLEW_DIR})
|
||||||
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
|
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
|
||||||
HINTS ${GLEW_DIR}/include
|
HINTS ${GLEW_DIR}/include
|
||||||
PATHS /usr/include /usr/local/include
|
PATHS /usr/include /usr/local/include /usr/pkg/include
|
||||||
NO_DEFAULT_PATH
|
NO_DEFAULT_PATH
|
||||||
DOC "The directory where GL/glew.h resides")
|
DOC "The directory where GL/glew.h resides")
|
||||||
FIND_LIBRARY( GLEW_LIBRARY
|
FIND_LIBRARY( GLEW_LIBRARY
|
||||||
NAMES GLEW glew
|
NAMES GLEW glew
|
||||||
HINTS ${GLEW_DIR}/lib
|
HINTS ${GLEW_DIR}/lib
|
||||||
PATHS /usr/lib /usr/local/lib
|
PATHS /usr/lib /usr/local/lib /usr/pkg/lib
|
||||||
NO_DEFAULT_PATH
|
NO_DEFAULT_PATH
|
||||||
DOC "The GLEW library")
|
DOC "The GLEW library")
|
||||||
ENDIF (WIN32)
|
ENDIF (WIN32)
|
||||||
|
|
|
@ -105,10 +105,10 @@ bool create_wgl_dummy_context(OffscreenContext &ctx)
|
||||||
wc.style = CS_OWNDC;
|
wc.style = CS_OWNDC;
|
||||||
wc.lpfnWndProc = WndProc;
|
wc.lpfnWndProc = WndProc;
|
||||||
wc.hInstance = inst;
|
wc.hInstance = inst;
|
||||||
wc.lpszClassName = "OpenSCAD";
|
wc.lpszClassName = (LPCWSTR)"OpenSCAD";
|
||||||
RegisterClass( &wc );
|
RegisterClass( &wc );
|
||||||
|
|
||||||
HWND window = CreateWindow( "OpenSCAD", "OpenSCAD",
|
HWND window = CreateWindow( (LPCWSTR)"OpenSCAD", (LPCWSTR)"OpenSCAD",
|
||||||
WS_CAPTION | WS_POPUPWINDOW, //| WS_VISIBLE,
|
WS_CAPTION | WS_POPUPWINDOW, //| WS_VISIBLE,
|
||||||
0, 0, ctx.width, ctx.height, NULL, NULL, inst, NULL );
|
0, 0, ctx.width, ctx.height, NULL, NULL, inst, NULL );
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "ThrownTogetherRenderer.h"
|
#include "ThrownTogetherRenderer.h"
|
||||||
|
|
||||||
#include "csgterm.h"
|
#include "csgterm.h"
|
||||||
|
#include "csgtermnormalizer.h"
|
||||||
#include "OffscreenView.h"
|
#include "OffscreenView.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
@ -315,12 +316,8 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSG normalization
|
// CSG normalization
|
||||||
csgInfo.root_norm_term = root_raw_term;
|
CSGTermNormalizer normalizer;
|
||||||
while (1) {
|
csgInfo.root_norm_term = normalizer.normalize(root_raw_term);
|
||||||
shared_ptr<CSGTerm> n = CSGTerm::normalize(csgInfo.root_norm_term);
|
|
||||||
if (csgInfo.root_norm_term == n) break;
|
|
||||||
csgInfo.root_norm_term = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(csgInfo.root_norm_term);
|
assert(csgInfo.root_norm_term);
|
||||||
|
|
||||||
|
@ -333,11 +330,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
|
||||||
|
|
||||||
csgInfo.highlights_chain = new CSGChain();
|
csgInfo.highlights_chain = new CSGChain();
|
||||||
for (unsigned int i = 0; i < csgInfo.highlight_terms.size(); i++) {
|
for (unsigned int i = 0; i < csgInfo.highlight_terms.size(); i++) {
|
||||||
while (1) {
|
csgInfo.highlight_terms[i] = normalizer.normalize(csgInfo.highlight_terms[i]);
|
||||||
shared_ptr<CSGTerm> n = CSGTerm::normalize(csgInfo.highlight_terms[i]);
|
|
||||||
if (csgInfo.highlight_terms[i] == n) break;
|
|
||||||
csgInfo.highlight_terms[i] = n;
|
|
||||||
}
|
|
||||||
csgInfo.highlights_chain->import(csgInfo.highlight_terms[i]);
|
csgInfo.highlights_chain->import(csgInfo.highlight_terms[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,11 +340,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
|
||||||
|
|
||||||
csgInfo.background_chain = new CSGChain();
|
csgInfo.background_chain = new CSGChain();
|
||||||
for (unsigned int i = 0; i < csgInfo.background_terms.size(); i++) {
|
for (unsigned int i = 0; i < csgInfo.background_terms.size(); i++) {
|
||||||
while (1) {
|
csgInfo.background_terms[i] = normalizer.normalize(csgInfo.background_terms[i]);
|
||||||
shared_ptr<CSGTerm> n = CSGTerm::normalize(csgInfo.background_terms[i]);
|
|
||||||
if (csgInfo.background_terms[i] == n) break;
|
|
||||||
csgInfo.background_terms[i] = n;
|
|
||||||
}
|
|
||||||
csgInfo.background_chain->import(csgInfo.background_terms[i]);
|
csgInfo.background_chain->import(csgInfo.background_terms[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,10 +65,9 @@ string dumptree(const Tree &tree, const AbstractNode &node)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef _MSC_VER
|
||||||
_set_output_format(_TWO_DIGIT_EXPONENT);
|
_set_output_format(_TWO_DIGIT_EXPONENT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
fprintf(stderr, "Usage: %s <file.scad> <output.txt>\n", argv[0]);
|
fprintf(stderr, "Usage: %s <file.scad> <output.txt>\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -59,7 +59,7 @@ static void outfile_handler(const std::string &msg, void *userdata) {
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef _MSC_VER
|
||||||
_set_output_format(_TWO_DIGIT_EXPONENT);
|
_set_output_format(_TWO_DIGIT_EXPONENT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -29,4 +29,7 @@
|
||||||
multmatrix([[1, 0, 0, 22], [0, 1, 0, 11], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
multmatrix([[1, 0, 0, 22], [0, 1, 0, 11], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
cylinder($fn = 0, $fa = 12, $fs = 2, h = 15, r1 = 5, r2 = 5, center = false);
|
cylinder($fn = 0, $fa = 12, $fs = 2, h = 15, r1 = 5, r2 = 5, center = false);
|
||||||
}
|
}
|
||||||
|
multmatrix([[1, 0, 0, -10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
|
cylinder($fn = 6, $fa = 12, $fs = 2, h = 2, r1 = 3, r2 = 3, center = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
multmatrix([[1, 0, 0, 12], [0, 1, 0, 12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
multmatrix([[1, 0, 0, 12], [0, 1, 0, 12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
intersection() {
|
intersection() {
|
||||||
cube(size = [10, 10, 10], center = true);
|
cube(size = [10, 10, 10], center = true);
|
||||||
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7], [0, 0, 0, 1]]) {
|
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7.01], [0, 0, 0, 1]]) {
|
||||||
cylinder($fn = 0, $fa = 12, $fs = 2, h = 4, r1 = 4, r2 = 4, center = true);
|
cylinder($fn = 0, $fa = 12, $fs = 2, h = 4, r1 = 4, r2 = 4, center = true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
multmatrix([[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
multmatrix([[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
color([1, 0.713725, 0.756863, 1]) {
|
color([1, 0.713726, 0.756863, 1]) {
|
||||||
sphere($fn = 5, $fa = 12, $fs = 2, r = 0.8);
|
sphere($fn = 5, $fa = 12, $fs = 2, r = 0.8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
multmatrix([[1, 0, 0, 8], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
multmatrix([[1, 0, 0, 8], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
color([1, 0.498039, 0.313725, 1]) {
|
color([1, 0.498039, 0.313726, 1]) {
|
||||||
sphere($fn = 5, $fa = 12, $fs = 2, r = 0.8);
|
sphere($fn = 5, $fa = 12, $fs = 2, r = 0.8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
group() {
|
||||||
|
group() {
|
||||||
|
multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
|
group() {
|
||||||
|
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 0.7, r2 = 0.2, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
multmatrix([[1, 0, 0, 2], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
|
group() {
|
||||||
|
cylinder($fn = 10, $fa = 12, $fs = 2, h = 1, r1 = 0.5, r2 = 0.5, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cube(size = [1, 1, 1], center = true);
|
||||||
|
}
|
||||||
|
multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
|
||||||
|
multmatrix([[1, 0, 0, 4], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]);
|
||||||
|
multmatrix([[1, 0, 0, -2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
|
group() {
|
||||||
|
sphere($fn = 8, $fa = 12, $fs = 2, r = 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
multmatrix([[1, 0, 0, -2], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
|
group() {
|
||||||
|
difference() {
|
||||||
|
cube(size = [1, 1, 1], center = true);
|
||||||
|
cylinder($fn = 0, $fa = 12, $fs = 2, h = 2, r1 = 0.4, r2 = 0.4, center = true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
|
||||||
|
sphere($fn = 16, $fa = 12, $fs = 2, r = 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -61,7 +61,11 @@ def execute_and_redirect(cmd, params, outfile):
|
||||||
else: return retval
|
else: return retval
|
||||||
|
|
||||||
def get_normalized_text(filename):
|
def get_normalized_text(filename):
|
||||||
text = open(filename).read()
|
try:
|
||||||
|
f = open(filename)
|
||||||
|
text = f.read()
|
||||||
|
except:
|
||||||
|
text = ''
|
||||||
return text.strip("\r\n").replace("\r\n", "\n") + "\n"
|
return text.strip("\r\n").replace("\r\n", "\n") + "\n"
|
||||||
|
|
||||||
def compare_text(expected, actual):
|
def compare_text(expected, actual):
|
||||||
|
@ -71,8 +75,9 @@ def compare_default(resultfilename):
|
||||||
print >> sys.stderr, 'diff text compare: '
|
print >> sys.stderr, 'diff text compare: '
|
||||||
print >> sys.stderr, ' expected textfile: ', expectedfilename
|
print >> sys.stderr, ' expected textfile: ', expectedfilename
|
||||||
print >> sys.stderr, ' actual textfile: ', resultfilename
|
print >> sys.stderr, ' actual textfile: ', resultfilename
|
||||||
if not compare_text(expectedfilename, resultfilename):
|
if not compare_text(expectedfilename, resultfilename):
|
||||||
execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)
|
if resultfilename:
|
||||||
|
execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -110,7 +115,7 @@ def compare_png(resultfilename):
|
||||||
elif compare_method=='NCC':
|
elif compare_method=='NCC':
|
||||||
thresh = 0.95
|
thresh = 0.95
|
||||||
ncc_err = float(output.strip())
|
ncc_err = float(output.strip())
|
||||||
if ncc_err > thresh: return True
|
if ncc_err > thresh or ncc_err==0.0: return True
|
||||||
else: print >> sys.stderr, ncc_err, ' Images differ: NCC comparison < ', thresh
|
else: print >> sys.stderr, ncc_err, ' Images differ: NCC comparison < ', thresh
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -136,8 +141,13 @@ def run_test(testname, cmd, args):
|
||||||
outputname = os.path.normpath( outputname )
|
outputname = os.path.normpath( outputname )
|
||||||
|
|
||||||
outfile = open(outputname, "wb")
|
outfile = open(outputname, "wb")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
proc = subprocess.Popen([cmd] + args + [outputname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
if os.path.isfile(cmd+'.exe') and options.mingw_cross_env:
|
||||||
|
cmdline = ['wine']+[cmd+'.exe'] + args + [outputname]
|
||||||
|
else:
|
||||||
|
cmdline = [cmd] + args + [outputname]
|
||||||
|
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
errtext = proc.communicate()[1]
|
errtext = proc.communicate()[1]
|
||||||
if errtext != None and len(errtext) > 0:
|
if errtext != None and len(errtext) > 0:
|
||||||
print >> sys.stderr, "Error output: " + errtext
|
print >> sys.stderr, "Error output: " + errtext
|
||||||
|
@ -166,11 +176,11 @@ def usage():
|
||||||
print >> sys.stderr, " -s, --suffix=<suffix> Write -expected and -actual files with the given suffix instead of .txt"
|
print >> sys.stderr, " -s, --suffix=<suffix> Write -expected and -actual files with the given suffix instead of .txt"
|
||||||
print >> sys.stderr, " -t, --test=<name> Specify test name instead of deducting it from the argument"
|
print >> sys.stderr, " -t, --test=<name> Specify test name instead of deducting it from the argument"
|
||||||
print >> sys.stderr, " -c, --convexec=<name> Path to ImageMagick 'convert' executable"
|
print >> sys.stderr, " -c, --convexec=<name> Path to ImageMagick 'convert' executable"
|
||||||
|
print >> sys.stderr, " -x, --mingw-cross-env Mingw-cross-env cross compilation"
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Handle command-line arguments
|
# Handle command-line arguments
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(sys.argv[1:], "gs:c:t:m:", ["generate", "convexec=", "suffix=", "test=", "comparator="])
|
opts, args = getopt.getopt(sys.argv[1:], "gs:c:t:m:x", ["generate", "convexec=", "suffix=", "test=", "comparator=", "mingw-cross-env"])
|
||||||
except getopt.GetoptError, err:
|
except getopt.GetoptError, err:
|
||||||
usage()
|
usage()
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
@ -192,6 +202,8 @@ if __name__ == '__main__':
|
||||||
options.convert_exec = os.path.normpath( a )
|
options.convert_exec = os.path.normpath( a )
|
||||||
elif o in ("-m", "--comparator"):
|
elif o in ("-m", "--comparator"):
|
||||||
options.comparator = a
|
options.comparator = a
|
||||||
|
elif o in ("-x", "--mingw-cross-env"):
|
||||||
|
options.mingw_cross_env = True
|
||||||
|
|
||||||
# <cmdline-tool> and <argument>
|
# <cmdline-tool> and <argument>
|
||||||
if len(args) < 2:
|
if len(args) < 2:
|
||||||
|
|
21
version.pri
|
@ -1,7 +1,7 @@
|
||||||
# get VERSION from system date
|
# get VERSION from system date
|
||||||
|
|
||||||
isEmpty(VERSION) {
|
isEmpty(VERSION) {
|
||||||
win32-msvc*: {
|
win32-msvc*:!mingw-cross-env {
|
||||||
#
|
#
|
||||||
# Windows XP date command only has one argument, /t
|
# Windows XP date command only has one argument, /t
|
||||||
# and it can print the date in various localized formats.
|
# and it can print the date in various localized formats.
|
||||||
|
@ -51,17 +51,18 @@ isEmpty(VERSION) {
|
||||||
} else {
|
} else {
|
||||||
# Unix/Mac
|
# Unix/Mac
|
||||||
VERSION = $$system(date "+%Y.%m.%d")
|
VERSION = $$system(date "+%Y.%m.%d")
|
||||||
VERSION_SPLIT=$$split(VERSION, ".")
|
|
||||||
VERSION_YEAR=$$member(VERSION_SPLIT, 0)
|
|
||||||
VERSION_MONTH=$$member(VERSION_SPLIT, 1)
|
|
||||||
VERSION_DAY=$$member(VERSION_SPLIT, 2)
|
|
||||||
}
|
}
|
||||||
# Fix for problem with integers with leading zeros
|
|
||||||
# being interpreted by C++ as octals. Now they're doubles.
|
|
||||||
VERSION_YEAR=$${VERSION_YEAR}.0
|
|
||||||
VERSION_MONTH=$${VERSION_MONTH}.0
|
|
||||||
VERSION_DAY=$${VERSION_DAY}.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VERSION_SPLIT=$$split(VERSION, ".")
|
||||||
|
VERSION_YEAR=$$member(VERSION_SPLIT, 0)
|
||||||
|
VERSION_MONTH=$$member(VERSION_SPLIT, 1)
|
||||||
|
VERSION_DAY=$$member(VERSION_SPLIT, 2)
|
||||||
|
# Fix for problem with integers with leading zeros
|
||||||
|
# being interpreted by C++ as octals. Now they're doubles.
|
||||||
|
VERSION_YEAR=$${VERSION_YEAR}.0
|
||||||
|
VERSION_MONTH=$${VERSION_MONTH}.0
|
||||||
|
VERSION_DAY=$${VERSION_DAY}.0
|
||||||
|
|
||||||
DEFINES += OPENSCAD_VERSION=$$VERSION OPENSCAD_YEAR=$$VERSION_YEAR OPENSCAD_MONTH=$$VERSION_MONTH
|
DEFINES += OPENSCAD_VERSION=$$VERSION OPENSCAD_YEAR=$$VERSION_YEAR OPENSCAD_MONTH=$$VERSION_MONTH
|
||||||
!isEmpty(VERSION_DAY): DEFINES += OPENSCAD_DAY=$$VERSION_DAY
|
!isEmpty(VERSION_DAY): DEFINES += OPENSCAD_DAY=$$VERSION_DAY
|
||||||
|
|