スポンサーリンク

C++でモデルを表示するためのコードをBlender Pythonから出力する。

試験的なプログラムを書くだけでいちいちモデルを読み込むライブラリを使うのが面倒なので、Blender PythonでC++OpenGLのコードをprintする。まだやってなかったっけという感じなんだがやっていたら申し訳ない。

import bpy
import sys

def as_cpp_array(outputto):
    obj = bpy.context.active_object

    mesh = obj.data
    
    pvecname = "points"   # 頂点データの配列の変数名
    vnvecname = "vnorms"  # 頂点法線の配列の変数名
    fvecname = "faces"    # 面データの配列の変数名
    fnvecname = "fnorms"  # 面法線の配列の変数名

    print("/////////////////////////////////////")

    if not pvecname is None:
        print("//std::vector<std::array<float, 3> > ",pvecname,";",file=outputto)

    if not vnvecname  is None:
        print("//std::vector<std::array<float, 3> > ",vnvecname,";",file=outputto)

    if not fvecname  is None:
        print("//std::vector<std::array<int, 3> > ",fvecname,";",file=outputto)

    if not fnvecname  is None:
        print("//std::vector<std::array<float, 3> > ",fnvecname,";",file=outputto)
    
    
    if not pvecname is None:
        for v in mesh.vertices:
            print(
                pvecname +
                ".push_back({",
                v.co.x,",",
                v.co.y,",",
                v.co.z,
                "});",
                file=outputto
                )
                
    if not vnvecname is None:
        for v in mesh.vertices:
            print(
                vnvecname +
                ".push_back({",
                v.normal.x,",",
                v.normal.y,",",
                v.normal.z,
                "});",
                file=outputto
                )



    if not fvecname is None:
        for f in mesh.polygons:
            print(
                fvecname + 
                ".push_back({",
                f.vertices[0],",",
                f.vertices[1],",",
                f.vertices[2],
                "});",
                file=outputto                
                )
                
    if not fnvecname is None:
        for f in mesh.polygons:
            print(
                fnvecname +
                ".push_back({",
                f.normal.x,",",
                f.normal.y,",",
                f.normal.z,
                "});",
                file=outputto
                )
                    
        

as_cpp_array(sys.stdout)

これをactive_objectに対して走らせると、例えば以下のような結果が得られる。

