見出し画像

ブレンダー ワンクリックで360スクショ スプリクト 


2024年 7月13日 更新 コードにある程度汎用性を持たせました。

ワンクリックでこんな感じのスクショが撮れます。

使用する上での注意事項


・OSはWindows11です。

・このスプリクトはBlender(ブレンダー)で動作します。

・このスプリクトは全てAIに書いてもらったものです。私自身プログラミングが一ミリも分からない素人なので動かなかったらすみません!!!

サポートが必要な場合はAIに聞くことをおススメします。特にclaude先生はとても頼りになるのでおススメです。

・このスプリクトは3Dモデル・オブジェクト単体での撮影を想定しています。

・初期設定ではVroid StudioでエクスポートされたVRMファイルの3Dモデルに最適化されています。

・自分が確認した限りではVroid Studioの.vrm・DAZの.obj・ブレンダーの.blendの各3Dモデルで動作しました。

※動作しましたが.vrm以外は画面外にはみ出ることがあったので、そういった場合は良い感じに調整してください。

VRoid Studioでのキャラクター作りについて

c/ja/articles/4405597663385-VRoid%E3%82%92%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86

ページを見なくても直観的にパーツをいじっていくだけで結構それらしいものが出来ます。

.VRMモデルをブレンダーに読み込ませる。


vroid studioでモデルを作成したあとにVRMエクスポートをクリック

右上のアップロードアイコンをクリックするとVRMエクスポートが表示されます。
エクスポートをクリック
アバター名と作者を適当な名前で埋める
エクスポートをクリック。

※エクスポートだけをする場合はオンライン上にファイルがアップロードされることはありません。

任意の保存フォルダに保存した後、以下のようなファイルが作成されます。

.VRM形式の3Dモデルが作成されました。

次に以下のサイトに行きDownloadをクリック

するとダウンロードフォルダなどに
以下のファイルがダウンロードされます。


以下のページを参考にブレンダーに拡張機能をインストールします。

ページをブラウザの翻訳機能で翻訳したものを引用

拡張機能をインストールしたらファイルをクリック

インポートを選択し、VRMをクリック

読み込ませたいVRMファイルを選択しFRMをインポートをクリック

新規ページにVRMを読み込むとこんな感じに表示されます。

キューブを削除するためにキューブを左クリック

キューブが選択されるとオレンジの枠が表示されます。

キューブをクリックした後に画像のように選択してキューブを削除

これでVRMモデルだけをブレンダ上に表示させることができました。



ザックリとした使用・調整方法

スクリプト作成をクリック

スクリプト作成をクリックした後で新規をクリック

下の画面が出てくるので、ここに下記のコードをコピー&ペースト

※コードの以下の部分を保存したいフォルダパスに変更してください。

以下のようにファイルエクスプローラーで
保存したいフォルダを開いてアドレスバーを
右クリックしてフォルダパスをコピーするとラクです。

そして最後に実行を押します

すると保存先に設定したフォルダに
以下のように画像が出力されていきます。

pcの性能によっては出力に時間がかかるかもしれません。

出力画像の調整方法

画像の保存先を設定する方法
output_dir = r"C:\Users\admin\Documents\DAZ 3D\1" 
””に囲まれた部分を保存したい場所のファイルパスに変更してください。

3Dモデル・オブジェクトの位置を調整する方法

scene_center = (min_coord + max_coord) / 0.8
この数値の上下でモデルの上げ下げができます。

cam.data.lens = 100 
数値を上げるとカメラが近づき、下げると遠くなります。

radius = scene_size * 1.3 
数値を下げるとカメラが近づき、上げると遠くなります。

・画像サイズを変更する方法

bpy.context.scene.render.resolution_x = 1024 
画像の横のピクセル数を設定します。

bpy.context.scene.render.resolution_y = 1024
画像の縦のピクセル数を設定します。

出力画像枚数を変更する方法

for i in range(12): 
各アングル(上・中・下)の写真を何枚撮影するか決定する項目。
()の数値を変更してください。

1に設定すると上・中・下、合計3枚のスクショが出力されます。
他の数値を調整したあとの結果を確認する際に便利です。

その他にもライトの光量・あたる角度など色々調整できます。

コードver2

import bpy  # BlenderのPythonモジュールをインポート
import math  # 数学モジュールをインポート
import os  # OSモジュールをインポート
import mathutils  # Blenderの数学ユーティリティをインポート

