公開してからダウンロード元を書いていなかったので追記。
glm-master.zip を展開し、glm-master/ を適当な場所へ置き、glm/glm.hppをincludeできるように設定する。以下のサンプルプログラムはやや変なことをしているので気が向いたら後で修正する。
OpenGLで非推奨になったglTranslate等の代わりになるライブラリglmを積極的に使っていこうと思う。includeだけで使え、リンクの必要はない。
注意点として、テンプレートを多用している関係上double→floatなどの暗黙的型変換が効かないので、0.1ではなくちゃんと0.1fと書かなければいけないような場所が多い。
使用例として、以前に書いたfreeglutのコピペ用コードをglmを使って書き直してみる。
#include <Windows.h> #include <gl/GL.h> #include <gl/GLU.h> #include <gl/freeglut.h> // mat4 等 #include <gl/glm-0.9.9/glm.hpp> // perspective , transform 等 #include <gl/glm-0.9.9/gtc/matrix_transform.hpp> // value_ptr 等 #include <gl/glm-0.9.9/gtc/type_ptr.hpp> // freeglut: // http://freeglut.sourceforge.net/ // glm // https://github.com/g-truc/glm //ウィンドウの幅と高さ int width, height; double rotate_angle = 0; //描画関数 void disp(void) { glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, width, height); #if 0 //カメラの設定 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, width / (double)height, 0.1, 3); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(0, 0, -2); glRotated(rotate_angle, 0, 1, 0); #else // 行列を計算 glm::mat4 P = glm::perspective(glm::radians(60.f), width / (float)height, 0.1f, 3.f); glm::mat4 M; M = glm::identity<glm::mat4>(); M = glm::translate(M, glm::vec3(0.f, 0.f, -2.f)); M = glm::rotate(M, glm::radians((float)rotate_angle), glm::vec3(0.f, 1.f, 0.f)); // 行列の設定 glMatrixMode(GL_PROJECTION); glLoadMatrixf(glm::value_ptr(P)); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(glm::value_ptr(M)); #endif double v = 0.7; glBegin(GL_QUADS); glColor3d(0, 0, 1); glVertex2d(-v, -v); glColor3d(1, 0, 1); glVertex2d(v, -v); glColor3d(1, 1, 1); glVertex2d(v, v); glColor3d(0, 1, 1); glVertex2d(-v, v); glEnd(); glFlush(); } //ウィンドウサイズの変化時に呼び出される void reshape(int w, int h) { width = w; height = h; disp(); } void timer(int value) { rotate_angle += 5; disp(); glutTimerFunc(10, timer, 0); } //エントリポイント int main(int argc, char** argv) { glutInit(&argc, argv); glutInitWindowPosition(100, 50); glutInitWindowSize(500, 500); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutCreateWindow("sample"); glutDisplayFunc(disp); glutReshapeFunc(reshape); glutTimerFunc(1000, timer, 0);//タイマー glutMainLoop(); return 0; }
Visual C++ 2019で作ったプロジェクト。ライブラリディレクトリの設定や基本的なコードなどをいちいち設定したりコピーペーストするのも良いがプロジェクトテンプレート化しておけば1クリックで再現できるようになる。
新しいプロジェクトの設定を終え、コードを書く。
プロジェクト→テンプレートのエクスポートを選択しウィザードを開く。
テンプレートのエクスポートを完了すると、新しいプロジェクトの生成の一覧に表示される。
プロジェクトテンプレートを削除するとき、出力先のディレクトリにあるzipファイルを削除しても消えない。
同時に、Visual Studio2019\Templates\ProjectTemplates\ にあるzipファイルも削除すれば消える。
残りもやる。
Planeを一枚追加して8倍する。ちょうど下のメッシュと同じサイズになる。
Subdivideで50分割する。
ICO Sphereを追加し分割数を3、見えない位置に移動しておく。
SphereにEmissionを設定し、強さを30にする。色を設定するのだが、動画内の色と数字がどう見ても合っていなかった。多分フレーム落ちしている。色合い的にはこっちが近い。
ICO Sphereを右クリックして Shade Smoothを設定する。
PlaneにParticleを設定。ObjectにIcosphereを設定する。
スケールを適用しておく。
Displace、及びそのテクスチャ、wireframeモディファイアを設定。DisplaceとParticleSystemの順番に注意する。
CompositでGlareとDenoiseを設定。この時、View Layer PropertiesでDenosing Dataをチェックする。
Easy Satisfying Animation in Blenderのチュートリアルを試す の途中。
[Curve]→[Nurbs Circle]を追加
・Forward Axis =-X
・Up Axis = Z
・Follow Curveをチェック
さらに、カメラの回転を
・X=90
GraphEditor
Cubeにマテリアルを追加し、以下を設定
・Roughness = 0.187
・Transmission = 1.0
CubeにBevelモディファイアを追加し、
・Amount=0.018
・Segments = 4
CubeにSolidifyモディファイアを追加し、
・Thickness = 0.103
Cubeを複製し、0.493倍にリサイズ。
マテリアルが上記で設定した物と共通になっているので、削除しリンクを切る。新たにマテリアルを設定しておく。
量補を選択し[R]で回転する。
大きい方のCubeのマテリアルを以下のように設定する:
ここまでの結果
この結果
Cubeをもう一つ追加し、カメラが含まれるまで拡大する
さらにAreaライトを追加し、Cubeの上部に配置する。
できるかどうかの確認。問題なく動作している。
https://bitnami.com/stack/joomla/virtual-machine
ログインURLは、bitnamiを起動したコンソール内に書かれたURL/administrator/ となる。
パスワードは人によって違うので注意。
System → Install → Extensions へ移動し、gantry 公式からダウンロードした本体とテーマをドラッグ&ドロップする。
System → Templates → Site Template Styles へ移動し、Set Default をチェックしテーマを有効化する。
windowsでシステムのプロパティの環境変数のPATHにパスを追加するのが嫌なので、環境変数を適用したコマンドプロンプトを開くバッチファイルを作成する
cd C:\mybins\command\work
set PATH_ANC=C:\Users\yamada\anaconda3;C:\Users\yamada\anaconda3\Scripts;C:\Users\yamada\anaconda3\Library\bin
set PATH_APP=C:\mybins\7za;C:\mybins\command\ffmpeg-2021-11-29-git-86a2123a6e-full_build\bin;C:\mybins\ImageMagick-7.1.0-portable-Q16-x64
set PATH_CMP=C:\mybins\command\PortableGit\bin;C:\mybins\command\depot_tools
set path=%PATH_ANC%;%PATH_APP%;%PATH_CMP%;%path%;
%windir%\system32\cmd.exe /k
一行目のcdでカレントディレクトリを設定する。
二行目以降、setで環境変数を三つ設定。一行でもいいのだが自分が管理しやすいように分割している。
最後のset path=で三つを結合し%path%と混ぜる。なおanaconda3を%path%より前に書かないとmicrosoft store?的な物が起動してしまう可能性がある。
最後のcmd.exeでコマンドプロンプトを開く。
SDL2に続いてSDL_imageを使う。
マニュアルを読むとpngの読込関数なんかが入っているが、別途libpng等を使っているのでただのラッパーだと思われる。
URL https://www.libsdl.org/projects/SDL_image/
ダウンロード SDL2_image-devel-2.0.5-VC.zip (Visual C++ 32/64-bit)
パス設定
include : SDL2_image-2.0.5\include
lib : SDL2_image-2.0.5\lib\x64
// このマクロを定義しないとエントリポイントが SDL_main になる #define SDL_MAIN_HANDLED #include <SDL.h> // IMG_Load #include <SDL_image.h> #pragma comment(lib,"SDL2.lib") #pragma comment(lib,"SDL2_image.lib") // 必要ファイル: // SDL2.dll // SDL2_image.dll // libpng16-16.dll // zlib1.dll int main(int argc, char* argv[]) { // これがないと IMG_Loadがnullptrを返す //SDL_Init(SDL_INIT_VIDEO); // PNG読むなら必要 //IMG_Init(IMG_INIT_PNG); // ↑の筈なんだが無くても動いたりする? ////////////////////////////// Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif ////////////////////////////// //■ レンダラ作成 SDL_Surface* surf_out = SDL_CreateRGBSurface(0, 500, 500, 32, rmask, gmask, bmask, amask); SDL_Renderer* rend_out = SDL_CreateSoftwareRenderer(surf_out); //////////////////////////// // 画像を読み込んでコピー SDL_Surface* surf_in = IMG_Load("C:\\test\\data\\a.png"); SDL_BlitSurface(surf_in, nullptr, surf_out, nullptr); SDL_FreeSurface(surf_in); //////////////////////////// // アルファブレンドの設定 SDL_SetRenderDrawBlendMode(rend_out, SDL_BLENDMODE_BLEND); ////////////////////////////// // 赤で直線 SDL_SetRenderDrawColor(rend_out, 255, 0, 0, 100); SDL_RenderDrawLine(rend_out, 50, 20, 500, 200); // ファイルに保存 //SDL_SaveBMP(surf_out, "out.bmp"); IMG_SavePNG(surf_out, "out.png"); ////////////////////////////// //■ レンダラ破棄 SDL_DestroyRenderer(rend_out); SDL_FreeSurface(surf_out); return 0; }
結果のサイズを500x500に設定しているのでクリップされている。
諸事情によりSDLライブラリ。
URL https://www.libsdl.org/download-2.0.php
ダウンロード SDL2-devel-2.0.18-VC.zip (Visual C++ 32/64-bit)
パス設定
include : SDL2-2.0.18\include
lib : SDL2-2.0.18\lib\x64
ウィンドウに画像を表示するサンプルばかりだったので、画像を作成してファイルに保存するサンプルにした。
SDL_CreateRGBSurface と SDL_CreateSoftwareRenderer を使う。
// このマクロを定義しないとエントリポイントが SDL_main になる #define SDL_MAIN_HANDLED #include <SDL.h> #pragma comment(lib,"SDL2.lib") // 必要ファイル: // SDL2.dll int main(int argc, char* argv[]) { ////////////////////////////// Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif ////////////////////////////// SDL_Surface* surf = SDL_CreateRGBSurface( 0, 256, 256, 32, rmask, gmask, bmask, amask); //■ レンダラ作成 SDL_Renderer* render = SDL_CreateSoftwareRenderer(surf); // アルファブレンドの設定 SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND); ////////////////////////////// // 黒でクリア SDL_SetRenderDrawColor(render, 0, 0, 0, 255); SDL_RenderClear(render); ////////////////////////////// // 赤で直線 SDL_SetRenderDrawColor(render, 255, 0, 0, 150); SDL_RenderDrawLine(render, 50, 20, 500, 200); ////////////////////////////// // ファイルに保存 SDL_SaveBMP(surf, "out.bmp"); ////////////////////////////// //■ レンダラ破棄 SDL_DestroyRenderer(render); SDL_FreeSurface(surf); return 0; }
要素数が「最大N個」の配列が欲しい場合がある。std::vectorではnewでヒープに確保されるので重すぎる。std::arrayはスタックに確保できるがpush_backできない。
そんなわけで、push_backできるがスタックに置ける配列を考える。
#include<array> namespace szl { //! @brief 最大要素数が決まっている可変長配列 //! @tparam T arrayに入れるデータ型 //! @tparam MAX arrayの要素数 template<typename T, size_t MAX> class LimitedVector { std::array<T, MAX> _data; size_t count; //!< 現在の要素数 public: LimitedVector() :count(0) {} auto begin() { return _data.begin(); } auto end() { return _data.begin() + count; } const auto cbegin()const { return _data.cbegin(); } const auto cend()const { return _data.cbegin() + count; } void push_back(const T& v) { if (count >= MAX) throw "count >= MAX"; _data[count++] = v; } void pop_back() { if (count == 0) throw "count == 0"; count--; } T& back() { if (count == 0) throw "count == 0"; return _data[count - 1]; } const T& back()const { return _data[count - 1]; } const T* data()const { return _data; } T* data() { return _data; } size_t size()const { return count; } const T& operator[](const size_t index)const { return _data[index]; } T& operator[](const size_t index) { return _data[index]; } }; }
#include "LimitedVector.hpp" int main() { szl::LimitedVector<int, 3> v; v.push_back(3); v.push_back(4); v.push_back(6); printf("%d\n", v.size()); v[1] = 1; for (auto vv : v) { printf("-- %d\n", vv); } v.pop_back(); printf("-------\n"); for (auto vv : v) { printf("-- %d\n", vv); } }
実行例