Merge remote-tracking branch 'origin/master' into scintillaeditor

Conflicts:
	src/MainWindow.h
	src/Preferences.ui
	src/mainwin.cc
master
Marius Kintel 2014-08-22 12:59:10 -04:00
commit 138d5bc57e
270 changed files with 2219 additions and 1380 deletions

Binary file not shown.

View File

@ -221,8 +221,9 @@ HEADERS += src/typedefs.h \
src/parsersettings.h \
src/renderer.h \
src/rendersettings.h \
src/colormap.h \
src/ThrownTogetherRenderer.h \
src/CGAL_renderer.h \
src/CGAL_OGL_Polyhedron.h \
src/OGL_helper.h \
src/QGLView.h \
src/GLView.h \
@ -379,6 +380,7 @@ src/FontCache.cc \
src/export_png.cc \
src/import.cc \
src/renderer.cc \
src/colormap.cc \
src/ThrownTogetherRenderer.cc \
src/CSGTermEvaluator.cc \
src/svg.cc \
@ -428,6 +430,7 @@ HEADERS += src/cgal.h \
src/Polygon2d-CGAL.h
SOURCES += src/cgalutils.cc \
src/cgalutils-tess.cc \
src/CGALCache.cc \
src/CGALRenderer.cc \
src/CGAL_Nef_polyhedron.cc \

View File

@ -96,10 +96,10 @@ fontconfig_sysver()
{
fcpath=$1/include/fontconfig/fontconfig.h
if [ ! -e $fcpath ]; then return; fi
fcmajor=`grep "define *FC_MAJOR *[0-9.]*" $fcpath | awk '{print $3}'`
fcminor=`grep "define *FC_MINOR *[0-9.]*" $fcpath | awk '{print $3}'`
fcrevison=`grep "define *FC_REVISION *[0-9.]*" $fcpath | awk '{print $3}'`
fontconfig_sysver="${fcmajor}.${fcminor}.${fcrevision}"
fcmajor=`grep "define *FC_MAJOR.*[0-9.]*" $fcpath | awk '{print $3}'`
fcminor=`grep "define *FC_MINOR.*[0-9.]*" $fcpath | awk '{print $3}'`
fcrevison=`grep "define *FC_REVISION.*[0-9.]*" $fcpath | awk '{print $3}'`
fontconfig_sysver_result="${fcmajor}.${fcminor}.${fcrevision}"
}
freetype2_sysver()

View File

