C言語 3Dオブジェクトの半透明化をしたいです

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
n_0804
記事: 1
登録日時: 2年前

C言語 3Dオブジェクトの半透明化をしたいです

#1

投稿記事 by n_0804 » 2年前

【質問】
読み込んだSTL形式の3Dオブジェクトと、作成した立方体の3DオブジェクトをAR表示するプログラムを作っています。
その立方体の3Dオブジェクトの半透明化処理でつまづいております。
ARを行うプログラミングにおいて立方体を半透明化したいのですが、半透明化する関数(glColor4f())がうまく適応されていないみたいです。
現在のプログラムではコンパイルは通っており、半透明化されていない立方体を表示できる状態です。
環境光などの部分を変更してみましたが上手くいきませんでした。
どのようにすれば立方体を半透明化できるかご教示いただきたいです。
お手数をおかけしますがよろしくお願いします。

【環境】
OS:Windows
コンパイラ:Visual studio2022 C言語
またARToolKit・OpenGL・GLUTを使用してます。

C言語は大学で勉強しており、1年半ほどC++をメインで使用しておりました。
現在は時々使う程度です。

【プログラム】
3Dオブジェクトの描画部分の関数

コード:

static void draw(int mid,double patt_trans[3][4])
{
    double    gl_para[16];
    GLfloat   mat_ambient1[] = { 0.7, 0.7, 0.7, 1.0 };
    GLfloat   mat_flash1[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat   mat_flash_shiny[] = { 50.0 };
    GLfloat   light_position[] = { 100.0,-200.0,200.0,0.0 };
    GLfloat   ambi[] = { 0.1, 0.1, 0.1, 0.1 };
    GLfloat   lightZeroColor[] = { 0.9 ,0.9,0.9,1.0 };
 


    GLfloat   mat_ambient2[] = { 1.0 ,1.0, 1.0, 0.0 };
    GLfloat   mat_flash2[] = { 1.0, 1.0, 1.0, 0.0 };
    GLfloat   mat_flash_shiny2[] = { 0.0 };
    GLfloat   ambi2[] = { 1.0, 1.0, 1.0, 0.0 };
    GLfloat   lightZeroColor2[] = { 1.0 ,1.0,1.0,0.0 };

    /*3Dオブジェクトの描画準備*/
    argDrawMode3D();
    argDraw3dCamera(0, 0);
   // glClearDepth(1.0);

    //glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST); //隠面消去・有効
    glDepthFunc(GL_LEQUAL); //デプス・テスト

    /* 座標変換行列の読み込み */
    argConvGlpara(patt_trans, gl_para); //ARToolkit->OpenGL
    glMatrixMode(GL_MODELVIEW); //行列変換モード・モデルビュー
    glLoadMatrixd(gl_para); //読み込む行列を指定

    /*ライティング*/
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);

 
    
    glMatrixMode(GL_MODELVIEW);
    glTranslatef(0.0, 0.0, 25.0);

    switch(mid) {
        case OBJ1_MARK_ID:
            glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash1);
            glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
            glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);
            glCallList(listid); //モデルの描画
            break;

        case OBJ2_MARK_ID:
            glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash1);
            glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
            glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);
            glCallList(listid); //モデルの描画

            break;

        case OBJ3_MARK_ID:
            //glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash2);
            //glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient2);

            //glLightfv(GL_LIGHT0, GL_AMBIENT,ambi2);
            //glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor2);
            //glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny2);

            glColor4f(1.0, 1.0, 1.0, 0.5);
            glTranslatef(0.0,0.0,-120.0);
            glutSolidCube(120.0); // 100.0[mm]の立方体を描画

    }

   

    glDisable(GL_LIGHTING);

    glDisable(GL_DEPTH_TEST);
}


プログラム全体

コード:

#ifdef _WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>

#include <io.h> //テクスチャ

#include <fcntl.h> //stl用に追加
#include <math.h> //stl用に追加


