CSGTermRenderer refactoring: Added matrix to traversal state

stl_dim
Marius Kintel 2010-08-28 17:34:22 +02:00
parent c868525c67
commit 93f3d4a1b6
23 changed files with 110 additions and 101 deletions

View File

@ -55,7 +55,7 @@ void CSGTermRenderer::applyToChildren(const AbstractNode &node, CSGTermRenderer:
this->stored_term[node.index()] = t1;
}
Response CSGTermRenderer::visit(const State &state, const AbstractNode &node)
Response CSGTermRenderer::visit(State &state, const AbstractNode &node)
{
if (state.isPostfix()) {
applyToChildren(node, UNION);
@ -64,7 +64,7 @@ Response CSGTermRenderer::visit(const State &state, const AbstractNode &node)
return ContinueTraversal;
}
Response CSGTermRenderer::visit(const State &state, const AbstractIntersectionNode &node)
Response CSGTermRenderer::visit(State &state, const AbstractIntersectionNode &node)
{
if (state.isPostfix()) {
applyToChildren(node, INTERSECTION);
@ -73,9 +73,9 @@ Response CSGTermRenderer::visit(const State &state, const AbstractIntersectionNo
return ContinueTraversal;
}
static CSGTerm *render_csg_term_from_ps(double m[20],
QVector<CSGTerm*> *highlights,
QVector<CSGTerm*> *background,
static CSGTerm *render_csg_term_from_ps(const double m[20],
vector<CSGTerm*> *highlights,
vector<CSGTerm*> *background,
PolySet *ps,
const ModuleInstantiation *modinst,
int idx)
@ -90,18 +90,18 @@ static CSGTerm *render_csg_term_from_ps(double m[20],
return t;
}
Response CSGTermRenderer::visit(const State &state, const AbstractPolyNode &node)
Response CSGTermRenderer::visit(State &state, const AbstractPolyNode &node)
{
if (state.isPostfix()) {
PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_OPENCSG);
CSGTerm *t1 = render_csg_term_from_ps(m, this->highlights, this->background, ps, node.modinst, node.index());
CSGTerm *t1 = render_csg_term_from_ps(state.matrix(), this->highlights, this->background, ps, node.modinst, node.index());
this->stored_term[node.index()] = t1;
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTermRenderer::visit(const State &state, const CsgNode &node)
Response CSGTermRenderer::visit(State &state, const CsgNode &node)
{
if (state.isPostfix()) {
CsgOp op;
@ -122,26 +122,28 @@ Response CSGTermRenderer::visit(const State &state, const CsgNode &node)
return ContinueTraversal;
}
Response CSGTermRenderer::visit(const State &state, const TransformNode &node)
Response CSGTermRenderer::visit(State &state, const TransformNode &node)
{
if (state.isPostfix()) {
double x[20];
if (state.isPrefix()) {
double m[20];
for (int i = 0; i < 16; i++)
{
int c_row = i%4;
int m_col = i/4;
x[i] = 0;
for (int j = 0; j < 4; j++)
x[i] += c[c_row + j*4] * m[m_col*4 + j];
m[i] = 0;
for (int j = 0; j < 4; j++) {
m[i] += state.matrix()[c_row + j*4] * node.matrix[m_col*4 + j];
}
}
for (int i = 16; i < 20; i++)
x[i] = m[i] < 0 ? c[i] : m[i];
// FIXME: Apply the x matrix.
// FIXME: Look into how bottom-up vs. top down affects matrix handling
for (int i = 16; i < 20; i++) {
m[i] = node.matrix[i] < 0 ? state.matrix()[i] : node.matrix[i];
}
state.setMatrix(m);
}
if (state.isPostfix()) {
applyToChildren(node, UNION);
addToParent(state, node);
}
@ -149,7 +151,7 @@ Response CSGTermRenderer::visit(const State &state, const TransformNode &node)
}
// FIXME: Find out how to best call into CGAL from this visitor
Response CSGTermRenderer::visit(const State &state, const RenderNode &node)
Response CSGTermRenderer::visit(State &state, const RenderNode &node)
{
PRINT("WARNING: Found render() statement but compiled without CGAL support!");
if (state.isPostfix()) {

View File

@ -19,12 +19,12 @@ public:
CSGTermRenderer() {}
virtual ~CSGTermRenderer() {}
virtual Response visit(const State &state, const AbstractNode &node);
virtual Response visit(const State &state, const AbstractIntersectionNode &node);
virtual Response visit(const State &state, const AbstractPolyNode &node);
virtual Response visit(const State &state, const CsgNode &node);
virtual Response visit(const State &state, const TransformNode &node);
virtual Response visit(const State &state, const RenderNode &node);
virtual Response visit(State &state, const AbstractNode &node);
virtual Response visit(State &state, const AbstractIntersectionNode &node);
virtual Response visit(State &state, const AbstractPolyNode &node);
virtual Response visit(State &state, const CsgNode &node);
virtual Response visit(State &state, const TransformNode &node);
virtual Response visit(State &state, const RenderNode &node);
private:
enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI};

View File

@ -59,7 +59,7 @@ public:
convexity = 1;
}
virtual ~CgaladvNode() { }
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -15,7 +15,7 @@ class CsgNode : public AbstractNode
public:
csg_type_e type;
CsgNode(const ModuleInstantiation *mi, csg_type_e type) : AbstractNode(mi), type(type) { }
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -26,7 +26,7 @@
#include "csgterm.h"
#include "polyset.h"
CSGTerm::CSGTerm(PolySet *polyset, double m[20], QString label)
CSGTerm::CSGTerm(PolySet *polyset, const double m[20], QString label)
{
this->type = TYPE_PRIMITIVE;
this->polyset = polyset;

View File

@ -22,7 +22,7 @@ public:
double m[20];
int refcounter;
CSGTerm(PolySet *polyset, double m[20], QString label);
CSGTerm(PolySet *polyset, const double m[20], QString label);
CSGTerm(type_e type, CSGTerm *left, CSGTerm *right);
CSGTerm *normalize();

View File

@ -13,7 +13,7 @@ public:
origin_x = origin_y = scale = 0;
center = has_twist = false;
}
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -12,7 +12,7 @@ public:
fn = fs = fa = 0;
origin_x = origin_y = scale = 0;
}
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -14,7 +14,7 @@ class ImportNode : public AbstractPolyNode
{
public:
ImportNode(const ModuleInstantiation *mi, import_type_e type) : AbstractPolyNode(mi), type(type) { }
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -49,17 +49,17 @@ AbstractNode::~AbstractNode()
delete v;
}
Response AbstractNode::accept(const class State &state, Visitor &visitor) const
Response AbstractNode::accept(class State &state, Visitor &visitor) const
{
return visitor.visit(state, *this);
}
Response AbstractIntersectionNode::accept(const class State &state, Visitor &visitor) const
Response AbstractIntersectionNode::accept(class State &state, Visitor &visitor) const
{
return visitor.visit(state, *this);
}
Response AbstractPolyNode::accept(const class State &state, Visitor &visitor) const
Response AbstractPolyNode::accept(class State &state, Visitor &visitor) const
{
return visitor.visit(state, *this);
}

View File

@ -27,7 +27,7 @@ class AbstractNode
public:
AbstractNode(const class ModuleInstantiation *mi);
virtual ~AbstractNode();
virtual Response accept(const class State &state, class Visitor &visitor) const;
virtual Response accept(class State &state, class Visitor &visitor) const;
virtual std::string toString() const;
// FIXME: Make return value a reference
@ -62,7 +62,7 @@ class AbstractIntersectionNode : public AbstractNode
public:
AbstractIntersectionNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
virtual ~AbstractIntersectionNode() { };
virtual Response accept(const class State &state, class Visitor &visitor) const;
virtual Response accept(class State &state, class Visitor &visitor) const;
virtual std::string toString() const;
};
@ -71,7 +71,7 @@ class AbstractPolyNode : public AbstractNode
public:
AbstractPolyNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
virtual ~AbstractPolyNode() { };
virtual Response accept(const class State &state, class Visitor &visitor) const;
virtual Response accept(class State &state, class Visitor &visitor) const;
enum render_mode_e {
RENDER_CGAL,

View File

@ -84,7 +84,7 @@ string NodeDumper::dumpChildren(const AbstractNode &node)
Called for each node in the tree.
Will abort traversal if we're cached
*/
Response NodeDumper::visit(const State &state, const AbstractNode &node)
Response NodeDumper::visit(State &state, const AbstractNode &node)
{
if (isCached(node)) return PruneTraversal;

View File

@ -20,7 +20,7 @@ public:
cache(cache), idprefix(idPrefix), root(NULL) { }
virtual ~NodeDumper() {}
virtual Response visit(const State &state, const AbstractNode &node);
virtual Response visit(State &state, const AbstractNode &node);
private:
void handleVisitedChildren(const State &state, const AbstractNode &node);

View File

@ -58,7 +58,7 @@ class PrimitiveNode : public AbstractPolyNode
{
public:
PrimitiveNode(const ModuleInstantiation *mi, primitive_type_e type) : AbstractPolyNode(mi), type(type) { }
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -10,7 +10,7 @@ public:
ProjectionNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
cut_mode = false;
}
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -8,7 +8,7 @@ class RenderNode : public AbstractNode
{
public:
RenderNode(const ModuleInstantiation *mi) : AbstractNode(mi), convexity(1) { }
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -5,24 +5,31 @@ class State
{
public:
State(const class AbstractNode *parent)
: parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) { }
: parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) {
for (int i=0;i<20;i++) this->m[i] = 0.0;
}
virtual ~State() {}
void setPrefix(bool on) { this->isprefix = on; }
void setPostfix(bool on) { this->ispostfix = on; }
void setNumChildren(unsigned int numc) { this->numchildren = numc; }
void setParent(const AbstractNode *parent) { this->parentnode = parent; }
void setMatrix(const double m[20]) { memcpy(this->m, m, sizeof(m)); }
bool isPrefix() const { return this->isprefix; }
bool isPostfix() const { return this->ispostfix; }
unsigned int numChildren() const { return this->numchildren; }
const AbstractNode *parent() const { return this->parentnode; }
const double *matrix() const { return this->m; }
private:
const AbstractNode * parentnode;
bool isprefix;
bool ispostfix;
unsigned int numchildren;
// Transformation matrix incl. color. FIXME: Generalize such state variables?
double m[20];
};
#endif

View File

@ -47,7 +47,7 @@ class SurfaceNode : public AbstractPolyNode
{
public:
SurfaceNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) { }
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;

View File

@ -57,9 +57,9 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
TransformNode *node = new TransformNode(inst);
for (int i = 0; i < 16; i++)
node->m[i] = i % 5 == 0 ? 1.0 : 0.0;
node->matrix[i] = i % 5 == 0 ? 1.0 : 0.0;
for (int i = 16; i < 20; i++)
node->m[i] = -1;
node->matrix[i] = -1;
QVector<QString> argnames;
QVector<Expression*> argexpr;
@ -89,12 +89,12 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
if (type == SCALE)
{
Value v = c.lookup_variable("v");
v.getnum(node->m[0]);
v.getnum(node->m[5]);
v.getnum(node->m[10]);
v.getv3(node->m[0], node->m[5], node->m[10]);
if (node->m[10] <= 0)
node->m[10] = 1;
v.getnum(node->matrix[0]);
v.getnum(node->matrix[5]);
v.getnum(node->matrix[10]);
v.getv3(node->matrix[0], node->matrix[5], node->matrix[10]);
if (node->matrix[10] <= 0)
node->matrix[10] = 1;
}
if (type == ROTATE)
{
@ -128,10 +128,10 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
{
m[x+y*4] = 0;
for (int i = 0; i < 4; i++)
m[x+y*4] += node->m[i+y*4] * mr[x+i*4];
m[x+y*4] += node->matrix[i+y*4] * mr[x+i*4];
}
for (int i = 0; i < 16; i++)
node->m[i] = m[i];
node->matrix[i] = m[i];
}
}
else
@ -153,17 +153,17 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
double c = cos(a*M_PI/180.0);
double s = sin(a*M_PI/180.0);
node->m[ 0] = x*x*(1-c)+c;
node->m[ 1] = y*x*(1-c)+z*s;
node->m[ 2] = z*x*(1-c)-y*s;
node->matrix[ 0] = x*x*(1-c)+c;
node->matrix[ 1] = y*x*(1-c)+z*s;
node->matrix[ 2] = z*x*(1-c)-y*s;
node->m[ 4] = x*y*(1-c)-z*s;
node->m[ 5] = y*y*(1-c)+c;
node->m[ 6] = z*y*(1-c)+x*s;
node->matrix[ 4] = x*y*(1-c)-z*s;
node->matrix[ 5] = y*y*(1-c)+c;
node->matrix[ 6] = z*y*(1-c)+x*s;
node->m[ 8] = x*z*(1-c)+y*s;
node->m[ 9] = y*z*(1-c)-x*s;
node->m[10] = z*z*(1-c)+c;
node->matrix[ 8] = x*z*(1-c)+y*s;
node->matrix[ 9] = y*z*(1-c)-x*s;
node->matrix[10] = z*z*(1-c)+c;
}
}
}
@ -181,23 +181,23 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
if (x != 0.0 || y != 0.0 || z != 0.0)
{
node->m[ 0] = 1-2*x*x;
node->m[ 1] = -2*y*x;
node->m[ 2] = -2*z*x;
node->matrix[ 0] = 1-2*x*x;
node->matrix[ 1] = -2*y*x;
node->matrix[ 2] = -2*z*x;
node->m[ 4] = -2*x*y;
node->m[ 5] = 1-2*y*y;
node->m[ 6] = -2*z*y;
node->matrix[ 4] = -2*x*y;
node->matrix[ 5] = 1-2*y*y;
node->matrix[ 6] = -2*z*y;
node->m[ 8] = -2*x*z;
node->m[ 9] = -2*y*z;
node->m[10] = 1-2*z*z;
node->matrix[ 8] = -2*x*z;
node->matrix[ 9] = -2*y*z;
node->matrix[10] = 1-2*z*z;
}
}
if (type == TRANSLATE)
{
Value v = c.lookup_variable("v");
v.getv3(node->m[12], node->m[13], node->m[14]);
v.getv3(node->matrix[12], node->matrix[13], node->matrix[14]);
}
if (type == MULTMATRIX)
{
@ -206,7 +206,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
for (int i = 0; i < 16; i++) {
int x = i / 4, y = i % 4;
if (y < v.vec.size() && v.vec[y]->type == Value::VECTOR && x < v.vec[y]->vec.size())
v.vec[y]->vec[x]->getnum(node->m[i]);
v.vec[y]->vec[x]->getnum(node->matrix[i]);
}
}
}
@ -215,7 +215,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
Value v = c.lookup_variable("c");
if (v.type == Value::VECTOR) {
for (int i = 0; i < 4; i++)
node->m[16+i] = i < v.vec.size() ? v.vec[i]->num : 1.0;
node->matrix[16+i] = i < v.vec.size() ? v.vec[i]->num : 1.0;
}
}
@ -232,8 +232,8 @@ std::string TransformNode::toString() const
{
std::stringstream stream;
if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) {
stream << "color([" << m[16] << ", " << m[17] << ", " << m[18] << ", " << m[19] << "])";
if (this->matrix[16] >= 0 || this->matrix[17] >= 0 || this->matrix[18] >= 0 || this->matrix[19] >= 0) {
stream << "color([" << this->matrix[16] << ", " << this->matrix[17] << ", " << this->matrix[18] << ", " << this->matrix[19] << "])";
}
else {
stream << "multmatrix([";
@ -241,7 +241,7 @@ std::string TransformNode::toString() const
stream << "[";
for (int i=0;i<4;i++) {
// FIXME: The 0 test is to avoid a leading minus before a single 0 (cosmetics)
stream << ((m[i*4+j]==0)?0:m[i*4+j]);
stream << ((this->matrix[i*4+j]==0)?0:this->matrix[i*4+j]);
if (i != 3) stream << ", ";
}
stream << "]";

View File

@ -8,12 +8,12 @@ class TransformNode : public AbstractNode
{
public:
TransformNode(const ModuleInstantiation *mi) : AbstractNode(mi) { }
virtual Response accept(const class State &state, Visitor &visitor) const {
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;
double m[20];
double matrix[20];
};
#endif

View File

@ -9,41 +9,41 @@ public:
Visitor() {}
virtual ~Visitor() {}
virtual Response visit(const class State &state, const class AbstractNode &node) = 0;
virtual Response visit(const class State &state, const class AbstractIntersectionNode &node) {
virtual Response visit(class State &state, const class AbstractNode &node) = 0;
virtual Response visit(class State &state, const class AbstractIntersectionNode &node) {
return visit(state, (const class AbstractNode &)node);
}
virtual Response visit(const class State &state, const class AbstractPolyNode &node) {
virtual Response visit(class State &state, const class AbstractPolyNode &node) {
return visit(state, (const class AbstractNode &)node);
}
virtual Response visit(const class State &state, const class CgaladvNode &node) {
virtual Response visit(class State &state, const class CgaladvNode &node) {
return visit(state, (const class AbstractNode &)node);
}
virtual Response visit(const class State &state, const class CsgNode &node) {
virtual Response visit(class State &state, const class CsgNode &node) {
return visit(state, (const class AbstractNode &)node);
}
virtual Response visit(const class State &state, const class DxfLinearExtrudeNode &node) {
virtual Response visit(class State &state, const class DxfLinearExtrudeNode &node) {
return visit(state, (const class AbstractPolyNode &)node);
}
virtual Response visit(const class State &state, const class DxfRotateExtrudeNode &node) {
virtual Response visit(class State &state, const class DxfRotateExtrudeNode &node) {
return visit(state, (const class AbstractPolyNode &)node);
}
virtual Response visit(const class State &state, const class ImportNode &node) {
virtual Response visit(class State &state, const class ImportNode &node) {
return visit(state, (const class AbstractPolyNode &)node);
}
virtual Response visit(const class State &state, const class PrimitiveNode &node) {
virtual Response visit(class State &state, const class PrimitiveNode &node) {
return visit(state, (const class AbstractPolyNode &)node);
}
virtual Response visit(const class State &state, const class ProjectionNode &node) {
virtual Response visit(class State &state, const class ProjectionNode &node) {
return visit(state, (const class AbstractPolyNode &)node);
}
virtual Response visit(const class State &state, const class RenderNode &node) {
virtual Response visit(class State &state, const class RenderNode &node) {
return visit(state, (const class AbstractNode &)node);
}
virtual Response visit(const class State &state, const class SurfaceNode &node) {
virtual Response visit(class State &state, const class SurfaceNode &node) {
return visit(state, (const class AbstractPolyNode &)node);
}
virtual Response visit(const class State &state, const class TransformNode &node) {
virtual Response visit(class State &state, const class TransformNode &node) {
return visit(state, (const class AbstractNode &)node);
}
// Add visit() methods for new visitable subtypes of AbstractNode here

View File

@ -23,7 +23,7 @@
*
*/
#include "CSGTextRenderer.h"
#include "CSGTermRenderer.h"
#include "CSGTextCache.h"
#include "openscad.h"
#include "node.h"
@ -62,10 +62,10 @@ void handle_dep(QString filename)
}
}
void csgTree(CSGTextCache &cache, const AbstractNode &root)
void csgTree(Tree &tree)
{
CSGTextRenderer renderer(cache);
Traverser render(renderer, root, Traverser::PRE_AND_POSTFIX);
CSGTermRenderer renderer;
Traverser render(renderer, *tree.root(), Traverser::PRE_AND_POSTFIX);
render.execute();
}
@ -157,7 +157,7 @@ int main(int argc, char **argv)
Tree tree;
tree.setRoot(root_node);
csgTree(tree);
destroy_builtin_functions();

View File

@ -69,7 +69,7 @@ HEADERS += ../src/builtin.h \
../src/myqhash.h \
../src/CSGTermRenderer.h
SOURCES += csgtexttest.cc \
SOURCES += csgtermtest.cc \
../src/export.cc \
../src/value.cc \
../src/expr.cc \