Blender进阶Python编程3D开发-源码分析笔记系列-做出你自己的3D数据图表

Blender进阶Python编程3D开发-源码分析笔记系列-做出你自己的3D数据图表

忽然想起之前研究Blender时,用Python编程做了个3D图表。当时还觉得只是炫酷而已,现在用处来了~

你有没有在写文章时感觉:

  • 在Markdown做表格太枯燥?
  • 不能像用Jupyter Notebook时,直接用matplotlib,而只能插入图表图片?
  • 感觉做得再炫酷也只是2D平平的?

同感三连的话,我们走起试一下用Blender的Python编辑功能,做一个3D数据图表~

注:前置基础

  • 3D软件设计的日常(Blender无Python编辑的各种操作及热键)
  • 基本Python编程技能
  • 编程环境,比如VScode及常用技巧

BTW,可以把Blender的Scripting模式(文尾有附图)里,代码窗口的代码们,复制到VSCode内,就能解锁以下几个 姿势 \xcancel{姿势} 姿势 大招:

  • 快捷键Alt+Shift+↓键:复制当前行
  • Alt+Z:自动换行

案例源码及分析

先放效果

3Ddata

代码直击

import bpy
#import csv

filepath=r'C:\<your path>\BlenderProject\BlenderPython\data\04\tutorial.txt'

data=dict()

with open(filepath, 'r') as txt_file:
    for idx,line in enumerate(txt_file.readlines()):
        if idx>0:
            line=line.rstrip('\n')    
            day=line.split(',')[0]
            hours_worked=line.split(',')[1]
        
            data[idx]={
    
    
                'lable':day,
#               'hours_worked':hours_worked
                'value':hours_worked
            }
#Cleanup scene
for obj in bpy.data.objects:
    bpy.data.objects.remove(obj)
    
#Visualize data
for idx, data_entry in enumerate(data):
#    print(data[data_entry])
    #Create a bar  
    height=float(data[data_entry]['value'])
#    label=data[data_entry]['lable']
#    print(label)
#    print(value)
    bpy.ops.mesh.primitive_cube_add(size=1, location=(0, idx, 0))
    bpy.ops.transform.resize(value=(1, 1, height), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

    bpy.ops.transform.translate(value=(0, 0, height/2), orient_axis_ortho='X', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

    #Label the bar
    label=data[data_entry]['lable']
    bpy.ops.object.text_add(enter_editmode=True,location=(0.6,idx-0.5, 0))
    bpy.ops.font.delete(type='PREVIOUS_WORD')
    bpy.ops.font.text_insert(text=label)
    bpy.ops.object.editmode_toggle()
    

#    reader=csv.reader(csv_file)
#    
##    for row in readers:
##        data[row[0]]=row[1]
##            
#    for idx, row in enumerate(reader):
#        data[idx]={
    
    
#            'lable':row[0],
#            'value':row[1],
#            }
#print(data)

改写案例

操作思路

先得有个数据来源,比如:全国历年考研人数;
然后:

  • 改写表格内容(这里是.txt文件)
  • 相关代码改写与 调教 \bcancel{调教} 调教 调试
  • 生成/渲染效果

代码直击

import bpy
#import csv


#filepath=r'C:\<your path>\BlenderProject\BlenderPython\data\04\tutorial.txt'
filepath=r'C:\PC2013_Code\BlenderProject\BlenderPython\data\04\pee_num.txt'
data=dict()

with open(filepath, 'r') as txt_file:
    for idx,line in enumerate(txt_file.readlines()):
        if idx>0:
            line=line.rstrip('\n')    
            #day=line.split(',')[0]
            Year=line.split(',')[0]
            #hours_worked=line.split(',')[1]
            num10k=line.split(',')[1]
        
            data[idx]={
    
    
                #'lable':day,
                'lable':Year,
#               'hours_worked':hours_worked
                #'value':hours_worked
                'value':num10k
            }
#Cleanup scene
for obj in bpy.data.objects:
    bpy.data.objects.remove(obj)
    
#Visualize data
for idx, data_entry in enumerate(data):
#    print(data[data_entry])
    #Create a bar  
    height=float(data[data_entry]['value'])
#    label=data[data_entry]['lable']
#    print(label)
#    print(value)
    bpy.ops.mesh.primitive_cube_add(size=1, location=(0, idx, 0))
    bpy.ops.transform.resize(value=(1, 1, height), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

    bpy.ops.transform.translate(value=(0, 0, height/2), orient_axis_ortho='X', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

    #Label the bar
    label=data[data_entry]['lable']
    bpy.ops.object.text_add(enter_editmode=True,location=(0.6,idx-0.5, 0))
    bpy.ops.font.delete(type='PREVIOUS_WORD')
    bpy.ops.font.text_insert(text=label)
    bpy.ops.object.editmode_toggle()
    

          

#    reader=csv.reader(csv_file)
#    
##    for row in readers:
##        data[row[0]]=row[1]
##            
#    for idx, row in enumerate(reader):
#        data[idx]={
    
    
#            'lable':row[0],
#            'value':row[1],
#            }
#print(data)

效果展示

你不对劲…
pee_num
敬仰之视角:
pee_num1
意识到问题所在:人家原先都是个位数,我这里的都是好几百~
篇幅关系(其实没有),直接给出位置截图:
pee_num2
贴心给出代码,方便复制粘贴:

    #height=float(data[data_entry]['value'])
    height=float(data[data_entry]['value'])/100

正常些了(怎么感觉又有些矮月半)…
pee_num3
好吧,先到这里,还需要进一步调试,比如:

  • 纵轴的数据
  • 厚度削薄些
  • 标题与上色

做好后拿到3D数据图表的图片(虽然还是平平的…),继续 肝 \cancel{肝} 赶其它稿子去了~

参考资料

暂时找不到了【建设中】

附图

Blender的Scripting窗口酱紫:
Blender的Scripting窗口
VSCode的窗口,鲜艳而舒适多了~
VSCode的窗口

猜你喜欢

转载自blog.csdn.net/AIShawnINT/article/details/126312549