#ifndef __APPLE__
#include <GL/gl.h>
#include <GL/glut.h>
#else
#include <OpenGL/gl.h>
#include <GLUT/glut.h>
#endif
#include <AR/gsub.h>
#include <AR/video.h>
#include <AR/param.h>
#include <AR/ar.h>



/*パターンファイル マーカーの数を2つにする*/

#define OBJ_NUM 3 //使用するマーカーの個数 

//----- 
#define OBJ1_MARK_ID 1 // マーカーID 
#define OBJ1_PATT_NAME "Data/patt.hiro" // パターンファイル名 
#define OBJ1_SIZE 80.0 //バターンの幅(80mm)

//----- 

#define OBJ2_MARK_ID 2 // マーカーID 
#define OBJ2_PATT_NAME "Data/patt.Kanji" // パターンファイル名 
#define OBJ2_SIZE 80.0 //バターンの幅(80mm)

//-----

#define OBJ3_MARK_ID 3 // マーカーID 
#define OBJ3_PATT_NAME "Data/patt.sample1" // パターンファイル名 
#define OBJ3_SIZE 80.0 //バターンの幅(80mm)



typedef struct {
    char* patt_name; //パターンファイル名
    int patt_id; //パターンID
    int mark_id; //マーカーID 
    int visible; //検出フラグ 
    double width; //パターンの幅(mm単位) 
    double center[3]; //パターンの中心座標 
    double trans[3][4]; //座標変換行列 

}OBJECT_T;

//----- 

OBJECT_T object[OBJ_NUM] = {

    {OBJ1_PATT_NAME, -1, OBJ1_MARK_ID, 0, OBJ1_SIZE, {0.0, 0.0} },

    {OBJ2_PATT_NAME, -1, OBJ2_MARK_ID, 0, OBJ2_SIZE, {0.0, 0.0} },

    {OBJ3_PATT_NAME, -1, OBJ3_MARK_ID, 0, OBJ3_SIZE, {0.0, 0.0} }

};





//
// Camera configuration.
//
#ifdef _WIN32
char* vconf = "Data\\WDM_camera_flipV.xml";
#else
char* vconf = "";
#endif

#pragma warning(disable : 4996) //fopen エラーを受け付けない

int             xsize, ysize;
int             thresh = 100;
int             count = 0;

char* cparam_name = "Data/my_camera_para_kotei.dat"; //後でmy_camera_para.datに変更する
ARParam         cparam;

//char* patt_name = "Data/patt.hiro";
//int             patt_id;
//double          patt_width = 80.0;
//double          patt_center[2] = { 0.0, 0.0 };
//double          patt_trans[3][4];




/* 3次元データ */
GLuint listid;// ディスプレイ・リストのID
char* filename = "3D/Sheep.stl";// STLファイル
static GLfloat exDt[1000000][3];// 頂点の座標
static int exNo[1000000][3];// 面を構成する頂点
static GLfloat exVec[1000000][3];// 法線ベクトル




static void   init(void);
static void   cleanup(void);
static void   keyEvent(unsigned char key, int x, int y);
static void   mainLoop(void);
static void   draw(int mid,double patt_trans[3][4]);
static void   readStlData(void);


int main(int argc, char** argv)
{
    /* GLUTの初期化 */
    glutInit(&argc, argv);

    /*ARアプリケーションの初期化*/
    init();


    /* STLデータの読み込み */
    readStlData();


    arVideoCapStart();
    argMainLoop(NULL, keyEvent, mainLoop);
    return (0);
}

static void   keyEvent(unsigned char key, int x, int y)
{
    /* quit if the ESC key is pressed */
    if (key == 0x1b) {
        printf("*** %f (frame/sec)\n", (double)count / arUtilTimer());
        cleanup();
        exit(0);
    }
}