@ -32,9 +32,10 @@
// dxfdata.h must come first for Eigen SIMD alignment issues
#include "dxfdata.h"
#include "polyset.h"
#include "printutils.h"
#include "CGALRenderer.h"
#include "CGAL_renderer.h"
#include "CGAL_OGL_Polyhedron.h"
#include "CGAL_Nef_polyhedron.h"
#include "cgal.h"
@ -51,19 +52,7 @@ CGALRenderer::CGALRenderer(shared_ptr<const class Geometry> geom)
else if (shared_ptr<const CGAL_Nef_polyhedron> new_N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom)) {
assert(new_N->getDimension() == 3);
if (!new_N->isEmpty()) {
this->polyhedron.reset(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(*new_N->p3, this->polyhedron.get());
this->polyhedron->init();
this->N = new_N;
}
}
}
@ -72,9 +61,37 @@ CGALRenderer::~CGALRenderer()
{
}
shared_ptr<class CGAL_OGL_Polyhedron> CGALRenderer::getPolyhedron() const
{
if (this->N && !this->polyhedron) buildPolyhedron();
return this->polyhedron;
}
void CGALRenderer::buildPolyhedron() const
{
PRINTD("buildPolyhedron");
this->polyhedron.reset(new CGAL_OGL_Polyhedron(*this->colorscheme));
CGAL::OGL::Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(*this->N->p3, this->polyhedron.get());
// CGAL_NEF3_MARKED_FACET_COLOR <- CGAL_FACE_BACK_COLOR
// CGAL_NEF3_UNMARKED_FACET_COLOR <- CGAL_FACE_FRONT_COLOR
this->polyhedron->init();
PRINTD("buildPolyhedron() end");
}
// Overridden from Renderer
void CGALRenderer::setColorScheme(const ColorScheme &cs)
{
PRINTD("setColorScheme");
Renderer::setColorScheme(cs);
this->polyhedron.reset(); // Mark as dirty
PRINTD("setColorScheme done");
}
void CGALRenderer::draw(bool showfaces, bool showedges) const
{
PRINTD("draw()");
if (this->polyset) {
PRINTD("draw() polyset");
if (this->polyset->getDimension() == 2) {
// Draw 2D polygons
glDisable(GL_LIGHTING);
@ -106,27 +123,33 @@ void CGALRenderer::draw(bool showfaces, bool showedges) const
this->polyset->render_surface(CSGMODE_NORMAL, Transform3d::Identity(), NULL);
}
}
else if (this->polyhedron) {
if (showfaces) this->polyhedron->set_style(SNC_BOUNDARY);
else this->polyhedron->set_style(SNC_SKELETON);
this->polyhedron->draw(showfaces && showedges);
}
else {
shared_ptr<class CGAL_OGL_Polyhedron> polyhedron = getPolyhedron();
if (polyhedron) {
PRINTD("draw() polyhedron");
if (showfaces) polyhedron->set_style(SNC_BOUNDARY);
else polyhedron->set_style(SNC_SKELETON);
polyhedron->draw(showfaces && showedges);
}
}
PRINTD("draw() end");
}
BoundingBox CGALRenderer::getBoundingBox() const
{
BoundingBox bbox;
if (this->polyhedron) {
CGAL::Bbox_3 cgalbbox = this->polyhedron->bbox();
bbox = BoundingBox(
Vector3d(cgalbbox.xmin(), cgalbbox.ymin(), cgalbbox.zmin()),
Vector3d(cgalbbox.xmax(), cgalbbox.ymax(), cgalbbox.zmax()) );
}
else if (this->polyset) {
if (this->polyset) {
bbox = this->polyset->getBoundingBox();
}
else {
shared_ptr<class CGAL_OGL_Polyhedron> polyhedron = getPolyhedron();
if (polyhedron) {
CGAL::Bbox_3 cgalbbox = polyhedron->bbox();
bbox = BoundingBox(
Vector3d(cgalbbox.xmin(), cgalbbox.ymin(), cgalbbox.zmin()),
Vector3d(cgalbbox.xmax(), cgalbbox.ymax(), cgalbbox.zmax()));
}
}
return bbox;
}

View File

@ -1,16 +1,22 @@
#pragma once
#include "renderer.h"
#include "CGAL_Nef_polyhedron.h"
class CGALRenderer : public Renderer
{
public:
CGALRenderer(shared_ptr<const class Geometry> geom);
virtual ~CGALRenderer();
~CGALRenderer();
virtual void draw(bool showfaces, bool showedges) const;
virtual void setColorScheme(const ColorScheme &cs);
virtual BoundingBox getBoundingBox() const;
public:
shared_ptr<class Polyhedron> polyhedron;
private:
shared_ptr<class CGAL_OGL_Polyhedron> getPolyhedron() const;
void buildPolyhedron() const;
mutable shared_ptr<class CGAL_OGL_Polyhedron> polyhedron;
shared_ptr<const CGAL_Nef_polyhedron> N;
shared_ptr<const class PolySet> polyset;
};

View File

@ -53,6 +53,8 @@ size_t CGAL_Nef_polyhedron::memsize() const
Note: Can return NULL if an error occurred
*/
// FIXME: Deprecated by CGALUtils::createPolySetFromNefPolyhedron3
#if 0
PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
{
if (this->isEmpty()) return new PolySet(3);
@ -74,7 +76,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
err = true;
errmsg = std::string(e.what());
}
if (!err) err = createPolySetFromPolyhedron(P, *ps);
if (!err) err = CGALUtils::createPolySetFromPolyhedron(P, *ps);
if (err) {
PRINT("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed.");
if (errmsg!="") PRINTB("ERROR: %s",errmsg);
@ -83,6 +85,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
CGAL::set_error_behaviour(old_behaviour);
return ps;
}
#endif
void CGAL_Nef_polyhedron::resize(Vector3d newsize,
const Eigen::Matrix<bool,3,1> &autosize)

View File

@ -27,7 +27,8 @@ public:
CGAL_Nef_polyhedron &operator*=(const CGAL_Nef_polyhedron &other);
CGAL_Nef_polyhedron &operator-=(const CGAL_Nef_polyhedron &other);
CGAL_Nef_polyhedron &minkowski(const CGAL_Nef_polyhedron &other);
class PolySet *convertToPolyset() const;
// FIXME: Deprecated by CGALUtils::createPolySetFromNefPolyhedron3
// class PolySet *convertToPolyset() const;
void transform( const Transform3d &matrix );
void resize(Vector3d newsize, const Eigen::Matrix<bool,3,1> &autosize);

View File

@ -27,19 +27,16 @@
#pragma once
#ifndef NULLGL
#include "OGL_helper.h"
#undef CGAL_NEF3_MARKED_VERTEX_COLOR
#undef CGAL_NEF3_MARKED_EDGE_COLOR
#undef CGAL_NEF3_MARKED_FACET_COLOR
#undef CGAL_NEF3_UNMARKED_VERTEX_COLOR
#undef CGAL_NEF3_UNMARKED_EDGE_COLOR
#undef CGAL_NEF3_UNMARKED_FACET_COLOR
#include "colormap.h"
#include "rendersettings.h"
#include "OGL_helper.h"
#include "printutils.h"
using CGAL::OGL::SNC_BOUNDARY;
using CGAL::OGL::SNC_SKELETON;
class Polyhedron : public CGAL::OGL::Polyhedron
class CGAL_OGL_Polyhedron : public CGAL::OGL::Polyhedron
{
public:
@ -53,16 +50,18 @@ public:
NUM_COLORS
};
Polyhedron() {
CGAL_OGL_Polyhedron(const ColorScheme &cs) {
PRINTD("CGAL_OGL_Polyhedron()");
// Set default colors.
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);
// Face and Edge colors are taken from default colorscheme
setColorScheme(cs);
PRINTD("CGAL_OGL_Polyhedron() end");
}
void draw(bool showedges) const {
PRINTD("draw()");
if(this->style == SNC_BOUNDARY) {
glCallList(this->object_list_+2);
if(showedges) {
@ -75,31 +74,55 @@ public:
glCallList(this->object_list_+1);
glCallList(this->object_list_);
}
PRINTD("draw() end");
}
// overrides function in OGL_helper.h
CGAL::Color getVertexColor(Vertex_iterator v) const {
PRINTD("getVertexColor");
CGAL::Color c = v->mark() ? colors[CGAL_NEF3_UNMARKED_VERTEX_COLOR] : colors[CGAL_NEF3_MARKED_VERTEX_COLOR];
return c;
}
// overrides function in OGL_helper.h
CGAL::Color getEdgeColor(Edge_iterator e) const {
PRINTD("getEdgeColor");
CGAL::Color c = e->mark() ? colors[CGAL_NEF3_UNMARKED_EDGE_COLOR] : colors[CGAL_NEF3_MARKED_EDGE_COLOR];
return c;
}
CGAL::Color getFacetColor(Halffacet_iterator f) const {
// overrides function in OGL_helper.h
CGAL::Color getFacetColor(Halffacet_iterator f, bool is_back_facing) const {
PRINTD("getFacetColor");
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,
void setColor(CGAL_OGL_Polyhedron::RenderColor color_index, const Color4f &c) {
PRINTDB("setColor %i %f %f %f",color_index%c[0]%c[1]%c[2]);
this->colors[color_index] = CGAL::Color(c[0]*255,c[1]*255,c[2]*255);
}
void setColor(CGAL_OGL_Polyhedron::RenderColor color_index,
unsigned char r, unsigned char g, unsigned char b) {
assert(color_index < Polyhedron::NUM_COLORS);
PRINTDB("setColor %i %i %i %i",color_index%r%g%b);
this->colors[color_index] = CGAL::Color(r,g,b);
}
// set this->colors based on the given colorscheme. vertex colors
// are not set here as colorscheme doesnt yet hold vertex colors.
void setColorScheme(const ColorScheme &cs) {
PRINTD("setColorScheme");
setColor(CGAL_NEF3_MARKED_FACET_COLOR, ColorMap::getColor(cs, CGAL_FACE_BACK_COLOR));
setColor(CGAL_NEF3_UNMARKED_FACET_COLOR, ColorMap::getColor(cs, CGAL_FACE_FRONT_COLOR));
setColor(CGAL_NEF3_MARKED_EDGE_COLOR, ColorMap::getColor(cs, CGAL_EDGE_BACK_COLOR));
setColor(CGAL_NEF3_UNMARKED_EDGE_COLOR, ColorMap::getColor(cs, CGAL_EDGE_FRONT_COLOR));
}
private:
CGAL::Color colors[NUM_COLORS];
}; // Polyhedron
}; // CGAL_OGL_Polyhedron
@ -108,10 +131,10 @@ private:
#include <CGAL/Bbox_3.h>
class Polyhedron
class CGAL_OGL_Polyhedron
{
public:
Polyhedron() {}
CGAL_OGL_Polyhedron() {}
void draw(bool showedges) const {}
CGAL::Bbox_3 bbox() const { return CGAL::Bbox_3(-1,-1,-1,1,1,1); }
};

View File

@ -5,6 +5,7 @@
Camera::Camera(enum CameraType camtype) :
type(camtype), projection(Camera::PERSPECTIVE), fov(45), height(60), viewall(false)
{
PRINTD("Camera()");
if (this->type == Camera::GIMBAL) {
object_trans << 0,0,0;
object_rot << 35,0,25;
@ -92,6 +93,10 @@ void Camera::viewAll(const BoundingBox &bbox, float scalefactor)
}
break;
}
PRINTDB("modified center x y z %f %f %f",center.x() % center.y() % center.z());
PRINTDB("modified eye x y z %f %f %f",eye.x() % eye.y() % eye.z());
PRINTDB("modified obj trans x y z %f %f %f",object_trans.x() % object_trans.y() % object_trans.z());
PRINTDB("modified obj rot x y z %f %f %f",object_rot.x() % object_rot.y() % object_rot.z());
}
void Camera::zoom(int delta)

View File

@ -1,8 +1,10 @@
#include "GLView.h"
#include "stdio.h"
#include "colormap.h"
#include "rendersettings.h"
#include "mathc99.h"
#include "printutils.h"
#include "renderer.h"
#ifdef _WIN32
@ -22,6 +24,7 @@ GLView::GLView()
showaxes = false;
showcrosshairs = false;
renderer = NULL;
colorscheme = &ColorMap::inst()->defaultColorScheme();
cam = Camera();
far_far_away = RenderSettings::inst()->far_gl_clip_limit;
#ifdef ENABLE_OPENCSG
@ -39,6 +42,32 @@ void GLView::setRenderer(Renderer* r)
renderer = r;
}
/* update the color schemes of the Renderer attached to this GLView
to match the colorscheme of this GLView.*/
void GLView::updateColorScheme()
{
if (this->renderer) this->renderer->setColorScheme(*this->colorscheme);
}
/* change this GLView's colorscheme to the one given, and update the
Renderer attached to this GLView as well. */
void GLView::setColorScheme(const ColorScheme &cs)
{
this->colorscheme = &cs;
this->updateColorScheme();
}
void GLView::setColorScheme(const std::string &cs)
{
const ColorScheme *colorscheme = ColorMap::inst()->findColorScheme(cs);
if (colorscheme) {
setColorScheme(*colorscheme);
}
else {
PRINTB("WARNING: GLView: unknown colorscheme %s", cs);
}
}
void GLView::resizeGL(int w, int h)
{
#ifdef ENABLE_OPENCSG
@ -125,7 +154,7 @@ void GLView::paintGL()
setupCamera();
Color4f bgcol = RenderSettings::inst()->color(RenderSettings::BACKGROUND_COLOR);
Color4f bgcol = ColorMap::getColor(*this->colorscheme, BACKGROUND_COLOR);
glClearColor(bgcol[0], bgcol[1], bgcol[2], 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@ -440,7 +469,7 @@ void GLView::showCrosshairs()
// FIXME: Crosshairs and axes are lighted, this doesn't make sense and causes them
// to change color based on view orientation.
glLineWidth(3);
Color4f col = RenderSettings::inst()->color(RenderSettings::CROSSHAIR_COLOR);
Color4f col = ColorMap::getColor(*this->colorscheme, CROSSHAIR_COLOR);
glColor3f(col[0], col[1], col[2]);
glBegin(GL_LINES);
for (double xf = -1; xf <= +1; xf += 2)

View File

@ -26,6 +26,7 @@ Some actions (showCrossHairs) only work properly on Gimbal Camera.
#include "system-gl.h"
#include <iostream>
#include "Camera.h"
#include "colormap.h"
class GLView
{
@ -45,11 +46,16 @@ public:
void showAxes();
void showSmallaxes();
void setColorScheme(const ColorScheme &cs);
void setColorScheme(const std::string &cs);
void updateColorScheme();
virtual bool save(const char *filename) = 0;
virtual std::string getRendererInfo() const = 0;
virtual float getDPI() { return 1.0f; }
Renderer *renderer;
const ColorScheme *colorscheme;
Camera cam;
double far_far_away;
size_t width;

View File

@ -60,7 +60,14 @@ shared_ptr<const Geometry> GeometryEvaluator::evaluateGeometry(const AbstractNod
if (!allownef) {
if (shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(this->root)) {
this->root.reset(N->convertToPolyset());
PolySet *ps = new PolySet(3);
ps->setConvexity(N->getConvexity());
this->root.reset(ps);
bool err = CGALUtils::createPolySetFromNefPolyhedron3(*N->p3, *ps);
if (err) {
PRINT("ERROR: Nef->PolySet failed");
}
smartCacheInsert(node, this->root);
}
}
@ -873,7 +880,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
if (chN) chPS.reset(chN->convertToPolyset());
if (chPS) ps2d = PolysetUtils::flatten(*chPS);
if (ps2d) {
CGAL_Nef_polyhedron *N2d = createNefPolyhedronFromGeometry(*ps2d);
CGAL_Nef_polyhedron *N2d = CGALUtils::createNefPolyhedronFromGeometry(*ps2d);
poly = N2d->convertToPolygon2d();
}
#endif
@ -887,7 +894,14 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
if (!chPS) {
shared_ptr<const CGAL_Nef_polyhedron> chN = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(chgeom);
if (chN) {
chPS.reset(chN->convertToPolyset());
PolySet *ps = new PolySet(3);
bool err = CGALUtils::createPolySetFromNefPolyhedron3(*chN->p3, *ps);
if (err) {
PRINT("ERROR: Nef->PolySet failed");
}
else {
chPS.reset(ps);
}
}
}
if (chPS) poly = PolysetUtils::project(*chPS);
@ -915,7 +929,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
if (newgeom) {
shared_ptr<const CGAL_Nef_polyhedron> Nptr = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(newgeom);
if (!Nptr) {
Nptr.reset(createNefPolyhedronFromGeometry(*newgeom));
Nptr.reset(CGALUtils::createNefPolyhedronFromGeometry(*newgeom));
}
if (!Nptr->isEmpty()) {
Polygon2d *poly = CGALUtils::project(*Nptr, node.cut_mode);
@ -948,7 +962,17 @@ Response GeometryEvaluator::visit(State &state, const CgaladvNode &node)
if (!isSmartCached(node)) {
switch (node.type) {
case MINKOWSKI: {
geom = applyToChildren(node, OPENSCAD_MINKOWSKI).constptr();
ResultObject res = applyToChildren(node, OPENSCAD_MINKOWSKI);
geom = res.constptr();
// If we added convexity, we need to pass it on
if (geom && geom->getConvexity() != node.convexity) {
shared_ptr<Geometry> editablegeom;
// If we got a const object, make a copy
if (res.isConst()) editablegeom.reset(geom->copy());
else editablegeom = res.ptr();
geom = editablegeom;
editablegeom->setConvexity(node.convexity);
}
break;
}
case HULL: {

View File

@ -82,6 +82,8 @@ private slots:
void updateMdiMode(bool mdi);
void updateUndockMode(bool undockMode);
void setFileName(const QString &filename);
void setFont(const QString &family, uint size);
void setColorScheme(const QString &cs);
void showProgress();
void openCSGSettingsChanged();

View File

@ -17,6 +17,8 @@
//
// Author(s) : Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
// Modified for OpenSCAD
#pragma once
#include <CGAL/Nef_S2/OGL_base_object.h>
@ -25,16 +27,18 @@
#include "system-gl.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_MARKED_BACK_FACET_COLOR 157,103,181
#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
#define CGAL_NEF3_UNMARKED_BACK_FACET_COLOR 249,115,144
// Overridden in CGAL_renderer
/*
#define CGAL_NEF3_OGL_MARKED_VERTEX_COLOR 183,232,92
#define CGAL_NEF3_OGL_MARKED_EDGE_COLOR 171,216,86
#define CGAL_NEF3_OGL_MARKED_FACET_COLOR 157,203,81
#define CGAL_NEF3_OGL_MARKED_BACK_FACET_COLOR 157,103,181
#define CGAL_NEF3_OGL_UNMARKED_VERTEX_COLOR 255,246,124
#define CGAL_NEF3_OGL_UNMARKED_EDGE_COLOR 255,236,94
#define CGAL_NEF3_OGL_UNMARKED_FACET_COLOR 249,215,44
#define CGAL_NEF3_OGL_UNMARKED_BACK_FACET_COLOR 249,115,144
*/
const bool cull_backfaces = false;
const bool color_backfaces = false;
@ -362,18 +366,24 @@ namespace OGL {
Bbox_3 bbox() const { return bbox_; }
Bbox_3& bbox() { return bbox_; }
// Overridden in CGAL_renderer
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;
PRINTD("getVertexColor()");
(void)v;
// CGAL::Color cf(CGAL_NEF3_OGL_MARKED_VERTEX_COLOR),
// ct(CGAL_NEF3_OGL_UNMARKED_VERTEX_COLOR); // more blue-ish
// CGAL::Color c = v->mark() ? ct : cf;
CGAL::Color c(0,0,200);
return c;
}
void draw(Vertex_iterator v) const {
PRINTD("draw( Vertex_iterator )");
// CGAL_NEF_TRACEN("drawing vertex "<<*v);
CGAL::Color c = getVertexColor(v);
glPointSize(10);
//glPointSize(1);
glColor3ub(c.red(), c.green(), c.blue());
glBegin(GL_POINTS);
glVertex3d(v->x(),v->y(),v->z());
@ -384,19 +394,26 @@ namespace OGL {
glEnd();
}
// Overridden in CGAL_renderer
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;
PRINTD("getEdgeColor)");
(void)e;
// CGAL::Color cf(CGAL_NEF3_OGL_MARKED_EDGE_COLOR),
// ct(CGAL_NEF3_OGL_UNMARKED_EDGE_COLOR); // more blue-ish
// CGAL::Color c = e->mark() ? ct : cf;
// Overridden in CGAL_renderer
CGAL::Color c(200,0,0);
return c;
}
void draw(Edge_iterator e) const {
PRINTD("draw(Edge_iterator)");
// CGAL_NEF_TRACEN("drawing edge "<<*e);
Double_point p = e->source(), q = e->target();
CGAL::Color c = getEdgeColor(e);
glLineWidth(5);
//glLineWidth(1);
glColor3ub(c.red(),c.green(),c.blue());
glBegin(GL_LINE_STRIP);
glVertex3d(p.x(), p.y(), p.z());
@ -404,18 +421,32 @@ namespace OGL {
glEnd();
}
// Overridden in CGAL_renderer
virtual CGAL::Color getFacetColor(Halffacet_iterator f, bool is_back_facing) const
{
PRINTD("getFacetColor");
/*
(void)f;
// CGAL::Color cf(CGAL_NEF3_OGL_MARKED_FACET_COLOR),
// ct(CGAL_NEF3_OGL_UNMARKED_FACET_COLOR); // more blue-ish
// CGAL::Color c = (f->mark() ? ct : cf);
*/
CGAL::Color c(0,200,0);
return c;
/*
if (is_back_facing) return !f->mark()
? CGAL::Color(CGAL_NEF3_MARKED_BACK_FACET_COLOR)
: CGAL::Color(CGAL_NEF3_UNMARKED_BACK_FACET_COLOR);
? CGAL::Color(CGAL_NEF3_OGL_MARKED_BACK_FACET_COLOR)
: CGAL::Color(CGAL_NEF3_OGL_UNMARKED_BACK_FACET_COLOR);
else return !f->mark()
? CGAL::Color(CGAL_NEF3_MARKED_FACET_COLOR)
: CGAL::Color(CGAL_NEF3_UNMARKED_FACET_COLOR);
? CGAL::Color(CGAL_NEF3_OGL_MARKED_FACET_COLOR)
: CGAL::Color(CGAL_NEF3_OGL_UNMARKED_FACET_COLOR);
*/
}
void draw(Halffacet_iterator f, bool is_back_facing) const {
PRINTD("draw(Halffacet_iterator)");
// CGAL_NEF_TRACEN("drawing facet "<<(f->debug(),""));
GLUtesselator* tess_ = gluNewTess();
gluTessCallback(tess_, GLenum(GLU_TESS_VERTEX_DATA),
@ -458,6 +489,7 @@ namespace OGL {
void construct_axes() const
{
PRINTD("construct_axes");
glLineWidth(2.0);
// red x-axis
glColor3f(1.0,0.0,0.0);
@ -491,6 +523,7 @@ namespace OGL {
void fill_display_lists() {
PRINTD("fill_display_lists");
glNewList(object_list_, GL_COMPILE);
Vertex_iterator v;
for(v=vertices_.begin();v!=vertices_.end();++v)
@ -528,6 +561,7 @@ namespace OGL {
}
void init() {
PRINTD("init()");
if (init_) return;
init_ = true;
switches[SNC_AXES] = false;
@ -535,11 +569,13 @@ namespace OGL {
object_list_ = glGenLists(4);
CGAL_assertion(object_list_);
fill_display_lists();
PRINTD("init() end");
}
void draw() const
{
PRINTD("draw()");
if (!is_initialized()) const_cast<Polyhedron&>(*this).init();
double l = (std::max)( (std::max)( bbox().xmax() - bbox().xmin(),
bbox().ymax() - bbox().ymin()),
@ -562,6 +598,7 @@ namespace OGL {
glCallList(object_list_+1); // edges
glCallList(object_list_); // vertices
if (switches[SNC_AXES]) glCallList(object_list_+3); // axis
PRINTD("draw() end");
}
void debug(std::ostream& os = std::cerr) const

View File

@ -4,6 +4,10 @@
#include "linalg.h"
#include <vector>
/*!
A single contour.
positive is (optionally) used to distinguish between polygon contours and hold contours.
*/
struct Outline2d {
Outline2d() : positive(true) {}
std::vector<Vector2d> vertices;

View File

@ -37,6 +37,8 @@
#ifdef ENABLE_CGAL
#include "CGALCache.h"
#endif
#include "colormap.h"
#include "rendersettings.h"
Preferences *Preferences::instance = NULL;
@ -91,7 +93,6 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent)
this->fontSize->setEditText( QString("%1").arg( savedsize ) );
// Setup default settings
this->defaultmap["3dview/colorscheme"] = this->colorSchemeChooser->currentItem()->text();
this->defaultmap["advanced/opencsg_show_warning"] = true;
this->defaultmap["advanced/enable_opencsg_opengl1x"] = true;
this->defaultmap["advanced/polysetCacheSize"] = uint(GeometryCache::instance()->maxSize());
@ -124,38 +125,7 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent)
this->actionTriggered(this->prefsAction3DView);
// 3D View pane
this->colorschemes["Cornfield"][RenderSettings::BACKGROUND_COLOR] = Color4f(0xff, 0xff, 0xe5);
this->colorschemes["Cornfield"][RenderSettings::OPENCSG_FACE_FRONT_COLOR] = Color4f(0xf9, 0xd7, 0x2c);
this->colorschemes["Cornfield"][RenderSettings::OPENCSG_FACE_BACK_COLOR] = Color4f(0x9d, 0xcb, 0x51);
this->colorschemes["Cornfield"][RenderSettings::CGAL_FACE_FRONT_COLOR] = Color4f(0xf9, 0xd7, 0x2c);
this->colorschemes["Cornfield"][RenderSettings::CGAL_FACE_BACK_COLOR] = Color4f(0x9d, 0xcb, 0x51);
this->colorschemes["Cornfield"][RenderSettings::CGAL_FACE_2D_COLOR] = Color4f(0x00, 0xbf, 0x99);
this->colorschemes["Cornfield"][RenderSettings::CGAL_EDGE_FRONT_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Cornfield"][RenderSettings::CGAL_EDGE_BACK_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Cornfield"][RenderSettings::CGAL_EDGE_2D_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Cornfield"][RenderSettings::CROSSHAIR_COLOR] = Color4f(0x80, 0x00, 0x00);
this->colorschemes["Metallic"][RenderSettings::BACKGROUND_COLOR] = Color4f(0xaa, 0xaa, 0xff);
this->colorschemes["Metallic"][RenderSettings::OPENCSG_FACE_FRONT_COLOR] = Color4f(0xdd, 0xdd, 0xff);
this->colorschemes["Metallic"][RenderSettings::OPENCSG_FACE_BACK_COLOR] = Color4f(0xdd, 0x22, 0xdd);
this->colorschemes["Metallic"][RenderSettings::CGAL_FACE_FRONT_COLOR] = Color4f(0xdd, 0xdd, 0xff);
this->colorschemes["Metallic"][RenderSettings::CGAL_FACE_BACK_COLOR] = Color4f(0xdd, 0x22, 0xdd);
this->colorschemes["Metallic"][RenderSettings::CGAL_FACE_2D_COLOR] = Color4f(0x00, 0xbf, 0x99);
this->colorschemes["Metallic"][RenderSettings::CGAL_EDGE_FRONT_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Metallic"][RenderSettings::CGAL_EDGE_BACK_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Metallic"][RenderSettings::CGAL_EDGE_2D_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Metallic"][RenderSettings::CROSSHAIR_COLOR] = Color4f(0x80, 0x00, 0x00);
this->colorschemes["Sunset"][RenderSettings::BACKGROUND_COLOR] = Color4f(0xaa, 0x44, 0x44);
this->colorschemes["Sunset"][RenderSettings::OPENCSG_FACE_FRONT_COLOR] = Color4f(0xff, 0xaa, 0xaa);
this->colorschemes["Sunset"][RenderSettings::OPENCSG_FACE_BACK_COLOR] = Color4f(0x88, 0x22, 0x33);
this->colorschemes["Sunset"][RenderSettings::CGAL_FACE_FRONT_COLOR] = Color4f(0xff, 0xaa, 0xaa);
this->colorschemes["Sunset"][RenderSettings::CGAL_FACE_BACK_COLOR] = Color4f(0x88, 0x22, 0x33);
this->colorschemes["Sunset"][RenderSettings::CGAL_FACE_2D_COLOR] = Color4f(0x00, 0xbf, 0x99);
this->colorschemes["Sunset"][RenderSettings::CGAL_EDGE_FRONT_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Sunset"][RenderSettings::CGAL_EDGE_BACK_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Sunset"][RenderSettings::CGAL_EDGE_2D_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colorschemes["Sunset"][RenderSettings::CROSSHAIR_COLOR] = Color4f(0x80, 0x00, 0x00);
this->defaultmap["3dview/colorscheme"] = "Cornfield";
// Advanced pane
QValidator *validator = new QIntValidator(this);
@ -167,8 +137,6 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent)
setupFeaturesPage();
updateGUI();
RenderSettings::inst()->setColors(this->colorschemes[getValue("3dview/colorscheme").toString()]);
}
Preferences::~Preferences()
@ -279,10 +247,7 @@ void Preferences::on_colorSchemeChooser_itemSelectionChanged()
QString scheme = this->colorSchemeChooser->currentItem()->text();
QSettings settings;
settings.setValue("3dview/colorscheme", scheme);
RenderSettings::inst()->setColors(this->colorschemes[scheme]);
emit requestRedraw();
emit colorSchemeChanged( scheme );
}
void Preferences::on_fontChooser_activated(const QString &family)

View File

@ -3,9 +3,7 @@
#include <QMainWindow>
#include <QSettings>
#include "ui_Preferences.h"
#include "rendersettings.h"
#include "linalg.h"
#include <map>
#include "colormap.h"
class Preferences : public QMainWindow, public Ui::Preferences
{
@ -43,6 +41,7 @@ signals:
void updateMdiMode(bool mdi) const;
void updateUndockMode(bool mdi) const;
void fontChanged(const QString &family, uint size) const;
void colorSchemeChanged(const QString &scheme) const;
void openCSGSettingsChanged() const;
void syntaxHighlightChanged(const QString &s);
void editorTypeChanged(const QString &type);
@ -56,7 +55,6 @@ private:
void addPrefPage(QActionGroup *group, QAction *action, QWidget *widget);
QSettings::SettingsMap defaultmap;
QHash<QString, std::map<RenderSettings::RenderColor, Color4f> > colorschemes;
QHash<const QAction *, QWidget *> prefPages;
static Preferences *instance;

View File

@ -49,29 +49,55 @@
</widget>
</item>
<item>
<widget class="QListWidget" name="colorSchemeChooser">
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="currentRow">
<number>0</number>
</property>
<item>
<property name="text">
<string>Cornfield</string>
</property>
</item>
<item>
<property name="text">
<string>Metallic</string>
</property>
</item>
<item>
<property name="text">
<string>Sunset</string>
</property>
</item>
</widget>
<widget class="QListWidget" name="colorSchemeChooser">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="currentRow">
<number>0</number>
</property>
<item>
<property name="text">
<string>Cornfield</string>
</property>
</item>
<item>
<property name="text">
<string>Metallic</string>
</property>
</item>
<item>
<property name="text">
<string>Sunset</string>
</property>
</item>
<item>
<property name="text">
<string>Starnight</string>
</property>
</item>
<item>
<property name="text">
<string>BeforeDawn</string>
</property>
</item>
<item>
<property name="text">
<string>Nature</string>
</property>
</item>
<item>
<property name="text">
<string>DeepOcean</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
@ -158,6 +184,9 @@
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>30</width>
@ -429,7 +458,45 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<spacer name="horizontalSpacer_11">
<widget class="QLabel" name="label_syntax_h">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Color syntax highlighting</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="syntaxHighlight">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>For Light Background</string>
</property>
</item>
<item>
<property name="text">
<string>For Dark Background</string>
</property>
</item>
<item>
<property name="text">
<string>Off</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>

View File

@ -27,6 +27,7 @@
#include "ThrownTogetherRenderer.h"
#include "polyset.h"
#include "csgterm.h"
#include "printutils.h"
#include "system-gl.h"
@ -43,6 +44,7 @@ ThrownTogetherRenderer::ThrownTogetherRenderer(CSGChain *root_chain,
void ThrownTogetherRenderer::draw(bool /*showfaces*/, bool showedges) const
{
PRINTD("Thrown draw");
if (this->root_chain) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
@ -62,6 +64,7 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
bool background, bool showedges,
bool fberror) const
{
PRINTD("Thrown renderCSGChain");
glDepthFunc(GL_LEQUAL);
boost::unordered_map<std::pair<const Geometry*,const Transform3d*>,int> geomVisitMark;
BOOST_FOREACH(const CSGChainObject &obj, chain->objects) {

433
src/cgalutils-tess.cc Normal file
View File

@ -0,0 +1,433 @@
/*
This is our custom tessellator of Nef Polyhedron faces. The problem with
Nef faces is that sometimes the 'default' tessellator of Nef Polyhedron
doesnt work. This is particularly true with situations where the polygon
face is not, actually, 'simple', according to CGAL itself. This can
occur on a bad quality STL import but also for other reasons. The
resulting Nef face will appear to the average human eye as an ordinary,
simple polygon... but in reality it has multiple edges that are
slightly-out-of-alignment and sometimes they backtrack on themselves.
When the triangulator is fed a polygon with self-intersecting edges,
it's default behavior is to throw an exception. The other terminology
for this is to say that the 'constraints' in the triangulation are
'intersecting'. The 'constraints' represent the edges of the polygon.
The 'triangulation' is the covering of all the polygon points with
triangles.
How do we allow interseting constraints during triangulation? We use an
'Itag' for the triangulation, per the CGAL docs. This allows the
triangulator to run without throwing an exception when it encounters
self-intersecting polygon edges. The trick here is that when it finds
an intersection, it actually creates a new point.
The triangulator creates new points in 2d, but they aren't matched to
any 3d points on our 3d polygon plane. (The plane of the Nef face). How
to fix this problem? We actually 'project back up' or 'lift' into the 3d
plane from the 2d point. This is handled in the 'deproject()' function.
There is also the issue of the Simplicity of Nef Polyhedron face
polygons. They are often not simple. The intersecting-constraints
Triangulation can triangulate non-simple polygons, but of course it's
result is also non-simple. This means that CGAL functions like
orientation_2() and bounded_side() simply will not work on the resulting
polygons because they all require input polygons to pass the
'is_simple2()' test. We have to use alternatives in order to create our
triangles.
There is also the question of which underlying number type to use. Some
of the CGAL functions simply dont guarantee good results with a type
like double. Although much the math here is somewhat simple, like
line-line intersection, and involves only simple algebra, the
approximations required when using floating-point types can cause the
answers to be wrong. For example questions like 'is a point inside a
triangle' do not have good answers under floating-point systems where a
line may have a slope that is not expressible exactly as a floating
point number. There are ways to deal with floating point inaccuracy but
it is much, much simpler to use Rational numbers, although potentially
much slower in many cases.
*/
#include "cgalutils.h"
#include <CGAL/Delaunay_mesher_no_edge_refinement_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
typedef CGAL_Kernel3 Kernel;
//typedef CGAL::Triangulation_vertex_base_2<Kernel> Vb;
typedef CGAL::Triangulation_vertex_base_2<Kernel> Vb;
//typedef CGAL::Constrained_triangulation_face_base_2<Kernel> Fb;
typedef CGAL::Delaunay_mesh_face_base_2<Kernel> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::Exact_intersections_tag ITAG;
typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS,ITAG> CDT;
//typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS> CDT;
typedef CDT::Vertex_handle Vertex_handle;
typedef CDT::Point CDTPoint;
typedef CGAL::Ray_2<Kernel> CGAL_Ray_2;
typedef CGAL::Line_3<Kernel> CGAL_Line_3;
typedef CGAL::Point_2<Kernel> CGAL_Point_2;
typedef CGAL::Vector_2<Kernel> CGAL_Vector_2;
typedef CGAL::Segment_2<Kernel> CGAL_Segment_2;
typedef CGAL::Direction_2<Kernel> CGAL_Direction_2;
typedef CGAL::Direction_3<Kernel> CGAL_Direction_3;
typedef CGAL::Plane_3<Kernel> CGAL_Plane_3;
/* The idea of 'projection' is how we make 3d points appear as though
they were 2d points to the tessellation algorithm. We take the 3-d plane
on which the polygon lies, and then 'project' or 'cast its shadow' onto
one of three standard planes, the xyplane, the yzplane, or the xzplane,
depending on which projection will prevent the polygon looking like a
flat line. (imagine, the triangle 0,0,1 0,1,1 0,1,0 ... if viewed from
the 'top' it looks line a flat line. so we want to view it from the
side). Thus we create a sequence of x,y points to feed to the algorithm,
but those points might actually be x,z pairs or y,z pairs... it is an
illusion we present to the triangulation algorithm by way of 'projection'.
We get a resulting sequence of triangles with x,y coordinates, which we
then 'deproject' back to x,z or y,z, in 3d space as needed. For example
the square 0,0,0 0,0,1 0,1,1 0,1,0 becomes '0,0 0,1 1,1 1,0', is then
split into two triangles, 0,0 1,0 1,1 and 0,0 1,1 0,1. those two triangles
then are projected back to 3d as 0,0,0 0,1,0 0,1,1 and 0,0 0,1,1 0,0,1.
There is an additional trick we do with projection related to Polygon
orientation and the orientation of our output triangles, and thus, which
way they are facing in space (aka their 'normals' or 'oriented side').
The basic issues is this: every 3d flat polygon can be thought of as
having two sides. In Computer Graphics the convention is that the
'outside' or 'oriented side' or 'normal' is determined by looking at the
triangle in terms of the 'ordering' or 'winding' of the points. If the
points come in a 'clockwise' order, you must be looking at the triangle
from 'inside'. If the points come in a 'counterclockwise' order, you
must be looking at the triangle from the outside. For example, the
triangle 0,0,0 1,0,0 0,1,0, when viewed from the 'top', has points in a
counterclockwise order, so the 'up' side is the 'normal' or 'outside'.
if you look at that same triangle from the 'bottom' side, the points
will appear to be 'clockwise', so the 'down' side is the 'inside', and is the
opposite of the 'normal' side.
How do we keep track of all that when doing a triangulation? We could
check each triangle as it was generated, and fix it's orientation before
we feed it back to our output list. That is done by, for example, checking
the orientation of the input polygon and then forcing the triangle to
match that orientation during output. This is what CGAL's Nef Polyhedron
does, you can read it inside /usr/include/CGAL/Nef_polyhedron_3.h.
Or.... we could actually add an additional 'projection' to the incoming
polygon points so that our triangulation algorithm is guaranteed to
create triangles with the proper orientation in the first place. How?
First, we assume that the triangulation algorithm will always produce
'counterclockwise' triangles in our plain old x-y plane.
The method is based on the following curious fact: That is, if you take
the points of a polygon, and flip the x,y coordinate of each point,
making y:=x and x:=y, then you essentially get a 'mirror image' of the
original polygon... but the orientation will be flipped. Given a
clockwise polygon, the 'flip' will result in a 'counterclockwise'
polygon mirror-image and vice versa.
Now, there is a second curious fact that helps us here. In 3d, we are
using the plane equation of ax+by+cz+d=0, where a,b,c determine its
direction. If you notice, there are actually mutiple sets of numbers
a:b:c that will describe the exact same plane. For example the 'ground'
plane, called the XYplane, where z is everywhere 0, has the equation
0x+0y+1z+0=0, simplifying to a solution for x,y,z of z=0 and x,y = any
numbers in your number system. However you can also express this as
0x+0y+-1z=0. The x,y,z solution is the same: z is everywhere 0, x and y
are any number, even though a,b,c are different. We can say that the
plane is 'oriented' differently, if we wish.
But how can we link that concept to the points on the polygon? Well, if
you generate a plane using the standard plane-equation generation
formula, given three points M,N,P, then you will get a plane equation
with <a:b:c:d>. However if you feed the points in the reverse order,
P,N,M, so that they are now oriented in the opposite order, you will get
a plane equation with the signs flipped. <-a:-b:-c:-d> This means you
can essentially consider that a plane has an 'orientation' based on it's
equation, by looking at the signs of a,b,c relative to some other
quantity.
This means that you can 'flip' the projection of the input polygon
points so that the projection will match the orientation of the input
plane, thus guaranteeing that the output triangles will be oriented in
the same direction as the input polygon was. In other words, even though
we technically 'lose information' when we project from 3d->2d, we can
actually keep the concept of 'orientation' through the whole
triangulation process, and not have to recalculate the proper
orientation during output.
For example take two side-squares of a cube and the plane equations
formed by feeding the points in counterclockwise, as if looking in from
outside the cube:
0,0,0 0,1,0 0,1,1 0,0,1 <-1:0:0:0>
1,0,0 1,1,0 1,1,1 1,0,1 <1:0:0:1>
They are both projected onto the YZ plane. They look the same:
0,0 1,0 1,1 0,1
0,0 1,0 1,1 0,1
But the second square plane has opposite orientation, so we flip the x
and y for each point:
0,0 1,0 1,1 0,1
0,0 0,1 1,1 1,0
Only now do we feed these two 2-d squares to the tessellation algorithm.
The result is 4 triangles. When de-projected back to 3d, they will have
the appropriate winding that will match that of the original 3d faces.
And the first two triangles will have opposite orientation from the last two.
*/
typedef enum { XYPLANE, YZPLANE, XZPLANE, NONE } plane_t;
struct projection_t {
plane_t plane;
bool flip;
};
CGAL_Point_2 get_projected_point( CGAL_Point_3 &p3, projection_t projection ) {
NT3 x,y;
if (projection.plane == XYPLANE) { x = p3.x(); y = p3.y(); }
else if (projection.plane == XZPLANE) { x = p3.x(); y = p3.z(); }
else if (projection.plane == YZPLANE) { x = p3.y(); y = p3.z(); }
else if (projection.plane == NONE) { x = 0; y = 0; }
if (projection.flip) return CGAL_Point_2( y,x );
return CGAL_Point_2( x,y );
}
/* given 2d point, 3d plane, and 3d->2d projection, 'deproject' from
2d back onto a point on the 3d plane. true on failure, false on success */
bool deproject( CGAL_Point_2 &p2, projection_t &projection, CGAL_Plane_3 &plane, CGAL_Point_3 &p3 )
{
NT3 x,y;
CGAL_Line_3 l;
CGAL_Point_3 p;
CGAL_Point_2 pf( p2.x(), p2.y() );
if (projection.flip) pf = CGAL_Point_2( p2.y(), p2.x() );
if (projection.plane == XYPLANE) {
p = CGAL_Point_3( pf.x(), pf.y(), 0 );
l = CGAL_Line_3( p, CGAL_Direction_3(0,0,1) );
} else if (projection.plane == XZPLANE) {
p = CGAL_Point_3( pf.x(), 0, pf.y() );
l = CGAL_Line_3( p, CGAL_Direction_3(0,1,0) );
} else if (projection.plane == YZPLANE) {
p = CGAL_Point_3( 0, pf.x(), pf.y() );
l = CGAL_Line_3( p, CGAL_Direction_3(1,0,0) );
}
CGAL::Object obj = CGAL::intersection( l, plane );
const CGAL_Point_3 *point_test = CGAL::object_cast<CGAL_Point_3>(&obj);
if (point_test) {
p3 = *point_test;
return false;
}
PRINT("ERROR: deproject failure");
return true;
}
/* this simple criteria guarantees CGALs triangulation algorithm will
terminate (i.e. not lock up and freeze the program) */
template <class T> class DummyCriteria {
public:
typedef double Quality;
class Is_bad {
public:
CGAL::Mesh_2::Face_badness operator()(const Quality) const {
return CGAL::Mesh_2::NOT_BAD;
}
CGAL::Mesh_2::Face_badness operator()(const typename T::Face_handle&, Quality&q) const {
q = 1;
return CGAL::Mesh_2::NOT_BAD;
}
};
Is_bad is_bad_object() const { return Is_bad(); }
};
NT3 sign( const NT3 &n )
{
if (n>0) return NT3(1);
if (n<0) return NT3(-1);
return NT3(0);
}
/* wedge, also related to 'determinant', 'signed parallelogram area',
'side', 'turn', 'winding', '2d portion of cross-product', etc etc. this
function can tell you whether v1 is 'counterclockwise' or 'clockwise'
from v2, based on the sign of the result. when the input Vectors are
formed from three points, A-B and B-C, it can tell you if the path along
the points A->B->C is turning left or right.*/
NT3 wedge( CGAL_Vector_2 &v1, CGAL_Vector_2 &v2 ) {
return v1.x()*v2.y()-v2.x()*v1.y();
}
/* given a point and a possibly non-simple polygon, determine if the
point is inside the polygon or not, using the given winding rule. note
that even_odd is not implemented. */
typedef enum { NONZERO_WINDING, EVEN_ODD } winding_rule_t;
bool inside(CGAL_Point_2 &p1,std::vector<CGAL_Point_2> &pgon, winding_rule_t winding_rule)
{
NT3 winding_sum = NT3(0);
CGAL_Point_2 p2;
CGAL_Ray_2 eastray(p1,CGAL_Direction_2(1,0));
for (size_t i=0;i<pgon.size();i++) {
CGAL_Point_2 tail = pgon[i];
CGAL_Point_2 head = pgon[(i+1)%pgon.size()];
CGAL_Segment_2 seg( tail, head );
CGAL::Object obj = intersection( eastray, seg );
const CGAL_Point_2 *point_test = CGAL::object_cast<CGAL_Point_2>(&obj);
if (point_test) {
p2 = *point_test;
CGAL_Vector_2 v1( p1, p2 );
CGAL_Vector_2 v2( p2, head );
NT3 this_winding = wedge( v1, v2 );
winding_sum += sign(this_winding);
} else {
continue;
}
}
if (winding_sum != NT3(0) && winding_rule == NONZERO_WINDING ) return true;
return false;
}
projection_t find_good_projection( CGAL_Plane_3 &plane )
{
projection_t goodproj;
goodproj.plane = NONE;
goodproj.flip = false;
NT3 qxy = plane.a()*plane.a()+plane.b()*plane.b();
NT3 qyz = plane.b()*plane.b()+plane.c()*plane.c();
NT3 qxz = plane.a()*plane.a()+plane.c()*plane.c();
NT3 min = std::min(qxy,std::min(qyz,qxz));
if (min==qxy) {
goodproj.plane = XYPLANE;
if (sign(plane.c())>0) goodproj.flip = true;
} else if (min==qyz) {
goodproj.plane = YZPLANE;
if (sign(plane.a())>0) goodproj.flip = true;
} else if (min==qxz) {
goodproj.plane = XZPLANE;
if (sign(plane.b())<0) goodproj.flip = true;
} else PRINT("ERROR: failed to find projection");
return goodproj;
}
namespace CGALUtils {
/* given a single near-planar 3d polygon with holes, tessellate into a
sequence of polygons without holes. as of writing, this means conversion
into a sequence of 3d triangles. the given plane should be the same plane
holding the polygon and it's holes. */
bool tessellate3DFaceWithHoles(std::vector<CGAL_Polygon_3> &polygons,
std::vector<CGAL_Polygon_3> &triangles,
CGAL_Plane_3 &plane)
{
if (polygons.size()==1 && polygons[0].size()==3) {
PRINTD("input polygon has 3 points. shortcut tessellation.");
CGAL_Polygon_3 t;
t.push_back(polygons[0][2]);
t.push_back(polygons[0][1]);
t.push_back(polygons[0][0]);
triangles.push_back( t );
return false;
}
bool err = false;
CDT cdt;
std::map<CDTPoint,CGAL_Point_3> vertmap;
PRINTD("finding good projection");
projection_t goodproj = find_good_projection( plane );
PRINTDB("plane %s",plane );
PRINTDB("proj: %i %i",goodproj.plane % goodproj.flip);
PRINTD("Inserting points and edges into Constrained Delaunay Triangulation");
std::vector< std::vector<CGAL_Point_2> > polygons2d;
for (size_t i=0;i<polygons.size();i++) {
std::vector<Vertex_handle> vhandles;
std::vector<CGAL_Point_2> polygon2d;
for (size_t j=0;j<polygons[i].size();j++) {
CGAL_Point_3 p3 = polygons[i][j];
CGAL_Point_2 p2 = get_projected_point( p3, goodproj );
CDTPoint cdtpoint = CDTPoint( p2.x(), p2.y() );
vertmap[ cdtpoint ] = p3;
Vertex_handle vh = cdt.push_back( cdtpoint );
vhandles.push_back( vh );
polygon2d.push_back( p2 );
}
polygons2d.push_back( polygon2d );
for (size_t k=0;k<vhandles.size();k++) {
int vindex1 = (k+0);
int vindex2 = (k+1)%vhandles.size();
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
cdt.insert_constraint( vhandles[vindex1], vhandles[vindex2] );
} catch (const CGAL::Failure_exception &e) {
PRINTB("WARNING: Constraint insertion failure %s", e.what());
}
CGAL::set_error_behaviour(old_behaviour);
}
}
size_t numholes = polygons2d.size()-1;
PRINTDB("seeding %i holes",numholes);
std::list<CDTPoint> list_of_seeds;
for (size_t i=1;i<polygons2d.size();i++) {
std::vector<CGAL_Point_2> &pgon = polygons2d[i];
for (size_t j=0;j<pgon.size();j++) {
CGAL_Point_2 p1 = pgon[(j+0)];
CGAL_Point_2 p2 = pgon[(j+1)%pgon.size()];
CGAL_Point_2 p3 = pgon[(j+2)%pgon.size()];
CGAL_Point_2 mp = CGAL::midpoint(p1,CGAL::midpoint(p2,p3));
if (inside(mp,pgon,NONZERO_WINDING)) {
CDTPoint cdtpt( mp.x(), mp.y() );
list_of_seeds.push_back( cdtpt );
break;
}
}
}
std::list<CDTPoint>::iterator li = list_of_seeds.begin();
for (;li!=list_of_seeds.end();li++) {
//PRINTB("seed %s",*li);
double x = CGAL::to_double( li->x() );
double y = CGAL::to_double( li->y() );
PRINTDB("seed %f,%f",x%y);
}
PRINTD("seeding done");
PRINTD( "meshing" );
CGAL::refine_Delaunay_mesh_2_without_edge_refinement( cdt,
list_of_seeds.begin(), list_of_seeds.end(),
DummyCriteria<CDT>() );
PRINTD("meshing done");
// this fails because it calls is_simple and is_simple fails on many
// Nef Polyhedron faces
//CGAL::Orientation original_orientation =
// CGAL::orientation_2( orienpgon.begin(), orienpgon.end() );
CDT::Finite_faces_iterator fit;
for( fit=cdt.finite_faces_begin(); fit!=cdt.finite_faces_end(); fit++ )
{
if(fit->is_in_domain()) {
CDTPoint p1 = cdt.triangle( fit )[0];
CDTPoint p2 = cdt.triangle( fit )[1];
CDTPoint p3 = cdt.triangle( fit )[2];
CGAL_Point_3 cp1,cp2,cp3;
CGAL_Polygon_3 pgon;
if (vertmap.count(p1)) cp1 = vertmap[p1];
else err = deproject( p1, goodproj, plane, cp1 );
if (vertmap.count(p2)) cp2 = vertmap[p2];
else err = deproject( p2, goodproj, plane, cp2 );
if (vertmap.count(p3)) cp3 = vertmap[p3];
else err = deproject( p3, goodproj, plane, cp3 );
if (err) PRINT("WARNING: 2d->3d deprojection failure");
pgon.push_back( cp1 );
pgon.push_back( cp2 );
pgon.push_back( cp3 );
triangles.push_back( pgon );
}
}
PRINTDB("built %i triangles",triangles.size());
return err;
}
};

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
#pragma once
#include <cgal.h>
#include "cgal.h"
#include "polyset.h"
#include "CGAL_Nef_polyhedron.h"
#include "enums.h"
@ -13,12 +13,17 @@ namespace CGALUtils {
CGAL_Iso_cuboid_3 boundingBox(const CGAL_Nef_polyhedron3 &N);
bool is_approximately_convex(const PolySet &ps);
Geometry const* applyMinkowski(const Geometry::ChildList &children);
};
CGAL_Nef_polyhedron *createNefPolyhedronFromGeometry(const class Geometry &geom);
template <typename Polyhedron> bool createPolySetFromPolyhedron(const Polyhedron &p, PolySet &ps);
bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps);
bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p);
CGAL_Nef_polyhedron *createNefPolyhedronFromGeometry(const class Geometry &geom);
template <typename Polyhedron> bool createPolySetFromPolyhedron(const Polyhedron &p, PolySet &ps);
bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps);
bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p);
typedef std::vector<CGAL_Point_3> CGAL_Polygon_3;
bool tessellate3DFaceWithHoles(std::vector<CGAL_Polygon_3> &polygons,
std::vector<CGAL_Polygon_3> &triangles,
CGAL::Plane_3<CGAL_Kernel3> &plane);
};
#include "svg.h"
#include "printutils.h"

View File

@ -35,18 +35,18 @@
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
using namespace boost::assign; // bring 'operator+=()' into scope
#include "colormap.h"
class ColorModule : public AbstractModule
{
public:
ColorModule() { }
ColorModule() : webcolors(ColorMap::inst()->webColors()) { }
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
private:
static boost::unordered_map<std::string, Color4f> colormap;
const boost::unordered_map<std::string, Color4f> &webcolors;
};
#include "colormap.h"
AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
ColorNode *node = new ColorNode(inst);
@ -72,8 +72,8 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
std::string colorname = v.toString();
boost::algorithm::to_lower(colorname);
Color4f color;
if (colormap.find(colorname) != colormap.end()) {
node->color = colormap[colorname];
if (webcolors.find(colorname) != webcolors.end()) {
node->color = webcolors.at(colorname);
} else {
PRINTB_NOCACHE("WARNING: Color name \"%s\" unknown. Please see", colorname);
PRINT_NOCACHE("WARNING: http://en.wikipedia.org/wiki/Web_colors");

318
src/colormap.cc Normal file
View File

@ -0,0 +1,318 @@
#include "colormap.h"
#include <boost/assign/list_of.hpp>
#include "printutils.h"
using namespace boost::assign; // bring map_list_of() into scope
ColorMap *ColorMap::inst(bool erase)
{
static ColorMap *instance = new ColorMap;
if (erase) {
delete instance;
instance = NULL;
}
return instance;
}
ColorMap::ColorMap() {
webcolors = map_list_of
("aliceblue", Color4f(240, 248, 255))
("antiquewhite", Color4f(250, 235, 215))
("aqua", Color4f(0, 255, 255))
("aquamarine", Color4f(127, 255, 212))
("azure", Color4f(240, 255, 255))
("beige", Color4f(245, 245, 220))
("bisque", Color4f(255, 228, 196))
("black", Color4f(0, 0, 0))
("blanchedalmond", Color4f(255, 235, 205))
("blue", Color4f(0, 0, 255))
("blueviolet", Color4f(138, 43, 226))
("brown", Color4f(165, 42, 42))
("burlywood", Color4f(222, 184, 135))
("cadetblue", Color4f(95, 158, 160))
("chartreuse", Color4f(127, 255, 0))
("chocolate", Color4f(210, 105, 30))
("coral", Color4f(255, 127, 80))
("cornflowerblue", Color4f(100, 149, 237))
("cornsilk", Color4f(255, 248, 220))
("crimson", Color4f(220, 20, 60))
("cyan", Color4f(0, 255, 255))
("darkblue", Color4f(0, 0, 139))
("darkcyan", Color4f(0, 139, 139))
("darkgoldenrod", Color4f(184, 134, 11))
("darkgray", Color4f(169, 169, 169))
("darkgreen", Color4f(0, 100, 0))
("darkgrey", Color4f(169, 169, 169))
("darkkhaki", Color4f(189, 183, 107))
("darkmagenta", Color4f(139, 0, 139))
("darkolivegreen", Color4f(85, 107, 47))
("darkorange", Color4f(255, 140, 0))
("darkorchid", Color4f(153, 50, 204))
("darkred", Color4f(139, 0, 0))
("darksalmon", Color4f(233, 150, 122))
("darkseagreen", Color4f(143, 188, 143))
("darkslateblue", Color4f(72, 61, 139))
("darkslategray", Color4f(47, 79, 79))
("darkslategrey", Color4f(47, 79, 79))
("darkturquoise", Color4f(0, 206, 209))
("darkviolet", Color4f(148, 0, 211))
("deeppink", Color4f(255, 20, 147))
("deepskyblue", Color4f(0, 191, 255))
("dimgray", Color4f(105, 105, 105))
("dimgrey", Color4f(105, 105, 105))
("dodgerblue", Color4f(30, 144, 255))
("firebrick", Color4f(178, 34, 34))
("floralwhite", Color4f(255, 250, 240))
("forestgreen", Color4f(34, 139, 34))
("fuchsia", Color4f(255, 0, 255))
("gainsboro", Color4f(220, 220, 220))
("ghostwhite", Color4f(248, 248, 255))
("gold", Color4f(255, 215, 0))
("goldenrod", Color4f(218, 165, 32))
("gray", Color4f(128, 128, 128))
("green", Color4f(0, 128, 0))
("greenyellow", Color4f(173, 255, 47))
("grey", Color4f(128, 128, 128))
("honeydew", Color4f(240, 255, 240))
("hotpink", Color4f(255, 105, 180))
("indianred", Color4f(205, 92, 92))
("indigo", Color4f(75, 0, 130))
("ivory", Color4f(255, 255, 240))
("khaki", Color4f(240, 230, 140))
("lavender", Color4f(230, 230, 250))
("lavenderblush", Color4f(255, 240, 245))
("lawngreen", Color4f(124, 252, 0))
("lemonchiffon", Color4f(255, 250, 205))
("lightblue", Color4f(173, 216, 230))
("lightcoral", Color4f(240, 128, 128))
("lightcyan", Color4f(224, 255, 255))
("lightgoldenrodyellow", Color4f(250, 250, 210))
("lightgray", Color4f(211, 211, 211))
("lightgreen", Color4f(144, 238, 144))
("lightgrey", Color4f(211, 211, 211))
("lightpink", Color4f(255, 182, 193))
("lightsalmon", Color4f(255, 160, 122))
("lightseagreen", Color4f(32, 178, 170))
("lightskyblue", Color4f(135, 206, 250))
("lightslategray", Color4f(119, 136, 153))
("lightslategrey", Color4f(119, 136, 153))
("lightsteelblue", Color4f(176, 196, 222))
("lightyellow", Color4f(255, 255, 224))
("lime", Color4f(0, 255, 0))
("limegreen", Color4f(50, 205, 50))
("linen", Color4f(250, 240, 230))
("magenta", Color4f(255, 0, 255))
("maroon", Color4f(128, 0, 0))
("mediumaquamarine", Color4f(102, 205, 170))
("mediumblue", Color4f(0, 0, 205))
("mediumorchid", Color4f(186, 85, 211))
("mediumpurple", Color4f(147, 112, 219))
("mediumseagreen", Color4f(60, 179, 113))
("mediumslateblue", Color4f(123, 104, 238))
("mediumspringgreen", Color4f(0, 250, 154))
("mediumturquoise", Color4f(72, 209, 204))
("mediumvioletred", Color4f(199, 21, 133))
("midnightblue", Color4f(25, 25, 112))
("mintcream", Color4f(245, 255, 250))
("mistyrose", Color4f(255, 228, 225))
("moccasin", Color4f(255, 228, 181))
("navajowhite", Color4f(255, 222, 173))
("navy", Color4f(0, 0, 128))
("oldlace", Color4f(253, 245, 230))
("olive", Color4f(128, 128, 0))
("olivedrab", Color4f(107, 142, 35))
("orange", Color4f(255, 165, 0))
("orangered", Color4f(255, 69, 0))
("orchid", Color4f(218, 112, 214))
("palegoldenrod", Color4f(238, 232, 170))
("palegreen", Color4f(152, 251, 152))
("paleturquoise", Color4f(175, 238, 238))
("palevioletred", Color4f(219, 112, 147))
("papayawhip", Color4f(255, 239, 213))
("peachpuff", Color4f(255, 218, 185))
("peru", Color4f(205, 133, 63))
("pink", Color4f(255, 192, 203))
("plum", Color4f(221, 160, 221))
("powderblue", Color4f(176, 224, 230))
("purple", Color4f(128, 0, 128))
("red", Color4f(255, 0, 0))
("rosybrown", Color4f(188, 143, 143))
("royalblue", Color4f(65, 105, 225))
("saddlebrown", Color4f(139, 69, 19))
("salmon", Color4f(250, 128, 114))
("sandybrown", Color4f(244, 164, 96))
("seagreen", Color4f(46, 139, 87))
("seashell", Color4f(255, 245, 238))
("sienna", Color4f(160, 82, 45))
("silver", Color4f(192, 192, 192))
("skyblue", Color4f(135, 206, 235))
("slateblue", Color4f(106, 90, 205))
("slategray", Color4f(112, 128, 144))
("slategrey", Color4f(112, 128, 144))
("snow", Color4f(255, 250, 250))
("springgreen", Color4f(0, 255, 127))
("steelblue", Color4f(70, 130, 180))
("tan", Color4f(210, 180, 140))
("teal", Color4f(0, 128, 128))
("thistle", Color4f(216, 191, 216))
("tomato", Color4f(255, 99, 71))
("transparent", Color4f(0, 0, 0, 0))
("turquoise", Color4f(64, 224, 208))
("violet", Color4f(238, 130, 238))
("wheat", Color4f(245, 222, 179))
("white", Color4f(255, 255, 255))
("whitesmoke", Color4f(245, 245, 245))
("yellow", Color4f(255, 255, 0))
("yellowgreen", Color4f(154, 205, 50));
ColorScheme cornfield = map_list_of
(BACKGROUND_COLOR, Color4f(0xff, 0xff, 0xe5))
(OPENCSG_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))
(OPENCSG_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51))
(CGAL_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))
(CGAL_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51))
(CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99))
(CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0xec, 0x5e))
(CGAL_EDGE_BACK_COLOR, Color4f(0xab, 0xd8, 0x56))
(CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00))
(CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00));
ColorScheme metallic = map_list_of
(BACKGROUND_COLOR, Color4f(0xaa, 0xaa, 0xff))
(OPENCSG_FACE_FRONT_COLOR, Color4f(0xdd, 0xdd, 0xff))
(OPENCSG_FACE_BACK_COLOR, Color4f(0xdd, 0x22, 0xdd))
(CGAL_FACE_FRONT_COLOR, Color4f(0xdd, 0xdd, 0xff))
(CGAL_FACE_BACK_COLOR, Color4f(0xdd, 0x22, 0xdd))
(CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99))
(CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00))
(CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00));
ColorScheme sunset = map_list_of
(BACKGROUND_COLOR, Color4f(0xaa, 0x44, 0x44))
(OPENCSG_FACE_FRONT_COLOR, Color4f(0xff, 0xaa, 0xaa))
(OPENCSG_FACE_BACK_COLOR, Color4f(0x88, 0x22, 0x33))
(CGAL_FACE_FRONT_COLOR, Color4f(0xff, 0xaa, 0xaa))
(CGAL_FACE_BACK_COLOR, Color4f(0x88, 0x22, 0x33))
(CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99))
(CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00))
(CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00));
ColorScheme starnight = map_list_of
(BACKGROUND_COLOR, webcolors["black"])
(OPENCSG_FACE_FRONT_COLOR, webcolors["lightyellow"])
(OPENCSG_FACE_BACK_COLOR, webcolors["cyan"])
(CGAL_FACE_FRONT_COLOR, webcolors["lightyellow"])
(CGAL_FACE_BACK_COLOR, webcolors["cyan"])
(CGAL_FACE_2D_COLOR, webcolors["mediumpurple"])
(CGAL_EDGE_FRONT_COLOR, Color4f(0x00, 0x00, 0xff))
(CGAL_EDGE_BACK_COLOR, Color4f(0x00, 0x00, 0xff))
(CGAL_EDGE_2D_COLOR, webcolors["magenta"])
(CROSSHAIR_COLOR, Color4f(0xf0, 0xf0, 0xf0));
ColorScheme beforedawn = map_list_of
(BACKGROUND_COLOR, Color4f(0x33, 0x33, 0x33))
(OPENCSG_FACE_FRONT_COLOR, Color4f(0xcc, 0xcc, 0xcc))
(OPENCSG_FACE_BACK_COLOR, Color4f(0x55, 0x63, 0xdd))
(CGAL_FACE_FRONT_COLOR, Color4f(0xcc, 0xcc, 0xcc))
(CGAL_FACE_BACK_COLOR, Color4f(0x55, 0x63, 0xdd))
(CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99))
(CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00))
(CROSSHAIR_COLOR, Color4f(0xf0, 0xf0, 0xf0));
ColorScheme nature = map_list_of
(BACKGROUND_COLOR, Color4f(0xfa, 0xfa, 0xfa))
(OPENCSG_FACE_FRONT_COLOR, Color4f(0x16, 0xa0, 0x85))
(OPENCSG_FACE_BACK_COLOR, Color4f(0xdb, 0xf4, 0xda))
(CGAL_FACE_FRONT_COLOR, Color4f(0x16, 0xa0, 0x85))
(CGAL_FACE_BACK_COLOR, Color4f(0xdb, 0xf4, 0xda))
(CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99))
(CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00))
(CROSSHAIR_COLOR, Color4f(0x11, 0x11, 0x11));
ColorScheme deepocean = map_list_of
(BACKGROUND_COLOR, Color4f(0x33, 0x33, 0x33))
(OPENCSG_FACE_FRONT_COLOR, Color4f(0xee, 0xee, 0xee))
(OPENCSG_FACE_BACK_COLOR, Color4f(0x0b, 0xab, 0xc8))
(CGAL_FACE_FRONT_COLOR, Color4f(0xee, 0xee, 0xee))
(CGAL_FACE_BACK_COLOR, Color4f(0x0b, 0xab, 0xc8))
(CGAL_FACE_2D_COLOR, webcolors["mediumpurple"])
(CGAL_EDGE_FRONT_COLOR, Color4f(0x00, 0x00, 0xff))
(CGAL_EDGE_BACK_COLOR, Color4f(0x00, 0x00, 0xff))
(CGAL_EDGE_2D_COLOR, webcolors["magenta"])
(CROSSHAIR_COLOR, Color4f(0xf0, 0xf0, 0xf0));
// Monotone - no difference between 'back face' and 'front face'
ColorScheme monotone = map_list_of
(BACKGROUND_COLOR, Color4f(0xff, 0xff, 0xe5))
(OPENCSG_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))
(OPENCSG_FACE_BACK_COLOR, Color4f(0xf9, 0xd7, 0x2c))
(CGAL_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))
(CGAL_FACE_BACK_COLOR, Color4f(0xf9, 0xd7, 0x2c))
(CGAL_FACE_2D_COLOR, Color4f(0x00, 0xbf, 0x99))
(CGAL_EDGE_FRONT_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_BACK_COLOR, Color4f(0xff, 0x00, 0x00))
(CGAL_EDGE_2D_COLOR, Color4f(0xff, 0x00, 0x00))
(CROSSHAIR_COLOR, Color4f(0x80, 0x00, 0x00));
colorschemes = map_list_of
("Cornfield", cornfield)
("Metallic", metallic)
("Sunset", sunset)
("Starnight", starnight)
("BeforeDawn", beforedawn)
("Nature", nature)
("DeepOcean", deepocean)
("Monotone", monotone); // Hidden, not in GUI
}
const ColorScheme &ColorMap::defaultColorScheme() const
{
return colorschemes.at("Cornfield");
}
const ColorScheme *ColorMap::findColorScheme(const std::string &name) const
{
if (colorschemes.find(name) != colorschemes.end()) return &colorschemes.at(name);
return NULL;
}
std::list<std::string> ColorMap::colorSchemeNames() const
{
std::list<std::string> names;
for (boost::unordered_map<std::string, ColorScheme>::const_iterator iter=colorschemes.begin(); iter!=colorschemes.end(); iter++) {
names.push_back(iter->first);
}
return names;
}
Color4f ColorMap::getColor(const ColorScheme &cs, const RenderColor rc)
{
if (cs.count(rc)) return cs.at(rc);
if (ColorMap::inst()->defaultColorScheme().count(rc)) return ColorMap::inst()->defaultColorScheme().at(rc);
return Color4f(0, 0, 0, 127);
}
/*
void printcolorscheme(const ColorScheme &cs)
{
for (ColorScheme::const_iterator j=cs.begin();j!=cs.end();j++)
PRINTB("%i %s",j->first % j->second.transpose());
}
void printcolorschemes()
{
for (boost::unordered_map<std::string, ColorScheme>::const_iterator i=colorschemes.begin();i!=colorschemes.end();i++) {
PRINTB("-- %s --", i->first);
for (ColorScheme::const_iterator j=i->second.begin();j!=i->second.end();j++)
PRINTB("%i %s",j->first % j->second.transpose());
}
}
*/

