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

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

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

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

デバッグ

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

C++

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

3DCG

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

Q&A

解決済

2回答

2084閲覧

opnegl objローダーのUV座標の設定方法が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

OpenGL

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

デバッグ

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

C++

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

3DCG

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

0グッド

0クリップ

投稿2021/10/22 01:19

編集2021/10/22 08:16

提示コードの下部のLoadObj()関数部ですがobjロードの正しい書き方がわからずモデルに上手くUV座標を設定できません。これは何が原因なのでしょうか?objファイルの中にあるuv座標をstd::vector<glm::vec2> uv に代入してそれをObjectクラスでロードして設定しても座標おかしく正常に描画されません。これはなぜでしょうか?原因がわかりません。

Github: https://github.com/Shigurechan/GL
参考サイト: https://github.com/opengl-tutorials/ogl/blob/master/common/objloader.cpp#L91-L108
イメージ説明
イメージ説明

Mode.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()); shader->Input(FrameWork::LoadShader("Shader/3D/BasicTexture_3D.vert")->data(), FrameWork::LoadShader("Shader/3D/BasicTexture_3D.frag")->data()); obj = o; //オブジェクトファイル glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao); // 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"); attrib = shader->getAttribLocation("vertexUV"); glEnableVertexAttribArray(attrib); //glVertexAttribPointer(attrib, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid *)(sizeof(GLfloat) * 3 * obj.vertex.size())); glVertexAttribPointer(attrib, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid *)(obj.vertex.size() * sizeof(obj.vertex[0]))); shader->setBindAttribLocation("vertexUV"); glBufferData(GL_ARRAY_BUFFER, obj.vertex.size() * sizeof(obj.vertex[0]) + obj.uv.size() * sizeof(obj.uv[0]), NULL, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, obj.vertex.size() * sizeof(obj.vertex[0]), obj.vertex.data()); glBufferSubData(GL_ARRAY_BUFFER, obj.vertex.size() * sizeof(obj.vertex[0]), obj.uv.size() * sizeof(obj.uv[0]), obj.uv.data()); //glBufferData(GL_ARRAY_BUFFER, obj.vertex.size() * sizeof(GLfloat) * 3, obj.vertex.data(), GL_STATIC_DRAW); //glBufferData(GL_ARRAY_BUFFER, obj.uv.size() * sizeof(GLfloat) * 2, obj.uv.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); //回転 glGenTextures(1, &textureID); //テクスチャIDの生成 glBindTexture(GL_TEXTURE_2D, textureID); //IDバインド glEnable(GL_TEXTURE_2D); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //テクスチャ生成 FrameWork::TextureFile file = FrameWork::LoadTexture("Assets/debug_texture.png"); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, file.size.x, file.size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, file.fileData); // テクスチャの補間設定 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glGenerateMipmap(GL_TEXTURE_2D); //バインド解除 glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 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, eao); glBindTexture(GL_TEXTURE_2D, textureID); //IDバインド //glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * 3 * obj.vertex.size(), obj.vertex.data()); glActiveTexture(GL_TEXTURE0); //テクスチャ有効 //Transform setPosition(glm::vec3(0, 0, -50)); //座標 setScale(glm::vec3(30, 30, 30)); //スケール //描画 shader->setUniformMatrix4fv("uTranslate", getMatTranslation()); shader->setUniformMatrix4fv("uRotate", getMatRotate()); shader->setUniformMatrix4fv("uScale", getMatScale()); shader->setUniformMatrix4fv("uViewProjection", FrameWork::Camera::getViewProjection()); glDrawElements(GL_TRIANGLES, obj.vertexIndex.size(), GL_UNSIGNED_INT,(void*)0); //描画 //バインド解除 glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); shader->setDisable(); } FrameWork::D3::Object::~Object() { } // ##################################### .objファイル読み込み ##################################### void FrameWork::D3::LoadObj(const char *fileName, ObjFile &attribute) { ObjFile obj; std::vector<int> vertexIndex; std::vector<int> uvIndex; std::vector<int> normalIndex; std::vector<glm::vec3> vertex; std::vector<glm::vec2> uv; std::vector<glm::vec3> normal; 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); obj.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); 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); 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] - 1); // obj.vertexIndex.push_back(v[1] - 1); //obj.vertexIndex.push_back(v[2] - 1); uvIndex.push_back(u[0]); uvIndex.push_back(u[1]); uvIndex.push_back(u[2]); obj.uvIndex.push_back(u[0]); obj.uvIndex.push_back(u[1]); obj.uvIndex.push_back(u[2]); normalIndex.push_back(n[0]); normalIndex.push_back(n[1]); normalIndex.push_back(n[2]); obj.normalIndex.push_back(n[0]); obj.normalIndex.push_back(n[1]); obj.normalIndex.push_back(n[2]); } } for( unsigned int i = 0; i < vertexIndex.size(); i++ ) { // Get the indices of its attributes unsigned int vi = vertexIndex[i]; unsigned int ui = uvIndex[i]; unsigned int ni = normalIndex[i]; obj.vertexIndex.push_back(vi - 1); // Get the attributes thanks to the index glm::vec3 v = vertex[ vi - 1 ]; glm::vec2 u = uv[ ui - 1]; glm::vec3 n = normal[ ni - 1 ]; // Put the attributes in buffers // obj.vertex.push_back(v); // obj.uv.push_back(u); // obj.normal .push_back(n); } } attribute = obj; }

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/10/22 01:36

