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

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

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

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

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

C++

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

3DCG

コンピュータの演算により、3次元空間の仮想物体を、2次元平面上で表現する手法である。

Blender

Blenderとは、オープンソースの3DCGソフトウェアです。フリーでありながら、3Dモデル作成、レンダリング、アニメーション、コンポジットなどのハイエンドに匹敵する高い機能を持ち、さらにゲームエンジンも搭載しています。

Q&A

解決済

1回答

1745閲覧

頂点インデックスを使って正常に描画できない理由が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

OpenGL

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

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

C++

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

3DCG

コンピュータの演算により、3次元空間の仮想物体を、2次元平面上で表現する手法である。

Blender

Blenderとは、オープンソースの3DCGソフトウェアです。フリーでありながら、3Dモデル作成、レンダリング、アニメーション、コンポジットなどのハイエンドに匹敵する高い機能を持ち、さらにゲームエンジンも搭載しています。

0グッド

1クリップ

投稿2021/10/17 07:08

編集2021/10/17 10:04

提示コードですが上の画像が普通に描画した時の画像で、下が頂点インデックスを使った時の描画ですが頂点インデックスを使った時に頂点の位置がおかしくなるのですが何が原因なのでしょうか?端末の提示コードは頂点数とインデックスの数です。.objファイルは blenderで出力しました。

#####確認した事
頂点インデックスを使わない場合は正常に描画されます。
頂点インデックスの数を確認
バインドを確認

Github

https://github.com/Shigurechan/GL

イメージ説明
イメージ説明

端末
$ ./GL 36 36
Model.cpp
#include "../header/Model.hpp" #include <iostream> #include <sstream> #include <fstream> #include <assert.h> #include <vector> #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> #include <glm/glm.hpp> #include <GL/glew.h> #include "../lib/stb/stb_image.h" #include "../header/Resource.hpp" #include "../header/Camera.hpp" #include "../header/Window.hpp" #include "../header/Camera.hpp" FrameWork::D3::Object::Object(ObjFile o) : Render() { shader->Input(FrameWork::LoadShader("Shader/3D/BasicMono_3D.vert")->data(), FrameWork::LoadShader("Shader/3D/BasicMono_3D.frag")->data()); obj = o; //オブジェクトファイル glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vio); printf("%d\n",obj.vertexIndex.size()); printf("%d\n",obj.vertex.size()); //頂点 GLint attrib = shader->getAttribLocation("vertexPosition"); glEnableVertexAttribArray(attrib); glVertexAttribPointer(attrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid *)0); shader->setBindAttribLocation("vertexPosition"); glBufferData(GL_ARRAY_BUFFER, obj.vertex.size() * sizeof(GLfloat) * 11, obj.vertex.data(), GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, obj.vertexIndex.size() * sizeof(unsigned int), obj.vertexIndex.data(), GL_STATIC_DRAW); setRotate(glm::vec3(1, 1, 1),0); //回転 //バインド解除 glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } void FrameWork::D3::Object::Renderer() { shader->setEnable(); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vio); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * 3 * obj.vertex.size(), obj.vertex.data()); //Transform setPosition(glm::vec3(0, 0, -50)); //座標 setScale(glm::vec3(30, 30, 30)); //スケール //setRotate(glm::vec3(0, 1, 0),PI /2); //回転 //描画 shader->setUniformMatrix4fv("uTranslate", getMatTranslation()); shader->setUniformMatrix4fv("uRotate", getMatRotate()); shader->setUniformMatrix4fv("uScale", getMatScale()); shader->setUniformMatrix4fv("uViewProjection", FrameWork::Camera::getViewProjection()); shader->setUniform4f("uFragment", GetGlColor(glm::vec4(0, 255, 0, 255))); //glDrawArrays(GL_TRIANGLES, 0, obj.vertex.size()); //描画 glDrawElements(GL_TRIANGLES, obj.vertexIndex.size(), GL_UNSIGNED_INT,(void*)0); //描画 //バインド解除 glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); shader->setDisable(); } FrameWork::D3::Object::~Object() { } // ##################################### .objファイル読み込み ##################################### void FrameWork::D3::LoadObj(const char *fileName, ObjFile &attribute) { ObjFile obj; std::vector<float> vertexIndex; std::vector<glm::vec3> vertex; FILE *file = fopen(fileName, "r"); if (file == NULL) { std::cerr << ".OBJファイルが開けません: " << fileName << std::endl; assert(0); } else { while (true) { char line[500]; int res = fscanf(file, "%s", line); if (res == EOF) { break; } if (strcmp(line, "v") == 0) { glm::vec3 vert; fscanf(file, "%f %f %fn", &vert.x, &vert.y, &vert.z); vertex.push_back(vert); } else if (strcmp(line, "vt") == 0) { glm::vec2 u; fscanf(file, "%f %fn", &u.x, &u.y); obj.uv.push_back(u); } else if (strcmp(line, "vn") == 0) { glm::vec3 norm; fscanf(file, "%f %f %fn", &norm.x, &norm.y, &norm.z); obj.normal.push_back(norm); } else if (strcmp(line, "f") == 0) { std::string vertex1, vertex2, vertex3; unsigned int v[3], u[3], n[3]; int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%dn", &v[0], &u[0], &n[0], &v[1], &u[1], &n[1], &v[2], &u[2], &n[2]); if (matches != 9) { printf("File can't be read by our simple parser : ( Try exporting with other optionsn"); assert(0); } vertexIndex.push_back(v[0]); vertexIndex.push_back(v[1]); vertexIndex.push_back(v[2]); obj.vertexIndex.push_back(v[0]); obj.vertexIndex.push_back(v[1]); obj.vertexIndex.push_back(v[2]); obj.uvIndex.push_back(u[0]); obj.uvIndex.push_back(u[1]); obj.uvIndex.push_back(u[2]); obj.normalIndex.push_back(n[0]); obj.normalIndex.push_back(n[1]); obj.normalIndex.push_back(n[2]); } } } for (int i = 0; i < vertexIndex.size(); i++) { int vert = vertexIndex[i]; obj.vertex.push_back(vertex[vert - 1]); // printf("%f %f %f \n", obj.vertex.at(i).x, obj.vertex.at(i).y, obj.vertex.at(i).z); } //printf("%d\n\n",obj.vertex.size()); attribute = obj; }

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

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

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

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

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

