/*****
* drawpath3.h
*
* Stores a path3 that has been added to a picture.
*****/
#ifndef DRAWPATH3_H
#define DRAWPATH3_H
#include "drawelement.h"
#include "path3.h"
#include "beziercurve.h"
namespace camp {
class drawPath3 : public drawElement {
protected:
const path3 g;
triple center;
bool straight;
prc::RGBAColour diffuse;
prc::RGBAColour emissive;
prc::RGBAColour specular;
double opacity;
double shininess;
double metallic;
double fresnel0;
bool invisible;
Interaction interaction;
triple Min,Max;
bool billboard;
size_t centerIndex;
public:
#ifdef HAVE_GL
BezierCurve R;
#endif
void init() {
billboard=interaction == BILLBOARD;
centerIndex=0;
}
drawPath3(path3 g, triple center, const vm::array& p, double opacity,
double shininess, double metallic, double fresnel0,
Interaction interaction, const string& key="") :
drawElement(key), g(g), center(center),
straight(g.piecewisestraight()), opacity(opacity),
shininess(shininess), metallic(metallic), fresnel0(fresnel0),
interaction(interaction), Min(g.min()), Max(g.max()) {
init();
pen Pen=vm::read<camp::pen>(p,0);
invisible=Pen.invisible();
diffuse=rgba(Pen);
emissive=rgba(vm::read<camp::pen>(p,1));
specular=rgba(vm::read<camp::pen>(p,2));
}
drawPath3(const double* t, const drawPath3 *s) :
drawElement(s->KEY), g(camp::transformed(t,s->g)), straight(s->straight),
diffuse(s->diffuse), emissive(s->emissive), specular(s->specular),
opacity(s->opacity), shininess(s->shininess),
metallic(s->metallic), fresnel0(s->fresnel0),
invisible(s->invisible), interaction(s->interaction),
Min(g.min()), Max(g.max()) {
init();
center=t*s->center;
}
virtual ~drawPath3() {}
bool is3D() {return true;}
void bounds(const double* t, bbox3& B) {
if(t != NULL) {
const path3 tg(camp::transformed(t,g));
B.add(tg.min());
B.add(tg.max());
} else {
B.add(Min);
B.add(Max);
}
}
void ratio(const double* t, pair &b, double (*m)(double, double), double,
bool &first) {
pair z;
if(t != NULL) {
const path3 tg(camp::transformed(t,g));
z=tg.ratio(m);
} else z=g.ratio(m);
if(first) {
b=z;
first=false;
} else b=pair(m(b.getx(),z.getx()),m(b.gety(),z.gety()));
}
void meshinit() {
if(billboard)
centerIndex=centerindex(center);
}
bool write(prcfile *out, unsigned int *, double, groupsmap&);
bool write(abs3Doutfile *out);
void render(double, const triple&, const triple&, double,
bool remesh);
drawElement *transformed(const double* t);
};
class drawNurbsPath3 : public drawElement {
protected:
size_t degree;
size_t n;
triple *controls;
double *weights;
double *knots;
prc::RGBAColour color;
bool invisible;
triple Min,Max;
#ifdef HAVE_LIBGLM
GLfloat *Controls;
GLfloat *Knots;
#endif
public:
drawNurbsPath3(const vm::array& g, const vm::array* knot,
const vm::array* weight, const pen& p, const string& key="") :
drawElement(key), color(rgba(p)), invisible(p.invisible()) {
size_t weightsize=checkArray(weight);
string wrongsize="Inconsistent NURBS data";
n=checkArray(&g);
if(n == 0 || (weightsize != 0 && weightsize != n))
reportError(wrongsize);
controls=new(UseGC) triple[n];
size_t k=0;
for(size_t i=0; i < n; ++i)
controls[k++]=vm::read<triple>(g,i);
if(weightsize > 0) {
size_t k=0;
weights=new(UseGC) double[n];
for(size_t i=0; i < n; ++i)
weights[k++]=vm::read<double>(weight,i);
} else weights=NULL;
size_t nknots=checkArray(knot);
if(nknots <= n+1 || nknots > 2*n)
reportError(wrongsize);
degree=nknots-n-1;
run::copyArrayC(knots,knot,0,NoGC);
#ifdef HAVE_LIBGLM
Controls=NULL;
#endif
}
drawNurbsPath3(const double* t, const drawNurbsPath3 *s) :
drawElement(s->KEY), degree(s->degree), n(s->n), weights(s->weights),
knots(s->knots), color(s->color), invisible(s->invisible) {
controls=new(UseGC) triple[n];
for(unsigned int i=0; i < n; ++i)
controls[i]=t*s->controls[i];
#ifdef HAVE_LIBGLM
Controls=NULL;
#endif
}
bool is3D() {return true;}
void bounds(const double* t, bbox3& b);
virtual ~drawNurbsPath3() {}
bool write(prcfile *out, unsigned int *, double, groupsmap&);
void displacement();
void ratio(const double* t, pair &b, double (*m)(double, double), double fuzz,
bool &first);
void render(double size2, const triple& Min, const triple& Max,
double perspective, bool remesh);
drawElement *transformed(const double* t);
};
// Draw a pixel.
class drawPixel : public drawElement {
triple v;
pen p;
prc::RGBAColour color;
double width;
bool invisible;
triple Min,Max;
public:
#ifdef HAVE_GL
Pixel R;
#endif
drawPixel(const triple& v, const pen& p, double width, const string& key="")
: drawElement(key), v(v), p(p), color(rgba(p)), width(width),
invisible(p.invisible()) {}
void bounds(const double* t, bbox3& B) {
Min=Max=(t != NULL) ? t*v : v;
B.add(Min);
}
void ratio(const double* t, pair &b, double (*m)(double, double), double,
bool &first) {
triple V=(t != NULL) ? t*v : v;
pair z=pair(xratio(V),yratio(V));
if(first) {
b=z;
first=false;
} else b=pair(m(b.getx(),z.getx()),m(b.gety(),z.gety()));
}
void render(double size2, const triple& b, const triple& B,
double perspective, bool remesh);
bool write(prcfile *out, unsigned int *, double, groupsmap&);
bool write(abs3Doutfile *out);
drawElement *transformed(const double* t);
};
}
#endif