文章を修正しました。
guest

回答2

0

ベストアンサー

やっぱりglDrawArraysを使うことにしましょう。
今のコードだとobjファイル位置データのインデックスをOpenGLに渡すようにしていますが、位置が同じでもuvやnormalは違うことがあるのでそのままでは使えません。

https://github.com/Shigurechan/GL/blob/ef43e57f5b6578b85a73c20c87d8d0e7482bbce1/source/Model.cpp#L108

glDrawArrays(GL_TRIANGLES, 0, obj.vertex.size());

objファイルのデータを直接OpenGLに渡すvectorには入れず一時的に使う別のvectorに入れます。
https://github.com/Shigurechan/GL/blob/ef43e57f5b6578b85a73c20c87d8d0e7482bbce1/source/Model.cpp#L158-L172

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); uv.push_back(u); }

https://github.com/Shigurechan/GL/blob/ef43e57f5b6578b85a73c20c87d8d0e7482bbce1/source/Model.cpp#L220-L239
ここのコメントアウトを外します

それからカリングを有効にするか、デプステストを有効にする必要がありそうでした。

glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST);

投稿2021/10/22 14:41

編集2021/10/22 14:55
tkaaad97

総合スコア64

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

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

fana

2021/10/22 15:07

> やっぱりglDrawArraysを使うことにしましょう。 書き出しが「やっぱり」? 二者間でしか共有していない何かを前提としたような話…??
退会済みユーザー

退会済みユーザー

2021/10/23 12:14 編集

gitを更新しました。 質問ですが一様できたのですが一面に対して一つのテクスチではなく一つの立方体で一つのテクスチャになってしまうのですがこれはまた別問題でしょうか?
tkaaad97

2021/10/23 13:49 編集

元のモデルとテクスチャの見え方が違ってるのでしょうか? 位置とuvをOpenGLに渡すことはできてると思うので画像を変えてみたりRenderDocで調べてみたらいいかもしれません。 それか面ごとにテクスチャを変えられるかという質問ですか? テクスチャを複数使うことはできますが、その場合は各面でどのテクスチャユニットを使うかという情報を渡す必要が出てきます。 画像パッキングしたりしベースカラー用はテクスチャ一枚にしてすませることが多いと思います。
退会済みユーザー

退会済みユーザー

2021/10/24 01:03

なるほど。わかりました。質問です頂点インデックスを使いたいのですが。それをするにはどうすればいいのでしょうか?自分で色々触りましたが立方体がおかしくなります。
tkaaad97

2021/10/25 10:44

OpenGLではインデックス一つだけ使うことになるのでデータを並べ替えてインデックスつけなおす必要があります。 バッファをそんなに小さくできるわけではないのでここで頂点インデックス使った方法を使う必要はあまりない気がします。 どうしてもやりたい場合は glDrawArraysのコードのままでインデックスを0, 1, 2, 3...と連番で作成してやればとりあえずは頂点インデックスを使った方法にできます。 これだとバッファは全く節約できないので、重複した頂点データ (位置とuvとnormalが完全に同じもの) を消してそのインデックスを書き換えるなどすると少し小さくなるかなと思います。
guest

0

FrameWork::D3::LoadObj() の末尾の for の中身に何の意味も成さない記述が見えます.
この時点ももう「ダメそう」に見えます.

for( unsigned int i = 0; i < vertexIndex.size(); i++ ) { // Get the indices of its attributes unsigned int vi = vertexIndex[i]; unsigned int ui = uvIndex[i]; unsigned int ni = normalIndex[i]; obj.vertexIndex.push_back(vi - 1); // Get the attributes thanks to the index glm::vec3 v = vertex[ vi - 1 ]; glm::vec2 u = uv[ ui - 1]; glm::vec3 n = normal[ ni - 1 ]; // Put the attributes in buffers // obj.vertex.push_back(v); // obj.uv.push_back(u); // obj.normal .push_back(n);

v, u, n は何なのでしょうか?
これらを用いる処理はコメントアウトされているように見えますが,
他方で,これらが残されている意味は何なのでしょう?

v, u, n が不要なのであれば,ui, ni もまた不要であり,であれば uvIndex, normalIndex, vertex, uv, normal とかいう vector 群も須らく不要な物となりそうですが.

こんなぐちゃぐちゃの状態で提示されているコードが本当に

正常に描画

されるハズの実装なのですか?


結論
提示コードは,他者の目には 書きかけの何か であるようにしか見えません.
まともに動作しない理由というのは
「完成品でない状態で動作させても所望の結果は得られない」というだけの話なのではないでしょうか.


Suggestion:
絵を見る限り,今現在扱っているモデルは非常に単純なものと見えます.
であれば,
「その OBJ ファイルを正常にロードしたならば,ロード結果のデータとはこういうデータになるハズ」というデータを
手作業で(ハードコーディングで)用意することができるでしょうから,
それを利用して問題点がどこにあるのかを突き止めることができるでしょう.

  1. FrameWork::D3::LoadObj() の中身から,ファイルから読み込むコードを全て除去(コメントアウトなり)し,代わりに前記ような「こうなるハズ」というハードコーディングされたデータを返す形にする.
  2. 上記1.の状態で正常な描画ができないのであれば,そもそもあなたの考えのどこかが間違っているということ.ファイル読込処理(だけ)が悪いのではない.
  3. 上記1.の状態であれば正常な描画ができるということであれば,ハードコーディングで用意したデータと,ファイル読込結果のデータを比較してみればよい.それでファイル読込処理の何が違うのかがわかる.

投稿2021/10/22 08:56

編集2021/10/22 09:05
fana

総合スコア11996

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

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

退会済みユーザー

退会済みユーザー

2021/10/22 11:13

なるほど。色々試したのが原因がわかりません。何が悪いのでしょうか?はやりobjローダーがわるいみたいないなのですが
fana

2021/10/22 14:58

> 何が悪いのでしょうか? という事柄に関して思うところをこれ以上無いほどに明瞭に述べたつもりなのですが. 「そもそもコードが完成してないこと」だと思いますぞ,という. --- で,本当に「読み込み処理部分だけが悪いのであれば」… どっかからパクってきたようなコードをいじくりまわしていても埒が明かないのであれば, その方針はさっさと見限ってしまえばどうですか? とりあえずあなたの今のプログラムに必要な要素だけをファイルから読み出す処理であれば, OBJファイルのフォーマットについてググって,1から完全自前で読み込み処理を書いたほうが早いような気もしますぞ. (小一時間もあれば終わるような話かと思いますが.)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問