質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

1010閲覧

法線ベクトルの単純平均について

windowsaa

総合スコア16

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/11/14 07:41

同じような内容の連続投稿となってしまいすみません。

また新たな質問として質問することとしました。

頂点の法線を単純に頂点を共有するメッシュの面法線を平均して求めて陰影をつけたいと思っていますが書き方がわからず苦戦しています。

C++

1#include"stlreader.h" 2 3#define STL_FILE "C:\Users\onower\Desktop\nsx_concept_LOW.stl" 4 5 6using namespace std; 7 8float light_pos[] = { -5.0, 5.0, 5.0, 1.0 }; 9 10//プロトタイプ宣言 11void display(void); 12void reshape(int w, int h); 13void draw(); 14void init(); 15void DRAW_XYZ(); 16void MouseWheel(int wheel, int direction, int x, int y); 17void mouse(int button, int state, int x, int y); 18void motion(int x, int y); 19 20Triangle *triangles; 21int num; 22STLreader stlreader; 23int rate = 1.0; 24double xAngle = 0.0, yAngle = 0.0; 25 26int main(int argc, char *argv[]) 27{ 28 glutInitWindowPosition(128, 128); 29 glutInitWindowSize(800, 800); 30 glutInit(&argc, argv); 31 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 32 glutCreateWindow("argv[0]"); 33 init(); 34 glutDisplayFunc(display); 35 glutReshapeFunc(reshape); 36 glutMouseFunc(mouse); 37 glutMotionFunc(motion); 38 glutMouseWheelFunc(MouseWheel); 39 // glutKeyboardFunc(keyboard); 40 glutMainLoop(); 41 42 if (triangles) 43 delete[] triangles; 44 45 return 0; 46} 47 48 49void display(void) 50{ 51 52 53 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 54 55 56 57 glLoadIdentity(); 58 gluLookAt(10.0 * rate,15.0 * rate ,10.0 * rate, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //視点の設定 59 60 //glLightfv(GL_LIGHT0, GL_POSITION, light_pos); 61 62 glRotated(xAngle, 1, 0, 0); 63 glRotated(yAngle, 0, 1, 0); 64 65 66 draw(); //描画 67 68 glutSwapBuffers(); //ウィンドウに出力 69 70 71 72 //double* getNormalVert(Triangle trinangles); 73 74} 75 76 77void reshape(int w, int h) 78{ 79 glViewport(0, 0, w, h); //ビューポートの設定 80 glMatrixMode(GL_PROJECTION); 81 glLoadIdentity(); 82 gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0); //視野の設定 83 glMatrixMode(GL_MODELVIEW); 84 glLoadIdentity(); 85 86 87} 88 89 90 91void draw() 92{ 93 94 95 DRAW_XYZ(); //XYZ軸の描画 96 97 glBegin(GL_TRIANGLES); 98 99 glColor3f(1.0, 0.0, 0.0); 100 101 102 for (int i = 0; i < num; i++) //stlデータの描画 103 { 104 105 glNormal3dv(triangles[i].nornVec); 106 glVertex3dv(triangles[i].pnt1); 107 glVertex3dv(triangles[i].pnt2); 108 glVertex3dv(triangles[i].pnt3); 109 110 111 112 113 } 114 115 glEnd(); 116 glFlush(); 117 118 119} 120 121 122void init() 123{ 124 125 if (triangles) 126 delete[] triangles; 127 128 num = stlreader.countTriangles(string(STL_FILE)); //stlデータを構成しているポリゴンの数のをカウント 129 130 131 if (!(num = stlreader.countTriangles(string(STL_FILE)))) 132 133 return; 134 135 triangles = new Triangle[num]; 136 137 stlreader.readASCIISTLFile(STL_FILE, triangles); 138 139 stlreader.readBinarySTLFile(STL_FILE, triangles); 140 141 glClearColor(1.0, 1.0, 1.0, 1.0); 142 143} 144 145 146 147void DRAW_XYZ() 148{ 149 glDisable(GL_LIGHTING); 150 glDisable(GL_LIGHT0); 151 glDisable(GL_DEPTH_TEST); 152 glDisable(GL_NORMALIZE); 153 154 glBegin(GL_LINES); 155 156 glColor3d(0, 1, 0);//x軸緑 157 glVertex2d(-1000, 0); 158 glVertex2d(1000, 0); 159 160 glColor3d(1, 0, 0);//y軸赤 161 glVertex2d(0, -1000); 162 glVertex2d(0, 1000); 163 164 glColor3d(0, 0, 1);//z軸青 165 glVertex3d(0, 0, -1000); 166 glVertex3d(0, 0, 1000); 167 168 glEnd(); 169 170 171 172 173 glEnable(GL_DEPTH_TEST); 174 glEnable(GL_NORMALIZE); 175 //glLightfv(GL_LIGHT0, GL_POSITION, light_pos); 176 glEnable(GL_LIGHT0); 177 glEnable(GL_LIGHTING); 178} 179 180 181void MouseWheel(int wheelnumber, int direction, int x, int y) 182{ 183 184 if (direction > 0) 185 { 186 rate++; 187 188 } 189 else 190 { 191 rate--; 192 193 } 194 195 glutPostRedisplay(); 196 197} 198 199 200int xStart, yStart; 201bool mouseFlag = GL_FALSE; 202void mouse(int button, int state, int x, int y) 203{ 204 if (button == GLUT_LEFT_BUTTON &&state == GLUT_DOWN) 205 { 206 xStart = x; 207 yStart = y; 208 mouseFlag = GL_TRUE; 209 } 210 else 211 { 212 mouseFlag = GL_FALSE; 213 214 } 215 216} 217 218void motion(int x, int y) 219{ 220 int xdis, ydis; 221 double a = 0.5; 222 223 if (mouseFlag == GL_FALSE)return; 224 225 xdis = x - xStart; 226 ydis = y - yStart; 227 228 xAngle += (double)ydis * a; 229 yAngle += (double)xdis * a; 230 231 xStart = x; 232 yStart = y; 233 glutPostRedisplay(); 234} 235

