summaryrefslogtreecommitdiff
path: root/tests/opencsgtest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/opencsgtest.cc')
-rw-r--r--tests/opencsgtest.cc368
1 files changed, 368 insertions, 0 deletions
diff --git a/tests/opencsgtest.cc b/tests/opencsgtest.cc
new file mode 100644
index 0000000..9381c54
--- /dev/null
+++ b/tests/opencsgtest.cc
@@ -0,0 +1,368 @@
+#include "openscad.h"
+#include "builtin.h"
+#include "context.h"
+#include "node.h"
+#include "module.h"
+#include "polyset.h"
+#include "Tree.h"
+#include "CSGTermRenderer.h"
+#include "CGALRenderer.h"
+#include "PolySetCGALRenderer.h"
+
+#include "csgterm.h"
+#include "render-opencsg.h"
+#include <GL/glew.h>
+#include "GLView.h"
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QSet>
+#include <QTimer>
+
+using std::cerr;
+using std::cout;
+
+QString commandline_commands;
+QString librarydir;
+QSet<QString> dependencies;
+const char *make_command = NULL;
+
+void handle_dep(QString filename)
+{
+ if (filename.startsWith("/"))
+ dependencies.insert(filename);
+ else
+ dependencies.insert(QDir::currentPath() + QString("/") + filename);
+ if (!QFile(filename).exists() && make_command) {
+ char buffer[4096];
+ snprintf(buffer, 4096, "%s '%s'", make_command, filename.replace("'", "'\\''").toUtf8().data());
+ system(buffer); // FIXME: Handle error
+ }
+}
+
+// static void renderfunc(void *vp)
+// {
+// glClearColor(1.0, 0.0, 0.0, 0.0);
+// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+// }
+
+struct CsgInfo
+{
+ CSGTerm *root_norm_term; // Normalized CSG products
+ class CSGChain *root_chain;
+ std::vector<CSGTerm*> highlight_terms;
+ CSGChain *highlights_chain;
+ std::vector<CSGTerm*> background_terms;
+ CSGChain *background_chain;
+ GLView *glview;
+};
+
+static void renderGLThrownTogetherChain(CSGChain *chain, bool highlight, bool background, bool fberror)
+{
+ glDepthFunc(GL_LEQUAL);
+ QHash<QPair<PolySet*,double*>,int> polySetVisitMark;
+ bool showEdges = false;
+ for (int i = 0; i < chain->polysets.size(); i++) {
+ if (polySetVisitMark[QPair<PolySet*,double*>(chain->polysets[i], chain->matrices[i])]++ > 0)
+ continue;
+ double *m = chain->matrices[i];
+ glPushMatrix();
+ glMultMatrixd(m);
+ int csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
+ if (highlight) {
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m);
+ if (showEdges) {
+ glDisable(GL_LIGHTING);
+ chain->polysets[i]->render_edges(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20));
+ glEnable(GL_LIGHTING);
+ }
+ } else if (background) {
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m);
+ if (showEdges) {
+ glDisable(GL_LIGHTING);
+ chain->polysets[i]->render_edges(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10));
+ glEnable(GL_LIGHTING);
+ }
+ } else if (fberror) {
+ if (highlight) {
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 20), m);
+ } else if (background) {
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode + 10), m);
+ } else {
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m);
+ }
+ } else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) {
+ glColor4d(m[16], m[17], m[18], m[19]);
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m);
+ if (showEdges) {
+ glDisable(GL_LIGHTING);
+ glColor4d((m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0);
+ chain->polysets[i]->render_edges(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode));
+ glEnable(GL_LIGHTING);
+ }
+ } else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) {
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m);
+ if (showEdges) {
+ glDisable(GL_LIGHTING);
+ chain->polysets[i]->render_edges(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode));
+ glEnable(GL_LIGHTING);
+ }
+ } else {
+ chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m);
+ if (showEdges) {
+ glDisable(GL_LIGHTING);
+ chain->polysets[i]->render_edges(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode));
+ glEnable(GL_LIGHTING);
+ }
+ }
+ glPopMatrix();
+ }
+}
+
+static void renderGLThrownTogether(void *vp)
+{
+ CsgInfo *csgInfo = (CsgInfo *)vp;
+ if (csgInfo->root_chain) {
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ renderGLThrownTogetherChain(csgInfo->root_chain, false, false, false);
+ glCullFace(GL_FRONT);
+ glColor3ub(255, 0, 255);
+ renderGLThrownTogetherChain(csgInfo->root_chain, false, false, true);
+ glDisable(GL_CULL_FACE);
+ }
+ if (csgInfo->background_chain)
+ renderGLThrownTogetherChain(csgInfo->background_chain, false, true, false);
+ if (csgInfo->highlights_chain)
+ renderGLThrownTogetherChain(csgInfo->highlights_chain, true, false, false);
+}
+
+static void renderGLviaOpenCSG(void *vp)
+{
+ CsgInfo *csgInfo = (CsgInfo *)vp;
+
+ if (csgInfo->root_chain) {
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glDepthFunc(GL_LEQUAL);
+ QHash<QPair<PolySet*,double*>,int> polySetVisitMark;
+ bool showEdges = false;
+ int i = 1;
+ double *m = csgInfo->root_chain->matrices[i];
+ glPushMatrix();
+ glMultMatrixd(m);
+ int csgmode = csgInfo->root_chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
+ csgInfo->root_chain->polysets[i]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m);
+ glPopMatrix();
+ }
+
+ // static bool glew_initialized = false;
+ // if (!glew_initialized) {
+ // glew_initialized = true;
+ // glewInit();
+ // }
+#ifdef ENABLE_MDI
+ OpenCSG::setContext(csgInfo->glview->opencsg_id);
+#endif
+ if (csgInfo->root_chain) {
+ renderCSGChainviaOpenCSG(csgInfo->root_chain, NULL, false, false);
+ GLint *shaderinfo = csgInfo->glview->shaderinfo;
+ if (!shaderinfo[0]) shaderinfo = NULL;
+ renderCSGChainviaOpenCSG(csgInfo->root_chain, NULL, false, false);
+ if (csgInfo->background_chain) {
+ renderCSGChainviaOpenCSG(csgInfo->background_chain, NULL, false, true);
+ }
+ if (csgInfo->highlights_chain) {
+ renderCSGChainviaOpenCSG(csgInfo->highlights_chain, NULL, true, false);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]);
+ exit(1);
+ }
+
+ const char *filename = argv[1];
+
+ initialize_builtin_functions();
+ initialize_builtin_modules();
+
+ QApplication app(argc, argv);
+
+ QDir original_path = QDir::current();
+
+ QString currentdir = QDir::currentPath();
+
+ QDir libdir(QApplication::instance()->applicationDirPath());
+#ifdef Q_WS_MAC
+ libdir.cd("../Resources"); // Libraries can be bundled
+ if (!libdir.exists("libraries")) libdir.cd("../../..");
+#elif defined(Q_OS_UNIX)
+ if (libdir.cd("../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../libraries")) {
+ librarydir = libdir.path();
+ } else
+#endif
+ if (libdir.cd("libraries")) {
+ librarydir = libdir.path();
+ }
+
+ Context root_ctx;
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
+ root_ctx.set_variable("$fn", Value(0.0));
+ root_ctx.set_variable("$fs", Value(1.0));
+ root_ctx.set_variable("$fa", Value(12.0));
+ root_ctx.set_variable("$t", Value(0.0));
+
+ Value zero3;
+ zero3.type = Value::VECTOR;
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ root_ctx.set_variable("$vpt", zero3);
+ root_ctx.set_variable("$vpr", zero3);
+
+
+ AbstractModule *root_module;
+ ModuleInstantiation root_inst;
+ AbstractNode *root_node;
+
+ QFileInfo fileInfo(filename);
+ handle_dep(filename);
+ FILE *fp = fopen(filename, "rt");
+ if (!fp) {
+ fprintf(stderr, "Can't open input file `%s'!\n", filename);
+ exit(1);
+ } else {
+ QString text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text += buffer;
+ }
+ fclose(fp);
+ root_module = parse((text+commandline_commands).toAscii().data(), fileInfo.absolutePath().toLocal8Bit(), false);
+ if (!root_module) {
+ exit(1);
+ }
+ }
+
+ QDir::setCurrent(fileInfo.absolutePath());
+
+ AbstractNode::resetIndexCounter();
+ root_node = root_module->evaluate(&root_ctx, &root_inst);
+
+ Tree tree(root_node);
+
+ QHash<std::string, CGAL_Nef_polyhedron> cache;
+ CGALRenderer cgalrenderer(cache, tree);
+ PolySetCGALRenderer psrenderer(cgalrenderer);
+ CSGTermRenderer renderer(tree);
+ CSGTerm *root_raw_term = renderer.renderCSGTerm(*root_node, NULL, NULL);
+
+ if (!root_raw_term) {
+ cerr << "Error: CSG generation failed! (no top level object found)\n";
+ return 1;
+ }
+
+ CsgInfo csgInfo;
+ csgInfo.root_norm_term = root_raw_term->link();
+
+ // CSG normalization
+ while (1) {
+ CSGTerm *n = csgInfo.root_norm_term->normalize();
+ csgInfo.root_norm_term->unlink();
+ if (csgInfo.root_norm_term == n)
+ break;
+ csgInfo.root_norm_term = n;
+ }
+
+ assert(csgInfo.root_norm_term);
+
+ csgInfo.root_chain = new CSGChain();
+ csgInfo.root_chain->import(csgInfo.root_norm_term);
+
+ if (csgInfo.highlight_terms.size() > 0) {
+ cerr << "Compiling highlights (" << " CSG Trees)...\n";
+
+ csgInfo.highlights_chain = new CSGChain();
+ for (unsigned int i = 0; i < csgInfo.highlight_terms.size(); i++) {
+ while (1) {
+ CSGTerm *n = csgInfo.highlight_terms[i]->normalize();
+ csgInfo.highlight_terms[i]->unlink();
+ if (csgInfo.highlight_terms[i] == n)
+ break;
+ csgInfo.highlight_terms[i] = n;
+ }
+ csgInfo.highlights_chain->import(csgInfo.highlight_terms[i]);
+ }
+ }
+
+ if (csgInfo.background_terms.size() > 0) {
+ cerr << "Compiling background (" << csgInfo.background_terms.size() << " CSG Trees)...\n";
+
+ csgInfo.background_chain = new CSGChain();
+ for (unsigned int i = 0; i < csgInfo.background_terms.size(); i++) {
+ while (1) {
+ CSGTerm *n = csgInfo.background_terms[i]->normalize();
+ csgInfo.background_terms[i]->unlink();
+ if (csgInfo.background_terms[i] == n)
+ break;
+ csgInfo.background_terms[i] = n;
+ }
+ csgInfo.background_chain->import(csgInfo.background_terms[i]);
+ }
+ }
+
+ QDir::setCurrent(original_path.absolutePath());
+
+ QGLFormat fmt = QGLFormat::defaultFormat();
+// fmt.setDirectRendering(false);
+// fmt.setDoubleBuffer(false);
+
+ csgInfo.glview = new GLView(fmt, NULL);
+ csgInfo.glview->makeCurrent();
+
+ glewInit();
+ cout << "GLEW version " << glewGetString(GLEW_VERSION) << "\n";
+ cout << (const char *)glGetString(GL_RENDERER) << "(" << (const char *)glGetString(GL_VENDOR) << ")\n"
+ << "OpenGL version " << (const char *)glGetString(GL_VERSION) << "\n";
+ cout << "Extensions: " << (const char *)glGetString(GL_EXTENSIONS) << "\n";
+
+
+ if (GLEW_ARB_framebuffer_object) {
+ cout << "ARB_FBO supported\n";
+ }
+ if (GLEW_EXT_framebuffer_object) {
+ cout << "EXT_FBO supported\n";
+ }
+ if (GLEW_EXT_packed_depth_stencil) {
+ cout << "EXT_packed_depth_stencil\n";
+ }
+
+// csgInfo.glview->setRenderFunc(renderGLThrownTogether, &csgInfo);
+ csgInfo.glview->setRenderFunc(renderGLviaOpenCSG, &csgInfo);
+ csgInfo.glview->show();
+ csgInfo.glview->hide();
+
+ QImage img = csgInfo.glview->grabFrameBuffer();
+ cout << "Image: " << img.width() << "x" << img.height() << " " << img.format() << "\n";
+ img.save("out.png");
+
+ destroy_builtin_functions();
+ destroy_builtin_modules();
+
+ return 0;
+}
contact: Jan Huwald // Impressum