ただXY平面を表現するだけだと目的に合わないので角度を自由に設定できるようにする。
// グリッド一つ分 class cell { glm::vec3 _min; //始点 glm::vec3 _vecx; //方向1 glm::vec3 _vecy; //方向2 public: cell(glm::vec3 _min_, glm::vec3 _vec_x, glm::vec3 _vec_y) { _min = _min_; _vecx = _vec_x; _vecy = _vec_y; } const glm::vec3& cmin()const { return _min; } const glm::vec3& cvecx()const { return _vecx; } const glm::vec3& cvecy()const { return _vecy; } // セルの中心 glm::vec3 center()const { return _min + _vecx / 2.f + _vecy / 2.f; } };
class grid { std::vector<cell> _cells; int _xcount; int _ycount; float _xwidth; float _ywidth; glm::vec3 _center; public: size_t cellCount()const { return _cells.size(); } cell& operator[](const size_t index) { return _cells[index]; } const cell& operator[](const size_t index)const { return _cells[index]; } grid() {} grid(const grid& g) { _cells = g._cells; _xcount = g._xcount; _ycount = g._ycount; _xwidth = g._xwidth; _ywidth = g._ywidth; _center = g._center; } grid& operator=(const grid& g) { _cells = g._cells; _xcount = g._xcount; _ycount = g._ycount; _xwidth = g._xwidth; _ywidth = g._ywidth; _center = g._center; } grid& operator=(grid&& g) { _cells = std::move(g._cells); _xcount = g._xcount; _ycount = g._ycount; _xwidth = g._xwidth; _ywidth = g._ywidth; _center = g._center; return *this; } // 平面一つ分。xcount × ycountのcellからなる grid( const glm::vec3 vecX, const glm::vec3 vecY, const glm::vec3 center, const float width, const float height, const int xcount, const int ycount) { _xcount = xcount; _ycount = ycount; _xwidth = width; _ywidth = height; _center = center; glm::vec3 NVecX = glm::normalize(vecX); glm::vec3 NVecY = glm::normalize(vecY); //////////////////// _cells.clear(); // セル一個の縦方向、横方向のベクトル。長さはセル一個分 const glm::vec3 CellVX = NVecX * (_xwidth / xcount); const glm::vec3 CellVY = NVecY * (_ywidth / ycount); // 面の始点 const glm::vec3 Start = _center - NVecX * _xwidth / 2.f - NVecY * _ywidth / 2.f; for (size_t y = 0; y < ycount; y++) { for (size_t x = 0; x < xcount; x++) { // 各セルの始点 glm::vec3 from = Start + CellVX * (float)x + CellVY * (float)y; // セルを記録 _cells.push_back( cell( from, CellVX, CellVY ) ); } } } /* p0 p3 +---------+ | | | | | | | | +---------+ p1 p2 */ glm::vec3 p0(const size_t index)const { return _cells[index].cmin(); } glm::vec3 p1(const size_t index)const { return _cells[index].cmin() + _cells[index].cvecx(); } glm::vec3 p2(const size_t index) const { return _cells[index].cmin() + _cells[index].cvecx() + _cells[index].cvecy(); } glm::vec3 p3(const size_t index) const { return _cells[index].cmin() + _cells[index].cvecy(); } };
//! @brief グリッドを表示 //! @param [in] g グリッドオブジェクト //! @param [in] dispcenter セルの中央を表示するか void drawGrid(const grid& g, const bool dispcenter) { glLineWidth(1); glColor3d(1, 1, 1); for (size_t i = 0; i < g.cellCount(); i++) { glBegin(GL_LINE_LOOP); glVertex3fv(glm::value_ptr(g.p0(i))); glVertex3fv(glm::value_ptr(g.p1(i))); glVertex3fv(glm::value_ptr(g.p2(i))); glVertex3fv(glm::value_ptr(g.p3(i))); glEnd(); } if (dispcenter) { glPointSize(1); glColor3d(1, 1, 1); glBegin(GL_POINTS); for (size_t i = 0; i < g.cellCount(); i++) { glVertex3fv( glm::value_ptr(g[i].center())); } glEnd(); } }
grid g( glm::vec3(1,0,0), glm::vec3(0,1,0), glm::vec3(0,0,0), 4.f,4.f, 10,10 ); drawGrid(g, false);
続き。inflateを使って伸長する。
#pragma warning(disable:4996) #include <vector> // 圧縮に必要 #include <zlib.h> #include <cassert> #include <array> // 圧縮に必要 #if _DEBUG #pragma comment(lib,"zlibstaticd.lib") #else #pragma comment(lib,"zlibstatic.lib") #endif constexpr int BUFFER_SIZE = 1000; struct buffer_t { size_t size; std::array<Byte, BUFFER_SIZE> buffer; buffer_t( const size_t _size, const std::array<Byte, BUFFER_SIZE>& data ) : size(_size), buffer(data) {} }; //! @brief ファイルからデータを読み込む //! @param [in] filename ファイル名 //! @param [out] ファイルを読み込んだ、固定長のバッファの一覧 //! @return ファイル一個分のデータ void read_buffer(const char* filename, std::vector< buffer_t >& datalist) { // データの準備 std::array<unsigned char, BUFFER_SIZE> buffer; FILE* fp = fopen(filename, "rb"); do { size_t readsize = fread(buffer.data(), 1, buffer.size(), fp); // データと読み込んだサイズを保存 datalist.emplace_back( readsize, buffer ); } while (feof(fp) == 0); fclose(fp); }
bool my_uncompress( const std::vector< buffer_t >& zippedBuffer, std::vector< buffer_t >& data_list) { z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; //初期化 int ret = inflateInit(&strm); if (ret != Z_OK) { return false; } for (size_t i = 0; i < zippedBuffer.size(); i++) { // これから伸長するデータ。 const buffer_t& inbuffer = zippedBuffer[i]; strm.next_in = (Bytef*)inbuffer.buffer.data(); strm.avail_in = (uInt)inbuffer.size; assert(strm.avail_in != 0); std::array<Byte, BUFFER_SIZE> tmpbuffer; do { strm.next_out = (Bytef*)tmpbuffer.data();// 伸長結果の書き込み先の指定 strm.avail_out = BUFFER_SIZE; // 書き込み先のバッファサイズ ret = inflate(&strm, Z_NO_FLUSH); // 伸長 assert((ret != Z_NEED_DICT) && (ret != Z_STREAM_ERROR) && (ret != Z_DATA_ERROR) && (ret != Z_MEM_ERROR)); uInt have = BUFFER_SIZE - strm.avail_out;// 展開されたデータのサイズ // 結果の出力先に積んでいく data_list.emplace_back(have, tmpbuffer); } while (strm.avail_out == 0); } while (ret != Z_STREAM_END);
// 終了字呼び出す inflateEnd(&strm); return true; }
int main() { // freadで読み込むデータ一覧。 // バッファが小さく一つの配列に収まらない状況を再現するため、 // 小さめの領域のリストとして全てのデータを読み込む std::vector< buffer_t > zippedBuffer; // 圧縮済みデータを用意 read_buffer("C:\\data\\cmp.data", zippedBuffer); std::vector< buffer_t > data_list; // 伸長実行 my_uncompress(zippedBuffer, data_list); // ファイル書き出し FILE* fp = fopen("C:\\data\\uncmp.data", "wb"); for (size_t i = 0; i < data_list.size(); i++) { const buffer_t& data = data_list[i]; fwrite(data.buffer.data(), 1, data.size, fp); } fclose(fp); }
巨大なデータを細切れに読み込んで少しずつ圧縮していく使い方をする。
#pragma warning(disable:4996) #include <vector> // 圧縮に必要 #include <zlib.h> #include <cassert> #include <array> // 圧縮に必要 #if _DEBUG #pragma comment(lib,"zlibstaticd.lib") #else #pragma comment(lib,"zlibstatic.lib") #endif constexpr int BUFFER_SIZE = 1000;
//! @brief 入出力バッファを格納するデータ型。 struct buffer_t { size_t size; //!< 有効なデータが入っているサイズ std::array<Byte, BUFFER_SIZE> buffer; //! @brief 確保したバッファ buffer_t( const size_t _size, const std::array<Byte, BUFFER_SIZE>& data ) : size(_size), buffer(data) {} }; //! @brief ファイルからデータを読み込む //! @param [in] filename ファイル名 //! @param [out] ファイルを読み込んだ、固定長のバッファの一覧 //! @return ファイル一個分のデータ void read_buffer(const char* filename, std::vector< buffer_t >& datalist) { // データの準備 std::array<unsigned char, BUFFER_SIZE> buffer; FILE* fp = fopen(filename, "rb"); do { size_t readsize = fread(buffer.data(), 1, buffer.size(), fp); // データと読み込んだサイズを保存 datalist.emplace_back( readsize, buffer ); } while (feof(fp) == 0); fclose(fp); }
bool my_compress( std::vector<buffer_t>& zippedBuffer, const std::vector< buffer_t >& data_list) { // 構造体の初期化 z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; //初期化 int ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION); if (ret != Z_OK) { return false; } int flush = Z_NO_FLUSH; for (size_t i = 0; i < data_list.size(); i++) { // これから圧縮するデータ。 const buffer_t& inbuffer = data_list[i]; // バッファが小さい場合、読み込みを分割せざるを得ない。 // zlibではデータを複数回に分けて入力し、 // すべて出そろった段階で処理を行えるような構造になっている。 // ここにfreadを書くのもわかりにくいので今回は data_listとしてデータ一覧を用意する strm.next_in = (Bytef*)inbuffer.buffer.data(); //圧縮前データ strm.avail_in = (uInt)inbuffer.size; // 圧縮前データのバイト数 // 全てのデータが処理されたら、一番最後にZ_FINISH設定 // つまり最後の一回だけ特別な処理をする。 if (i == data_list.size() - 1) { flush = Z_FINISH; } else { flush = Z_NO_FLUSH; } // 圧縮関数に渡して処理されたデータを受け取るためのバッファ std::array<Byte, BUFFER_SIZE> tmpbuffer; do { strm.avail_out = BUFFER_SIZE;// 出力先バッファのサイズ strm.next_out = tmpbuffer.data(); // 出力先バッファ ret = deflate(&strm, flush); /* no bad return value */ assert(ret != Z_STREAM_ERROR); /* state not clobbered */ // バッファが全部使われた場合、avail_outは0となる // 従って BUFFER_SIZE - 0 で have==BUFFER_SIZE となる。 //圧縮したデータサイズを取得 unsigned have = BUFFER_SIZE - strm.avail_out; // 結果の出力先に積んでいく zippedBuffer.emplace_back(have,tmpbuffer); } while (strm.avail_out == 0); } // 終了時呼び出す。 deflateEnd(&strm); return true; }
int main() { // 結果の出力先 // 固定長バッファの配列。 // 結果のサイズを一括で確保しない方針の実装。 std::vector<buffer_t> zippedBuffer; // 圧縮データ一覧を用意 // freadで読み込むデータ一覧。 // バッファが小さく一つの配列に収まらない状況を再現するため、 // 小さめの領域のリストとして全てのデータを読み込む std::vector< buffer_t > data_list; // 元データ読込 read_buffer("C:/data/.cipd_client.exe", data_list); // 圧縮実行 my_compress(zippedBuffer, data_list); // ファイル書き出し FILE* fp = fopen("C:\\data\\cmp.data", "wb"); for (size_t i = 0; i < zippedBuffer.size(); i++) { fwrite( zippedBuffer[i].buffer.data(), // バッファの先頭 1, // 1要素のサイズ zippedBuffer[i].size, // 要素数 fp); } fclose(fp); }
本当は伸長もやりたかったが圧縮に結構体力を使ったので次回にする。
以前libpng等で使ったzlibでデータを圧縮してみる。
圧縮時、まずcompressBound に元データのサイズを渡し、最低限その戻り値のバイト数分だけメモリを確保する。
圧縮はcompress関数で行い、結果は第一引数で指定したメモリに書き込まれ、書き込まれたサイズは第二引数destLenに返る。
注意点として、この関数で圧縮されたデータには元データのサイズ情報が入っていない。本来ファイル出力するのであればその情報を何らかの形で入れておくべきだが今回は画面表示して伸長プログラム側に直打ちすることにする。
int compress( Bytef* dest, // 結果の格納先のバッファ uLongf* destLen, // 入力:バッファサイズ ,出力:結果データサイズ const Bytef* source, // 元データ uLong sourceLen // 元データのサイズ );
#pragma warning(disable:4996) #include <vector> #include <filesystem> // 圧縮に必要 #include <zlib.h> // 圧縮に必要 #if _DEBUG #pragma comment(lib,"zlibstaticd.lib") #else #pragma comment(lib,"zlibstatic.lib") #endif
//! @brief 圧縮のテスト //! @param [in] source 圧縮したいデータ //! @return 圧縮後のデータ std::vector< Bytef > compress_test(std::vector<unsigned char>& source) { //圧縮前のデータと //そのデータのサイズを準備 unsigned char* src = source.data(); unsigned int sourceLen = source.size(); // compressBoundの戻り値だけメモリを確保 uLong destLen = compressBound(sourceLen); std::vector< Bytef > dest; dest.resize(destLen); // compressで圧縮。 // destLenは呼び出し時に確保したメモリ量を指定すると // 圧縮後の長さが帰ってくる int ret = compress(dest.data(), &destLen, src, sourceLen); if (ret != Z_OK) { return std::vector< Bytef >(); } // 圧縮後のデータの長さがdestLenなので // 配列をdestLenに切り詰める dest.erase(dest.begin() + destLen, dest.end()); return dest; }
std::vector<unsigned char> read_buffer(const char* filename); int main() { // 圧縮テスト std::vector<unsigned char> buffer = read_buffer("C:/data/.cipd_client.exe"); std::vector< Bytef > cmpressed = compress_test(buffer); // ファイル書き出し FILE* fp = fopen("C:\\data\\cmp.data", "wb"); fwrite(cmpressed.data(), 1, cmpressed.size(), fp); fclose(fp); // 注意 圧縮後データには「元のファイルサイズ」が含まれない // これは、伸長時、結果を格納する領域のサイズを知ることができないことを意味する。 // 従って本来、ファイル出力時には、別途元のサイズを記録しておく必要がある。 // 今回はプログラムを複雑にしないため、画面表示してその値を手動で記録しておく。 printf("for decompress : %d bytes\n", buffer.size()); } //! @brief ファイルからデータを読み込む //! @param [in] filename ファイル名 //! @return ファイル一個分のデータ std::vector<unsigned char> read_buffer(const char* filename) { // データの準備 namespace fs = std::filesystem; std::vector<unsigned char> buffer; uintmax_t size = fs::file_size(filename); FILE* fp = fopen(filename, "rb"); buffer.resize(size); fread(buffer.data(), size, 1, fp); fclose(fp); return buffer; }
int uncompress ( Bytef* dest, // 伸長後のデータ格納先 uLongf* destLen, // 入力時:格納先のメモリサイズ 出力時:結果のメモリサイズ const Bytef* source, // 圧縮されたデータ uLong sourceLen // 圧縮されたデータのバイト数 );
#pragma warning(disable:4996) #include <vector> #include <filesystem> // 圧縮に必要 #include <zlib.h> // 圧縮に必要 #if _DEBUG #pragma comment(lib,"zlibstaticd.lib") #else #pragma comment(lib,"zlibstatic.lib") #endif
//! @brief 圧縮されたデータを伸長する //! @param [in] compressed 圧縮されたデータ //! @param [in] original_size 伸長後のデータサイズ //! @return 伸長後のデータ std::vector< Bytef > uncompress_test(const std::vector<unsigned char>& compressed,const unsigned int original_size) { // 元のデータのサイズだけメモリ確保 std::vector< Bytef > dest; dest.resize(original_size); //伸長 uLongf destLen = original_size; int ret = uncompress( dest.data(), // 伸長したデータの格納先 &destLen, // 格納先のメモリサイズ compressed.data(), // 圧縮データ compressed.size() // 圧縮データのサイズ ); if (ret != Z_OK) return std::vector< Bytef >(); return dest; }
std::vector<unsigned char> read_buffer(const char* filename); int main() { std::vector<unsigned char> buffer = read_buffer("C:/data/cmp.data"); // この数字は圧縮時に取得したものを指定する int original_filesize = 18199552; std::vector< Bytef > uncompressed = uncompress_test(buffer, original_filesize); // ファイル書き出し FILE* fp = fopen("C:\\data\\uncmp.data", "wb"); fwrite(uncompressed.data(), 1, uncompressed.size(), fp); fclose(fp); } //! @brief ファイルからデータを読み込む //! @param [in] filename ファイル名 //! @return ファイル一個分のデータ std::vector<unsigned char> read_buffer(const char* filename) { // データの準備 namespace fs = std::filesystem; std::vector<unsigned char> buffer; uintmax_t size = fs::file_size(filename); FILE* fp = fopen(filename, "rb"); buffer.resize(size); fread(buffer.data(), size, 1, fp); fclose(fp); return buffer; }
.cipd_client.exeをcompressし、cmp.dataを作成した。
cmp.dataをuncompressし、uncmp.dataを作成した。
ちゃんと伸長できているか確認するため、コマンドプロンプトからcompコマンドでバイナリ比較する。
ImGui、他のマウスイベントと重複して困ったので回避策。
マウスのコールバック関数が呼ばれている最中、ImGuiIO::WantCaptureMouseを調べtrueであればマウスがImGuiのウィンドウの内部にあることがわかる。
#include <cstdlib> #include <iostream> #include <Windows.h> #include <gl/GL.h> #include <GLFW/glfw3.h>
#include "imgui/imgui.h" #include "imgui/imgui_impl_glfw.h" #include "imgui/imgui_impl_opengl3.h"
#pragma comment(lib,"opengl32.lib") #pragma comment(lib,"glfw3.lib") #pragma warning(disable:4996) // マウスクリックを処理するコールバック関数 void mouse_button_callback(GLFWwindow* pwin, int button, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); // マウスがImGuiのウィンドウ内にあるときは // この中を通らない if (io.WantCaptureMouse == false) { if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { printf("L - down\n"); } if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) { printf("R - down\n"); } if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS) { printf("M - down\n"); } } } // 背景色 float bg_color[3]; // マウス移動を処理するコールバック関数 void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) { int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); ImGuiIO& io = ImGui::GetIO();
// マウスがImGuiのウィンドウ内にあるときは // この中を通らない
if (io.WantCaptureMouse == false) { //背景色 bg_color[0] = xpos / display_w; bg_color[1] = ypos / display_h; bg_color[2] = bg_color[0] * bg_color[1]; } } int main() { if (!glfwInit()) { return -1; } const char* glsl_version = "#version 130"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); GLFWwindow* window = glfwCreateWindow(640, 480, "test", NULL, NULL); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSwapInterval(1); // 自分の作業用の目的 glfwSetMouseButtonCallback(window, mouse_button_callback); glfwSetCursorPosCallback(window, cursor_position_callback);
/////////////// /////////////// /////////////// IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(glsl_version);
float x = 0.f, y = 0.f; char buffer[1024]; strcpy(buffer, "here"); bool pushed; while (!glfwWindowShouldClose(window)) { glfwPollEvents();
/////////////// /////////////// /////////////// // GUIを準備 ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); ImGui::SetNextWindowPos(ImVec2(30, 30)); ImGui::SetNextWindowSize(ImVec2(200, 250)); ImGui::Begin("Title"); ImGui::Text("input your message."); // ボタンを押されたフレームでpushedがtrueになる
pushed = ImGui::Button("push", ImVec2{ 0,0 }); ImGui::SameLine(); ImGui::InputText("", buffer, sizeof(buffer)); if (pushed) { printf("%s\n", buffer); } ImGui::End();
/////////////// /////////////// /////////////// int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glClearColor(bg_color[0], bg_color[1], bg_color[2], 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, display_w, display_h); ////////////// glColor3d(0.0, 0.0, 0.7); glBegin(GL_TRIANGLES); glVertex2d(-0.7, 0.7); glVertex2d(-0.7, -0.7); glVertex2d( 0.7, -0.0); glEnd();
/////////////// /////////////// /////////////// // GUIをレンダリング ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
/////////////// /////////////// /////////////// glfwSwapBuffers(window); } /////////////// /////////////// /////////////// // Cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); return 0; }
標準でないのか疑問だったがちょっと(30秒くらい)検索して出てこなかったので誰かの役に立つかもしれない。
以下のDEBUG_INFOマクロは、指定した文を#if 1の時だけ実行する。
#if 0の時は/**/に置き換わる。なお/**/はスペース一個に置き換わる。
以下は初心者にありがちなfloatをループカウンタにする例。
値の推移を表示させたいがリリース時にはいらない時に使う。
#include <stdio.h> // デバッグの時は #if 1 , そうでないときは0を指定 #if 0 #define DEBUG_INFO(a) a #else #define DEBUG_INFO(a) /**/ #endif int main() { int i = 0; float x; for (x = 0.1f; x <= 1.0f; x += 0.1f) { DEBUG_INFO(printf("%.10lf\n", x);) i++; } DEBUG_INFO(printf("%.10lf\n", x);) printf("%d\n", i); }
しかしこのマクロではうまく動いてくれない場合がある。
DEBUG_INFOの中に,(カンマ)があると、関数形式マクロと認識されてしまい、(多分)第二引数だけを指定した状態になり、しかし置換は第一引数に対して行われ、つまり第一引数は存在しないので、結果yが定義されていないというエラーが生じる(のだと思う)。
#include <stdio.h> // デバッグの時は #if 1 , そうでないときは0を指定 #if 1 #define DEBUG_INFO(a) a #else #define DEBUG_INFO(a) /**/ #endif int function( int x DEBUG_INFO(, int y)// エラー 'y':定義されていない識別子です。 ) { return x DEBUG_INFO(*y); } int main() { int a = 10, b = 12; int i = function(a DEBUG_INFO(,b)); printf("%d\n", i); }
C++11以降可変長引数マクロが使えるらしいので、それを使って以下のように書き換える。
#if 1 #define DEBUG_INFO(...) __VA_ARGS__ #else #define DEBUG_INFO(a) /**/ #endif
可変長引数マクロは、... (ドット三つ)で可変長であることを表現し、展開時 __VA_ARGS__ が...に指定した内容に置き換わる。
#include <iostream> // デバッグの時は #if 1 , そうでないときは0を指定 #if 1 #define DEBUG_INFO(...) __VA_ARGS__ #else #define DEBUG_INFO(a) /**/ #endif int function( int x DEBUG_INFO(, int y) ) { return x DEBUG_INFO(*y); } int main() { int a = 10, b = 12; int i = function(a DEBUG_INFO(,b)); printf("%d\n", i); }
標準にないのかこれ。今暇なくて真面目に探せない。
まずgitをインストール。
そしてOpen3Dをダウンロード。git cloneをするとレポジトリをダウンロードしてくれる。嫌ならブラウザから行ってDownload Zipとかでもいい。
ダウンロードした~/develop/Open3 へ入り、util/ ディレクトリにあるinstall_deps_ubuntu.sh スクリプトを実行。これによりOpen3Dが依存しているものが導入されるらしい。
インストール先のディレクトリ作成
ビルドのためのディレクトリ作成
ビルドディレクトリへ行き、cmake をOpen3D/ に対して走らせる。この時、CMAKE_INSTALL_PREFIXに上で作成したインストールディレクトリを指定しておく
make , 及び make install
#include <open3d/Open3D.h> #include <open3d/geometry/PointCloud.h> #include <iostream> #include <memory> int main(){ std::shared_ptr<open3d::geometry::PointCloud> pc = std::make_shared<open3d::geometry::PointCloud>(); pc->points_.push_back(Eigen::Vector3d(0.0, 0.1,0.7)); pc->points_.push_back(Eigen::Vector3d(1.0, 0.0,0.0)); pc->points_.push_back(Eigen::Vector3d(0.5,-0.3,0.1)); open3d::io::WritePointCloudToPLY("points.ply",*pc,true); std::cout << pc->points_.size() << std::endl; }
~/develop/Open3D_install/lib 以下の全てのlibOpen3D*.aをリンクしている。
filesystemを使うためlibstdc++fs.a、OpenMPのために -fopenmp を指定。
一週間近く掛けた気がするが、実はcmakeのビルドで失敗していただけでそこがちゃんどできればOpen3Dのほうは殆ど何も迷うことがなかった。
諸事情によりUbuntuでCMakeする事になったのだが、apt install cmakeで入れたのではバージョンが足りなかったのでCMakeをソースからビルドする。
10年近くまともにLinuxを触っていなかったので結構苦労した。
まず以下が必要。
libssl-devはOpenSSLのヘッダなどを使えるようにする物で、CMakeのビルドに必須ではないのだが、OpenSSLなしでビルドすると実際に使うときに苦労するので絶対に入れた方がいい。
1.作業用ディレクトリを作成
2.CMakeのソースコードをダウンロード
URLは: https://cmake.org/download/
から、Unix/Linux Source (has \n line feeds) cmake-3.22.1.tar.gz をダウンロードするのだがここはlinuxらしくwgetを使うことにする。
以下で該当ファイルを~/developディレクトリにダウンロードする。
3.tarを展開
~/developへ展開する。
1.cmakeのソースコードを展開したディレクトリへ移動
2.bootstrap , make , make install
OpenSSLを入れなかった場合、./bootstrap中に以下が出る。
もしOpenSSLを使わないと断言できるなら、オプション付きで./bootstrapすれば無効化できる
これで最後。
最後のほうは色々試しているのでざっくり纏める。
まず中央部分と周囲の部分を分割し、それぞれに異なるマテリアルを割り当てる。
最初に対象物をGlassにしておく。
Planeを追加して
そのままだと背景が灰色(全方位から光が入る)なので、黒(光源以外の光は存在しない)にする。
光源にしているPlaneをカメラで撮影されないように、Ray VisibilityのCameraとShadowを消す。
上下両方から光を照らす。
Subdivisionの設定。
カーブをなめらかにする。
グラスの色をColorRampで着色。