Kính sọc đen

Nov 03 2020

Tôi còn khá mới với Blender và tôi đang cố gắng tạo ra một hình dung về kết quả khoa học của mình. Tôi bắt đầu bằng cách tạo dữ liệu giả của đường tâm và sau đó sử dụng đường cong Bezier để nội suy. Sau đó, tôi chỉ định góc xiên cho nó (một hình vuông đơn giản, được xác định bởi polyline) và do đó tạo ra một đối tượng 3D (tôi cũng đóng nắp). Ít nhất thì tôi hy vọng đó là một vật thể 3D, tôi không chắc liệu mình có nên sử dụng một số chức năng lấp đầy hay không.

Tuy nhiên, tôi đã cố gắng tạo ra tất cả những thứ này, đặt nó trong một môi trường, nơi tôi bao quanh đối tượng của mình bằng các bức tường và đưa vào đó một ánh sáng. Tôi đã gán cho nó một vật liệu giống như thủy tinh. Khi tôi kết xuất (chu kỳ), hình ảnh của tôi có các sọc đen lạ và tôi không biết cách khắc phục. Tôi có tất cả trong một kịch bản mà bạn có thể tìm thấy dưới đây.

Tất nhiên, tôi không phiền nếu giải pháp không có trong tập lệnh Python, tôi sẽ quản lý để chuyển đổi nó. Tôi chỉ muốn hiểu tại sao chúng lại xuất hiện và cách giải quyết.

import bpy
import numpy as np


# delete everything
print("\n\n\n\nNew run")
objs = [ob for ob in bpy.context.scene.objects]
bpy.ops.object.delete({"selected_objects": objs})
print("\n\n\n\n")

def dump(obj):
   for attr in dir(obj):
       if hasattr( obj, attr ):
           print( "obj.%s = %s" % (attr, getattr(obj, attr)))
           
def polyline_from(coords, name, closed):
    # create the Curve Datablock
    curvedata = bpy.data.curves.new(name, type='CURVE')
    curvedata.dimensions = '3D'
    
    # map coords to spline
    polyline = curvedata.splines.new('POLY')
    polyline.points.add(len(coords)-1)
    
    for i, coord in enumerate(coords):
        x,y = coord
        polyline.points[i].co = (x, y, 0, 1)
        
    if(closed):
        polyline.use_cyclic_u = True
  
    # create Object
    objectdata = bpy.data.objects.new(name+"Object", curvedata)

    return objectdata


def curve_from(coords, name, closed, res=10):
    # create the Curve Datablock
    curvedata = bpy.data.curves.new(name, type='CURVE')
    curvedata.dimensions = '3D'
    curvedata.resolution_u = res
    
    # map coords to spline
    spline = curvedata.splines.new('BEZIER')
    spline.bezier_points.add(len(coords)-1)
    
    for i, p in enumerate(spline.bezier_points):
        x,y,z = coords[i]
        p.co = (x, y, z)
        p.handle_left = (x, y, z)
        p.handle_right = (x, y, z)
        
        #Set automatic
        p.handle_right_type = 'AUTO'
        p.handle_left_type = 'AUTO'
        
    if(closed):
        spline.use_cyclic_u = True
    
    # create Object
    objectdata = bpy.data.objects.new(name+"Object", curvedata)

    return objectdata


# create scene
scene = bpy.context.scene
scene.world.color = (0,0,0)

# select render engine
scene.render.engine = 'CYCLES'

# Set render resolution
scene.render.resolution_x = 1920
scene.render.resolution_y = 1080

# Generate fake data
def data(t):    
    x = np.linspace(0, 1, 10)
    y = 0*x
    z = x**2 * 0.2 * np.sin(t)
    return np.array([x, y, z]).T

centerline_points = data(0)

# Cross section
cross_section_points = 0.5*np.array([
    [-0.1,-0.1],
    [ 0.1,-0.1],
    [ 0.1, 0.1],
    [-0.1, 0.1]
])

centerline = curve_from(
    coords=centerline_points,
    name="Centerline",
    closed=False,
    res=13
)

cross_section = polyline_from(
    coords=cross_section_points,
    name="CrossSection",
    closed=True
)

# add bevel object
centerline.data.bevel_object = cross_section
centerline.data.use_fill_caps = True

# attach to scene and validate context
scene.collection.objects.link(centerline)

# clear all previous animation data
centerline.animation_data_clear()

# set first and last frame index
total_time = 2*np.pi # Animation should be 2*pi seconds long
fps = 10 # Frames per second (fps)
scene.frame_start = 0
scene.frame_end = int(total_time*fps)+1

# loop of frames and insert keyframes every 10th frame
keyframe_freq = 1
nlast = bpy.context.scene.frame_end
for n in range(nlast):
    t = total_time*n/nlast

    # Do computations
    new_points = data(t)

    # Check if n is a multiple of keyframe_freq
    if n%keyframe_freq == 0:
        # Set frame like this
        scene.frame_set(n)

        # Set current location like this
        for (i, p) in enumerate(centerline.data.splines.active.bezier_points):
            x,y,z = new_points[i]
            p.co = (x,y,z)
            p.keyframe_insert(data_path="co")
            p.handle_left = (x, y, z)
            p.keyframe_insert(data_path="handle_left")
            p.handle_right = (x, y, z)
            p.keyframe_insert(data_path="handle_right")