/* main loop */
static void mainLoop(void)
{
    ARUint8* dataPtr;
    ARMarkerInfo* marker_info;
    int             marker_num;
    int             i, j, k;

    /* カメラ画像の取得 */
    if ((dataPtr = (ARUint8*)arVideoGetImage()) == NULL) {
        arUtilSleep(2);
        return;
    }
    if (count == 0) arUtilTimerReset();
    count++;

    /*キャプチャした画像の表示*/
    argDrawMode2D();
    argDispImage(dataPtr, 0, 0);

    /* マーカーの検出 */
    if (arDetectMarker(dataPtr, thresh, &marker_info, &marker_num) < 0) {
        cleanup();
        exit(0);
    }

    /*次の画像をキャプチャ*/
    arVideoCapNext();

    /*デプス・バッファの初期化*/
    glClearDepth(1.0); //デプス・バッファの消去値
    glClear(GL_DEPTH_BUFFER_BIT); //デプス・バッファの初期化



    /* マーカーの一致度を判定 */
    for (i = 0; i < OBJ_NUM; i++) {
        k = -1;
        for (j = 0; j < marker_num; j++) {
            if (object[i].patt_id == marker_info[j].id) {
                if (k == -1) k = j;
                else if (marker_info[k].cf < marker_info[j].cf) k = j;
            }
        }

        //マーカーが見つからなかったとき
        if (k == -1) {
            object[i].visible = 0;
            continue;
        }

        /* 座標変換行列を取得 */
        else {
            arGetTransMat(&marker_info[k], object[i].center, object[i].width, object[i].trans);
            object[i].visible = 1;
        }
        draw(object[i].mark_id,object[i].trans);
    }

    argSwapBuffers();
}

static void init(void)
{
    ARParam  wparam;
    int i; //ループカウンタ


    /* ビデオデバイスの設定 */
    if (arVideoOpen(vconf) < 0) exit(0);
    /* ウィンドウサイズの取得 */
    if (arVideoInqSize(&xsize, &ysize) < 0) exit(0);
    printf("Image size (x,y) = (%d,%d)\n", xsize, ysize);

    /* カメラパラメーターの読み込み */
    if (arParamLoad(cparam_name, 1, &wparam) < 0) {
        printf("Camera parameter load error !!\n");
        exit(0);
    }
    /*カメラパラメーターの初期化*/
    arParamChangeSize(&wparam, xsize, ysize, &cparam);
    arInitCparam(&cparam);
    printf("*** Camera Parameter ***\n");
    arParamDisp(&cparam);

    /*パターンファイルの読み込み*/
    for (i = 0; i < OBJ_NUM; i++) {
        if ((object[i].patt_id = arLoadPatt(object[i].patt_name)) < 0) {
            printf("pattern load error !!\n", object[i].patt_name);
            exit(0);
        }
    }

    /* gsubライブラリの初期化 */
    argInit(&cparam, 1.0, 0, 0, 0, 0);


}

/* cleanup function called when program exits */
static void cleanup(void)
{
    arVideoCapStop();
    arVideoClose();
    argCleanup();
}

static void draw(int mid,double patt_trans[3][4])
{
    double    gl_para[16];
    GLfloat   mat_ambient1[] = { 0.7, 0.7, 0.7, 1.0 };
    GLfloat   mat_flash1[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat   mat_flash_shiny[] = { 50.0 };
    GLfloat   light_position[] = { 100.0,-200.0,200.0,0.0 };
    GLfloat   ambi[] = { 0.1, 0.1, 0.1, 0.1 };
    GLfloat   lightZeroColor[] = { 0.9 ,0.9,0.9,1.0 };
 


    GLfloat   mat_ambient2[] = { 1.0 ,1.0, 1.0, 0.0 };
    GLfloat   mat_flash2[] = { 1.0, 1.0, 1.0, 0.0 };
    GLfloat   mat_flash_shiny2[] = { 0.0 };
    GLfloat   ambi2[] = { 1.0, 1.0, 1.0, 0.0 };
    GLfloat   lightZeroColor2[] = { 1.0 ,1.0,1.0,0.0 };

    /*3Dオブジェクトの描画準備*/
    argDrawMode3D();
    argDraw3dCamera(0, 0);
   // glClearDepth(1.0);

    //glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST); //隠面消去・有効
    glDepthFunc(GL_LEQUAL); //デプス・テスト

    /* 座標変換行列の読み込み */
    argConvGlpara(patt_trans, gl_para); //ARToolkit->OpenGL
    glMatrixMode(GL_MODELVIEW); //行列変換モード・モデルビュー
    glLoadMatrixd(gl_para); //読み込む行列を指定

    /*ライティング*/
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);

 
    
    glMatrixMode(GL_MODELVIEW);
    glTranslatef(0.0, 0.0, 25.0);

    switch(mid) {
        case OBJ1_MARK_ID:
            glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash1);
            glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
            glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);
            glCallList(listid); //モデルの描画
            break;

        case OBJ2_MARK_ID:
            glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash1);
            glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
            glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);
            glCallList(listid); //モデルの描画

            break;

        case OBJ3_MARK_ID:
            //glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash2);
            //glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient2);

            //glLightfv(GL_LIGHT0, GL_AMBIENT,ambi2);
            //glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor2);
            //glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny2);

            glColor4f(1.0, 1.0, 1.0, 0.5);
            glTranslatef(0.0,0.0,-120.0);
            glutSolidCube(120.0); // 100.0[mm]の立方体を描画

    }

   

    glDisable(GL_LIGHTING);

    glDisable(GL_DEPTH_TEST);
}



