ぬの部屋(仮)
nu-no-he-ya
  • 1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
         12
    3456789
    10111213141516
    17181920212223
    2425262728  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
       1234
    567891011
    12131415161718
    19202122232425
    26272829   
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • Windowsで環境変数を設定してアプリケーション起動(1)

    CreateProcessで環境変数を設定してアプリケーションを起動できる。

    display_myenvs.exe(テスト用)

    テスト用の環境変数を表示するプログラム。

    // プログラム1 環境変数を表示
    // display_myenvs.exe
    
    #include <iostream>
    
    #include <windows.h>
    
    
    int main()
    {
        char EnvVal[32767];
        size_t limit = sizeof(EnvVal) / sizeof(EnvVal[0]);
    
        std::cout << "------------------------" << std::endl;
        // 環境変数を取得
        GetEnvironmentVariableA("MY_ENV_STR", EnvVal, limit);
        std::cout << "MY_ENV_STR: " << EnvVal << std::endl;
    
        std::cout << "------------------------" << std::endl;
    
        GetEnvironmentVariableA("MY_ENV_INT",EnvVal, limit);
        std::cout << "MY_ENV_INT: " << EnvVal << std::endl;
    
    }
    

    test.exe

    // プログラム2 環境変数設定してアプリケーションを起動
    
    #include <iostream>
    
    #include <windows.h>
    
    int main()
    {
        ////////////////////////////////////////////////////
        // 独自の環境変数設定
        // 環境変数作成
        std::wstring envVar1 = L"MY_ENV_STR=HelloWorld";
        std::wstring envVar2 = L"MY_ENV_INT=12345";
    
        // 環境変数を設定するときは各変数を\0文字で区切り、終端を\0\0にする
        // "VAL1=value1\0VAL2=value2\0\0"
    
        std::wstring envVars;
        envVars += envVar1;
        envVars.push_back(L'\0'); // 環境変数の区切り
        envVars += envVar2;
        envVars.push_back(L'\0'); // 環境変数の区切り
        // 最後は\0\0で終端
        envVars.push_back(L'\0');
        envVars.push_back(L'\0');
    
    
       // アプリ起動
       STARTUPINFOW si = { sizeof(si) };
       PROCESS_INFORMATION pi;
       std::wstring apppath = L"display_myenvs.exe";
    
       BOOL ret = CreateProcessW(
           nullptr,
           &apppath[0], // 破壊的パースがされるため非constで渡す
           nullptr,
           nullptr,
           FALSE,
           CREATE_UNICODE_ENVIRONMENT,
           (void*)envVars.c_str(),
           nullptr,
           &si,
           &pi
       );
    
       // エラー処理
       if (!ret) {
          std::cerr << "CreateProcessA failed with error: " << GetLastError() << std::endl;
          return 1;
       }
    
    }
    

    C++でfunc(param=10);のように関数呼び出しに引数名を使用する方法を考える

    やってできないことはない。実用性があるかどうかは別。これを使うと引数を与える順番を考えなくてよくなるのと、引数の意味が呼び出し側でわかるようになるので若干可読性が上がるかもしれない。

    #include <iostream>
    #include <type_traits>
    
    
    // 型TがArgs...に含まれているかどうかを判定するメタ関数
    template <typename T, typename... Args>
    constexpr bool is_contains_type = (std::is_same_v<T, Args> || ...);
    

    // 可変引数テンプレートから特定の型Tで与えられた変数を取得する
    template<typename T, typename First, typename... Rest>
    decltype(auto) get_value(First&& first, Rest&&... rest) {
        if constexpr (std::is_same_v<T, std::decay_t<First> > == true) {
            return std::forward<First>(first);
        }
        // sizeof...(rest)で残りの引数の数をチェック
        else if constexpr (sizeof...(rest) > 0) {
    
            // 残りの引数restから T を探す
            return get_value<T>( std::forward<Rest>(rest)...);
        }
        else {
            static_assert(sizeof...(rest) > 0, "No matching type found in arguments.");
        }
    
    }
    
          
    template<int ID> // IDを与えてusing時にそれぞれを違う型として認識されるようにする
    struct ArgString {
        std::string value;
        ArgString& operator=(const std::string& str) {
            value = str;
            return *this;
        }
    };
    template<int ID>
    struct ArgInt {
        int value;
        ArgInt& operator=(int i) {
            value = i;
            return *this;
        }
    };
    
    using Text = ArgString<0>;
    using Title = ArgString<1>;
    using Index = ArgInt<0>;
    using Count = ArgInt<1>;
    
    // グローバル引数として、関数に渡す時に指定する引数名を定義
    Index index;
    Count count;
    Text text;
    Title title;
    
          
    // print関数の定義
    template <class... Args>
    void print(Args&&... args) {// argsにはindex,count,text,titleのいずれかが入っている
        Index index;
        Count count;
        Text text;
        Title title;
        if constexpr (is_contains_type<Index, std::decay_t<Args>...>) {
            auto&& arg = get_value<Index>( std::forward<Args>(args)... );
            index = arg; // 引数の値をIndexに設定
        }
        if constexpr (is_contains_type<Count, std::decay_t<Args>...>) {
            auto&& arg = get_value<Count>( std::forward<Args>(args)... );
            count = arg; // 引数の値をCountに設定
        }
        if constexpr (is_contains_type<Text, std::decay_t<Args>...>) {
            auto&& arg = get_value<Text>( std::forward<Args>(args)... );
            text = arg; // 引数の値をTextに設定
        }
        if constexpr (is_contains_type<Title, std::decay_t<Args>...>) {
            auto&& arg = get_value<Title>( std::forward<Args>(args)... );
            title = arg; // 引数の値をTitleに設定
        }
    
        // 各値を使用
        std::cout << "index: " << index.value << std::endl;
        std::cout << "count: " << count.value << std::endl;
        std::cout << "text: " << text.value << std::endl;
        std::cout << "title: " << title.value << std::endl;
    
    }
    
    
    int main()
    {
        print(
            index = 5,
            count = 10,
            text = "Hello, World!",
            title = "My Title"
        );
    }
    

    実行結果

    index: 5
    count: 10
    text: Hello, World!
    title: My Title

    OptiX 9.0を試す(2)optixRaycastingのプロジェクトに必要なファイルを確認

    optixRaycastingのプロジェクトにどのファイルが必要かを確認する

    ソースコードの場所:

    C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK\optixRaycasting\

    に、以下のファイルが存在

    • optixRaycasting.cpp
    • optixRaycasting.cu
    • optixRaycasting.h
    • optixRaycastingKernels.cu
    • optixRaycastingKernels.h

    .cu.obj / dlink.obj / .cu.optixir の作成

    プロジェクトの作成の前に、nvccで以下を生成しておく。

    cl.exeも呼び出されるので、x64 Native Tools Command Prompt等で実行する。

    .cu.optixir

    nvcc optixRaycasting.cu -o optixRaycasting_generated_optixRaycasting.cu.optixir -arch compute_50 -lineinfo -use_fast_math -optix-ir -rdc true -D__x86_64 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK"

    .cu.obj の作成

    本体のC++プロジェクトがMTかMDかでビルドオプションを変える

    MT

    nvcc optixRaycastingKernels.cu -c -o optixRaycasting_generated_optixRaycastingKernels.cu.obj -arch compute_50 -lineinfo -use_fast_math -rdc true -D__x86_64 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK"

    MD

    nvcc optixRaycastingKernels.cu -c -o optixRaycasting_generated_optixRaycastingKernels.cu.obj -arch compute_50 -lineinfo -use_fast_math -rdc true -D__x86_64 -Xcompiler "/MD" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK"

    dlink.obj (デバイスリンク)

    nvcc -dlink optixRaycasting_generated_optixRaycastingKernels.cu.obj -o optixRaycasting_generated_optixRaycastingKernels_dlink.obj -arch compute_50 -Xcompiler "/MD" -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8\lib\x64" -lcudart_static

    C++プロジェクト

    • optixRaycasting.cpp
    • optixRaycasting.h
    • optixRaycastingKernels.h

    で、VC++で、C++プロジェクトを作成。

    ぱっと見いらないものなどを消して、依存関係やらを整頓する。

    ・サンプルをビルドしたディレクトリ内にある sutil_7_sdk.lib が必要。

    gladはこの段階では取り除けなかった。

    ・sutil::loadSceneがモデルの他にシーン情報も設定している

    ・optixRaycasting_generated_optixRaycastingKernels.cu.obj optixRaycasting_generated_optixRaycastingKernels_dlink.obj をリンカー → 入力 → 追加の依存ファイルに追記しておく

     

    /*
    
     * SPDX-FileCopyrightText: Copyright (c) 2019 - 2024  NVIDIA CORPORATION & AFFILIATES. All rights reserved.
     * SPDX-License-Identifier: BSD-3-Clause
     * 
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     * list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form must reproduce the above copyright notice,
     * this list of conditions and the following disclaimer in the documentation
     * and/or other materials provided with the distribution.
     *
     * 3. Neither the name of the copyright holder nor the names of its
     * contributors may be used to endorse or promote products derived from
     * this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    
    #include <cuda_runtime.h>
    
    #include <optix.h>
    #include <optix_function_table_definition.h>
    #include <optix_stack_size.h>
    #include <optix_stubs.h>
    
     /*
     // Include ディレクトリ
     C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\include
     C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK\cuda
     C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK
     C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8\include
     C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK\support\imgui\..
     */
    
    /*
    // nvccでビルドして作成する各種関連ファイル:
    optixRaycasting_generated_optixRaycastingKernels.cu.obj
    optixRaycasting_generated_optixRaycastingKernels_dlink.obj
    */
    
    /*
    プリプロセッサ
    _USE_MATH_DEFINES
    NOMINMAX
    GLAD_GLAPI_EXPORT
    */
    
    // D:\tmp\optixbuild ここでインクルードしなくてもよい
    //#include <sampleConfig.h>
    
    #include <fstream> // getInputDataの代わりにifstreamを使う
    
    #include "cuda/whitted.h"
    #include <sutil/CUDAOutputBuffer.h>
    #include <sutil/Matrix.h>
    #include <sutil/Record.h>
    #include <sutil/Scene.h>
    #include <sutil/sutil.h>
    
    #include "optixRaycasting.h"
    #include "optixRaycastingKernels.h"
    
    #include <iomanip>
    
    
    #pragma comment(lib, "D:\\tmp\\optixbuild\\lib\\Release\\glad.lib")
    #pragma comment(lib, "D:\\tmp\\optixbuild\\lib\\Release\\sutil_7_sdk.lib")
    
    #pragma comment(lib, "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v12.8\\lib\\x64\\cudart_static.lib")
    #pragma comment(lib, "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v12.8\\lib\\x64\\cudadevrt.lib")
    
    
    struct RaycastingState
    {
        int                         width                    = 0;
        int                         height                   = 0;
    
        OptixDeviceContext          context                  = 0;
        sutil::Scene                scene                    = {};
    
        OptixPipelineCompileOptions pipeline_compile_options = {};
        OptixModule                 ptx_module               = 0;
        OptixPipeline               pipeline_1               = 0;
        OptixPipeline               pipeline_2               = 0;
    
        OptixProgramGroup           raygen_prog_group        = 0;
        OptixProgramGroup           miss_prog_group          = 0;
        OptixProgramGroup           hit_prog_group           = 0;
    
        Params                      params                   = {};
        Params                      params_translated        = {};
        OptixShaderBindingTable     sbt                      = {};
    
        sutil::Texture           mask                     = {};
    };
    
    
    typedef sutil::Record<whitted::HitGroupData> HitGroupRecord;
    
    
    void createModule( RaycastingState& state )
    {
        OptixModuleCompileOptions module_compile_options = {};
    #if OPTIX_DEBUG_DEVICE_CODE
        module_compile_options.optLevel   = OPTIX_COMPILE_OPTIMIZATION_LEVEL_0;
        module_compile_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_FULL;
    #else
        module_compile_options.optLevel   = OPTIX_COMPILE_OPTIMIZATION_DEFAULT;
        module_compile_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_MINIMAL;
    #endif
    
        state.pipeline_compile_options.usesMotionBlur        = false;
        state.pipeline_compile_options.traversableGraphFlags = OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING;
        state.pipeline_compile_options.numPayloadValues      = 4;
        state.pipeline_compile_options.numAttributeValues    = 2;
        state.pipeline_compile_options.exceptionFlags        = OPTIX_EXCEPTION_FLAG_NONE;
        state.pipeline_compile_options.pipelineLaunchParamsVariableName = "params";
    
        size_t      inputSize = 0;
    
        // 使いにくいので書き換え
    #if 0
        const char* input     = sutil::getInputData( OPTIX_SAMPLE_NAME, OPTIX_SAMPLE_DIR, "optixRaycasting.cu", inputSize );
    #else
     
        std::string filepath = "optixRaycasting_generated_optixRaycasting.cu.optixir";
        std::ifstream file(filepath, std::ios::binary | std::ios::ate);
        if (!file)
            throw std::runtime_error("Failed to open file: " + filepath);
    
        std::streamsize size = file.tellg(); // ファイルサイズ
        file.seekg(0, std::ios::beg); // 先頭へ移動
    
        std::vector<char> buffer;
        buffer.resize(size);
    
        if (!file.read(buffer.data(), size))
            throw std::runtime_error("Failed to read file: " + filepath);
    
        const char* input = buffer.data();
        inputSize = size;
    
    #endif
        // optixModuleCreateに.optixirを与える
        OPTIX_CHECK_LOG( optixModuleCreate( state.context, &module_compile_options, &state.pipeline_compile_options, input,
                                            inputSize, LOG, &LOG_SIZE, &state.ptx_module ) );
    }
    
    void createProgramGroups( RaycastingState& state )
    {
        OptixProgramGroupOptions program_group_options = {};
    
        OptixProgramGroupDesc raygen_prog_group_desc    = {};
        raygen_prog_group_desc.kind                     = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
        raygen_prog_group_desc.raygen.module            = state.ptx_module;
        raygen_prog_group_desc.raygen.entryFunctionName = "__raygen__from_buffer";
    
        OPTIX_CHECK_LOG( optixProgramGroupCreate( state.context, &raygen_prog_group_desc,
                                                  1,  // num program groups
                                                  &program_group_options, LOG, &LOG_SIZE, &state.raygen_prog_group ) );
    
        OptixProgramGroupDesc miss_prog_group_desc  = {};
        miss_prog_group_desc.kind                   = OPTIX_PROGRAM_GROUP_KIND_MISS;
        miss_prog_group_desc.miss.module            = state.ptx_module;
        miss_prog_group_desc.miss.entryFunctionName = "__miss__buffer_miss";
        OPTIX_CHECK_LOG( optixProgramGroupCreate( state.context, &miss_prog_group_desc,
                                                  1,  // num program groups
                                                  &program_group_options, LOG, &LOG_SIZE, &state.miss_prog_group ) );
    
    
        OptixProgramGroupDesc hit_prog_group_desc = {};
        hit_prog_group_desc.kind                  = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
        hit_prog_group_desc.hitgroup.moduleAH            = state.ptx_module;
        hit_prog_group_desc.hitgroup.entryFunctionNameAH = "__anyhit__texture_mask";
        hit_prog_group_desc.hitgroup.moduleCH            = state.ptx_module;
        hit_prog_group_desc.hitgroup.entryFunctionNameCH = "__closesthit__buffer_hit";
        OPTIX_CHECK_LOG( optixProgramGroupCreate( state.context, &hit_prog_group_desc,
                                                  1,  // num program groups
                                                  &program_group_options, LOG, &LOG_SIZE, &state.hit_prog_group ) );
    }
    
    
    void createPipelines( RaycastingState& state )
    {
        const uint32_t    max_trace_depth   = 1;
        OptixProgramGroup program_groups[3] = {state.raygen_prog_group, state.miss_prog_group, state.hit_prog_group};
    
        OptixPipelineLinkOptions pipeline_link_options = {};
        pipeline_link_options.maxTraceDepth            = max_trace_depth;
    
        OPTIX_CHECK_LOG( optixPipelineCreate( state.context, &state.pipeline_compile_options, &pipeline_link_options,
                                              program_groups, sizeof( program_groups ) / sizeof( program_groups[0] ), LOG,
                                              &LOG_SIZE, &state.pipeline_1 ) );
        OPTIX_CHECK_LOG( optixPipelineCreate( state.context, &state.pipeline_compile_options, &pipeline_link_options,
                                              program_groups, sizeof( program_groups ) / sizeof( program_groups[0] ), LOG,
                                              &LOG_SIZE, &state.pipeline_2 ) );
    
        OptixStackSizes stack_sizes_1 = {};
        OptixStackSizes stack_sizes_2 = {};
        for( auto& prog_group : program_groups )
        {
            OPTIX_CHECK( optixUtilAccumulateStackSizes( prog_group, &stack_sizes_1, state.pipeline_1 ) );
            OPTIX_CHECK( optixUtilAccumulateStackSizes( prog_group, &stack_sizes_2, state.pipeline_2 ) );
        }
    
        uint32_t direct_callable_stack_size_from_traversal;
        uint32_t direct_callable_stack_size_from_state;
        uint32_t continuation_stack_size;
        OPTIX_CHECK( optixUtilComputeStackSizes( &stack_sizes_1, max_trace_depth,
                                                 0,  // maxCCDepth
                                                 0,  // maxDCDEpth
                                                 &direct_callable_stack_size_from_traversal,
                                                 &direct_callable_stack_size_from_state, &continuation_stack_size ) );
        OPTIX_CHECK( optixPipelineSetStackSize( state.pipeline_1, direct_callable_stack_size_from_traversal,
                                                direct_callable_stack_size_from_state, continuation_stack_size,
                                                2  // maxTraversableDepth
                                                ) );
        OPTIX_CHECK( optixUtilComputeStackSizes( &stack_sizes_2, max_trace_depth,
                                                 0,  // maxCCDepth
                                                 0,  // maxDCDEpth
                                                 &direct_callable_stack_size_from_traversal,
                                                 &direct_callable_stack_size_from_state, &continuation_stack_size ) );
        OPTIX_CHECK( optixPipelineSetStackSize( state.pipeline_2, direct_callable_stack_size_from_traversal,
                                                direct_callable_stack_size_from_state, continuation_stack_size,
                                                2  // maxTraversableDepth
                                                ) );
    }
    
    
    void createSBT( RaycastingState& state )
    {
        // raygen
        CUdeviceptr  d_raygen_record    = 0;
        const size_t raygen_record_size = sizeof( sutil::EmptyRecord );
        CUDA_CHECK( cudaMalloc( reinterpret_cast<void**>( &d_raygen_record ), raygen_record_size ) );
    
        sutil::EmptyRecord rg_record;
        OPTIX_CHECK( optixSbtRecordPackHeader( state.raygen_prog_group, &rg_record ) );
        CUDA_CHECK( cudaMemcpy( reinterpret_cast<void*>( d_raygen_record ), &rg_record, raygen_record_size, cudaMemcpyHostToDevice ) );
    
        // miss
        CUdeviceptr  d_miss_record    = 0;
        const size_t miss_record_size = sizeof( sutil::EmptyRecord );
        CUDA_CHECK( cudaMalloc( reinterpret_cast<void**>( &d_miss_record ), miss_record_size ) );
    
        sutil::EmptyRecord ms_record;
        OPTIX_CHECK( optixSbtRecordPackHeader( state.miss_prog_group, &ms_record ) );
        CUDA_CHECK( cudaMemcpy( reinterpret_cast<void*>( d_miss_record ), &ms_record, miss_record_size, cudaMemcpyHostToDevice ) );
    
        // hit group
        std::vector<HitGroupRecord> hitgroup_records;
        for( const auto& mesh : state.scene.meshes() )
        {
            for( size_t i = 0; i < mesh->material_idx.size(); ++i )
            {
                HitGroupRecord rec = {};
                OPTIX_CHECK( optixSbtRecordPackHeader( state.hit_prog_group, &rec ) );
                GeometryData::TriangleMesh triangle_mesh = {};
                triangle_mesh.positions                  = mesh->positions[i];
                triangle_mesh.normals                    = mesh->normals[i];
                for( size_t j = 0; j < GeometryData::num_texcoords; ++j )
                    triangle_mesh.texcoords[j] = mesh->texcoords[j][i];
                triangle_mesh.indices = mesh->indices[i];
                rec.data.geometry_data.setTriangleMesh( triangle_mesh );
                rec.data.material_data = state.scene.materials()[mesh->material_idx[i]];
                hitgroup_records.push_back( rec );
            }
        }
    
        CUdeviceptr  d_hitgroup_record    = 0;
        const size_t hitgroup_record_size = sizeof( HitGroupRecord );
        CUDA_CHECK( cudaMalloc( reinterpret_cast<void**>( &d_hitgroup_record ), hitgroup_record_size * hitgroup_records.size() ) );
        CUDA_CHECK( cudaMemcpy( reinterpret_cast<void*>( d_hitgroup_record ), hitgroup_records.data(),
                                hitgroup_record_size * hitgroup_records.size(), cudaMemcpyHostToDevice ) );
    
        state.sbt.raygenRecord                = d_raygen_record;
        state.sbt.missRecordBase              = d_miss_record;
        state.sbt.missRecordStrideInBytes     = static_cast<uint32_t>( miss_record_size );
        state.sbt.missRecordCount             = RAY_TYPE_COUNT;
        state.sbt.hitgroupRecordBase          = d_hitgroup_record;
        state.sbt.hitgroupRecordStrideInBytes = static_cast<uint32_t>( hitgroup_record_size );
        state.sbt.hitgroupRecordCount         = static_cast<int>( hitgroup_records.size() );
    }
    
    
    void bufferRays( RaycastingState& state )
    {
        // Create CUDA buffers for rays and hits
        sutil::Aabb aabb = state.scene.aabb();
        aabb.invalidate();
        for( const auto& instance : state.scene.instances() )
            aabb.include( instance->world_aabb );
        const float3 bbox_span = aabb.extent();
        state.height           = static_cast<int>( state.width * bbox_span.y / bbox_span.x );
    
        Ray*   rays_d             = 0;
        Ray*   translated_rays_d  = 0;
        size_t rays_size_in_bytes = sizeof( Ray ) * state.width * state.height;
        CUDA_CHECK( cudaMalloc( &rays_d, rays_size_in_bytes ) );
        CUDA_CHECK( cudaMalloc( &translated_rays_d, rays_size_in_bytes ) );
    
        createRaysOrthoOnDevice( rays_d, state.width, state.height, aabb.m_min, aabb.m_max, 0.05f );
        CUDA_CHECK( cudaGetLastError() );
        CUDA_CHECK( cudaMemcpy( translated_rays_d, rays_d, rays_size_in_bytes, cudaMemcpyDeviceToDevice ) );
    
        translateRaysOnDevice( translated_rays_d, state.width * state.height, bbox_span * make_float3( 0.2f, 0, 0 ) );
        CUDA_CHECK( cudaGetLastError() );
    
        Hit*   hits_d             = 0;
        Hit*   translated_hits_d  = 0;
        size_t hits_size_in_bytes = sizeof( Hit ) * state.width * state.height;
        CUDA_CHECK( cudaMalloc( &hits_d, hits_size_in_bytes ) );
        CUDA_CHECK( cudaMalloc( &translated_hits_d, hits_size_in_bytes ) );
    
        state.params            = {state.scene.traversableHandle(), rays_d, hits_d};
        state.params_translated = {state.scene.traversableHandle(), translated_rays_d, translated_hits_d};
    }
    
    
    void launch( RaycastingState& state )
    {
        CUstream stream_1 = 0;
        CUstream stream_2 = 0;
        CUDA_CHECK( cudaStreamCreate( &stream_1 ) );
        CUDA_CHECK( cudaStreamCreate( &stream_2 ) );
    
        Params* d_params            = 0;
        Params* d_params_translated = 0;
        CUDA_CHECK( cudaMalloc( reinterpret_cast<void**>( &d_params ), sizeof( Params ) ) );
        CUDA_CHECK( cudaMemcpyAsync( reinterpret_cast<void*>( d_params ), &state.params, sizeof( Params ),
                                     cudaMemcpyHostToDevice, stream_1 ) );
    
        OPTIX_CHECK( optixLaunch( state.pipeline_1, stream_1, reinterpret_cast<CUdeviceptr>( d_params ), sizeof( Params ),
                                  &state.sbt, state.width, state.height, 1 ) );
    
        // Translated
        CUDA_CHECK( cudaMalloc( reinterpret_cast<void**>( &d_params_translated ), sizeof( Params ) ) );
        CUDA_CHECK( cudaMemcpyAsync( reinterpret_cast<void*>( d_params_translated ), &state.params_translated,
                                     sizeof( Params ), cudaMemcpyHostToDevice, stream_2 ) );
    
        OPTIX_CHECK( optixLaunch( state.pipeline_2, stream_2, reinterpret_cast<CUdeviceptr>( d_params_translated ),
                                  sizeof( Params ), &state.sbt, state.width, state.height, 1 ) );
    
        CUDA_SYNC_CHECK();
    
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( d_params ) ) );
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( d_params_translated ) ) );
    }
    
    
    void shadeHits( RaycastingState& state, const std::string& outfile )
    {
        sutil::CUDAOutputBufferType     output_buffer_type = sutil::CUDAOutputBufferType::CUDA_DEVICE;
        sutil::CUDAOutputBuffer<float3> output_buffer( output_buffer_type, state.width, state.height );
    
        sutil::ImageBuffer buffer;
        buffer.width        = state.width;
        buffer.height       = state.height;
        buffer.pixel_format = sutil::BufferImageFormat::FLOAT3;
    
        // Original
        shadeHitsOnDevice( output_buffer.map(), state.width * state.height, state.params.hits );
        CUDA_CHECK( cudaGetLastError() );
        output_buffer.unmap();
    
        std::string ppmfile = outfile + ".ppm";
        buffer.data         = output_buffer.getHostPointer();
        sutil::saveImage( ppmfile.c_str(), buffer, false );
        std::cerr << "Wrote image to " << ppmfile << std::endl;
    
        // Translated
        shadeHitsOnDevice( output_buffer.map(), state.width * state.height, state.params_translated.hits );
        CUDA_CHECK( cudaGetLastError() );
        output_buffer.unmap();
    
        ppmfile     = outfile + "_translated.ppm";
        buffer.data = output_buffer.getHostPointer();
        sutil::saveImage( ppmfile.c_str(), buffer, false );
        std::cerr << "Wrote translated image to " << ppmfile << std::endl;
    }
    
    
    void cleanup( RaycastingState& state )
    {
        OPTIX_CHECK( optixPipelineDestroy( state.pipeline_1 ) );
        OPTIX_CHECK( optixPipelineDestroy( state.pipeline_2 ) );
        OPTIX_CHECK( optixProgramGroupDestroy( state.raygen_prog_group ) );
        OPTIX_CHECK( optixProgramGroupDestroy( state.miss_prog_group ) );
        OPTIX_CHECK( optixProgramGroupDestroy( state.hit_prog_group ) );
        OPTIX_CHECK( optixModuleDestroy( state.ptx_module ) );
    
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( state.params.rays ) ) );
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( state.params.hits ) ) );
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( state.params_translated.rays ) ) );
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( state.params_translated.hits ) ) );
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( state.sbt.raygenRecord ) ) );
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( state.sbt.missRecordBase ) ) );
        CUDA_CHECK( cudaFree( reinterpret_cast<void*>( state.sbt.hitgroupRecordBase ) ) );
    
        CUDA_CHECK( cudaDestroyTextureObject( state.mask.texture ) );
        CUDA_CHECK( cudaFreeArray( state.mask.array ) );
    }
    
    
    int main( int argc, char** argv )
    {
        std::string     infile, outfile;
        RaycastingState state;
        state.width = 640;
    
        // .gltfはモデルとシーン情報を含む
    
        // データの場所:
        // C:\ProgramData\NVIDIA Corporation\OptiX SDK 9.0.0\SDK\data
        infile = sutil::sampleDataFilePath("Duck/DuckHole.gltf");
        outfile = "output";
    
        try
        {
            sutil::loadScene( infile.c_str(), state.scene );
            state.scene.createContext();
    
            state.scene.buildMeshAccels();
            state.scene.buildInstanceAccel( RAY_TYPE_COUNT );
            state.context = state.scene.context();
    
            OPTIX_CHECK( optixInit() );  // Need to initialize function table
            createModule( state );
            createProgramGroups( state );
            createPipelines( state );
            createSBT( state );
    
            bufferRays( state );
            launch( state );
            shadeHits( state, outfile );
            cleanup( state );
        }
        catch( std::exception& e )
        {
            std::cerr << "Caught exception: " << e.what() << std::endl;
            return 1;
        }
    
        return 0;
    }
    

    OptiX 9.0を試す(1) ダウンロード / サンプルのビルド

    Windows 11 + Visual C++ 2022 + CUDA 12.8 でOptiX 9.0を試す。

    以下からドライバとCUDAを最新にしておく

    ダウンロード

    NVIDIA Driver 今回使用:576.02

    https://www.nvidia.com/ja-jp/drivers

    CUDA Toolkit 今回使用:12.8

    https://developer.nvidia.com/cuda-downloads

    以下からOptiX 9.0をダウンロード・インストール

    OptiX

    https://developer.nvidia.com/designworks/optix/download

    サンプルビルド

    以下にインストールされている:

    C:/ProgramData/NVIDIA Corporation/OptiX SDK 9.0.0/SDK

    ここにCMakeLists.txtも入っているので、CMake-GUI で、Where is the source codeに指定。

    Where to build the binaries: にビルド用のディレクトリを入れる。

    インストールは行わないので、これでConfigure Generate Open Project する。

    VC++でALL_BUILDすると、D:\tmp\optixbuild\bin\Release にサンプルプログラムが入っている。

    C++、Fold expressionで可変引数テンプレート関数の引数を一括で計算する

    C++17でFold expressionという機能が追加されたらしい。

    なんでも

    (pack op ...)

    とすると、

    (val1 op val2 op val3 op)

    と展開される。

    #include <iostream>
    
    
    template<typename... Args>
    auto add1(Args... val) {
    
        // Fold expression
        // val1 + val2 + val3 + ...
    
        return (val + ...); 
    }
    

    template<int... Args>
    int add2() {
    
        // Fold expression
        // args1 + args2 + args3 + ...
    
        return (Args + ...);
    }
    
    
    int main()
    {
    
        auto ret1 = add1(1.0, 2.2, 3.f, 4, 5);
        std::cout << "Sum: " << ret1 << "\n";
    
        int ret2 = add2<1, 2, 3, 4, 5>();
        std::cout << "Sum: " << ret2 << "\n";
    
    }
    
    Sum: 15.2
    Sum: 15

    C++、可変引数テンプレート関数で、引数の型に応じた動作を定義する

    可変引数テンプレートもそうだが、if constexprやtype_traits、型推論に右辺参照もあるのでかなり簡単に書けるようになっている。

    #include <iostream>
    #include <type_traits>
    
    
    // 型TがArgs...に含まれているかどうかを判定するメタ関数
    template <typename T, typename... Args>
    constexpr bool is_contains_type = (std::is_same_v<T, Args> || ...);
    

    template<typename T, typename First, typename... Rest>
    decltype(auto) get_value(First&& first, Rest&&... rest) {
        if constexpr (std::is_same_v<T, std::decay_t<First> > == true) {
            return std::forward<First>(first);
        }
        // sizeof...(rest)で残りの引数の数をチェック
        else if constexpr (sizeof...(rest) > 0) {
    
            // 残りの引数restから T を探す
            return get_value<T>( std::forward<Rest>(rest)...);
        }
        else {
            static_assert(sizeof...(rest) > 0, "No matching type found in arguments.");
        }
    
    }
    

    template <class... Args>
    void print(Args&&... args) {
    
        if constexpr (is_contains_type<int, std::decay_t<Args>...>) {
            auto&& arg_int = get_value<int>( std::forward<Args>(args)... );
            std::cout << "int is " << arg_int << "\n";
        }
    
        if constexpr (is_contains_type<double, std::decay_t<Args>...>) {
            auto&& arg_double = get_value<double>(std::forward<Args>(args)... );
            std::cout << "double is "<< arg_double << "\n";
        }
    
        if constexpr (is_contains_type<float, std::decay_t<Args>...>) {
            auto&& arg_float = get_value<float>(std::forward<Args>(args)... );
            std::cout << "float is " << arg_float << "\n";
        }
    
    }
    
    int main()
    {
        print(1, 2.5, 5.f); // 引数が右辺値の場合
    
        int K = 10;
        print(K); // 引数が左辺値の場合
    
        std::cout << "K is " << K << "\n";
    }
    
    

    Qwen3でPythonスクリプトのSyntax Errorを修正してみた

    compile()関数を使うとPythonスクリプトのSyntax Errorを検出できる。スクリプトとその情報を与えてQwen3でバグフィクスをさせてみた。

    from langchain_ollama import OllamaLLM
    from langchain_ollama import OllamaEmbeddings
    from langchain_community.vectorstores import FAISS
    from langchain_community.document_loaders import TextLoader
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    from langchain.chains import RetrievalQA
    
    
    import re
    
    
    base_question="""あなたはPythonのコード修正アシスタントです。
    あなたの仕事は、PythonコードのSyntax Errorを修正することです。
    ・Syntax Errorの内容はPythonのcompile()関数により取得したものが与えられる。
    ・Syntax Errorの修正以外は、オリジナルのコードを維持すること。
    ・修正したスクリプトを出力せよ。
    ・出力するスクリプトは ```python と ``` で囲うこと。
    ////////////////////////////////////////
    Syntax Errorの内容:
    {SyntaxError}
    
    ////////////////////////////////////////
    修正すべきスクリプト:
    {MyScript}
    """
    
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    
    
    def extract_python_code_blocks(text):
        """
        与えられた文字列から、 ```python ~ ``` で囲まれた範囲のコードをリストで返す。
        """
        pattern = r"```python\s*(.*?)```"
        match = re.search(pattern, text, re.DOTALL)
        return match.group(1) if match else None
    
    def check_syntax(code_str):
      try:
        compile(code_str, "<string>", "exec")
        print("構文エラーはありません。")
        return None
        
      except SyntaxError as e:
        print(f"構文エラーが発生しました: {e}")
        error_message = (
            f"構文エラー: {e.msg}\n"
            f"ファイル名: {e.filename}\n"
            f"行番号: {e.lineno}\n"
            f"エラー発生位置: {e.offset}\n"
            f"エラー箇所: {e.text.strip() if e.text else '不明'}"
        )
        return error_message
    
    
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    
    def trycode(source):
      llm = OllamaLLM(model="qwen3:4b")
    
      code = source
    
      Loop = True
      while Loop:
        
        print("trycode===============================")
        print(code)
        print("=========================================")
    
        # 構文が間違っていたらもう一度生成し直し
        err = check_syntax(code)
        if err == None:
          break
        else:
          print("Syntax Error ============================")
          print(err)
          print("=========================================")
      
        # 問い合わせ作成
        q1 = base_question.format(SyntaxError=err, MyScript=code)
    
        # 問い合わせ実行
        response = llm.invoke(q1)
    
        code = re.sub(r"<think>.*?</think>", "", response, flags=re.DOTALL)    
        # ```pythonを外す
        code = extract_python_code_blocks(code)
    
    
      return code
    
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    ############################################################################################
    
    # スクリプトファイル読み込み
    # myscript_path = "test.py"
    # パスを引数から取得
    import sys
    if len(sys.argv) < 2:
      print("Usage: python auto_debugger.py <script_path>")
      sys.exit(1)
    myscript_path = sys.argv[1]
    if not myscript_path.endswith(".py"):
      print("Error: The script path must end with '.py'")
      sys.exit(1)
    
    
    myscript = ""
    with open(myscript_path, "r",encoding="utf-8") as f:
      myscript = f.read()
    
    myscript = trycode(myscript)# 自動Syntax Error修復
    print(myscript)
    
    # スクリプトファイル書き込み
    with open(myscript_path + "_fix.py", "w",encoding="utf-8") as f:
      f.write(myscript)
    

    実行例

    python auto_debugger.py whitenoise.py
    import numpy as np
    import cv2
    
    def generate_white_noise(width, height):
        # 0〜255のランダムな値を持つ画像を生成
    noise = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)
        return noise
    
    def save_image(image, filename):
        cv2.imwrite(filename, image)
    
    if __name__ == "__main__":
        width = 640*
        height = 480
        noise_image = generate_white_noise(width, height
        save_image(noise_image, "white_noise.png")
    

    修正前

    import numpy as np
    import cv2
    
    def generate_white_noise(width, height):
        # 0〜255のランダムな値を持つ画像を生成
        noise = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)
        return noise
    
    def save_image(image, filename):
        cv2.imwrite(filename, image)
    
    if __name__ == "__main__":
        width = 640
        height = 480
        noise_image = generate_white_noise(width, height)
        save_image(noise_image, "white_noise.png")
    

    修正後

    VTKでVTKが管理していない頂点データを指定して可視化

    vtkDoubleArrayでSetArrayをすると、他ライブラリで管理している頂点データやカラーデータをVTKにコピーせずに使用できる(かもしれない)。

    データ構造がXYZの配列のようにVTKの管理形式と同じである必要がある。

    ただ、vtkCellArray(可視化する際に必要な頂点IDの配列)はいずれにせよ作成しなければいけないので、メモリ効率が劇的によくなるかというとそうでもない。

    #include <iostream>
    
    //VTK_MODULE_INITに必要
    #include <vtkAutoInit.h>
    
    
    #include <vtkSmartPointer.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    
    //円筒とその表示に必要
    #include <vtkPolyDataMapper.h>
    #include <vtkDoubleArray.h>
    #include <vtkPointData.h>
    #include <vtkActor.h>
    
    
    #include <vtkeigen/eigen/Dense>
    
    #pragma comment(lib,"opengl32.lib")
    #pragma comment(lib,"psapi.lib")
    #pragma comment(lib,"dbghelp.lib")
    #pragma comment(lib,"ws2_32.lib")
    
    
    //必須
    VTK_MODULE_INIT(vtkRenderingOpenGL2);
    VTK_MODULE_INIT(vtkInteractionStyle);
    
    
    void create(std::vector<Eigen::Vector3d>& position, std::vector<Eigen::Vector3d>& color) {
      for (size_t i = 0; i < 100000; i++) {
        double x = (double)rand() / (double)RAND_MAX;
        double y = (double)rand() / (double)RAND_MAX;
        double z = (double)rand() / (double)RAND_MAX;
    
        position.push_back(Eigen::Vector3d(x, y, z));
        color.push_back(Eigen::Vector3d(x, y, z)); // 色も同じ値にする
      }
    }
    
    
    vtkSmartPointer<vtkActor> createActor(double* const position,double* const color,size_t count) {
    
      ///////////////////////////////////////////////////
      // 頂点データをVTKでラップ
      auto vtk_array_points = vtkSmartPointer<vtkDoubleArray>::New();
      vtk_array_points->SetNumberOfComponents(3);
      vtk_array_points->SetArray(position, count * 3, 1); // save=1の時、double_ptrの管理を移譲しない
    
      ///////////////////////////////////////////////////
      // カラーデータをVTKでラップ
      auto vtk_array_color = vtkSmartPointer<vtkDoubleArray>::New();
      vtk_array_color->SetNumberOfComponents(3);
      vtk_array_color->SetName("Colors");
      vtk_array_color->SetArray(color, count * 3, 1); // save=1の時、double_ptrの管理を移譲しない
      ///////////////////////////////////////////////////
      // 頂点インデクスの配列
      auto vertices = vtkSmartPointer<vtkCellArray>::New();
      for (vtkIdType i = 0; i < count; ++i) {
        vertices->InsertNextCell(1, &i);
      }
    
      ///////////////////////////////////////////////////
      auto vtk_points = vtkSmartPointer<vtkPoints>::New();
      vtk_points->SetData(vtk_array_points);
    
      // --- vtkPolyData作成 ---
      auto polydata = vtkSmartPointer<vtkPolyData>::New();
      polydata->SetPoints(vtk_points);
      polydata->SetVerts(vertices);
      polydata->GetPointData()->SetScalars(vtk_array_color);
    
      // --- actor作成 ---
      auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
      mapper->SetInputData(polydata);
    
      vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
      actor->SetMapper(mapper);
    
    
    
      return actor;
    
    }
    
    
    int main(int /*argc*/, char** /*argv*/)
    {
      std::vector<Eigen::Vector3d> position;
      std::vector<Eigen::Vector3d> color;
      create(position, color);
    
      auto actor = createActor(
        reinterpret_cast<double*>(position.data()),
        reinterpret_cast<double*>(color.data()),
        position.size()
      );
    
      auto renderer = vtkSmartPointer<vtkRenderer>::New();
      renderer->AddActor(actor);
      renderer->ResetCamera();
    
      //////////////////////////////////////
      auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    
      //////////////////////////////////////
      auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
      renderWindow->AddRenderer(renderer);
      renderWindow->SetInteractor(interactor);
      renderWindow->Render();
    
      interactor->Start(); //イベントループへ入る
    
      return 0;
    }
    

    VTKでタイマー(クラスインスタンスver)、複数タイマー,タイマー停止

    前にやったときはコールバック関数を直接呼び出していたが今度はクラスのインスタンスを作成してExecuteメンバを呼び出す。

    VTKのタイマーは一つのコールバック用のクラスインスタンスのExecuteを各タイミングで呼び出す。

    タイマーの停止はDestroyTimerで行う。

    #include <iostream>
    
    //VTK_MODULE_INITに必要
    #include <vtkAutoInit.h>
    
    
    #include <vtkSmartPointer.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    
    //円筒とその表示に必要
    #include <vtkCylinderSource.h>
    #include <vtkPolyDataMapper.h>
    
    
    #pragma comment(lib,"opengl32.lib")
    #pragma comment(lib,"psapi.lib")
    #pragma comment(lib,"dbghelp.lib")
    #pragma comment(lib,"ws2_32.lib")
    
    
    //必須
    VTK_MODULE_INIT(vtkRenderingOpenGL2);
    VTK_MODULE_INIT(vtkInteractionStyle);
    
    
    
    
    class MyTimerCallback : public vtkCommand
    {
    public:
        static MyTimerCallback* New()
        {
            return new MyTimerCallback;
        }
    
        int counter100 = 0;
        int counter500 = 0;
    
    
        void Execute(vtkObject* caller, unsigned long eventId, void* callData) override
        {
            if (eventId == vtkCommand::TimerEvent)
            {
                int timerId = *(int*)(callData);
    
                if (timerId == this->TimerId100)
                {
                    // TimerId100の処理
                    counter100++;
                    std::cout << "Timer100 triggered!" << counter100 <<std::endl;
    
                    // タイマーを停止
                    if(counter100 >= 10)
                    {
                        std::cout << "Stopping Timer100" << std::endl;
                        Interactor->DestroyTimer(timerId);
                    }
                }
                else if (timerId == this->TimerId500)
                {
                    // TimerId500の処理
                    counter500++;
                    std::cout << "Timer500 triggered!" << counter500 << std::endl;
                }
            }
        }
    
        vtkSmartPointer<vtkRenderWindowInteractor> Interactor;
        int TimerId100 = -1; // タイマーの識別子
        int TimerId500 = -1;
    };
    
    
    
    
    int main(int /*argc*/, char** /*argv*/)
    {
    
        //////////////////////////////////////
        // Create a vtkCylinderSource
        vtkSmartPointer<vtkCylinderSource> cylinderSource = vtkSmartPointer<vtkCylinderSource>::New();
        cylinderSource->SetCenter(0.0, 0.0, 0.0);
        cylinderSource->SetRadius(5.0);
        cylinderSource->SetHeight(7.0);
        cylinderSource->SetResolution(100);
    
        //////////////////////////////////////
        // Create a mapper and actor
        vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
        mapper->SetInputConnection(cylinderSource->GetOutputPort());
        vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
        actor->SetMapper(mapper);
    
        //////////////////////////////////////
        auto renderer = vtkSmartPointer<vtkRenderer>::New();
        renderer->AddActor(actor);
        renderer->ResetCamera();
    
        //////////////////////////////////////
        auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
        //////////////////////////////////////
        auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
        renderWindow->AddRenderer(renderer);
        renderWindow->SetInteractor(interactor);
        renderWindow->Render();
        //////////////////////////////////////
    
        // タイマーコールバックの設定
        vtkSmartPointer<MyTimerCallback> timerCallback =
            vtkSmartPointer<MyTimerCallback>::New();
    
        // タイマーを作成。戻り値は識別子
        timerCallback->TimerId100 = interactor->CreateRepeatingTimer(100);
        timerCallback->TimerId500 = interactor->CreateRepeatingTimer(500);
    
        // DestroyTimerのためにinteractorを保持
        timerCallback->Interactor = interactor;
    
        interactor->AddObserver(vtkCommand::TimerEvent, timerCallback);
        interactor->SetRenderWindow(renderer->GetRenderWindow());
        interactor->Initialize();
        //////////////////////////////////////
    
    
        interactor->Start(); //イベントループへ入る
    
        return 0;
    }
    

    VTKでクリックした位置を注視点にする

    #include <iostream>
    
    //VTK_MODULE_INITに必要
    #include <vtkAutoInit.h>
    
    
    #include <vtkSmartPointer.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    
    //円筒とその表示に必要
    #include <vtkCylinderSource.h>
    #include <vtkPolyDataMapper.h>
    
    #pragma comment(lib,"opengl32.lib")
    #pragma comment(lib,"psapi.lib")
    #pragma comment(lib,"dbghelp.lib")
    #pragma comment(lib,"ws2_32.lib")
    
    
    //必須
    VTK_MODULE_INIT(vtkRenderingOpenGL2);
    VTK_MODULE_INIT(vtkInteractionStyle);
    
    #include <vtkInteractorStyleTrackballCamera.h>
    #include <vtkCamera.h>
    #include <vtkPropPicker.h>
    
    #include <vtkAppendPolyData.h>
    #include <vtkLineSource.h>
    #include <vtkProperty.h>
    
    
    // 注視点を表示するためのアクタを作成
    vtkSmartPointer<vtkActor> Create3DPlusActor(
        double length = 1.0,
        double width = 2.0
    );
    
    
    // マウスイベントをカスタマイズするためのクラス
    class MouseInteractorStyle2 : public vtkInteractorStyleTrackballCamera
    {
    public:
    
        // 注視点を表示するためのアクタ
        vtkSmartPointer<vtkActor> focal_mark; 
    
        static MouseInteractorStyle2* New();
        vtkTypeMacro(MouseInteractorStyle2, vtkInteractorStyleTrackballCamera);
    
        virtual void OnLeftButtonDown()
        {
            int ctrl = this->Interactor->GetControlKey();
            if (ctrl) {
    
                int* clickPos = this->GetInteractor()->GetEventPosition();
    
                // ピック下オブジェクトを取得
                auto picker = vtkSmartPointer<vtkPropPicker>::New();
                picker->Pick(clickPos[0], clickPos[1], 0, this->GetDefaultRenderer());
    
                // オブジェクトがクリックされていたら位置とアドレスを出力
                if (picker->GetActor() != nullptr) {
    
                    double* pos = picker->GetPickPosition();
    
                    auto camera = this->GetDefaultRenderer()->GetActiveCamera();
                    camera->SetFocalPoint(pos); // カメラの焦点をクリック位置に設定
                    focal_mark->SetPosition(pos); // クリック位置に移動
    
                }
            }
    
    
            // Forward events
            vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
        }
    
    private:
    
    };
    
    vtkStandardNewMacro(MouseInteractorStyle2);
    
    
    
    int main(int /*argc*/, char** /*argv*/)
    {
    
        //////////////////////////////////////
        // Create a vtkCylinderSource
        vtkSmartPointer<vtkCylinderSource> cylinderSource = vtkSmartPointer<vtkCylinderSource>::New();
        cylinderSource->SetCenter(0.0, 0.0, 0.0);
        cylinderSource->SetRadius(5.0);
        cylinderSource->SetHeight(7.0);
        cylinderSource->SetResolution(100);
    
        //////////////////////////////////////
        // Create a mapper and actor
        vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
        mapper->SetInputConnection(cylinderSource->GetOutputPort());
        vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
        actor->SetMapper(mapper);
    
        //////////////////////////////////////
        auto renderer = vtkSmartPointer<vtkRenderer>::New();
        renderer->AddActor(actor);
        renderer->ResetCamera();
    
    
    
    
        //////////////////////////////////////
        auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    
        //////////////////////////////////////
        auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
        renderWindow->AddRenderer(renderer);
        renderWindow->SetInteractor(interactor);
        renderWindow->Render();
    
    
        //////////////////////////////////////
        // マウスイベントを設定.
        auto style = vtkSmartPointer<MouseInteractorStyle2>::New();
        style->SetDefaultRenderer(renderer);
        interactor->SetInteractorStyle(style);
        //////////////////////////////////////
        vtkCamera* cam = renderer->GetActiveCamera();
        double focal[3];
        cam->GetFocalPoint(focal);
        auto axes = Create3DPlusActor(1, 1);
        axes->SetPosition(focal);
        renderer->AddActor(axes); // 軸をレンダラーに追加
        style->focal_mark = axes;
    
        //////////////////////////////////////
    
        interactor->Start(); //イベントループへ入る
    
        return 0;
    }
    
    
    
    // 線分の長さ、太さ、色を指定できる
    vtkSmartPointer<vtkActor> Create3DPlusActor(
        double length,
        double width
    ) {
        double center[3]= { 0.0, 0.0, 0.0 };
        double color[3] = { 1.0, 1.0, 1.0 };
    
        // 各軸の線分を作成
        auto appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
    
        // x軸の線
        auto xLine = vtkSmartPointer<vtkLineSource>::New();
        xLine->SetPoint1(center[0] - length / 2.0, center[1], center[2]);
        xLine->SetPoint2(center[0] + length / 2.0, center[1], center[2]);
        xLine->Update();
        appendFilter->AddInputData(xLine->GetOutput());
    
    
    
        // y軸の線
        auto yLine = vtkSmartPointer<vtkLineSource>::New();
        yLine->SetPoint1(center[0], center[1] - length / 2.0, center[2]);
        yLine->SetPoint2(center[0], center[1] + length / 2.0, center[2]);
        yLine->Update();
        appendFilter->AddInputData(yLine->GetOutput());
    
        // z軸の線
        auto zLine = vtkSmartPointer<vtkLineSource>::New();
        zLine->SetPoint1(center[0], center[1], center[2] - length / 2.0);
        zLine->SetPoint2(center[0], center[1], center[2] + length / 2.0);
        zLine->Update();
        appendFilter->AddInputData(zLine->GetOutput());
    
        appendFilter->Update();
    
        // マッパーとアクター
        auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
        mapper->SetInputConnection(appendFilter->GetOutputPort());
    
        auto actor = vtkSmartPointer<vtkActor>::New();
        actor->SetMapper(mapper);
        actor->GetProperty()->SetLineWidth(width);
        actor->GetProperty()->SetColor(color);
    
        return actor;
    }
    

    昔書いた内容かどうか思い出せない。コードを書いた記憶はあるが記事が見つからなかった。

    やったことはあるかもしれないが、きっと当時よりはよいコードになっている。