# どこに画像を保存するかを指定します。ここでは、Cドライブの中の特定のフォルダに保存します。
output_dir = r"C:\Users\admin\Documents\DAZ 3D\1"

# シーンの中にあるカメラを取得します。これは写真を撮るためのカメラです。
cam = bpy.data.objects['Camera']

# オブジェクトの位置を元に戻す関数です。オブジェクトはシーン内にある色々な物体です。
def reset_object_positions():
    for obj in bpy.data.objects:  # シーン内の全てのオブジェクトを繰り返し処理
        if obj.type != 'CAMERA':  # カメラオブジェクトを除外
            # オブジェクトの位置を0に戻します。これはシーンの中心です。
            obj.location = mathutils.Vector((0, 0, 0))
            # オブジェクトの回転をリセットします。つまり、向きを初期状態に戻します。
            obj.rotation_euler = mathutils.Euler((0, 0, 0))
            # オブジェクトの大きさを元に戻します。元の大きさは1です。
            obj.scale = mathutils.Vector((1, 1, 1))

# 全てのオブジェクトの位置を初期化します。
reset_object_positions()

# シーン内の全てのオブジェクトの大きさを計算する関数です。
def calculate_scene_bounding_box():
    min_coord = mathutils.Vector((float('inf'), float('inf'), float('inf')))  # 最小座標の初期値を設定
    max_coord = mathutils.Vector((float('-inf'), float('-inf'), float('-inf')))  # 最大座標の初期値を設定
    
    # メッシュ、カーブ、サーフェスなどのオブジェクトを対象にします。これらは一般的な3Dオブジェクトの種類です。
    for obj in bpy.data.objects:  # シーン内の全てのオブジェクトを繰り返し処理
        if obj.type in ['MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'ARMATURE', 'LATTICE']:
            for v in obj.bound_box:  # 各オブジェクトのバウンディングボックスの頂点を繰り返し処理
                # オブジェクトの各頂点をグローバル座標に変換します。
                v_global = obj.matrix_world @ mathutils.Vector(v)
                # シーンの中で最も小さい座標を見つけます。
                min_coord = mathutils.Vector(min(min_coord[i], v_global[i]) for i in range(3))
                # シーンの中で最も大きい座標を見つけます。
                max_coord = mathutils.Vector(max(max_coord[i], v_global[i]) for i in range(3))
    
    return min_coord, max_coord  # 最小座標と最大座標を返します

# シーンの中心とサイズを計算します。
min_coord, max_coord = calculate_scene_bounding_box()  # バウンディングボックスを計算
scene_center = (min_coord + max_coord) / 0.8  # シーンの中心を計算します。この数値の上下でモデルを上げ下げできます。
scene_size = (max_coord - min_coord).length  # シーンの大きさを計算します。

# シーンのライトを設定する関数です。ライトはシーンを照らす光です。
def setup_lighting():
    # 既存のライトを全て削除します。
    for obj in bpy.data.objects:  # シーン内の全てのオブジェクトを繰り返し処理
        if obj.type == 'LIGHT':  # ライトオブジェクトを対象にします。
            bpy.data.objects.remove(obj, do_unlink=True)  # ライトオブジェクトを削除します。
    
    # 新しい太陽光を追加します。これはシーン全体を照らします。
    light_data = bpy.data.lights.new(name="Sun Light", type='SUN')  # 新しいライトデータを作成します。
    light_object = bpy.data.objects.new(name="Sun Light", object_data=light_data)  # 新しいライトオブジェクトを作成します。
    bpy.context.scene.collection.objects.link(light_object)  # ライトオブジェクトをシーンにリンクします。
    # 太陽光の角度を設定します。
    light_object.rotation_euler = (math.radians(45), 0, math.radians(45))  # ライトの回転を設定します。
    light_data.energy = 5  # 光の強さを設定します。

    # 新しいエリアライトを追加します。これは特定の部分を明るくします。
    area_light_data = bpy.data.lights.new(name="Area Light", type='AREA')  # 新しいエリアライトデータを作成します。
    area_light_object = bpy.data.objects.new(name="Area Light", object_data=area_light_data)  # 新しいエリアライトオブジェクトを作成します。
    bpy.context.scene.collection.objects.link(area_light_object)  # エリアライトオブジェクトをシーンにリンクします。
    # エリアライトの位置を設定します。
    area_light_object.location = scene_center + mathutils.Vector((scene_size / 2, -scene_size / 3, scene_size / 3))  # エリアライトの位置を設定します。
    # エリアライトの角度を設定します。
    area_light_object.rotation_euler = (math.radians(45), 0, math.radians(45))  # エリアライトの回転を設定します。
    area_light_data.energy = 1000  # 光の強さを設定します。
    area_light_data.size = scene_size / 4  # ライトの大きさを設定します。

# ライトのセットアップを実行します。
setup_lighting()

# レンダリング設定を行う関数です。レンダリングは画像を生成するプロセスです。
def setup_rendering():
    bpy.context.scene.render.engine = 'BLENDER_EEVEE'  # EEVEEというレンダリングエンジンを使います。
    bpy.context.scene.eevee.taa_render_samples = 128  # レンダリングの品質を設定します。数字が大きいほど高品質です。
    bpy.context.scene.render.resolution_x = 1024  # 画像の横のピクセル数を設定します。
    bpy.context.scene.render.resolution_y = 1024  # 画像の縦のピクセル数を設定します。
    bpy.context.scene.render.film_transparent = True  # 背景を透明に設定します。

    # 背景を透明に設定します。
    world = bpy.context.scene.world  # シーンのワールド設定を取得します。
    world.use_nodes = True  # ノードを使う設定にします。
    bg_node = world.node_tree.nodes["Background"]  # 背景ノードを取得します。
    bg_node.inputs[0].default_value = (1, 1, 1, 0)  # 背景を透明に設定します。

# レンダリング設定を適用します。
setup_rendering()

# カメラの位置を変更する関数です。カメラはシーンを撮影するためのものです。
def set_camera_position(elevation, azimuth):
    radius = scene_size * 1.3  # シーンの大きさに基づいてカメラの距離を設定します。数値を下げると近づき、上げると遠くなる1
    # カメラの位置を計算します。
    x = radius * math.sin(azimuth) * math.cos(elevation)
    y = radius * math.cos(azimuth) * math.cos(elevation)
    z = radius * math.sin(elevation)
    cam.location = scene_center + mathutils.Vector((x, y, z))  # カメラの位置を設定します。
    
    # カメラをシーンの中心に向けます。
    direction = scene_center - cam.location  # カメラからシーンの中心への方向を計算します。
    rot_quat = direction.to_track_quat('-Z', 'Y')  # カメラの回転を計算します。
    cam.rotation_euler = rot_quat.to_euler()  # カメラの回転を設定します。

    # カメラの焦点距離を調整します。焦点距離はレンズのズーム具合を決めます。
    cam.data.lens = 100  # 数値を上げるとカメラが近づき、下げると遠くなる。

# カメラを動かしながら写真を撮影します。
elevations = [math.radians(40), math.radians(0), math.radians(-40)]  # カメラの高さを設定します。
for elevation in elevations:  # 各高さでループ
    for i in range(12):  # 12枚の写真を撮ります。各アングルの撮影枚数を決定できます。
        azimuth = i * (2 * math.pi / 12)  # カメラの角度を計算します。
        set_camera_position(elevation, azimuth)  # カメラの位置を設定します。
        bpy.context.view_layer.update()  # シーンを更新します。
        
        # 画像ファイルの名前を設定します。
        elevation_name = "up" if elevation > 0 else "down" if elevation < 0 else "front"  # 高さに応じた名前を設定します。
        bpy.context.scene.render.filepath = os.path.join(output_dir, f"{elevation_name}rotation{i * 30}.png")  # 画像ファイルのパスを設定します。
        
        # レンダリングを実行し、画像を保存します。
        bpy.ops.render.render(write_still=True)  # レンダリングを実行し、画像を保存します。

print("All screenshots taken!")  # すべてのスクリーンショットが撮影されたことを表示します。

応用例


scene_center = (min_coord + max_coord) / 0.465

cam.data.lens = 340

上の設定で.VRMモデルを撮影すると
以下のようにバストアップで撮影できます。

上の設定だとモデルのサイズによっては見切れます。

elevations = [math.radians(40), math.radians(0), math.radians(-40)] を

elevations = [ math.radians(0)] のみにすると

以下のように中アングルのみの360度スクショを撮ることができます。

この記事が気に入ったらサポートをしてみませんか?