Cleaned up progress handling, implemented cancel function. Needs more testing

git-svn-id: http://svn.clifford.at/openscad/trunk@420 b57f626f-c46c-0410-a088-ec61d464b74c
stl_dim
kintel 2010-02-09 13:48:09 +00:00
parent 66ac923976
commit c7b9a49c15
13 changed files with 320 additions and 354 deletions

View File

@ -86,7 +86,8 @@ HEADERS += src/CGAL_renderer.h \
src/openscad.h \
src/polyset.h \
src/printutils.h \
src/value.h
src/value.h \
src/progress.h
SOURCES += src/openscad.cc \
src/mainwin.cc \
@ -118,7 +119,8 @@ SOURCES += src/openscad.cc \
src/highlighter.cc \
src/printutils.cc \
src/nef2dxf.cc \
src/Preferences.cc
src/Preferences.cc \
src/progress.cc
macx {
HEADERS += src/AppleEvents.h \

View File

@ -68,6 +68,7 @@ private:
void load();
AbstractNode *find_root_tag(AbstractNode *n);
void compile(bool procevents);
void compileCSG(bool procevents);
bool maybeSave();
private slots:

View File

@ -31,6 +31,7 @@
#include "dxfdata.h"
#include "dxftess.h"
#include "polyset.h"
#include "progress.h"
#include "openscad.h" // get_fragments_from_r()
#include <sys/types.h>
@ -209,17 +210,6 @@ static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2,
}
}
static void report_func(const class AbstractNode*, void *vp, int mark)
{
QProgressDialog *pd = (QProgressDialog*)vp;
int v = (int)((mark*100.0) / progress_report_count);
pd->setValue(v < 100 ? v : 99);
QString label;
label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
pd->setLabelText(label);
QApplication::processEvents();
}
PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e rm) const
{
QString key = mk_cache_id();
@ -234,26 +224,9 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e rm) const
if (filename.isEmpty())
{
#ifdef ENABLE_CGAL
QTime t;
QProgressDialog *pd = NULL;
if (rm == RENDER_OPENCSG)
{
PRINT_NOCACHE("Processing uncached linear_extrude outline...");
QApplication::processEvents();
t.start();
pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
pd->setValue(0);
pd->setAutoClose(false);
pd->show();
QApplication::processEvents();
progress_report_prep((AbstractNode*)this, report_func, pd);
}
// Before extruding, union all (2D) children nodes
// to a single DxfData, then tessealte this into a PolySet
// to a single DxfData, then tesselate this into a PolySet
CGAL_Nef_polyhedron N;
N.dim = 2;
foreach(AbstractNode * v, children) {
@ -263,12 +236,6 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e rm) const
}
dxf = new DxfData(N);
if (rm == RENDER_OPENCSG) {
progress_report_fin();
int s = t.elapsed() / 1000;
PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
delete pd;
}
#else // ENABLE_CGAL
PRINT("WARNING: Found linear_extrude() statement without dxf file but compiled without CGAL support!");
dxf = new DxfData();

View File

@ -30,6 +30,7 @@
#include "builtin.h"
#include "polyset.h"
#include "dxfdata.h"
#include "progress.h"
#include "openscad.h" // get_fragments_from_r()
#include <sys/types.h>
@ -112,17 +113,6 @@ void register_builtin_dxf_rotate_extrude()
builtin_modules["rotate_extrude"] = new DxfRotateExtrudeModule();
}
static void report_func(const class AbstractNode*, void *vp, int mark)
{
QProgressDialog *pd = (QProgressDialog*)vp;
int v = (int)((mark*100.0) / progress_report_count);
pd->setValue(v < 100 ? v : 99);
QString label;
label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
pd->setLabelText(label);
QApplication::processEvents();
}
PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e rm) const
{
QString key = mk_cache_id();
@ -137,24 +127,6 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e rm) const
if (filename.isEmpty())
{
#ifdef ENABLE_CGAL
QTime t;
QProgressDialog *pd;
if (rm == RENDER_OPENCSG)
{
PRINT_NOCACHE("Processing uncached rotate_extrude outline...");
QApplication::processEvents();
t.start();
pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
pd->setValue(0);
pd->setAutoClose(false);
pd->show();
QApplication::processEvents();
progress_report_prep((AbstractNode*)this, report_func, pd);
}
CGAL_Nef_polyhedron N;
N.dim = 2;
foreach(AbstractNode * v, children) {
@ -164,12 +136,6 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e rm) const
}
dxf = new DxfData(N);
if (rm == RENDER_OPENCSG) {
progress_report_fin();
int s = t.elapsed() / 1000;
PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
delete pd;
}
#else // ENABLE_CGAL
PRINT("WARNING: Found rotate_extrude() statement without dxf file but compiled without CGAL support!");
dxf = new DxfData();

