summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/asymptote/three_surface.asy
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/asymptote/three_surface.asy')
-rw-r--r--Master/texmf-dist/asymptote/three_surface.asy485
1 files changed, 225 insertions, 260 deletions
diff --git a/Master/texmf-dist/asymptote/three_surface.asy b/Master/texmf-dist/asymptote/three_surface.asy
index 4ad31d6d2d7..12ac464b242 100644
--- a/Master/texmf-dist/asymptote/three_surface.asy
+++ b/Master/texmf-dist/asymptote/three_surface.asy
@@ -71,10 +71,6 @@ struct patch {
triple BuP(int j, real u) {
return bezierP(P[0][j],P[1][j],P[2][j],P[3][j],u);
}
- triple BuPP(int j, real u) {
- return bezierPP(P[0][j],P[1][j],P[2][j],P[3][j],u);
- }
- triple BuPPP(int j) {return bezierPPP(P[0][j],P[1][j],P[2][j],P[3][j]);}
path3 uequals(real u) {
triple z0=Bu(0,u);
@@ -87,10 +83,6 @@ struct patch {
triple BvP(int i, real v) {
return bezierP(P[i][0],P[i][1],P[i][2],P[i][3],v);
}
- triple BvPP(int i, real v) {
- return bezierPP(P[i][0],P[i][1],P[i][2],P[i][3],v);
- }
- triple BvPPP(int i) {return bezierPPP(P[i][0],P[i][1],P[i][2],P[i][3]);}
path3 vequals(real v) {
triple z0=Bv(0,v);
@@ -103,29 +95,52 @@ struct patch {
return bezier(Bu(0,u),Bu(1,u),Bu(2,u),Bu(3,u),v);
}
- // compute normal vectors for degenerate cases
- private triple normal0(real u, real v, real epsilon) {
- triple n=0.5*(cross(bezier(BuPP(0,u),BuPP(1,u),BuPP(2,u),BuPP(3,u),v),
- bezier(BvP(0,v),BvP(1,v),BvP(2,v),BvP(3,v),u))+
- cross(bezier(BuP(0,u),BuP(1,u),BuP(2,u),BuP(3,u),v),
- bezier(BvPP(0,v),BvPP(1,v),BvPP(2,v),BvPP(3,v),u)));
- return abs(n) > epsilon ? n :
- 0.25*cross(bezier(BuPP(0,u),BuPP(1,u),BuPP(2,u),BuPP(3,u),v),
- bezier(BvPP(0,v),BvPP(1,v),BvPP(2,v),BvPP(3,v),u))+
- 1/6*(cross(bezier(BuP(0,u),BuP(1,u),BuP(2,u),BuP(3,u),v),
- bezier(BvPPP(0),BvPPP(1),BvPPP(2),BvPPP(3),u))+
- cross(bezier(BuPPP(0),BuPPP(1),BuPPP(2),BuPPP(3),v),
- bezier(BvP(0,v),BvP(1,v),BvP(2,v),BvP(3,v),u)))+
- 1/12*(cross(bezier(BuPPP(0),BuPPP(1),BuPPP(2),BuPPP(3),v),
- bezier(BvPP(0,v),BvPP(1,v),BvPP(2,v),BvPP(3,v),u))+
- cross(bezier(BuPP(0,u),BuPP(1,u),BuPP(2,u),BuPP(3,u),v),
- bezier(BvPPP(0),BvPPP(1),BvPPP(2),BvPPP(3),u)))+
- 1/36*cross(bezier(BuPPP(0),BuPPP(1),BuPPP(2),BuPPP(3),v),
- bezier(BvPPP(0),BvPPP(1),BvPPP(2),BvPPP(3),u));
- }
-
static real fuzz=1000*realEpsilon;
+ triple normal(triple left3, triple left2, triple left1, triple middle,
+ triple right1, triple right2, triple right3) {
+ real epsilon=fuzz*change2(P);
+
+ triple lp=3.0*(left1-middle);
+ triple rp=3.0*(right1-middle);
+
+ triple n=cross(rp,lp);
+ if(abs(n) > epsilon)
+ return n;
+
+ // Return one-half of the second derivative of the Bezier curve defined
+ // by a,b,c,d at 0.
+ triple bezierPP(triple a, triple b, triple c) {
+ return 3.0*(a+c-2.0*b);
+ }
+
+ triple lpp=bezierPP(middle,left1,left2);
+ triple rpp=bezierPP(middle,right1,right2);
+
+ n=cross(rpp,lp)+cross(rp,lpp);
+ if(abs(n) > epsilon)
+ return n;
+
+ // Return one-sixth of the third derivative of the Bezier curve defined
+ // by a,b,c,d at 0.
+ triple bezierPPP(triple a, triple b, triple c, triple d) {
+ return d-a+3.0*(b-c);
+ }
+
+ triple lppp=bezierPPP(middle,left1,left2,left3);
+ triple rppp=bezierPPP(middle,right1,right2,right3);
+
+ n=cross(rpp,lpp)+cross(rppp,lp)+cross(rp,lppp);
+ if(abs(n) > epsilon)
+ return n;
+
+ n=cross(rppp,lpp)+cross(rpp,lppp);
+ if(abs(n) > epsilon)
+ return n;
+
+ return cross(rppp,lppp);
+ }
+
triple partialu(real u, real v) {
return bezier(BuP(0,u),BuP(1,u),BuP(2,u),BuP(3,u),v);
}
@@ -134,34 +149,32 @@ struct patch {
return bezier(BvP(0,v),BvP(1,v),BvP(2,v),BvP(3,v),u);
}
- triple normal(real u, real v) {
- triple n=cross(partialu(u,v),partialv(u,v));
- real epsilon=fuzz*change2(P);
- return (abs(n) > epsilon) ? n : normal0(u,v,epsilon);
- }
-
triple normal00() {
- triple n=9*cross(P[1][0]-P[0][0],P[0][1]-P[0][0]);
- real epsilon=fuzz*change2(P);
- return abs(n) > epsilon ? n : normal0(0,0,epsilon);
+ return normal(P[0][3],P[0][2],P[0][1],P[0][0],P[1][0],P[2][0],P[3][0]);
}
triple normal10() {
- triple n=9*cross(P[3][0]-P[2][0],P[3][1]-P[3][0]);
- real epsilon=fuzz*change2(P);
- return abs(n) > epsilon ? n : normal0(1,0,epsilon);
+ return normal(P[0][0],P[1][0],P[2][0],P[3][0],P[3][1],P[3][2],P[3][3]);
}
triple normal11() {
- triple n=9*cross(P[3][3]-P[2][3],P[3][3]-P[3][2]);
- real epsilon=fuzz*change2(P);
- return abs(n) > epsilon ? n : normal0(1,1,epsilon);
+ return normal(P[3][0],P[3][1],P[3][2],P[3][3],P[2][3],P[1][3],P[0][3]);
}
triple normal01() {
- triple n=9*cross(P[1][3]-P[0][3],P[0][3]-P[0][2]);
- real epsilon=fuzz*change2(P);
- return abs(n) > epsilon ? n : normal0(0,1,epsilon);
+ return normal(P[3][3],P[2][3],P[1][3],P[0][3],P[0][2],P[0][1],P[0][0]);
+ }
+
+ triple normal(real u, real v) {
+ if(u == 0) {
+ if(v == 0) return normal00();
+ if(v == 1) return normal01();
+ }
+ if(u == 1) {
+ if(v == 0) return normal10();
+ if(v == 1) return normal11();
+ }
+ return cross(partialu(u,v),partialv(u,v));
}
triple pointtriangular(real u, real v) {
@@ -171,7 +184,7 @@ struct patch {
6*u*v*w*P[2][1]+v^2*(3*(w*P[2][2]+u*P[3][2])+v*P[3][3]);
}
- triple bu(real u, real v) {
+ triple partialutriangular(real u, real v) {
// Compute one-third of the directional derivative of a Bezier triangle
// in the u direction at (u,v).
real w=1-u-v;
@@ -179,21 +192,7 @@ struct patch {
2*v*(w-u)*P[2][1]-v^2*P[2][2]+u^2*P[3][0]+2*u*v*P[3][1]+v^2*P[3][2];
}
- triple buu(real u, real v) {
- // Compute one-sixth of the second directional derivative of a Bezier
- // triangle in the u direction at (u,v).
- real w=1-u-v;
- return w*P[0][0]+(u-2*w)*P[1][0]+v*P[1][1]+(w-2*u)*P[2][0]-2*v*P[2][1]+
- u*P[3][0]+v*P[3][1];
- }
-
- triple buuu() {
- // Compute one-sixth of the third directional derivative of a Bezier
- // triangle in the u direction at (u,v).
- return -P[0][0]+3*P[1][0]-3*P[2][0]+P[3][0];
- }
-
- triple bv(real u, real v) {
+ triple partialvtriangular(real u, real v) {
// Compute one-third of the directional derivative of a Bezier triangle
// in the v direction at (u,v).
real w=1-u-v;
@@ -202,54 +201,26 @@ struct patch {
v^2*P[3][3];
}
- triple bvv(real u, real v) {
- // Compute one-sixth of the second directional derivative of a Bezier
- // triangle in the v direction at (u,v).
- real w=1-u-v;
- return w*P[0][0]+u*P[1][0]+(v-2*w)*P[1][1]-2*u*P[2][1]+(w-2*v)*P[2][2]+
- u*P[3][2]+v*P[3][3];
- }
-
- triple bvvv() {
- // Compute one-sixth of the third directional derivative of a Bezier
- // triangle in the v direction at (u,v).
- return -P[0][0]+3*P[1][1]-3*P[2][2]+P[3][3];
- }
-
- // compute normal vectors for a degenerate Bezier triangle
- private triple normaltriangular0(real u, real v, real epsilon) {
- triple n=9*(cross(buu(u,v),bv(u,v))+
- cross(bu(u,v),bvv(u,v)));
- return abs(n) > epsilon ? n :
- 9*cross(buu(u,v),bvv(u,v))+
- 3*(cross(buuu(),bv(u,v))+cross(bu(u,v),bvvv())+
- cross(buuu(),bvv(u,v))+cross(buu(u,v),bvvv()))+
- cross(buuu(),bvvv());
- }
-
- // Compute the normal of a Bezier triangle at (u,v)
- triple normaltriangular(real u, real v) {
- triple n=9*cross(bu(u,v),bv(u,v));
- real epsilon=fuzz*change2(P);
- return (abs(n) > epsilon) ? n : normal0(u,v,epsilon);
- }
-
triple normal00triangular() {
- triple n=9*cross(P[1][0]-P[0][0],P[1][1]-P[0][0]);
- real epsilon=fuzz*change2(P);
- return abs(n) > epsilon ? n : normaltriangular0(0,0,epsilon);
+ return normal(P[3][3],P[2][2],P[1][1],P[0][0],P[1][0],P[2][0],P[3][0]);
}
triple normal10triangular() {
- triple n=9*cross(P[3][0]-P[2][0],P[3][1]-P[2][0]);
- real epsilon=fuzz*change2(P);
- return abs(n) > epsilon ? n : normaltriangular0(1,0,epsilon);
+ return normal(P[0][0],P[1][0],P[2][0],P[3][0],P[3][1],P[3][2],P[3][3]);
}
triple normal01triangular() {
- triple n=9*cross(P[3][2]-P[2][2],P[3][3]-P[2][2]);
- real epsilon=fuzz*change2(P);
- return abs(n) > epsilon ? n : normaltriangular0(0,1,epsilon);
+ return normal(P[3][0],P[3][1],P[3][2],P[3][3],P[2][2],P[1][1],P[0][0]);
+ }
+
+ // Compute the normal vector of a Bezier triangle at (u,v)
+ triple normaltriangular(real u, real v) {
+ if(u == 0) {
+ if(v == 0) return normal00triangular();
+ if(v == 1) return normal01triangular();
+ }
+ if(u == 1 && v == 0) return normal10triangular();
+ return cross(partialutriangular(u,v),partialvtriangular(u,v));
}
pen[] colors(material m, light light=currentlight) {
@@ -751,11 +722,18 @@ path[] regularize(path p, bool checkboundary=true)
return s;
}
+typedef void drawfcn(frame f, transform3 t=identity4, material[] m,
+ light light=currentlight, render render=defaultrender);
+
struct surface {
patch[] s;
int index[][];// Position of patch corresponding to major U,V parameter in s.
bool vcyclic;
+ transform3 T=identity4;
+ drawfcn draw;
+ bool PRCprimitive=true; // True unless no PRC primitive is available.
+
bool empty() {
return s.length == 0;
}
@@ -1052,6 +1030,9 @@ surface operator * (transform3 t, surface s)
S.s[i]=t*s.s[i];
S.index=copy(s.index);
S.vcyclic=(bool) s.vcyclic;
+ S.T=t*s.T;
+ S.draw=s.draw;
+ S.PRCprimitive=s.PRCprimitive;
return S;
}
@@ -1365,16 +1346,6 @@ triple point(patch s, real u, real v)
return s.point(u,v);
}
-real PRCshininess(real shininess)
-{
- // Empirical translation table from Phong-Blinn to PRC shininess model:
- static real[] x={0.015,0.025,0.05,0.07,0.1,0.14,0.23,0.5,0.65,0.75,0.85,
- 0.875,0.9,1};
- static real[] y={0.05,0.1,0.15,0.2,0.25,0.3,0.4,0.5,0.55,0.6,0.7,0.8,0.9,1};
- static realfunction s=fspline(x,y,monotonic);
- return s(shininess);
-}
-
struct interaction
{
int type;
@@ -1393,30 +1364,34 @@ interaction LabelInteraction()
return settings.autobillboard ? Billboard : Embedded;
}
-material material(material m, light light)
+material material(material m, light light, bool colors=false)
{
- return light.on() || invisible((pen) m) ? m : emissive(m);
+ return light.on() || invisible((pen) m) ? m : emissive(m,colors);
}
-void draw3D(frame f, int type=0, patch s, triple center=O, material m,
+void draw3D(frame f, patch s, triple center=O, material m,
light light=currentlight, interaction interaction=Embedded,
- bool prc=true)
+ bool primitive=false)
{
bool straight=s.straight && s.planar;
- bool prc=prc();
if(s.colors.length > 0) {
- if(prc && light.on())
+ if(prc() && light.on())
straight=false; // PRC vertex colors (for quads only) ignore lighting
- m=mean(s.colors);
+ m.diffuse(mean(s.colors));
}
- m=material(m,light);
+ m=material(m,light,s.colors.length > 0);
- real PRCshininess;
- if(prc) PRCshininess=PRCshininess(m.shininess);
-
(s.triangular ? drawbeziertriangle : draw)
(f,s.P,center,straight,m.p,m.opacity,m.shininess,
- m.metallic,m.fresnel0,PRCshininess,s.colors,interaction.type,prc);
+ m.metallic,m.fresnel0,s.colors,interaction.type,primitive);
+}
+
+void _draw(frame f, path3 g, triple center=O, material m,
+ light light=currentlight, interaction interaction=Embedded)
+{
+ if(!prc()) m=material(m,light);
+ _draw(f,g,center,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0,
+ interaction.type);
}
int computeNormals(triple[] v, int[][] vi, triple[] n, int[][] ni)
@@ -1448,11 +1423,7 @@ void draw(frame f, triple[] v, int[][] vi,
if(p.length > 0)
m=mean(p);
m=material(m,light);
- real PRCshininess;
- if(prc())
- PRCshininess=PRCshininess(m.shininess);
- draw(f,v,vi,n,ni,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0,
- PRCshininess,p,pi);
+ draw(f,v,vi,n,ni,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0,p,pi);
}
// Draw triangles on a picture.
@@ -1520,40 +1491,9 @@ void draw(picture pic=currentpicture, triple[] v, int[][] vi,
pic.addPoint(v[viij]);
}
-void drawPRCsphere(frame f, transform3 t=identity4, bool half=false,
- material m, light light=currentlight,
- render render=defaultrender)
-{
- m=material(m,light);
- drawPRCsphere(f,t,half,m.p,m.opacity,PRCshininess(m.shininess),
- render.sphere);
-}
-
-void drawPRCcylinder(frame f, transform3 t=identity4, material m,
- light light=currentlight)
-{
- m=material(m,light);
- drawPRCcylinder(f,t,m.p,m.opacity,PRCshininess(m.shininess));
-}
-
-void drawPRCdisk(frame f, transform3 t=identity4, material m,
- light light=currentlight)
-{
- m=material(m,light);
- drawPRCdisk(f,t,m.p,m.opacity,PRCshininess(m.shininess));
-}
-
-void drawPRCtube(frame f, path3 center, path3 g, material m,
- light light=currentlight)
-{
- m=material(m,light);
- drawPRCtube(f,center,g,m.p,m.opacity,PRCshininess(m.shininess));
-}
-
void tensorshade(transform t=identity(), frame f, patch s,
material m, light light=currentlight, projection P)
{
-
pen[] p;
if(s.triangular) {
p=s.colorstriangular(m,light);
@@ -1574,53 +1514,62 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1,
{
bool is3D=is3D();
if(is3D) {
- bool group=name != "" || render.defaultnames;
- if(group)
- begingroup3(f,name == "" ? "surface" : name,render);
-
- // Sort patches by mean distance from camera
- triple camera=P.camera;
- if(P.infinity) {
- triple m=min(s);
- triple M=max(s);
- camera=P.target+camerafactor*(abs(M-m)+abs(m-P.target))*unit(P.vector());
- }
-
- real[][] depth=new real[s.s.length][];
- for(int i=0; i < depth.length; ++i)
- depth[i]=new real[] {dot(P.normal,camera-s.s[i].cornermean()),i};
+ bool prc=prc();
+ if(s.draw != null && (settings.outformat == "html" ||
+ (prc && s.PRCprimitive))) {
+ for(int k=0; k < s.s.length; ++k)
+ draw3D(f,s.s[k],surfacepen[k],light,primitive=true);
+ s.draw(f,s.T,surfacepen,light,render);
+ } else {
+ bool group=name != "" || render.defaultnames;
+ if(group)
+ begingroup3(f,name == "" ? "surface" : name,render);
+
+ // Sort patches by mean distance from camera
+ triple camera=P.camera;
+ if(P.infinity) {
+ triple m=min(s);
+ triple M=max(s);
+ camera=P.target+camerafactor*(abs(M-m)+abs(m-P.target))*
+ unit(P.vector());
+ }
- depth=sort(depth);
+ real[][] depth=new real[s.s.length][];
+ for(int i=0; i < depth.length; ++i)
+ depth[i]=new real[] {dot(P.normal,camera-s.s[i].cornermean()),i};
- for(int p=depth.length-1; p >= 0; --p) {
- real[] a=depth[p];
- int k=round(a[1]);
- draw3D(f,s.s[k],surfacepen[k],light);
- }
+ depth=sort(depth);
- if(group)
- endgroup3(f);
+ for(int p=depth.length-1; p >= 0; --p) {
+ real[] a=depth[p];
+ int k=round(a[1]);
+ draw3D(f,s.s[k],surfacepen[k],light);
+ }
- pen modifiers=thin()+squarecap;
- for(int p=depth.length-1; p >= 0; --p) {
- real[] a=depth[p];
- int k=round(a[1]);
- patch S=s.s[k];
- pen meshpen=meshpen[k];
- if(!invisible(meshpen) && !S.triangular) {
- if(group)
- begingroup3(f,meshname(name),render);
- meshpen=modifiers+meshpen;
- real step=nu == 0 ? 0 : 1/nu;
- for(int i=0; i <= nu; ++i)
- draw(f,S.uequals(i*step),meshpen,meshlight,partname(i,render),
- render);
- step=nv == 0 ? 0 : 1/nv;
- for(int j=0; j <= nv; ++j)
- draw(f,S.vequals(j*step),meshpen,meshlight,partname(j,render),
- render);
- if(group)
- endgroup3(f);
+ if(group)
+ endgroup3(f);
+
+ pen modifiers=thin()+squarecap;
+ for(int p=depth.length-1; p >= 0; --p) {
+ real[] a=depth[p];
+ int k=round(a[1]);
+ patch S=s.s[k];
+ pen meshpen=meshpen[k];
+ if(!invisible(meshpen) && !S.triangular) {
+ if(group)
+ begingroup3(f,meshname(name),render);
+ meshpen=modifiers+meshpen;
+ real step=nu == 0 ? 0 : 1/nu;
+ for(int i=0; i <= nu; ++i)
+ draw(f,S.uequals(i*step),meshpen,meshlight,partname(i,render),
+ render);
+ step=nv == 0 ? 0 : 1/nv;
+ for(int j=0; j <= nv; ++j)
+ draw(f,S.vequals(j*step),meshpen,meshlight,partname(j,render),
+ render);
+ if(group)
+ endgroup3(f);
+ }
}
}
}
@@ -1881,7 +1830,7 @@ void label(frame f, Label L, triple position, align align=NoAlign,
draw3D(f3,S,position,L.p,light,interaction);
// Fill subdivision cracks
if(prc && render.labelfill && opacity(L.p) == 1 && !lighton)
- _draw(f3,S.external(),position,L.p,interaction.type);
+ _draw(f3,S.external(),position,L.p,light,interaction);
}
endgroup3(f3);
if(L.defaulttransform3)
@@ -1901,7 +1850,7 @@ void label(frame f, Label L, triple position, align align=NoAlign,
draw3D(f,S,V,L.p,light,interaction);
// Fill subdivision cracks
if(prc && render.labelfill && opacity(L.p) == 1 && !lighton)
- _draw(f,S.external(),V,L.p,interaction.type);
+ _draw(f,S.external(),V,L.p,light,interaction);
}
endgroup3(f);
}
@@ -1970,7 +1919,7 @@ void label(picture pic=currentpicture, Label L, triple position,
draw3D(f3,S,v,L.p,light,interaction);
// Fill subdivision cracks
if(prc && render.labelfill && opacity(L.p) == 1 && !lighton)
- _draw(f3,S.external(),v,L.p,interaction.type);
+ _draw(f3,S.external(),v,L.p,light,interaction);
}
endgroup3(f3);
if(L.defaulttransform3)
@@ -1990,7 +1939,7 @@ void label(picture pic=currentpicture, Label L, triple position,
draw3D(f,S,V,L.p,light,interaction);
// Fill subdivision cracks
if(prc && render.labelfill && opacity(L.p) == 1 && !lighton)
- _draw(f,S.external(),V,L.p,interaction.type);
+ _draw(f,S.external(),V,L.p,light,interaction);
}
endgroup3(f);
}
@@ -2114,14 +2063,25 @@ surface surface(Label L, surface s, real uoffset, real voffset,
}
private real a=4/3*(sqrt(2)-1);
+private real f=0.5*sqrt(3)*a^2;
+
private transform3 t1=rotate(90,O,Z);
private transform3 t2=t1*t1;
private transform3 t3=t2*t1;
private transform3 i=xscale3(-1)*zscale3(-1);
-restricted patch octant1=patch(X{Y}..{-X}Y{Z}..{-Y}Z..Z{X}..{-Z}cycle,
+// Degenerate first octant
+restricted patch octant1x=patch(X{Y}..{-X}Y{Z}..{-Y}Z..Z{X}..{-Z}cycle,
new triple[] {(1,a,a),(a,1,a),(a^2,a,1),
- (a,a^2,1)});
+ (a,a^2,1)});
+private triple[][][] P=hsplit(octant1x.P,
+ intersect((1,0){N}..{W}(0,1),(0,0)--2*dir(60))[0]);
+// Nondegenerate first octant
+surface octant1=surface(patch(P[0]),
+ patch(P[1][0][0]..controls P[1][1][0] and P[1][2][0]..
+ P[1][3][0]..controls P[1][3][1] and P[1][3][2]..
+ P[1][3][3]..controls P[1][0][2] and P[1][0][1]..
+ cycle,(f,f,1)));
restricted surface unithemisphere=surface(octant1,t1*octant1,t2*octant1,
t3*octant1);
@@ -2129,33 +2089,41 @@ restricted surface unitsphere=surface(octant1,t1*octant1,t2*octant1,t3*octant1,
i*octant1,i*t1*octant1,i*t2*octant1,
i*t3*octant1);
-restricted patch unitfrustum(real t1, real t2)
+unitsphere.draw=
+ new void(frame f, transform3 t=identity4, material[] m,
+ light light=currentlight, render render=defaultrender)
+ {
+ material m=material(m[0],light);
+ drawSphere(f,t,half=false,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0,
+ render.sphere);
+ };
+
+unithemisphere.draw=
+ new void(frame f, transform3 t=identity4, material[] m,
+ light light=currentlight, render render=defaultrender)
+ {
+ material m=material(m[0],light);
+ drawSphere(f,t,half=true,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0,
+ render.sphere);
+ };
+
+restricted patch unitfrustum1(real ta, real tb)
{
- real s1=interp(t1,t2,1/3);
- real s2=interp(t1,t2,2/3);
- return patch(interp(Z,X,t2){Y}..{-X}interp(Z,Y,t2)--interp(Z,Y,t1){X}..{-Y}
- interp(Z,X,t1)--cycle,
+ real s1=interp(ta,tb,1/3);
+ real s2=interp(ta,tb,2/3);
+ return patch(interp(Z,X,tb){Y}..{-X}interp(Z,Y,tb)--interp(Z,Y,ta){X}..{-Y}
+ interp(Z,X,ta)--cycle,
new triple[] {(s2,s2*a,1-s2),(s2*a,s2,1-s2),(s1*a,s1,1-s1),
(s1,s1*a,1-s1)});
}
-// Return a unitcone constructed from n frusta (the final one being degenerate)
-surface unitcone(int n=6)
+restricted surface unitfrustum(real ta, real tb)
{
- surface unitcone;
- unitcone.s=new patch[4*n];
- real r=1/3;
- for(int i=0; i < n; ++i) {
- patch s=unitfrustum(i < n-1 ? r^(i+1) : 0,r^i);
- unitcone.s[i]=s;
- unitcone.s[n+i]=t1*s;
- unitcone.s[2n+i]=t2*s;
- unitcone.s[3n+i]=t3*s;
- }
- return unitcone;
+ patch p=unitfrustum1(ta,tb);
+ return surface(p,t1*p,t2*p,t3*p);
}
-restricted surface unitcone=unitcone();
+restricted surface unitcone=surface(unitfrustum(0,1));
restricted surface unitsolidcone=surface(patch(unitcircle3)...unitcone.s);
// Construct an approximate cone over an arbitrary base.
@@ -2166,6 +2134,18 @@ private patch unitcylinder1=patch(X{Y}..{-X}Y--Y+Z{X}..{-Y}X+Z--cycle);
restricted surface unitcylinder=surface(unitcylinder1,t1*unitcylinder1,
t2*unitcylinder1,t3*unitcylinder1);
+drawfcn unitcylinderDraw(bool core) {
+ return new void(frame f, transform3 t=identity4, material[] m,
+ light light=currentlight, render render=defaultrender)
+ {
+ material m=material(m[0],light);
+ drawCylinder(f,t,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0,
+ m.opacity == 1 ? core : false);
+ };
+}
+
+unitcylinder.draw=unitcylinderDraw(false);
+
private patch unitplane=patch(new triple[] {O,X,X+Y,Y});
restricted surface unitcube=surface(reverse(unitplane),
rotate(90,O,X)*unitplane,
@@ -2176,24 +2156,23 @@ restricted surface unitcube=surface(reverse(unitplane),
restricted surface unitplane=surface(unitplane);
restricted surface unitdisk=surface(unitcircle3);
+unitdisk.draw=
+ new void(frame f, transform3 t=identity4, material[] m,
+ light light=currentlight, render render=defaultrender)
+ {
+ material m=material(m[0],light);
+ drawDisk(f,t,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0);
+ };
+
void dot(frame f, triple v, material p=currentpen,
light light=nolight, string name="",
render render=defaultrender, projection P=currentprojection)
{
+ if(name == "" && render.defaultnames) name="dot";
pen q=(pen) p;
- if(is3D()) {
- bool group=name != "" || render.defaultnames;
- if(group)
- begingroup3(f,name == "" ? "dot" : name,render);
- real size=0.5*linewidth(dotsize(q)+q);
- transform3 T=shift(v)*scale3(size);
- for(patch s : unitsphere.s)
- draw3D(f,T*s,v,p,light,prc=false);
- if(prc())
- drawPRCsphere(f,T,p,light);
- if(group)
- endgroup3(f);
- } else dot(f,project(v,P.t),q);
+ real size=0.5*linewidth(dotsize(q)+q);
+ transform3 T=shift(v)*scale3(size);
+ draw(f,T*unitsphere,p,light,name,render,P);
}
void dot(frame f, triple[] v, material p=currentpen, light light=nolight,
@@ -2250,18 +2229,7 @@ void dot(picture pic=currentpicture, triple v, material p=currentpen,
real size=0.5*linewidth(dotsize(q)+q);
pic.add(new void(frame f, transform3 t, picture pic, projection P) {
triple V=t*v;
- if(is3D()) {
- bool group=name != "" || render.defaultnames;
- if(group)
- begingroup3(f,name == "" ? "dot" : name,render);
- transform3 T=shift(V)*scale3(size);
- for(patch s : unitsphere.s)
- draw3D(f,T*s,V,p,light,prc=false);
- if(prc())
- drawPRCsphere(f,T,p,light,render);
- if(group)
- endgroup3(f);
- }
+ dot(f,V,p,light,name,render,P);
if(pic != null)
dot(pic,project(V,P.t),q);
},true);
@@ -2450,11 +2418,8 @@ void draw(picture pic=currentpicture, triple[][] P, real[] uknot, real[] vknot,
if(group)
begingroup3(f,name == "" ? "surface" : name,render);
triple[][] P=t*P;
- real PRCshininess;
- if(prc())
- PRCshininess=PRCshininess(m.shininess);
- draw(f,P,uknot,vknot,weights,m.p,m.opacity,m.shininess,m.metallic,m.fresnel0,
- PRCshininess,colors);
+ draw(f,P,uknot,vknot,weights,m.p,m.opacity,m.shininess,m.metallic,
+ m.fresnel0,colors);
if(group)
endgroup3(f);
if(pic != null)