NSDT工具推荐Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割 - 3D道路快速建模

我想为大约 1000 多个 NFT 收藏品创建 3D 角色,但不知道该怎么做。手动一个一个地创建所有模型是愚蠢的。

实际上,我喜欢使用 Blender 来创建 3D 模型,所以也想使用它。

当我在互联网上搜索时,我发现Blender Scripting(Python)可以用于随机组合各种特征以编程方式创建3D模型的解决方案。它使用Python语言。

1、NFT藏品目录结构

目录树如下:

树
  • parts ——其中包含的每个 3D 零件。
  • body ——身体。
  • head ——头。
  • misc — 其他文件(背景、灯光、相机等)。
  • outputs——由 Blender 脚本生成的图像和元数据。
  • script - Python脚本文件。

2、创建3D部件

这一次,创建 2 种类型的零件,包括头部身体。和misc(包括背景图像、相机、灯光的文件)

步骤如下:

  1. 打开 Blender 并创建一个新文件并删除所有默认对象,并将其保存在bodyhead文件夹中。(例如nft-collectibles/parts/head/head_rabbit.blend
  2. 在 Blender 中,创建一个与文件名相同的新集合。(例如,如果文件名为head_rabbit.blend,则集合名称为head_rabbit
  3. 在刚刚创建的集合中创建一个零件模型。
  4. 调整大小和位置,使角色看起来自然。
  5. 最后保存。

2.1 3D NFT 头部件示例

文件名:nft-collectibles/parts/head/head_rabbit.blend
收藏名:head_rabbit

文件名:nft-collectibles/parts/head/head_frog.blend
收藏名:head_frog

Head_2

2.2 3D NFT身体部件示例

文件名:nft-collectibles/parts/body/body_shirt.blend
收藏名:body_shirt

身体_1

文件名:nft-collectibles/parts/head/body_zombie.blend
收藏名:body_zombie

身体_2

2.3 3D NFT 辅助部件示例

文件名:nft-collectibles/parts/misc/misc.blend
收藏名:misc

3、创建Blender Python脚本文件

要创建脚本文件,请在 Blender的脚本工作区中打开你喜欢的代码/文本编辑器或文本编辑器。

3.1 gen_metadata.py

这是为了为 NFT 生成随机元数据:

import bpy  # The module for Blender Python
import json
import random

# This time, 100 characters will be generated.
TOTAL_CHARACTERS = 100

# Specify the directory in which generate images finally.
OUTPUTS_DIR = "c:/nft-collectibles/outputs/"

# List of parts (the file name (collection name) of each created part is included in this.)
list_body = [
    "hoodie",
    "overall",
    "pants",
    "shirt",
    "tanktop",
    "t_shirt",
    "zombie"
]
list_head = [
    "devil",
    "dragon",
    "frog",
    "king",
    "pirate",
    "rabbit",
    "robot",
    "skull",
    "warrior"
]


def random_attributes():
    # Select parts randomly from lists
    random_head = random.choice(list_head)
    random_body = random.choice(list_body)

    # Format each name for the value of attributes in metadata (e.g. "head_rabbit" -> "Head Rabbit")
    random_head = random_head.replace("_", " ").title()
    random_body = random_body.replace("_", " ").title()

    attributes = [
        {
            "trait_type": "Body",
            "value": random_body
        },
        {
            "trait_type": "Head",
            "value": random_head
        }
    ]

    return attributes


def main():
    print("Start generating metadata...")

    # Create a tempolary dict
    dict_list = []

    for i in range(TOTAL_CHARACTERS):
        attributes = random_attributes(i)
        d = { "attributes": attributes }
        dict_list.append(d)

    # Create a list of unique data removed duplicates 
    unique_list = list(map(json.loads, set(map(json.dumps, dict_list))))
    # If the duplicated found, cancel scripting and try again
    if len(unique_list) < TOTAL_CHARACTERS:
        print("ERROR: Properties duplicate")
        return

    # Save metadata files (.json) to outputs folder
    for i, attr_dict in enumerate(unique_list):
        # Create a metadata object
        obj = {
            "name": "Character #" + str(i),
            "description": "A collection of 3D character",
            "image": "https://example.com/"+ str(i) + ".png",
            "external_url": "https://example.com/",
            "attributes": attr_dict["attributes"]
        }
        with open(OUTPUTS_DIR + str(i) + ".json", 'w') as outjson:
            json.dump(obj, outjson, indent=4)

        print("Generated metadata id: {}\n".format(i))


main()

3.2 gen_model.py

这是为了从元数据生成模型。

import bpy
import json
import random
import shutil

# This time, 100 characters will be generated.
TOTAL_CHARACTERS = 100

# Path
PARTS_DIR = "c:/nft-collectibles/parts/"
OUTPUTS_DIR = "c:/nft-collectibles/outputs/"


# Initialize the scene (deleting the all default objects)
def init():
    for obj in bpy.data.objects:
        bpy.data.objects.remove(obj)
    for col in bpy.data.collections:
        bpy.data.collections.remove(col)


# Set configurations for rendering
def set_render_config():

    # For example, set the rendering engine "EEVEE" (but Blender may be configured EEVEE default. if so, you don't need to do that)
    r = bpy.context.scene.render
    r.engine = "BLENDER_EEVEE"
    r.resolution_x = 1024
    r.resolution_y = 1024

    # Set the output file format
    r.image_settings.file_format = 'PNG'


def append_misc():
    path = PARTS_DIR + "misc/" + "misc.blend/Collection/"
    collection_name = "misc"
    bpy.ops.wm.append(filename=collection_name, directory=path)

    # Link camera to scene
    cam = bpy.data.objects["camera"]
    scene = bpy.context.scene
    scene.camera = cam


def append_body(trait_value):
    body_name = "body_" + trait_value

    path = PARTS_DIR + "body/" + body_name + ".blend/Collection/"
    bpy.ops.wm.append(filename=body_name, directory=path)


def append_head(trait_value):
    head_name = "head_" + trait_value

    path = PARTS_DIR + "head/" + head_name + ".blend/Collection/"
    bpy.ops.wm.append(filename=head_name, directory=path)


def render(id):
    # Render
    bpy.ops.render.render(write_still=1)

    # Save
    bpy.data.images['Render Result'].save_render(filepath=OUTPUTS_DIR + id + ".png")


def remove_parts():
    # Remove all parts except "misc"
    for col in bpy.data.collections:
        if col.name != "misc":
            for obj in col.objects:
                bpy.data.objects.remove(obj)
            bpy.data.collections.remove(col)
            continue


def generate(id, metadata):
    for attr in metadata["attributes"]:
        # Body
        if attr["trait_type"] == "Body" and attr["value"] != "":
            append_body(attr["value"])
        # Head
        if attr["trait_type"] == "Head" and attr["value"] != "":
            append_head(attr["value"])

    render(str(id))

    # After rendered, remove all parts
    remove_parts()


def main():
    print("Start generating models...")

    init()
    set_render_config()
    append_misc()   # Regarding "misc", add it to the scene in advance because it is common to all characters.

    # Generate character images
    for i in TOTAL_CHARACTERS:
        with open(OUTPUTS_DIR + str(i) + ".json", 'r') as metaJson:
            data = json.load(metaJson)
            generate(i, data)
            print("Generated model id: {}\n".format(id))

main()

4、 运行脚本

创建脚本文件后,你可以运行它们。
打开 Blender 并单击编辑器顶部 几何节点旁边的脚本工作区。

脚本工作区

要检查处理过程中的状态,可以通过单击顶部菜单中的“窗口”->“切换系统控制台”来打开控制台。

4.1、生成元数据

单击Open -> 选择gen_metadata.py -> 单击Run Script

如上源代码所示(gen_metadata.py,第68-73行),如果数据组合重复,该过程将被取消。在这种情况下,你需要再次单击运行脚本

之后,可以看到在output文件夹中生成了0.json1.json等元数据文件。

4.2 生成3D NFT角色

点击Open -> 选择一个gen_model.py -> 点击Run Script

之后,可以看到在output文件夹中生成了0.png1.png等渲染图像文件。


原文链接:Create NFT 3D Collectibles Using Blender Scripting

BimAnt翻译整理,转载请标明出处