/////////////////////////////////////
//std::vector<std::array<float, 3> > points ;
//std::vector<std::array<float, 3> > vnorms ;
//std::vector<std::array<int, 3> > faces ;
//std::vector<std::array<float, 3> > fnorms ;
points.push_back({ 0.0 , 0.0 , -0.57135009765625 });
points.push_back({ 0.4134289026260376 , -0.3003701865673065 , -0.25551632046699524 });
points.push_back({ -0.15791259706020355 , -0.4860132336616516 , -0.25551632046699524 });
points.push_back({ -0.5110297799110413 , 0.0 , -0.25551632046699524 });
points.push_back({ -0.15791259706020355 , 0.4860132336616516 , -0.25551632046699524 });
points.push_back({ 0.4134289026260376 , 0.3003701865673065 , -0.25551632046699524 });
points.push_back({ 0.15791259706020355 , -0.4860132336616516 , 0.25551632046699524 });
points.push_back({ -0.4134289026260376 , -0.3003701865673065 , 0.25551632046699524 });
points.push_back({ -0.4134289026260376 , 0.3003701865673065 , 0.25551632046699524 });
points.push_back({ 0.15791259706020355 , 0.4860132336616516 , 0.25551632046699524 });
points.push_back({ 0.5110297799110413 , 0.0 , 0.25551632046699524 });
points.push_back({ 0.0 , 0.0 , 0.57135009765625 });
vnorms.push_back({ 0.0 , 0.0 , -1.0 });
vnorms.push_back({ 0.7235938310623169 , -0.5257118344306946 , -0.44718772172927856 });
vnorms.push_back({ -0.2763756215572357 , -0.8506424427032471 , -0.44718772172927856 });
vnorms.push_back({ -0.8944059610366821 , 0.0 , -0.44718772172927856 });
vnorms.push_back({ -0.2763756215572357 , 0.8506424427032471 , -0.44718772172927856 });
vnorms.push_back({ 0.7235938310623169 , 0.5257118344306946 , -0.44718772172927856 });
vnorms.push_back({ 0.2763756215572357 , -0.8506424427032471 , 0.44718772172927856 });
vnorms.push_back({ -0.7235938310623169 , -0.5257118344306946 , 0.44718772172927856 });
vnorms.push_back({ -0.7235938310623169 , 0.5257118344306946 , 0.44718772172927856 });
vnorms.push_back({ 0.2763756215572357 , 0.8506424427032471 , 0.44718772172927856 });
vnorms.push_back({ 0.8944059610366821 , 0.0 , 0.44718772172927856 });
vnorms.push_back({ 0.0 , 0.0 , 1.0 });
faces.push_back({ 0 , 1 , 2 });
faces.push_back({ 1 , 0 , 5 });
faces.push_back({ 0 , 2 , 3 });
faces.push_back({ 0 , 3 , 4 });
faces.push_back({ 0 , 4 , 5 });
faces.push_back({ 1 , 5 , 10 });
faces.push_back({ 2 , 1 , 6 });
faces.push_back({ 3 , 2 , 7 });
faces.push_back({ 4 , 3 , 8 });
faces.push_back({ 5 , 4 , 9 });
faces.push_back({ 1 , 10 , 6 });
faces.push_back({ 2 , 6 , 7 });
faces.push_back({ 3 , 7 , 8 });
faces.push_back({ 4 , 8 , 9 });
faces.push_back({ 5 , 9 , 10 });
faces.push_back({ 6 , 10 , 11 });
faces.push_back({ 7 , 6 , 11 });
faces.push_back({ 8 , 7 , 11 });
faces.push_back({ 9 , 8 , 11 });
faces.push_back({ 10 , 9 , 11 });
fnorms.push_back({ 0.18759654462337494 , -0.5773536562919617 , -0.7946510910987854 });
fnorms.push_back({ 0.6070646643638611 , 0.0 , -0.7946524620056152 });
fnorms.push_back({ -0.4911220967769623 , -0.35682904720306396 , -0.7946522235870361 });
fnorms.push_back({ -0.4911220967769623 , 0.35682904720306396 , -0.7946522235870361 });
fnorms.push_back({ 0.18759654462337494 , 0.5773536562919617 , -0.7946510910987854 });
fnorms.push_back({ 0.9822461009025574 , 0.0 , -0.18759679794311523 });
fnorms.push_back({ 0.3035355508327484 , -0.9341715574264526 , -0.1875891536474228 });
fnorms.push_back({ -0.7946491241455078 , -0.5773593187332153 , -0.1875869631767273 });
fnorms.push_back({ -0.7946491241455078 , 0.5773593187332153 , -0.1875869780778885 });
fnorms.push_back({ 0.3035355508327484 , 0.9341715574264526 , -0.1875891238451004 });
fnorms.push_back({ 0.7946491241455078 , -0.5773593187332153 , 0.1875869780778885 });
fnorms.push_back({ -0.3035355508327484 , -0.9341715574264526 , 0.1875891238451004 });
fnorms.push_back({ -0.9822461009025574 , 0.0 , 0.18759679794311523 });
fnorms.push_back({ -0.3035355508327484 , 0.9341715574264526 , 0.1875891536474228 });
fnorms.push_back({ 0.7946491241455078 , 0.5773593187332153 , 0.1875869631767273 });
fnorms.push_back({ 0.4911220967769623 , -0.35682904720306396 , 0.7946522235870361 });
fnorms.push_back({ -0.18759654462337494 , -0.5773536562919617 , 0.7946510910987854 });
fnorms.push_back({ -0.6070646643638611 , 0.0 , 0.7946524620056152 });
fnorms.push_back({ -0.18759654462337494 , 0.5773536562919617 , 0.7946510910987854 });
fnorms.push_back({ 0.4911220967769623 , 0.35682904720306396 , 0.7946522235870361 });

これをC++で書いたOpenGLの表示コードに貼り付ける。

#include <iostream>
#include <cstdlib>

#include <Windows.h>
#include <gl/GL.h>
#include <gl/glfw/glfw3.h>

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glfw3.lib")

#include <gl/GLU.h>
#pragma comment(lib,"glu32.lib")