View File

@ -37,6 +37,7 @@
#include "export.h"
#include "builtin.h"
#include "dxftess.h"
#include "progress.h"
#include <QMenu>
#include <QTime>
@ -45,6 +46,7 @@
#include <QFileDialog>
#include <QApplication>
#include <QProgressDialog>
#include <QProgressBar>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
@ -336,6 +338,20 @@ MainWindow::~MainWindow()
#endif
}
typedef QPair<QProgressBar*, QProgressDialog*> ProgressData;
static void report_func(const class AbstractNode*, void *vp, int mark)
{
ProgressData *progpair = static_cast<ProgressData*>(vp);
int v = (int)((mark*100.0) / progress_report_count);
progpair->first->setValue(v < 100 ? v : 99);
QString label;
label.sprintf("Rendering Polygon Mesh (%d/%d)", mark, progress_report_count);
progpair->second->setLabelText(label);
QApplication::processEvents();
if (progpair->second->wasCanceled()) throw ProgressCancelException();
}
/*!
Requests to open a file from an external event, e.g. by double-clicking a filename.
*/
@ -458,6 +474,9 @@ AbstractNode *MainWindow::find_root_tag(AbstractNode *n)
return NULL;
}
/*!
Parse and evaluate the design -> this->root_node
*/
void MainWindow::compile(bool procevents)
{
PRINT("Parsing design (AST generation)...");
@ -554,7 +573,7 @@ void MainWindow::compile(bool procevents)
if (procevents)
QApplication::processEvents();
AbstractNode::idx_counter = 1;
AbstractNode::resetIndexCounter();
root_inst = ModuleInstantiation();
absolute_root_node = root_module->evaluate(&root_ctx, &root_inst);
@ -567,89 +586,6 @@ void MainWindow::compile(bool procevents)
}
root_node->dump("");
PRINT("Compiling design (CSG Products generation)...");
if (procevents)
QApplication::processEvents();
double m[20];
for (int i = 0; i < 16; i++)
m[i] = i % 5 == 0 ? 1.0 : 0.0;
for (int i = 16; i < 20; i++)
m[i] = -1;
// Main CSG evaluation
root_raw_term = root_node->render_csg_term(m, &highlight_terms, &background_terms);
if (!root_raw_term)
goto fail;
PRINT("Compiling design (CSG Products normalization)...");
if (procevents)
QApplication::processEvents();
root_norm_term = root_raw_term->link();
// CSG normalization
while (1) {
CSGTerm *n = root_norm_term->normalize();
root_norm_term->unlink();
if (root_norm_term == n)
break;
root_norm_term = n;
}
if (!root_norm_term)
goto fail;
root_chain = new CSGChain();
root_chain->import(root_norm_term);
if (root_chain->polysets.size() > 1000) {
PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size());
PRINTF("WARNING: OpenCSG rendering has been disabled.");
} else {
enableOpenCSG = true;
}
if (highlight_terms.size() > 0)
{
PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size());
if (procevents)
QApplication::processEvents();
highlights_chain = new CSGChain();
for (int i = 0; i < highlight_terms.size(); i++) {
while (1) {
CSGTerm *n = highlight_terms[i]->normalize();
highlight_terms[i]->unlink();
if (highlight_terms[i] == n)
break;
highlight_terms[i] = n;
}
highlights_chain->import(highlight_terms[i]);
}
}
if (background_terms.size() > 0)
{
PRINTF("Compiling background (%d CSG Trees)...", background_terms.size());
if (procevents)
QApplication::processEvents();
background_chain = new CSGChain();
for (int i = 0; i < background_terms.size(); i++) {
while (1) {
CSGTerm *n = background_terms[i]->normalize();
background_terms[i]->unlink();
if (background_terms[i] == n)
break;
background_terms[i] = n;
}
background_chain->import(background_terms[i]);
}
}
if (1) {
PRINT("Compilation finished.");
if (procevents)
@ -677,6 +613,126 @@ fail:
}
}
/*!
Generates CSG tree for OpenCSG evaluation.
Assumes that the design has been parsed and evaluated
*/
void MainWindow::compileCSG(bool procevents)
{
assert(this->root_node);
PRINT("Compiling design (CSG Products generation)...");
if (procevents)
QApplication::processEvents();
double m[20];
for (int i = 0; i < 16; i++)
m[i] = i % 5 == 0 ? 1.0 : 0.0;
for (int i = 16; i < 20; i++)
m[i] = -1;
// Main CSG evaluation
QTime t;
t.start();
QProgressDialog *pd = new QProgressDialog("Rendering CSG products...", "Cancel", 0, 100);
QProgressBar *bar = new QProgressBar(pd);
bar->setRange(0, 100);
bar->setValue(0);
pd->setBar(bar);
pd->setAutoClose(false);
pd->show();
ProgressData progpair(bar, pd);
QApplication::processEvents();
progress_report_prep(root_node, report_func, &progpair);
try {
root_raw_term = root_node->render_csg_term(m, &highlight_terms, &background_terms);
if (!root_raw_term) {
PRINT("ERROR: CSG generation failed! (no top level object found)");
if (procevents)
QApplication::processEvents();
}
}
catch (ProgressCancelException e) {
}
progress_report_fin();
delete pd;
if (root_raw_term) {
PRINT("Compiling design (CSG Products normalization)...");
if (procevents)
QApplication::processEvents();
root_norm_term = root_raw_term->link();
// CSG normalization
while (1) {
CSGTerm *n = root_norm_term->normalize();
root_norm_term->unlink();
if (root_norm_term == n)
break;
root_norm_term = n;
}
assert(root_norm_term);
root_chain = new CSGChain();
root_chain->import(root_norm_term);
if (root_chain->polysets.size() > 1000) {
PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size());
PRINTF("WARNING: OpenCSG rendering has been disabled.");
} else {
enableOpenCSG = true;
}
if (highlight_terms.size() > 0)
{
PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size());
if (procevents)
QApplication::processEvents();
highlights_chain = new CSGChain();
for (int i = 0; i < highlight_terms.size(); i++) {
while (1) {
CSGTerm *n = highlight_terms[i]->normalize();
highlight_terms[i]->unlink();
if (highlight_terms[i] == n)
break;
highlight_terms[i] = n;
}
highlights_chain->import(highlight_terms[i]);
}
}
if (background_terms.size() > 0)
{
PRINTF("Compiling background (%d CSG Trees)...", background_terms.size());
if (procevents)
QApplication::processEvents();
background_chain = new CSGChain();
for (int i = 0; i < background_terms.size(); i++) {
while (1) {
CSGTerm *n = background_terms[i]->normalize();
background_terms[i]->unlink();
if (background_terms[i] == n)
break;
background_terms[i] = n;
}
background_chain->import(background_terms[i]);
}
}
PRINT("CSG generation finished.");
int s = t.elapsed() / 1000;
PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
if (procevents)
QApplication::processEvents();
}
}
void MainWindow::actionNew()
{
#ifdef ENABLE_MDI
@ -909,6 +965,7 @@ void MainWindow::actionReloadCompile()
current_win = this;
compile(true);
if (this->root_node) compileCSG(true);
#ifdef ENABLE_OPENCSG
if (!(viewActionOpenCSG->isVisible() && viewActionOpenCSG->isChecked()) &&
@ -929,6 +986,7 @@ void MainWindow::actionCompile()
console->clear();
compile(!viewActionAnimate->isChecked());
if (this->root_node) compileCSG(!viewActionAnimate->isChecked());
// Go to non-CGAL view mode
if (!viewActionOpenCSG->isChecked() && !viewActionThrownTogether->isChecked()) {
@ -952,17 +1010,6 @@ void MainWindow::actionCompile()
#ifdef ENABLE_CGAL
static void report_func(const class AbstractNode*, void *vp, int mark)
{
QProgressDialog *pd = (QProgressDialog*)vp;
int v = (int)((mark*100.0) / progress_report_count);
pd->setValue(v < 100 ? v : 99);
QString label;
label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
pd->setLabelText(label);
QApplication::processEvents();
}
void MainWindow::actionRenderCGAL()
{
current_win = this;
@ -985,72 +1032,85 @@ void MainWindow::actionRenderCGAL()
QTime t;
t.start();
QProgressDialog *pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
pd->setValue(0);
QProgressDialog *pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", "Cancel", 0, 100);
QProgressBar *bar = new QProgressBar(pd);
bar->setRange(0, 100);
bar->setValue(0);
pd->setBar(bar);
pd->setAutoClose(false);
pd->show();
// this->statusBar()->addPermanentWidget(bar);
ProgressData progpair(bar, pd);
QApplication::processEvents();
progress_report_prep(root_node, report_func, pd);
this->root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron());
progress_report_prep(root_node, report_func, &progpair);
try {
this->root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron());
}
catch (ProgressCancelException e) {
}
progress_report_fin();
// this->statusBar()->removeWidget(bar);
PRINTF("Number of vertices currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.totalCost());
PRINTF("Number of objects currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.size());
QApplication::processEvents();
if (this->root_N)
{
PRINTF("Number of vertices currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.totalCost());
PRINTF("Number of objects currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.size());
QApplication::processEvents();
if (this->root_N->dim == 2) {
PRINTF(" Top level object is a 2D object:");
QApplication::processEvents();
PRINTF(" Empty: %6s", this->root_N->p2.is_empty() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Plane: %6s", this->root_N->p2.is_plane() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Vertices: %6d", (int)this->root_N->p2.explorer().number_of_vertices());
QApplication::processEvents();
PRINTF(" Halfedges: %6d", (int)this->root_N->p2.explorer().number_of_halfedges());
QApplication::processEvents();
PRINTF(" Edges: %6d", (int)this->root_N->p2.explorer().number_of_edges());
QApplication::processEvents();
PRINTF(" Faces: %6d", (int)this->root_N->p2.explorer().number_of_faces());
QApplication::processEvents();
PRINTF(" FaceCycles: %6d", (int)this->root_N->p2.explorer().number_of_face_cycles());
QApplication::processEvents();
PRINTF(" ConnComp: %6d", (int)this->root_N->p2.explorer().number_of_connected_components());
QApplication::processEvents();
if (this->root_N->dim == 2) {
PRINTF(" Top level object is a 2D object:");
QApplication::processEvents();
PRINTF(" Empty: %6s", this->root_N->p2.is_empty() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Plane: %6s", this->root_N->p2.is_plane() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Vertices: %6d", (int)this->root_N->p2.explorer().number_of_vertices());
QApplication::processEvents();
PRINTF(" Halfedges: %6d", (int)this->root_N->p2.explorer().number_of_halfedges());
QApplication::processEvents();
PRINTF(" Edges: %6d", (int)this->root_N->p2.explorer().number_of_edges());
QApplication::processEvents();
PRINTF(" Faces: %6d", (int)this->root_N->p2.explorer().number_of_faces());
QApplication::processEvents();
PRINTF(" FaceCycles: %6d", (int)this->root_N->p2.explorer().number_of_face_cycles());
QApplication::processEvents();
PRINTF(" ConnComp: %6d", (int)this->root_N->p2.explorer().number_of_connected_components());
QApplication::processEvents();
}
if (this->root_N->dim == 3) {
PRINTF(" Top level object is a 3D object:");
PRINTF(" Simple: %6s", this->root_N->p3.is_simple() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Valid: %6s", this->root_N->p3.is_valid() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Vertices: %6d", (int)this->root_N->p3.number_of_vertices());
QApplication::processEvents();
PRINTF(" Halfedges: %6d", (int)this->root_N->p3.number_of_halfedges());
QApplication::processEvents();
PRINTF(" Edges: %6d", (int)this->root_N->p3.number_of_edges());
QApplication::processEvents();
PRINTF(" Halffacets: %6d", (int)this->root_N->p3.number_of_halffacets());
QApplication::processEvents();
PRINTF(" Facets: %6d", (int)this->root_N->p3.number_of_facets());
QApplication::processEvents();
PRINTF(" Volumes: %6d", (int)this->root_N->p3.number_of_volumes());
QApplication::processEvents();
}
int s = t.elapsed() / 1000;
PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
if (!viewActionCGALSurfaces->isChecked() && !viewActionCGALGrid->isChecked()) {
viewModeCGALSurface();
} else {
screen->updateGL();
}
PRINT("Rendering finished.");
}
if (this->root_N->dim == 3) {
PRINTF(" Top level object is a 3D object:");
PRINTF(" Simple: %6s", this->root_N->p3.is_simple() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Valid: %6s", this->root_N->p3.is_valid() ? "yes" : "no");
QApplication::processEvents();
PRINTF(" Vertices: %6d", (int)this->root_N->p3.number_of_vertices());
QApplication::processEvents();
PRINTF(" Halfedges: %6d", (int)this->root_N->p3.number_of_halfedges());
QApplication::processEvents();
PRINTF(" Edges: %6d", (int)this->root_N->p3.number_of_edges());
QApplication::processEvents();
PRINTF(" Halffacets: %6d", (int)this->root_N->p3.number_of_halffacets());
QApplication::processEvents();
PRINTF(" Facets: %6d", (int)this->root_N->p3.number_of_facets());
QApplication::processEvents();
PRINTF(" Volumes: %6d", (int)this->root_N->p3.number_of_volumes());
QApplication::processEvents();
}
int s = t.elapsed() / 1000;
PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
if (!viewActionCGALSurfaces->isChecked() && !viewActionCGALGrid->isChecked()) {
viewModeCGALSurface();
} else {
screen->updateGL();
}
PRINT("Rendering finished.");
delete pd;
current_win = NULL;
}

View File

@ -27,6 +27,8 @@
#include "node.h"
#include "module.h"
#include "csgterm.h"
#include "progress.h"
#include "polyset.h"
#include <QRegExp>
int AbstractNode::idx_counter;
@ -55,7 +57,7 @@ QString AbstractNode::mk_cache_id() const
#ifdef ENABLE_CGAL
AbstractNode::cgal_nef_cache_entry::cgal_nef_cache_entry(CGAL_Nef_polyhedron N) :
AbstractNode::cgal_nef_cache_entry::cgal_nef_cache_entry(const CGAL_Nef_polyhedron &N) :
N(N), msg(print_messages_stack.last()) { };
QCache<QString, AbstractNode::cgal_nef_cache_entry> AbstractNode::cgal_nef_cache(100000);
@ -167,35 +169,64 @@ QString AbstractIntersectionNode::dump(QString indent) const
return dump_cache;
}
int progress_report_count;
void (*progress_report_f)(const class AbstractNode*, void*, int);
void *progress_report_vp;
void AbstractNode::progress_prepare()
{
foreach (AbstractNode *v, children)
v->progress_prepare();
progress_mark = ++progress_report_count;
this->progress_mark = ++progress_report_count;
}
void AbstractNode::progress_report() const
{
if (progress_report_f)
progress_report_f(this, progress_report_vp, progress_mark);
progress_update(this, this->progress_mark);
}
void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *vp, int mark), void *vp)
#ifdef ENABLE_CGAL
CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const
{
progress_report_count = 0;
progress_report_f = f;
progress_report_vp = vp;
root->progress_prepare();
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
progress_report();
PRINT(cgal_nef_cache[cache_id]->msg);
return cgal_nef_cache[cache_id]->N;
}
print_messages_push();
PolySet *ps = render_polyset(RENDER_CGAL);
try {
CGAL_Nef_polyhedron N = ps->render_cgal_nef_polyhedron();
cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());
print_messages_pop();
progress_report();
ps->unlink();
return N;
}
catch (...) { // Don't leak the PolySet on ProgressCancelException
ps->unlink();
throw;
}
}
void progress_report_fin()
#endif /* ENABLE_CGAL */
CSGTerm *AbstractPolyNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
progress_report_count = 0;
progress_report_f = NULL;
progress_report_vp = NULL;
PolySet *ps = render_polyset(RENDER_OPENCSG);
return render_csg_term_from_ps(m, highlights, background, ps, modinst, idx);
}
CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx)
{
CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx));
if (modinst->tag_highlight && highlights)
highlights->append(t->link());
if (modinst->tag_background && background) {
background->append(t);
return NULL;
}
return t;
}