// STLデータの読み込み 



static void readStlData(void)
{
    FILE* handle;    //ファイル ハンドル 
    char buf[256];  //ファイルから読み込んだデータ 
    int v;              //頂点の数
    int f;              //面の数 
    long p1, p2, p3;    //面を構成する頂点 
    int L;              //ファセットの個数 
    WORD m;             //空白データ 
    float x1, y1, z1;   //頂点1
    float x2, y2, z2;   //頂点2
    float x3, y3, z3;   //頂点3 
    float vx, vy, vz;   //法線ベクトル 
    float cx, cy, cz;   //オブジェクトの中心
    float len;          //原点から頂点までの空間距離 
    float maxlen;       //空間距離の最大値 
    GLfloat scale = 100.0;//1単位の長さ(mm单位) 
    GLfloat zmin;       //z軸方向の最小値


    int i;  //ループカウンタ 

    /*--STLファイルの読み込みーー*/
    handle = fopen(filename, "rb");

    //ファイルヘッダーの読み込み 
    if ((fread(buf, sizeof(char), 80, handle) == -1)) {
        fclose(handle);
        return;
    }

    //ファセットの個数を取得 
    if ((fread(&L, sizeof(int), 1, handle) == -1)) {
        fclose(handle);
        return;
    }

    //ファセットの読み込み 
    v = 0;
    f = 0;
    for (i = 0; i < L; i++) {
        if (v >= 100000) break;
        //法線ベクトル 
        fread(&vx, sizeof(float), 1, handle);
        fread(&vy, sizeof(float), 1, handle);
        fread(&vz, sizeof(float), 1, handle);

        //頂点1
        fread(&x1, sizeof(float), 1, handle);
        fread(&y1, sizeof(float), 1, handle);
        fread(&z1, sizeof(float), 1, handle);

        //頂点2
        fread(&x2, sizeof(float), 1, handle);
        fread(&y2, sizeof(float), 1, handle);
        fread(&z2, sizeof(float), 1, handle);

        //頂点3
        fread(&x3, sizeof(float), 1, handle);
        fread(&y3, sizeof(float), 1, handle);
        fread(&z3, sizeof(float), 1, handle);

        //空白データ
        fread(&m, sizeof(WORD), 1, handle);

        //配列に入れる 
        exDt[v][0] = x1; //頂点1 x
        exDt[v][1] = y1; //      y
        exDt[v][2] = z1; //      z
        v++;

        exDt[v][0] = x2; //頂点2 x
        exDt[v][1] = y2; //      y
        exDt[v][2] = z2; //      z
        v++;

        exDt[v][0] = x3; //頂点3 x
        exDt[v][1] = y3; //      y
        exDt[v][2] = z3; //      z
        v++;

        exNo[i][0] = v - 3; //面を構成する頂点x
        exNo[i][1] = v - 2; //面を構成する頂点y
        exNo[i][2] = v - 1; //面を構成する頂点z

        exVec[i][0] = vx; // 法線ベクトルx
        exVec[i][1] = vy; // 法線ベクトルy
        exVec[i][2] = vz; // 法線ベクトルz 
        f++;
    }
    fclose(handle);

    //頂点の数が足りないとき 
    if (v < 3) return;

    /*--オブジェクトの中心を調整--*/
    //座標の平均を求める
    cx = 0.0;
    cy = 0.0;
    cz = 0.0;

    for (i = 0; i < v; i++) {
        cx = cx + exDt[i][0];
        cy = cy + exDt[i][1];
        cz = cz + exDt[i][2];
    }
    cx = cx / v;
    cy = cy / v;
    cz = cz / v;

    //オブジェクトの中心を原点に移動
    for (i = 0; i < v; i++) {
        exDt[i][0] = exDt[i][0] - cx;
        exDt[i][1] = exDt[i][1] - cy;
        exDt[i][2] = exDt[i][2] - cz;
    }

    /*--オブジェクトの大きさを調整--*/

    //空間距離の最大値を求める
    maxlen = 0.0;
    for (i = 0; i < v; i++) {
        len = sqrt(exDt[i][0] * exDt[i][0] +
            exDt[i][1] * exDt[i][1] +
            exDt[i][2] * exDt[i][2]);
        if (len > maxlen) maxlen = len;
    }

    //オブジェクトを指定したサイズに変更
    zmin = 100000.0;
    for (i = 0; i < v; i++) {
        exDt[i][0] = (exDt[i][0] / maxlen) * scale;
        exDt[i][1] = (exDt[i][1] / maxlen) * scale;
        exDt[i][2] = (exDt[i][2] / maxlen) * scale;

        if (exDt[i][2] < zmin) zmin = exDt[i][2];
    }

    /*-- ディスプレイ・リストの作成--*/
    listid = glGenLists(1);
    glNewList(listid, GL_COMPILE);

    //z軸方向の移動
    glTranslatef(0.0, 0.0, -zmin);

    for (i = 0; i < f; i++) {
        //面を構成する頂点の取得
        p1 = exNo[i][0];
        p2 = exNo[i][1];
        p3 = exNo[i][2];

        //多角形の描画
        glBegin(GL_POLYGON);
        glNormal3f(exVec[i][0], exVec[i][1], exVec[i][2]);
        glVertex3f(exDt[p1][0], exDt[p1][1], exDt[p1][2]);
        glVertex3f(exDt[p2][0], exDt[p2][1], exDt[p2][2]);
        glVertex3f(exDt[p3][0], exDt[p3][1], exDt[p3][2]);
        glEnd();
    }

    glEndList();
}



