Ply 形式のファイルを STL 形式に変換
変換したいだけならば、meshlab を利用するのが楽. Color STL 形式を作りたいと思い、プログラムを作成.
STL ファイルの情報: https://orion.math.iastate.edu/burkardt/data/stl/stl.html
コンパイル手順
gcc -o a.out a.cc -lm

使用法
- Ply ファイルの準備
60 Excellent Free 3D Model Websites http://www.hongkiat.com/blog/60-excellent-free-3d-model-websites/
- meshlab を用いて前処理
- meshlab を起動.
- Import Mesh でファイルを読み込む
- Export Mesh As で ply 形式を選ぶ.normal にチェックする.binary のチェックを外す.
次のような形式に変換
- その後、下のプログラムを利用.
ソースコード
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> static void Error(char* msg) { fputs(msg,stderr); fputc('\n',stderr); exit(1); } #define STR_LEN 256 static char line[STR_LEN]; static void Scan(FILE* file) { char str[STR_LEN]; for (;;) { if (fgets(line,STR_LEN,file)==NULL) Error("unexpected end of file."); if (line[strlen(line)-1]!='\n') Error("missing end of line."); if (sscanf(line,"%s",str)==1 && strcmp(str,"comment")) return; } } static int CheckElement(FILE* file, char* element) { char str[3][STR_LEN]; int number; Scan(file); fprintf(stderr, "%s\n", line); if (sscanf(line,"%s %s %s",str[0],str[1],str[2])!=3 || strcmp(str[0],"element") || strcmp(str[1],element) || sscanf(str[2],"%d",&number)!=1 || number<=0) { fprintf(stderr,"bad element specification for %s (number = %d) \n",element, number); exit(1); } return number; } static void CheckProperty(FILE* file, char* type, char* name, char* element) { char str[3][STR_LEN]; Scan(file); if (sscanf(line,"%s %s %s",str[0],str[1],str[2])!=3 || strcmp(str[0],"property") || strcmp(str[1],type) || strcmp(str[2],name)) { fprintf(stderr,"bad property specification for %s, (line = %s)\n",element, line); exit(1); } } #define MA(noe,ptr) malloc((noe)*sizeof(*(ptr))) typedef struct _vertex { double x; double y; double z; double nx; double ny; double nz; int r; int g; int b; int alpha; } vertex; typedef struct _face { int v0; int v1; int v2; } face; int main(int argc, char** argv) { FILE *zcp,*stl; char str[10][STR_LEN]; int vertices, faces; // int vertices,faces,face,vertex,idx,R,G,B; // double x10,x20,y10,y20,z10,z20,nx,ny,nz,n; // short flag; if (argc!=3) Error("usage : zcp_stl ZCP STL"); if (argv[1][0]=='-') zcp=stdin; else if ((zcp=fopen(argv[1],"rb"))==NULL) Error("file not found."); if (fgetc(zcp)!='p' || fgetc(zcp)!='l' || fgetc(zcp)!='y') Error("bad magic number."); Scan(zcp); if (sscanf(line,"%s %s %s",str[0],str[1],str[2])!=3 || strcmp(str[0],"format") || // strcmp(str[1],"binary_little_endian") || strcmp(str[1],"ascii") || strcmp(str[2],"1.0")) Error("bad format specification."); vertices=CheckElement(zcp,"vertex"); CheckProperty(zcp,"float","x","vertex"); CheckProperty(zcp,"float","y","vertex"); CheckProperty(zcp,"float","z","vertex"); CheckProperty(zcp,"float","nx","vertex"); CheckProperty(zcp,"float","ny","vertex"); CheckProperty(zcp,"float","nz","vertex"); faces=CheckElement(zcp,"face"); Scan(zcp); if (sscanf(line,"%s %s %s %s %s", str[0],str[1],str[2],str[3],str[4])!=5 || strcmp(str[0],"property") || strcmp(str[1],"list") || strcmp(str[2],"uchar") || strcmp(str[3],"int") || strcmp(str[4],"vertex_indices")) Error("bad vertex index specification for face."); CheckProperty(zcp,"uchar","red","vertex"); CheckProperty(zcp,"uchar","green","vertex"); CheckProperty(zcp,"uchar","blue","vertex"); CheckProperty(zcp,"uchar","alpha","vertex"); Scan(zcp); if (sscanf(line,"%s",str[0])!=1 || strcmp(str[0],"end_header")) Error("missing end of header."); vertex *XYZ = (vertex *)malloc(sizeof(vertex) * vertices); int i; for (i=0; i<vertices; i++) { Scan(zcp); sscanf(line,"%s %s %s %s %s", str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7], str[8], str[9] ); XYZ[i].x = atof(str[0]); XYZ[i].y = atof(str[1]); XYZ[i].z = atof(str[2]); XYZ[i].nx = atof(str[3]); XYZ[i].ny = atof(str[4]); XYZ[i].nz = atof(str[5]); XYZ[i].r = atoi(str[6]); XYZ[i].g = atoi(str[7]); XYZ[i].b = atoi(str[8]); XYZ[i].alpha = atoi(str[9]); } face *F = (face *)malloc(sizeof(face) * faces); for (i=0; i<faces; i++) { Scan(zcp); sscanf(line,"%s %s %s %s", str[0], str[1], str[2], str[3]); F[i].v0 = atoi(str[1]); F[i].v1 = atoi(str[2]); F[i].v2 = atoi(str[3]); } // for debug // printf("%f %f %f\n", XYZ[0].x, XYZ[0].y, XYZ[0].z ); // printf("%d %d %d\n", F[0].v0, F[0].v1, F[0].v2 ); if (argv[2][0]=='-') stl=stdout; else if ((stl=fopen(argv[2],"w"))==NULL) Error("file not stored."); // header fputs("solid \n", stl); for (i=0; i<faces; i++) { double x10 = XYZ[F[i].v1].x - XYZ[F[i].v0].x; double x20 = XYZ[F[i].v2].x - XYZ[F[i].v0].x; double y10 = XYZ[F[i].v1].y - XYZ[F[i].v0].y; double y20 = XYZ[F[i].v2].y - XYZ[F[i].v0].y; double z10 = XYZ[F[i].v1].z - XYZ[F[i].v0].z; double z20 = XYZ[F[i].v2].z - XYZ[F[i].v0].z; double nx=y10*z20-z10*y20; double ny=z10*x20-x10*z20; double nz=x10*y20-y10*x20; double n=sqrt(nx*nx+ny*ny+nz*nz); fprintf(stl, "facet normal %f %f %f\n", nx/n, ny/n, nz/n ); fprintf(stl, "outer loop\n"); fprintf(stl, "vertex %f %f %f %d %d %d\n", XYZ[F[i].v0].x, XYZ[F[i].v0].y, XYZ[F[i].v0].z, XYZ[F[i].v0].r, XYZ[F[i].v0].g, XYZ[F[i].v0].b ); fprintf(stl, "vertex %f %f %f %d %d %d\n", XYZ[F[i].v1].x, XYZ[F[i].v1].y, XYZ[F[i].v1].z, XYZ[F[i].v1].r, XYZ[F[i].v1].g, XYZ[F[i].v1].b ); fprintf(stl, "vertex %f %f %f %d %d %d\n", XYZ[F[i].v2].x, XYZ[F[i].v2].y, XYZ[F[i].v2].z, XYZ[F[i].v2].r, XYZ[F[i].v2].g, XYZ[F[i].v2].b ); fprintf(stl, "endloop\n"); fprintf(stl, "endfacet\n"); } // end fputs("endsolid \n", stl); fclose(stl); // if ( XYZ != NULL ) { free(XYZ); } if ( F != NULL ) { free(F); } return 0; }