/***** * drawsurface.cc * * Stores a surface that has been added to a picture. *****/ #include "drawsurface.h" #include "drawpath3.h" #include "arrayop.h" #include #include #include #ifdef HAVE_LIBGLM #include #include #include #endif using namespace prc; #include "material.h" namespace camp { mem::vector drawElement::centers; size_t drawElement::centerIndex=0; centerMap drawElement::centermap; 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(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(const RGBAColour& diffuse, const RGBAColour& emissive, const RGBAColour& specular, double shininess, double metallic, double fresnel0, abs3Doutfile *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); auto p=materialMap.find(m); if(p != materialMap.end()) materialIndex=p->second; else { materialIndex=materials.size(); if(materialIndex >= nmaterials) nmaterials=min(Maxmaterials,2*nmaterials); materials.push_back(m); materialMap[m]=materialIndex; if(out) out->addMaterial(m); } } #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,c0,fuzz,maxdepth); X=bound(cx,max,c0,fuzz,maxdepth); c0=cy[0]; fuzz=Fuzz*run::norm(cy,16); y=bound(cy,min,c0,fuzz,maxdepth); Y=bound(cy,max,c0,fuzz,maxdepth); c0=cz[0]; fuzz=Fuzz*run::norm(cz,16); z=bound(cz,min,c0,fuzz,maxdepth); Z=bound(cz,max,c0,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(abs3Doutfile *out) { #ifdef HAVE_LIBGLM if(invisible || primitive) return true; setcolors(diffuse,emissive,specular,shininess,metallic,fresnel0,out); if(billboard) { meshinit(); drawElement::centerIndex=centerIndex; } else drawElement::centerIndex=0; out->precision(digits); if(straight) { triple Controls[]={controls[0],controls[12],controls[15],controls[3]}; out->addStraightPatch(Controls,colors); } else { double prerender=renderResolution(); if(prerender) { GLfloat c[16]; if(colors) for(size_t i=0; i < 4; ++i) storecolor(c,4*i,colors[i]); S.init(prerender,colors ? c : NULL); S.render(controls,straight,c); drawTriangles dt(S.data,center,colors,diffuse,emissive,specular,opacity, shininess,metallic,fresnel0,interaction,invisible, Min,Max); dt.write(out); } else out->addPatch(controls,colors); } out->precision(getSetting("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(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,c0,fuzz,maxdepth); X=boundtri(cx,max,c0,fuzz,maxdepth); c0=cy[0]; fuzz=Fuzz*run::norm(cy,10); y=boundtri(cy,min,c0,fuzz,maxdepth); Y=boundtri(cy,max,c0,fuzz,maxdepth); c0=cz[0]; fuzz=Fuzz*run::norm(cz,10); z=boundtri(cz,min,c0,fuzz,maxdepth); Z=boundtri(cz,max,c0,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(abs3Doutfile *out) { #ifdef HAVE_LIBGLM if(invisible || primitive) return true; setcolors(diffuse,emissive,specular,shininess,metallic,fresnel0,out); if(billboard) { meshinit(); drawElement::centerIndex=centerIndex; } else drawElement::centerIndex=0; out->precision(digits); if(straight) { triple Controls[]={controls[0],controls[6],controls[9]}; out->addStraightBezierTriangle(Controls,colors); } else { double prerender=renderResolution(); if(prerender) { GLfloat c[16]; if(colors) for(size_t i=0; i < 4; ++i) storecolor(c,4*i,colors[i]); S.init(prerender,colors ? c : NULL); S.render(controls,straight,c); drawTriangles dt(S.data,center,colors,diffuse,emissive,specular,opacity, shininess,metallic,fresnel0,interaction,invisible, Min,Max); dt.write(out); } else out->addBezierTriangle(controls,colors); } out->precision(getSetting("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(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 { if(!remesh && S.Onscreen) { // Fully onscreen; no need to re-render S.append(); return; } Controls=controls; } 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(abs3Doutfile *out) { #ifdef HAVE_LIBGLM if(invisible) return true; drawElement::centerIndex=0; setcolors(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->addHemisphere(O,r,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(abs3Doutfile *out) { #ifdef HAVE_LIBGLM if(invisible) return true; drawElement::centerIndex=0; setcolors(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(abs3Doutfile *out) { #ifdef HAVE_LIBGLM if(invisible) return true; drawElement::centerIndex=0; setcolors(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(abs3Doutfile *out) { #ifdef HAVE_LIBGLM if(invisible) return true; drawElement::centerIndex=0; setcolors(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,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(abs3Doutfile *out) { #ifdef HAVE_LIBGLM if(invisible) return true; if(billboard) { meshinit(); drawElement::centerIndex=centerIndex; } else drawElement::centerIndex=0; setcolors(diffuse,emissive,specular,shininess,metallic,fresnel0,out); out->addTriangles(nP,P,nN,N,nC,C,nI,PI,NI,CI); #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; setcolors(diffuse,emissive,specular,shininess,metallic,fresnel0); if(transparent) setMaterial(transparentData,drawTransparent); else setMaterial(triangleData,drawTriangle); 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 R.Onscreen=false; R.data.clear(); R.transparent=transparent; R.notRendered(); return; } triple *P0; if(billboard) { P0=new triple [nP]; for(size_t i=0; i < nP; i++) P0[i]=BB.transform(P[i]); } else { if(!remesh && R.Onscreen) { // Fully onscreen; no need to re-render R.append(); return; } P0=P; } R.queue(nP,P0,nN,N,nC,C,nI,PI,NI,CI,transparent); if(billboard) delete [] P0; #endif } } //namespace camp