View File

@ -17,7 +17,10 @@ void progress_report_fin();
class AbstractNode
{
static int idx_counter; // Node instantiation index
public:
static void resetIndexCounter() { idx_counter = 1; }
QVector<AbstractNode*> children;
const class ModuleInstantiation *modinst;
@ -26,7 +29,6 @@ public:
void progress_report() const;
int idx;
static int idx_counter;
QString dump_cache;
AbstractNode(const ModuleInstantiation *mi);
@ -36,7 +38,7 @@ public:
struct cgal_nef_cache_entry {
CGAL_Nef_polyhedron N;
QString msg;
cgal_nef_cache_entry(CGAL_Nef_polyhedron N);
cgal_nef_cache_entry(const CGAL_Nef_polyhedron &N);
};
static QCache<QString, cgal_nef_cache_entry> cgal_nef_cache;
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
@ -64,7 +66,7 @@ public:
RENDER_OPENCSG
};
AbstractPolyNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
virtual class PolySet *render_polyset(render_mode_e mode) const;
virtual class PolySet *render_polyset(render_mode_e mode) const = 0;
#ifdef ENABLE_CGAL
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif

View File

@ -227,7 +227,7 @@ int main(int argc, char **argv)
QString original_path = QDir::currentPath();
QDir::setCurrent(fileInfo.absolutePath());
AbstractNode::idx_counter = 1;
AbstractNode::resetIndexCounter();
root_node = root_module->evaluate(&root_ctx, &root_inst);
CGAL_Nef_polyhedron *root_N;

