mirror of https://github.com/vitalif/openscad
Merge branch 'master' into visitor
Conflicts: src/GLView.h src/glview.cc src/mainwin.cc src/render-opencsg.ccstl_dim
commit
6882228058
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -49,7 +49,6 @@ o non-convex minkowski example from chrysn fails with an exception
|
|||
USER INTERFACE
|
||||
--------------
|
||||
o Preferences
|
||||
- Remember settings done in menus between sessions (automatic reload, perspective, show*, hide*)
|
||||
- Beautify color schemes
|
||||
- Color schemes read from file
|
||||
- Color scheme editor
|
||||
|
@ -57,7 +56,6 @@ o Preferences
|
|||
- pointsize
|
||||
- OpenGL params
|
||||
- Default language feature settings
|
||||
- Auto-view CSG/thrown together on load
|
||||
- Make the library search path configurable?
|
||||
o MDI
|
||||
- Think about how to do MDI the right way
|
||||
|
|
|
@ -3,8 +3,8 @@ opencsg {
|
|||
CONFIG += glew
|
||||
include(glew.pri)
|
||||
|
||||
HEADERS += src/render-opencsg.h
|
||||
SOURCES += src/render-opencsg.cc
|
||||
HEADERS += src/opencsgrenderer.h
|
||||
SOURCES += src/opencsgrenderer.cc
|
||||
|
||||
isEmpty(DEPLOYDIR) {
|
||||
# Optionally specify location of OpenCSG using the
|
||||
|
|
24
openscad.pro
24
openscad.pro
|
@ -118,7 +118,11 @@ include(boost.pri)
|
|||
FORMS += src/MainWindow.ui \
|
||||
src/Preferences.ui
|
||||
|
||||
HEADERS += src/CGAL_renderer.h \
|
||||
HEADERS += src/renderer.h \
|
||||
src/cgalrenderer.h \
|
||||
src/throwntogetherrenderer.h \
|
||||
src/CGAL_renderer.h \
|
||||
src/OGL_helper.h \
|
||||
src/GLView.h \
|
||||
src/MainWindow.h \
|
||||
src/Preferences.h \
|
||||
|
@ -154,16 +158,18 @@ HEADERS += src/CGAL_renderer.h \
|
|||
src/traverser.h \
|
||||
src/nodecache.h \
|
||||
src/nodedumper.h \
|
||||
src/CGALRenderer.h \
|
||||
src/PolySetRenderer.h \
|
||||
src/PolySetCGALRenderer.h \
|
||||
src/CSGTermRenderer.h \
|
||||
src/CGALEvaluator.h \
|
||||
src/PolySetEvaluator.h \
|
||||
src/PolySetCGALEvaluator.h \
|
||||
src/CSGTermEvaluator.h \
|
||||
src/myqhash.h \
|
||||
src/Tree.h \
|
||||
src/mathc99.h
|
||||
|
||||
SOURCES += src/openscad.cc \
|
||||
src/mainwin.cc \
|
||||
src/cgalrenderer.cc \
|
||||
src/throwntogetherrenderer.cc \
|
||||
src/glview.cc \
|
||||
src/export.cc \
|
||||
src/value.cc \
|
||||
|
@ -201,10 +207,10 @@ SOURCES += src/openscad.cc \
|
|||
src/editor.cc \
|
||||
src/traverser.cc \
|
||||
src/nodedumper.cc \
|
||||
src/CGALRenderer.cc \
|
||||
src/PolySetRenderer.cc \
|
||||
src/PolySetCGALRenderer.cc \
|
||||
src/CSGTermRenderer.cc \
|
||||
src/CGALEvaluator.cc \
|
||||
src/PolySetEvaluator.cc \
|
||||
src/PolySetCGALEvaluator.cc \
|
||||
src/CSGTermEvaluator.cc \
|
||||
src/qhash.cc \
|
||||
src/Tree.cc \
|
||||
src/mathc99.cc
|
||||
|
|
|
@ -119,7 +119,9 @@ build_cgal()
|
|||
version=$1
|
||||
echo "Building CGAL" $version "..."
|
||||
cd $BASEDIR/src
|
||||
curl -O https://gforge.inria.fr/frs/download.php/27641/CGAL-$version.tar.gz
|
||||
rm -rf CGAL*
|
||||
curl -O https://gforge.inria.fr/frs/download.php/28500/CGAL-$version.tar.gz
|
||||
# curl -O https://gforge.inria.fr/frs/download.php/27641/CGAL-$version.tar.gz
|
||||
tar xzf CGAL-$version.tar.gz
|
||||
cd CGAL-$version
|
||||
# We build a static lib. Not really necessary, but it's well tested.
|
||||
|
@ -160,7 +162,8 @@ echo "Using basedir:" $BASEDIR
|
|||
mkdir -p $SRCDIR $DEPLOYDIR
|
||||
build_gmp 5.0.1
|
||||
build_mpfr 3.0.1
|
||||
build_boost 1.46.1
|
||||
build_cgal 3.7
|
||||
build_glew 1.5.8
|
||||
build_boost 1.47.0
|
||||
# NB! For CGAL, also update the actual download URL in the function
|
||||
build_cgal 3.8
|
||||
build_glew 1.6.0
|
||||
build_opencsg 1.3.0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "CGALRenderer.h"
|
||||
#include "CGALEvaluator.h"
|
||||
#include "visitor.h"
|
||||
#include "state.h"
|
||||
#include "module.h" // FIXME: Temporarily for ModuleInstantiation
|
||||
|
@ -21,17 +21,17 @@
|
|||
#include <assert.h>
|
||||
#include <QRegExp>
|
||||
|
||||
CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractNode &node)
|
||||
CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const AbstractNode &node)
|
||||
{
|
||||
if (!isCached(node)) {
|
||||
Traverser render(*this, node, Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
Traverser evaluate(*this, node, Traverser::PRE_AND_POSTFIX);
|
||||
evaluate.execute();
|
||||
assert(isCached(node));
|
||||
}
|
||||
return this->cache[this->tree.getString(node)];
|
||||
}
|
||||
|
||||
bool CGALRenderer::isCached(const AbstractNode &node) const
|
||||
bool CGALEvaluator::isCached(const AbstractNode &node) const
|
||||
{
|
||||
return this->cache.contains(this->tree.getString(node));
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ bool CGALRenderer::isCached(const AbstractNode &node) const
|
|||
Modifies target by applying op to target and src:
|
||||
target = target [op] src
|
||||
*/
|
||||
void CGALRenderer::process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CsgOp op)
|
||||
void CGALEvaluator::process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CsgOp op)
|
||||
{
|
||||
if (target.dim != 2 && target.dim != 3) {
|
||||
assert(false && "Dimension of Nef polyhedron must be 2 or 3");
|
||||
|
@ -92,7 +92,7 @@ void CGALRenderer::process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedro
|
|||
FIXME: Let caller insert into the cache since caller might modify the result
|
||||
(e.g. transform)
|
||||
*/
|
||||
void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp op)
|
||||
void CGALEvaluator::applyToChildren(const AbstractNode &node, CGALEvaluator::CsgOp op)
|
||||
{
|
||||
CGAL_Nef_polyhedron N;
|
||||
if (this->visitedchildren[node.index()].size() > 0) {
|
||||
|
@ -126,7 +126,7 @@ void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp
|
|||
o In postfix: addToParent()
|
||||
*/
|
||||
|
||||
Response CGALRenderer::visit(State &state, const AbstractNode &node)
|
||||
Response CGALEvaluator::visit(State &state, const AbstractNode &node)
|
||||
{
|
||||
if (state.isPrefix() && isCached(node)) return PruneTraversal;
|
||||
if (state.isPostfix()) {
|
||||
|
@ -136,7 +136,7 @@ Response CGALRenderer::visit(State &state, const AbstractNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
Response CGALRenderer::visit(State &state, const AbstractIntersectionNode &node)
|
||||
Response CGALEvaluator::visit(State &state, const AbstractIntersectionNode &node)
|
||||
{
|
||||
if (state.isPrefix() && isCached(node)) return PruneTraversal;
|
||||
if (state.isPostfix()) {
|
||||
|
@ -146,7 +146,7 @@ Response CGALRenderer::visit(State &state, const AbstractIntersectionNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
Response CGALRenderer::visit(State &state, const CsgNode &node)
|
||||
Response CGALEvaluator::visit(State &state, const CsgNode &node)
|
||||
{
|
||||
if (state.isPrefix() && isCached(node)) return PruneTraversal;
|
||||
if (state.isPostfix()) {
|
||||
|
@ -170,7 +170,7 @@ Response CGALRenderer::visit(State &state, const CsgNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
Response CGALRenderer::visit(State &state, const TransformNode &node)
|
||||
Response CGALEvaluator::visit(State &state, const TransformNode &node)
|
||||
{
|
||||
if (state.isPrefix() && isCached(node)) return PruneTraversal;
|
||||
if (state.isPostfix()) {
|
||||
|
@ -203,7 +203,7 @@ Response CGALRenderer::visit(State &state, const TransformNode &node)
|
|||
ps.is2d = true;
|
||||
dxf_tesselate(&ps, &dd, 0, true, false, 0);
|
||||
|
||||
N = renderCGALMesh(ps);
|
||||
N = evaluateCGALMesh(ps);
|
||||
ps.refcount = 0;
|
||||
}
|
||||
else if (N.dim == 3) {
|
||||
|
@ -220,7 +220,7 @@ Response CGALRenderer::visit(State &state, const TransformNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
// FIXME: RenderNode: Union over children + some magic
|
||||
// FIXME: EvaluateNode: Union over children + some magic
|
||||
// FIXME: CgaladvNode: Iterate over children. Special operation
|
||||
|
||||
// FIXME: Subtypes of AbstractPolyNode:
|
||||
|
@ -229,7 +229,7 @@ Response CGALRenderer::visit(State &state, const TransformNode &node)
|
|||
// DxfRotateExtrudeNode
|
||||
// (SurfaceNode)
|
||||
// (PrimitiveNode)
|
||||
Response CGALRenderer::visit(State &state, const AbstractPolyNode &node)
|
||||
Response CGALEvaluator::visit(State &state, const AbstractPolyNode &node)
|
||||
{
|
||||
if (state.isPrefix() && isCached(node)) return PruneTraversal;
|
||||
if (state.isPostfix()) {
|
||||
|
@ -238,10 +238,10 @@ Response CGALRenderer::visit(State &state, const AbstractPolyNode &node)
|
|||
applyToChildren(node, UNION);
|
||||
|
||||
// Then apply polyset operation
|
||||
PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_CGAL, &this->psrenderer);
|
||||
PolySet *ps = node.evaluate_polyset(AbstractPolyNode::RENDER_CGAL, &this->psevaluator);
|
||||
if (ps) {
|
||||
try {
|
||||
CGAL_Nef_polyhedron N = renderCGALMesh(*ps);
|
||||
CGAL_Nef_polyhedron N = evaluateCGALMesh(*ps);
|
||||
// print_messages_pop();
|
||||
node.progress_report();
|
||||
|
||||
|
@ -263,7 +263,7 @@ Response CGALRenderer::visit(State &state, const AbstractPolyNode &node)
|
|||
Adds ourself to out parent's list of traversed children.
|
||||
Call this for _every_ node which affects output during the postfix traversal.
|
||||
*/
|
||||
void CGALRenderer::addToParent(const State &state, const AbstractNode &node)
|
||||
void CGALEvaluator::addToParent(const State &state, const AbstractNode &node)
|
||||
{
|
||||
assert(state.isPostfix());
|
||||
this->visitedchildren.erase(node.index());
|
||||
|
@ -274,19 +274,19 @@ void CGALRenderer::addToParent(const State &state, const AbstractNode &node)
|
|||
|
||||
#if 0
|
||||
/*!
|
||||
Static function to render CGAL meshes.
|
||||
Static function to evaluate CGAL meshes.
|
||||
NB! This is just a support function used for development and debugging
|
||||
*/
|
||||
CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractPolyNode &node)
|
||||
CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const AbstractPolyNode &node)
|
||||
{
|
||||
// FIXME: Lookup Nef polyhedron in cache.
|
||||
|
||||
// print_messages_push();
|
||||
|
||||
PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_CGAL);
|
||||
PolySet *ps = node.evaluate_polyset(AbstractPolyNode::RENDER_CGAL);
|
||||
if (ps) {
|
||||
try {
|
||||
CGAL_Nef_polyhedron N = ps->renderCSGMesh();
|
||||
CGAL_Nef_polyhedron N = ps->evaluateCSGMesh();
|
||||
// FIXME: Insert into cache
|
||||
// print_messages_pop();
|
||||
node.progress_report();
|
||||
|
@ -389,7 +389,7 @@ public:
|
|||
|
||||
#endif /* ENABLE_CGAL */
|
||||
|
||||
CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const PolySet &ps)
|
||||
CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
|
||||
{
|
||||
if (ps.is2d)
|
||||
{
|
|
@ -1,11 +1,11 @@
|
|||
#ifndef CGALRENDERER_H_
|
||||
#define CGALRENDERER_H_
|
||||
#ifndef CGALEVALUATOR_H_
|
||||
#define CGALEVALUATOR_H_
|
||||
|
||||
#include "myqhash.h"
|
||||
#include "visitor.h"
|
||||
#include "Tree.h"
|
||||
#include "cgal.h"
|
||||
#include "PolySetCGALRenderer.h"
|
||||
#include "PolySetCGALEvaluator.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -19,13 +19,13 @@ using std::map;
|
|||
using std::list;
|
||||
using std::pair;
|
||||
|
||||
class CGALRenderer : public Visitor
|
||||
class CGALEvaluator : public Visitor
|
||||
{
|
||||
public:
|
||||
enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI, HULL};
|
||||
// FIXME: If a cache is not given, we need to fix this ourselves
|
||||
CGALRenderer(QHash<string, CGAL_Nef_polyhedron> &cache, const Tree &tree) : cache(cache), tree(tree), psrenderer(*this) {}
|
||||
virtual ~CGALRenderer() {}
|
||||
CGALEvaluator(QHash<string, CGAL_Nef_polyhedron> &cache, const Tree &tree) : cache(cache), tree(tree), psevaluator(*this) {}
|
||||
virtual ~CGALEvaluator() {}
|
||||
|
||||
virtual Response visit(State &state, const AbstractNode &node);
|
||||
virtual Response visit(State &state, const AbstractIntersectionNode &node);
|
||||
|
@ -33,16 +33,16 @@ public:
|
|||
virtual Response visit(State &state, const TransformNode &node);
|
||||
virtual Response visit(State &state, const AbstractPolyNode &node);
|
||||
|
||||
CGAL_Nef_polyhedron renderCGALMesh(const AbstractNode &node);
|
||||
CGAL_Nef_polyhedron renderCGALMesh(const PolySet &polyset);
|
||||
CGAL_Nef_polyhedron evaluateCGALMesh(const AbstractNode &node);
|
||||
CGAL_Nef_polyhedron evaluateCGALMesh(const PolySet &polyset);
|
||||
|
||||
const Tree &getTree() const { return this->tree; }
|
||||
|
||||
private:
|
||||
void addToParent(const State &state, const AbstractNode &node);
|
||||
bool isCached(const AbstractNode &node) const;
|
||||
void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CGALRenderer::CsgOp op);
|
||||
void applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp op);
|
||||
void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CGALEvaluator::CsgOp op);
|
||||
void applyToChildren(const AbstractNode &node, CGALEvaluator::CsgOp op);
|
||||
|
||||
string currindent;
|
||||
typedef list<pair<const AbstractNode *, string> > ChildList;
|
||||
|
@ -50,7 +50,7 @@ private:
|
|||
|
||||
QHash<string, CGAL_Nef_polyhedron> &cache;
|
||||
const Tree &tree;
|
||||
PolySetCGALRenderer psrenderer;
|
||||
PolySetCGALEvaluator psevaluator;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,660 +1,104 @@
|
|||
// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||||
// the terms of the Q Public License version 1.0.
|
||||
// See the file LICENSE.QPL distributed with CGAL.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Nef_3/include/CGAL/Nef_3/OGL_helper.h $
|
||||
// $Id: OGL_helper.h 44713 2008-08-01 15:38:58Z hachenb $
|
||||
//
|
||||
//
|
||||
// Author(s) : Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
|
||||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CGAL_NEF_OPENGL_HELPER_H
|
||||
#define CGAL_NEF_OPENGL_HELPER_H
|
||||
#ifndef CGAL_RENDERER_H
|
||||
#define CGAL_RENDERER_H
|
||||
|
||||
#include <CGAL/Nef_S2/OGL_base_object.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Nef_3/SNC_decorator.h>
|
||||
#include <qgl.h>
|
||||
#include <cstdlib>
|
||||
#include "OGL_helper.h"
|
||||
#undef CGAL_NEF3_MARKED_VERTEX_COLOR
|
||||
#undef CGAL_NEF3_MARKED_EDGE_COLOR
|
||||
#undef CGAL_NEF3_MARKED_FACET_COLOR
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CGAL_GLU_TESS_CALLBACK CALLBACK
|
||||
#else
|
||||
#define CGAL_GLU_TESS_CALLBACK
|
||||
#endif
|
||||
#undef CGAL_NEF3_UNMARKED_VERTEX_COLOR
|
||||
#undef CGAL_NEF3_UNMARKED_EDGE_COLOR
|
||||
#undef CGAL_NEF3_UNMARKED_FACET_COLOR
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif
|
||||
using CGAL::OGL::SNC_BOUNDARY;
|
||||
using CGAL::OGL::SNC_SKELETON;
|
||||
|
||||
#if defined __APPLE__ && !defined MAC_OS_X_VERSION_10_5
|
||||
#define CGAL_GLU_TESS_DOTS ...
|
||||
#else
|
||||
#define CGAL_GLU_TESS_DOTS
|
||||
#endif
|
||||
class Polyhedron : public CGAL::OGL::Polyhedron
|
||||
{
|
||||
public:
|
||||
|
||||
using namespace CGAL;
|
||||
using namespace CGAL::OGL;
|
||||
enum RenderColor {
|
||||
CGAL_NEF3_MARKED_VERTEX_COLOR,
|
||||
CGAL_NEF3_MARKED_EDGE_COLOR,
|
||||
CGAL_NEF3_MARKED_FACET_COLOR,
|
||||
CGAL_NEF3_UNMARKED_VERTEX_COLOR,
|
||||
CGAL_NEF3_UNMARKED_EDGE_COLOR,
|
||||
CGAL_NEF3_UNMARKED_FACET_COLOR,
|
||||
NUM_COLORS
|
||||
};
|
||||
|
||||
namespace OpenSCAD {
|
||||
Polyhedron() {
|
||||
setColor(CGAL_NEF3_MARKED_VERTEX_COLOR,0xb7,0xe8,0x5c);
|
||||
setColor(CGAL_NEF3_MARKED_EDGE_COLOR,0xab,0xd8,0x56);
|
||||
setColor(CGAL_NEF3_MARKED_FACET_COLOR,0x9d,0xcb,0x51);
|
||||
setColor(CGAL_NEF3_UNMARKED_VERTEX_COLOR,0xff,0xf6,0x7c);
|
||||
setColor(CGAL_NEF3_UNMARKED_EDGE_COLOR,0xff,0xec,0x5e);
|
||||
setColor(CGAL_NEF3_UNMARKED_FACET_COLOR,0xf9,0xd7,0x2c);
|
||||
}
|
||||
|
||||
namespace OGL {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Drawable double types:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> DKernel;
|
||||
typedef DKernel::Point_3 Double_point;
|
||||
typedef DKernel::Vector_3 Double_vector;
|
||||
typedef DKernel::Segment_3 Double_segment;
|
||||
typedef DKernel::Aff_transformation_3 Affine_3;
|
||||
|
||||
// DPoint = a double point including a mark
|
||||
class DPoint : public Double_point {
|
||||
bool m_;
|
||||
public:
|
||||
DPoint() {}
|
||||
DPoint(const Double_point& p, bool m) : Double_point(p) { m_ = m; }
|
||||
DPoint(const DPoint& p) : Double_point(p) { m_ = p.m_; }
|
||||
DPoint& operator=(const DPoint& p)
|
||||
{ Double_point::operator=(p); m_ = p.m_; return *this; }
|
||||
bool mark() const { return m_; }
|
||||
};
|
||||
|
||||
// DSegment = a double segment including a mark
|
||||
class DSegment : public Double_segment {
|
||||
bool m_;
|
||||
public:
|
||||
DSegment() {}
|
||||
DSegment(const Double_segment& s, bool m) : Double_segment(s) { m_ = m; }
|
||||
DSegment(const DSegment& s) : Double_segment(s) { m_ = s.m_; }
|
||||
DSegment& operator=(const DSegment& s)
|
||||
{ Double_segment::operator=(s); m_ = s.m_; return *this; }
|
||||
bool mark() const { return m_; }
|
||||
};
|
||||
|
||||
// Double_triple = a class that stores a triple of double
|
||||
// coordinates; we need a pointer to the coordinates in a C array
|
||||
// for OpenGL
|
||||
class Double_triple {
|
||||
typedef double* double_ptr;
|
||||
typedef const double* const_double_ptr;
|
||||
double coords_[3];
|
||||
public:
|
||||
Double_triple()
|
||||
{ coords_[0]=coords_[1]=coords_[2]=0.0; }
|
||||
Double_triple(double x, double y, double z)
|
||||
{ coords_[0]=x; coords_[1]=y; coords_[2]=z; }
|
||||
Double_triple(const Double_triple& t)
|
||||
{ coords_[0]=t.coords_[0];
|
||||
coords_[1]=t.coords_[1];
|
||||
coords_[2]=t.coords_[2];
|
||||
}
|
||||
Double_triple& operator=(const Double_triple& t)
|
||||
{ coords_[0]=t.coords_[0];
|
||||
coords_[1]=t.coords_[1];
|
||||
coords_[2]=t.coords_[2];
|
||||
return *this; }
|
||||
operator double_ptr() const
|
||||
{ return const_cast<Double_triple&>(*this).coords_; }
|
||||
double operator[](unsigned i)
|
||||
{ CGAL_assertion(i<3); return coords_[i]; }
|
||||
}; // Double_triple
|
||||
|
||||
static std::ostream& operator << (std::ostream& os,
|
||||
const Double_triple& t)
|
||||
{ os << "(" << t[0] << "," << t[1] << "," << t[2] << ")";
|
||||
return os; }
|
||||
|
||||
|
||||
// DFacet stores the facet cycle vertices in a continuus C array
|
||||
// of three double components, this is necessary due to the OpenGL
|
||||
// tesselator input format !
|
||||
class DFacet {
|
||||
typedef std::vector<Double_triple> Coord_vector;
|
||||
typedef std::vector<unsigned> Cycle_vector;
|
||||
Coord_vector coords_; // stores all vertex coordinates
|
||||
Cycle_vector fc_ends_; // stores entry points of facet cycles
|
||||
Double_triple normal_; // stores normal and mark of facet
|
||||
bool mark_;
|
||||
|
||||
public:
|
||||
typedef Coord_vector::iterator Coord_iterator;
|
||||
typedef Coord_vector::const_iterator Coord_const_iterator;
|
||||
|
||||
DFacet() {}
|
||||
|
||||
void push_back_vertex(double x, double y, double z)
|
||||
{ coords_.push_back(Double_triple(x,y,z)); }
|
||||
|
||||
DFacet(const DFacet& f)
|
||||
{ coords_ = f.coords_;
|
||||
fc_ends_ = f.fc_ends_;
|
||||
normal_ = f.normal_;
|
||||
mark_ = f.mark_;
|
||||
}
|
||||
|
||||
DFacet& operator=(const DFacet& f)
|
||||
{ coords_ = f.coords_;
|
||||
fc_ends_ = f.fc_ends_;
|
||||
normal_ = f.normal_;
|
||||
mark_ = f.mark_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~DFacet()
|
||||
{ coords_.clear(); fc_ends_.clear(); }
|
||||
|
||||
void push_back_vertex(const Double_point& p)
|
||||
{ push_back_vertex(p.x(),p.y(),p.z()); }
|
||||
|
||||
void set_normal(double x, double y, double z, bool m)
|
||||
{ double l = sqrt(x*x + y*y + z*z);
|
||||
normal_ = Double_triple(x/l,y/l,z/l); mark_ = m; }
|
||||
|
||||
double dx() const { return normal_[0]; }
|
||||
double dy() const { return normal_[1]; }
|
||||
double dz() const { return normal_[2]; }
|
||||
bool mark() const { return mark_; }
|
||||
double* normal() const
|
||||
{ return static_cast<double*>(normal_); }
|
||||
|
||||
void new_facet_cycle()
|
||||
{ fc_ends_.push_back(coords_.size()); }
|
||||
|
||||
unsigned number_of_facet_cycles() const
|
||||
{ return fc_ends_.size(); }
|
||||
|
||||
Coord_iterator facet_cycle_begin(unsigned i)
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i==0) return coords_.begin();
|
||||
else return coords_.begin()+fc_ends_[i]; }
|
||||
|
||||
Coord_iterator facet_cycle_end(unsigned i)
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1];
|
||||
else return coords_.end(); }
|
||||
|
||||
Coord_const_iterator facet_cycle_begin(unsigned i) const
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i==0) return coords_.begin();
|
||||
else return coords_.begin()+fc_ends_[i]; }
|
||||
|
||||
Coord_const_iterator facet_cycle_end(unsigned i) const
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1];
|
||||
else return coords_.end(); }
|
||||
|
||||
void debug(std::ostream& os = std::cerr) const
|
||||
{ os << "DFacet, normal=" << normal_ << ", mark=" << mark() << std::endl;
|
||||
for(unsigned i=0; i<number_of_facet_cycles(); ++i) {
|
||||
os << " facet cycle ";
|
||||
// put all vertices in facet cycle into contour:
|
||||
Coord_const_iterator cit;
|
||||
for(cit = facet_cycle_begin(i); cit != facet_cycle_end(i); ++cit)
|
||||
os << *cit;
|
||||
os << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}; // DFacet
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// OGL Drawable Polyhedron:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK beginCallback(GLenum which)
|
||||
{ glBegin(which); }
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK endCallback(void)
|
||||
{ glEnd(); }
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK errorCallback(GLenum errorCode)
|
||||
{ const GLubyte *estring;
|
||||
estring = gluErrorString(errorCode);
|
||||
fprintf(stderr, "Tessellation Error: %s\n", estring);
|
||||
std::exit (0);
|
||||
void draw(bool showedges) const {
|
||||
if(this->style == SNC_BOUNDARY) {
|
||||
glCallList(this->object_list_+2);
|
||||
if(showedges) {
|
||||
glDisable(GL_LIGHTING);
|
||||
glCallList(this->object_list_+1);
|
||||
glCallList(this->object_list_);
|
||||
}
|
||||
} else {
|
||||
glDisable(GL_LIGHTING);
|
||||
glCallList(this->object_list_+1);
|
||||
glCallList(this->object_list_);
|
||||
}
|
||||
}
|
||||
CGAL::Color getVertexColor(Vertex_iterator v) const {
|
||||
CGAL::Color c = v->mark() ? colors[CGAL_NEF3_UNMARKED_VERTEX_COLOR] : colors[CGAL_NEF3_MARKED_VERTEX_COLOR];
|
||||
return c;
|
||||
}
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK vertexCallback(GLvoid* vertex,
|
||||
GLvoid* user)
|
||||
{ GLdouble* pc(static_cast<GLdouble*>(vertex));
|
||||
GLdouble* pu(static_cast<GLdouble*>(user));
|
||||
// CGAL_NEF_TRACEN("vertexCallback coord "<<pc[0]<<","<<pc[1]<<","<<pc[2]);
|
||||
// CGAL_NEF_TRACEN("vertexCallback normal "<<pu[0]<<","<<pu[1]<<","<<pu[2]);
|
||||
glNormal3dv(pu);
|
||||
glVertex3dv(pc);
|
||||
}
|
||||
CGAL::Color getEdgeColor(Edge_iterator e) const {
|
||||
CGAL::Color c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR];
|
||||
return c;
|
||||
}
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK combineCallback(GLdouble coords[3], GLvoid *[4], GLfloat [4], GLvoid **dataOut)
|
||||
{
|
||||
static std::list<GLdouble*> pcache;
|
||||
if (dataOut) {
|
||||
GLdouble *n = new GLdouble[3];
|
||||
n[0] = coords[0];
|
||||
n[1] = coords[1];
|
||||
n[2] = coords[2];
|
||||
pcache.push_back(n);
|
||||
*dataOut = n;
|
||||
} else {
|
||||
for (std::list<GLdouble*>::const_iterator i = pcache.begin(); i != pcache.end(); i++)
|
||||
delete[] *i;
|
||||
pcache.clear();
|
||||
}
|
||||
}
|
||||
CGAL::Color getFacetColor(Halffacet_iterator f) const {
|
||||
CGAL::Color c = f->mark() ? colors[CGAL_NEF3_UNMARKED_FACET_COLOR] : colors[CGAL_NEF3_MARKED_FACET_COLOR];
|
||||
return c;
|
||||
}
|
||||
|
||||
void setColor(Polyhedron::RenderColor color_index,
|
||||
unsigned char r, unsigned char g, unsigned char b) {
|
||||
assert(color_index < Polyhedron::NUM_COLORS);
|
||||
this->colors[color_index] = CGAL::Color(r,g,b);
|
||||
}
|
||||
private:
|
||||
CGAL::Color colors[NUM_COLORS];
|
||||
|
||||
enum { SNC_AXES};
|
||||
enum { SNC_BOUNDARY, SNC_SKELETON };
|
||||
}; // Polyhedron
|
||||
|
||||
class Polyhedron : public CGAL::OGL::OGL_base_object {
|
||||
public:
|
||||
std::list<DPoint> vertices_;
|
||||
std::list<DSegment> edges_;
|
||||
std::list<DFacet> halffacets_;
|
||||
|
||||
GLuint object_list_;
|
||||
bool init_;
|
||||
|
||||
Bbox_3 bbox_;
|
||||
|
||||
int style;
|
||||
std::vector<bool> switches;
|
||||
|
||||
typedef std::list<DPoint>::const_iterator Vertex_iterator;
|
||||
typedef std::list<DSegment>::const_iterator Edge_iterator;
|
||||
typedef std::list<DFacet>::const_iterator Halffacet_iterator;
|
||||
|
||||
enum RenderColor {
|
||||
CGAL_NEF3_MARKED_VERTEX_COLOR,
|
||||
CGAL_NEF3_MARKED_EDGE_COLOR,
|
||||
CGAL_NEF3_MARKED_FACET_COLOR,
|
||||
CGAL_NEF3_UNMARKED_VERTEX_COLOR,
|
||||
CGAL_NEF3_UNMARKED_EDGE_COLOR,
|
||||
CGAL_NEF3_UNMARKED_FACET_COLOR,
|
||||
NUM_COLORS
|
||||
};
|
||||
static unsigned char colors[NUM_COLORS][3];
|
||||
public:
|
||||
Polyhedron() : bbox_(-1,-1,-1,1,1,1), switches(1) {
|
||||
object_list_ = 0;
|
||||
init_ = false;
|
||||
style = SNC_BOUNDARY;
|
||||
switches[SNC_AXES] = false;
|
||||
}
|
||||
|
||||
~Polyhedron()
|
||||
{ if (object_list_) glDeleteLists(object_list_, 4); }
|
||||
|
||||
void push_back(const Double_point& p, bool m) {
|
||||
vertices_.push_back(DPoint(p,m));
|
||||
}
|
||||
void push_back(const Double_segment& s, bool m)
|
||||
{ edges_.push_back(DSegment(s,m)); }
|
||||
void push_back(const DFacet& f)
|
||||
{ halffacets_.push_back(f); }
|
||||
|
||||
void toggle(int index) {
|
||||
switches[index] = !switches[index];
|
||||
}
|
||||
|
||||
void set_style(int index) {
|
||||
style = index;
|
||||
}
|
||||
|
||||
bool is_initialized() const { return init_; }
|
||||
|
||||
Bbox_3 bbox() const { return bbox_; }
|
||||
Bbox_3& bbox() { return bbox_; }
|
||||
|
||||
void draw(Vertex_iterator v) const {
|
||||
// CGAL_NEF_TRACEN("drawing vertex "<<*v);
|
||||
unsigned char *c = v->mark() ? colors[CGAL_NEF3_UNMARKED_VERTEX_COLOR] : colors[CGAL_NEF3_MARKED_VERTEX_COLOR];
|
||||
glPointSize(10);
|
||||
glColor3ubv(c);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3d(v->x(),v->y(),v->z());
|
||||
#ifdef CGAL_NEF_EMPHASIZE_VERTEX
|
||||
glColor3ub(255,0,0);
|
||||
glVertex3d(CGAL_NEF_EMPHASIZE_VERTEX);
|
||||
#endif
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void draw(Edge_iterator e) const {
|
||||
// CGAL_NEF_TRACEN("drawing edge "<<*e);
|
||||
Double_point p = e->source(), q = e->target();
|
||||
unsigned char *c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR];
|
||||
glLineWidth(5);
|
||||
glColor3ubv(c);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3d(p.x(), p.y(), p.z());
|
||||
glVertex3d(q.x(), q.y(), q.z());
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void draw(Halffacet_iterator f) const {
|
||||
// CGAL_NEF_TRACEN("drawing facet "<<(f->debug(),""));
|
||||
GLUtesselator* tess_ = gluNewTess();
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_VERTEX_DATA),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &vertexCallback);
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_COMBINE),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &combineCallback);
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_BEGIN),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &beginCallback);
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_END),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &endCallback);
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_ERROR),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &errorCallback);
|
||||
gluTessProperty(tess_, GLenum(GLU_TESS_WINDING_RULE),
|
||||
GLU_TESS_WINDING_POSITIVE);
|
||||
|
||||
DFacet::Coord_const_iterator cit;
|
||||
unsigned char *c = f->mark() ? colors[CGAL_NEF3_UNMARKED_FACET_COLOR] : colors[CGAL_NEF3_MARKED_FACET_COLOR];
|
||||
glColor3ubv(c);
|
||||
gluTessBeginPolygon(tess_,f->normal());
|
||||
// CGAL_NEF_TRACEN(" ");
|
||||
// CGAL_NEF_TRACEN("Begin Polygon");
|
||||
gluTessNormal(tess_,f->dx(),f->dy(),f->dz());
|
||||
// forall facet cycles of f:
|
||||
for(unsigned i = 0; i < f->number_of_facet_cycles(); ++i) {
|
||||
gluTessBeginContour(tess_);
|
||||
// CGAL_NEF_TRACEN(" Begin Contour");
|
||||
// put all vertices in facet cycle into contour:
|
||||
for(cit = f->facet_cycle_begin(i);
|
||||
cit != f->facet_cycle_end(i); ++cit) {
|
||||
gluTessVertex(tess_, *cit, *cit);
|
||||
// CGAL_NEF_TRACEN(" add Vertex");
|
||||
}
|
||||
gluTessEndContour(tess_);
|
||||
// CGAL_NEF_TRACEN(" End Contour");
|
||||
}
|
||||
gluTessEndPolygon(tess_);
|
||||
// CGAL_NEF_TRACEN("End Polygon");
|
||||
gluDeleteTess(tess_);
|
||||
combineCallback(NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void construct_axes() const
|
||||
{
|
||||
glLineWidth(2.0);
|
||||
// red x-axis
|
||||
glColor3f(1.0,0.0,0.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0,0.0,0.0);
|
||||
glVertex3f(5000.0,0.0,0.0);
|
||||
glEnd();
|
||||
// green y-axis
|
||||
glColor3f(0.0,1.0,0.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0,0.0,0.0);
|
||||
glVertex3f(0.0,5000.0,0.0);
|
||||
glEnd();
|
||||
// blue z-axis and equator
|
||||
glColor3f(0.0,0.0,1.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0,0.0,0.0);
|
||||
glVertex3f(0.0,0.0,5000.0);
|
||||
glEnd();
|
||||
// six coordinate points in pink:
|
||||
glPointSize(10);
|
||||
glBegin(GL_POINTS);
|
||||
glColor3f(1.0,0.0,0.0);
|
||||
glVertex3d(5,0,0);
|
||||
glColor3f(0.0,1.0,0.0);
|
||||
glVertex3d(0,5,0);
|
||||
glColor3f(0.0,0.0,1.0);
|
||||
glVertex3d(0,0,5);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void fill_display_lists() {
|
||||
glNewList(object_list_, GL_COMPILE);
|
||||
Vertex_iterator v;
|
||||
for(v=vertices_.begin();v!=vertices_.end();++v)
|
||||
draw(v);
|
||||
glEndList();
|
||||
|
||||
glNewList(object_list_+1, GL_COMPILE);
|
||||
Edge_iterator e;
|
||||
for(e=edges_.begin();e!=edges_.end();++e)
|
||||
draw(e);
|
||||
glEndList();
|
||||
|
||||
glNewList(object_list_+2, GL_COMPILE);
|
||||
Halffacet_iterator f;
|
||||
for(f=halffacets_.begin();f!=halffacets_.end();++f)
|
||||
draw(f);
|
||||
glEndList();
|
||||
|
||||
glNewList(object_list_+3, GL_COMPILE); // axes:
|
||||
construct_axes();
|
||||
glEndList();
|
||||
|
||||
}
|
||||
|
||||
void init() {
|
||||
if (init_) return;
|
||||
init_ = true;
|
||||
switches[SNC_AXES] = false;
|
||||
style = SNC_BOUNDARY;
|
||||
object_list_ = glGenLists(4);
|
||||
CGAL_assertion(object_list_);
|
||||
fill_display_lists();
|
||||
}
|
||||
|
||||
|
||||
void draw() const
|
||||
{
|
||||
if (!is_initialized()) const_cast<Polyhedron&>(*this).init();
|
||||
double l = (std::max)( (std::max)( bbox().xmax() - bbox().xmin(),
|
||||
bbox().ymax() - bbox().ymin()),
|
||||
bbox().zmax() - bbox().zmin());
|
||||
if ( l < 1) // make sure that a single point doesn't screw up here
|
||||
l = 1;
|
||||
glScaled( 4.0/l, 4.0/l, 4.0/l);
|
||||
glTranslated( -(bbox().xmax() + bbox().xmin()) / 2.0,
|
||||
-(bbox().ymax() + bbox().ymin()) / 2.0,
|
||||
-(bbox().zmax() + bbox().zmin()) / 2.0);
|
||||
if (style == SNC_BOUNDARY) {
|
||||
//glEnable(GL_LIGHTING);
|
||||
glCallList(object_list_+2); // facets
|
||||
//glDisable(GL_LIGHTING);
|
||||
}
|
||||
// move edges and vertices a bit towards the view-point,
|
||||
// i.e., 1/100th of the unit vector in camera space
|
||||
// double f = l / 4.0 / 100.0;
|
||||
// glTranslated( z_vec[0] * f, z_vec[1] * f, z_vec[2] * f);
|
||||
glCallList(object_list_+1); // edges
|
||||
glCallList(object_list_); // vertices
|
||||
if (switches[SNC_AXES]) glCallList(object_list_+3); // axis
|
||||
}
|
||||
|
||||
void debug(std::ostream& os = std::cerr) const
|
||||
{
|
||||
os << "OGL::Polyhedron" << std::endl;
|
||||
os << "Vertices:" << std::endl;
|
||||
Vertex_iterator v;
|
||||
for(v=vertices_.begin();v!=vertices_.end();++v)
|
||||
os << " "<<*v<<", mark="<<v->mark()<<std::endl;
|
||||
os << "Edges:" << std::endl;
|
||||
Edge_iterator e;
|
||||
for(e=edges_.begin();e!=edges_.end();++e)
|
||||
os << " "<<*e<<", mark="<<e->mark()<<std::endl;
|
||||
os << "Facets:" << std::endl;
|
||||
Halffacet_iterator f;
|
||||
for(f=halffacets_.begin();f!=halffacets_.end();++f)
|
||||
f->debug(); os << std::endl;
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
}; // Polyhedron
|
||||
unsigned char Polyhedron::colors[][3] = {
|
||||
{0xb7, 0xe8, 0x5c},
|
||||
{0xab, 0xd8, 0x56},
|
||||
{0x9d, 0xcb, 0x51},
|
||||
{0xff, 0xf6, 0x7c},
|
||||
{0xff, 0xec, 0x5e},
|
||||
{0xf9, 0xd7, 0x2c}
|
||||
};
|
||||
|
||||
template<typename Nef_polyhedron>
|
||||
class Nef3_Converter {
|
||||
typedef typename Nef_polyhedron::SNC_structure SNC_structure;
|
||||
typedef CGAL::SNC_decorator<SNC_structure> Base;
|
||||
typedef CGAL::SNC_FM_decorator<SNC_structure> FM_decorator;
|
||||
|
||||
public:
|
||||
typedef typename SNC_structure::Vertex_const_iterator Vertex_const_iterator;
|
||||
typedef typename SNC_structure::Halfedge_const_iterator Halfedge_const_iterator;
|
||||
typedef typename SNC_structure::Halffacet_const_iterator Halffacet_const_iterator;
|
||||
typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator;
|
||||
|
||||
typedef typename SNC_structure::Object_const_handle Object_const_handle;
|
||||
typedef typename SNC_structure::SHalfedge_const_handle SHalfedge_const_handle;
|
||||
typedef typename SNC_structure::SHalfloop_const_handle SHalfloop_const_handle;
|
||||
|
||||
typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle;
|
||||
|
||||
typedef typename SNC_structure::Point_3 Point_3;
|
||||
typedef typename SNC_structure::Vector_3 Vector_3;
|
||||
typedef typename SNC_structure::Segment_3 Segment_3;
|
||||
typedef typename SNC_structure::Plane_3 Plane_3;
|
||||
typedef typename SNC_structure::Mark Mark;
|
||||
typedef typename SNC_structure::SHalfedge_around_facet_const_circulator
|
||||
SHalfedge_around_facet_const_circulator;
|
||||
|
||||
private:
|
||||
static OGL::Double_point double_point(const Point_3& p)
|
||||
{ return OGL::Double_point(CGAL::to_double(p.x()),
|
||||
CGAL::to_double(p.y()),
|
||||
CGAL::to_double(p.z())); }
|
||||
|
||||
static OGL::Double_segment double_segment(const Segment_3& s)
|
||||
{ return OGL::Double_segment(double_point(s.source()),
|
||||
double_point(s.target())); }
|
||||
|
||||
static void draw(Vertex_const_handle v, const Nef_polyhedron& ,
|
||||
Polyhedron& P) {
|
||||
Point_3 bp = v->point();
|
||||
// CGAL_NEF_TRACEN("vertex " << bp);
|
||||
P.push_back(double_point(bp), v->mark());
|
||||
}
|
||||
|
||||
static void draw(Halfedge_const_handle e, const Nef_polyhedron& ,
|
||||
Polyhedron& P) {
|
||||
Vertex_const_handle s = e->source();
|
||||
Vertex_const_handle t = e->twin()->source();
|
||||
Segment_3 seg(s->point(),t->point());
|
||||
// CGAL_NEF_TRACEN("edge " << seg);
|
||||
P.push_back(double_segment(seg), e->mark());
|
||||
}
|
||||
|
||||
static void draw(Halffacet_const_handle f, const Nef_polyhedron& ,
|
||||
Polyhedron& P) {
|
||||
OGL::DFacet g;
|
||||
Halffacet_cycle_const_iterator fc; // all facet cycles:
|
||||
CGAL_forall_facet_cycles_of(fc,f)
|
||||
if ( fc.is_shalfedge() ) { // non-trivial facet cycle
|
||||
g.new_facet_cycle();
|
||||
SHalfedge_const_handle h = fc;
|
||||
SHalfedge_around_facet_const_circulator hc(h), he(hc);
|
||||
CGAL_For_all(hc,he){ // all vertex coordinates in facet cycle
|
||||
Point_3 sp = hc->source()->source()->point();
|
||||
// CGAL_NEF_TRACEN(" ");CGAL_NEF_TRACEN("facet" << sp);
|
||||
g.push_back_vertex(double_point(sp));
|
||||
}
|
||||
}
|
||||
Vector_3 v = f->plane().orthogonal_vector();
|
||||
g.set_normal(CGAL::to_double(v.x()),
|
||||
CGAL::to_double(v.y()),
|
||||
CGAL::to_double(v.z()),
|
||||
f->mark());
|
||||
P.push_back(g);
|
||||
}
|
||||
|
||||
// Returns the bounding box of the finite vertices of the polyhedron.
|
||||
// Returns $[-1,+1]^3$ as bounding box if no finite vertex exists.
|
||||
|
||||
static Bbox_3 bounded_bbox(const Nef_polyhedron& N) {
|
||||
bool first_vertex = true;
|
||||
Bbox_3 bbox( -1.0, -1.0, -1.0, 1.0, 1.0, 1.0);
|
||||
Vertex_const_iterator vi;
|
||||
CGAL_forall_vertices(vi, N) {
|
||||
Point_3 p = vi->point();
|
||||
double x = CGAL::to_double(p.hx());
|
||||
double y = CGAL::to_double(p.hy());
|
||||
double z = CGAL::to_double(p.hz());
|
||||
double w = CGAL::to_double(p.hw());
|
||||
if (N.is_standard(vi)) {
|
||||
if(first_vertex) {
|
||||
bbox = Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w);
|
||||
first_vertex = false;
|
||||
} else {
|
||||
bbox = bbox + Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w);
|
||||
first_vertex = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bbox;
|
||||
}
|
||||
|
||||
static void set_R(Bbox_3& bbox, const Nef_polyhedron& N) {
|
||||
if(N.is_standard_kernel()) return;
|
||||
double size = abs(bbox.xmin());
|
||||
if(size < bbox.xmax()) size = bbox.xmax();
|
||||
if(size < bbox.ymin()) size = bbox.ymin();
|
||||
if(size < bbox.ymax()) size = bbox.ymax();
|
||||
if(size < bbox.zmin()) size = bbox.zmin();
|
||||
if(size < bbox.zmax()) size = bbox.zmax();
|
||||
N.set_size_of_infimaximal_box(size*50);
|
||||
// CGAL_NEF_TRACEN("set infi box size to " << size);
|
||||
Vertex_const_iterator vi;
|
||||
CGAL_forall_vertices(vi, N)
|
||||
if(N.is_standard(vi))
|
||||
return;
|
||||
bbox = Bbox_3(bbox.xmin()*10,bbox.ymin()*10,bbox.zmin()*10,
|
||||
bbox.xmax()*10,bbox.ymax()*10,bbox.zmax()*10);
|
||||
}
|
||||
public:
|
||||
static void setColor(Polyhedron::RenderColor color_index,
|
||||
unsigned char r, unsigned char g, unsigned char b) {
|
||||
assert(color_index < Polyhedron::NUM_COLORS);
|
||||
Polyhedron::colors[color_index][0] = r;
|
||||
Polyhedron::colors[color_index][1] = g;
|
||||
Polyhedron::colors[color_index][2] = b;
|
||||
}
|
||||
|
||||
static void convert_to_OGLPolyhedron(const Nef_polyhedron& N, Polyhedron* P) {
|
||||
Bbox_3 bbox(bounded_bbox(N));
|
||||
set_R(bbox,N);
|
||||
P->bbox() = bbox;
|
||||
Vertex_const_iterator v;
|
||||
CGAL_forall_vertices(v,*N.sncp()) draw(v,N,*P);
|
||||
Halfedge_const_iterator e;
|
||||
CGAL_forall_edges(e,*N.sncp()) draw(e,N,*P);
|
||||
Halffacet_const_iterator f;
|
||||
CGAL_forall_facets(f,*N.sncp()) draw(f,N,*P);
|
||||
}
|
||||
|
||||
}; // Nef3_Converter
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
} // namespace OpenSCAD
|
||||
|
||||
#endif // CGAL_NEF_OPENGL_HELPER_H
|
||||
#endif // CGAL_RENDERER_H
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "CSGTermRenderer.h"
|
||||
#include "CSGTermEvaluator.h"
|
||||
#include "visitor.h"
|
||||
#include "state.h"
|
||||
#include "csgterm.h"
|
||||
|
@ -16,22 +16,22 @@
|
|||
#include <assert.h>
|
||||
|
||||
/*!
|
||||
\class CSGTermRenderer
|
||||
\class CSGTermEvaluator
|
||||
|
||||
A visitor responsible for creating a tree of CSGTerm nodes used for rendering
|
||||
with OpenCSG.
|
||||
*/
|
||||
|
||||
CSGTerm *CSGTermRenderer::renderCSGTerm(const AbstractNode &node,
|
||||
CSGTerm *CSGTermEvaluator::evaluateCSGTerm(const AbstractNode &node,
|
||||
vector<CSGTerm*> *highlights,
|
||||
vector<CSGTerm*> *background)
|
||||
{
|
||||
Traverser render(*this, node, Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
Traverser evaluate(*this, node, Traverser::PRE_AND_POSTFIX);
|
||||
evaluate.execute();
|
||||
return this->stored_term[node.index()];
|
||||
}
|
||||
|
||||
void CSGTermRenderer::applyToChildren(const AbstractNode &node, CSGTermRenderer::CsgOp op)
|
||||
void CSGTermEvaluator::applyToChildren(const AbstractNode &node, CSGTermEvaluator::CsgOp op)
|
||||
{
|
||||
CSGTerm *t1 = NULL;
|
||||
for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin();
|
||||
|
@ -62,7 +62,7 @@ void CSGTermRenderer::applyToChildren(const AbstractNode &node, CSGTermRenderer:
|
|||
this->stored_term[node.index()] = t1;
|
||||
}
|
||||
|
||||
Response CSGTermRenderer::visit(State &state, const AbstractNode &node)
|
||||
Response CSGTermEvaluator::visit(State &state, const AbstractNode &node)
|
||||
{
|
||||
if (state.isPostfix()) {
|
||||
applyToChildren(node, UNION);
|
||||
|
@ -71,7 +71,7 @@ Response CSGTermRenderer::visit(State &state, const AbstractNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
Response CSGTermRenderer::visit(State &state, const AbstractIntersectionNode &node)
|
||||
Response CSGTermEvaluator::visit(State &state, const AbstractIntersectionNode &node)
|
||||
{
|
||||
if (state.isPostfix()) {
|
||||
applyToChildren(node, INTERSECTION);
|
||||
|
@ -80,7 +80,7 @@ Response CSGTermRenderer::visit(State &state, const AbstractIntersectionNode &no
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
static CSGTerm *render_csg_term_from_ps(const double m[20],
|
||||
static CSGTerm *evaluate_csg_term_from_ps(const double m[20],
|
||||
vector<CSGTerm*> *highlights,
|
||||
vector<CSGTerm*> *background,
|
||||
PolySet *ps,
|
||||
|
@ -97,13 +97,13 @@ static CSGTerm *render_csg_term_from_ps(const double m[20],
|
|||
return t;
|
||||
}
|
||||
|
||||
Response CSGTermRenderer::visit(State &state, const AbstractPolyNode &node)
|
||||
Response CSGTermEvaluator::visit(State &state, const AbstractPolyNode &node)
|
||||
{
|
||||
if (state.isPostfix()) {
|
||||
CSGTerm *t1 = NULL;
|
||||
PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_OPENCSG, this->psrenderer);
|
||||
PolySet *ps = node.evaluate_polyset(AbstractPolyNode::RENDER_OPENCSG, this->psevaluator);
|
||||
if (ps) {
|
||||
t1 = render_csg_term_from_ps(state.matrix(), this->highlights, this->background,
|
||||
t1 = evaluate_csg_term_from_ps(state.matrix(), this->highlights, this->background,
|
||||
ps, node.modinst, node);
|
||||
}
|
||||
this->stored_term[node.index()] = t1;
|
||||
|
@ -112,7 +112,7 @@ Response CSGTermRenderer::visit(State &state, const AbstractPolyNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
Response CSGTermRenderer::visit(State &state, const CsgNode &node)
|
||||
Response CSGTermEvaluator::visit(State &state, const CsgNode &node)
|
||||
{
|
||||
if (state.isPostfix()) {
|
||||
CsgOp op;
|
||||
|
@ -133,7 +133,7 @@ Response CSGTermRenderer::visit(State &state, const CsgNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
Response CSGTermRenderer::visit(State &state, const TransformNode &node)
|
||||
Response CSGTermEvaluator::visit(State &state, const TransformNode &node)
|
||||
{
|
||||
if (state.isPrefix()) {
|
||||
double m[20];
|
||||
|
@ -162,7 +162,7 @@ Response CSGTermRenderer::visit(State &state, const TransformNode &node)
|
|||
}
|
||||
|
||||
// FIXME: Find out how to best call into CGAL from this visitor
|
||||
Response CSGTermRenderer::visit(State &state, const RenderNode &node)
|
||||
Response CSGTermEvaluator::visit(State &state, const RenderNode &node)
|
||||
{
|
||||
PRINT("WARNING: Found render() statement but compiled without CGAL support!");
|
||||
if (state.isPostfix()) {
|
||||
|
@ -176,7 +176,7 @@ Response CSGTermRenderer::visit(State &state, const RenderNode &node)
|
|||
Adds ourself to out parent's list of traversed children.
|
||||
Call this for _every_ node which affects output during the postfix traversal.
|
||||
*/
|
||||
void CSGTermRenderer::addToParent(const State &state, const AbstractNode &node)
|
||||
void CSGTermEvaluator::addToParent(const State &state, const AbstractNode &node)
|
||||
{
|
||||
assert(state.isPostfix());
|
||||
this->visitedchildren.erase(node.index());
|
||||
|
@ -190,26 +190,26 @@ void CSGTermRenderer::addToParent(const State &state, const AbstractNode &node)
|
|||
|
||||
// FIXME: #ifdef ENABLE_CGAL
|
||||
#if 0
|
||||
CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
CSGTerm *CgaladvNode::evaluate_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
{
|
||||
if (type == MINKOWSKI)
|
||||
return render_csg_term_from_nef(m, highlights, background, "minkowski", this->convexity);
|
||||
return evaluate_csg_term_from_nef(m, highlights, background, "minkowski", this->convexity);
|
||||
|
||||
if (type == GLIDE)
|
||||
return render_csg_term_from_nef(m, highlights, background, "glide", this->convexity);
|
||||
return evaluate_csg_term_from_nef(m, highlights, background, "glide", this->convexity);
|
||||
|
||||
if (type == SUBDIV)
|
||||
return render_csg_term_from_nef(m, highlights, background, "subdiv", this->convexity);
|
||||
return evaluate_csg_term_from_nef(m, highlights, background, "subdiv", this->convexity);
|
||||
|
||||
if (type == HULL)
|
||||
return render_csg_term_from_nef(m, highlights, background, "hull", this->convexity);
|
||||
return evaluate_csg_term_from_nef(m, highlights, background, "hull", this->convexity);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else // ENABLE_CGAL
|
||||
|
||||
CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
CSGTerm *CgaladvNode::evaluate_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
{
|
||||
PRINT("WARNING: Found minkowski(), glide(), subdiv() or hull() statement but compiled without CGAL support!");
|
||||
return NULL;
|
||||
|
@ -221,12 +221,12 @@ CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlight
|
|||
|
||||
// FIXME: #ifdef ENABLE_CGAL
|
||||
#if 0
|
||||
CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const
|
||||
CSGTerm *AbstractNode::evaluate_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const
|
||||
{
|
||||
QString key = mk_cache_id();
|
||||
if (PolySet::ps_cache.contains(key)) {
|
||||
PRINT(PolySet::ps_cache[key]->msg);
|
||||
return AbstractPolyNode::render_csg_term_from_ps(m, highlights, background,
|
||||
return AbstractPolyNode::evaluate_csg_term_from_ps(m, highlights, background,
|
||||
PolySet::ps_cache[key]->ps->link(), modinst, idx);
|
||||
}
|
||||
|
||||
|
@ -248,10 +248,10 @@ CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector<CSGTerm*>
|
|||
QTime t;
|
||||
t.start();
|
||||
|
||||
N = this->renderCSGMesh();
|
||||
N = this->evaluateCSGMesh();
|
||||
|
||||
int s = t.elapsed() / 1000;
|
||||
PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
|
||||
PRINTF_NOCACHE("..processing time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
|
||||
}
|
||||
|
||||
PolySet *ps = NULL;
|
||||
|
@ -315,19 +315,19 @@ CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector<CSGTerm*>
|
|||
return NULL;
|
||||
}
|
||||
|
||||
CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
CSGTerm *RenderNode::evaluate_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
{
|
||||
return render_csg_term_from_nef(m, highlights, background, "render", this->convexity);
|
||||
return evaluate_csg_term_from_nef(m, highlights, background, "render", this->convexity);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
CSGTerm *RenderNode::evaluate_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
|
||||
{
|
||||
CSGTerm *t1 = NULL;
|
||||
PRINT("WARNING: Found render() statement but compiled without CGAL support!");
|
||||
foreach(AbstractNode * v, children) {
|
||||
CSGTerm *t2 = v->render_csg_term(m, highlights, background);
|
||||
CSGTerm *t2 = v->evaluate_csg_term(m, highlights, background);
|
||||
if (t2 && !t1) {
|
||||
t1 = t2;
|
||||
} else if (t2 && t1) {
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef CSGTERMRENDERER_H_
|
||||
#define CSGTERMRENDERER_H_
|
||||
#ifndef CSGTERMEVALUATOR_H_
|
||||
#define CSGTERMEVALUATOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -14,13 +14,13 @@ using std::map;
|
|||
using std::list;
|
||||
using std::vector;
|
||||
|
||||
class CSGTermRenderer : public Visitor
|
||||
class CSGTermEvaluator : public Visitor
|
||||
{
|
||||
public:
|
||||
CSGTermRenderer(const Tree &tree, class PolySetRenderer *psrenderer = NULL)
|
||||
: highlights(NULL), background(NULL), tree(tree), psrenderer(psrenderer) {
|
||||
CSGTermEvaluator(const Tree &tree, class PolySetEvaluator *psevaluator = NULL)
|
||||
: highlights(NULL), background(NULL), tree(tree), psevaluator(psevaluator) {
|
||||
}
|
||||
virtual ~CSGTermRenderer() {}
|
||||
virtual ~CSGTermEvaluator() {}
|
||||
|
||||
virtual Response visit(State &state, const AbstractNode &node);
|
||||
virtual Response visit(State &state, const AbstractIntersectionNode &node);
|
||||
|
@ -29,25 +29,25 @@ public:
|
|||
virtual Response visit(State &state, const TransformNode &node);
|
||||
virtual Response visit(State &state, const RenderNode &node);
|
||||
|
||||
class CSGTerm *renderCSGTerm(const AbstractNode &node,
|
||||
class CSGTerm *evaluateCSGTerm(const AbstractNode &node,
|
||||
vector<CSGTerm*> *highlights, vector<CSGTerm*> *background);
|
||||
|
||||
private:
|
||||
enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI};
|
||||
void addToParent(const State &state, const AbstractNode &node);
|
||||
void applyToChildren(const AbstractNode &node, CSGTermRenderer::CsgOp op);
|
||||
void applyToChildren(const AbstractNode &node, CSGTermEvaluator::CsgOp op);
|
||||
|
||||
const AbstractNode *root;
|
||||
typedef list<const AbstractNode *> ChildList;
|
||||
map<int, ChildList> visitedchildren;
|
||||
|
||||
public:
|
||||
map<int, class CSGTerm*> stored_term; // The term rendered from each node index
|
||||
map<int, class CSGTerm*> stored_term; // The term evaluated from each node index
|
||||
|
||||
vector<CSGTerm*> *highlights;
|
||||
vector<CSGTerm*> *background;
|
||||
const Tree &tree;
|
||||
class PolySetRenderer *psrenderer;
|
||||
class PolySetEvaluator *psevaluator;
|
||||
};
|
||||
|
||||
#endif
|
23
src/GLView.h
23
src/GLView.h
|
@ -12,6 +12,8 @@
|
|||
class GLView : public QGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool showFaces READ showFaces WRITE setShowFaces);
|
||||
Q_PROPERTY(bool showEdges READ showEdges WRITE setShowEdges);
|
||||
Q_PROPERTY(bool showAxes READ showAxes WRITE setShowAxes);
|
||||
Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs);
|
||||
Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode);
|
||||
|
@ -19,18 +21,23 @@ class GLView : public QGLWidget
|
|||
public:
|
||||
GLView(QWidget *parent = NULL);
|
||||
GLView(const QGLFormat & format, QWidget *parent = NULL);
|
||||
void setRenderFunc(void (*func)(void*), void *userdata);
|
||||
void setRenderer(class Renderer* r);
|
||||
#ifdef ENABLE_OPENCSG
|
||||
bool hasOpenCSGSupport() { return this->opencsg_support; }
|
||||
#endif
|
||||
// Properties
|
||||
bool showFaces() const { return this->showfaces; }
|
||||
void setShowFaces(bool enabled) { this->showfaces = enabled; }
|
||||
bool showEdges() const { return this->showedges; }
|
||||
void setShowEdges(bool enabled) { this->showedges = enabled; }
|
||||
bool showAxes() const { return this->showaxes; }
|
||||
void setShowAxes(bool enabled) { this->showaxes = enabled; }
|
||||
bool showCrosshairs() const { return this->showcrosshairs; }
|
||||
void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; }
|
||||
bool orthoMode() const { return this->orthomode; }
|
||||
void setOrthoMode(bool enabled) { this->orthomode = enabled; }
|
||||
|
||||
|
||||
public:
|
||||
QLabel *statusLabel;
|
||||
double object_rot_x;
|
||||
double object_rot_y;
|
||||
|
@ -47,10 +54,10 @@ public:
|
|||
|
||||
private:
|
||||
void init();
|
||||
Renderer *renderer;
|
||||
|
||||
void (*renderfunc)(void*);
|
||||
void *renderfunc_vp;
|
||||
|
||||
bool showfaces;
|
||||
bool showedges;
|
||||
bool showaxes;
|
||||
bool showcrosshairs;
|
||||
bool orthomode;
|
||||
|
@ -60,8 +67,7 @@ private:
|
|||
double w_h_ratio;
|
||||
|
||||
bool mouse_drag_active;
|
||||
int last_mouse_x;
|
||||
int last_mouse_y;
|
||||
QPoint last_mouse;
|
||||
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
|
@ -71,7 +77,10 @@ private:
|
|||
|
||||
void initializeGL();
|
||||
void resizeGL(int w, int h);
|
||||
void setupPerspective();
|
||||
void setupOrtho(double distance,bool offset=false);
|
||||
void paintGL();
|
||||
void normalizeAngle(GLdouble& angle);
|
||||
|
||||
#ifdef ENABLE_OPENCSG
|
||||
private slots:
|
||||
|
|
|
@ -41,17 +41,18 @@ public:
|
|||
class CSGChain *root_chain;
|
||||
#ifdef ENABLE_CGAL
|
||||
class CGAL_Nef_polyhedron *root_N;
|
||||
bool recreate_cgal_ogl_p;
|
||||
void *cgal_ogl_p;
|
||||
PolySet *cgal_ogl_ps;
|
||||
class CGALRenderer *cgalRenderer;
|
||||
#endif
|
||||
#ifdef ENABLE_OPENCSG
|
||||
class OpenCSGRenderer *opencsgRenderer;
|
||||
#endif
|
||||
class ThrownTogetherRenderer *thrownTogetherRenderer;
|
||||
|
||||
std::vector<CSGTerm*> highlight_terms;
|
||||
CSGChain *highlights_chain;
|
||||
std::vector<CSGTerm*> background_terms;
|
||||
CSGChain *background_chain;
|
||||
QString last_compiled_doc;
|
||||
bool enableOpenCSG;
|
||||
|
||||
static const int maxRecentFiles = 10;
|
||||
QAction *actionRecentFile[maxRecentFiles];
|
||||
|
|
|
@ -0,0 +1,687 @@
|
|||
// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
||||
// the terms of the Q Public License version 1.0.
|
||||
// See the file LICENSE.QPL distributed with CGAL.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.7-branch/Nef_3/include/CGAL/Nef_3/OGL_helper.h $
|
||||
// $Id: OGL_helper.h 56667 2010-06-09 07:37:13Z sloriot $
|
||||
//
|
||||
//
|
||||
// Author(s) : Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
|
||||
|
||||
#ifndef CGAL_NEF_OPENGL_HELPER_H
|
||||
#define CGAL_NEF_OPENGL_HELPER_H
|
||||
|
||||
#include <CGAL/Nef_S2/OGL_base_object.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Nef_3/SNC_decorator.h>
|
||||
#include <qgl.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#define CGAL_NEF3_MARKED_VERTEX_COLOR 183,232,92
|
||||
#define CGAL_NEF3_MARKED_EDGE_COLOR 171,216,86
|
||||
#define CGAL_NEF3_MARKED_FACET_COLOR 157,203,81
|
||||
|
||||
#define CGAL_NEF3_UNMARKED_VERTEX_COLOR 255,246,124
|
||||
#define CGAL_NEF3_UNMARKED_EDGE_COLOR 255,236,94
|
||||
#define CGAL_NEF3_UNMARKED_FACET_COLOR 249,215,44
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CGAL_GLU_TESS_CALLBACK CALLBACK
|
||||
#else
|
||||
#define CGAL_GLU_TESS_CALLBACK
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
#if defined __APPLE__ && !defined MAC_OS_X_VERSION_10_5
|
||||
#define CGAL_GLU_TESS_DOTS ...
|
||||
#else
|
||||
#define CGAL_GLU_TESS_DOTS
|
||||
#endif
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace OGL {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Drawable double types:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
typedef CGAL::Simple_cartesian<double> DKernel;
|
||||
typedef DKernel::Point_3 Double_point;
|
||||
typedef DKernel::Vector_3 Double_vector;
|
||||
typedef DKernel::Segment_3 Double_segment;
|
||||
typedef DKernel::Aff_transformation_3 Affine_3;
|
||||
|
||||
// DPoint = a double point including a mark
|
||||
class DPoint : public Double_point {
|
||||
bool m_;
|
||||
public:
|
||||
DPoint() {}
|
||||
DPoint(const Double_point& p, bool m) : Double_point(p) { m_ = m; }
|
||||
DPoint(const DPoint& p) : Double_point(p) { m_ = p.m_; }
|
||||
DPoint& operator=(const DPoint& p)
|
||||
{ Double_point::operator=(p); m_ = p.m_; return *this; }
|
||||
bool mark() const { return m_; }
|
||||
};
|
||||
|
||||
// DSegment = a double segment including a mark
|
||||
class DSegment : public Double_segment {
|
||||
bool m_;
|
||||
public:
|
||||
DSegment() {}
|
||||
DSegment(const Double_segment& s, bool m) : Double_segment(s) { m_ = m; }
|
||||
DSegment(const DSegment& s) : Double_segment(s) { m_ = s.m_; }
|
||||
DSegment& operator=(const DSegment& s)
|
||||
{ Double_segment::operator=(s); m_ = s.m_; return *this; }
|
||||
bool mark() const { return m_; }
|
||||
};
|
||||
|
||||
// Double_triple = a class that stores a triple of double
|
||||
// coordinates; we need a pointer to the coordinates in a C array
|
||||
// for OpenGL
|
||||
class Double_triple {
|
||||
typedef double* double_ptr;
|
||||
typedef const double* const_double_ptr;
|
||||
double coords_[3];
|
||||
public:
|
||||
Double_triple()
|
||||
{ coords_[0]=coords_[1]=coords_[2]=0.0; }
|
||||
Double_triple(double x, double y, double z)
|
||||
{ coords_[0]=x; coords_[1]=y; coords_[2]=z; }
|
||||
Double_triple(const Double_triple& t)
|
||||
{ coords_[0]=t.coords_[0];
|
||||
coords_[1]=t.coords_[1];
|
||||
coords_[2]=t.coords_[2];
|
||||
}
|
||||
Double_triple& operator=(const Double_triple& t)
|
||||
{ coords_[0]=t.coords_[0];
|
||||
coords_[1]=t.coords_[1];
|
||||
coords_[2]=t.coords_[2];
|
||||
return *this; }
|
||||
operator double_ptr() const
|
||||
{ return const_cast<Double_triple&>(*this).coords_; }
|
||||
double operator[](unsigned i)
|
||||
{ CGAL_assertion(i<3); return coords_[i]; }
|
||||
}; // Double_triple
|
||||
|
||||
static std::ostream& operator << (std::ostream& os,
|
||||
const Double_triple& t)
|
||||
{ os << "(" << t[0] << "," << t[1] << "," << t[2] << ")";
|
||||
return os; }
|
||||
|
||||
|
||||
// DFacet stores the facet cycle vertices in a continuus C array
|
||||
// of three double components, this is necessary due to the OpenGL
|
||||
// tesselator input format !
|
||||
class DFacet {
|
||||
typedef std::vector<Double_triple> Coord_vector;
|
||||
typedef std::vector<unsigned> Cycle_vector;
|
||||
Coord_vector coords_; // stores all vertex coordinates
|
||||
Cycle_vector fc_ends_; // stores entry points of facet cycles
|
||||
Double_triple normal_; // stores normal and mark of facet
|
||||
bool mark_;
|
||||
|
||||
public:
|
||||
typedef Coord_vector::iterator Coord_iterator;
|
||||
typedef Coord_vector::const_iterator Coord_const_iterator;
|
||||
|
||||
DFacet() {}
|
||||
|
||||
void push_back_vertex(double x, double y, double z)
|
||||
{ coords_.push_back(Double_triple(x,y,z)); }
|
||||
|
||||
DFacet(const DFacet& f)
|
||||
{ coords_ = f.coords_;
|
||||
fc_ends_ = f.fc_ends_;
|
||||
normal_ = f.normal_;
|
||||
mark_ = f.mark_;
|
||||
}
|
||||
|
||||
DFacet& operator=(const DFacet& f)
|
||||
{ coords_ = f.coords_;
|
||||
fc_ends_ = f.fc_ends_;
|
||||
normal_ = f.normal_;
|
||||
mark_ = f.mark_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~DFacet()
|
||||
{ coords_.clear(); fc_ends_.clear(); }
|
||||
|
||||
void push_back_vertex(const Double_point& p)
|
||||
{ push_back_vertex(p.x(),p.y(),p.z()); }
|
||||
|
||||
void set_normal(double x, double y, double z, bool m)
|
||||
{ double l = sqrt(x*x + y*y + z*z);
|
||||
normal_ = Double_triple(x/l,y/l,z/l); mark_ = m; }
|
||||
|
||||
double dx() const { return normal_[0]; }
|
||||
double dy() const { return normal_[1]; }
|
||||
double dz() const { return normal_[2]; }
|
||||
bool mark() const { return mark_; }
|
||||
double* normal() const
|
||||
{ return static_cast<double*>(normal_); }
|
||||
|
||||
void new_facet_cycle()
|
||||
{ fc_ends_.push_back(coords_.size()); }
|
||||
|
||||
unsigned number_of_facet_cycles() const
|
||||
{ return fc_ends_.size(); }
|
||||
|
||||
Coord_iterator facet_cycle_begin(unsigned i)
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i==0) return coords_.begin();
|
||||
else return coords_.begin()+fc_ends_[i]; }
|
||||
|
||||
Coord_iterator facet_cycle_end(unsigned i)
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1];
|
||||
else return coords_.end(); }
|
||||
|
||||
Coord_const_iterator facet_cycle_begin(unsigned i) const
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i==0) return coords_.begin();
|
||||
else return coords_.begin()+fc_ends_[i]; }
|
||||
|
||||
Coord_const_iterator facet_cycle_end(unsigned i) const
|
||||
{ CGAL_assertion(i<number_of_facet_cycles());
|
||||
if (i<fc_ends_.size()-1) return coords_.begin()+fc_ends_[i+1];
|
||||
else return coords_.end(); }
|
||||
|
||||
void debug(std::ostream& os = std::cerr) const
|
||||
{ os << "DFacet, normal=" << normal_ << ", mark=" << mark() << std::endl;
|
||||
for(unsigned i=0; i<number_of_facet_cycles(); ++i) {
|
||||
os << " facet cycle ";
|
||||
// put all vertices in facet cycle into contour:
|
||||
Coord_const_iterator cit;
|
||||
for(cit = facet_cycle_begin(i); cit != facet_cycle_end(i); ++cit)
|
||||
os << *cit;
|
||||
os << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}; // DFacet
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// OGL Drawable Polyhedron:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK beginCallback(GLenum which)
|
||||
{ glBegin(which); }
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK endCallback(void)
|
||||
{ glEnd(); }
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK errorCallback(GLenum errorCode)
|
||||
{ const GLubyte *estring;
|
||||
estring = gluErrorString(errorCode);
|
||||
fprintf(stderr, "Tessellation Error: %s\n", estring);
|
||||
std::exit (0);
|
||||
}
|
||||
|
||||
inline void CGAL_GLU_TESS_CALLBACK vertexCallback(GLvoid* vertex,
|
||||
GLvoid* user)
|
||||
{ GLdouble* pc(static_cast<GLdouble*>(vertex));
|
||||
GLdouble* pu(static_cast<GLdouble*>(user));
|
||||
// CGAL_NEF_TRACEN("vertexCallback coord "<<pc[0]<<","<<pc[1]<<","<<pc[2]);
|
||||
// CGAL_NEF_TRACEN("vertexCallback normal "<<pu[0]<<","<<pu[1]<<","<<pu[2]);
|
||||
glNormal3dv(pu);
|
||||
glVertex3dv(pc);
|
||||
}
|
||||
|
||||
|
||||
enum { SNC_AXES};
|
||||
enum { SNC_BOUNDARY, SNC_SKELETON };
|
||||
|
||||
class Polyhedron : public OGL_base_object {
|
||||
protected:
|
||||
std::list<DPoint> vertices_;
|
||||
std::list<DSegment> edges_;
|
||||
std::list<DFacet> halffacets_;
|
||||
|
||||
GLuint object_list_;
|
||||
bool init_;
|
||||
|
||||
Bbox_3 bbox_;
|
||||
|
||||
int style;
|
||||
std::vector<bool> switches;
|
||||
|
||||
typedef std::list<DPoint>::const_iterator Vertex_iterator;
|
||||
typedef std::list<DSegment>::const_iterator Edge_iterator;
|
||||
typedef std::list<DFacet>::const_iterator Halffacet_iterator;
|
||||
|
||||
public:
|
||||
Polyhedron() : bbox_(-1,-1,-1,1,1,1), switches(1) {
|
||||
object_list_ = 0;
|
||||
init_ = false;
|
||||
style = SNC_BOUNDARY;
|
||||
switches[SNC_AXES] = false;
|
||||
}
|
||||
|
||||
/*
|
||||
Polyhedron(const Polyhedron& P) :
|
||||
object_list_(0),
|
||||
init_(false),
|
||||
bbox_(P.bbox_),
|
||||
style(P.style),
|
||||
switches(2) {
|
||||
|
||||
switches[SNC_AXES] = P.switches[SNC_AXES];
|
||||
|
||||
Vertex_iterator v;
|
||||
for(v=P.vertices_.begin();v!=P.vertices_.end();++v)
|
||||
vertices_.push_back(*v);
|
||||
Edge_iterator e;
|
||||
for(e=P.edges_.begin();e!=P.edges_.end();++e)
|
||||
edges_.push_back(*e);
|
||||
Halffacet_iterator f;
|
||||
for(f=P.halffacets_.begin();f!=P.halffacets_.end();++f)
|
||||
halffacets_.push_back(*f);
|
||||
}
|
||||
|
||||
Polyhedron& operator=(const Polyhedron& P) {
|
||||
if (object_list_) glDeleteLists(object_list_, 4);
|
||||
object_list_ = 0;
|
||||
init_ = false;
|
||||
style = P.style;
|
||||
switches[SNC_AXES] = P.switches[SNC_AXES];
|
||||
|
||||
Vertex_iterator v;
|
||||
vertices_.clear();
|
||||
for(v=P.vertices_.begin();v!=P.vertices_.end();++v)
|
||||
vertices_.push_back(*v);
|
||||
Edge_iterator e;
|
||||
edges_.clear();
|
||||
for(e=P.edges_.begin();e!=P.edges_.end();++e)
|
||||
edges_.push_back(*e);
|
||||
Halffacet_iterator f;
|
||||
halffacets_.clear();
|
||||
for(f=P.halffacets_.begin();f!=P.halffacets_.end();++f)
|
||||
halffacets_.push_back(*f);
|
||||
init();
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
~Polyhedron()
|
||||
{ if (object_list_) glDeleteLists(object_list_, 4); }
|
||||
|
||||
void push_back(const Double_point& p, bool m) {
|
||||
vertices_.push_back(DPoint(p,m));
|
||||
}
|
||||
void push_back(const Double_segment& s, bool m)
|
||||
{ edges_.push_back(DSegment(s,m)); }
|
||||
void push_back(const DFacet& f)
|
||||
{ halffacets_.push_back(f); }
|
||||
|
||||
void toggle(int index) {
|
||||
switches[index] = !switches[index];
|
||||
}
|
||||
|
||||
void set_style(int index) {
|
||||
style = index;
|
||||
}
|
||||
|
||||
bool is_initialized() const { return init_; }
|
||||
|
||||
Bbox_3 bbox() const { return bbox_; }
|
||||
Bbox_3& bbox() { return bbox_; }
|
||||
|
||||
virtual CGAL::Color getVertexColor(Vertex_iterator v) const
|
||||
{
|
||||
CGAL::Color cf(CGAL_NEF3_MARKED_VERTEX_COLOR),
|
||||
ct(CGAL_NEF3_UNMARKED_VERTEX_COLOR); // more blue-ish
|
||||
CGAL::Color c = v->mark() ? ct : cf;
|
||||
return c;
|
||||
}
|
||||
|
||||
void draw(Vertex_iterator v) const {
|
||||
// CGAL_NEF_TRACEN("drawing vertex "<<*v);
|
||||
CGAL::Color c = getVertexColor(v);
|
||||
glPointSize(10);
|
||||
glColor3ub(c.red(), c.green(), c.blue());
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3d(v->x(),v->y(),v->z());
|
||||
#ifdef CGAL_NEF_EMPHASIZE_VERTEX
|
||||
glColor3ub(255,0,0);
|
||||
glVertex3d(CGAL_NEF_EMPHASIZE_VERTEX);
|
||||
#endif
|
||||
glEnd();
|
||||
}
|
||||
|
||||
virtual CGAL::Color getEdgeColor(Edge_iterator e) const
|
||||
{
|
||||
CGAL::Color cf(CGAL_NEF3_MARKED_EDGE_COLOR),
|
||||
ct(CGAL_NEF3_UNMARKED_EDGE_COLOR); // more blue-ish
|
||||
CGAL::Color c = e->mark() ? ct : cf;
|
||||
return c;
|
||||
}
|
||||
|
||||
void draw(Edge_iterator e) const {
|
||||
// CGAL_NEF_TRACEN("drawing edge "<<*e);
|
||||
Double_point p = e->source(), q = e->target();
|
||||
CGAL::Color c = getEdgeColor(e);
|
||||
glLineWidth(5);
|
||||
glColor3ub(c.red(),c.green(),c.blue());
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3d(p.x(), p.y(), p.z());
|
||||
glVertex3d(q.x(), q.y(), q.z());
|
||||
glEnd();
|
||||
}
|
||||
|
||||
virtual CGAL::Color getFacetColor(Halffacet_iterator f) const
|
||||
{
|
||||
CGAL::Color cf(CGAL_NEF3_MARKED_FACET_COLOR),
|
||||
ct(CGAL_NEF3_UNMARKED_FACET_COLOR); // more blue-ish
|
||||
CGAL::Color c = (f->mark() ? ct : cf);
|
||||
return c;
|
||||
}
|
||||
|
||||
void draw(Halffacet_iterator f) const {
|
||||
// CGAL_NEF_TRACEN("drawing facet "<<(f->debug(),""));
|
||||
GLUtesselator* tess_ = gluNewTess();
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_VERTEX_DATA),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &vertexCallback);
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_BEGIN),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &beginCallback);
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_END),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &endCallback);
|
||||
gluTessCallback(tess_, GLenum(GLU_TESS_ERROR),
|
||||
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &errorCallback);
|
||||
gluTessProperty(tess_, GLenum(GLU_TESS_WINDING_RULE),
|
||||
GLU_TESS_WINDING_POSITIVE);
|
||||
|
||||
DFacet::Coord_const_iterator cit;
|
||||
CGAL::Color c = getFacetColor(f);
|
||||
glColor3ub(c.red(),c.green(),c.blue());
|
||||
gluTessBeginPolygon(tess_,f->normal());
|
||||
// CGAL_NEF_TRACEN(" ");
|
||||
// CGAL_NEF_TRACEN("Begin Polygon");
|
||||
gluTessNormal(tess_,f->dx(),f->dy(),f->dz());
|
||||
// forall facet cycles of f:
|
||||
for(unsigned i = 0; i < f->number_of_facet_cycles(); ++i) {
|
||||
gluTessBeginContour(tess_);
|
||||
// CGAL_NEF_TRACEN(" Begin Contour");
|
||||
// put all vertices in facet cycle into contour:
|
||||
for(cit = f->facet_cycle_begin(i);
|
||||
cit != f->facet_cycle_end(i); ++cit) {
|
||||
gluTessVertex(tess_, *cit, *cit);
|
||||
// CGAL_NEF_TRACEN(" add Vertex");
|
||||
}
|
||||
gluTessEndContour(tess_);
|
||||
// CGAL_NEF_TRACEN(" End Contour");
|
||||
}
|
||||
gluTessEndPolygon(tess_);
|
||||
// CGAL_NEF_TRACEN("End Polygon");
|
||||
gluDeleteTess(tess_);
|
||||
}
|
||||
|
||||
void construct_axes() const
|
||||
{
|
||||
glLineWidth(2.0);
|
||||
// red x-axis
|
||||
glColor3f(1.0,0.0,0.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0,0.0,0.0);
|
||||
glVertex3f(5000.0,0.0,0.0);
|
||||
glEnd();
|
||||
// green y-axis
|
||||
glColor3f(0.0,1.0,0.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0,0.0,0.0);
|
||||
glVertex3f(0.0,5000.0,0.0);
|
||||
glEnd();
|
||||
// blue z-axis and equator
|
||||
glColor3f(0.0,0.0,1.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0,0.0,0.0);
|
||||
glVertex3f(0.0,0.0,5000.0);
|
||||
glEnd();
|
||||
// six coordinate points in pink:
|
||||
glPointSize(10);
|
||||
glBegin(GL_POINTS);
|
||||
glColor3f(1.0,0.0,0.0);
|
||||
glVertex3d(5,0,0);
|
||||
glColor3f(0.0,1.0,0.0);
|
||||
glVertex3d(0,5,0);
|
||||
glColor3f(0.0,0.0,1.0);
|
||||
glVertex3d(0,0,5);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void fill_display_lists() {
|
||||
glNewList(object_list_, GL_COMPILE);
|
||||
Vertex_iterator v;
|
||||
for(v=vertices_.begin();v!=vertices_.end();++v)
|
||||
draw(v);
|
||||
glEndList();
|
||||
|
||||
glNewList(object_list_+1, GL_COMPILE);
|
||||
Edge_iterator e;
|
||||
for(e=edges_.begin();e!=edges_.end();++e)
|
||||
draw(e);
|
||||
glEndList();
|
||||
|
||||
glNewList(object_list_+2, GL_COMPILE);
|
||||
Halffacet_iterator f;
|
||||
for(f=halffacets_.begin();f!=halffacets_.end();++f)
|
||||
draw(f);
|
||||
glEndList();
|
||||
|
||||
glNewList(object_list_+3, GL_COMPILE); // axes:
|
||||
construct_axes();
|
||||
glEndList();
|
||||
|
||||
}
|
||||
|
||||
void init() {
|
||||
if (init_) return;
|
||||
init_ = true;
|
||||
switches[SNC_AXES] = false;
|
||||
style = SNC_BOUNDARY;
|
||||
object_list_ = glGenLists(4);
|
||||
CGAL_assertion(object_list_);
|
||||
fill_display_lists();
|
||||
}
|
||||
|
||||
|
||||
void draw() const
|
||||
{
|
||||
if (!is_initialized()) const_cast<Polyhedron&>(*this).init();
|
||||
double l = (std::max)( (std::max)( bbox().xmax() - bbox().xmin(),
|
||||
bbox().ymax() - bbox().ymin()),
|
||||
bbox().zmax() - bbox().zmin());
|
||||
if ( l < 1) // make sure that a single point doesn't screw up here
|
||||
l = 1;
|
||||
glScaled( 4.0/l, 4.0/l, 4.0/l);
|
||||
glTranslated( -(bbox().xmax() + bbox().xmin()) / 2.0,
|
||||
-(bbox().ymax() + bbox().ymin()) / 2.0,
|
||||
-(bbox().zmax() + bbox().zmin()) / 2.0);
|
||||
if (style == SNC_BOUNDARY) {
|
||||
//glEnable(GL_LIGHTING);
|
||||
glCallList(object_list_+2); // facets
|
||||
//glDisable(GL_LIGHTING);
|
||||
}
|
||||
// move edges and vertices a bit towards the view-point,
|
||||
// i.e., 1/100th of the unit vector in camera space
|
||||
// double f = l / 4.0 / 100.0;
|
||||
// glTranslated( z_vec[0] * f, z_vec[1] * f, z_vec[2] * f);
|
||||
glCallList(object_list_+1); // edges
|
||||
glCallList(object_list_); // vertices
|
||||
if (switches[SNC_AXES]) glCallList(object_list_+3); // axis
|
||||
}
|
||||
|
||||
void debug(std::ostream& os = std::cerr) const
|
||||
{
|
||||
os << "OGL::Polyhedron" << std::endl;
|
||||
os << "Vertices:" << std::endl;
|
||||
Vertex_iterator v;
|
||||
for(v=vertices_.begin();v!=vertices_.end();++v)
|
||||
os << " "<<*v<<", mark="<<v->mark()<<std::endl;
|
||||
os << "Edges:" << std::endl;
|
||||
Edge_iterator e;
|
||||
for(e=edges_.begin();e!=edges_.end();++e)
|
||||
os << " "<<*e<<", mark="<<e->mark()<<std::endl;
|
||||
os << "Facets:" << std::endl;
|
||||
Halffacet_iterator f;
|
||||
for(f=halffacets_.begin();f!=halffacets_.end();++f)
|
||||
f->debug(); os << std::endl;
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
}; // Polyhedron
|
||||
|
||||
template<typename Nef_polyhedron>
|
||||
class Nef3_Converter {
|
||||
typedef typename Nef_polyhedron::SNC_structure SNC_structure;
|
||||
typedef CGAL::SNC_decorator<SNC_structure> Base;
|
||||
typedef CGAL::SNC_FM_decorator<SNC_structure> FM_decorator;
|
||||
|
||||
public:
|
||||
typedef typename SNC_structure::Vertex_const_iterator Vertex_const_iterator;
|
||||
typedef typename SNC_structure::Halfedge_const_iterator Halfedge_const_iterator;
|
||||
typedef typename SNC_structure::Halffacet_const_iterator Halffacet_const_iterator;
|
||||
typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator;
|
||||
|
||||
typedef typename SNC_structure::Object_const_handle Object_const_handle;
|
||||
typedef typename SNC_structure::SHalfedge_const_handle SHalfedge_const_handle;
|
||||
typedef typename SNC_structure::SHalfloop_const_handle SHalfloop_const_handle;
|
||||
|
||||
typedef typename SNC_structure::Vertex_const_handle Vertex_const_handle;
|
||||
typedef typename SNC_structure::Halfedge_const_handle Halfedge_const_handle;
|
||||
typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle;
|
||||
|
||||
typedef typename SNC_structure::Point_3 Point_3;
|
||||
typedef typename SNC_structure::Vector_3 Vector_3;
|
||||
typedef typename SNC_structure::Segment_3 Segment_3;
|
||||
typedef typename SNC_structure::Plane_3 Plane_3;
|
||||
typedef typename SNC_structure::Mark Mark;
|
||||
typedef typename SNC_structure::SHalfedge_around_facet_const_circulator
|
||||
SHalfedge_around_facet_const_circulator;
|
||||
|
||||
private:
|
||||
static OGL::Double_point double_point(const Point_3& p)
|
||||
{ return OGL::Double_point(CGAL::to_double(p.x()),
|
||||
CGAL::to_double(p.y()),
|
||||
CGAL::to_double(p.z())); }
|
||||
|
||||
static OGL::Double_segment double_segment(const Segment_3& s)
|
||||
{ return OGL::Double_segment(double_point(s.source()),
|
||||
double_point(s.target())); }
|
||||
|
||||
static void draw(Vertex_const_handle v, const Nef_polyhedron& ,
|
||||
CGAL::OGL::Polyhedron& P) {
|
||||
Point_3 bp = v->point();
|
||||
// CGAL_NEF_TRACEN("vertex " << bp);
|
||||
P.push_back(double_point(bp), v->mark());
|
||||
}
|
||||
|
||||
static void draw(Halfedge_const_handle e, const Nef_polyhedron& ,
|
||||
CGAL::OGL::Polyhedron& P) {
|
||||
Vertex_const_handle s = e->source();
|
||||
Vertex_const_handle t = e->twin()->source();
|
||||
Segment_3 seg(s->point(),t->point());
|
||||
// CGAL_NEF_TRACEN("edge " << seg);
|
||||
P.push_back(double_segment(seg), e->mark());
|
||||
}
|
||||
|
||||
static void draw(Halffacet_const_handle f, const Nef_polyhedron& ,
|
||||
CGAL::OGL::Polyhedron& P) {
|
||||
OGL::DFacet g;
|
||||
Halffacet_cycle_const_iterator fc; // all facet cycles:
|
||||
CGAL_forall_facet_cycles_of(fc,f)
|
||||
if ( fc.is_shalfedge() ) { // non-trivial facet cycle
|
||||
g.new_facet_cycle();
|
||||
SHalfedge_const_handle h = fc;
|
||||
SHalfedge_around_facet_const_circulator hc(h), he(hc);
|
||||
CGAL_For_all(hc,he){ // all vertex coordinates in facet cycle
|
||||
Point_3 sp = hc->source()->source()->point();
|
||||
// CGAL_NEF_TRACEN(" ");CGAL_NEF_TRACEN("facet" << sp);
|
||||
g.push_back_vertex(double_point(sp));
|
||||
}
|
||||
}
|
||||
Vector_3 v = f->plane().orthogonal_vector();
|
||||
g.set_normal(CGAL::to_double(v.x()),
|
||||
CGAL::to_double(v.y()),
|
||||
CGAL::to_double(v.z()),
|
||||
f->mark());
|
||||
P.push_back(g);
|
||||
}
|
||||
|
||||
// Returns the bounding box of the finite vertices of the polyhedron.
|
||||
// Returns $[-1,+1]^3$ as bounding box if no finite vertex exists.
|
||||
|
||||
static Bbox_3 bounded_bbox(const Nef_polyhedron& N) {
|
||||
bool first_vertex = true;
|
||||
Bbox_3 bbox( -1.0, -1.0, -1.0, 1.0, 1.0, 1.0);
|
||||
Vertex_const_iterator vi;
|
||||
CGAL_forall_vertices(vi, N) {
|
||||
Point_3 p = vi->point();
|
||||
double x = CGAL::to_double(p.hx());
|
||||
double y = CGAL::to_double(p.hy());
|
||||
double z = CGAL::to_double(p.hz());
|
||||
double w = CGAL::to_double(p.hw());
|
||||
if (N.is_standard(vi)) {
|
||||
if(first_vertex) {
|
||||
bbox = Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w);
|
||||
first_vertex = false;
|
||||
} else {
|
||||
bbox = bbox + Bbox_3(x/w, y/w, z/w, x/w, y/w, z/w);
|
||||
first_vertex = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bbox;
|
||||
}
|
||||
|
||||
static void set_R(Bbox_3& bbox, const Nef_polyhedron& N) {
|
||||
if(N.is_standard_kernel()) return;
|
||||
double size = abs(bbox.xmin());
|
||||
if(size < bbox.xmax()) size = bbox.xmax();
|
||||
if(size < bbox.ymin()) size = bbox.ymin();
|
||||
if(size < bbox.ymax()) size = bbox.ymax();
|
||||
if(size < bbox.zmin()) size = bbox.zmin();
|
||||
if(size < bbox.zmax()) size = bbox.zmax();
|
||||
N.set_size_of_infimaximal_box(size*50);
|
||||
// CGAL_NEF_TRACEN("set infi box size to " << size);
|
||||
Vertex_const_iterator vi;
|
||||
CGAL_forall_vertices(vi, N)
|
||||
if(N.is_standard(vi))
|
||||
return;
|
||||
bbox = Bbox_3(bbox.xmin()*10,bbox.ymin()*10,bbox.zmin()*10,
|
||||
bbox.xmax()*10,bbox.ymax()*10,bbox.zmax()*10);
|
||||
}
|
||||
public:
|
||||
static void convert_to_OGLPolyhedron(const Nef_polyhedron& N, CGAL::OGL::Polyhedron* P) {
|
||||
Bbox_3 bbox(bounded_bbox(N));
|
||||
set_R(bbox,N);
|
||||
P->bbox() = bbox;
|
||||
Vertex_const_iterator v;
|
||||
CGAL_forall_vertices(v,*N.sncp()) draw(v,N,*P);
|
||||
Halfedge_const_iterator e;
|
||||
CGAL_forall_edges(e,*N.sncp()) draw(e,N,*P);
|
||||
Halffacet_const_iterator f;
|
||||
CGAL_forall_facets(f,*N.sncp()) draw(f,N,*P);
|
||||
}
|
||||
|
||||
}; // Nef3_Converter
|
||||
|
||||
} // namespace OGL
|
||||
|
||||
} //namespace CGAL
|
||||
#endif // CGAL_NEF_OPENGL_HELPER_H
|
|
@ -1,6 +1,6 @@
|
|||
#include "PolySetCGALRenderer.h"
|
||||
#include "PolySetCGALEvaluator.h"
|
||||
#include "polyset.h"
|
||||
#include "CGALRenderer.h"
|
||||
#include "CGALEvaluator.h"
|
||||
#include "projectionnode.h"
|
||||
#include "dxflinextrudenode.h"
|
||||
#include "dxfrotextrudenode.h"
|
||||
|
@ -12,12 +12,12 @@
|
|||
#include "export.h" // void cgal_nef3_to_polyset()
|
||||
#include "openscad.h" // get_fragments_from_r()
|
||||
|
||||
PolySet *PolySetCGALRenderer::renderPolySet(const ProjectionNode &node, AbstractPolyNode::render_mode_e)
|
||||
PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node, AbstractPolyNode::render_mode_e)
|
||||
{
|
||||
const string &cacheid = this->cgalrenderer.getTree().getString(node);
|
||||
const string &cacheid = this->cgalevaluator.getTree().getString(node);
|
||||
if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link();
|
||||
|
||||
CGAL_Nef_polyhedron N = this->cgalrenderer.renderCGALMesh(node);
|
||||
CGAL_Nef_polyhedron N = this->cgalevaluator.evaluateCGALMesh(node);
|
||||
|
||||
PolySet *ps = new PolySet();
|
||||
ps->convexity = node.convexity;
|
||||
|
@ -64,7 +64,7 @@ PolySet *PolySetCGALRenderer::renderPolySet(const ProjectionNode &node, Abstract
|
|||
cube->append_vertex(x1, y1, z1);
|
||||
cube->append_vertex(x1, y1, z2);
|
||||
cube->append_vertex(x1, y2, z2);
|
||||
CGAL_Nef_polyhedron Ncube = this->cgalrenderer.renderCGALMesh(*cube);
|
||||
CGAL_Nef_polyhedron Ncube = this->cgalevaluator.evaluateCGALMesh(*cube);
|
||||
cube->unlink();
|
||||
|
||||
// N.p3 *= CGAL_Nef_polyhedron3(CGAL_Plane(0, 0, 1, 0), CGAL_Nef_polyhedron3::INCLUDED);
|
||||
|
@ -234,9 +234,9 @@ static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2,
|
|||
}
|
||||
}
|
||||
|
||||
PolySet *PolySetCGALRenderer::renderPolySet(const DxfLinearExtrudeNode &node, AbstractPolyNode::render_mode_e)
|
||||
PolySet *PolySetCGALEvaluator::evaluatePolySet(const DxfLinearExtrudeNode &node, AbstractPolyNode::render_mode_e)
|
||||
{
|
||||
const string &cacheid = this->cgalrenderer.getTree().getString(node);
|
||||
const string &cacheid = this->cgalevaluator.getTree().getString(node);
|
||||
if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link();
|
||||
|
||||
DxfData *dxf;
|
||||
|
@ -249,7 +249,7 @@ PolySet *PolySetCGALRenderer::renderPolySet(const DxfLinearExtrudeNode &node, Ab
|
|||
N.dim = 2;
|
||||
foreach (AbstractNode * v, node.getChildren()) {
|
||||
if (v->modinst->tag_background) continue;
|
||||
N.p2 += this->cgalrenderer.renderCGALMesh(*v).p2;
|
||||
N.p2 += this->cgalevaluator.evaluateCGALMesh(*v).p2;
|
||||
}
|
||||
|
||||
dxf = new DxfData(N);
|
||||
|
@ -324,10 +324,10 @@ PolySet *PolySetCGALRenderer::renderPolySet(const DxfLinearExtrudeNode &node, Ab
|
|||
return ps;
|
||||
}
|
||||
|
||||
PolySet *PolySetCGALRenderer::renderPolySet(const DxfRotateExtrudeNode &node,
|
||||
PolySet *PolySetCGALEvaluator::evaluatePolySet(const DxfRotateExtrudeNode &node,
|
||||
AbstractPolyNode::render_mode_e)
|
||||
{
|
||||
const string &cacheid = this->cgalrenderer.getTree().getString(node);
|
||||
const string &cacheid = this->cgalevaluator.getTree().getString(node);
|
||||
if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link();
|
||||
|
||||
DxfData *dxf;
|
||||
|
@ -340,7 +340,7 @@ PolySet *PolySetCGALRenderer::renderPolySet(const DxfRotateExtrudeNode &node,
|
|||
N.dim = 2;
|
||||
foreach (AbstractNode * v, node.getChildren()) {
|
||||
if (v->modinst->tag_background) continue;
|
||||
N.p2 += this->cgalrenderer.renderCGALMesh(*v).p2;
|
||||
N.p2 += this->cgalevaluator.evaluateCGALMesh(*v).p2;
|
||||
}
|
||||
|
||||
dxf = new DxfData(N);
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef POLYSETCGALEVALUATOR_H_
|
||||
#define POLYSETCGALEVALUATOR_H_
|
||||
|
||||
#include "PolySetEvaluator.h"
|
||||
|
||||
/*!
|
||||
This is a PolySet evaluator which uses the CGALEvaluator to support building
|
||||
polysets.
|
||||
*/
|
||||
class PolySetCGALEvaluator : public PolySetEvaluator
|
||||
{
|
||||
public:
|
||||
PolySetCGALEvaluator(class CGALEvaluator &CGALEvaluator) :
|
||||
PolySetEvaluator(), cgalevaluator(CGALEvaluator) { }
|
||||
virtual ~PolySetCGALEvaluator() { }
|
||||
virtual PolySet *evaluatePolySet(const ProjectionNode &node, AbstractPolyNode::render_mode_e);
|
||||
virtual PolySet *evaluatePolySet(const DxfLinearExtrudeNode &node, AbstractPolyNode::render_mode_e);
|
||||
virtual PolySet *evaluatePolySet(const DxfRotateExtrudeNode &node, AbstractPolyNode::render_mode_e);
|
||||
|
||||
private:
|
||||
CGALEvaluator &cgalevaluator;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,24 +0,0 @@
|
|||
#ifndef POLYSETCGALRENDERER_H_
|
||||
#define POLYSETCGALRENDERER_H_
|
||||
|
||||
#include "PolySetRenderer.h"
|
||||
|
||||
/*!
|
||||
This is a PolySet renderer which uses the CGALRenderer to support building
|
||||
polysets.
|
||||
*/
|
||||
class PolySetCGALRenderer : public PolySetRenderer
|
||||
{
|
||||
public:
|
||||
PolySetCGALRenderer(class CGALRenderer &cgalrenderer) :
|
||||
PolySetRenderer(), cgalrenderer(cgalrenderer) { }
|
||||
virtual ~PolySetCGALRenderer() { }
|
||||
virtual PolySet *renderPolySet(const ProjectionNode &node, AbstractPolyNode::render_mode_e);
|
||||
virtual PolySet *renderPolySet(const DxfLinearExtrudeNode &node, AbstractPolyNode::render_mode_e);
|
||||
virtual PolySet *renderPolySet(const DxfRotateExtrudeNode &node, AbstractPolyNode::render_mode_e);
|
||||
|
||||
private:
|
||||
CGALRenderer &cgalrenderer;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
#include "PolySetEvaluator.h"
|
||||
#include "printutils.h"
|
||||
#include "polyset.h"
|
||||
|
||||
PolySetEvaluator *PolySetEvaluator::global_evaluator = NULL;
|
||||
|
||||
PolySetEvaluator::cache_entry::cache_entry(PolySet *ps) :
|
||||
ps(ps), msg(print_messages_stack.last())
|
||||
{
|
||||
}
|
||||
|
||||
PolySetEvaluator::cache_entry::~cache_entry()
|
||||
{
|
||||
ps->unlink();
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef POLYSETEVALUATOR_H_
|
||||
#define POLYSETEVALUATOR_H_
|
||||
|
||||
#include "myqhash.h"
|
||||
#include "node.h"
|
||||
#include <QCache>
|
||||
|
||||
class PolySetEvaluator
|
||||
{
|
||||
public:
|
||||
enum EvaluateMode { EVALUATE_CGAL, EVALUATE_OPENCSG };
|
||||
PolySetEvaluator() : cache(100) {}
|
||||
|
||||
virtual ~PolySetEvaluator() {}
|
||||
|
||||
virtual PolySet *evaluatePolySet(const class ProjectionNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *evaluatePolySet(const class DxfLinearExtrudeNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *evaluatePolySet(const class DxfRotateExtrudeNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
|
||||
void clearCache() {
|
||||
this->cache.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
struct cache_entry {
|
||||
class PolySet *ps;
|
||||
QString msg;
|
||||
cache_entry(PolySet *ps);
|
||||
~cache_entry();
|
||||
};
|
||||
|
||||
QCache<std::string, cache_entry> cache;
|
||||
|
||||
private:
|
||||
static PolySetEvaluator *global_evaluator;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,15 +0,0 @@
|
|||
#include "PolySetRenderer.h"
|
||||
#include "printutils.h"
|
||||
#include "polyset.h"
|
||||
|
||||
PolySetRenderer *PolySetRenderer::global_renderer = NULL;
|
||||
|
||||
PolySetRenderer::cache_entry::cache_entry(PolySet *ps) :
|
||||
ps(ps), msg(print_messages_stack.last())
|
||||
{
|
||||
}
|
||||
|
||||
PolySetRenderer::cache_entry::~cache_entry()
|
||||
{
|
||||
ps->unlink();
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#ifndef POLYSETRENDERER_H_
|
||||
#define POLYSETRENDERER_H_
|
||||
|
||||
#include "myqhash.h"
|
||||
#include "node.h"
|
||||
#include <QCache>
|
||||
|
||||
class PolySetRenderer
|
||||
{
|
||||
public:
|
||||
enum RenderMode { RENDER_CGAL, RENDER_OPENCSG };
|
||||
PolySetRenderer() : cache(100) {}
|
||||
|
||||
virtual ~PolySetRenderer() {}
|
||||
|
||||
virtual PolySet *renderPolySet(const class ProjectionNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *renderPolySet(const class DxfLinearExtrudeNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *renderPolySet(const class DxfRotateExtrudeNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
|
||||
void clearCache() {
|
||||
this->cache.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
struct cache_entry {
|
||||
class PolySet *ps;
|
||||
QString msg;
|
||||
cache_entry(PolySet *ps);
|
||||
~cache_entry();
|
||||
};
|
||||
|
||||
QCache<std::string, cache_entry> cache;
|
||||
|
||||
private:
|
||||
static PolySetRenderer *global_renderer;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cgalrenderer.h"
|
||||
#include "polyset.h"
|
||||
#include "CGAL_renderer.h"
|
||||
#include "dxfdata.h"
|
||||
#include "dxftess.h"
|
||||
|
||||
#include "Preferences.h"
|
||||
|
||||
CGALRenderer::CGALRenderer(const CGAL_Nef_polyhedron &root) : root(root)
|
||||
{
|
||||
if (root.dim == 2) {
|
||||
DxfData dd(root);
|
||||
this->polyset = new PolySet();
|
||||
this->polyset->is2d = true;
|
||||
dxf_tesselate(this->polyset, &dd, 0, true, false, 0);
|
||||
}
|
||||
else if (root.dim == 3) {
|
||||
this->polyhedron = new Polyhedron();
|
||||
// FIXME: Make independent of Preferences
|
||||
this->polyhedron->setColor(Polyhedron::CGAL_NEF3_MARKED_FACET_COLOR,
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).red(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).green(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).blue());
|
||||
this->polyhedron->setColor(Polyhedron::CGAL_NEF3_UNMARKED_FACET_COLOR,
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).red(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).green(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).blue());
|
||||
|
||||
CGAL::OGL::Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(this->root.p3, this->polyhedron);
|
||||
this->polyhedron->init();
|
||||
}
|
||||
}
|
||||
|
||||
CGALRenderer::~CGALRenderer()
|
||||
{
|
||||
if (this->polyset) this->polyset->unlink();
|
||||
}
|
||||
|
||||
void CGALRenderer::draw(bool showfaces, bool showedges) const
|
||||
{
|
||||
if (this->root.dim == 2) {
|
||||
// Draw 2D polygons
|
||||
glDisable(GL_LIGHTING);
|
||||
const QColor &col = Preferences::inst()->color(Preferences::CGAL_FACE_2D_COLOR);
|
||||
glColor3f(col.redF(), col.greenF(), col.blueF());
|
||||
|
||||
for (int i=0; i < this->polyset->polygons.size(); i++) {
|
||||
glBegin(GL_POLYGON);
|
||||
for (int j=0; j < this->polyset->polygons[i].size(); j++) {
|
||||
PolySet::Point p = this->polyset->polygons[i][j];
|
||||
glVertex3d(p.x, p.y, -0.1);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
typedef CGAL_Nef_polyhedron2::Explorer Explorer;
|
||||
typedef Explorer::Face_const_iterator fci_t;
|
||||
typedef Explorer::Halfedge_around_face_const_circulator heafcc_t;
|
||||
typedef Explorer::Point Point;
|
||||
Explorer E = this->root.p2.explorer();
|
||||
|
||||
// Draw 2D edges
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2);
|
||||
const QColor &col2 = Preferences::inst()->color(Preferences::CGAL_EDGE_2D_COLOR);
|
||||
glColor3f(col2.redF(), col2.greenF(), col2.blueF());
|
||||
|
||||
// Extract the boundary, including inner boundaries of the polygons
|
||||
for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit) {
|
||||
bool fset = false;
|
||||
double fx = 0.0, fy = 0.0;
|
||||
heafcc_t fcirc(E.halfedge(fit)), fend(fcirc);
|
||||
CGAL_For_all(fcirc, fend) {
|
||||
if(E.is_standard(E.target(fcirc))) {
|
||||
Point p = E.point(E.target(fcirc));
|
||||
double x = to_double(p.x()), y = to_double(p.y());
|
||||
if (!fset) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
fx = x, fy = y;
|
||||
fset = true;
|
||||
}
|
||||
glVertex3d(x, y, -0.1);
|
||||
}
|
||||
}
|
||||
if (fset) {
|
||||
glVertex3d(fx, fy, -0.1);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
else if (this->root.dim == 3) {
|
||||
if (showfaces) this->polyhedron->set_style(SNC_BOUNDARY);
|
||||
else this->polyhedron->set_style(SNC_SKELETON);
|
||||
|
||||
this->polyhedron->draw(showfaces && showedges);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef CGALRENDERER_H_
|
||||
#define CGALRENDERER_H_
|
||||
|
||||
#include "renderer.h"
|
||||
#include "cgal.h"
|
||||
|
||||
class CGALRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
CGALRenderer(const CGAL_Nef_polyhedron &root);
|
||||
~CGALRenderer();
|
||||
void draw(bool showfaces, bool showedges) const;
|
||||
|
||||
private:
|
||||
const CGAL_Nef_polyhedron &root;
|
||||
class Polyhedron *polyhedron;
|
||||
class PolySet *polyset;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -35,7 +35,7 @@
|
|||
#include "polyset.h"
|
||||
#include "progress.h"
|
||||
#include "visitor.h"
|
||||
#include "PolySetRenderer.h"
|
||||
#include "PolySetEvaluator.h"
|
||||
#include "openscad.h" // get_fragments_from_r()
|
||||
|
||||
#include <sstream>
|
||||
|
@ -126,11 +126,11 @@ void register_builtin_dxf_linear_extrude()
|
|||
builtin_modules["linear_extrude"] = new DxfLinearExtrudeModule();
|
||||
}
|
||||
|
||||
PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e mode,
|
||||
PolySetRenderer *renderer) const
|
||||
PolySet *DxfLinearExtrudeNode::evaluate_polyset(render_mode_e mode,
|
||||
PolySetEvaluator *evaluator) const
|
||||
{
|
||||
if (!renderer) {
|
||||
PRINTF("WARNING: No suitable PolySetRenderer found for %s module!", this->name().c_str());
|
||||
if (!evaluator) {
|
||||
PRINTF("WARNING: No suitable PolySetEvaluator found for %s module!", this->name().c_str());
|
||||
PolySet *ps = new PolySet();
|
||||
ps->is2d = true;
|
||||
return ps;
|
||||
|
@ -138,7 +138,7 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e mode,
|
|||
|
||||
print_messages_push();
|
||||
|
||||
PolySet *ps = renderer->renderPolySet(*this, mode);
|
||||
PolySet *ps = evaluator->evaluatePolySet(*this, mode);
|
||||
|
||||
print_messages_pop();
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
double origin_x, origin_y, scale;
|
||||
bool center, has_twist;
|
||||
QString filename, layername;
|
||||
virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const;
|
||||
virtual PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "dxfdata.h"
|
||||
#include "progress.h"
|
||||
#include "visitor.h"
|
||||
#include "PolySetRenderer.h"
|
||||
#include "PolySetEvaluator.h"
|
||||
#include "openscad.h" // get_fragments_from_r()
|
||||
|
||||
#include <sstream>
|
||||
|
@ -102,11 +102,11 @@ void register_builtin_dxf_rotate_extrude()
|
|||
builtin_modules["rotate_extrude"] = new DxfRotateExtrudeModule();
|
||||
}
|
||||
|
||||
PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e mode,
|
||||
PolySetRenderer *renderer) const
|
||||
PolySet *DxfRotateExtrudeNode::evaluate_polyset(render_mode_e mode,
|
||||
PolySetEvaluator *evaluator) const
|
||||
{
|
||||
if (!renderer) {
|
||||
PRINTF("WARNING: No suitable PolySetRenderer found for %s module!", this->name().c_str());
|
||||
if (!evaluator) {
|
||||
PRINTF("WARNING: No suitable PolySetEvaluator found for %s module!", this->name().c_str());
|
||||
PolySet *ps = new PolySet();
|
||||
ps->is2d = true;
|
||||
return ps;
|
||||
|
@ -114,7 +114,7 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e mode,
|
|||
|
||||
print_messages_push();
|
||||
|
||||
PolySet *ps = renderer->renderPolySet(*this, mode);
|
||||
PolySet *ps = evaluator->evaluatePolySet(*this, mode);
|
||||
|
||||
print_messages_pop();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
double fn, fs, fa;
|
||||
double origin_x, origin_y, scale;
|
||||
QString filename, layername;
|
||||
virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const;
|
||||
virtual PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
223
src/glview.cc
223
src/glview.cc
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "GLView.h"
|
||||
#include "Preferences.h"
|
||||
#include "renderer.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWheelEvent>
|
||||
|
@ -41,9 +42,13 @@
|
|||
#include "mathc99.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef ENABLE_OPENCSG
|
||||
# include <opencsg.h>
|
||||
#endif
|
||||
|
||||
#define FAR_FAR_AWAY 100000.0
|
||||
|
||||
GLView::GLView(QWidget *parent) : QGLWidget(parent)
|
||||
GLView::GLView(QWidget *parent) : QGLWidget(parent), renderer(NULL)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
@ -64,16 +69,13 @@ void GLView::init()
|
|||
this->object_trans_z = 0;
|
||||
|
||||
this->mouse_drag_active = false;
|
||||
this->last_mouse_x = 0;
|
||||
this->last_mouse_y = 0;
|
||||
|
||||
this->showedges = false;
|
||||
this->showfaces = true;
|
||||
this->orthomode = false;
|
||||
this->showaxes = false;
|
||||
this->showcrosshairs = false;
|
||||
|
||||
this->renderfunc = NULL;
|
||||
this->renderfunc_vp = NULL;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
this->shaderinfo[i] = 0;
|
||||
|
||||
|
@ -87,10 +89,10 @@ void GLView::init()
|
|||
#endif
|
||||
}
|
||||
|
||||
void GLView::setRenderFunc(void (*func)(void*), void *userdata)
|
||||
void GLView::setRenderer(Renderer *r)
|
||||
{
|
||||
this->renderfunc = func;
|
||||
this->renderfunc_vp = userdata;
|
||||
this->renderer = r;
|
||||
updateGL();
|
||||
}
|
||||
|
||||
void GLView::initializeGL()
|
||||
|
@ -101,6 +103,22 @@ void GLView::initializeGL()
|
|||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
|
||||
GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0};
|
||||
GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0};
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
|
||||
glEnable(GL_LIGHT1);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
|
||||
#ifdef ENABLE_OPENCSG
|
||||
GLenum err = glewInit();
|
||||
if (GLEW_OK != err) {
|
||||
|
@ -266,43 +284,47 @@ void GLView::resizeGL(int w, int h)
|
|||
#endif
|
||||
glViewport(0, 0, w, h);
|
||||
w_h_ratio = sqrt((double)w / (double)h);
|
||||
|
||||
setupPerspective();
|
||||
}
|
||||
|
||||
void GLView::setupPerspective()
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY);
|
||||
}
|
||||
|
||||
void GLView::setupOrtho(double distance, bool offset)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if(offset)
|
||||
glTranslated(-0.8, -0.8, 0);
|
||||
double l = distance/10;
|
||||
glOrtho(-w_h_ratio*l, +w_h_ratio*l,
|
||||
-(1/w_h_ratio)*l, +(1/w_h_ratio)*l,
|
||||
-FAR_FAR_AWAY, +FAR_FAR_AWAY);
|
||||
}
|
||||
|
||||
void GLView::paintGL()
|
||||
{
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
if (orthomode)
|
||||
setupOrtho(viewer_distance);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
const QColor &bgcol = Preferences::inst()->color(Preferences::BACKGROUND_COLOR);
|
||||
glClearColor(bgcol.redF(), bgcol.greenF(), bgcol.blueF(), 0.0);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if (orthomode)
|
||||
glOrtho(-w_h_ratio*viewer_distance/10, +w_h_ratio*viewer_distance/10,
|
||||
-(1/w_h_ratio)*viewer_distance/10, +(1/w_h_ratio)*viewer_distance/10,
|
||||
-FAR_FAR_AWAY, +FAR_FAR_AWAY);
|
||||
else
|
||||
glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY);
|
||||
gluLookAt(0.0, -viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
|
||||
GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0};
|
||||
GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0};
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
|
||||
glEnable(GL_LIGHT1);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glTranslated(object_trans_x, object_trans_y, object_trans_z);
|
||||
|
||||
glRotated(object_rot_x, 1.0, 0.0, 0.0);
|
||||
glRotated(object_rot_y, 0.0, 1.0, 0.0);
|
||||
|
@ -325,8 +347,6 @@ void GLView::paintGL()
|
|||
glEnd();
|
||||
}
|
||||
|
||||
glTranslated(object_trans_x, object_trans_y, object_trans_z);
|
||||
|
||||
// Large gray axis cross inline with the model
|
||||
// FIXME: This is always gray - adjust color to keep contrast with background
|
||||
if (showaxes)
|
||||
|
@ -334,12 +354,13 @@ void GLView::paintGL()
|
|||
glLineWidth(1);
|
||||
glColor3d(0.5, 0.5, 0.5);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3d(-viewer_distance/10, 0, 0);
|
||||
glVertex3d(+viewer_distance/10, 0, 0);
|
||||
glVertex3d(0, -viewer_distance/10, 0);
|
||||
glVertex3d(0, +viewer_distance/10, 0);
|
||||
glVertex3d(0, 0, -viewer_distance/10);
|
||||
glVertex3d(0, 0, +viewer_distance/10);
|
||||
double l = viewer_distance/10;
|
||||
glVertex3d(-l, 0, 0);
|
||||
glVertex3d(+l, 0, 0);
|
||||
glVertex3d(0, -l, 0);
|
||||
glVertex3d(0, +l, 0);
|
||||
glVertex3d(0, 0, -l);
|
||||
glVertex3d(0, 0, +l);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
@ -350,20 +371,21 @@ void GLView::paintGL()
|
|||
glLineWidth(2);
|
||||
glColor3d(1.0, 0.0, 0.0);
|
||||
|
||||
if (renderfunc)
|
||||
renderfunc(renderfunc_vp);
|
||||
if (this->renderer) {
|
||||
#if defined(ENABLE_MDI) && defined(ENABLE_OPENCSG)
|
||||
// FIXME: This belongs in the OpenCSG renderer, but it doesn't know about this ID yet
|
||||
OpenCSG::setContext(this->opencsg_id);
|
||||
#endif
|
||||
this->renderer->draw(showfaces, showedges);
|
||||
}
|
||||
|
||||
// Small axis cross in the lower left corner
|
||||
if (showaxes)
|
||||
{
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glTranslated(-0.8, -0.8, 0);
|
||||
glOrtho(-w_h_ratio*1000/10, +w_h_ratio*1000/10,
|
||||
-(1/w_h_ratio)*1000/10, +(1/w_h_ratio)*1000/10,
|
||||
-FAR_FAR_AWAY, +FAR_FAR_AWAY);
|
||||
setupOrtho(1000,true);
|
||||
|
||||
gluLookAt(0.0, -1000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
@ -428,6 +450,10 @@ void GLView::paintGL()
|
|||
glVertex3d(zlabel_x-3, zlabel_y+3, 0); glVertex3d(zlabel_x+3, zlabel_y+3, 0);
|
||||
glVertex3d(zlabel_x-3, zlabel_y-3, 0); glVertex3d(zlabel_x+3, zlabel_y+3, 0);
|
||||
glEnd();
|
||||
|
||||
//Restore perspective for next paint
|
||||
if(!orthomode)
|
||||
setupPerspective();
|
||||
}
|
||||
|
||||
if (statusLabel) {
|
||||
|
@ -462,101 +488,48 @@ void GLView::wheelEvent(QWheelEvent *event)
|
|||
void GLView::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
mouse_drag_active = true;
|
||||
last_mouse_x = event->globalX();
|
||||
last_mouse_y = event->globalY();
|
||||
last_mouse = event->globalPos();
|
||||
grabMouse();
|
||||
setFocus();
|
||||
}
|
||||
|
||||
static void mat_id(double *trg)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
trg[i] = i%5 == 0;
|
||||
}
|
||||
|
||||
static void mat_mul(double *trg, const double *m1, const double *m2)
|
||||
void GLView::normalizeAngle(GLdouble& angle)
|
||||
{
|
||||
double m[16];
|
||||
for (int x = 0; x < 4; x++)
|
||||
for (int y = 0; y < 4; y++)
|
||||
{
|
||||
m[x+y*4] = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
m[x+y*4] += m1[i+y*4] * m2[x+i*4];
|
||||
}
|
||||
for (int i = 0; i < 16; i++)
|
||||
trg[i] = m[i];
|
||||
}
|
||||
|
||||
static void mat_rot(double *trg, double angle, double x, double y, double z)
|
||||
{
|
||||
double s = sin(M_PI*angle/180), c = cos(M_PI*angle/180);
|
||||
double cc = 1 - c;
|
||||
double m[16] = {
|
||||
x*x*cc+c, x*y*cc-z*s, x*z*cc+y*s, 0,
|
||||
y*x*cc+z*s, y*y*cc+c, y*z*cc-x*s, 0,
|
||||
x*z*cc-y*s, y*z*cc+x*s, z*z*cc+c, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
for (int i = 0; i < 16; i++)
|
||||
trg[i] = m[i];
|
||||
while(angle < 0)
|
||||
angle += 360;
|
||||
while(angle > 360)
|
||||
angle -= 360;
|
||||
}
|
||||
|
||||
void GLView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
int this_mouse_x = event->globalX();
|
||||
int this_mouse_y = event->globalY();
|
||||
QPoint this_mouse = event->globalPos();
|
||||
double dx = (this_mouse.x()-last_mouse.x()) * 0.7;
|
||||
double dy = (this_mouse.y()-last_mouse.y()) * 0.7;
|
||||
if (mouse_drag_active) {
|
||||
if ((event->buttons() & Qt::LeftButton) != 0) {
|
||||
object_rot_x += (this_mouse_y-last_mouse_y) * 0.7;
|
||||
object_rot_x += dy;
|
||||
if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0)
|
||||
object_rot_y += (this_mouse_x-last_mouse_x) * 0.7;
|
||||
object_rot_y += dx;
|
||||
else
|
||||
object_rot_z += (this_mouse_x-last_mouse_x) * 0.7;
|
||||
while (object_rot_x < 0)
|
||||
object_rot_x += 360;
|
||||
while (object_rot_x >= 360)
|
||||
object_rot_x -= 360;
|
||||
while (object_rot_y < 0)
|
||||
object_rot_y += 360;
|
||||
while (object_rot_y >= 360)
|
||||
object_rot_y -= 360;
|
||||
while (object_rot_z < 0)
|
||||
object_rot_z += 360;
|
||||
while (object_rot_z >= 360)
|
||||
object_rot_z -= 360;
|
||||
object_rot_z += dx;
|
||||
|
||||
normalizeAngle(object_rot_x);
|
||||
normalizeAngle(object_rot_y);
|
||||
normalizeAngle(object_rot_z);
|
||||
} else {
|
||||
double mx = +(this_mouse_x-last_mouse_x) * viewer_distance/1000;
|
||||
double my = -(this_mouse_y-last_mouse_y) * viewer_distance/1000;
|
||||
double rx[16], ry[16], rz[16], tm[16];
|
||||
mat_rot(rx, -object_rot_x, 1.0, 0.0, 0.0);
|
||||
mat_rot(ry, -object_rot_y, 0.0, 1.0, 0.0);
|
||||
mat_rot(rz, -object_rot_z, 0.0, 0.0, 1.0);
|
||||
mat_id(tm);
|
||||
mat_mul(tm, rx, tm);
|
||||
mat_mul(tm, ry, tm);
|
||||
mat_mul(tm, rz, tm);
|
||||
double vec[16] = {
|
||||
0, 0, 0, mx,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, my,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
if ((QApplication::keyboardModifiers() & Qt::ShiftModifier) != 0) {
|
||||
vec[3] = 0;
|
||||
vec[7] = my;
|
||||
vec[11] = 0;
|
||||
viewer_distance += (GLdouble)dy;
|
||||
} else {
|
||||
object_trans_x += dx;
|
||||
object_trans_z -= dy;
|
||||
}
|
||||
mat_mul(tm, tm, vec);
|
||||
object_trans_x += tm[3];
|
||||
object_trans_y += tm[7];
|
||||
object_trans_z += tm[11];
|
||||
}
|
||||
updateGL();
|
||||
emit doAnimateUpdate();
|
||||
}
|
||||
last_mouse_x = this_mouse_x;
|
||||
last_mouse_y = this_mouse_y;
|
||||
last_mouse = this_mouse;
|
||||
}
|
||||
|
||||
void GLView::mouseReleaseEvent(QMouseEvent*)
|
||||
|
|
|
@ -105,7 +105,7 @@ void register_builtin_import()
|
|||
builtin_modules["import_dxf"] = new ImportModule(TYPE_DXF);
|
||||
}
|
||||
|
||||
PolySet *ImportNode::render_polyset(render_mode_e, class PolySetRenderer *) const
|
||||
PolySet *ImportNode::evaluate_polyset(render_mode_e, class PolySetEvaluator *) const
|
||||
{
|
||||
PolySet *p = new PolySet();
|
||||
p->convexity = this->convexity;
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
int convexity;
|
||||
double fn, fs, fa;
|
||||
double origin_x, origin_y, scale;
|
||||
virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const;
|
||||
virtual PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
380
src/mainwin.cc
380
src/mainwin.cc
|
@ -40,14 +40,15 @@
|
|||
#include "dxftess.h"
|
||||
#include "progress.h"
|
||||
#ifdef ENABLE_OPENCSG
|
||||
#include "render-opencsg.h"
|
||||
#include "CSGTermRenderer.h"
|
||||
#include "CSGTermEvaluator.h"
|
||||
#include "opencsgRenderer.h"
|
||||
#endif
|
||||
#ifdef USE_PROGRESSWIDGET
|
||||
#include "ProgressWidget.h"
|
||||
#endif
|
||||
#include "CGALRenderer.h"
|
||||
#include "PolySetCGALRenderer.h"
|
||||
#include "CGALEvaluator.h"
|
||||
#include "PolySetCGALEvaluator.h"
|
||||
#include "thrownTogetherRenderer.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QTime>
|
||||
|
@ -83,32 +84,8 @@ using namespace boost::lambda;
|
|||
|
||||
#ifdef ENABLE_CGAL
|
||||
|
||||
#if 1
|
||||
#include "CGAL_renderer.h"
|
||||
using OpenSCAD::OGL::Polyhedron;
|
||||
using OpenSCAD::OGL::SNC_BOUNDARY;
|
||||
using OpenSCAD::OGL::SNC_SKELETON;
|
||||
using OpenSCAD::OGL::Nef3_Converter;
|
||||
#else
|
||||
// a little hackish: we need access to default-private members of
|
||||
// CGAL::OGL::Nef3_Converter so we can implement our own draw function
|
||||
// that does not scale the model. so we define 'class' to 'struct'
|
||||
// for this header..
|
||||
//
|
||||
// theoretically there could be two problems:
|
||||
// 1.) defining language keyword with the pre processor is illegal afair
|
||||
// 2.) the compiler could use a different memory layout or name mangling for structs
|
||||
//
|
||||
// both does not seam to be the case with todays compilers...
|
||||
//
|
||||
#define class struct
|
||||
#include <CGAL/Nef_3/OGL_helper.h>
|
||||
#undef class
|
||||
using CGAL::OGL::Polyhedron;
|
||||
using CGAL::OGL::SNC_BOUNDARY;
|
||||
using CGAL::OGL::SNC_SKELETON;
|
||||
using CGAL::OGL::Nef3_Converter;
|
||||
#endif
|
||||
#include "cgalrenderer.h"
|
||||
|
||||
#endif // ENABLE_CGAL
|
||||
|
||||
// Global application state
|
||||
|
@ -187,15 +164,16 @@ MainWindow::MainWindow(const QString &filename)
|
|||
root_chain = NULL;
|
||||
#ifdef ENABLE_CGAL
|
||||
this->root_N = NULL;
|
||||
this->recreate_cgal_ogl_p = false;
|
||||
cgal_ogl_p = NULL;
|
||||
cgal_ogl_ps = NULL;
|
||||
this->cgalRenderer = NULL;
|
||||
#endif
|
||||
#ifdef ENABLE_OPENCSG
|
||||
this->opencsgRenderer = NULL;
|
||||
#endif
|
||||
this->thrownTogetherRenderer = NULL;
|
||||
|
||||
highlights_chain = NULL;
|
||||
background_chain = NULL;
|
||||
root_node = NULL;
|
||||
enableOpenCSG = false;
|
||||
|
||||
tval = 0;
|
||||
fps = 0;
|
||||
|
@ -339,11 +317,6 @@ MainWindow::MainWindow(const QString &filename)
|
|||
connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));
|
||||
connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole()));
|
||||
|
||||
// #ifdef ENABLE_CGAL
|
||||
// viewActionCGALSurface = menu->addAction("CGAL Surfaces", this, SLOT(viewModeCGALSurface()), QKeySequence(Qt::Key_F10));
|
||||
// viewActionCGALGrid = menu->addAction("CGAL Grid Only", this, SLOT(viewModeCGALGrid()), QKeySequence(Qt::Key_F11));
|
||||
// #endif
|
||||
|
||||
// Help menu
|
||||
connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout()));
|
||||
connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage()));
|
||||
|
@ -443,19 +416,14 @@ MainWindow::loadDesignSettings()
|
|||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if (root_module)
|
||||
delete root_module;
|
||||
if (root_node)
|
||||
delete root_node;
|
||||
if (root_module) delete root_module;
|
||||
if (root_node) delete root_node;
|
||||
#ifdef ENABLE_CGAL
|
||||
if (this->root_N)
|
||||
delete this->root_N;
|
||||
if (cgal_ogl_p) {
|
||||
Polyhedron *p = (Polyhedron*)cgal_ogl_p;
|
||||
delete p;
|
||||
}
|
||||
if (cgal_ogl_ps)
|
||||
cgal_ogl_ps->unlink();
|
||||
if (this->root_N) delete this->root_N;
|
||||
delete this->cgalRenderer;
|
||||
#endif
|
||||
#ifdef ENABLE_OPENCSG
|
||||
delete this->opencsgRenderer;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -624,6 +592,16 @@ void MainWindow::compile(bool procevents)
|
|||
if (procevents)
|
||||
QApplication::processEvents();
|
||||
|
||||
// Invalidate renderers before we kill the CSG tree
|
||||
this->glview->setRenderer(NULL);
|
||||
if (this->opencsgRenderer) {
|
||||
delete this->opencsgRenderer;
|
||||
this->opencsgRenderer = NULL;
|
||||
}
|
||||
if (this->thrownTogetherRenderer) {
|
||||
delete this->thrownTogetherRenderer;
|
||||
this->thrownTogetherRenderer = NULL;
|
||||
}
|
||||
|
||||
// Remove previous CSG tree
|
||||
if (this->root_module) {
|
||||
|
@ -666,7 +644,6 @@ void MainWindow::compile(bool procevents)
|
|||
|
||||
this->root_node = NULL;
|
||||
this->tree.setRoot(NULL);
|
||||
this->enableOpenCSG = false;
|
||||
|
||||
// Initialize special variables
|
||||
this->root_ctx.set_variable("$t", Value(e_tval->text().toDouble()));
|
||||
|
@ -799,10 +776,10 @@ void MainWindow::compileCSG(bool procevents)
|
|||
try {
|
||||
// FIXME: put cache somewhere else as it's pretty useless now
|
||||
QHash<std::string, CGAL_Nef_polyhedron> cache;
|
||||
CGALRenderer cgalrenderer(cache, this->tree);
|
||||
PolySetCGALRenderer psrenderer(cgalrenderer);
|
||||
CSGTermRenderer csgrenderer(this->tree, &psrenderer);
|
||||
root_raw_term = csgrenderer.renderCSGTerm(*root_node, &highlight_terms, &background_terms);
|
||||
CGALEvaluator cgalevaluator(cache, this->tree);
|
||||
PolySetCGALEvaluator psevaluator(cgalevaluator);
|
||||
CSGTermEvaluator csgrenderer(this->tree, &psevaluator);
|
||||
root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, &highlight_terms, &background_terms);
|
||||
if (!root_raw_term) {
|
||||
PRINT("ERROR: CSG generation failed! (no top level object found)");
|
||||
if (procevents)
|
||||
|
@ -839,13 +816,6 @@ void MainWindow::compileCSG(bool procevents)
|
|||
root_chain = new CSGChain();
|
||||
root_chain->import(root_norm_term);
|
||||
|
||||
if (root_chain->polysets.size() > 1000) {
|
||||
PRINTF("WARNING: Normalized tree has %u elements!", root_chain->polysets.size());
|
||||
PRINTF("WARNING: OpenCSG rendering has been disabled.");
|
||||
} else {
|
||||
enableOpenCSG = true;
|
||||
}
|
||||
|
||||
if (highlight_terms.size() > 0)
|
||||
{
|
||||
PRINTF("Compiling highlights (%zu CSG Trees)...", highlight_terms.size());
|
||||
|
@ -883,6 +853,20 @@ void MainWindow::compileCSG(bool procevents)
|
|||
background_chain->import(background_terms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
this->opencsgRenderer = new OpenCSGRenderer(this->root_chain,
|
||||
this->highlights_chain,
|
||||
this->background_chain,
|
||||
this->glview->shaderinfo);
|
||||
}
|
||||
this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain,
|
||||
this->highlights_chain,
|
||||
this->background_chain);
|
||||
|
||||
PRINT("CSG generation finished.");
|
||||
int s = t.elapsed() / 1000;
|
||||
|
@ -1155,16 +1139,16 @@ void MainWindow::actionCompile()
|
|||
if (this->root_node) compileCSG(!viewActionAnimate->isChecked());
|
||||
|
||||
// Go to non-CGAL view mode
|
||||
if (!viewActionOpenCSG->isChecked() && !viewActionThrownTogether->isChecked()) {
|
||||
if (viewActionThrownTogether->isChecked()) {
|
||||
viewModeThrownTogether();
|
||||
}
|
||||
else {
|
||||
#ifdef ENABLE_OPENCSG
|
||||
viewModeOpenCSG();
|
||||
#else
|
||||
viewModeThrownTogether();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
this->glview->updateGL();
|
||||
}
|
||||
|
||||
if (viewActionAnimate->isChecked() && e_dump->isChecked()) {
|
||||
QImage img = this->glview->grabFrameBuffer();
|
||||
|
@ -1194,10 +1178,12 @@ void MainWindow::actionRenderCGAL()
|
|||
return;
|
||||
}
|
||||
|
||||
this->glview->setRenderer(NULL);
|
||||
delete this->cgalRenderer;
|
||||
this->cgalRenderer = NULL;
|
||||
if (this->root_N) {
|
||||
delete this->root_N;
|
||||
this->root_N = NULL;
|
||||
this->recreate_cgal_ogl_p = true;
|
||||
}
|
||||
|
||||
PRINT("Rendering Polygon Mesh using CGAL...");
|
||||
|
@ -1226,8 +1212,8 @@ void MainWindow::actionRenderCGAL()
|
|||
try {
|
||||
// FIXME: put cache somewhere else as it's pretty useless now
|
||||
QHash<std::string, CGAL_Nef_polyhedron> cache;
|
||||
CGALRenderer renderer(cache, this->tree);
|
||||
this->root_N = new CGAL_Nef_polyhedron(renderer.renderCGALMesh(*this->root_node));
|
||||
CGALEvaluator evaluator(cache, this->tree);
|
||||
this->root_N = new CGAL_Nef_polyhedron(evaluator.evaluateCGALMesh(*this->root_node));
|
||||
}
|
||||
catch (ProgressCancelException e) {
|
||||
PRINT("Rendering cancelled.");
|
||||
|
@ -1285,10 +1271,13 @@ void MainWindow::actionRenderCGAL()
|
|||
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()) {
|
||||
this->cgalRenderer = new CGALRenderer(*this->root_N);
|
||||
// Go to CGAL view mode
|
||||
if (viewActionCGALGrid->isChecked()) {
|
||||
viewModeCGALGrid();
|
||||
}
|
||||
else {
|
||||
viewModeCGALSurface();
|
||||
} else {
|
||||
this->glview->updateGL();
|
||||
}
|
||||
|
||||
PRINT("Rendering finished.");
|
||||
|
@ -1491,11 +1480,11 @@ void MainWindow::actionExportImage()
|
|||
|
||||
void MainWindow::actionFlushCaches()
|
||||
{
|
||||
// FIXME: Polycache -> PolySetRenderer
|
||||
// FIXME: PolySetRenderer->clearCache();
|
||||
// FIXME: Polycache -> PolySetEvaluator
|
||||
// FIXME: PolySetEvaluator->clearCache();
|
||||
#ifdef ENABLE_CGAL
|
||||
// FIXME: Flush caches through whatever channels we have
|
||||
// CGALRenderer::renderer()->getCache().clear();
|
||||
// CGALEvaluator::evaluator()->getCache().clear();
|
||||
// this->dumper->clearCache();
|
||||
#endif
|
||||
dxf_dim_cache.clear();
|
||||
|
@ -1514,37 +1503,6 @@ void MainWindow::viewModeActionsUncheck()
|
|||
|
||||
#ifdef ENABLE_OPENCSG
|
||||
|
||||
static void renderGLThrownTogether(void *vp);
|
||||
|
||||
static void renderGLviaOpenCSG(void *vp)
|
||||
{
|
||||
MainWindow *mainwin = (MainWindow *)vp;
|
||||
if (!mainwin->enableOpenCSG) {
|
||||
renderGLThrownTogether(vp);
|
||||
return;
|
||||
}
|
||||
static int glew_initialized = 0;
|
||||
if (!glew_initialized) {
|
||||
glew_initialized = 1;
|
||||
glewInit();
|
||||
}
|
||||
#ifdef ENABLE_MDI
|
||||
OpenCSG::setContext(mainwin->glview->opencsg_id);
|
||||
#endif
|
||||
if (mainwin->root_chain) {
|
||||
GLint *shaderinfo = mainwin->glview->shaderinfo;
|
||||
if (!shaderinfo[0])
|
||||
shaderinfo = NULL;
|
||||
renderCSGChainviaOpenCSG(mainwin->root_chain, mainwin->viewActionShowEdges->isChecked() ? shaderinfo : NULL, false, false);
|
||||
if (mainwin->background_chain) {
|
||||
renderCSGChainviaOpenCSG(mainwin->background_chain, mainwin->viewActionShowEdges->isChecked() ? shaderinfo : NULL, false, true);
|
||||
}
|
||||
if (mainwin->highlights_chain) {
|
||||
renderCSGChainviaOpenCSG(mainwin->highlights_chain, mainwin->viewActionShowEdges->isChecked() ? shaderinfo : NULL, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Go to the OpenCSG view mode.
|
||||
Falls back to thrown together mode if OpenCSG is not available
|
||||
|
@ -1554,8 +1512,7 @@ void MainWindow::viewModeOpenCSG()
|
|||
if (this->glview->hasOpenCSGSupport()) {
|
||||
viewModeActionsUncheck();
|
||||
viewActionOpenCSG->setChecked(true);
|
||||
this->glview->setRenderFunc(renderGLviaOpenCSG, this);
|
||||
this->glview->updateGL();
|
||||
this->glview->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer);
|
||||
} else {
|
||||
viewModeThrownTogether();
|
||||
}
|
||||
|
@ -1565,125 +1522,12 @@ void MainWindow::viewModeOpenCSG()
|
|||
|
||||
#ifdef ENABLE_CGAL
|
||||
|
||||
static void renderGLviaCGAL(void *vp)
|
||||
{
|
||||
MainWindow *m = (MainWindow*)vp;
|
||||
if (m->recreate_cgal_ogl_p) {
|
||||
m->recreate_cgal_ogl_p = false;
|
||||
Polyhedron *p = (Polyhedron*)m->cgal_ogl_p;
|
||||
delete p;
|
||||
m->cgal_ogl_p = NULL;
|
||||
if (m->cgal_ogl_ps)
|
||||
m->cgal_ogl_ps->unlink();
|
||||
m->cgal_ogl_ps = NULL;
|
||||
}
|
||||
if (!m->root_N) return;
|
||||
if (m->root_N->dim == 2)
|
||||
{
|
||||
if (m->cgal_ogl_ps == NULL) {
|
||||
DxfData dd(*m->root_N);
|
||||
m->cgal_ogl_ps = new PolySet();
|
||||
m->cgal_ogl_ps->is2d = true;
|
||||
dxf_tesselate(m->cgal_ogl_ps, &dd, 0, true, false, 0);
|
||||
}
|
||||
|
||||
// Draw 2D polygons
|
||||
glDisable(GL_LIGHTING);
|
||||
const QColor &col = Preferences::inst()->color(Preferences::CGAL_FACE_2D_COLOR);
|
||||
glColor3f(col.redF(), col.greenF(), col.blueF());
|
||||
|
||||
for (int i=0; i < m->cgal_ogl_ps->polygons.size(); i++) {
|
||||
glBegin(GL_POLYGON);
|
||||
for (int j=0; j < m->cgal_ogl_ps->polygons[i].size(); j++) {
|
||||
PolySet::Point p = m->cgal_ogl_ps->polygons[i][j];
|
||||
glVertex3d(p.x, p.y, -0.1);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
typedef CGAL_Nef_polyhedron2::Explorer Explorer;
|
||||
typedef Explorer::Face_const_iterator fci_t;
|
||||
typedef Explorer::Halfedge_around_face_const_circulator heafcc_t;
|
||||
typedef Explorer::Point Point;
|
||||
Explorer E = m->root_N->p2.explorer();
|
||||
|
||||
// Draw 2D edges
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glLineWidth(2);
|
||||
const QColor &col2 = Preferences::inst()->color(Preferences::CGAL_EDGE_2D_COLOR);
|
||||
glColor3f(col2.redF(), col2.greenF(), col2.blueF());
|
||||
|
||||
// Extract the boundary, including inner boundaries of the polygons
|
||||
for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit)
|
||||
{
|
||||
bool fset = false;
|
||||
double fx = 0.0, fy = 0.0;
|
||||
heafcc_t fcirc(E.halfedge(fit)), fend(fcirc);
|
||||
CGAL_For_all(fcirc, fend) {
|
||||
if(E.is_standard(E.target(fcirc))) {
|
||||
Point p = E.point(E.target(fcirc));
|
||||
double x = to_double(p.x()), y = to_double(p.y());
|
||||
if (!fset) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
fx = x, fy = y;
|
||||
fset = true;
|
||||
}
|
||||
glVertex3d(x, y, -0.1);
|
||||
}
|
||||
}
|
||||
if (fset) {
|
||||
glVertex3d(fx, fy, -0.1);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
else if (m->root_N->dim == 3)
|
||||
{
|
||||
Polyhedron *p = (Polyhedron*)m->cgal_ogl_p;
|
||||
if (!p) {
|
||||
Nef3_Converter<CGAL_Nef_polyhedron3>::setColor(Polyhedron::CGAL_NEF3_MARKED_FACET_COLOR,
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).red(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).green(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_BACK_COLOR).blue());
|
||||
Nef3_Converter<CGAL_Nef_polyhedron3>::setColor(Polyhedron::CGAL_NEF3_UNMARKED_FACET_COLOR,
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).red(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).green(),
|
||||
Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).blue());
|
||||
m->cgal_ogl_p = p = new Polyhedron();
|
||||
Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(m->root_N->p3, p);
|
||||
p->init();
|
||||
}
|
||||
if (m->viewActionCGALSurfaces->isChecked())
|
||||
p->set_style(SNC_BOUNDARY);
|
||||
if (m->viewActionCGALGrid->isChecked())
|
||||
p->set_style(SNC_SKELETON);
|
||||
#if 0
|
||||
p->draw();
|
||||
#else
|
||||
if (p->style == SNC_BOUNDARY) {
|
||||
glCallList(p->object_list_+2);
|
||||
if (m->viewActionShowEdges->isChecked()) {
|
||||
glDisable(GL_LIGHTING);
|
||||
glCallList(p->object_list_+1);
|
||||
glCallList(p->object_list_);
|
||||
}
|
||||
} else {
|
||||
glDisable(GL_LIGHTING);
|
||||
glCallList(p->object_list_+1);
|
||||
glCallList(p->object_list_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::viewModeCGALSurface()
|
||||
{
|
||||
viewModeActionsUncheck();
|
||||
viewActionCGALSurfaces->setChecked(true);
|
||||
this->glview->setRenderFunc(renderGLviaCGAL, this);
|
||||
this->glview->setShowFaces(true);
|
||||
this->glview->setRenderer(this->cgalRenderer);
|
||||
this->glview->updateGL();
|
||||
}
|
||||
|
||||
|
@ -1691,104 +1535,24 @@ void MainWindow::viewModeCGALGrid()
|
|||
{
|
||||
viewModeActionsUncheck();
|
||||
viewActionCGALGrid->setChecked(true);
|
||||
this->glview->setRenderFunc(renderGLviaCGAL, this);
|
||||
this->glview->updateGL();
|
||||
this->glview->setShowFaces(false);
|
||||
this->glview->setRenderer(this->cgalRenderer);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_CGAL */
|
||||
|
||||
static void renderGLThrownTogetherChain(MainWindow *m, CSGChain *chain, bool highlight, bool background, bool fberror)
|
||||
{
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
QHash<QPair<PolySet*,double*>,int> polySetVisitMark;
|
||||
bool showEdges = m->viewActionShowEdges->isChecked();
|
||||
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)
|
||||
{
|
||||
MainWindow *m = (MainWindow*)vp;
|
||||
if (m->root_chain) {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
renderGLThrownTogetherChain(m, m->root_chain, false, false, false);
|
||||
glCullFace(GL_FRONT);
|
||||
glColor3ub(255, 0, 255);
|
||||
renderGLThrownTogetherChain(m, m->root_chain, false, false, true);
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
if (m->background_chain)
|
||||
renderGLThrownTogetherChain(m, m->background_chain, false, true, false);
|
||||
if (m->highlights_chain)
|
||||
renderGLThrownTogetherChain(m, m->highlights_chain, true, false, false);
|
||||
}
|
||||
|
||||
void MainWindow::viewModeThrownTogether()
|
||||
{
|
||||
viewModeActionsUncheck();
|
||||
viewActionThrownTogether->setChecked(true);
|
||||
this->glview->setRenderFunc(renderGLThrownTogether, this);
|
||||
this->glview->updateGL();
|
||||
this->glview->setRenderer(this->thrownTogetherRenderer);
|
||||
}
|
||||
|
||||
void MainWindow::viewModeShowEdges()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.setValue("view/showEdges",viewActionShowEdges->isChecked());
|
||||
this->glview->setShowEdges(viewActionShowEdges->isChecked());
|
||||
this->glview->updateGL();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
#define rgb(r,g,b) (0xff000000 | (r << 16) | (g << 8) | b)
|
||||
|
||||
static const struct RGBData {
|
||||
const char *name;
|
||||
uint value;
|
||||
} named_colors[] = {
|
||||
{ "aliceblue", rgb(240, 248, 255) },
|
||||
{ "antiquewhite", rgb(250, 235, 215) },
|
||||
{ "aqua", rgb( 0, 255, 255) },
|
||||
{ "aquamarine", rgb(127, 255, 212) },
|
||||
{ "azure", rgb(240, 255, 255) },
|
||||
{ "beige", rgb(245, 245, 220) },
|
||||
{ "bisque", rgb(255, 228, 196) },
|
||||
{ "black", rgb( 0, 0, 0) },
|
||||
{ "blanchedalmond", rgb(255, 235, 205) },
|
||||
{ "blue", rgb( 0, 0, 255) },
|
||||
{ "blueviolet", rgb(138, 43, 226) },
|
||||
{ "brown", rgb(165, 42, 42) },
|
||||
{ "burlywood", rgb(222, 184, 135) },
|
||||
{ "cadetblue", rgb( 95, 158, 160) },
|
||||
{ "chartreuse", rgb(127, 255, 0) },
|
||||
{ "chocolate", rgb(210, 105, 30) },
|
||||
{ "coral", rgb(255, 127, 80) },
|
||||
{ "cornflowerblue", rgb(100, 149, 237) },
|
||||
{ "cornsilk", rgb(255, 248, 220) },
|
||||
{ "crimson", rgb(220, 20, 60) },
|
||||
{ "cyan", rgb( 0, 255, 255) },
|
||||
{ "darkblue", rgb( 0, 0, 139) },
|
||||
{ "darkcyan", rgb( 0, 139, 139) },
|
||||
{ "darkgoldenrod", rgb(184, 134, 11) },
|
||||
{ "darkgray", rgb(169, 169, 169) },
|
||||
{ "darkgreen", rgb( 0, 100, 0) },
|
||||
{ "darkgrey", rgb(169, 169, 169) },
|
||||
{ "darkkhaki", rgb(189, 183, 107) },
|
||||
{ "darkmagenta", rgb(139, 0, 139) },
|
||||
{ "darkolivegreen", rgb( 85, 107, 47) },
|
||||
{ "darkorange", rgb(255, 140, 0) },
|
||||
{ "darkorchid", rgb(153, 50, 204) },
|
||||
{ "darkred", rgb(139, 0, 0) },
|
||||
{ "darksalmon", rgb(233, 150, 122) },
|
||||
{ "darkseagreen", rgb(143, 188, 143) },
|
||||
{ "darkslateblue", rgb( 72, 61, 139) },
|
||||
{ "darkslategray", rgb( 47, 79, 79) },
|
||||
{ "darkslategrey", rgb( 47, 79, 79) },
|
||||
{ "darkturquoise", rgb( 0, 206, 209) },
|
||||
{ "darkviolet", rgb(148, 0, 211) },
|
||||
{ "deeppink", rgb(255, 20, 147) },
|
||||
{ "deepskyblue", rgb( 0, 191, 255) },
|
||||
{ "dimgray", rgb(105, 105, 105) },
|
||||
{ "dimgrey", rgb(105, 105, 105) },
|
||||
{ "dodgerblue", rgb( 30, 144, 255) },
|
||||
{ "firebrick", rgb(178, 34, 34) },
|
||||
{ "floralwhite", rgb(255, 250, 240) },
|
||||
{ "forestgreen", rgb( 34, 139, 34) },
|
||||
{ "fuchsia", rgb(255, 0, 255) },
|
||||
{ "gainsboro", rgb(220, 220, 220) },
|
||||
{ "ghostwhite", rgb(248, 248, 255) },
|
||||
{ "gold", rgb(255, 215, 0) },
|
||||
{ "goldenrod", rgb(218, 165, 32) },
|
||||
{ "gray", rgb(128, 128, 128) },
|
||||
{ "green", rgb( 0, 128, 0) },
|
||||
{ "greenyellow", rgb(173, 255, 47) },
|
||||
{ "grey", rgb(128, 128, 128) },
|
||||
{ "honeydew", rgb(240, 255, 240) },
|
||||
{ "hotpink", rgb(255, 105, 180) },
|
||||
{ "indianred", rgb(205, 92, 92) },
|
||||
{ "indigo", rgb( 75, 0, 130) },
|
||||
{ "ivory", rgb(255, 255, 240) },
|
||||
{ "khaki", rgb(240, 230, 140) },
|
||||
{ "lavender", rgb(230, 230, 250) },
|
||||
{ "lavenderblush", rgb(255, 240, 245) },
|
||||
{ "lawngreen", rgb(124, 252, 0) },
|
||||
{ "lemonchiffon", rgb(255, 250, 205) },
|
||||
{ "lightblue", rgb(173, 216, 230) },
|
||||
{ "lightcoral", rgb(240, 128, 128) },
|
||||
{ "lightcyan", rgb(224, 255, 255) },
|
||||
{ "lightgoldenrodyellow", rgb(250, 250, 210) },
|
||||
{ "lightgray", rgb(211, 211, 211) },
|
||||
{ "lightgreen", rgb(144, 238, 144) },
|
||||
{ "lightgrey", rgb(211, 211, 211) },
|
||||
{ "lightpink", rgb(255, 182, 193) },
|
||||
{ "lightsalmon", rgb(255, 160, 122) },
|
||||
{ "lightseagreen", rgb( 32, 178, 170) },
|
||||
{ "lightskyblue", rgb(135, 206, 250) },
|
||||
{ "lightslategray", rgb(119, 136, 153) },
|
||||
{ "lightslategrey", rgb(119, 136, 153) },
|
||||
{ "lightsteelblue", rgb(176, 196, 222) },
|
||||
{ "lightyellow", rgb(255, 255, 224) },
|
||||
{ "lime", rgb( 0, 255, 0) },
|
||||
{ "limegreen", rgb( 50, 205, 50) },
|
||||
{ "linen", rgb(250, 240, 230) },
|
||||
{ "magenta", rgb(255, 0, 255) },
|
||||
{ "maroon", rgb(128, 0, 0) },
|
||||
{ "mediumaquamarine", rgb(102, 205, 170) },
|
||||
{ "mediumblue", rgb( 0, 0, 205) },
|
||||
{ "mediumorchid", rgb(186, 85, 211) },
|
||||
{ "mediumpurple", rgb(147, 112, 219) },
|
||||
{ "mediumseagreen", rgb( 60, 179, 113) },
|
||||
{ "mediumslateblue", rgb(123, 104, 238) },
|
||||
{ "mediumspringgreen", rgb( 0, 250, 154) },
|
||||
{ "mediumturquoise", rgb( 72, 209, 204) },
|
||||
{ "mediumvioletred", rgb(199, 21, 133) },
|
||||
{ "midnightblue", rgb( 25, 25, 112) },
|
||||
{ "mintcream", rgb(245, 255, 250) },
|
||||
{ "mistyrose", rgb(255, 228, 225) },
|
||||
{ "moccasin", rgb(255, 228, 181) },
|
||||
{ "navajowhite", rgb(255, 222, 173) },
|
||||
{ "navy", rgb( 0, 0, 128) },
|
||||
{ "oldlace", rgb(253, 245, 230) },
|
||||
{ "olive", rgb(128, 128, 0) },
|
||||
{ "olivedrab", rgb(107, 142, 35) },
|
||||
{ "orange", rgb(255, 165, 0) },
|
||||
{ "orangered", rgb(255, 69, 0) },
|
||||
{ "orchid", rgb(218, 112, 214) },
|
||||
{ "palegoldenrod", rgb(238, 232, 170) },
|
||||
{ "palegreen", rgb(152, 251, 152) },
|
||||
{ "paleturquoise", rgb(175, 238, 238) },
|
||||
{ "palevioletred", rgb(219, 112, 147) },
|
||||
{ "papayawhip", rgb(255, 239, 213) },
|
||||
{ "peachpuff", rgb(255, 218, 185) },
|
||||
{ "peru", rgb(205, 133, 63) },
|
||||
{ "pink", rgb(255, 192, 203) },
|
||||
{ "plum", rgb(221, 160, 221) },
|
||||
{ "powderblue", rgb(176, 224, 230) },
|
||||
{ "purple", rgb(128, 0, 128) },
|
||||
{ "red", rgb(255, 0, 0) },
|
||||
{ "rosybrown", rgb(188, 143, 143) },
|
||||
{ "royalblue", rgb( 65, 105, 225) },
|
||||
{ "saddlebrown", rgb(139, 69, 19) },
|
||||
{ "salmon", rgb(250, 128, 114) },
|
||||
{ "sandybrown", rgb(244, 164, 96) },
|
||||
{ "seagreen", rgb( 46, 139, 87) },
|
||||
{ "seashell", rgb(255, 245, 238) },
|
||||
{ "sienna", rgb(160, 82, 45) },
|
||||
{ "silver", rgb(192, 192, 192) },
|
||||
{ "skyblue", rgb(135, 206, 235) },
|
||||
{ "slateblue", rgb(106, 90, 205) },
|
||||
{ "slategray", rgb(112, 128, 144) },
|
||||
{ "slategrey", rgb(112, 128, 144) },
|
||||
{ "snow", rgb(255, 250, 250) },
|
||||
{ "springgreen", rgb( 0, 255, 127) },
|
||||
{ "steelblue", rgb( 70, 130, 180) },
|
||||
{ "tan", rgb(210, 180, 140) },
|
||||
{ "teal", rgb( 0, 128, 128) },
|
||||
{ "thistle", rgb(216, 191, 216) },
|
||||
{ "tomato", rgb(255, 99, 71) },
|
||||
{ "transparent", 0 },
|
||||
{ "turquoise", rgb( 64, 224, 208) },
|
||||
{ "violet", rgb(238, 130, 238) },
|
||||
{ "wheat", rgb(245, 222, 179) },
|
||||
{ "white", rgb(255, 255, 255) },
|
||||
{ "whitesmoke", rgb(245, 245, 245) },
|
||||
{ "yellow", rgb(255, 255, 0) },
|
||||
{ "yellowgreen", rgb(154, 205, 50) }
|
||||
};
|
|
@ -83,7 +83,7 @@ public:
|
|||
/*! Should return a PolySet of the given geometry. It's normal to return an
|
||||
empty PolySet if smth. is wrong, but don't return NULL unless we change the calling
|
||||
strategy for this method. */
|
||||
virtual class PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *renderer) const = 0;
|
||||
virtual class PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *evaluator) const = 0;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const AbstractNode &node);
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "opencsgrenderer.h"
|
||||
#include "polyset.h"
|
||||
#include "csgterm.h"
|
||||
|
||||
class OpenCSGPrim : public OpenCSG::Primitive
|
||||
{
|
||||
public:
|
||||
OpenCSGPrim(OpenCSG::Operation operation, unsigned int convexity) :
|
||||
OpenCSG::Primitive(operation, convexity) { }
|
||||
PolySet *p;
|
||||
double *m;
|
||||
int csgmode;
|
||||
virtual void render() {
|
||||
glPushMatrix();
|
||||
glMultMatrixd(m);
|
||||
p->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m);
|
||||
glPopMatrix();
|
||||
}
|
||||
};
|
||||
|
||||
OpenCSGRenderer::OpenCSGRenderer(CSGChain *root_chain, CSGChain *highlights_chain,
|
||||
CSGChain *background_chain, GLint *shaderinfo)
|
||||
: root_chain(root_chain), highlights_chain(highlights_chain),
|
||||
background_chain(background_chain), shaderinfo(shaderinfo)
|
||||
{
|
||||
}
|
||||
|
||||
void OpenCSGRenderer::draw(bool showfaces, bool showedges) const
|
||||
{
|
||||
static int glew_initialized = 0;
|
||||
if (!glew_initialized) {
|
||||
glew_initialized = 1;
|
||||
glewInit();
|
||||
}
|
||||
if (this->root_chain) {
|
||||
GLint *shaderinfo = this->shaderinfo;
|
||||
if (!shaderinfo[0]) shaderinfo = NULL;
|
||||
renderCSGChain(this->root_chain, showedges ? shaderinfo : NULL, false, false);
|
||||
if (this->background_chain) {
|
||||
renderCSGChain(this->background_chain, showedges ? shaderinfo : NULL, false, true);
|
||||
}
|
||||
if (this->highlights_chain) {
|
||||
renderCSGChain(this->highlights_chain, showedges ? shaderinfo : NULL, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
|
||||
bool highlight, bool background) const
|
||||
{
|
||||
std::vector<OpenCSG::Primitive*> primitives;
|
||||
int j = 0;
|
||||
for (int i = 0;; i++)
|
||||
{
|
||||
bool last = i == chain->polysets.size();
|
||||
|
||||
if (last || chain->types[i] == CSGTerm::TYPE_UNION)
|
||||
{
|
||||
if (j+1 != i) {
|
||||
OpenCSG::render(primitives);
|
||||
glDepthFunc(GL_EQUAL);
|
||||
}
|
||||
if (shaderinfo)
|
||||
glUseProgram(shaderinfo[0]);
|
||||
for (; j < i; j++) {
|
||||
double *m = chain->matrices[j];
|
||||
glPushMatrix();
|
||||
glMultMatrixd(m);
|
||||
int csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
|
||||
if (highlight) {
|
||||
chain->polysets[j]->render_surface(PolySet::COLORMODE_HIGHLIGHT, PolySet::csgmode_e(csgmode + 20), m, shaderinfo);
|
||||
} else if (background) {
|
||||
chain->polysets[j]->render_surface(PolySet::COLORMODE_BACKGROUND, PolySet::csgmode_e(csgmode + 10), m, shaderinfo);
|
||||
} else if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) {
|
||||
// User-defined color from source
|
||||
glColor4d(m[16], m[17], m[18], m[19]);
|
||||
if (shaderinfo) {
|
||||
glUniform4f(shaderinfo[1], m[16], m[17], m[18], m[19]);
|
||||
glUniform4f(shaderinfo[2], (m[16]+1)/2, (m[17]+1)/2, (m[18]+1)/2, 1.0);
|
||||
}
|
||||
chain->polysets[j]->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m, shaderinfo);
|
||||
} else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) {
|
||||
chain->polysets[j]->render_surface(PolySet::COLORMODE_CUTOUT, PolySet::csgmode_e(csgmode), m, shaderinfo);
|
||||
} else {
|
||||
chain->polysets[j]->render_surface(PolySet::COLORMODE_MATERIAL, PolySet::csgmode_e(csgmode), m, shaderinfo);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
if (shaderinfo)
|
||||
glUseProgram(0);
|
||||
for (unsigned int k = 0; k < primitives.size(); k++) {
|
||||
delete primitives[k];
|
||||
}
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
primitives.clear();
|
||||
}
|
||||
|
||||
if (last)
|
||||
break;
|
||||
|
||||
OpenCSGPrim *prim = new OpenCSGPrim(chain->types[i] == CSGTerm::TYPE_DIFFERENCE ?
|
||||
OpenCSG::Subtraction : OpenCSG::Intersection, chain->polysets[i]->convexity);
|
||||
prim->p = chain->polysets[i];
|
||||
prim->m = chain->matrices[i];
|
||||
prim->csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
|
||||
if (highlight)
|
||||
prim->csgmode += 20;
|
||||
else if (background)
|
||||
prim->csgmode += 10;
|
||||
primitives.push_back(prim);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef OPENCSGRENDERER_H_
|
||||
#define OPENCSGRENDERER_H_
|
||||
|
||||
#include "renderer.h"
|
||||
#include <GL/glew.h> // this must be included before the GL headers
|
||||
#include <qgl.h>
|
||||
|
||||
class OpenCSGRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
OpenCSGRenderer(class CSGChain *root_chain, CSGChain *highlights_chain,
|
||||
CSGChain *background_chain, GLint *shaderinfo);
|
||||
void draw(bool showfaces, bool showedges) const;
|
||||
private:
|
||||
void renderCSGChain(class CSGChain *chain, GLint *shaderinfo,
|
||||
bool highlight, bool background) const;
|
||||
|
||||
CSGChain *root_chain;
|
||||
CSGChain *highlights_chain;
|
||||
CSGChain *background_chain;
|
||||
GLint *shaderinfo;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -33,8 +33,8 @@
|
|||
#include "export.h"
|
||||
#include "builtin.h"
|
||||
#include "nodedumper.h"
|
||||
#include "CGALRenderer.h"
|
||||
#include "PolySetCGALRenderer.h"
|
||||
#include "CGALEvaluator.h"
|
||||
#include "PolySetCGALEvaluator.h"
|
||||
#include "printutils.h"
|
||||
|
||||
#include <string>
|
||||
|
@ -261,8 +261,8 @@ int main(int argc, char **argv)
|
|||
Tree tree;
|
||||
// FIXME: enforce some maximum cache size (old version had 100K vertices as limit)
|
||||
QHash<std::string, CGAL_Nef_polyhedron> cache;
|
||||
CGALRenderer cgalrenderer(cache, tree);
|
||||
PolySetCGALRenderer psrenderer(cgalrenderer);
|
||||
CGALEvaluator cgalevaluator(cache, tree);
|
||||
PolySetCGALEvaluator psevaluator(cgalevaluator);
|
||||
|
||||
if (stl_output_file || off_output_file || dxf_output_file)
|
||||
{
|
||||
|
@ -315,7 +315,7 @@ int main(int argc, char **argv)
|
|||
root_node = root_module->evaluate(&root_ctx, &root_inst);
|
||||
|
||||
tree.setRoot(root_node);
|
||||
CGAL_Nef_polyhedron root_N = cgalrenderer.renderCGALMesh(*tree.root());
|
||||
CGAL_Nef_polyhedron root_N = cgalevaluator.evaluateCGALMesh(*tree.root());
|
||||
|
||||
QDir::setCurrent(original_path.absolutePath());
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#ifndef POLYSET_H_
|
||||
#define POLYSET_H_
|
||||
|
||||
#ifdef ENABLE_OPENCSG
|
||||
// this must be included before the GL headers
|
||||
# include <GL/glew.h>
|
||||
#endif
|
||||
#include <GL/glew.h> // this must be included before the GL headers
|
||||
#include <qgl.h>
|
||||
|
||||
#include "grid.h"
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
primitive_type_e type;
|
||||
int convexity;
|
||||
Value points, paths, triangles;
|
||||
virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const;
|
||||
virtual PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *) const;
|
||||
};
|
||||
|
||||
AbstractNode *PrimitiveModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
|
||||
|
@ -272,7 +272,7 @@ static void generate_circle(point2d *circle, double r, int fragments)
|
|||
}
|
||||
}
|
||||
|
||||
PolySet *PrimitiveNode::render_polyset(render_mode_e, class PolySetRenderer *) const
|
||||
PolySet *PrimitiveNode::evaluate_polyset(render_mode_e, class PolySetEvaluator *) const
|
||||
{
|
||||
PolySet *p = new PolySet();
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "export.h"
|
||||
#include "progress.h"
|
||||
#include "visitor.h"
|
||||
#include "PolySetRenderer.h"
|
||||
#include "PolySetEvaluator.h"
|
||||
|
||||
#ifdef ENABLE_CGAL
|
||||
# include <CGAL/assertions_behaviour.h>
|
||||
|
@ -83,10 +83,10 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant
|
|||
return node;
|
||||
}
|
||||
|
||||
PolySet *ProjectionNode::render_polyset(render_mode_e mode, PolySetRenderer *renderer) const
|
||||
PolySet *ProjectionNode::evaluate_polyset(render_mode_e mode, PolySetEvaluator *evaluator) const
|
||||
{
|
||||
if (!renderer) {
|
||||
PRINTF("WARNING: No suitable PolySetRenderer found for %s module!", this->name().c_str());
|
||||
if (!evaluator) {
|
||||
PRINTF("WARNING: No suitable PolySetEvaluator found for %s module!", this->name().c_str());
|
||||
PolySet *ps = new PolySet();
|
||||
ps->is2d = true;
|
||||
return ps;
|
||||
|
@ -94,7 +94,7 @@ PolySet *ProjectionNode::render_polyset(render_mode_e mode, PolySetRenderer *ren
|
|||
|
||||
print_messages_push();
|
||||
|
||||
PolySet *ps = renderer->renderPolySet(*this, mode);
|
||||
PolySet *ps = evaluator->evaluatePolySet(*this, mode);
|
||||
|
||||
print_messages_pop();
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
|
||||
int convexity;
|
||||
bool cut_mode;
|
||||
virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *renderer) const;
|
||||
virtual PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *evaluator) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef RENDER_OPENCSG_H_
|
||||
#define RENDER_OPENCSG_H_
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
void renderCSGChainviaOpenCSG(class CSGChain *chain, GLint *shaderinfo, bool highlight, bool background);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef RENDERER_H_
|
||||
#define RENDERER_H_
|
||||
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
virtual ~Renderer() {}
|
||||
virtual void draw(bool showfaces, bool showedges) const = 0;
|
||||
};
|
||||
|
||||
#endif // RENDERER_H
|
|
@ -57,7 +57,7 @@ public:
|
|||
QString filename;
|
||||
bool center;
|
||||
int convexity;
|
||||
virtual PolySet *render_polyset(render_mode_e mode, class PolySetRenderer *) const;
|
||||
virtual PolySet *evaluate_polyset(render_mode_e mode, class PolySetEvaluator *) const;
|
||||
};
|
||||
|
||||
AbstractNode *SurfaceModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
|
||||
|
@ -92,7 +92,7 @@ void register_builtin_surface()
|
|||
builtin_modules["surface"] = new SurfaceModule();
|
||||
}
|
||||
|
||||
PolySet *SurfaceNode::render_polyset(render_mode_e, class PolySetRenderer *) const
|
||||
PolySet *SurfaceNode::evaluate_polyset(render_mode_e, class PolySetEvaluator *) const
|
||||
{
|
||||
PolySet *p = new PolySet();
|
||||
handle_dep(filename);
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ThrownTogetherRenderer.h"
|
||||
#include "polyset.h"
|
||||
#include "csgterm.h"
|
||||
|
||||
#include <GL/glew.h> // this must be included before the GL headers
|
||||
#include <qgl.h>
|
||||
|
||||
ThrownTogetherRenderer::ThrownTogetherRenderer(CSGChain *root_chain,
|
||||
CSGChain *highlights_chain,
|
||||
CSGChain *background_chain)
|
||||
: root_chain(root_chain), highlights_chain(highlights_chain),
|
||||
background_chain(background_chain)
|
||||
{
|
||||
}
|
||||
|
||||
void ThrownTogetherRenderer::draw(bool showfaces, bool showedges) const
|
||||
{
|
||||
if (this->root_chain) {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
renderCSGChain(this->root_chain, false, false, showedges, false);
|
||||
glCullFace(GL_FRONT);
|
||||
glColor3ub(255, 0, 255);
|
||||
renderCSGChain(this->root_chain, false, false, showedges, true);
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
if (this->background_chain)
|
||||
renderCSGChain(this->background_chain, false, true, showedges, false);
|
||||
if (this->highlights_chain)
|
||||
renderCSGChain(this->highlights_chain, true, false, showedges, false);
|
||||
}
|
||||
|
||||
void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
|
||||
bool background, bool showedges,
|
||||
bool fberror) const
|
||||
{
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
QHash<QPair<PolySet*,double*>,int> polySetVisitMark;
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef THROWNTOGETHERRENDERER_H_
|
||||
#define THROWNTOGETHERRENDERER_H_
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
class ThrownTogetherRenderer : public Renderer
|
||||
{
|
||||
public:
|
||||
ThrownTogetherRenderer(class CSGChain *root_chain,
|
||||
CSGChain *highlights_chain, CSGChain *background_chain);
|
||||
void draw(bool showfaces, bool showedges) const;
|
||||
private:
|
||||
void renderCSGChain(CSGChain *chain, bool highlight, bool background, bool showedges,
|
||||
bool fberror) const;
|
||||
|
||||
CSGChain *root_chain;
|
||||
CSGChain *highlights_chain;
|
||||
CSGChain *background_chain;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue