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

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
tui

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

#1

投稿記事 by tui » 6年前

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

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

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

アドバイスお願いします。

コード:

#include"stlreader.h"

#define STL_FILE "C:\\Users\\onower\\Desktop\\nsx_concept_LOW.stl"


using namespace std;

float light_pos[] = { -5.0, 5.0, 5.0, 1.0 };

//プロトタイプ宣言
void display(void);
void reshape(int w, int h);
void draw();
void init();
void DRAW_XYZ();
void MouseWheel(int wheel, int direction, int x, int y);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);

Triangle *triangles;
int num;
STLreader stlreader;
int rate = 1.0;
double xAngle = 0.0, yAngle = 0.0;

int main(int argc, char *argv[])
{
    glutInitWindowPosition(128, 128);
    glutInitWindowSize(800, 800);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("argv[0]");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutMouseWheelFunc(MouseWheel);
    //    glutKeyboardFunc(keyboard);
    glutMainLoop();

        if (triangles)
            delete[] triangles;

    return 0;
}


void display(void)
{


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);



    glLoadIdentity();
    gluLookAt(10.0 * rate,15.0 * rate ,10.0 * rate, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //視点の設定

    //glLightfv(GL_LIGHT0, GL_POSITION, light_pos);

    glRotated(xAngle, 1, 0, 0);
    glRotated(yAngle, 0, 1, 0);


    draw();  //描画

    glutSwapBuffers();  //ウィンドウに出力



    //double* getNormalVert(Triangle trinangles);

}


void reshape(int w, int h)
{
    glViewport(0, 0, w, h);  //ビューポートの設定
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0); //視野の設定
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


}



void draw()
{


     DRAW_XYZ(); //XYZ軸の描画    

     glBegin(GL_TRIANGLES);

     glColor3f(1.0, 0.0, 0.0);


    for (int i = 0; i < num; i++)   //stlデータの描画
    {

        glNormal3dv(triangles[i].nornVec);
        glVertex3dv(triangles[i].pnt1);
        glVertex3dv(triangles[i].pnt2);
        glVertex3dv(triangles[i].pnt3);




    }

    glEnd();
    glFlush();


}


void init()
{

    if (triangles)
        delete[] triangles;

    num = stlreader.countTriangles(string(STL_FILE));  //stlデータを構成しているポリゴンの数のをカウント


    if (!(num = stlreader.countTriangles(string(STL_FILE))))

        return;

    triangles = new Triangle[num];

    stlreader.readASCIISTLFile(STL_FILE, triangles);

    stlreader.readBinarySTLFile(STL_FILE, triangles);

    glClearColor(1.0, 1.0, 1.0, 1.0);

}



void DRAW_XYZ()
{
    glDisable(GL_LIGHTING);
    glDisable(GL_LIGHT0);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_NORMALIZE);

    glBegin(GL_LINES);

    glColor3d(0, 1, 0);//x軸緑
    glVertex2d(-1000, 0);
    glVertex2d(1000, 0);

    glColor3d(1, 0, 0);//y軸赤
    glVertex2d(0, -1000);
    glVertex2d(0, 1000);

    glColor3d(0, 0, 1);//z軸青
    glVertex3d(0, 0, -1000);
    glVertex3d(0, 0, 1000);

    glEnd();




    glEnable(GL_DEPTH_TEST);
    glEnable(GL_NORMALIZE);
    //glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
}


void MouseWheel(int wheelnumber, int direction, int x, int y)
{

    if (direction > 0)
    {
        rate++;

    }
    else
    {
        rate--;

    }

    glutPostRedisplay();

}


int xStart, yStart;
bool mouseFlag = GL_FALSE;
void mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON &&state == GLUT_DOWN)
    {
        xStart = x;
        yStart = y;
        mouseFlag = GL_TRUE;
    }
    else
    {
        mouseFlag = GL_FALSE;

    }

}

void motion(int x, int y)
{
    int xdis, ydis;
    double a = 0.5;

    if (mouseFlag == GL_FALSE)return;

    xdis = x - xStart;
    ydis = y - yStart;

    xAngle += (double)ydis * a;
    yAngle += (double)xdis * a;

    xStart = x;
    yStart = y;
    glutPostRedisplay();
}
ヘッダーファイル

コード:

#include <iostream>
#include <cmath>
#include <string>
#include <fstream>

using namespace std;

struct vert
{
    double pnt1[3];
    double pnt2[3];
    double pnt3[3];
};

struct vert4
{
    double pnt1[4];//x,y,z,w
    double pnt2[4];
    double pnt3[4];
};

struct Triangle {
    double nornVec[3];
    double pnt1[3];
    double pnt2[3];
    double pnt3[3];
    unsigned int index;
};


class STLreader
{

    unsigned int num_tmp_points;//一時的な変数
    unsigned int num_triangles;//三角形の数



public:
    static int countTriangles(string filename)
    {
        //STLファイルのオープン
        ifstream ifs;
        char line[80];
        ifs.open(filename);
        if (ifs.fail())
            return false;
        string str;
        int count = 0;
        int a;
        getline(ifs, str);
        //int h = str.find("solid");
        if (str.find("solid")==-1){
            ifs.close();
            ifs.open(filename, ios::binary);
            if (ifs.fail())
                return false;
            ifs.read(line, 80);
            ifs.read(line, 4);
            return *(int *)line;
        }
        while (getline(ifs, str)){
            a = str.find("normal");
            if (a > 0)
                count++;
        }
        ifs.close();
        return count;
    };

    bool readASCIISTLFile(string filename, Triangle *values)
    {

        //STLファイルのオープン
        ifstream ifs(filename);
        if (ifs.fail())
            return false;

        //vector<mesh> Stldata;
        string str;
        int index = 0, j;
        double x = 0, y = 0, z = 0;
        //tmp_point *tmp_pnt = new tmp_point;

        getline(ifs, str);
        if (0 < str.find("solid"))
            return false;
        //ファイルから座標値の読み込み
        printf("Tring text STL file ...");
        num_tmp_points = 0;
        num_triangles = 0;


        while (getline(ifs, str)){



            //vertexが見つかるまで読み飛ばす
            j = str.find("vertex");
            if (j<0)
                continue;
            //連続する3頂点の読み込みポリゴンを登録
            //tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
            for (int c = 2; c >= 0; c--)
            {
                values[num_triangles].pnt1[c] = atof(str.substr(str.rfind(" ")).c_str());
                str.erase(str.rfind(" "));
                num_tmp_points++;
            }
            //point_array[num_tmp_points-1] = tmp_pnt;

            //tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
            getline(ifs, str);

            for (int c = 2; c >= 0; c--)
            {
                values[num_triangles].pnt2[c] = atof(str.substr(str.rfind(" ")).c_str());
                str.erase(str.rfind(" "));
                //tmp_pnt->index = num_tmp_points;
                num_tmp_points++;
            }
            //point_array[num_tmp_points-1] = tmp_pnt;

            //tmp_pnt = (tmp_point *)malloc(sizeof(tmp_point));
            getline(ifs, str);

            for (int c = 2; c >= 0; c--)
            {
                values[num_triangles].pnt3[c] = atof(str.substr(str.rfind(" ")).c_str());
                str.erase(str.rfind(" "));
                //tmp_pnt->index = num_tmp_points;
                num_tmp_points++;
            }

            values[num_triangles].nornVec[0] = getNormalVert(values[num_triangles])[0];
            values[num_triangles].nornVec[1] = getNormalVert(values[num_triangles])[1];
            values[num_triangles].nornVec[2] = getNormalVert(values[num_triangles])[2];

            values[num_triangles].index = num_triangles;
            num_triangles++;

        }
        ifs.close();
        //fclose(in);
        if (num_triangles > 0)
            printf("Done.\n");
        else
            printf("Failed\n");
        return(num_triangles > 0);

    }

    bool readBinarySTLFile(string STL_file, Triangle *values)
    {
        char line[81];
        float *coord;
        int num;
        FILE *in;
        errno_t error;

        ifstream ifs(STL_file);
        if (ifs.fail())
            return false;


        if ((error = fopen_s(&in,STL_file.c_str(), "rb")) != 0)
        {
            // エラー処理
            //ofs << "Can't open file " << endl;
            fclose(in);
            return false;
        }

        //最初の84ビット分を読み飛ばす
        if (fread(line, 1, 80, in) != 80)
            return false;

        printf("Tring binary STL file ...");
        fread(line, 1, 4, in);
        num = *(int*)line;

        //ofs << "number of triangles: " << num<< endl;
        int j = 0;
        //ofs << "solid model" << endl;
        while (fread(line, 1, 50, in) == 50)
        {
            coord = (float *)line;
            //values[j].nornVec[0] = coord[0];
            //values[j].nornVec[1] = coord[1];
            //values[j].nornVec[2] = coord[2];

            values[j].pnt1[0] = coord[3];
            values[j].pnt1[1] = coord[4];
            values[j].pnt1[2] = coord[5];

            values[j].pnt2[0] = coord[6];
            values[j].pnt2[1] = coord[7];
            values[j].pnt2[2] = coord[8];

            values[j].pnt3[0] = coord[9];
            values[j].pnt3[1] = coord[10];
            values[j].pnt3[2] = coord[11];

            values[j].nornVec[0] = getNormalVert(values[j])[0];
            values[j].nornVec[1] = getNormalVert(values[j])[1];
            values[j].nornVec[2] = getNormalVert(values[j])[2];
            values[j].index = j;
            j++;

        }

        //ofs << "endsolid model" << endl;
        fclose(in);
        //ofs.close();
        if (num > 0)
            printf("Done.\n");
        else
            printf("Failed\n");
        return(num > 0);

    }


    //vec0とvec1の内積の計算
    double dot(double vec0[], double vec1[])
    {
        return (vec0[0] * vec1[0] + vec0[1] * vec1[1] + vec0[2] * vec1[2]);
    }

    void cross(double vec0[], double vec1[], double vec2[])
    {
        vec2[0] = vec0[1] * vec1[2] - vec0[2] * vec1[1];
        vec2[1] = vec0[2] * vec1[0] - vec0[0] * vec1[2];
        vec2[2] = vec0[0] * vec1[1] - vec0[1] * vec1[0];
    }

    void normVec(double vec[])
    {
        double norm;
        norm = sqrt((vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]));
        vec[0] /= norm; vec[1] /= norm; vec[2] /= norm;
    }

    double* getNormalVert(Triangle vertex)
    {
        double normalVec[3] = {};
        double vec1[3] = { vertex.pnt2[0] - vertex.pnt1[0],
                            vertex.pnt2[1] - vertex.pnt1[1],
                            vertex.pnt2[2] - vertex.pnt1[2] };
        double vec2[3] = { vertex.pnt3[0] - vertex.pnt2[0],
                            vertex.pnt3[1] - vertex.pnt2[1],
                            vertex.pnt3[2] - vertex.pnt2[2] };
        cross(vec1, vec2, normalVec);
        normVec(normalVec);//正規化

        return normalVec;
    }


};

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