diff options
Diffstat (limited to 'Build/source/utils/asymptote/drawsurface.cc')
-rw-r--r-- | Build/source/utils/asymptote/drawsurface.cc | 1008 |
1 files changed, 1008 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/drawsurface.cc b/Build/source/utils/asymptote/drawsurface.cc new file mode 100644 index 00000000000..b491f20b0d5 --- /dev/null +++ b/Build/source/utils/asymptote/drawsurface.cc @@ -0,0 +1,1008 @@ +/***** + * drawsurface.cc + * + * Stores a surface that has been added to a picture. + *****/ + +#include "drawsurface.h" +#include "drawpath3.h" +#include "arrayop.h" + +#include <iostream> +#include <iomanip> +#include <fstream> + +#ifdef HAVE_LIBGLM +#include <glm/glm.hpp> +#include <glm/gtc/matrix_transform.hpp> +#include <glm/gtc/type_ptr.hpp> +#endif + +using namespace prc; +#include "material.h" + +namespace camp { + +mem::vector<triple> drawElement::center; +size_t drawElement::centerIndex=0; +triple drawElement::lastcenter=0; +size_t drawElement::lastcenterIndex=0; + +const triple drawElement::zero; + +using vm::array; +using settings::getSetting; + +#ifdef HAVE_LIBGLM + +void storecolor(GLfloat *colors, 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(); +} + +void storecolor(GLfloat *colors, int i, const RGBAColour& p) +{ + colors[i]=p.R; + colors[i+1]=p.G; + colors[i+2]=p.B; + colors[i+3]=p.A; +} + +void setcolors(bool colors, + const RGBAColour& diffuse, + const RGBAColour& emissive, + const RGBAColour& specular, double shininess, + double metallic, double fresnel0, jsfile *out) +{ + Material m=Material(glm::vec4(diffuse.R,diffuse.G,diffuse.B,diffuse.A), + glm::vec4(emissive.R,emissive.G,emissive.B,emissive.A), + glm::vec4(specular.R,specular.G,specular.B,specular.A), + shininess,metallic,fresnel0); + + MaterialMap::iterator p=materialMap.find(m); + if(p != materialMap.end()) materialIndex=p->second; + else { + materialIndex=material.size(); + if(materialIndex >= nmaterials) + nmaterials=min(Maxmaterials,2*nmaterials); + material.push_back(m); + materialMap[m]=materialIndex; + if(out) + out->addMaterial(materialIndex); + } +} + +#endif + +void drawBezierPatch::bounds(const double* t, bbox3& b) +{ + double x,y,z; + double X,Y,Z; + + if(straight) { + triple Vertices[4]; + if(t == NULL) { + Vertices[0]=controls[0]; + Vertices[1]=controls[3]; + Vertices[2]=controls[12]; + Vertices[3]=controls[15]; + } else { + Vertices[0]=t*controls[0]; + Vertices[1]=t*controls[3]; + Vertices[2]=t*controls[12]; + Vertices[3]=t*controls[15]; + } + + boundstriples(x,y,z,X,Y,Z,4,Vertices); + } else { + double cx[16]; + double cy[16]; + double cz[16]; + + if(t == NULL) { + for(unsigned int i=0; i < 16; ++i) { + triple v=controls[i]; + cx[i]=v.getx(); + cy[i]=v.gety(); + cz[i]=v.getz(); + } + } else { + for(unsigned int i=0; i < 16; ++i) { + triple v=t*controls[i]; + cx[i]=v.getx(); + cy[i]=v.gety(); + cz[i]=v.getz(); + } + } + + double c0=cx[0]; + double fuzz=Fuzz*run::norm(cx,16); + x=bound(cx,min,b.empty ? c0 : min(c0,b.left),fuzz,maxdepth); + X=bound(cx,max,b.empty ? c0 : max(c0,b.right),fuzz,maxdepth); + + c0=cy[0]; + fuzz=Fuzz*run::norm(cy,16); + y=bound(cy,min,b.empty ? c0 : min(c0,b.bottom),fuzz,maxdepth); + Y=bound(cy,max,b.empty ? c0 : max(c0,b.top),fuzz,maxdepth); + + c0=cz[0]; + fuzz=Fuzz*run::norm(cz,16); + z=bound(cz,min,b.empty ? c0 : min(c0,b.near),fuzz,maxdepth); + Z=bound(cz,max,b.empty ? c0 : max(c0,b.far),fuzz,maxdepth); + } + + b.add(x,y,z); + b.add(X,Y,Z); + + if(t == NULL) { + Min=triple(x,y,z); + Max=triple(X,Y,Z); + } +} + +void drawBezierPatch::ratio(const double* t, pair &b, double (*m)(double, double), + double fuzz, bool &first) +{ + triple buf[16]; + triple* Controls; + if(straight) { + if(t == NULL) Controls=controls; + else { + Controls=buf; + Controls[0]=t*controls[0]; + Controls[3]=t*controls[3]; + Controls[12]=t*controls[12]; + Controls[15]=t*controls[15]; + } + + triple v=Controls[0]; + double x=xratio(v); + double y=yratio(v); + if(first) { + first=false; + b=pair(x,y); + } else { + x=m(b.getx(),x); + y=m(b.gety(),y); + } + v=Controls[3]; + x=m(x,xratio(v)); + y=m(y,yratio(v)); + v=Controls[12]; + x=m(x,xratio(v)); + y=m(y,yratio(v)); + v=Controls[15]; + x=m(x,xratio(v)); + y=m(y,yratio(v)); + b=pair(x,y); + } else { + if(t == NULL) Controls=controls; + else { + Controls=buf; + for(unsigned int i=0; i < 16; ++i) + Controls[i]=t*controls[i]; + } + + if(first) { + triple v=Controls[0]; + b=pair(xratio(v),yratio(v)); + first=false; + } + + b=pair(bound(Controls,m,xratio,b.getx(),fuzz,maxdepth), + bound(Controls,m,yratio,b.gety(),fuzz,maxdepth)); + } +} + +bool drawBezierPatch::write(prcfile *out, unsigned int *, double, groupsmap&) +{ + if(invisible || primitive) + return true; + + RGBAColour Black(0.0,0.0,0.0,diffuse.A); + PRCmaterial m(Black,diffuse,emissive,specular,opacity,shininess); + + if(straight) { + triple vertices[]={controls[0],controls[12],controls[3],controls[15]}; + if(colors) { + prc::RGBAColour Colors[]={colors[0],colors[1],colors[3],colors[2]}; + out->addQuad(vertices,Colors); + } else + out->addRectangle(vertices,m); + } else + out->addPatch(controls,m); + + return true; +} + +bool drawBezierPatch::write(jsfile *out) +{ +#ifdef HAVE_LIBGLM + if(invisible || primitive) + return true; + + if(billboard) { + meshinit(); + drawElement::centerIndex=centerIndex; + } else drawElement::centerIndex=0; + + setcolors(colors,diffuse,emissive,specular,shininess,metallic,fresnel0,out); + + out->precision(digits); + if(straight) { + triple Controls[]={controls[0],controls[12],controls[15],controls[3]}; + out->addPatch(Controls,4,Min,Max,colors,4); + } else + out->addPatch(controls,16,Min,Max,colors,4); + out->precision(getSetting<Int>("digits")); + +#endif + return true; +} + +void drawBezierPatch::render(double size2, const triple& b, const triple& B, + double perspective, bool remesh) +{ +#ifdef HAVE_GL + if(invisible) return; + transparent=colors ? colors[0].A+colors[1].A+colors[2].A+colors[3].A < 4.0 : + diffuse.A < 1.0; + + setcolors(colors,diffuse,emissive,specular,shininess,metallic,fresnel0); + + if(transparent) + setMaterial(transparentData,drawTransparent); + else { + if(colors) + setMaterial(colorData,drawColor); + else + setMaterial(materialData,drawMaterial); + } + + bool offscreen; + if(billboard) { + drawElement::centerIndex=centerIndex; + BB.init(center); + offscreen=bbox2(Min,Max,BB).offscreen(); + } else + offscreen=bbox2(Min,Max).offscreen(); + + if(offscreen) { // Fully offscreen + S.Onscreen=false; + S.data.clear(); + S.transparent=transparent; + S.color=colors; + S.notRendered(); + return; + } + + triple *Controls; + triple Controls0[16]; + if(billboard) { + Controls=Controls0; + for(size_t i=0; i < 16; i++) { + Controls[i]=BB.transform(controls[i]); + } + } else { + Controls=controls; + if(!remesh && S.Onscreen) { // Fully onscreen; no need to re-render + S.append(); + return; + } + } + + double s=perspective ? Min.getz()*perspective : 1.0; // Move to glrender + + const pair size3(s*(B.getx()-b.getx()),s*(B.gety()-b.gety())); + + if(gl::outlinemode) { + setMaterial(material1Data,drawMaterial); + triple edge0[]={Controls[0],Controls[4],Controls[8],Controls[12]}; + C.queue(edge0,straight,size3.length()/size2); + triple edge1[]={Controls[12],Controls[13],Controls[14],Controls[15]}; + C.queue(edge1,straight,size3.length()/size2); + triple edge2[]={Controls[15],Controls[11],Controls[7],Controls[3]}; + C.queue(edge2,straight,size3.length()/size2); + triple edge3[]={Controls[3],Controls[2],Controls[1],Controls[0]}; + C.queue(edge3,straight,size3.length()/size2); + } else { + GLfloat c[16]; + if(colors) + for(size_t i=0; i < 4; ++i) + storecolor(c,4*i,colors[i]); + + S.queue(Controls,straight,size3.length()/size2,transparent, + colors ? c : NULL); + } +#endif +} + +drawElement *drawBezierPatch::transformed(const double* t) +{ + return new drawBezierPatch(t,this); +} + +void drawBezierTriangle::bounds(const double* t, bbox3& b) +{ + double x,y,z; + double X,Y,Z; + + if(straight) { + triple Vertices[3]; + if(t == NULL) { + Vertices[0]=controls[0]; + Vertices[1]=controls[6]; + Vertices[2]=controls[9]; + } else { + Vertices[0]=t*controls[0]; + Vertices[1]=t*controls[6]; + Vertices[2]=t*controls[9]; + } + + boundstriples(x,y,z,X,Y,Z,3,Vertices); + } else { + double cx[10]; + double cy[10]; + double cz[10]; + + if(t == NULL) { + for(unsigned int i=0; i < 10; ++i) { + triple v=controls[i]; + cx[i]=v.getx(); + cy[i]=v.gety(); + cz[i]=v.getz(); + } + } else { + for(unsigned int i=0; i < 10; ++i) { + triple v=t*controls[i]; + cx[i]=v.getx(); + cy[i]=v.gety(); + cz[i]=v.getz(); + } + } + + double c0=cx[0]; + double fuzz=Fuzz*run::norm(cx,10); + x=boundtri(cx,min,b.empty ? c0 : min(c0,b.left),fuzz,maxdepth); + X=boundtri(cx,max,b.empty ? c0 : max(c0,b.right),fuzz,maxdepth); + + c0=cy[0]; + fuzz=Fuzz*run::norm(cy,10); + y=boundtri(cy,min,b.empty ? c0 : min(c0,b.bottom),fuzz,maxdepth); + Y=boundtri(cy,max,b.empty ? c0 : max(c0,b.top),fuzz,maxdepth); + + c0=cz[0]; + fuzz=Fuzz*run::norm(cz,10); + z=boundtri(cz,min,b.empty ? c0 : min(c0,b.near),fuzz,maxdepth); + Z=boundtri(cz,max,b.empty ? c0 : max(c0,b.far),fuzz,maxdepth); + } + + b.add(x,y,z); + b.add(X,Y,Z); + + if(t == NULL) { + Min=triple(x,y,z); + Max=triple(X,Y,Z); + } +} + +void drawBezierTriangle::ratio(const double* t, pair &b, + double (*m)(double, double), double fuzz, + bool &first) +{ + triple buf[10]; + triple* Controls; + if(straight) { + if(t == NULL) Controls=controls; + else { + Controls=buf; + Controls[0]=t*controls[0]; + Controls[6]=t*controls[6]; + Controls[9]=t*controls[9]; + } + + triple v=Controls[0]; + double x=xratio(v); + double y=yratio(v); + if(first) { + first=false; + b=pair(x,y); + } else { + x=m(b.getx(),x); + y=m(b.gety(),y); + } + v=Controls[6]; + x=m(x,xratio(v)); + y=m(y,yratio(v)); + v=Controls[9]; + x=m(x,xratio(v)); + y=m(y,yratio(v)); + b=pair(x,y); + } else { + if(t == NULL) Controls=controls; + else { + Controls=buf; + for(unsigned int i=0; i < 10; ++i) + Controls[i]=t*controls[i]; + } + + if(first) { + triple v=Controls[0]; + b=pair(xratio(v),yratio(v)); + first=false; + } + + b=pair(boundtri(Controls,m,xratio,b.getx(),fuzz,maxdepth), + boundtri(Controls,m,yratio,b.gety(),fuzz,maxdepth)); + } +} + +bool drawBezierTriangle::write(prcfile *out, unsigned int *, double, + groupsmap&) +{ + if(invisible || primitive) + return true; + + RGBAColour Black(0.0,0.0,0.0,diffuse.A); + PRCmaterial m(Black,diffuse,emissive,specular,opacity,shininess); + + static const double third=1.0/3.0; + static const double third2=2.0/3.0; + triple Controls[]={controls[0],controls[0],controls[0],controls[0], + controls[1],third2*controls[1]+third*controls[2], + third*controls[1]+third2*controls[2], + controls[2],controls[3], + third*controls[3]+third2*controls[4], + third2*controls[4]+third*controls[5], + controls[5],controls[6],controls[7], + controls[8],controls[9]}; + out->addPatch(Controls,m); + + return true; +} + +bool drawBezierTriangle::write(jsfile *out) +{ +#ifdef HAVE_LIBGLM + if(invisible || primitive) + return true; + + if(billboard) { + meshinit(); + drawElement::centerIndex=centerIndex; + } else drawElement::centerIndex=0; + + setcolors(colors,diffuse,emissive,specular,shininess,metallic,fresnel0,out); + + out->precision(digits); + if(straight) { + triple Controls[]={controls[0],controls[6],controls[9]}; + out->addPatch(Controls,3,Min,Max,colors,3); + } else + out->addPatch(controls,10,Min,Max,colors,3); + out->precision(getSetting<Int>("digits")); + +#endif + return true; +} + +void drawBezierTriangle::render(double size2, const triple& b, const triple& B, + double perspective, bool remesh) +{ +#ifdef HAVE_GL + if(invisible) return; + transparent=colors ? colors[0].A+colors[1].A+colors[2].A < 3.0 : + diffuse.A < 1.0; + + setcolors(colors,diffuse,emissive,specular,shininess,metallic,fresnel0); + + if(transparent) + setMaterial(transparentData,drawTransparent); + else { + if(colors) + setMaterial(colorData,drawColor); + else + setMaterial(materialData,drawMaterial); + } + + bool offscreen; + if(billboard) { + drawElement::centerIndex=centerIndex; + BB.init(center); + offscreen=bbox2(Min,Max,BB).offscreen(); + } else + offscreen=bbox2(Min,Max).offscreen(); + + if(offscreen) { // Fully offscreen + S.Onscreen=false; + S.data.clear(); + S.transparent=transparent; + S.color=colors; + S.notRendered(); + return; + } + + triple *Controls; + triple Controls0[10]; + if(billboard) { + Controls=Controls0; + for(size_t i=0; i < 10; i++) { + Controls[i]=BB.transform(controls[i]); + } + } else { + Controls=controls; + if(!remesh && S.Onscreen) { // Fully onscreen; no need to re-render + S.append(); + return; + } + } + + double s=perspective ? Min.getz()*perspective : 1.0; // Move to glrender + + const pair size3(s*(B.getx()-b.getx()),s*(B.gety()-b.gety())); + + if(gl::outlinemode) { + setMaterial(material1Data,drawMaterial); + triple edge0[]={Controls[0],Controls[1],Controls[3],Controls[6]}; + C.queue(edge0,straight,size3.length()/size2); + triple edge1[]={Controls[6],Controls[7],Controls[8],Controls[9]}; + C.queue(edge1,straight,size3.length()/size2); + triple edge2[]={Controls[9],Controls[5],Controls[2],Controls[0]}; + C.queue(edge2,straight,size3.length()/size2); + } else { + GLfloat c[12]; + if(colors) + for(size_t i=0; i < 3; ++i) + storecolor(c,4*i,colors[i]); + + S.queue(Controls,straight,size3.length()/size2,transparent, + colors ? c : NULL); + } +#endif +} + +drawElement *drawBezierTriangle::transformed(const double* t) +{ + return new drawBezierTriangle(t,this); +} + +bool drawNurbs::write(prcfile *out, unsigned int *, double, groupsmap&) +{ + if(invisible) + return true; + + RGBAColour Black(0.0,0.0,0.0,diffuse.A); + PRCmaterial m(Black,diffuse,emissive,specular,opacity,shininess); + out->addSurface(udegree,vdegree,nu,nv,controls,uknots,vknots,m,weights); + + return true; +} + +// Approximate bounds by bounding box of control polyhedron. +void drawNurbs::bounds(const double* t, bbox3& b) +{ + double x,y,z; + double X,Y,Z; + + const size_t n=nu*nv; + triple* Controls; + if(t == NULL) Controls=controls; + else { + Controls=new triple[n]; + for(size_t i=0; i < n; i++) + Controls[i]=t*controls[i]; + } + + boundstriples(x,y,z,X,Y,Z,n,Controls); + + b.add(x,y,z); + b.add(X,Y,Z); + + if(t == NULL) { + Min=triple(x,y,z); + Max=triple(X,Y,Z); + } else delete[] Controls; +} + +drawElement *drawNurbs::transformed(const double* t) +{ + return new drawNurbs(t,this); +} + +void drawNurbs::ratio(const double *t, pair &b, double (*m)(double, double), + double, bool &first) +{ + const size_t n=nu*nv; + + triple* Controls; + if(t == NULL) Controls=controls; + else { + Controls=new triple[n]; + for(unsigned int i=0; i < n; ++i) + Controls[i]=t*controls[i]; + } + + if(first) { + first=false; + triple v=Controls[0]; + b=pair(xratio(v),yratio(v)); + } + + double x=b.getx(); + double y=b.gety(); + for(size_t i=0; i < n; ++i) { + triple v=Controls[i]; + x=m(x,xratio(v)); + y=m(y,yratio(v)); + } + b=pair(x,y); + + if(t != NULL) + delete[] Controls; +} + + +void drawNurbs::displacement() +{ +#ifdef HAVE_GL + size_t n=nu*nv; + size_t nuknots=udegree+nu+1; + size_t nvknots=vdegree+nv+1; + + if(Controls == NULL) { + Controls=new(UseGC) GLfloat[(weights ? 4 : 3)*n]; + uKnots=new(UseGC) GLfloat[nuknots]; + vKnots=new(UseGC) GLfloat[nvknots]; + } + + if(weights) + for(size_t i=0; i < n; ++i) + store(Controls+4*i,controls[i],weights[i]); + else + for(size_t i=0; i < n; ++i) + store(Controls+3*i,controls[i]); + + for(size_t i=0; i < nuknots; ++i) + uKnots[i]=uknots[i]; + for(size_t i=0; i < nvknots; ++i) + vKnots[i]=vknots[i]; +#endif +} + +void drawNurbs::render(double size2, const triple& b, const triple& B, + double perspective, bool remesh) +{ +// TODO: implement NURBS renderer +} + +void drawPRC::P(triple& t, double x, double y, double z) +{ + if(T == NULL) { + t=triple(x,y,z); + return; + } + + double f=T[12]*x+T[13]*y+T[14]*z+T[15]; + if(f == 0.0) run::dividebyzero(); + f=1.0/f; + + t=triple((T[0]*x+T[1]*y+T[2]*z+T[3])*f,(T[4]*x+T[5]*y+T[6]*z+T[7])*f, + (T[8]*x+T[9]*y+T[10]*z+T[11])*f); +} + +void drawSphere::P(triple& t, double x, double y, double z) +{ + if(half) { + double temp=z; z=x; x=-temp; + } + drawPRC::P(t,x,y,z); +} + +bool drawSphere::write(prcfile *out, unsigned int *, double, groupsmap&) +{ + if(invisible) + return true; + + RGBAColour Black(0.0,0.0,0.0,diffuse.A); + PRCmaterial m(Black,diffuse,emissive,specular,opacity,shininess); + + switch(type) { + case 0: // PRCsphere + { + if(half) + out->addHemisphere(1.0,m,NULL,NULL,NULL,1.0,T); + else + out->addSphere(1.0,m,NULL,NULL,NULL,1.0,T); + break; + } + case 1: // NURBSsphere + { + static double uknot[]={0.0,0.0,1.0/3.0,0.5,1.0,1.0}; + static double vknot[]={0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0}; + static double Weights[12]={2.0/3.0,2.0/9.0,2.0/9.0,2.0/3.0, + 1.0/3.0,1.0/9.0,1.0/9.0,1.0/3.0, + 1.0,1.0/3.0,1.0/3.0,1.0}; + +// NURBS representation of a sphere using 10 distinct control points +// K. Qin, J. Comp. Sci. and Tech. 12, 210-216 (1997). + + triple N,S,P1,P2,P3,P4,P5,P6,P7,P8; + + P(N,0.0,0.0,1.0); + P(P1,-2.0,-2.0,1.0); + P(P2,-2.0,-2.0,-1.0); + P(S,0.0,0.0,-1.0); + P(P3,2.0,-2.0,1.0); + P(P4,2.0,-2.0,-1.0); + P(P5,2.0,2.0,1.0); + P(P6,2.0,2.0,-1.0); + P(P7,-2.0,2.0,1.0); + P(P8,-2.0,2.0,-1.0); + + triple p0[]={N,P1,P2,S, + N,P3,P4,S, + N,P5,P6,S, + N,P7,P8,S, + N,P1,P2,S, + N,P3,P4,S}; + + out->addSurface(2,3,3,4,p0,uknot,vknot,m,Weights); + out->addSurface(2,3,3,4,p0+4,uknot,vknot,m,Weights); + if(!half) { + out->addSurface(2,3,3,4,p0+8,uknot,vknot,m,Weights); + out->addSurface(2,3,3,4,p0+12,uknot,vknot,m,Weights); + } + + break; + } + default: + reportError("Invalid sphere type"); + } + + return true; +} + +bool drawSphere::write(jsfile *out) +{ +#ifdef HAVE_LIBGLM + if(invisible) + return true; + + drawElement::centerIndex=0; + + setcolors(false,diffuse,emissive,specular,shininess,metallic,fresnel0,out); + + triple O,E; + P(E,1.0,0.0,0.0); + P(O,0.0,0.0,0.0); + triple X=E-O; + double r=length(X); + + if(half) + out->addSphere(O,r,half,X.polar(false),X.azimuth(false)); + else + out->addSphere(O,r); + +#endif + return true; +} + +bool drawCylinder::write(prcfile *out, unsigned int *, double, groupsmap&) +{ + if(invisible) + return true; + + RGBAColour Black(0.0,0.0,0.0,diffuse.A); + PRCmaterial m(Black,diffuse,emissive,specular,opacity,shininess); + + out->addCylinder(1.0,1.0,m,NULL,NULL,NULL,1.0,T); + + return true; +} + +bool drawCylinder::write(jsfile *out) +{ +#ifdef HAVE_LIBGLM + if(invisible) + return true; + + drawElement::centerIndex=0; + + setcolors(false,diffuse,emissive,specular,shininess,metallic,fresnel0,out); + + triple E,H,O; + P(E,1.0,0.0,0.0); + P(H,0.0,0.0,1.0); + P(O,0.0,0.0,0.0); + triple X=E-O; + triple Z=H-O; + double r=length(X); + double h=length(Z); + + out->addCylinder(O,r,h,Z.polar(false),Z.azimuth(false),core); + +#endif + return true; +} + +bool drawDisk::write(prcfile *out, unsigned int *, double, groupsmap&) +{ + if(invisible) + return true; + + RGBAColour Black(0.0,0.0,0.0,diffuse.A); + PRCmaterial m(Black,diffuse,emissive,specular,opacity,shininess); + + out->addDisk(1.0,m,NULL,NULL,NULL,1.0,T); + + return true; +} + +bool drawDisk::write(jsfile *out) +{ +#ifdef HAVE_LIBGLM + if(invisible) + return true; + + drawElement::centerIndex=0; + + setcolors(false,diffuse,emissive,specular,shininess,metallic,fresnel0,out); + + triple E,H,O; + P(E,1.0,0.0,0.0); + P(H,0.0,0.0,1.0); + P(O,0.0,0.0,0.0); + triple X=E-O; + triple Z=H-O; + double r=length(X); + + out->addDisk(O,r,Z.polar(false),Z.azimuth(false)); + +#endif + return true; +} + +bool drawTube::write(jsfile *out) +{ +#ifdef HAVE_LIBGLM + if(invisible) + return true; + + drawElement::centerIndex=0; + + setcolors(false,diffuse,emissive,specular,shininess,metallic,fresnel0,out); + + bbox3 b; + b.add(T*m); + b.add(T*triple(m.getx(),m.gety(),M.getz())); + b.add(T*triple(m.getx(),M.gety(),m.getz())); + b.add(T*triple(m.getx(),M.gety(),M.getz())); + b.add(T*triple(M.getx(),m.gety(),m.getz())); + b.add(T*triple(M.getx(),m.gety(),M.getz())); + b.add(T*triple(M.getx(),M.gety(),m.getz())); + b.add(T*M); + + out->addTube(g,width,b.Min(),b.Max(),core); + +#endif + return true; +} + +const string drawBaseTriangles::wrongsize= + "triangle indices require 3 components"; +const string drawBaseTriangles::outofrange="index out of range"; + +void drawBaseTriangles::bounds(const double* t, bbox3& b) +{ + double x,y,z; + double X,Y,Z; + triple* tP; + + if(t == NULL) tP=P; + else { + tP=new triple[nP]; + for(size_t i=0; i < nP; i++) + tP[i]=t*P[i]; + } + + boundstriples(x,y,z,X,Y,Z,nP,tP); + + b.add(x,y,z); + b.add(X,Y,Z); + + if(t == NULL) { + Min=triple(x,y,z); + Max=triple(X,Y,Z); + } else delete[] tP; +} + +void drawBaseTriangles::ratio(const double* t, pair &b, + double (*m)(double, double), double fuzz, + bool &first) +{ + triple* tP; + + if(t == NULL) tP=P; + else { + tP=new triple[nP]; + for(size_t i=0; i < nP; i++) + tP[i]=t*P[i]; + } + + ratiotriples(b,m,first,nP,tP); + + if(t != NULL) + delete[] tP; +} + +bool drawTriangles::write(prcfile *out, unsigned int *, double, groupsmap&) +{ + if(invisible) + return true; + + if(nC) { + const RGBAColour white(1,1,1,opacity); + const RGBAColour black(0,0,0,opacity); + const PRCmaterial m(black,white,black,specular,opacity,shininess); + out->addTriangles(nP,P,nI,PI,m,nN,N,NI,0,NULL,NULL,nC,C,CI,0,NULL,NULL,30); + } else { + RGBAColour Black(0.0,0.0,0.0,diffuse.A); + const PRCmaterial m(Black,diffuse,emissive,specular,opacity,shininess); + out->addTriangles(nP,P,nI,PI,m,nN,N,NI,0,NULL,NULL,0,NULL,NULL,0,NULL,NULL,30); + } + + return true; +} + +bool drawTriangles::write(jsfile *out) +{ +#ifdef HAVE_LIBGLM + if(invisible) + return true; + + setcolors(nC,diffuse,emissive,specular,shininess,metallic,fresnel0,out); + + out->addTriangles(nP,P,nN,N,nC,C,nI,PI,NI,CI,Min,Max); +#endif + return true; +} + +void drawTriangles::render(double size2, const triple& b, + const triple& B, double perspective, + bool remesh) +{ +#ifdef HAVE_GL + if(invisible) return; + + transparent=diffuse.A < 1.0; + + if(bbox2(Min,Max).offscreen()) { // Fully offscreen + R.Onscreen=false; + R.data.clear(); + R.transparent=transparent; + R.notRendered(); + return; + } + + setcolors(nC,diffuse,emissive,specular,shininess,metallic,fresnel0); + + if(transparent) + setMaterial(transparentData,drawTransparent); + else + setMaterial(triangleData,drawTriangle); + + if(!remesh && R.Onscreen) { // Fully onscreen; no need to re-render + R.append(); + return; + } + + R.queue(nP,P,nN,N,nC,C,nI,PI,NI,CI,transparent); +#endif +} + +} //namespace camp |