また新たな質問として質問することとしました。
頂点の法線を単純に頂点を共有するメッシュの面法線を平均して求めて陰影をつけたいと思っていますが書き方がわからず苦戦しています。
アドバイスお願いします。
#include"stlreader.h"
#define STL_FILE "C:\\Users\\onower\\Desktop\\nsx_concept_LOW.stl"
using namespace std;
float light_pos[] = { -5.0, 5.0, 5.0, 1.0 };
//プロトタイプ宣言
void display(void);
void reshape(int w, int h);
void draw();
void init();
void DRAW_XYZ();
void MouseWheel(int wheel, int direction, int x, int y);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);
Triangle *triangles;
int num;
STLreader stlreader;
int rate = 1.0;
double xAngle = 0.0, yAngle = 0.0;
int main(int argc, char *argv[])
{
glutInitWindowPosition(128, 128);
glutInitWindowSize(800, 800);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("argv[0]");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutMouseWheelFunc(MouseWheel);
// glutKeyboardFunc(keyboard);
glutMainLoop();
if (triangles)
delete[] triangles;
return 0;
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(10.0 * rate,15.0 * rate ,10.0 * rate, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //視点の設定
//glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
glRotated(xAngle, 1, 0, 0);
glRotated(yAngle, 0, 1, 0);
draw(); //描画
glutSwapBuffers(); //ウィンドウに出力
//double* getNormalVert(Triangle trinangles);
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h); //ビューポートの設定
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0); //視野の設定
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void draw()
{
DRAW_XYZ(); //XYZ軸の描画
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
for (int i = 0; i < num; i++) //stlデータの描画
{
glNormal3dv(triangles[i].nornVec);
glVertex3dv(triangles[i].pnt1);
glVertex3dv(triangles[i].pnt2);
glVertex3dv(triangles[i].pnt3);
}
glEnd();
glFlush();
}
void init()
{
if (triangles)
delete[] triangles;
num = stlreader.countTriangles(string(STL_FILE)); //stlデータを構成しているポリゴンの数のをカウント
if (!(num = stlreader.countTriangles(string(STL_FILE))))
return;
triangles = new Triangle[num];
stlreader.readASCIISTLFile(STL_FILE, triangles);
stlreader.readBinarySTLFile(STL_FILE, triangles);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void DRAW_XYZ()
{
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glDisable(GL_DEPTH_TEST);
glDisable(GL_NORMALIZE);
glBegin(GL_LINES);
glColor3d(0, 1, 0);//x軸緑
glVertex2d(-1000, 0);
glVertex2d(1000, 0);
glColor3d(1, 0, 0);//y軸赤
glVertex2d(0, -1000);
glVertex2d(0, 1000);
glColor3d(0, 0, 1);//z軸青
glVertex3d(0, 0, -1000);
glVertex3d(0, 0, 1000);
glEnd();
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
//glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
}
void MouseWheel(int wheelnumber, int direction, int x, int y)
{
if (direction > 0)
{
rate++;
}
else
{
rate--;
}
glutPostRedisplay();
}
int xStart, yStart;
bool mouseFlag = GL_FALSE;
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON &&state == GLUT_DOWN)
{
xStart = x;
yStart = y;
mouseFlag = GL_TRUE;
}
else
{
mouseFlag = GL_FALSE;
}
}
void motion(int x, int y)
{
int xdis, ydis;
double a = 0.5;
if (mouseFlag == GL_FALSE)return;
xdis = x - xStart;
ydis = y - yStart;
xAngle += (double)ydis * a;
yAngle += (double)xdis * a;
xStart = x;
yStart = y;
glutPostRedisplay();
}
#include <iostream>
#include <cmath>
#include <string>
#include <fstream>
using namespace std;
struct vert
{
double pnt1[3];
double pnt2[3];
double pnt3[3];
};
struct vert4
{
double pnt1[4];//x,y,z,w
double pnt2[4];
double pnt3[4];
};
struct Triangle {
double nornVec[3];
double pnt1[3];
double pnt2[3];
double pnt3[3];
unsigned int index;
};
class STLreader
{
unsigned int num_tmp_points;//一時的な変数
unsigned int num_triangles;//三角形の数
public:
static int countTriangles(string filename)
{
//STLファイルのオープン
ifstream ifs;
char line[80];
ifs.open(filename);
if (ifs.fail())
return false;
string str;
int count = 0;
int a;
getline(ifs, str);
//int h = str.find("solid");
if (str.find("solid")==-1){
ifs.close();
ifs.open(filename, ios::binary);
if (ifs.fail())
return false;
ifs.read(line, 80);
ifs.read(line, 4);
return *(int *)line;
}
while (getline(ifs, str)){
a = str.find("normal");
if (a > 0)
count++;
}
ifs.close();
return count;
};
bool readASCIISTLFile(string filename, Triangle *values)
{
//STLファイルのオープン
ifstream ifs(filename);
if (ifs.fail())
return false;
//vector<mesh> Stldata;
string str;
int index = 0, j;
double x = 0, y = 0, z = 0;
//tmp_point *tmp_pnt = new tmp_point;
getline(ifs, str);
if (0 < str.find("solid"))
return false;
//ファイルから座標値の読み込み
printf("Tring text STL file ...");
num_tmp_points = 0;
num_triangles = 0;
while (getline(ifs, str)){
//vertexが見つかるまで読み飛ばす
j = str.find("vertex");
if (j<0)
continue;
//連続する3頂点の読み込みポリゴンを登録
//tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
for (int c = 2; c >= 0; c--)
{
values[num_triangles].pnt1[c] = atof(str.substr(str.rfind(" ")).c_str());
str.erase(str.rfind(" "));
num_tmp_points++;
}
//point_array[num_tmp_points-1] = tmp_pnt;
//tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
getline(ifs, str);
for (int c = 2; c >= 0; c--)
{
values[num_triangles].pnt2[c] = atof(str.substr(str.rfind(" ")).c_str());
str.erase(str.rfind(" "));
//tmp_pnt->index = num_tmp_points;
num_tmp_points++;
}
//point_array[num_tmp_points-1] = tmp_pnt;
//tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
getline(ifs, str);
for (int c = 2; c >= 0; c--)
{
values[num_triangles].pnt3[c] = atof(str.substr(str.rfind(" ")).c_str());
str.erase(str.rfind(" "));
//tmp_pnt->index = num_tmp_points;
num_tmp_points++;
}
values[num_triangles].nornVec[0] = getNormalVert(values[num_triangles])[0];
values[num_triangles].nornVec[1] = getNormalVert(values[num_triangles])[1];
values[num_triangles].nornVec[2] = getNormalVert(values[num_triangles])[2];
values[num_triangles].index = num_triangles;
num_triangles++;
}
ifs.close();
//fclose(in);
if (num_triangles > 0)
printf("Done.\n");
else
printf("Failed\n");
return(num_triangles > 0);
}
bool readBinarySTLFile(string STL_file, Triangle *values)
{
char line[81];
float *coord;
int num;
FILE *in;
errno_t error;
ifstream ifs(STL_file);
if (ifs.fail())
return false;
if ((error = fopen_s(&in,STL_file.c_str(), "rb")) != 0)
{
// エラー処理
//ofs << "Can't open file " << endl;
fclose(in);
return false;
}
//最初の84ビット分を読み飛ばす
if (fread(line, 1, 80, in) != 80)
return false;
printf("Tring binary STL file ...");
fread(line, 1, 4, in);
num = *(int*)line;
//ofs << "number of triangles: " << num<< endl;
int j = 0;
//ofs << "solid model" << endl;
while (fread(line, 1, 50, in) == 50)
{
coord = (float *)line;
//values[j].nornVec[0] = coord[0];
//values[j].nornVec[1] = coord[1];
//values[j].nornVec[2] = coord[2];
values[j].pnt1[0] = coord[3];
values[j].pnt1[1] = coord[4];
values[j].pnt1[2] = coord[5];
values[j].pnt2[0] = coord[6];
values[j].pnt2[1] = coord[7];
values[j].pnt2[2] = coord[8];
values[j].pnt3[0] = coord[9];
values[j].pnt3[1] = coord[10];
values[j].pnt3[2] = coord[11];
values[j].nornVec[0] = getNormalVert(values[j])[0];
values[j].nornVec[1] = getNormalVert(values[j])[1];
values[j].nornVec[2] = getNormalVert(values[j])[2];
values[j].index = j;
j++;
}
//ofs << "endsolid model" << endl;
fclose(in);
//ofs.close();
if (num > 0)
printf("Done.\n");
else
printf("Failed\n");
return(num > 0);
}
//vec0とvec1の内積の計算
double dot(double vec0[], double vec1[])
{
return (vec0[0] * vec1[0] + vec0[1] * vec1[1] + vec0[2] * vec1[2]);
}
void cross(double vec0[], double vec1[], double vec2[])
{
vec2[0] = vec0[1] * vec1[2] - vec0[2] * vec1[1];
vec2[1] = vec0[2] * vec1[0] - vec0[0] * vec1[2];
vec2[2] = vec0[0] * vec1[1] - vec0[1] * vec1[0];
}
void normVec(double vec[])
{
double norm;
norm = sqrt((vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]));
vec[0] /= norm; vec[1] /= norm; vec[2] /= norm;
}
double* getNormalVert(Triangle vertex)
{
double normalVec[3] = {};
double vec1[3] = { vertex.pnt2[0] - vertex.pnt1[0],
vertex.pnt2[1] - vertex.pnt1[1],
vertex.pnt2[2] - vertex.pnt1[2] };
double vec2[3] = { vertex.pnt3[0] - vertex.pnt2[0],
vertex.pnt3[1] - vertex.pnt2[1],
vertex.pnt3[2] - vertex.pnt2[2] };
cross(vec1, vec2, normalVec);
normVec(normalVec);//正規化
return normalVec;
}
};