#include<vector>
#include<array>

struct d3item {
  std::vector<std::array<float, 3> >  points;
  std::vector<std::array<float, 3> >  vnorms;
  std::vector<std::array<int, 3> >  faces;
  std::vector<std::array<float, 3> >  fnorms;

public:
  void init() {

    points.push_back({ 0.0 , 0.0 , -0.57135009765625 });
    points.push_back({ 0.4134289026260376 , -0.3003701865673065 , -0.25551632046699524 });
    points.push_back({ -0.15791259706020355 , -0.4860132336616516 , -0.25551632046699524 });
    points.push_back({ -0.5110297799110413 , 0.0 , -0.25551632046699524 });
    points.push_back({ -0.15791259706020355 , 0.4860132336616516 , -0.25551632046699524 });
    points.push_back({ 0.4134289026260376 , 0.3003701865673065 , -0.25551632046699524 });
    points.push_back({ 0.15791259706020355 , -0.4860132336616516 , 0.25551632046699524 });
    points.push_back({ -0.4134289026260376 , -0.3003701865673065 , 0.25551632046699524 });
    points.push_back({ -0.4134289026260376 , 0.3003701865673065 , 0.25551632046699524 });
    points.push_back({ 0.15791259706020355 , 0.4860132336616516 , 0.25551632046699524 });
    points.push_back({ 0.5110297799110413 , 0.0 , 0.25551632046699524 });
    points.push_back({ 0.0 , 0.0 , 0.57135009765625 });
    vnorms.push_back({ 0.0 , 0.0 , -1.0 });
    vnorms.push_back({ 0.7235938310623169 , -0.5257118344306946 , -0.44718772172927856 });
    vnorms.push_back({ -0.2763756215572357 , -0.8506424427032471 , -0.44718772172927856 });
    vnorms.push_back({ -0.8944059610366821 , 0.0 , -0.44718772172927856 });
    vnorms.push_back({ -0.2763756215572357 , 0.8506424427032471 , -0.44718772172927856 });
    vnorms.push_back({ 0.7235938310623169 , 0.5257118344306946 , -0.44718772172927856 });
    vnorms.push_back({ 0.2763756215572357 , -0.8506424427032471 , 0.44718772172927856 });
    vnorms.push_back({ -0.7235938310623169 , -0.5257118344306946 , 0.44718772172927856 });
    vnorms.push_back({ -0.7235938310623169 , 0.5257118344306946 , 0.44718772172927856 });
    vnorms.push_back({ 0.2763756215572357 , 0.8506424427032471 , 0.44718772172927856 });
    vnorms.push_back({ 0.8944059610366821 , 0.0 , 0.44718772172927856 });
    vnorms.push_back({ 0.0 , 0.0 , 1.0 });
    faces.push_back({ 0 , 1 , 2 });
    faces.push_back({ 1 , 0 , 5 });
    faces.push_back({ 0 , 2 , 3 });
    faces.push_back({ 0 , 3 , 4 });
    faces.push_back({ 0 , 4 , 5 });
    faces.push_back({ 1 , 5 , 10 });
    faces.push_back({ 2 , 1 , 6 });
    faces.push_back({ 3 , 2 , 7 });
    faces.push_back({ 4 , 3 , 8 });
    faces.push_back({ 5 , 4 , 9 });
    faces.push_back({ 1 , 10 , 6 });
    faces.push_back({ 2 , 6 , 7 });
    faces.push_back({ 3 , 7 , 8 });
    faces.push_back({ 4 , 8 , 9 });
    faces.push_back({ 5 , 9 , 10 });
    faces.push_back({ 6 , 10 , 11 });
    faces.push_back({ 7 , 6 , 11 });
    faces.push_back({ 8 , 7 , 11 });
    faces.push_back({ 9 , 8 , 11 });
    faces.push_back({ 10 , 9 , 11 });
    fnorms.push_back({ 0.18759654462337494 , -0.5773536562919617 , -0.7946510910987854 });
    fnorms.push_back({ 0.6070646643638611 , 0.0 , -0.7946524620056152 });
    fnorms.push_back({ -0.4911220967769623 , -0.35682904720306396 , -0.7946522235870361 });
    fnorms.push_back({ -0.4911220967769623 , 0.35682904720306396 , -0.7946522235870361 });
    fnorms.push_back({ 0.18759654462337494 , 0.5773536562919617 , -0.7946510910987854 });
    fnorms.push_back({ 0.9822461009025574 , 0.0 , -0.18759679794311523 });
    fnorms.push_back({ 0.3035355508327484 , -0.9341715574264526 , -0.1875891536474228 });
    fnorms.push_back({ -0.7946491241455078 , -0.5773593187332153 , -0.1875869631767273 });
    fnorms.push_back({ -0.7946491241455078 , 0.5773593187332153 , -0.1875869780778885 });
    fnorms.push_back({ 0.3035355508327484 , 0.9341715574264526 , -0.1875891238451004 });
    fnorms.push_back({ 0.7946491241455078 , -0.5773593187332153 , 0.1875869780778885 });
    fnorms.push_back({ -0.3035355508327484 , -0.9341715574264526 , 0.1875891238451004 });
    fnorms.push_back({ -0.9822461009025574 , 0.0 , 0.18759679794311523 });
    fnorms.push_back({ -0.3035355508327484 , 0.9341715574264526 , 0.1875891536474228 });
    fnorms.push_back({ 0.7946491241455078 , 0.5773593187332153 , 0.1875869631767273 });
    fnorms.push_back({ 0.4911220967769623 , -0.35682904720306396 , 0.7946522235870361 });
    fnorms.push_back({ -0.18759654462337494 , -0.5773536562919617 , 0.7946510910987854 });
    fnorms.push_back({ -0.6070646643638611 , 0.0 , 0.7946524620056152 });
    fnorms.push_back({ -0.18759654462337494 , 0.5773536562919617 , 0.7946510910987854 });
    fnorms.push_back({ 0.4911220967769623 , 0.35682904720306396 , 0.7946522235870361 });
  }
  void draw() {

    auto color = std::array<float, 4>{1.0, 0, 0, 1};
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color.data());
    glColor3d(1, 1, 1);
    glBegin(GL_TRIANGLES);
    for (size_t f = 0; f < faces.size(); f++) {
      
      //面法線
      glNormal3fv(fnorms[f].data());

      size_t p0 = faces[f][0];
      size_t p1 = faces[f][1];
      size_t p2 = faces[f][2];

      //頂点法線
      //glNormal3fv(vnorms[p0].data());
      glVertex3fv(points[p0].data());

      //頂点法線
      //glNormal3fv(vnorms[p1].data());
      glVertex3fv(points[p1].data());

      //頂点法線
      //glNormal3fv(vnorms[p2].data());
      glVertex3fv(points[p2].data());
    }
    glEnd();

  }
};
int main()
{
  ////////////////////////////////////////////////////////////////////////////////
  // GLFW の初期化
  if (glfwInit() == GL_FALSE) {
    // 初期化に失敗したら終了
    return 1;
  }

  ////////////////////////////////////////////////////////////////////////////////
  // ウィンドウを作成
  GLFWwindow* window = glfwCreateWindow(
    400,           //width
    400,           //height
    "window title",//title 
    NULL,          //monitor
    NULL           //share
  );

  ////////////////////////////////////////////////////////////////////////////////
  // ウィンドウを作成できなければ終了
  if (window == nullptr) {
    glfwTerminate();
    return 1;
  }

  d3item item;
  item.init();

  glfwMakeContextCurrent(window);

  while (glfwWindowShouldClose(window) == GL_FALSE) {

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);

    const GLfloat lightPos[] = { -3 , 0 , 0 , 1 };
    const GLfloat lightCol[] = { 1 , 1 , 1 , 1 };
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightCol);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);

    glEnable(GL_DEPTH_TEST);

    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /////////////////////
    // 描画
    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    gluPerspective(45, width / (double)height, 0.01, 10);
    {
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glLoadIdentity();

      static int angle = 0;

      glTranslated(0, 0, -2);
      glRotated(angle++, 1, 1, 1);

      item.draw();

      glPopMatrix();
    }
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    //
    /////////////////////

    //glFlush();

    glfwSwapBuffers(window);


    // イベント取得
    glfwWaitEvents();

  }

  glfwTerminate();

}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: