忍者ブログ

カレンダー

03 2025/04 05
S M T W T F S
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

最新コメント

[11/20 かいせい]
[11/18 NONAME]
[10/01 かいせい]
[10/01 masafumi]
[09/28 なんとなく]

最新トラックバック

プロフィール

HN:
Kaisei+
性別:
男性

バーコード

ブログ内検索

カウンター

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

OBJファイルの読み込み その3

.objファイルから読み込んだデータをどのように持とうが構わないと思いますが,ボクの場合は前回お話した通りに持っています.
今回はどのようにファイルから読みだしていくかを話していこうと思います.
ボクのプログラムの書き方はゲッターとセッターをしっかり書いてしまうタイプなので,まともな方だとは思っているのですが,このような記事を書くときは不便でして,関数の説明を一からしなければなりません.しかし,そんな説明をするほど元気ではないので,簡単にどのような手続きをとればよいのかを記述します.
前回の記事で記述しているように.objファイルは一行に一頂点,一面を定義しているので,ファイルの読み込み時に一行ずつ読み込んでいけばよいのです.
これには,ファイルの入力処理がわかっていればよいので,本か他のサイトで調べてください.
ちなみにボクはVC++でコードを書いており,ファイル周りに関してはc++よりcの関数のほうが使いやすいと思っています.fopen_s関数でファイルポインターを掴んで,fgets関数で300文字くらいを指定して,一行読み込んでいます.
次に,一行を読み込んでスペース区切りで切りだされた文字を見ます.その文字が「v」「vt」「vn」「f」なら気にすることにしましょう.それ以外は「#」か「g」か「mtllib」ですので,今は無視しておきましょう.とくに「#」から始まる行はコメント行なので永年無視です.
vの場合は,頂点座標として格納する.
vtならば,テクスチャ座標として格納する.
vnならば,法線として格納する.
fならば,面として格納する.
と言った感じに場合わけの処理になります.
このとき,前回の説明で用意してあるフラグを立ててやれば,描画処理の時にテクスチャ座標がないのか,法線がないのかわかりやすいので,楽です.
「v」「vt」「vn」ならば一行読み取った文字列を全てスペース区切りにして行末まで送っていきます.これでこの行の読み込みは完了するはずです.

「f」の行はちょろっとひねりが必要になります.
スペース区切りで参照している頂点の数はわかるのですが,問題は切り出したあとで,スラッシュ区切りの部分です.
cで用意されているstrtok_sを区切り文字を用いて「a//c」のようにスラッシュが二重に続いたものを処理した場合,スラッシュが一度で2つ飛ばされて処理されてしまいます.
ですので,文字を一文字見ていってスラッシュ区切りを実装するしかありません.
ボクはトークンの切り出し関数mystrtokを作って,スラッシュを一文字ずつ抜き出していました.

char *mystrtok(char *s, char *t)
{
    static char buf[50];
    static char *headp;
    char *tailp;
    char *p;
   
    if (s != NULL) {
        strcpy_s(buf, s);
        headp = buf; /* headpは先頭を指す */
    }
    //sがNULLでかつheadpがNULLの場合,これは終点に達しているということ
    if(headp==NULL){
        return NULL;
    }
    //headp文字列からtを検索
    // tailpは区切り文字を指す
    tailp = strstr(headp, t);
   
    //区切りがない場合,最後という判定でこのときのheadpを返す
    if (tailp == NULL){
        p = headp;
        headp = NULL;
        return p;
    }

    //このときtailpがheadpと同じ場合,区切り文字が連続に続いているということでNULLを返す
    if(tailp==headp){
        headp = tailp + strlen(t); /* 次の頭 */
        return NULL;
    }

    *tailp = '\0';
    p = headp;
    headp = tailp + strlen(t); /* 次の頭 */
    return p;
}

この関数my_strtok()は引数に,区切りたい文字列sと,区切り文字列tとします.簡単に言うと,標準ライブラリのstrtok()と同じ使い方です.
最初に引数に入れた区切りたい文字列sは,先頭から区切り文字列tまでを切り出して返り値として返します.
区切りたい文字列sから次のトークンを得たいときは,NULLをsに入れ,区切り文字tを入力します.すると次のトークンが返ってきます.
今の場合,スラッシュ区切りにしたいので,面のスペース区切りしたあとの文字列と"/"を引数として指定します.
区切りたい文字列sが「200/201/202」の場合,mystrtok(s,"/")とします.この返り値は200となります.
次に,次のトークンがほしいので,mystrtok(NULL,"/")とします.すると,201が返ってきます.
最後のトークンがほしいので再度mystrtok(NULL,"/")とします.もちろん,202が返ってきます.

仮に,区切りたい文字列sが「200//202」だったら,標準ライブラリのstrtok()では,二重のスラッシュ//を1区切りとしてみなします.しかし,mystrtok()では,/毎に区切っていきます.
ですから,mystrtok(s,"/"),mystrtok(NULL,"/"),mystrtok(NULL,"/")とした場合,200,NULL,202と返します.
区切りたい文字列が最後まで行くと,それからは常にNULLしか返さなくなります.

これで取り出して,メモリに格納していけば,面情報を得ることができるので読み込み終了となります.

PR

Trackbacks

TRACKBACK URL :

Comments

Comment Form