View File

@ -1,149 +1,43 @@
boost::unordered_map<std::string, Color4f> ColorModule::colormap = map_list_of
("aliceblue", Color4f(240, 248, 255))
("antiquewhite", Color4f(250, 235, 215))
("aqua", Color4f(0, 255, 255))
("aquamarine", Color4f(127, 255, 212))
("azure", Color4f(240, 255, 255))
("beige", Color4f(245, 245, 220))
("bisque", Color4f(255, 228, 196))
("black", Color4f(0, 0, 0))
("blanchedalmond", Color4f(255, 235, 205))
("blue", Color4f(0, 0, 255))
("blueviolet", Color4f(138, 43, 226))
("brown", Color4f(165, 42, 42))
("burlywood", Color4f(222, 184, 135))
("cadetblue", Color4f(95, 158, 160))
("chartreuse", Color4f(127, 255, 0))
("chocolate", Color4f(210, 105, 30))
("coral", Color4f(255, 127, 80))
("cornflowerblue", Color4f(100, 149, 237))
("cornsilk", Color4f(255, 248, 220))
("crimson", Color4f(220, 20, 60))
("cyan", Color4f(0, 255, 255))
("darkblue", Color4f(0, 0, 139))
("darkcyan", Color4f(0, 139, 139))
("darkgoldenrod", Color4f(184, 134, 11))
("darkgray", Color4f(169, 169, 169))
("darkgreen", Color4f(0, 100, 0))
("darkgrey", Color4f(169, 169, 169))
("darkkhaki", Color4f(189, 183, 107))
("darkmagenta", Color4f(139, 0, 139))
("darkolivegreen", Color4f(85, 107, 47))
("darkorange", Color4f(255, 140, 0))
("darkorchid", Color4f(153, 50, 204))
("darkred", Color4f(139, 0, 0))
("darksalmon", Color4f(233, 150, 122))
("darkseagreen", Color4f(143, 188, 143))
("darkslateblue", Color4f(72, 61, 139))
("darkslategray", Color4f(47, 79, 79))
("darkslategrey", Color4f(47, 79, 79))
("darkturquoise", Color4f(0, 206, 209))
("darkviolet", Color4f(148, 0, 211))
("deeppink", Color4f(255, 20, 147))
("deepskyblue", Color4f(0, 191, 255))
("dimgray", Color4f(105, 105, 105))
("dimgrey", Color4f(105, 105, 105))
("dodgerblue", Color4f(30, 144, 255))
("firebrick", Color4f(178, 34, 34))
("floralwhite", Color4f(255, 250, 240))
("forestgreen", Color4f(34, 139, 34))
("fuchsia", Color4f(255, 0, 255))
("gainsboro", Color4f(220, 220, 220))
("ghostwhite", Color4f(248, 248, 255))
("gold", Color4f(255, 215, 0))
("goldenrod", Color4f(218, 165, 32))
("gray", Color4f(128, 128, 128))
("green", Color4f(0, 128, 0))
("greenyellow", Color4f(173, 255, 47))
("grey", Color4f(128, 128, 128))
("honeydew", Color4f(240, 255, 240))
("hotpink", Color4f(255, 105, 180))
("indianred", Color4f(205, 92, 92))
("indigo", Color4f(75, 0, 130))
("ivory", Color4f(255, 255, 240))
("khaki", Color4f(240, 230, 140))
("lavender", Color4f(230, 230, 250))
("lavenderblush", Color4f(255, 240, 245))
("lawngreen", Color4f(124, 252, 0))
("lemonchiffon", Color4f(255, 250, 205))
("lightblue", Color4f(173, 216, 230))
("lightcoral", Color4f(240, 128, 128))
("lightcyan", Color4f(224, 255, 255))
("lightgoldenrodyellow", Color4f(250, 250, 210))
("lightgray", Color4f(211, 211, 211))
("lightgreen", Color4f(144, 238, 144))
("lightgrey", Color4f(211, 211, 211))
("lightpink", Color4f(255, 182, 193))
("lightsalmon", Color4f(255, 160, 122))
("lightseagreen", Color4f(32, 178, 170))
("lightskyblue", Color4f(135, 206, 250))
("lightslategray", Color4f(119, 136, 153))
("lightslategrey", Color4f(119, 136, 153))
("lightsteelblue", Color4f(176, 196, 222))
("lightyellow", Color4f(255, 255, 224))
("lime", Color4f(0, 255, 0))
("limegreen", Color4f(50, 205, 50))
("linen", Color4f(250, 240, 230))
("magenta", Color4f(255, 0, 255))
("maroon", Color4f(128, 0, 0))
("mediumaquamarine", Color4f(102, 205, 170))
("mediumblue", Color4f(0, 0, 205))
("mediumorchid", Color4f(186, 85, 211))
("mediumpurple", Color4f(147, 112, 219))
("mediumseagreen", Color4f(60, 179, 113))
("mediumslateblue", Color4f(123, 104, 238))
("mediumspringgreen", Color4f(0, 250, 154))
("mediumturquoise", Color4f(72, 209, 204))
("mediumvioletred", Color4f(199, 21, 133))
("midnightblue", Color4f(25, 25, 112))
("mintcream", Color4f(245, 255, 250))
("mistyrose", Color4f(255, 228, 225))
("moccasin", Color4f(255, 228, 181))
("navajowhite", Color4f(255, 222, 173))
("navy", Color4f(0, 0, 128))
("oldlace", Color4f(253, 245, 230))
("olive", Color4f(128, 128, 0))
("olivedrab", Color4f(107, 142, 35))
("orange", Color4f(255, 165, 0))
("orangered", Color4f(255, 69, 0))
("orchid", Color4f(218, 112, 214))
("palegoldenrod", Color4f(238, 232, 170))
("palegreen", Color4f(152, 251, 152))
("paleturquoise", Color4f(175, 238, 238))
("palevioletred", Color4f(219, 112, 147))
("papayawhip", Color4f(255, 239, 213))
("peachpuff", Color4f(255, 218, 185))
("peru", Color4f(205, 133, 63))
("pink", Color4f(255, 192, 203))
("plum", Color4f(221, 160, 221))
("powderblue", Color4f(176, 224, 230))
("purple", Color4f(128, 0, 128))
("red", Color4f(255, 0, 0))
("rosybrown", Color4f(188, 143, 143))
("royalblue", Color4f(65, 105, 225))
("saddlebrown", Color4f(139, 69, 19))
("salmon", Color4f(250, 128, 114))
("sandybrown", Color4f(244, 164, 96))
("seagreen", Color4f(46, 139, 87))
("seashell", Color4f(255, 245, 238))
("sienna", Color4f(160, 82, 45))
("silver", Color4f(192, 192, 192))
("skyblue", Color4f(135, 206, 235))
("slateblue", Color4f(106, 90, 205))
("slategray", Color4f(112, 128, 144))
("slategrey", Color4f(112, 128, 144))
("snow", Color4f(255, 250, 250))
("springgreen", Color4f(0, 255, 127))
("steelblue", Color4f(70, 130, 180))
("tan", Color4f(210, 180, 140))
("teal", Color4f(0, 128, 128))
("thistle", Color4f(216, 191, 216))
("tomato", Color4f(255, 99, 71))
("transparent", Color4f(0, 0, 0, 0))
("turquoise", Color4f(64, 224, 208))
("violet", Color4f(238, 130, 238))
("wheat", Color4f(245, 222, 179))
("white", Color4f(255, 255, 255))
("whitesmoke", Color4f(245, 245, 245))
("yellow", Color4f(255, 255, 0))
("yellowgreen", Color4f(154, 205, 50));
#pragma once
#include <map>
#include <string>
#include <list>
#include "linalg.h"
#include <boost/unordered/unordered_map.hpp>
enum RenderColor {
BACKGROUND_COLOR,
OPENCSG_FACE_FRONT_COLOR,
OPENCSG_FACE_BACK_COLOR,
CGAL_FACE_FRONT_COLOR,
CGAL_FACE_2D_COLOR,
CGAL_FACE_BACK_COLOR,
CGAL_EDGE_FRONT_COLOR,
CGAL_EDGE_BACK_COLOR,
CGAL_EDGE_2D_COLOR,
CROSSHAIR_COLOR
};
typedef std::map<RenderColor, Color4f> ColorScheme;
class ColorMap
{
public:
static ColorMap *inst(bool erase = false);
const ColorScheme &defaultColorScheme() const;
const boost::unordered_map<std::string, Color4f> &webColors() const { return webcolors; }
const ColorScheme *findColorScheme(const std::string &name) const;
std::list<std::string> colorSchemeNames() const;
static Color4f getColor(const ColorScheme &cs, const RenderColor rc);
private:
ColorMap();
~ColorMap() {}
boost::unordered_map<std::string, Color4f> webcolors;
boost::unordered_map<std::string, ColorScheme> colorschemes;
};