guest

回答1

0

ベストアンサー

OpenGL ではなく WebGL ですが、同様の事象が再現することを確認しました。
おそらくですが obj ファイルの「頂点座標値番号」をそのまま頂点インデックスとして使用しているのが原因ではないでしょうか?

https://jsfiddle.net/cx20/hzoutmkv/
イメージ説明

obj

1f 5/1/1 3/2/1 1/3/1 2f 3/2/2 8/4/2 4/5/2 3f 7/6/3 6/7/3 8/8/3 4f 2/9/4 8/10/4 6/11/4 5f 1/3/5 4/5/5 2/9/5 6f 5/12/6 2/9/6 6/7/6 7f 5/1/1 7/13/1 3/2/1 8f 3/2/2 7/14/2 8/4/2 9f 7/6/3 5/12/3 6/7/3 10f 2/9/4 4/5/4 8/10/4 11f 1/3/5 3/2/5 4/5/5 12f 5/12/6 1/3/6 2/9/6

javascript

1 // NG ケース 2 const indices = [ 3 5, 3, 1, 4 3, 8, 4, 5 7, 6, 8, 6 2, 8, 6, 7 1, 4, 2, 8 5, 2, 6, 9 5, 7, 3, 10 3, 7, 8, 11 7, 5, 6, 12 2, 4, 8, 13 1, 3, 4, 14 5, 1, 2 15 ]; 16 17 // OK ケース 18 const indices = [ 19 0, 1, 2, 0, 2 , 3, // Front face 20 4, 5, 6, 4, 6 , 7, // Back face 21 8, 9, 10, 8, 10, 11, // Top face 22 12, 13, 14, 12, 14, 15, // Bottom face 23 16, 17, 18, 16, 18, 19, // Right face 24 20, 21, 22, 20, 22, 23 // Left face 25 ];

■ OBJファイルフォーマット
https://www.hiramine.com/programming/3dmodelfileformat/objfileformat.html

「f」キーワード行
数値/数値/数値 の場合、頂点座標値番号/テクスチャ座標値番号/頂点法線ベクトル番号

投稿2021/10/17 11:25

cx20

総合スコア4648

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

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

退会済みユーザー

退会済みユーザー

2021/10/17 12:13

なるほど。質問ですがどうれば頂点座標値番号をインデックスとして利用できるのでしょうか?
cx20

2021/10/17 12:19 編集

すみません。自分も obj ファイルのフォーマットを熟知しているわけではないので調べないと分からないです。 探せば OSS で obj ファイルを読み込むライブラリがあると思うので、そのあたりのコードを参考にしてみると良いかも知れません。
cx20

2021/10/17 12:45

度々すみません。よくよく見返してみたら、もう少し単純な話かもしれません。 > 頂点座標値番号 頂点座標番号ですが、1番から始まるようです。 インデックスの値として「-1」してみたらどうでしょうか?
退会済みユーザー

退会済みユーザー

2021/10/17 13:36