ヘッダーファイル

C++

1#include <iostream> 2#include <cmath> 3#include <string> 4#include <fstream> 5 6using namespace std; 7 8struct vert 9{ 10 double pnt1[3]; 11 double pnt2[3]; 12 double pnt3[3]; 13}; 14 15struct vert4 16{ 17 double pnt1[4];//x,y,z,w 18 double pnt2[4]; 19 double pnt3[4]; 20}; 21 22struct Triangle { 23 double nornVec[3]; 24 double pnt1[3]; 25 double pnt2[3]; 26 double pnt3[3]; 27 unsigned int index; 28}; 29 30 31class STLreader 32{ 33 34 unsigned int num_tmp_points;//一時的な変数 35 unsigned int num_triangles;//三角形の数 36 37 38 39public: 40 static int countTriangles(string filename) 41 { 42 //STLファイルのオープン 43 ifstream ifs; 44 char line[80]; 45 ifs.open(filename); 46 if (ifs.fail()) 47 return false; 48 string str; 49 int count = 0; 50 int a; 51 getline(ifs, str); 52 //int h = str.find("solid"); 53 if (str.find("solid")==-1){ 54 ifs.close(); 55 ifs.open(filename, ios::binary); 56 if (ifs.fail()) 57 return false; 58 ifs.read(line, 80); 59 ifs.read(line, 4); 60 return *(int *)line; 61 } 62 while (getline(ifs, str)){ 63 a = str.find("normal"); 64 if (a > 0) 65 count++; 66 } 67 ifs.close(); 68 return count; 69 }; 70 71 bool readASCIISTLFile(string filename, Triangle *values) 72 { 73 74 //STLファイルのオープン 75 ifstream ifs(filename); 76 if (ifs.fail()) 77 return false; 78 79 //vector<mesh> Stldata; 80 string str; 81 int index = 0, j; 82 double x = 0, y = 0, z = 0; 83 //tmp_point *tmp_pnt = new tmp_point; 84 85 getline(ifs, str); 86 if (0 < str.find("solid")) 87 return false; 88 //ファイルから座標値の読み込み 89 printf("Tring text STL file ..."); 90 num_tmp_points = 0; 91 num_triangles = 0; 92 93 94 while (getline(ifs, str)){ 95 96 97 98 //vertexが見つかるまで読み飛ばす 99 j = str.find("vertex"); 100 if (j<0) 101 continue; 102 //連続する3頂点の読み込みポリゴンを登録 103 //tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point)); 104 for (int c = 2; c >= 0; c--) 105 { 106 values[num_triangles].pnt1[c] = atof(str.substr(str.rfind(" ")).c_str()); 107 str.erase(str.rfind(" ")); 108 num_tmp_points++; 109 } 110 //point_array[num_tmp_points-1] = tmp_pnt; 111 112 //tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point)); 113 getline(ifs, str); 114 115 for (int c = 2; c >= 0; c--) 116 { 117 values[num_triangles].pnt2[c] = atof(str.substr(str.rfind(" ")).c_str()); 118 str.erase(str.rfind(" ")); 119 //tmp_pnt->index = num_tmp_points; 120 num_tmp_points++; 121 } 122 //point_array[num_tmp_points-1] = tmp_pnt; 123 124 //tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point)); 125 getline(ifs, str); 126 127 for (int c = 2; c >= 0; c--) 128 { 129 values[num_triangles].pnt3[c] = atof(str.substr(str.rfind(" ")).c_str()); 130 str.erase(str.rfind(" ")); 131 //tmp_pnt->index = num_tmp_points; 132 num_tmp_points++; 133 } 134 135 values[num_triangles].nornVec[0] = getNormalVert(values[num_triangles])[0]; 136 values[num_triangles].nornVec[1] = getNormalVert(values[num_triangles])[1]; 137 values[num_triangles].nornVec[2] = getNormalVert(values[num_triangles])[2]; 138 139 values[num_triangles].index = num_triangles; 140 num_triangles++; 141 142 } 143 ifs.close(); 144 //fclose(in); 145 if (num_triangles > 0) 146 printf("Done.\n"); 147 else 148 printf("Failed\n"); 149 return(num_triangles > 0); 150 151 } 152 153 bool readBinarySTLFile(string STL_file, Triangle *values) 154 { 155 char line[81]; 156 float *coord; 157 int num; 158 FILE *in; 159 errno_t error; 160 161 ifstream ifs(STL_file); 162 if (ifs.fail()) 163 return false; 164 165 166 if ((error = fopen_s(&in,STL_file.c_str(), "rb")) != 0) 167 { 168 // エラー処理 169 //ofs << "Can't open file " << endl; 170 fclose(in); 171 return false; 172 } 173 174 //最初の84ビット分を読み飛ばす 175 if (fread(line, 1, 80, in) != 80) 176 return false; 177 178 printf("Tring binary STL file ..."); 179 fread(line, 1, 4, in); 180 num = *(int*)line; 181 182 //ofs << "number of triangles: " << num<< endl; 183 int j = 0; 184 //ofs << "solid model" << endl; 185 while (fread(line, 1, 50, in) == 50) 186 { 187 coord = (float *)line; 188 //values[j].nornVec[0] = coord[0]; 189 //values[j].nornVec[1] = coord[1]; 190 //values[j].nornVec[2] = coord[2]; 191 192 values[j].pnt1[0] = coord[3]; 193 values[j].pnt1[1] = coord[4]; 194 values[j].pnt1[2] = coord[5]; 195 196 values[j].pnt2[0] = coord[6]; 197 values[j].pnt2[1] = coord[7]; 198 values[j].pnt2[2] = coord[8]; 199 200 values[j].pnt3[0] = coord[9]; 201 values[j].pnt3[1] = coord[10]; 202 values[j].pnt3[2] = coord[11]; 203 204 values[j].nornVec[0] = getNormalVert(values[j])[0]; 205 values[j].nornVec[1] = getNormalVert(values[j])[1]; 206 values[j].nornVec[2] = getNormalVert(values[j])[2]; 207 values[j].index = j; 208 j++; 209 210 } 211 212 //ofs << "endsolid model" << endl; 213 fclose(in); 214 //ofs.close(); 215 if (num > 0) 216 printf("Done.\n"); 217 else 218 printf("Failed\n"); 219 return(num > 0); 220 221 } 222 223 224 //vec0とvec1の内積の計算 225 double dot(double vec0[], double vec1[]) 226 { 227 return (vec0[0] * vec1[0] + vec0[1] * vec1[1] + vec0[2] * vec1[2]); 228 } 229 230 void cross(double vec0[], double vec1[], double vec2[]) 231 { 232 vec2[0] = vec0[1] * vec1[2] - vec0[2] * vec1[1]; 233 vec2[1] = vec0[2] * vec1[0] - vec0[0] * vec1[2]; 234 vec2[2] = vec0[0] * vec1[1] - vec0[1] * vec1[0]; 235 } 236 237 void normVec(double vec[]) 238 { 239 double norm; 240 norm = sqrt((vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2])); 241 vec[0] /= norm; vec[1] /= norm; vec[2] /= norm; 242 } 243 244 double* getNormalVert(Triangle vertex) 245 { 246 double normalVec[3] = {}; 247 double vec1[3] = { vertex.pnt2[0] - vertex.pnt1[0], 248 vertex.pnt2[1] - vertex.pnt1[1], 249 vertex.pnt2[2] - vertex.pnt1[2] }; 250 double vec2[3] = { vertex.pnt3[0] - vertex.pnt2[0], 251 vertex.pnt3[1] - vertex.pnt2[1], 252 vertex.pnt3[2] - vertex.pnt2[2] }; 253 cross(vec1, vec2, normalVec); 254 normVec(normalVec);//正規化 255 256 return normalVec; 257 } 258 259 260 261 262}; 263

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

