I am new to Asymptote, and is very imressed so far. The program that follows is a first attempt at rendering a 3D figure and the code was pillaged from various examples. It works more or less, but I am sure there are much better ways to do this. I would appreciated it a lot if you can point me to better routines or examples.
I there a way to implement light for better shading?
I am new to Asymptote, and is very imressed so far. The program that follows is a first attempt at rendering a 3D figure and the code was pillaged from various examples. It works more or less, but I am sure there are much better ways to do this. I would appreciated it a lot if you can point me to better routines or examples.
I there a way to implement light for better shading?
Thank you very much
Danie
//////////////////////////////////////////////////////////
import three;
//currentprojection=orthographic(1600,800,400);
currentprojection=perspective((1600,800,400)); //Far away!
typedef path3[] Shape;
Shape operator *(transform3 T, Shape p){
Shape pt;
for(int i=0;i<p.length;++i) pt[i]=T*p[i];
return pt;
}
path3 buildpath(triple[] T){
path3 P;
P = T[0];
for(int i=1; i<T.length; ++i){P = P -- T[i];}
return P;
}
face[] drawshapes(face[] F, Shape[] Shp, pen fcol=white, pen dcol=black+0.3bp, real op=1){
face[] faces;
faces.append(F);
for(int i=0; i<Shp.length; ++i){
for(int j=0; j<Shp[i].length; ++j) {
picture pic=faces.push(Shp[i][j]);
filldraw(pic,Shp[i][j], fcol+opacity(op), dcol);
}
}
return faces;
}
Shape BuildCylinder(real R=1.0, real H=1.0, int n=18, transform3 T=scale3(1)){
Shape Cyl;
triple[] CTop;
triple[] CBot;
void Vertex(real x,real y, real z){ CBot.push((x,y,0)); }
for(int i=0;i<n+1;++i){Vertex(R*cos(2pi*i/n), R*sin(2pi*i/n),0);}
CTop = CBot+(0,0,H);
for(int i=0;i<n;++i){Cyl.push(CBot[i]--CBot[i+1]--CTop[i+1]--CTop[i]--cycle3);}
path3 P = buildpath(CBot)--cycle3;
Cyl.push(P);
Cyl.push(shift(H*Z)*P);
return T*Cyl;
}
Shape BuildSlab(real x=1.0, real y=1.0, real z=1.0, transform3 T=scale3(1)){
Shape Slab;
Slab[0] = (0,0,0)--(1,0,0)--(1,1,0)--(0,1,0)--cycle3;
Slab[1] = (0,0,0)--(1,0,0)--(1,0,1)--(0,0,1)--cycle3;
Slab[2] = (1,0,0)--(1,1,0)--(1,1,1)--(1,0,1)--cycle3;
Slab[3] = (1,1,0)--(0,1,0)--(0,1,1)--(1,1,1)--cycle3;
Slab[4] = (0,1,0)--(0,0,0)--(0,0,1)--(0,1,1)--cycle3;
Slab[5] = (0,0,1)--(1,0,1)--(1,1,1)--(0,1,1)--cycle3;
return T*scale(x,y,z)*Slab;
}
size(10cm,0);
real Blen = 360;
real Bwdt = 30;
real Bhgt = 3;
real Clen = 130;
real Cwdt = 100;
real Chgt = 100;
real cylr = 7.5;
real cylh = 37.0 ;
Shape slab1 = BuildSlab(Blen,Bwdt,Bhgt, shift(-Bwdt/2*Y - Bhgt/2*Z + Clen/2*X));
Shape slab2 = BuildSlab(Clen,Cwdt,Chgt, shift(-Cwdt/2*Y - Chgt/2*Z - Clen/2*X));
Shape cyl1 = BuildCylinder(R=cylr, H=cylh, shift(400*X - (cylh/2)*Z));
Shape[] Sarr1={slab1,slab2};
Shape[] Sarr2={cyl1};
face[] faces;
faces = drawshapes(faces, Sarr1, fcol=gray(0.8), dcol=black+0.25bp, op=0.8 );
faces = drawshapes(faces, Sarr2, fcol=yellow+white, dcol=black+0.25bp, op=0.8 );
add(faces);
shipout(bbox(3mm,white));
//////////////////////////////////////////////////////////
Yes, it is easy to add lighting. Just change your drawshapes routine to:
import light;
face[] drawshapes(face[] F, Shape[] Shp, pen fcol=white, pen dcol=black+0.3bp, real op=1){
face[] faces;
faces.append(F);
for(int i=0; i<Shp.length; ++i){
for(int j=0; j<Shp[i].length; ++j) {
path3 g=Shp[i][j];
picture pic=faces.push(g);
filldraw(pic,g,currentlight.intensity(faces[faces.length-1].point)*fcol+opacity(op), dcol);
}
}
return faces;
}