diff options
Diffstat (limited to 'Master/texmf-dist/asymptote/v3d.asy')
-rw-r--r-- | Master/texmf-dist/asymptote/v3d.asy | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/Master/texmf-dist/asymptote/v3d.asy b/Master/texmf-dist/asymptote/v3d.asy new file mode 100644 index 00000000000..5bdd0627d5f --- /dev/null +++ b/Master/texmf-dist/asymptote/v3d.asy @@ -0,0 +1,645 @@ +// Supakorn "Jamie" Rassameemasuang <jamievlin@outlook.com> and +// John C. Bowman + +import three; +import v3dtypes; +import v3dheadertypes; + +struct triangleGroup +{ + triple[] positions; + triple[] normals; + pen[] colors; + + int[][] positionIndices; + int[][] normalIndices; + int[][] colorIndices; +} + +struct pixel +{ + triple point; + real width; +} + +struct CameraInformation +{ + int canvasWidth; + int canvasHeight; + bool absolute; + + triple b; + triple B; + bool orthographic; + real angle; + real Zoom0; + pair viewportshift; + pair viewportmargin; + + light light; + + void setCameraInfo() + { + size(canvasWidth,canvasHeight); + triple center=0.5*(b.z+B.z)*Z; + + if(orthographic) + currentprojection=orthographic(Z,target=center,Zoom0, + viewportshift=viewportshift); + else + currentprojection=perspective(Z,Y,target=center,Zoom0, + degrees(2.0*atan(tan(0.5*angle)/Zoom0)), + viewportshift=viewportshift, + autoadjust=false); + light.specular=light.diffuse; + currentlight=light; + } +} + +transform3 Align(real polar, real azimuth) +{ + return align(dir(degrees(polar),degrees(azimuth))); +} + +struct v3dfile +{ + file xdrfile; + int version; + bool hasCameraInfo=false; + CameraInformation info; + bool singleprecision=false; + + triple[] centers; + material[] materials; + + surface[][][] surfaces; + path3[][][] paths3; + triangleGroup[][][] triangles; + pixel[][] pixels; + + void initSurface(int center, int material) { + if(!surfaces.initialized(center)) + surfaces[center]=new surface[][]; + if(!surfaces[center].initialized(material)) + surfaces[center][material]=new surface[] {new surface}; + } + + void initPath3(int center, int material) { + if(!paths3.initialized(center)) + paths3[center]=new path3[][]; + if(!paths3[center].initialized(material)) + paths3[center][material]=new path3[]; + } + + void initTriangleGroup(int center, int material) { + if (!triangles.initialized(center)) + triangles[center]=new triangleGroup[][]; + if(!triangles[center].initialized(material)) + triangles[center][material]=new triangleGroup[]; + } + + void initPixel(int material) { + if(!pixels.initialized(material)) + pixels[material]=new pixel[]; + } + + void surface(int center, int material, patch p) { + initSurface(center,material); + surfaces[center][material][0].s.push(p); + } + + void primitive(int center, int material, surface s) { + initSurface(center,material); + surfaces[center][material].push(s); + } + + void path3(int center, int material, path3 p) { + initPath3(center,material); + paths3[center][material].push(p); + } + + void triangleGroup(int center, int material, triangleGroup g) { + initTriangleGroup(center,material); + triangles[center][material].push(g); + } + + void pixel(int material, pixel P) { + initPixel(material); + pixels[material].push(P); + } + + void operator init(string name) + { + xdrfile=input(name, mode="xdrgz"); + version=xdrfile; + + int doubleprecision=xdrfile; + singleprecision=doubleprecision == 0; + xdrfile.singlereal(singleprecision); + } + + int getType() + { + return xdrfile; + } + + void setCameraInfo() + { + if(hasCameraInfo) + info.setCameraInfo(); + } + + pen[] readColorData(int size=4, bool alpha=true) + { + xdrfile.singlereal(true); + + xdrfile.dimension(alpha ? 4 : 3); + pen[] newPen=new pen[size]; + for (int i=0; i < size; ++i) + { + newPen[i]=alpha ? rgba(xdrfile) : rgb((real[]) xdrfile); + } + + xdrfile.singlereal(singleprecision); + + return newPen; + } + + CameraInformation processHeader() + { + CameraInformation ci; + + int entryCount=xdrfile; + for (int i=0;i<entryCount;++i) + { + int headerKey=xdrfile; + int headerSz=xdrfile; + + if (headerKey == v3dheadertypes.canvasWidth) + { + ci.canvasWidth=xdrfile; + } + else if (headerKey == v3dheadertypes.canvasHeight) + { + ci.canvasHeight=xdrfile; + } + else if (headerKey == v3dheadertypes.absolute) + { + int val=xdrfile; + ci.absolute=(val != 0); + } + else if (headerKey == v3dheadertypes.minBound) + { + ci.b=xdrfile; + } + else if (headerKey == v3dheadertypes.maxBound) + { + ci.B=xdrfile; + } + else if (headerKey == v3dheadertypes.orthographic) + { + int val=xdrfile; + ci.orthographic=(val != 0); + } + else if (headerKey == v3dheadertypes.angleOfView) + { + ci.angle=xdrfile; + } + else if (headerKey == v3dheadertypes.initialZoom) + { + ci.Zoom0=xdrfile; + } + else if (headerKey==v3dheadertypes.viewportShift) + { + ci.viewportshift=xdrfile; + } + else if (headerKey==v3dheadertypes.viewportMargin) + { + ci.viewportmargin=xdrfile; + } + else if (headerKey==v3dheadertypes.background) + { + ci.light.background=readColorData(1)[0]; + } + else if (headerKey==v3dheadertypes.light) + { + triple position=xdrfile; + ci.light.position.push(position); + ci.light.diffuse.push(rgba(readColorData(1,false)[0])); + } + else + { + xdrfile.dimension(headerSz); + int[] _dmp=xdrfile; + } + } + return ci; + } + + material readMaterial() { + xdrfile.dimension(4); + xdrfile.singlereal(true); + + pen diffusePen=rgba(xdrfile); + pen emissivePen=rgba(xdrfile); + pen specularPen=rgba(xdrfile); + + xdrfile.dimension(3); + real[] params=xdrfile; + real shininess=params[0]; + real metallic=params[1]; + real F0=params[2]; + + xdrfile.singlereal(singleprecision); + + return material(diffusePen,emissivePen,specularPen,1,shininess, + metallic,F0); + } + + triple[][] readRawPatchData() { + triple[][] val; + xdrfile.dimension(4,4); + val=xdrfile; + return val; + } + + triple[][] readRawTriangleData() { + triple[][] val; + + for(int i=0; i < 4; ++i) { + xdrfile.dimension(i+1); + triple[] v=xdrfile; + val.push(v); + } + return val; + } + + void readBezierPatch() { + triple[][] val=readRawPatchData(); + int center=xdrfile; + int material=xdrfile; + surface(center,material,patch(val)); + } + + void readBezierTriangle() { + triple[][] val=readRawTriangleData(); + int center=xdrfile; + int material=xdrfile; + surface(center,material,patch(val,triangular=true)); + } + + triple[] readCenters() { + int centerCount=xdrfile; + xdrfile.dimension(centerCount); + triple[] centersFetched; + if (centerCount>0) + centersFetched=xdrfile; + return centersFetched; + } + + void readBezierPatchColor() { + triple[][] val=readRawPatchData(); + int center=xdrfile; + int material=xdrfile; + pen[] colors=readColorData(4); + surface(center,material,patch(val,colors=colors)); + } + + void readBezierTriangleColor() { + triple[][] val=readRawTriangleData(); + int center=xdrfile; + int material=xdrfile; + pen[] colors=readColorData(3); + surface(center,material,patch(val,triangular=true,colors=colors)); + } + + void readSphere() { + triple origin=xdrfile; + real radius=xdrfile; + + int center=xdrfile; + int material=xdrfile; + + surface s=shift(origin)*scale3(radius)*unitsphere; + s.draw=unitsphere.draw; + primitive(center,material,s); + } + + void readHemisphere() { + triple origin=xdrfile; + real radius=xdrfile; + + int center=xdrfile; + int material=xdrfile; + + real polar=xdrfile; + real azimuth=xdrfile; + + surface s=shift(origin)*Align(polar,azimuth)*scale3(radius)*unithemisphere; + s.draw=unithemisphere.draw; + primitive(center,material,s); + } + + void readDisk() { + triple origin=xdrfile; + real radius=xdrfile; + + int center=xdrfile; + int material=xdrfile; + + real polar=xdrfile; + real azimuth=xdrfile; + + surface s=shift(origin)*Align(polar,azimuth)*scale3(radius)*unitdisk; + s.draw=unitdisk.draw; + primitive(center,material,s); + } + + void readPolygon(int n) + { + xdrfile.dimension(n); + triple[] val=xdrfile; + + int center=xdrfile; + int material=xdrfile; + surface(center,material,patch(val)); + } + + void readPolygonColor(int n) + { + xdrfile.dimension(n); + triple[] val=xdrfile; + + int center=xdrfile; + int material=xdrfile; + + pen[] colors=readColorData(n); + surface(center,material,patch(val,colors=colors)); + } + + void readCylinder() { + triple origin=xdrfile; + real radius=xdrfile; + real height=xdrfile; + + int center=xdrfile; + int material=xdrfile; + + real polar=xdrfile; + real azimuth=xdrfile; + + int core=xdrfile; + + transform3 T=shift(origin)*Align(polar,azimuth)* + scale(radius,radius,height); + if(core != 0) + path3(center,material,T*(O--Z)); + + surface s=T*unitcylinder; + s.draw=unitcylinder.draw; + primitive(center,material,s); + } + + void readTube() { + xdrfile.dimension(4); + triple[] g=xdrfile; + + real width=xdrfile; + int center=xdrfile; + int material=xdrfile; + + int core=xdrfile; + + if(core != 0) + path3(center,material,g[0]..controls g[1] and g[2]..g[3]); + + surface s=tube(g[0],g[1],g[2],g[3],width); + s.draw=drawTube(g,width,info.b,info.B); + primitive(center,material,s); + } + + void readCurve() { + xdrfile.dimension(4); + triple[] points=xdrfile; + + int center=xdrfile; + int material=xdrfile; + + path3(center,material, + points[0]..controls points[1] and points[2]..points[3]); + } + + void readLine() { + xdrfile.dimension(2); + triple[] points=xdrfile; + + int center=xdrfile; + int material=xdrfile; + + path3(center,material,points[0]--points[1]); + } + + void readTriangles() { + triangleGroup g; + + int nI=xdrfile; + + int nP=xdrfile; + xdrfile.dimension(nP); + g.positions=xdrfile; + + int nN=xdrfile; + xdrfile.dimension(nN); + g.normals=xdrfile; + + int explicitNI=xdrfile; + + int nC=xdrfile; + int explicitCI; + if (nC > 0) { + g.colors=readColorData(nC); + explicitCI=xdrfile; + } + + g.positionIndices=new int[nI][3]; + g.normalIndices=new int[nI][3]; + int[][] colorIndices; + if (nC > 0) + g.colorIndices=new int[nI][3]; + + for (int i=0; i < nI; ++i) { + xdrfile.dimension(3); + g.positionIndices[i]=xdrfile; + g.normalIndices[i]=explicitNI != 0 ? xdrfile : + g.positionIndices[i]; + g.colorIndices[i]=nC > 0 && explicitCI != 0 ? xdrfile : + g.positionIndices[i]; + } + int center=xdrfile; + int material=xdrfile; + triangleGroup(center,material,g); + } + + void readPixel() { + pixel P; + P.point=xdrfile; + P.width=xdrfile; + int material=xdrfile; + pixel(material,P); + } + + void process() + { + static bool processed; + if(processed) return; + + while (!eof(xdrfile)) + { + int ty=getType(); + if(ty == v3dtypes.header) + { + hasCameraInfo=true; + info=processHeader(); + } + else if(ty == v3dtypes.material) + { + materials.push(readMaterial()); + } + else if(ty == v3dtypes.bezierPatch) + { + readBezierPatch(); + } + else if(ty == v3dtypes.bezierTriangle) + { + readBezierTriangle(); + } + else if(ty == v3dtypes.bezierPatchColor) + { + readBezierPatchColor(); + } + else if(ty == v3dtypes.bezierTriangleColor) + { + readBezierTriangleColor(); + } + else if(ty == v3dtypes.quad) + { + readPolygon(4); + } + else if(ty == v3dtypes.quadColor) + { + readPolygonColor(4); + } + else if(ty == v3dtypes.triangle) + { + readPolygon(3); + } + else if(ty == v3dtypes.triangleColor) + { + readPolygonColor(3); + } + else if(ty == v3dtypes.sphere) + { + readSphere(); + } + else if(ty == v3dtypes.halfSphere) + { + readHemisphere(); + } + else if(ty == v3dtypes.cylinder) + { + readCylinder(); + } + else if(ty == v3dtypes.tube) + { + readTube(); + } + else if(ty == v3dtypes.disk) + { + readDisk(); + } + else if(ty == v3dtypes.curve) + { + readCurve(); + } + else if(ty == v3dtypes.line) + { + readLine(); + } + else if(ty == v3dtypes.triangles) + { + readTriangles(); + } + else if(ty == v3dtypes.centers) + { + centers=readCenters(); + } + else if(ty == v3dtypes.pixel) + { + readPixel(); + } + else + { + // abort("Unknown type:"+string(ty)); + } + } + processed=true; + } +} + +void importv3d(string name) +{ + if(name == stripextension(name)) name += ".v3d"; + v3dfile xf=v3dfile(name); + xf.process(); + xf.setCameraInfo(); + + for(int c=0; c < xf.surfaces.length; ++c) { + triple center=c > 0 ? xf.centers[c-1] : O; + render r=render(interaction(c == 0 ? Embedded : Billboard,center=center)); + surface[][] S=xf.surfaces[c]; + for(int m=0; m < S.length; ++m) + if(S.initialized(m)) + draw(S[m],xf.materials[m],r); + } + + for(int c=0; c < xf.paths3.length; ++c) { + triple center=c > 0 ? xf.centers[c-1] : O; + render r=render(interaction(c == 0 ? Embedded : Billboard,center=center)); + path3[][] G=xf.paths3[c]; + for(int m=0; m < G.length; ++m) + if(G.initialized(m)) { + material material=material(xf.materials[m]); + material.p[0] += thin(); + draw(G[m],material,currentlight,r); + } + } + + for(int c=0;c < xf.triangles.length; ++c) { + triple center=c > 0 ? xf.centers[c-1] : O; + render r=render(interaction(c == 0 ? Embedded : Billboard,center=center)); + triangleGroup[][] groups=xf.triangles[c]; + for(int m=0; m < groups.length; ++m) { + if(groups.initialized(m)) { + material material=xf.materials[m]; + triangleGroup[] triangleGroups=groups[m]; + for(triangleGroup g : triangleGroups) { + if(g.colors.length > 0) + draw(g.positions,g.positionIndices,g.normals,g.normalIndices, + g.colors,g.colorIndices,r); + else + draw(g.positions,g.positionIndices,g.normals,g.normalIndices, + material,r); + } + } + } + } + + for(int m=0; m < xf.pixels.length; ++m) { + if(xf.pixels.initialized(m)) { + material material=xf.materials[m]; + pixel[] pixels=xf.pixels[m]; + for(pixel P : pixels) + pixel(P.point,material.p[0],P.width); + } + } +} |