From 431a613ae2b9ead2ecd820f6bc9cffb620f430d5 Mon Sep 17 00:00:00 2001 From: akaneyu Date: Tue, 5 Mar 2024 21:02:32 +0900 Subject: [PATCH] Initial commit --- .gitignore | 2 + CMakeLists.txt | 11 +++++ addon/__init__.py | 35 ++++++++++++++ addon/cpp_test.py | 93 ++++++++++++++++++++++++++++++++++++++ addon/utils.py | 21 +++++++++ src/cpp_test_processor.cpp | 78 ++++++++++++++++++++++++++++++++ src/cpp_test_processor.h | 35 ++++++++++++++ 7 files changed, 275 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 addon/__init__.py create mode 100644 addon/cpp_test.py create mode 100644 addon/utils.py create mode 100644 src/cpp_test_processor.cpp create mode 100644 src/cpp_test_processor.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b958328 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build*/ +__pycache__/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..43c3502 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.11) + +set(LIB_NAME cpp_test) + +project(${LIB_NAME}) + +add_library(${LIB_NAME} SHARED + src/cpp_test_processor.cpp + + src/cpp_test_processor.h +) diff --git a/addon/__init__.py b/addon/__init__.py new file mode 100644 index 0000000..a3961f0 --- /dev/null +++ b/addon/__init__.py @@ -0,0 +1,35 @@ +bl_info = { + "name": "Cpp Test", + "author": "akaneyu", + "version": (1, 1, 1), + "blender": (2, 93, 0), + "location": "Image", + "warning": "", + "description": "", + "wiki_url": "", + "tracker_url": "", + "category": "Paint"} + +if "bpy" in locals(): + import importlib + importlib.reload(cpp_test) + importlib.reload(utils) + +import bpy +from . import cpp_test + +classes = [ + cpp_test.CPP_TEST_OT_generate_image, + cpp_test.CPP_TEST_PT_panel +] + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + +def unregister(): + for cls in classes: + bpy.utils.unregister_class(cls) + +if __name__ == "__main__": + register() diff --git a/addon/cpp_test.py b/addon/cpp_test.py new file mode 100644 index 0000000..2813b21 --- /dev/null +++ b/addon/cpp_test.py @@ -0,0 +1,93 @@ +import sys +import os +import ctypes +import bpy +import numpy as np +from . import utils + +class Session: + def __init__(self): + pass + +def get_session(): + global session + + return session + +def load_native_library(): + script_dir = os.path.dirname(os.path.realpath(__file__)) + + if os.name == 'nt': + lib_file_name = 'cpp_test.dll' + else: + lib_file_name = 'libcpp_test.so' + + lib = ctypes.CDLL(os.path.join(script_dir, lib_file_name)) + + return lib + +def unload_native_library(lib): + if os.name == 'nt': + kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) + kernel32.FreeLibrary.argtypes = [ctypes.c_void_p] + kernel32.FreeLibrary(lib._handle) + else: + stdlib = ctypes.CDLL("") + stdlib.dlclose.argtypes = [ctypes.c_void_p] + stdlib.dlclose(lib._handle) + +class CPP_TEST_OT_generate_image(bpy.types.Operator): + """Generate a image""" + bl_idname = "cpp_test.generate_image" + bl_label = "Generate Image" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self, context): + global session + + wm = context.window_manager + + native_lib = load_native_library() + + native_lib.CPPTEST_init() + + img = bpy.data.images.new('cpp_test', 1024, 1024, alpha=True) + + context.tool_settings.image_paint.canvas = img + context.tool_settings.image_paint.mode = 'IMAGE' + + img_width, img_height = img.size + + pixels = utils.read_pixels_from_image(img) + pixels_ctypes = pixels.ctypes.data_as(ctypes.POINTER(ctypes.c_float)) + + native_lib.CPPTEST_setImageSize(img_width, img_height) + native_lib.CPPTEST_setImagePixels(pixels_ctypes) + + native_lib.CPPTEST_process() + + utils.write_pixels_to_image(img, pixels) + + native_lib.CPPTEST_free() + + unload_native_library(native_lib) + + return {'FINISHED'} + +class CPP_TEST_PT_panel(bpy.types.Panel): + bl_label = "Cpp Test" + bl_space_type = "IMAGE_EDITOR" + bl_region_type = "UI" + bl_category = "Cpp Test" + + @classmethod + def poll(cls, context): + return True + + def draw(self, context): + layout = self.layout + + row = layout.row() + op = row.operator(CPP_TEST_OT_generate_image.bl_idname, text='Generate Image') + +session = Session() diff --git a/addon/utils.py b/addon/utils.py new file mode 100644 index 0000000..a86cc06 --- /dev/null +++ b/addon/utils.py @@ -0,0 +1,21 @@ +import bpy +import numpy as np + +def read_pixels_from_image(img): + width, height = img.size[0], img.size[1] + + if bpy.app.version >= (2, 83, 0): + pixels = np.empty(len(img.pixels), dtype=np.float32); + img.pixels.foreach_get(pixels) + return np.reshape(pixels, (height, width, 4)) + else: + return np.reshape(img.pixels[:], (height, width, 4)) + +def write_pixels_to_image(img, pixels): + if bpy.app.version >= (2, 83, 0): + img.pixels.foreach_set(np.reshape(pixels, -1)) + else: + img.pixels = np.reshape(pixels, -1) + + if img.preview: + img.preview.reload() diff --git a/src/cpp_test_processor.cpp b/src/cpp_test_processor.cpp new file mode 100644 index 0000000..cf2aadd --- /dev/null +++ b/src/cpp_test_processor.cpp @@ -0,0 +1,78 @@ +#include "cpp_test_processor.h" + +#include +#include + +using namespace std; + +Processor *g_processor; + +int CPPTEST_init() +{ + g_processor = new Processor(); + + return 0; +} + +void CPPTEST_free() +{ + delete g_processor; +} + +void CPPTEST_setImageSize(int width, int height) +{ + g_processor->setImageSize(width, height); +} + +void CPPTEST_setImagePixels(float *pixels) +{ + g_processor->setImagePixels(pixels); +} + +void CPPTEST_process() +{ + g_processor->process(); +} + +Processor::Processor() : + m_imageWidth(0), + m_imageHeight(0), + m_imagePixels(NULL) +{ +} + +Processor::~Processor() +{ +} + +void Processor::setImageSize(int width, int height) +{ + m_imageWidth = width; + m_imageHeight = height; +} + +void Processor::process() +{ + int x, y; + + for (y = 0; y < m_imageHeight; y++) { + for (x = 0; x < m_imageWidth; x++) { + long offset = (m_imageWidth * y + x) * 4; + + float *addr = m_imagePixels + offset; + + float r = (float) cos(x * 0.01); + float g = (float) sin(y * 0.01); + float b = (float) cos(x * y * 0.01); + + r = (r + 1.0f) / 2.0f; + g = (g + 1.0f) / 2.0f; + b = (b + 1.0f) / 2.0f; + + *addr = r; + *(addr + 1) = g; + *(addr + 2) = b; + *(addr + 3) = 1.0f; + } + } +} diff --git a/src/cpp_test_processor.h b/src/cpp_test_processor.h new file mode 100644 index 0000000..8a1b598 --- /dev/null +++ b/src/cpp_test_processor.h @@ -0,0 +1,35 @@ +#ifndef CPP_TEST_PROCESSOR_H_ +#define CPP_TEST_PROCESSOR_H_ + +#if defined(_MSC_VER) + #define EXPORT __declspec(dllexport) +#else + #define EXPORT +#endif + +extern "C" { + +EXPORT int CPPTEST_init(); +EXPORT void CPPTEST_free(); +EXPORT void CPPTEST_setImageSize(int width, int height); +EXPORT void CPPTEST_setImagePixels(float *pixels); +EXPORT void CPPTEST_process(); + +} + +class Processor +{ +public: + Processor(); + virtual ~Processor(); + void setImageSize(int width, int height); + void setImagePixels(float *pixels) { m_imagePixels = pixels; } + void process(); + +private: + int m_imageWidth; + int m_imageHeight; + float *m_imagePixels; +}; + +#endif // CPP_TEST_PROCESSOR_H_