summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/drawsurface.h
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/drawsurface.h')
-rw-r--r--Build/source/utils/asymptote/drawsurface.h320
1 files changed, 264 insertions, 56 deletions
diff --git a/Build/source/utils/asymptote/drawsurface.h b/Build/source/utils/asymptote/drawsurface.h
index 9c7f25342b9..16d369cb545 100644
--- a/Build/source/utils/asymptote/drawsurface.h
+++ b/Build/source/utils/asymptote/drawsurface.h
@@ -12,11 +12,20 @@
#include "arrayop.h"
#include "path3.h"
+namespace run {
+extern double *copyArrayC(const array *a, size_t dim);
+}
+
namespace camp {
+#ifdef HAVE_LIBGL
+void storecolor(GLfloat *colors, int i, const vm::array &pens, int j);
+#endif
+
class drawSurface : public drawElement {
protected:
- Triple controls[16];
+ Triple *controls;
+ Triple vertices[4];
bool straight;
RGBAColour diffuse;
RGBAColour ambient;
@@ -27,47 +36,56 @@ protected:
double PRCshininess;
double granularity;
triple normal;
+ bool invisible;
bool lighton;
+ string name;
- bool invisible;
triple Min,Max;
- static triple c3[16];
- GLfloat *colors;
- bool havecolors;
#ifdef HAVE_LIBGL
- GLfloat c[48];
+ GLfloat *colors;
triple d; // Maximum deviation of surface from a quadrilateral.
triple dperp;
- GLfloat v1[16];
- GLfloat v2[16];
- GLfloat Normal[3];
- bool havenormal;
- bool havetransparency;
#endif
- void storecolor(int i, const vm::array &pens, int j) {
- pen p=vm::read<camp::pen>(pens,j);
- p.torgb();
- colors[i]=p.red();
- colors[i+1]=p.green();
- colors[i+2]=p.blue();
- colors[i+3]=p.opacity();
- }
-
+ static const triple zero;
+
public:
drawSurface(const vm::array& g, bool straight, const vm::array&p,
double opacity, double shininess, double PRCshininess,
- double granularity, triple normal, bool lighton,
- const vm::array &pens) :
+ double granularity, triple normal, const vm::array &pens,
+ bool lighton, const string& name) :
straight(straight), opacity(opacity), shininess(shininess),
PRCshininess(PRCshininess), granularity(granularity), normal(unit(normal)),
- lighton(lighton) {
+ lighton(lighton), name(name) {
string wrongsize=
"Bezier surface patch requires 4x4 array of triples and array of 4 pens";
if(checkArray(&g) != 4 || checkArray(&p) != 4)
reportError(wrongsize);
+ bool havenormal=normal != zero;
+
+ vm::array *g0=vm::read<vm::array*>(g,0);
+ vm::array *g3=vm::read<vm::array*>(g,3);
+ if(checkArray(g0) != 4 || checkArray(g3) != 4)
+ reportError(wrongsize);
+ store(vertices[0],vm::read<triple>(g0,0));
+ store(vertices[1],vm::read<triple>(g0,3));
+ store(vertices[2],vm::read<triple>(g3,0));
+ store(vertices[3],vm::read<triple>(g3,3));
+
+ if(!havenormal || !straight) {
+ size_t k=0;
+ controls=new Triple[16];
+ for(size_t i=0; i < 4; ++i) {
+ vm::array *gi=vm::read<vm::array*>(g,i);
+ if(checkArray(gi) != 4)
+ reportError(wrongsize);
+ for(size_t j=0; j < 4; ++j)
+ store(controls[k++],vm::read<triple>(gi,j));
+ }
+ } else controls=NULL;
+
pen surfacepen=vm::read<camp::pen>(p,0);
invisible=surfacepen.invisible();
@@ -78,72 +96,262 @@ public:
#ifdef HAVE_LIBGL
int size=checkArray(&pens);
- havecolors=size > 0;
- if(havecolors) {
- colors=new GLfloat[16];
+ if(size > 0) {
if(size != 4) reportError(wrongsize);
- storecolor(0,pens,0);
- storecolor(8,pens,1);
- storecolor(12,pens,2);
- storecolor(4,pens,3);
+ colors=new GLfloat[16];
+ storecolor(colors,0,pens,0);
+ storecolor(colors,8,pens,1);
+ storecolor(colors,12,pens,2);
+ storecolor(colors,4,pens,3);
+ } else colors=NULL;
+#endif
+ }
+
+ drawSurface(const vm::array& t, const drawSurface *s) :
+ straight(s->straight), diffuse(s->diffuse), ambient(s->ambient),
+ emissive(s->emissive), specular(s->specular), opacity(s->opacity),
+ shininess(s->shininess), PRCshininess(s->PRCshininess),
+ granularity(s->granularity), invisible(s->invisible),
+ lighton(s->lighton), name(s->name) {
+
+ for(size_t i=0; i < 4; ++i) {
+ const double *c=s->vertices[i];
+ store(vertices[i],run::operator *(t,triple(c[0],c[1],c[2])));
}
+
+ if(s->controls) {
+ controls=new Triple[16];
+ for(size_t i=0; i < 16; ++i) {
+ const double *c=s->controls[i];
+ store(controls[i],run::operator *(t,triple(c[0],c[1],c[2])));
+ }
+ } else controls=NULL;
+
+ normal=run::multshiftless(t,s->normal);
+
+#ifdef HAVE_LIBGL
+ if(s->colors) {
+ colors=new GLfloat[16];
+ for(int i=0; i < 16; ++i)
+ colors[i]=s->colors[i];
+ } else colors=NULL;
#endif
+ }
+
+ bool is3D() {return true;}
+
+ void bounds(bbox3& b);
+
+ void ratio(pair &b, double (*m)(double, double), bool &first);
+
+ virtual ~drawSurface() {
+ if(controls)
+ delete[] controls;
+
+#ifdef HAVE_LIBGL
+ if(colors)
+ delete[] colors;
+#endif
+ }
+
+ bool write(prcfile *out);
+
+ void displacement();
+ void render(GLUnurbs *nurb, double, const triple& Min, const triple& Max,
+ double perspective, bool transparent);
+
+ drawElement *transformed(const vm::array& t);
+};
+
+class drawNurbs : public drawElement {
+protected:
+ size_t udegree,vdegree;
+ size_t nu,nv;
+ Triple *controls;
+ double *weights;
+ double *uknots, *vknots;
+ RGBAColour diffuse;
+ RGBAColour ambient;
+ RGBAColour emissive;
+ RGBAColour specular;
+ double opacity;
+ double shininess;
+ double PRCshininess;
+ double granularity;
+ triple normal;
+ bool invisible;
+ bool lighton;
+ string name;
+
+ triple Min,Max;
+
+#ifdef HAVE_LIBGL
+ GLfloat *colors;
+ GLfloat *Controls;
+ GLfloat *uKnots;
+ GLfloat *vKnots;
+#endif
+
+public:
+ drawNurbs(const vm::array& g, const vm::array* uknot, const vm::array* vknot,
+ const vm::array* weight, const vm::array&p, double opacity,
+ double shininess, double PRCshininess, double granularity,
+ const vm::array &pens, bool lighton, const string& name) :
+ opacity(opacity), shininess(shininess), PRCshininess(PRCshininess),
+ granularity(granularity), lighton(lighton), name(name) {
+ size_t weightsize=checkArray(weight);
+
+ string wrongsize="Inconsistent NURBS data";
+ nu=checkArray(&g);
+
+ if(nu == 0 || (weightsize != 0 && weightsize != nu) || checkArray(&p) != 4)
+ reportError(wrongsize);
+
+ vm::array *g0=vm::read<vm::array*>(g,0);
+ nv=checkArray(g0);
+
+ size_t n=nu*nv;
+ controls=new Triple[n];
size_t k=0;
- for(size_t i=0; i < 4; ++i) {
+ for(size_t i=0; i < nu; ++i) {
vm::array *gi=vm::read<vm::array*>(g,i);
- size_t gisize=checkArray(gi);
- if(gisize != 4)
+ if(checkArray(gi) != nv)
reportError(wrongsize);
- for(size_t j=0; j < 4; ++j) {
- triple v=vm::read<triple>(gi,j);
- controls[k][0]=v.getx();
- controls[k][1]=v.gety();
- controls[k][2]=v.getz();
- ++k;
- }
+ for(size_t j=0; j < nv; ++j)
+ store(controls[k++],vm::read<triple>(gi,j));
}
+
+ if(weightsize > 0) {
+ size_t k=0;
+ weights=new double[n];
+ for(size_t i=0; i < nu; ++i) {
+ vm::array *weighti=vm::read<vm::array*>(weight,i);
+ if(checkArray(weighti) != nv)
+ reportError(wrongsize);
+ for(size_t j=0; j < nv; ++j) {
+ weights[k]=vm::read<double>(weighti,j);
+ ++k;
+ }
+ }
+ } else weights=NULL;
+
+ size_t nuknots=checkArray(uknot);
+ size_t nvknots=checkArray(vknot);
+
+ if(nuknots <= nu+1 || nuknots > 2*nu || nvknots <= nv+1 || nvknots > 2*nv)
+ reportError(wrongsize);
+
+ udegree=nuknots-nu-1;
+ vdegree=nvknots-nv-1;
+
+ uknots=run::copyArrayC(uknot,0);
+ vknots=run::copyArrayC(vknot,0);
+
+ pen surfacepen=vm::read<camp::pen>(p,0);
+ invisible=surfacepen.invisible();
+
+ diffuse=rgba(surfacepen);
+ ambient=rgba(vm::read<camp::pen>(p,1));
+ emissive=rgba(vm::read<camp::pen>(p,2));
+ specular=rgba(vm::read<camp::pen>(p,3));
+#ifdef HAVE_LIBGL
+ uKnots=new GLfloat[nuknots];
+ vKnots=new GLfloat[nvknots];
+ Controls=new GLfloat[(weights ? 4 : 3)*n];
+
+ int size=checkArray(&pens);
+ if(size > 0) {
+ colors=new GLfloat[16];
+ if(size != 4) reportError(wrongsize);
+ storecolor(colors,0,pens,0);
+ storecolor(colors,8,pens,1);
+ storecolor(colors,12,pens,2);
+ storecolor(colors,4,pens,3);
+ } else colors=NULL;
+#endif
}
- drawSurface(const vm::array& t, const drawSurface *s) :
- straight(s->straight), diffuse(s->diffuse), ambient(s->ambient),
+ drawNurbs(const vm::array& t, const drawNurbs *s) :
+ udegree(s->udegree), vdegree(s->vdegree), nu(s->nu), nv(s->nv),
+ diffuse(s->diffuse), ambient(s->ambient),
emissive(s->emissive), specular(s->specular), opacity(s->opacity),
shininess(s->shininess), PRCshininess(s->PRCshininess),
- granularity(s->granularity), lighton(s->lighton),
- invisible(s->invisible), colors(s->colors), havecolors(s->havecolors) {
- for(size_t i=0; i < 16; ++i) {
+ granularity(s->granularity), invisible(s->invisible), lighton(s->lighton),
+ name(s->name) {
+
+ size_t n=nu*nv;
+ controls=new double[n][3];
+
+ for(size_t i=0; i < n; ++i) {
const double *c=s->controls[i];
triple v=run::operator *(t,triple(c[0],c[1],c[2]));
controls[i][0]=v.getx();
controls[i][1]=v.gety();
controls[i][2]=v.getz();
}
- normal=run::multshiftless(t,s->normal);
+
+ if(s->weights) {
+ weights=new double[n];
+ for(size_t i=0; i < n; ++i)
+ weights[i]=s->weights[i];
+ } else weights=NULL;
+
+ size_t nuknots=udegree+nu+1;
+ size_t nvknots=vdegree+nv+1;
+ uknots=new double[nuknots];
+ vknots=new double[nvknots];
+
+ for(size_t i=0; i < nuknots; ++i)
+ uknots[i]=s->uknots[i];
+
+ for(size_t i=0; i < nvknots; ++i)
+ vknots[i]=s->vknots[i];
+
+#ifdef HAVE_LIBGL
+ uKnots=new GLfloat[nuknots];
+ vKnots=new GLfloat[nvknots];
+ Controls=new GLfloat[(weights ? 4 : 3)*n];
+
+ if(s->colors) {
+ colors=new GLfloat[16];
+ for(int i=0; i < 16; ++i)
+ colors[i]=s->colors[i];
+ } else colors=NULL;
+#endif
}
bool is3D() {return true;}
void bounds(bbox3& b);
- void ratio(pair &b, double (*m)(double, double), bool &first);
-
- virtual ~drawSurface() {
- if(havecolors)
- delete[] colors;
+ virtual ~drawNurbs() {
+ delete[] vknots;
+ delete[] uknots;
+ if(weights)
+ delete[] weights;
+ delete[] controls;
+#ifdef HAVE_LIBGL
+ if(colors)
+ delete[] colors;
+ delete[] Controls;
+ delete[] vKnots;
+ delete[] uKnots;
+#endif
}
bool write(prcfile *out);
void displacement();
- void render(GLUnurbs *nurb, double, const triple& Min, const triple& Max,
+ void ratio(pair &b, double (*m)(double, double), bool &first);
+
+ void render(GLUnurbs *nurb, double size2,
+ const triple& Min, const triple& Max,
double perspective, bool transparent);
-
+
drawElement *transformed(const vm::array& t);
};
-double norm(double *a, size_t n);
-double norm(triple *a, size_t n);
-
}
#endif