View File

@ -24,9 +24,6 @@
*/
#include "polyset.h"
#include "node.h"
#include "module.h"
#include "csgterm.h"
#include "printutils.h"
#include "Preferences.h"
@ -666,52 +663,3 @@ CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const
#endif /* ENABLE_CGAL */
PolySet *AbstractPolyNode::render_polyset(render_mode_e) const
{
return NULL;
}
#ifdef ENABLE_CGAL
CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const
{
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
progress_report();
PRINT(cgal_nef_cache[cache_id]->msg);
return cgal_nef_cache[cache_id]->N;
}
print_messages_push();
PolySet *ps = render_polyset(RENDER_CGAL);
CGAL_Nef_polyhedron N = ps->render_cgal_nef_polyhedron();
cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());
print_messages_pop();
progress_report();
ps->unlink();
return N;
}
#endif /* ENABLE_CGAL */
CSGTerm *AbstractPolyNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
PolySet *ps = render_polyset(RENDER_OPENCSG);
return render_csg_term_from_ps(m, highlights, background, ps, modinst, idx);
}
CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx)
{
CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx));
if (modinst->tag_highlight && highlights)
highlights->append(t->link());
if (modinst->tag_background && background) {
background->append(t);
return NULL;
}
return t;
}

28
src/progress.cc Normal file
View File