View File

@ -134,14 +134,33 @@ void export_stl(const PolySet &ps, std::ostream &output)
setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output
output << "solid OpenSCAD_Model\n";
BOOST_FOREACH(const PolySet::Polygon &p, triangulated.polygons) {
output << " facet normal 0 0 0\n";
output << " outer loop\n";
assert(p.size() == 3); // STL only allows triangles
BOOST_FOREACH(const Vector3d &v, p) {
output << "vertex " << v[0] << " " << v[1] << " " << v[2] << "\n";
std::stringstream stream;
stream << p[0][0] << " " << p[0][1] << " " << p[0][2];
std::string vs1 = stream.str();
stream.str("");
stream << p[1][0] << " " << p[1][1] << " " << p[1][2];
std::string vs2 = stream.str();
stream.str("");
stream << p[2][0] << " " << p[2][1] << " " << p[2][2];
std::string vs3 = stream.str();
if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) {
// The above condition ensures that there are 3 distinct vertices, but
// they may be collinear. If they are, the unit normal is meaningless
// so the default value of "1 0 0" can be used. If the vertices are not
// collinear then the unit normal must be calculated from the
// components.
Vector3d normal = (p[1] - p[0]).cross(p[2] - p[0]);
normal.normalize();
output << " facet normal " << normal[0] << " " << normal[1] << " " << normal[2] << "\n";
output << " outer loop\n";
BOOST_FOREACH(const Vector3d &v, p) {
output << " vertex " << v[0] << " " << v[1] << " " << v[2] << "\n";
}
output << " endloop\n";
output << " endfacet\n";
}
output << " endloop\n";
output << " endfacet\n";
}
output << "endsolid OpenSCAD_Model\n";
setlocale(LC_NUMERIC, ""); // Set default locale
@ -230,10 +249,10 @@ void export_stl(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
}
bool usePolySet = false;
bool usePolySet = true;
if (usePolySet) {
PolySet ps(3);
bool err = createPolySetFromNefPolyhedron3(*(root_N->p3), ps);
bool err = CGALUtils::createPolySetFromNefPolyhedron3(*(root_N->p3), ps);
if (err) { PRINT("ERROR: Nef->PolySet failed"); }
else {
export_stl(ps, output);
@ -264,7 +283,7 @@ void export_stl(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
void export_off(const class PolySet &ps, std::ostream &output)
{
// FIXME: Implement this without creating a Nef polyhedron
CGAL_Nef_polyhedron *N = createNefPolyhedronFromGeometry(ps);
CGAL_Nef_polyhedron *N = CGALUtils::createNefPolyhedronFromGeometry(ps);
export_off(N, output);
delete N;
}
@ -290,7 +309,7 @@ void export_off(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
void export_amf(const class PolySet &ps, std::ostream &output)
{
// FIXME: Implement this without creating a Nef polyhedron
CGAL_Nef_polyhedron *N = createNefPolyhedronFromGeometry(ps);
CGAL_Nef_polyhedron *N = CGALUtils::createNefPolyhedronFromGeometry(ps);
export_amf(N, output);
delete N;
}

View File

@ -8,7 +8,6 @@
#ifdef ENABLE_CGAL
#include "CGALRenderer.h"
#include "CGAL_renderer.h"
#include "cgal.h"
#include "cgalutils.h"
#include "CGAL_Nef_polyhedron.h"
@ -38,6 +37,7 @@ void export_png(const Geometry *root_geom, Camera &cam, std::ostream &output)
glview->setCamera(cam);
glview->setRenderer(&cgalRenderer);
glview->setColorScheme(RenderSettings::inst()->colorscheme);
glview->paintGL();
glview->save(output);
}
@ -85,6 +85,7 @@ void export_png_preview_common(Tree &tree, Camera &cam, std::ostream &output, Pr
OpenCSG::setContext(0);
OpenCSG::setOption(OpenCSG::OffscreenSetting, OpenCSG::FrameBufferObject);
#endif
csgInfo.glview->setColorScheme(RenderSettings::inst()->colorscheme);
csgInfo.glview->paintGL();
csgInfo.glview->save(output);
}

View File

@ -527,6 +527,17 @@ Value builtin_str(const Context *, const EvalContext *evalctx)
return Value(stream.str());
}
Value builtin_chr(const Context *, const EvalContext *evalctx)
{
std::stringstream stream;
for (size_t i = 0; i < evalctx->numArgs(); i++) {
const Value v = evalctx->getArgValue(i);
stream << v.chrString();
}
return Value(stream.str());
}
Value builtin_concat(const Context *, const EvalContext *evalctx)
{
Value::VectorType result;
@ -928,6 +939,7 @@ void register_builtin_functions()
Builtins::init("log", new BuiltinFunction(&builtin_log));
Builtins::init("ln", new BuiltinFunction(&builtin_ln));
Builtins::init("str", new BuiltinFunction(&builtin_str));
Builtins::init("chr", new BuiltinFunction(&builtin_chr));
Builtins::init("concat", new BuiltinFunction(&builtin_concat));
Builtins::init("lookup", new BuiltinFunction(&builtin_lookup));
Builtins::init("search", new BuiltinFunction(&builtin_search));

View File

@ -287,7 +287,7 @@ Geometry *ImportNode::createGeometry() const
else {
file >> poly;
file.close();
bool err = createPolySetFromPolyhedron(poly, *p);
bool err = CGALUtils::createPolySetFromPolyhedron(poly, *p);
}
#else
PRINT("WARNING: OFF import requires CGAL.");

View File

@ -3,7 +3,7 @@
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <Eigen/Dense>
#include<Eigen/StdVector>
#include <Eigen/StdVector>
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d)
using Eigen::Vector2d;

View File

@ -27,6 +27,7 @@
#include "ModuleCache.h"
#include "MainWindow.h"
#include "parsersettings.h"
#include "rendersettings.h"
#include "Preferences.h"
#include "printutils.h"
#include "node.h"
@ -430,8 +431,13 @@ MainWindow::MainWindow(const QString &filename)
this, SLOT(openCSGSettingsChanged()));
connect(Preferences::inst(), SIGNAL(syntaxHighlightChanged(const QString&)),
editor, SLOT(setHighlightScheme(const QString&)));
connect(Preferences::inst(), SIGNAL(colorSchemeChanged(const QString&)),
this, SLOT(setColorScheme(const QString&)));
Preferences::inst()->apply();
QString cs = Preferences::inst()->getValue("3dview/colorscheme").toString();
this->setColorScheme(cs);
//find and replace panel
connect(this->findTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectFindType(int)));
connect(this->findInputField, SIGNAL(textChanged(QString)), this, SLOT(findString(QString)));
@ -1811,6 +1817,12 @@ void MainWindow::actionExport(export_type_e, QString, QString)
return;
}
if (this->root_geom->isEmpty()) {
PRINT("Current top level object is empty.");
clearCurrentOutput();
return;
}
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(this->root_geom.get());
if (N && !N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export");
@ -1938,7 +1950,7 @@ void MainWindow::actionExportCSG()
return;
}
std::ofstream fstream(csg_filename.toUtf8());
std::ofstream fstream(csg_filename.toLocal8Bit());
if (!fstream.is_open()) {
PRINTB("Can't open file \"%s\" for export", csg_filename.toLocal8Bit().constData());
}
@ -2000,6 +2012,7 @@ void MainWindow::viewModePreview()
viewModeActionsUncheck();
viewActionPreview->setChecked(true);
this->qglview->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer);
this->qglview->updateColorScheme();
this->qglview->updateGL();
} else {
viewModeThrownTogether();
@ -2016,6 +2029,7 @@ void MainWindow::viewModeSurface()
viewActionSurfaces->setChecked(true);
this->qglview->setShowFaces(true);
this->qglview->setRenderer(this->cgalRenderer);
this->qglview->updateColorScheme();
this->qglview->updateGL();
}
@ -2025,6 +2039,7 @@ void MainWindow::viewModeWireframe()
viewActionWireframe->setChecked(true);
this->qglview->setShowFaces(false);
this->qglview->setRenderer(this->cgalRenderer);
this->qglview->updateColorScheme();
this->qglview->updateGL();
}
@ -2035,6 +2050,7 @@ void MainWindow::viewModeThrownTogether()
viewModeActionsUncheck();
viewActionThrownTogether->setChecked(true);
this->qglview->setRenderer(this->thrownTogetherRenderer);
this->qglview->updateColorScheme();
this->qglview->updateGL();
}
@ -2373,6 +2389,23 @@ MainWindow::preferences()
Preferences::inst()->raise();
}
void MainWindow::setColorScheme(const QString &scheme)
{
RenderSettings::inst()->colorscheme = scheme.toStdString();
this->qglview->setColorScheme(scheme.toStdString());
this->qglview->updateGL();
}
void MainWindow::setFont(const QString &family, uint size)
{
QFont font;
if (!family.isEmpty()) font.setFamily(family);
else font.setFixedPitch(true);
if (size > 0) font.setPointSize(size);
font.setStyleHint(QFont::TypeWriter);
editor->setFont(font);
}
void MainWindow::quit()
{
QCloseEvent ev;

View File

@ -81,6 +81,7 @@ std::string currentdir;
using std::string;
using std::vector;
using boost::lexical_cast;
using boost::bad_lexical_cast;
using boost::is_any_of;
class Echostream : public std::ofstream
@ -114,6 +115,7 @@ static void help(const char *progname)
"%2%[ --viewall ] \\\n"
"%2%[ --imgsize=width,height ] [ --projection=(o)rtho|(p)ersp] \\\n"
"%2%[ --render | --preview[=throwntogether] ] \\\n"
"%2%[ --colorscheme=[Cornfield|Sunset|Metallic|Starnight|BeforeDawn|Nature|DeepOcean] ] \\\n"
"%2%[ --csglimit=num ]"
#ifdef ENABLE_EXPERIMENTAL
" [ --enable=<feature> ]"
@ -152,7 +154,7 @@ static void info()
exit(0);
}
Camera get_camera( po::variables_map vm )
Camera get_camera(po::variables_map vm)
{
Camera camera;
@ -161,12 +163,16 @@ Camera get_camera( po::variables_map vm )
vector<double> cam_parameters;
split(strs, vm["camera"].as<string>(), is_any_of(","));
if ( strs.size()==6 || strs.size()==7 ) {
BOOST_FOREACH(string &s, strs)
cam_parameters.push_back(lexical_cast<double>(s));
camera.setup( cam_parameters );
try {
BOOST_FOREACH(string &s, strs) cam_parameters.push_back(lexical_cast<double>(s));
camera.setup(cam_parameters);
}
catch (bad_lexical_cast &) {
PRINT("Camera setup requires numbers as parameters");
}
} else {
PRINT("Camera setup requires either 7 numbers for Gimbal Camera\n");
PRINT("or 6 numbers for Vector Camera\n");
PRINT("Camera setup requires either 7 numbers for Gimbal Camera");
PRINT("or 6 numbers for Vector Camera");
exit(1);
}
}
@ -201,11 +207,16 @@ Camera get_camera( po::variables_map vm )
vector<string> strs;
split(strs, vm["imgsize"].as<string>(), is_any_of(","));
if ( strs.size() != 2 ) {
PRINT("Need 2 numbers for imgsize\n");
PRINT("Need 2 numbers for imgsize");
exit(1);
} else {
w = lexical_cast<int>( strs[0] );
h = lexical_cast<int>( strs[1] );
try {
w = lexical_cast<int>(strs[0]);
h = lexical_cast<int>(strs[1]);
}
catch (bad_lexical_cast &) {
PRINT("Need 2 numbers for imgsize");
}
}
}
camera.pixel_width = w;
@ -228,6 +239,10 @@ static bool checkAndExport(shared_ptr<const Geometry> root_geom, unsigned nd,
PRINTB("Current top level object is not a %dD object.", nd);
return false;
}
if (root_geom->isEmpty()) {
PRINT("Current top level object is empty.");
return false;
}
exportFileByName(root_geom.get(), format, filename, filename);
return true;
}
@ -623,6 +638,7 @@ int main(int argc, char **argv)
("viewall", "adjust camera to fit object")
("imgsize", po::value<string>(), "=width,height for exporting png")
("projection", po::value<string>(), "(o)rtho or (p)erspective when exporting png")
("colorscheme", po::value<string>(), "colorscheme")
("debug", po::value<string>(), "special debug info")
("o,o", po::value<string>(), "out-file")
("s,s", po::value<string>(), "stl-file")
@ -723,6 +739,19 @@ int main(int argc, char **argv)
}
#endif
if (vm.count("colorscheme")) {
std::string colorscheme = vm["colorscheme"].as<string>();
if (ColorMap::inst()->findColorScheme(colorscheme)) {
RenderSettings::inst()->colorscheme = colorscheme;
} else {
PRINT("Unknown color scheme. Valid schemes:");
BOOST_FOREACH (const std::string &name, ColorMap::inst()->colorSchemeNames()) {
PRINT(name);
}
exit(1);
}
}
currentdir = boosty::stringy(fs::current_path());
Camera camera = get_camera(vm);

