ウィンドウは表示されるのですが、読み込んだはずのデータが表示されず真っ白のままです。
バイナリ形、アスキー型どちらにも対応しております。
以下にコードを載せます。
abc.h
#define X 0
#define Y 1
#define Z 2
#define A 0
#define B 1
#define C 2
#define D 3
#define EPS 0.00001 //十分に微小な値
#define LARGE 1000000 //十分に大きな値
#define PI 3.141592
#define MAX_NUM_POINTS 1000000
#define MAX_NUM_EDGES 1000000
#define MAX_NUM_TRIANGLES 1000000
//一時的に利用する点の構造体
typedef struct tmp_point{
double coord[3];//座標
unsigned int index;//点に付随するインデックス
}tmp_point;
//一時的に利用する辺の構造体
typedef struct tmp_edge{
unsigned int start;
unsigned int end;
tmp_edge *next;
} tmp_edge;
#include<iostream>
#include<tchar.h>
#include<math.h>
#include"abc.h"
//vec0とvec1の内積の計算
double dot(double vec0[],double vec1[])
{
return (vec0[X] * vec1[X] + vec0[Y] * vec1[Y] + vec0[Z] * vec1[Z]);
}
//vec0とvec1の外積
void cross(double vec0[],double vec1[],double vec2[])
{
vec2[X] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
vec2[Y] = vec0[Z] * vec1[X] - vec0[X] * vec1[Z];
vec2[Z] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
}
//ベクトルの正規化
void normVec(double vec[])
{
double norm;
norm = sqrt(vec[X] * vec[X] + vec[Y] * vec[Y] + vec[Z] * vec[Z]);
vec[X]/=norm;
vec[Y]/=norm;
vec[Z]/=norm;
}
//単位法線ベクトルの計算
void normal(double p0[],double p1[],double p2[],double normal[])
{
unsigned int i;
double v0[3],v1[3];
//基本となる2つのベクトルの生成
for(i = 0; i < 3; i++){
v0[i] = p2[i] - p1[i];
v1[i] = p0[i] - p1[i];
}
//生成したベクトルの外積を計算
cross(v0,v1,normal);
//外積によって得られた法線ベクトルを正規化
normVec(normal);
}
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include <tchar.h>
#include"abc.h"
//点とその個数、一時的な利用
tmp_point *point_array[3*MAX_NUM_TRIANGLES];
unsigned int num_tmp_points;
//点に接続する辺のリスト、一時的な利用
tmp_edge **connecting_edge;
//点
double point[MAX_NUM_POINTS][3];
unsigned int num_points;
//辺
unsigned int edge[MAX_NUM_EDGES][2];
unsigned int num_edges;
//三角形ポリゴンの頂点と周辺の辺
unsigned int triangle[MAX_NUM_TRIANGLES][3];
unsigned int triangle_edge[MAX_NUM_TRIANGLES][3];
unsigned int num_triangles;
//アスキー形式のSTLファイルの読み込み
//読み込まれた座標は一時的にpoint_arrayに収納される
bool readASCIISTLFile(const char* STL_file)
//const char* STL_fileはファイル名
{
double x,y,z;
char line[100];
static char dummy[100];
FILE *in;
tmp_point *tmp_pnt;
//stlファイルオープン
in=fopen(STL_file, "r");
if(in == NULL)
return false;
//ファイルから座標の読み込み
printf("ファイルを読み込みます\n");
num_tmp_points = 0;
num_triangles = 0;
while(fgets(line,100,in) != NULL){
//vertexが見つかるまで読み飛ばし
if(strstr(line,"vertex") == NULL)
continue;
//連続する3頂点を読み込み
sscanf(line, "%s, %lf, %lf, %lf",dummy, &x, &y, &z);
tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
point_array[num_tmp_points] = tmp_pnt;
tmp_pnt->coord[X] = x;
tmp_pnt->coord[Y] = y;
tmp_pnt->coord[Z] = z;
tmp_pnt->index = num_tmp_points;
num_tmp_points++;
fgets(line,100,in);
sscanf(line,"%s, %lf, %lf, %lf",dummy, &x, &y, &z);
tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
point_array[num_tmp_points] = tmp_pnt;
tmp_pnt->coord[X] = x;
tmp_pnt->coord[Y] = y;
tmp_pnt->coord[Z] = z;
tmp_pnt->index = num_tmp_points;
num_tmp_points++;
fgets(line,100,in);
sscanf(line,"%s, %lf, %lf, %lf",dummy, &x, &y, &z);
tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
point_array[num_tmp_points] = tmp_pnt;
tmp_pnt->coord[X] = x;
tmp_pnt->coord[Y] = y;
tmp_pnt->coord[Z] = z;
tmp_pnt->index = num_tmp_points;
num_tmp_points++;
num_triangles++;
}
fclose(in);
if(num_triangles > 0)
printf("完了しました\n");
else
printf("読込に失敗しました\n");
return(num_triangles > 0);
}
//バイナリー形式のSTLファイルの読み込み
//読み込んだ座標は一時的にpoint_arrayに格納される
bool readBinarySTLFile(const char* STL_file)
{
char line[85];
FILE *in;
float *coord;
tmp_point *tmp_pnt;
//STLファイルのオープン
in = fopen(STL_file,"rb");
if(in == NULL)
return false;
//最初の84バイトを読み飛ばす
if(fread(line,1,84,in) != 84){
return false;
}
printf("ファイルを読み込みます\n");
while(fread(line,1,50,in) == 50){
coord=(float *)line;
//連続する3頂点の読み込み
tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
point_array[num_tmp_points] = tmp_pnt;
tmp_pnt->coord[X] = coord[3];
tmp_pnt->coord[Y] = coord[4];
tmp_pnt->coord[Z] = coord[5];
tmp_pnt->index = num_tmp_points;
num_tmp_points++;
tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
point_array[num_tmp_points] = tmp_pnt;
tmp_pnt->coord[X] = coord[6];
tmp_pnt->coord[Y] = coord[7];
tmp_pnt->coord[Z]=coord[8];
tmp_pnt->index = num_tmp_points;
num_tmp_points++;
tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
point_array[num_tmp_points] = tmp_pnt;
tmp_pnt->coord[X] = coord[9];
tmp_pnt->coord[Y] = coord[10];
tmp_pnt->coord[Z] = coord[11];
tmp_pnt->index = num_tmp_points;
num_tmp_points++;
num_triangles++;
}
fclose(in);
if(num_triangles > 0)
printf("完了しました\n");
else
printf("読み込みに失敗しました\n");
return (num_triangles > 0);
}
//点の比較関数
int compare(tmp_point *point0,tmp_point *point1)
//tmp_point *point0,*point1は比較対象の点
{
//X座標値で比較
if(point0->coord[X] < (point1->coord[X]-(EPS)))
return -1;
else if(point0->coord[X] > (point1->coord[X]+(EPS)))
return 1;
//Y座標値で比較
else{
if(point0->coord[Y] < (point1->coord[Y]-(EPS)))
return -1;
else if(point0->coord[Y] > (point1->coord[Y]+(EPS)))
return 1;
//Z座標値で比較
else{
if(point0->coord[Z] < (point1->coord[Z]-(EPS)))
return -1;
else if(point0->coord[Z] > (point1->coord[Z]+(EPS)))
return 1;
else
return 0; //2点を同一とみなす
}
}
}
//点列のクイックソート
void quickSort(int l,int r,tmp_point *point[])
//int l,rはソート範囲の左側と右側のインデックス
//tmp_point *point[]はソート対象の点列
{
int i,j;
tmp_point *m_p, *swap;
if(l<r){
m_p = point[(l+r)/2];
i = l-1;
j = r+1;
while(true){
while(compare(point[++i],m_p) == -1){};
while(compare(point[--j],m_p) == 1){};
if(i >= j)break;
swap = point[i];
point[i] = point[j];
point[j] = swap;
}
quickSort(l,i-1,point);
quickSort(j+1,r,point);
}
}
bool loadSTLFile(const char* STL_file)
{
unsigned int i, j, start,end;
unsigned int tri_index, ver_index;
double ref_pnt[3]={LARGE, LARGE, LARGE};
tmp_edge *ed, *new_ed, *next_ed;
//アスキー型ファイルの読み込み、一時的にpoint_arrayに格納
if(readASCIISTLFile(STL_file))
printf("Triangles: %d ",num_triangles);
//バイナリー形式ファイルの読み込み、一時的にpoint_arrayに格納
else if(readBinarySTLFile(STL_file))
printf("Triangles: %d ",num_triangles);
else{
printf("ファイルが開けません\n");
return(false);
}
//得られた点群をソートし同じ座標の点を一つにまとめる
quickSort(0, num_tmp_points-1 ,point_array);
//ソート済みの点列を先頭からスキャン
num_points=0;
for(i = 0; i <= num_tmp_points; i++){
//最後の点が見つかる、もしくは参照点と異なる点がみつかる
if((i == num_tmp_points)
||(fabs(ref_pnt[X] - (point_array[i]->coord[X])) > (EPS))
||(fabs(ref_pnt[Y] - (point_array[i]->coord[Y])) > (EPS))
||(fabs(ref_pnt[Z] - (point_array[i]->coord[Z])) > (EPS))){
//同一の点を同じ点として登録
end=i;
if(i > 0){
point[num_points][X] = ref_pnt[X];
point[num_points][Y] = ref_pnt[Y];
point[num_points][Z] = ref_pnt[Z];
for(j = start; j < end; j++){
//その点を含むポリゴンが何番目のポリゴンか計算
tri_index=point_array[j]->index/3;
//点がそのポリゴンにおけるいくつめの頂点は計算
ver_index=point_array[j]->index%3;
triangle[tri_index][ver_index] = num_points;
}
num_points++;
}
//参照点の更新
if(end < num_tmp_points){
ref_pnt[X] = point_array[end]->coord[X];
ref_pnt[Y] = point_array[end]->coord[Y];
ref_pnt[Z] = point_array[end]->coord[Z];
start = end;
}
}
}
for(i = 0; i < num_tmp_points; i++)
free(point_array[i]);
//辺の登録
num_edges = 0;
//各点に接続する辺の記録場所の初期化
connecting_edge = (tmp_edge **)malloc(num_points * sizeof(tmp_edge));
for(i = 0; i <num_points; i++)
connecting_edge[i] = NULL;
//各三角形の周辺の辺と登録済みの辺を比較
//i番目のポリゴンデータのj番目の頂点
for(i = 0; i < num_triangles; i++){
for(j = 0; j < 3; j++){
ed = connecting_edge[triangle[i][j]];
while(ed != NULL){
if(((ed->start == triangle[i][j])
&&(ed->end == triangle[i][(j+1)%3]))
||((ed->start == triangle[i][(j+1)%3])
&&(ed->end == triangle[i][j])))
goto try_next;
ed = ed->next;
}
//未登録の辺を見つけて登録
edge[num_edges][0] = triangle[i][j];
edge[num_edges][1] = triangle[i][(j+1)%3];
//辺を三角形に登録
triangle_edge[i][j] = num_edges;
num_edges++;
//同時に点にも登録
new_ed = (tmp_edge *)malloc(sizeof(tmp_edge));
new_ed->start = triangle[i][j];
new_ed->end = triangle[i][(j+1)%3];
new_ed->next = connecting_edge[triangle[i][j]];
connecting_edge[triangle[i][j]] = new_ed;
new_ed=(tmp_edge *)malloc(sizeof(tmp_edge));
new_ed->start = triangle[i][(j+1)%3];
new_ed->end = triangle[i][j];
new_ed->next = connecting_edge[triangle[i][(j+1)%3]];
connecting_edge[triangle[i][(j+1)%3]] = new_ed;
try_next:;
}
}
for(i = 0; i < num_points; i++){
ed = connecting_edge[i];
while(ed != NULL){
next_ed = ed->next;
free(ed);
ed = next_ed;
}
}
free(connecting_edge);
printf("Edges:%d ",num_edges);
printf("Points:%d \n",num_points);
return(true);
}
#include<iostream>
#include<tchar.h>
#include<gl/glut.h>
#include<math.h>
#include"abc.h"
//視点位置に関する変数
double eye[3];
double center[3]={0.0, 0.0, 0.0};
double up[3];
//生投影の座標系
double x_axis[3], y_axis[3], z_axis[3];
//ウィンドウ上の座標とモデル座標の変換に用いるデータ
double corner[3];
double pixel_size, ref_far, ref_near;
//照明
GLfloat light_pos[4];
//点
extern double point[MAX_NUM_POINTS][3];
extern unsigned int num_points;
//三角形ポリゴン
extern unsigned int triangle[MAX_NUM_TRIANGLES][3];
extern unsigned int num_triangles;
//基本的な図形計算
extern double dot(double vec0[], double vec1[]);
extern void cross(double vec0[], double vec1[], double vec2[]);
extern void normVec(double vec[]);
extern void normal(double p0[], double p1[], double p2[], double normal[]);
//投影処理用の行列定義
void defineViewMatrix(double phi, double theta, unsigned int width,
unsigned int height,double margin)
//double phi,theta 方位角と仰角
//unsigned int width,height ウィンドウサイズ
//double margin 表示の余裕
{
unsigned int i,j;
double c, s, xy_dist;
double vec[3];
double left, right, bottom, top, farVal, nearVal;
double dx, dy, d_aspect, w_aspect, d;
//視点の設定
eye[Z] = sin(theta * PI / 180.0);
xy_dist = cos(theta * PI / 180.0);
c = cos(phi * PI / 180.0);
s = sin(phi * PI / 180.0);
eye[X] = xy_dist * c;
eye[Y] = xy_dist * s;
up[X] = -c * eye[Z];
up[Y] = -s * eye[Z];
up[Z] = s * eye[Y] + c * eye[X];
normVec(up);
//視点を原点とする座標系の定義
for(i = 0; i < 3; i++)
z_axis[i] = eye[i] - center[i];
normVec(z_axis);
cross(up,z_axis,x_axis);
normVec(z_axis);
cross(up,z_axis,x_axis);
normVec(x_axis);
cross(z_axis,x_axis,y_axis);
//left,right,bottom,top,nearVal,farValの決定
left = bottom = farVal = 10000.0;
right = top = nearVal = -10000.0;
for(i = 0; i < num_points; i++){
for(j = 0; j < 3; j++)
vec[j] = point[i][j] - eye[j];
if(dot(x_axis,vec) < left)
left = dot(x_axis,vec);
if(dot(x_axis,vec) > right)
right = dot(x_axis,vec);
if(dot(y_axis,vec) < bottom)
bottom = dot(x_axis,vec);
if(dot(y_axis,vec) < top)
top = dot(y_axis,vec);
if(dot(z_axis,vec) < farVal)
farVal = dot(z_axis,vec);
if(dot(z_axis,vec) > nearVal)
nearVal = dot(z_axis,vec);
}
//図形の周辺に5%ほど余裕を与える
margin += (right-left)*0.05;
left -= margin;
right += margin;
bottom -= margin;
top += margin;
farVal -= margin;
nearVal += margin;
ref_far = farVal;
ref_near = nearVal;
//表示範囲のアスペクト比とウィンドウのアスペクト比の比較
dx = right - left;
dy = top - bottom;
d_aspect = dy/dx;
w_aspect = (double)height/(double)width;
//各ピクセルの実サイズ
pixel_size = (right-left)/width;
//視体積の左下隅奥の座標を記録
for(i = 0;i < 3;i++){
corner[i] = eye[i] + bottom * y_axis[i] + left * x_axis[i]
+ farVal * z_axis[i];
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(left, right, bottom, top, -nearVal, -farVal);
glViewport(0, 0, width, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye[X], eye[Y], eye[Z], center[X], center[Y], center[Z],
up[X], up[Y], up[Z]);
}
//モデル表示関数
void displayModel(void)
{
unsigned int i;
double nrml_vec[3];
//光源の設定
light_pos[0] = (float)eye[X];
light_pos[1] = (float)eye[Y];
light_pos[2] = (float)eye[Z];
light_pos[3] = 0.0f;
glLightfv(GL_LIGHT0, GL_POSITION,light_pos);
//描写処理
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
for(i = 0; i < num_triangles; i++){
normal(point[triangle[i][0]],point[triangle[i][1]],
point[triangle[i][2]], nrml_vec);
if(dot(nrml_vec, z_axis) > 0.0)
glNormal3dv(nrml_vec);
else
glNormal3d(-nrml_vec[X], -nrml_vec[Y], -nrml_vec[Z]);
glVertex3dv(point[triangle[i][0]]);
glVertex3dv(point[triangle[i][1]]);
glVertex3dv(point[triangle[i][2]]);
}
glEnd();
glFlush();
}
//ピクセルの横方向と縦方向の番地(h,v)とデプス値dから対応するモデル座標を得る
void pixelCoordToModelCoord(int h,int v,float d,double point[])
{
unsigned int i;
//cornerには左下隅奥に対応するモデル座標が格納
//デプス値はnearが0.0,farが1.0に対応するように正規化してある
for(i = 0; i < 3; i++){
point[i] = corner[i] + pixel_size * h * x_axis[i]
+ pixel_size * v * y_axis[i] + (ref_near - ref_far) * (1.0-d) * z_axis[i];
}
}
#include<gl/glut.h>
#include<iostream>
#include<tchar.h>
#include<math.h>
#include"abc.h"
//STLデータのファイル名
#define STL_FILE "/*stlファイル名*/"
//視点位置
#define PHI 30.0
#define THETA 90.0
double phi=PHI;
double theta=THETA;
//ウィンドウサイズ
#define INIT_X_POS 128
#define INIT_Y_POS 128
#define INIT_WIDTH 600
#define INIT_HEIGHT 600
//画面の縦横サイズ
unsigned int window_height, window_width;
//球や円筒形を多面化近似する際の分割数
#define DIV 64
//表示モード
#define DISPLAY_MODEL 0
unsigned int display_mode = DISPLAY_MODEL;
//オフセット半径
double radius=10.0;
//マウス処理
int mouse_old_x,mouse_old_y;
bool motion_p;
//点
extern double point[MAX_NUM_POINTS][3];
extern unsigned int num_points;
//辺
extern unsigned int edge[MAX_NUM_EDGES][2];
extern unsigned int num_edged;
//三角形ポリゴンの頂点
extern unsigned int triangle[MAX_NUM_TRIANGLES][3];
extern unsigned int num_triangles;
//STLファイルの読み込み
extern bool loadSTLFile(const char* STL_file);
//基本的な図形計算
extern void cross(double vec0[], double vec1[], double vec2[]);
extern void normVec(double vec[]);
extern void normal(double p0[], double p1[], double p2[], double normal[]);
//基本的な表示関数
extern void defineViewMatrix(double phi, double theta, unsigned int width,
unsigned int height, double margin);
extern void displayModel(void);
extern void pixelCoordToModelCoord(int h, int v, float d, double point[]);
//表示
void display (void)
{
switch(display_mode){
case DISPLAY_MODEL:
defineViewMatrix(phi, theta, window_width, window_height, radius);
displayModel();
break;
default:
break;
}
}
//キー処理
void keyboard(unsigned char key, int x, int y)
{
switch(key){
case'q':
case'Q':
case'\033':
exit(0);
//STLファイルの読み込み
case'r':
case'R':
if(!loadSTLFile(STL_FILE))
break;
display_mode = DISPLAY_MODEL;
glutPostRedisplay();
break;
//STLモデル表示
case'd':
case'D':
display_mode = DISPLAY_MODEL;
glutPostRedisplay();
break;
default:
break;
}
}
//OpenGL関係の初期設定
void initGL(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
void resize(int width,int height)
{
printf("Size %d × %d\n",width,height);
window_width = width;
window_height = height;
}
//マウスボタン処理
void mouse_button(int button,int state,int x,int y)
{
if((state == GLUT_DOWN) && (button == GLUT_LEFT_BUTTON))
motion_p = true;
else if (state==GLUT_UP)
motion_p = false;
mouse_old_x = x;
mouse_old_y = y;
}
//マウスの移動処理
void mouse_motion(int x,int y)
{
int dx, dy;
dx = x-mouse_old_x;
dy = y-mouse_old_y;
if(motion_p){
phi -= dx * 0.2;
theta += dy * 0.2;
}
mouse_old_x = x;
mouse_old_y = y;
glutPostRedisplay();
}
//メイン関数
int main(int argc,char *argv[])
{
printf("'R'でファイル読み込み、'D'でモデル表示、'Q'で終了\n");
glutInitWindowPosition(128,128);
glutInitWindowSize(800,800);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH);
glutCreateWindow("Preview");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutReshapeFunc(resize);
glutMouseFunc(mouse_button);
glutMotionFunc(mouse_motion);
initGL();
glutMainLoop();
return 0;
}