なるほど。jsは全く分からないのであれなのですが。こんな感じに修正したのですが治りません vertexIndex.push_back(v[0] - 1); vertexIndex.push_back(v[1] - 1); vertexIndex.push_back(v[2] - 1); obj.vertexIndex.push_back(v[0] - 1); obj.vertexIndex.push_back(v[1] - 1); obj.vertexIndex.push_back(v[2] - 1); obj.uvIndex.push_back(u[0]); obj.uvIndex.push_back(u[1]); obj.uvIndex.push_back(u[2]); obj.normalIndex.push_back(n[0]); obj.normalIndex.push_back(n[1]); obj.normalIndex.push_back(n[2]); } } } for (int i = 0; i < vertexIndex.size(); i++) { int vert = vertexIndex[i]; obj.vertex.push_back(vertex[vert - 1]); // printf("%f %f %f \n", obj.vertex.at(i).x, obj.vertex.at(i).y, obj.vertex.at(i).z); } //printf("%d\n\n",obj.vertex.size()); attribute = obj; }
txty

2021/10/18 10:06 編集

横やり失礼します。質問者と別人ですがちょっと疑問に思ったので、 三角化のときしか使えないのですが、 頂点座標値番号をb[0]とした場合、 3*b[0]-3,3*b[0]-2, 3*b[0]-1になると思ったんですが、何で、index値-1になるのですか。 理解できるか、分かりませんが、ちょっと知りたいです。 自分が書いた構成に誤りがあるかもしれません
cx20

2021/10/17 13:51

akagi_chan さん> > int vert = vertexIndex[i]; > obj.vertex.push_back(vertex[vert - 1]); ここの「vertex[vert - 1]」は「vertex[vert]」で良いと思います。vertexIndex を詰める際に「-1」しているので。
cx20

2021/10/17 13:58

txty さん> > 頂点座標値番号をb[0]とした場合、 > 3*b[0]-3,3*b[0]-2, 3*b[0]-1 すみません、b[0] はどこのことを指しているのでしょうか?
cx20

2021/10/17 14:03

以下は Blender で Cube を obj ファイル出力した際の、出力結果の抜粋です。 ----------------------- f 5/1/1 3/2/1 1/3/1 f 3/2/2 8/4/2 4/5/2 f 7/6/3 6/7/3 8/8/3 f 2/9/4 8/10/4 6/11/4 f 1/3/5 4/5/5 2/9/5 f 5/12/6 2/9/6 6/7/6 f 5/1/1 7/13/1 3/2/1 f 3/2/2 7/14/2 8/4/2 f 7/6/3 5/12/3 6/7/3 f 2/9/4 4/5/4 8/10/4 f 1/3/5 3/2/5 4/5/5 f 5/12/6 1/3/6 2/9/6 ----------------------- 自分の理解としては、objファイルの「頂点座標値番号」は 下記にあるように「0」からではなく「1」番から始まっている認識です。 //     [5]------[1] //    / |   / | //   [7]------[3] | //    | |   | | //    | [6]----|-[2] //    |/    |/ //   [8]------[4] // <頂点座標と頂点座標値番号の関係> 1.0, 1.0, -1.0, // 頂点座標値番号1 1.0, -1.0, -1.0, // 頂点座標値番号2 1.0, 1.0, 1.0, // 頂点座標値番号3 1.0,- 1.0, 1.0, // 頂点座標値番号4 -1.0, 1.0, -1.0, // 頂点座標値番号5 -1.0, -1.0, -1.0, // 頂点座標値番号6 -1.0, 1.0, 1.0, // 頂点座標値番号7 -1.0, -1.0, 1.0, // 頂点座標値番号8 このように1番から始まっている為、vertexIndex に設定する際に「-1」する必要があると思った次第です。
txty

2021/10/18 10:07 編集

fscanfで、法線を housenbox[9*i+0]、housenbox[9*i+1],housenbox[9*i+2] で取り出し、b[0]=housenbox[9*i+0]としたときの値。b[1]=housenbox[9*i+1];b[2]=housenbox[9*i+2];としている場合。一番初めの法線。ややこしいですが。 自分が書いた構成に誤りがあるかもしれません
txty

2021/10/17 14:14

あっ頂点か。説明は、同じだけど。
cx20

2021/10/17 14:24

txty さん> > fscanfで、法線を housenbox[9*i+0]、housenbox[9*i+1],housenbox[9*i+2]  すみません。housenbox が急に出てきて、ちょっと混乱してます。 housenbox はどこから出てきた変数でしょうか?この質問文にあるコードでしょうか?
txty

2021/10/17 14:44 編集

i=0で、a[0]=chouten[3*i+0];  a[1]=chouten[3*i+1];a[2]=chouten[3*i+2]と書くべきだったけど,不都合があったので9に変えました。fscanfで数値を読み込みに使う変数なので、5,3,1とかはいりそうだが。
txty

2021/10/17 14:42 編集

そちらの方法であってるなら使いたいというのが趣旨なのですが。説明の続きお願いします。
cx20

2021/10/17 14:43

txty さん> housenbox や chouten という変数は質問文のコードにある変数ではなく、 obj ファイルを読み込む際の例として書かれている変数ということでしょうか? > 5,3,1とかはいりそう そうですね。 > f 5/1/1 3/2/1 1/3/1 であれば、頂点座標値番号 として5,3,1 が入るかと思います。 ただ、頂点インデックスとして使う場合「インデックス」で指定が必要な為、「-1」する必要があります。 以下、イメージです。 <番号での指定> //     [5]------[1] //    / |   / | //   [7]------[3] | //    | |   | | //    | [6]----|-[2] //    |/    |/ //   [8]------[4] // <インデックスでの指定> //     [4]------[0] //    / |   / | //   [6]------[2] | //    | |   | | //    | [5]----|-[1] //    |/    |/ //   [7]------[3] //
txty

2021/10/18 10:04 編集

上の内容は分かりました。 すいません。自分 glEnable(GL_NORMALIZE);をglBeginの内側に書いてました。本当は外側。glEnable(GL_NORMALIZE);glBegin(); glEnd();glDisable(GL_NORMAlIZE);が正しい語順で、正しい語順に直したら正しいオブジェクトの形と、合っていないことが分かりました。なので、自分が書いた構成に誤りがあるかもしれません。
cx20

2021/10/17 14:54

txty さん> すみません、理解不足で何を聞きたいのかが良く分かりません。。 別の質問として立ててもらっても良いでしょうか?
txty

2021/10/17 15:00

cx20さん>私はindexが気になったから聞いたんだが大体わかったので、それは今度、やるとして、こんな感じに修正したのですが治りませんから、続きをやればいいと思う。
cx20

2021/10/17 15:04

txty さん> 了解です。
txty

2021/10/17 15:22

>^^ 質問者こないので 該当箇所を直そうとしたが、治らないそうです。どうしたものかと。 vertexIndex.push_back(v[0] - 1); vertexIndex.push_back(v[1] - 1); vertexIndex.push_back(v[2] - 1); obj.vertexIndex.push_back(v[0] - 1); obj.vertexIndex.push_back(v[1] - 1); obj.vertexIndex.push_back(v[2] - 1); obj.uvIndex.push_back(u[0]); obj.uvIndex.push_back(u[1]); obj.uvIndex.push_back(u[2]); obj.normalIndex.push_back(n[0]); obj.normalIndex.push_back(n[1]); obj.normalIndex.push_back(n[2]); } } } for (int i = 0; i < vertexIndex.size(); i++) { int vert = vertexIndex[i]; obj.vertex.push_back(vertex[vert - 1]); // printf("%f %f %f \n", obj.vertex.at(i).x, obj.vertex.at(i).y, obj.vertex.at(i).z); } //printf("%d\n\n",obj.vertex.size()); attribute = obj; }
cx20

2021/10/17 15:33

今、気が付いたのですが、akagi_chan さんのコードは、 こちらの opengl-tutorial のコードがベースになっているようですね。 ■ チュートリアル7:モデルのロード http://www.opengl-tutorial.org/jp/beginners-tutorials/tutorial-7-model-loading/ これだと、vertexIndices に詰める際は「-1」しておらず、 > vertexIndices.push_back(vertexIndex[0]); > vertexIndices.push_back(vertexIndex[1]); > vertexIndices.push_back(vertexIndex[2]); vertices から取り出す際に「vertexIndex-1 」してますね。 > unsigned int vertexIndex = vertexIndices[i]; > glm::vec3 vertex = temp_vertices[ vertexIndex-1 ]; > out_vertices.push_back(vertex); って、これだと、元の akagi_chan さんのコードであってそうな気がしてきました。 何でしょうね。。
cx20

2021/10/17 16:09

あぁ、理由分かったかもしれません。 たぶん、ですが、このループが不要です。 ------------------------------------------------ for (int i = 0; i < vertexIndex.size(); i++) {   obj.vertex.push_back(vertex[vert - 1]); } ------------------------------------------------ このループを実行すると、obj.vertex に 36個の頂点が設定されますが、 頂点インデックスを用いる場合は、Cube の頂点は8個で済むはずです。 その為、fscanf する際に、vertex.push でなく obj.vertex.push すれば済みそうです。 ----------------------------------------------- if (strcmp(line, "v") == 0) {   glm::vec3 vert;   fscanf(file, "%f %f %fn", &vert.x, &vert.y, &vert.z);   //vertex.push_back(vert);   obj.vertex.push_back(vert); } -----------------------------------------------
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問