# create material
material = bpy.data.materials.new("Material")
centerline.active_material = material
material.use_nodes = True
material.node_tree.links.remove(material.node_tree.links[0])
material.node_tree.nodes.remove(material.node_tree.nodes['Principled BSDF'])

glass_node = material.node_tree.nodes.new("ShaderNodeBsdfGlass")
glass_node.inputs["Color"].default_value = (0.0, 0.8, 1.0, 1.0)
glass_node.inputs["Roughness"].default_value = 0.1
material.node_tree.links.new(material.node_tree.nodes["Material Output"].inputs["Surface"], glass_node.outputs["BSDF"])

# create plane
minx = -0.1
maxx = 1.1
miny = -0.25
maxy = 0.25
minz = -0.25
maxz = 0.25
bpy.ops.mesh.primitive_plane_add(size=30, location=(0.0,0.0,minz), rotation=(0.0,0.0,0.0))
basez1 = bpy.context.active_object
bpy.ops.mesh.primitive_plane_add(size=30, location=(0.0,0.0,15), rotation=(0.0,0.0,0.0))
basez2 = bpy.context.active_object
bpy.ops.mesh.primitive_plane_add(size=30, location=(0.0,-15,0.0), rotation=(-np.pi/2,0.0,0.0))
basey1 = bpy.context.active_object
bpy.ops.mesh.primitive_plane_add(size=30, location=(0.0,15,0.0), rotation=(np.pi/2,0.0,0.0))
basey2 = bpy.context.active_object
bpy.ops.mesh.primitive_plane_add(size=30, location=(-15,0.0,0.0), rotation=(0.0,-np.pi/2,0.0))
basex1 = bpy.context.active_object
bpy.ops.mesh.primitive_plane_add(size=30, location=(15,0.0,0.0), rotation=(0.0,np.pi/2,0.0))
basex2 = bpy.context.active_object

# create material
base_material = bpy.data.materials.new("BaseMaterial")
base_material.use_nodes = True

base_bsdf = base_material.node_tree.nodes["Principled BSDF"]

texture_image = base_material.node_tree.nodes.new('ShaderNodeTexImage')
texture_path = "/Users/jantomec/Downloads/fabric_pattern_05_8k_png/fabric_pattern_05_rough_8k.png"
texture_image.image = bpy.data.images.load(texture_path)
texture_image.texture_mapping.scale = (10,10,10)
base_material.node_tree.links.new(base_bsdf.inputs['Base Color'], texture_image.outputs['Color'])

basez1.active_material = base_material
basez2.active_material = base_material
basey1.active_material = base_material
basey2.active_material = base_material
basex1.active_material = base_material
basex2.active_material = base_material

# add light
# create light datablock, set attributes
light_data = bpy.data.lights.new(name="light_2.80", type='POINT')
light_data.energy = 10000
light_data.cycles.samples = 4

# create new object with our light datablock
light_object = bpy.data.objects.new(name="Light", object_data=light_data)
light_object.location = (7,-10,10)

# link light object
bpy.context.collection.objects.link(light_object)


# add camera
camera_data = bpy.data.cameras.new(name='Camera')
camera_object = bpy.data.objects.new('Camera', camera_data)
bpy.context.scene.collection.objects.link(camera_object)

# Set camera fov in degrees
camera_object.data.angle = 35*np.pi/180.0

# Set camera rotation in euler angles
xc = 1.3
yc = -3.0
zc = 0.75
midpoint = [(minx+maxx)/2, (miny+maxy)/2, (minz+maxz)/2]
camera_object.rotation_mode = 'XZY'
camera_object.rotation_euler[0] = np.pi/2
camera_object.rotation_euler[2] = np.arctan2(xc - midpoint[0], -(yc - midpoint[1]))
camera_object.rotation_euler[0] = np.pi/2 - np.arctan2(zc, np.sqrt((xc - midpoint[0])**2 * (yc-midpoint[1])**2)) + 0.07

# Set camera translation
camera_object.location = (xc, yc, zc)

Trả lời

3 lemon Nov 03 2020 at 18:42

Bạn có thể sửa lỗi đó bằng cách làm mịn một chút các cạnh của hình dạng.

Trong trường hợp đó, để làm điều đó:

Đảo ngược đối tượng Bevel (nếu không, hình dạng cuối cùng có các chuẩn đảo ngược):

#Reversed indices to make the final shape correctly oriented
cross_section_points = 0.5*np.array([
    [-0.1, 0.1],
    [ 0.1, 0.1],
    [ 0.1,-0.1],
    [-0.1,-0.1]
])

Thêm công cụ sửa đổi Bevel vào đối tượng "centerline":

# Bevel modifier
bevel_modifier = centerline.modifiers.new("Bevel", "BEVEL")
bevel_modifier.width = 0.005
bevel_modifier.segments = 3
bevel_modifier.limit_method = 'ANGLE'

Lưu ý: đầu tiên mặc dù đây là tụ quang và điều đó phải là (?). Tuy nhiên, điều này không hoạt động ở đây .