アバター
あたっしゅ
記事: 664
登録日時: 13年前
住所: 東京23区
連絡を取る:

Re: C言語 3Dオブジェクトの半透明化をしたいです

#2

投稿記事 by あたっしゅ » 2年前

東上☆海美☆「
謹賀新年みみ。
検索しただけで、プログラムを作って確かめたわけではないですが...


https://okwave.jp/qa/q4285172.html
OpenGL で描画するテクスチャのアルファ値(透明度)を変更したい| OKWAVE(ja)

http://www.oit.ac.jp/is/L231/~whashimo/ ... index.html
OpenGL 勉強会用 資料のページ(ja)


とりあえず、3D だと、

> さて,実際に混合処理をさせたい物体には,物体の描画コマンド直前で

> glEnable(GL_BLEND);

> と混合処理を有効にします.物体を描画する際には,色の設定で

> glColor4f(1.0, 1.0, 1.0, 0.2);

> というように第4引数でアルファ値を設定するのを忘れずに.最後に

> glDisable(GL_BLEND);

> で混合処理を無効にします.挟み込まれた部分だけ混合処理がおこなわれます.

GL_BLEND を有効にする必要があるようだみみ。」
烏賊賀 出支貴(いかが・でしたか)「いかがでしたか ?」
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

返信

“C言語何でも質問掲示板” へ戻る