View File

@ -239,6 +239,7 @@ static void gl_draw_triangle(GLint *shaderinfo, const Vector3d &p0, const Vector
void PolySet::render_surface(Renderer::csgmode_e csgmode, const Transform3d &m, GLint *shaderinfo) const
{
PRINTD("Polyset render");
bool mirrored = m.matrix().determinant() < 0;
#ifdef ENABLE_OPENCSG
if (shaderinfo) {

View File

@ -243,7 +243,7 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
node->faces = c.lookup_variable("faces");
if (node->faces.type() == Value::UNDEFINED) {
// backwards compatible
node->faces = c.lookup_variable("triangles");
node->faces = c.lookup_variable("triangles", true);
if (node->faces.type() != Value::UNDEFINED) {
printDeprecation("DEPRECATED: polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead.");
}

View File

@ -3,47 +3,46 @@
#include "Geometry.h"
#include "polyset.h"
#include "Polygon2d.h"
#include "colormap.h"
#include "printutils.h"
bool Renderer::getColor(Renderer::ColorMode colormode, Color4f &col) const
{
switch (colormode) {
case COLORMODE_NONE:
return false;
break;
case COLORMODE_MATERIAL:
col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
break;
case COLORMODE_CUTOUT:
col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_BACK_COLOR);
break;
case COLORMODE_HIGHLIGHT:
col.setRgb(255, 81, 81, 128);
break;
case COLORMODE_BACKGROUND:
col.setRgb(180, 180, 180, 128);
break;
case COLORMODE_MATERIAL_EDGES:
col.setRgb(255, 236, 94);
break;
case COLORMODE_CUTOUT_EDGES:
col.setRgb(171, 216, 86);
break;
case COLORMODE_HIGHLIGHT_EDGES:
col.setRgb(255, 171, 86, 128);
break;
case COLORMODE_BACKGROUND_EDGES:
col.setRgb(150, 150, 150, 128);
break;
default:
return false;
break;
if (colormode==COLORMODE_NONE) return false;
if (colormap.count(colormode) > 0) {
col = colormap.at(colormode);
return true;
}
return true;
return false;
}
Renderer::Renderer() : colorscheme(NULL)
{
PRINTD("Renderer() start");
// Setup default colors
// The main colors, MATERIAL and CUTOUT, come from this object's
// colorscheme. Colorschemes don't currently hold information
// for Highlight/Background colors
// but it wouldn't be too hard to make them do so.
// MATERIAL is set by this object's colorscheme
// CUTOUT is set by this object's colorscheme
colormap[COLORMODE_HIGHLIGHT] = Color4f(255, 81, 81, 128);
colormap[COLORMODE_BACKGROUND] = Color4f(180, 180, 180, 128);
// MATERIAL_EDGES is set by this object's colorscheme
// CUTOUT_EDGES is set by this object's colorscheme
colormap[COLORMODE_HIGHLIGHT_EDGES] = Color4f(255, 171, 86, 128);
colormap[COLORMODE_BACKGROUND_EDGES] = Color4f(150, 150, 150, 128);
setColorScheme(ColorMap::inst()->defaultColorScheme());
PRINTD("Renderer() end");
}
void Renderer::setColor(const float color[4], GLint *shaderinfo) const
{
Color4f col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
PRINTD("setColor a");
Color4f col;
getColor(COLORMODE_MATERIAL,col);
float c[4] = {color[0], color[1], color[2], color[3]};
if (c[0] < 0) c[0] = col[0];
if (c[1] < 0) c[1] = col[1];
@ -60,6 +59,7 @@ void Renderer::setColor(const float color[4], GLint *shaderinfo) const
void Renderer::setColor(ColorMode colormode, const float color[4], GLint *shaderinfo) const
{
PRINTD("setColor b");
Color4f basecol;
if (getColor(colormode, basecol)) {
if (colormode == COLORMODE_BACKGROUND) {
@ -80,10 +80,25 @@ void Renderer::setColor(ColorMode colormode, const float color[4], GLint *shader
void Renderer::setColor(ColorMode colormode, GLint *shaderinfo) const
{
PRINTD("setColor c");
float c[4] = {-1,-1,-1,-1};
setColor(colormode, c, shaderinfo);
}
/* fill this->colormap with matching entries from the colorscheme. note
this does not change Highlight or Background colors as they are not
represented in the colorscheme (yet). Also edgecolors are currently the
same for CGAL & OpenCSG */
void Renderer::setColorScheme(const ColorScheme &cs) {
PRINTD("setColorScheme");
colormap[COLORMODE_MATERIAL] = ColorMap::getColor(cs, OPENCSG_FACE_FRONT_COLOR);
colormap[COLORMODE_CUTOUT] = ColorMap::getColor(cs, OPENCSG_FACE_BACK_COLOR);
colormap[COLORMODE_MATERIAL_EDGES] = ColorMap::getColor(cs, CGAL_EDGE_FRONT_COLOR);
colormap[COLORMODE_CUTOUT_EDGES] = ColorMap::getColor(cs, CGAL_EDGE_BACK_COLOR);
colormap[COLORMODE_EMPTY_SPACE] = ColorMap::getColor(cs, BACKGROUND_COLOR);
this->colorscheme = &cs;
}
void Renderer::render_surface(shared_ptr<const Geometry> geom, csgmode_e csgmode, const Transform3d &m, GLint *shaderinfo)
{
shared_ptr<const PolySet> ps;

View File

@ -3,6 +3,7 @@
#include "system-gl.h"
#include "linalg.h"
#include "memory.h"
#include "colormap.h"
#ifdef _MSC_VER // NULL
#include <cstdlib>
@ -11,6 +12,7 @@
class Renderer
{
public:
Renderer();
virtual ~Renderer() {}
virtual void draw(bool showfaces, bool showedges) const = 0;
virtual BoundingBox getBoundingBox() const = 0;
@ -35,14 +37,20 @@ public:
COLORMODE_MATERIAL_EDGES,
COLORMODE_CUTOUT_EDGES,
COLORMODE_HIGHLIGHT_EDGES,
COLORMODE_BACKGROUND_EDGES
COLORMODE_BACKGROUND_EDGES,
COLORMODE_EMPTY_SPACE
};
virtual bool getColor(ColorMode colormode, Color4f &col) const;
virtual void setColor(const float color[4], GLint *shaderinfo = NULL) const;
virtual void setColor(ColorMode colormode, GLint *shaderinfo = NULL) const;
virtual void setColor(ColorMode colormode, const float color[4], GLint *shaderinfo = NULL) const;
virtual void setColorScheme(const ColorScheme &cs);
static void render_surface(shared_ptr<const class Geometry> geom, csgmode_e csgmode, const Transform3d &m, GLint *shaderinfo = NULL);
static void render_edges(shared_ptr<const Geometry> geom, csgmode_e csgmode);
protected:
std::map<ColorMode,Color4f> colormap;
const ColorScheme *colorscheme;
};

View File

@ -1,4 +1,6 @@
#include "rendersettings.h"
#include "colormap.h"
#include "printutils.h"
RenderSettings *RenderSettings::inst(bool erase)
{
@ -16,24 +18,5 @@ RenderSettings::RenderSettings()
far_gl_clip_limit = 100000.0;
img_width = 512;
img_height = 512;
this->colors[BACKGROUND_COLOR] = Color4f(0xff, 0xff, 0xe5);
this->colors[OPENCSG_FACE_FRONT_COLOR] = Color4f(0xf9, 0xd7, 0x2c);
this->colors[OPENCSG_FACE_BACK_COLOR] = Color4f(0x9d, 0xcb, 0x51);
this->colors[CGAL_FACE_FRONT_COLOR] = Color4f(0xf9, 0xd7, 0x2c);
this->colors[CGAL_FACE_BACK_COLOR] = Color4f(0x9d, 0xcb, 0x51);
this->colors[CGAL_FACE_2D_COLOR] = Color4f(0x00, 0xbf, 0x99);
this->colors[CGAL_EDGE_FRONT_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colors[CGAL_EDGE_BACK_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colors[CGAL_EDGE_2D_COLOR] = Color4f(0xff, 0x00, 0x00);
this->colors[CROSSHAIR_COLOR] = Color4f(0x80, 0x00, 0x00);
}
Color4f RenderSettings::color(RenderColor idx)
{
return this->colors[idx];
}
void RenderSettings::setColors(const std::map<RenderColor, Color4f> &colors)
{
this->colors = colors;
colorscheme = "Cornfield";
}

View File

@ -2,33 +2,17 @@
#include <map>
#include "linalg.h"
#include "colormap.h"
class RenderSettings
{
public:
static RenderSettings *inst(bool erase = false);
enum RenderColor {
BACKGROUND_COLOR,
OPENCSG_FACE_FRONT_COLOR,
OPENCSG_FACE_BACK_COLOR,
CGAL_FACE_FRONT_COLOR,
CGAL_FACE_2D_COLOR,
CGAL_FACE_BACK_COLOR,
CGAL_EDGE_FRONT_COLOR,
CGAL_EDGE_BACK_COLOR,
CGAL_EDGE_2D_COLOR,
CROSSHAIR_COLOR
};
void setColors(const std::map<RenderColor, Color4f> &colors);
Color4f color(RenderColor idx);
unsigned int openCSGTermLimit, img_width, img_height;
double far_gl_clip_limit;
std::string colorscheme;
private:
RenderSettings();
~RenderSettings() {}
std::map<RenderColor, Color4f> colors;
};

View File

@ -2,13 +2,14 @@
#include <string>
#include <vector>
#include <utility>
#include <boost/shared_ptr.hpp>
class Assignment : public std::pair<std::string, boost::shared_ptr<class Expression> >
{
public:
Assignment(std::string name) : pair(name, boost::shared_ptr<class Expression>()) {}
Assignment(std::string name, boost::shared_ptr<class Expression> expr) : pair(name, expr) {}
Assignment(std::string name) { first = name; second = boost::shared_ptr<class Expression>(); }
Assignment(std::string name, boost::shared_ptr<class Expression> expr) { first = name; second = expr; }
};
typedef std::vector<Assignment> AssignmentList;

View File

@ -248,6 +248,58 @@ std::string Value::toString() const
return boost::apply_visitor(tostring_visitor(), this->value);
}
class chr_visitor : public boost::static_visitor<std::string> {
public:
template <typename S> std::string operator()(const S &) const
{
return "";
}
std::string operator()(const double &v) const
{
char buf[8];
memset(buf, 0, 8);
if (v > 0) {
const gunichar c = v;
if (g_unichar_validate(c) && (c != 0)) {
g_unichar_to_utf8(c, buf);
}
}
return std::string(buf);
}
std::string operator()(const Value::VectorType &v) const
{
std::stringstream stream;
for (size_t i = 0; i < v.size(); i++) {
stream << v[i].chrString();
}
return stream.str();
}
std::string operator()(const Value::RangeType &v) const
{
const boost::uint32_t steps = v.nbsteps();
if (steps >= 10000) {
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
return "";
}
std::stringstream stream;
Value::RangeType range = v;
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
const Value value(*it);
stream << value.chrString();
}
return stream.str();
}
};
std::string Value::chrString() const
{
return boost::apply_visitor(chr_visitor(), this->value);
}
const Value::VectorType &Value::toVector() const
{
static VectorType empty;

View File

@ -87,6 +87,7 @@ public:
/// return number of steps, max uint32_t value if step is 0
boost::uint32_t nbsteps() const;
friend class chr_visitor;
friend class tostring_visitor;
friend class bracket_visitor;
};
@ -121,6 +122,7 @@ public:
bool getDouble(double &v) const;
bool toBool() const;
std::string toString() const;
std::string chrString() const;
const VectorType &toVector() const;
bool getVec2(double &x, double &y) const;
bool getVec3(double &x, double &y, double &z, double defaultval = 0.0) const;

View File

@ -0,0 +1 @@
import_stl("import.stl");

View File

@ -1,4 +1,4 @@
// These are tests which are not yet possible to express with the
// non-deprecated functionality
rotate_extrude(file = "../../dxf/open-polyline.dxf");
rotate_extrude(file = "../../../dxf/open-polyline.dxf");

View File

@ -1,7 +1,7 @@
module erode(r) {
difference() {
children();
minkowski() {
minkowski(convexity=3) {
difference() {
cube(25, center=true);
children();

Some files were not shown because too many files have changed in this diff Show More