やり方は前回の質問に書いたとおりです。
https://teratail.com/questions/100307

私が「やり方しか書かなかった」のは「慈善でコードを提供するには作業量が多すぎる」からです。技術の話であれば私は延々喋り続けられますが、正解がただ欲しいという人には厳しくあたります。ここはエンジニアがお互いの疑問に答え研鑽する場であり、他人にやってほしいことを頼む場ではないです。

投稿2017/11/14 08:09

masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

前回の質問に対する回答の一番最初の「自力で変換」のところで方針を示していただいていますが、
STLは位相情報がないポリゴンフォーマットですので、まずは、座標が一致==位相的に同一の頂点、
とみなして、頂点の共有状況を求めないことにはその先の計算に進めませんね。

座標の一致判定はトレランスを考慮すると難しくなりますが、パフォーマンスを気にしないので
あれば、単純に1点頂点を読むごとに、それまでに読んだ頂点を総当りでdouble値として完全一致
するものがないか調べるだけで良いと思います。
(内容やコードの質から察するに、大学のCG系の課題とかでは?、と推測したのですが、
そうであれば、大規模モデルとかパフォーマンスとかは、2の次でいいかもですし)

今更ですが、なめらかな表示ではなく、Trinagle単位でパキパキの表示で良いのであれば、STLの法線
&法線の指定はサボって、単にglEnable(GL_AUTO_NORMAL);を指定する、という手もありますね。

投稿2017/11/17 06:42

osakana_kana

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

3Dデータを扱いたいのであれば先ず基本となるベクトル演算に(空間幾何学)関する基礎を身に着けましょう。
それからでないと説明している言葉を理解していただくのが難しいと思います。

たとえば件の法線ですが、ベクトルの外積を計算すればよいわけですが、その意味が分からなければ説明自体を理解してもらうことが難しいと思います。

先ず基礎を身に着ける努力をして見ましょう。

投稿2017/11/15 09:10

Fritha

総合スコア33

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問