@ -0,0 +1,28 @@
#include "progress.h"
#include "node.h"
int progress_report_count;
void (*progress_report_f)(const class AbstractNode*, void*, int);
void *progress_report_userdata;
void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *userdata, int mark), void *userdata)
{
progress_report_count = 0;
progress_report_f = f;
progress_report_userdata = userdata;
root->progress_prepare();
}
void progress_report_fin()
{
progress_report_count = 0;
progress_report_f = NULL;
progress_report_userdata = NULL;
}
void progress_update(const AbstractNode *node, int mark)
{
if (progress_report_f)
progress_report_f(node, progress_report_userdata, mark);
}

16
src/progress.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef PROGRESS_H_
#define PROGRESS_H_
// Reset to 0 in _prep() and increased for each Node instance in progress_prepare()
extern int progress_report_count;
extern void (*progress_report_f)(const class AbstractNode*, void*, int);
extern void *progress_report_userdata;
void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *userdata, int mark), void *userdata);
void progress_report_fin();
void progress_update(const AbstractNode *node, int mark);
class ProgressCancelException { };
#endif

View File

@ -32,6 +32,7 @@
#include "dxftess.h"
#include "polyset.h"
#include "export.h"
#include "progress.h"
#include <sys/types.h>
#include <sys/stat.h>
@ -95,17 +96,6 @@ void register_builtin_projection()
#ifdef ENABLE_CGAL
static void report_func(const class AbstractNode*, void *vp, int mark)
{
QProgressDialog *pd = (QProgressDialog*)vp;
int v = (int)((mark*100.0) / progress_report_count);
pd->setValue(v < 100 ? v : 99);
QString label;
label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
pd->setLabelText(label);
QApplication::processEvents();
}
PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
{
QString key = mk_cache_id();
@ -116,24 +106,6 @@ PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
print_messages_push();
QTime t;
QProgressDialog *pd = NULL;
if (rm == RENDER_OPENCSG)
{
PRINT_NOCACHE("Processing uncached projection body...");
QApplication::processEvents();
t.start();
pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
pd->setValue(0);
pd->setAutoClose(false);
pd->show();
QApplication::processEvents();
progress_report_prep((AbstractNode*)this, report_func, pd);
}
CGAL_Nef_polyhedron N;
N.dim = 3;
foreach(AbstractNode *v, this->children) {
@ -142,13 +114,6 @@ PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
N.p3 += v->render_cgal_nef_polyhedron().p3;
}
if (rm == RENDER_OPENCSG) {
progress_report_fin();
int s = t.elapsed() / 1000;
PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
delete pd;
}
PolySet *ps = new PolySet();
ps->convexity = this->convexity;
ps->is2d = true;

View File

@ -32,6 +32,7 @@
#include "csgterm.h"
#include "builtin.h"
#include "printutils.h"
#include "progress.h"
#ifdef ENABLE_CGAL
# include "cgal.h"
#endif
@ -124,17 +125,6 @@ CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const
return N;
}
static void report_func(const class AbstractNode*, void *vp, int mark)
{
QProgressDialog *pd = (QProgressDialog*)vp;
int v = (int)((mark*100.0) / progress_report_count);
pd->setValue(v < 100 ? v : 99);
QString label;
label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
pd->setLabelText(label);
QApplication::processEvents();
}
CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
QString key = mk_cache_id();
@ -162,20 +152,10 @@ CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights
QTime t;
t.start();
QProgressDialog *pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
pd->setValue(0);
pd->setAutoClose(false);
pd->show();
QApplication::processEvents();
progress_report_prep((AbstractNode*)this, report_func, pd);
N = this->render_cgal_nef_polyhedron();
progress_report_fin();
int s = t.elapsed() / 1000;
PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
delete pd;
}
PolySet *ps = NULL;