184 lines
6.6 KiB
Python
184 lines
6.6 KiB
Python
import os
|
|
import sys
|
|
|
|
import bpy
|
|
|
|
|
|
def link_object(name, data):
|
|
obj = bpy.data.objects.new(name, data)
|
|
bpy.context.scene.collection.objects.link(obj)
|
|
return obj
|
|
|
|
|
|
def build_curve():
|
|
data = bpy.data.curves.new("WebCurveData", "CURVE")
|
|
data.dimensions = "3D"
|
|
data.resolution_u = 8
|
|
poly = data.splines.new("POLY")
|
|
poly.points.add(3)
|
|
for point, co in zip(poly.points, ((-2.0, 0.0, 0.0, 1.0), (-0.8, 0.7, 0.2, 1.0), (0.6, -0.4, 0.4, 1.0), (2.0, 0.2, 0.0, 1.0))):
|
|
point.co = co
|
|
bezier = data.splines.new("BEZIER")
|
|
bezier.bezier_points.add(2)
|
|
for point, co in zip(bezier.bezier_points, ((-1.5, -1.0, 0.0), (0.0, -1.8, 0.5), (1.5, -1.0, 0.0))):
|
|
point.co = co
|
|
point.handle_left_type = "AUTO"
|
|
point.handle_right_type = "AUTO"
|
|
return link_object("WebCurveObject", data)
|
|
|
|
|
|
def build_surface():
|
|
bpy.ops.surface.primitive_nurbs_surface_surface_add(enter_editmode=False)
|
|
obj = bpy.context.object
|
|
obj.name = "WebSurfaceObject"
|
|
data = obj.data
|
|
data.name = "WebSurfaceData"
|
|
data.resolution_u = 4
|
|
data.resolution_v = 4
|
|
spline = data.splines[0]
|
|
spline.order_u = 4
|
|
spline.order_v = 4
|
|
spline.use_endpoint_u = True
|
|
spline.use_endpoint_v = True
|
|
for index, point in enumerate(spline.points):
|
|
u = index % 4
|
|
v = index // 4
|
|
x = -1.0 + 2.0 * u / 3.0
|
|
y = v / 3.0
|
|
z = 0.35 * (1.0 if u in (1, 2) else 0.0) * (1.0 if v in (1, 2) else 0.0)
|
|
point.co = (x, y, z, 1.0)
|
|
return obj
|
|
|
|
|
|
def build_text():
|
|
data = bpy.data.curves.new("WebFontData", "FONT")
|
|
data.body = "Web Blender"
|
|
data.align_x = "CENTER"
|
|
data.size = 0.7
|
|
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
font_path = os.path.join(root, "blender-5.2.0", "release", "datafiles", "bfont.pfb")
|
|
regular = bpy.data.fonts.load(font_path, check_existing=False)
|
|
alternate = bpy.data.fonts.load(font_path, check_existing=False)
|
|
regular.name = "WebFontRegular"
|
|
alternate.name = "WebFontAlternate"
|
|
data.font = regular
|
|
data.font_bold = alternate
|
|
data.font_italic = regular
|
|
data.font_bold_italic = alternate
|
|
return link_object("WebFontObject", data)
|
|
|
|
|
|
def build_metaball():
|
|
data = bpy.data.metaballs.new("WebMetaballData")
|
|
data.resolution = 0.2
|
|
first = data.elements.new()
|
|
first.co = (-0.65, 0.0, 0.4)
|
|
first.radius = 0.75
|
|
second = data.elements.new()
|
|
second.co = (0.65, 0.0, 0.4)
|
|
second.radius = 0.55
|
|
return link_object("WebMetaballObject", data)
|
|
|
|
|
|
def build_point_cloud():
|
|
mesh = bpy.data.meshes.new("WebPointSeed")
|
|
mesh.from_pydata(((-1.5, 1.4, 0.0), (-0.5, 1.7, 0.2), (0.5, 1.4, 0.0), (1.5, 1.7, 0.2)), [], [])
|
|
obj = link_object("WebPointCloudObject", mesh)
|
|
bpy.ops.object.select_all(action="DESELECT")
|
|
bpy.context.view_layer.objects.active = obj
|
|
obj.select_set(True)
|
|
bpy.ops.object.convert(target="POINTCLOUD")
|
|
obj.data.name = "WebPointCloudData"
|
|
weight = obj.data.attributes.new("web_weight", "FLOAT", "POINT")
|
|
for index, item in enumerate(weight.data):
|
|
item.value = 0.25 + index * 0.25
|
|
radius = obj.data.attributes.get("radius") or obj.data.attributes.new("radius", "FLOAT", "POINT")
|
|
for index, item in enumerate(radius.data):
|
|
item.value = 0.05 + index * 0.01
|
|
return obj
|
|
|
|
|
|
def build_hair():
|
|
surface_mesh = bpy.data.meshes.new("WebHairSurfaceData")
|
|
surface_mesh.from_pydata(((-2.0, 3.0, -0.1), (2.0, 3.0, -0.1), (2.0, 4.0, -0.1), (-2.0, 4.0, -0.1)), (), ((0, 1, 2, 3),))
|
|
surface = link_object("WebHairSurface", surface_mesh)
|
|
surface.hide_viewport = True
|
|
surface.hide_render = True
|
|
legacy = bpy.data.curves.new("WebHairSeed", "CURVE")
|
|
legacy.dimensions = "3D"
|
|
spline = legacy.splines.new("POLY")
|
|
spline.points.add(3)
|
|
for point, co in zip(spline.points, ((-1.2, 3.2, 0.0, 1.0), (-0.5, 3.4, 0.5, 1.0), (0.4, 3.3, 0.8, 1.0), (1.2, 3.5, 1.0, 1.0))):
|
|
point.co = co
|
|
obj = link_object("WebHairObject", legacy)
|
|
bpy.ops.object.select_all(action="DESELECT")
|
|
bpy.context.view_layer.objects.active = obj
|
|
obj.select_set(True)
|
|
bpy.ops.object.convert(target="CURVES")
|
|
if legacy != obj.data:
|
|
bpy.data.curves.remove(legacy, do_unlink=True)
|
|
obj.data.name = "WebHairData"
|
|
obj.data.surface = surface
|
|
radius = obj.data.attributes.get("radius") or obj.data.attributes.new("radius", "FLOAT", "POINT")
|
|
for index, item in enumerate(radius.data):
|
|
item.value = 0.02 + index * 0.004
|
|
density = obj.data.attributes.new("web_density", "FLOAT", "CURVE")
|
|
density.data[0].value = 0.75
|
|
return obj
|
|
|
|
|
|
def build_curves():
|
|
legacy = bpy.data.curves.new("WebCurvesSeed", "CURVE")
|
|
legacy.dimensions = "3D"
|
|
spline = legacy.splines.new("BEZIER")
|
|
spline.bezier_points.add(3)
|
|
for point, co in zip(spline.bezier_points, ((-1.5, 2.5, 0.0), (-0.5, 2.8, 0.3), (0.5, 2.5, 0.0), (1.5, 2.8, 0.3))):
|
|
point.co = co
|
|
point.handle_left_type = "AUTO"
|
|
point.handle_right_type = "AUTO"
|
|
obj = link_object("WebCurvesObject", legacy)
|
|
bpy.ops.object.select_all(action="DESELECT")
|
|
bpy.context.view_layer.objects.active = obj
|
|
obj.select_set(True)
|
|
bpy.ops.object.convert(target="CURVES")
|
|
if legacy != obj.data:
|
|
bpy.data.curves.remove(legacy, do_unlink=True)
|
|
obj.data.name = "WebCurvesData"
|
|
radius = obj.data.attributes.get("radius") or obj.data.attributes.new("radius", "FLOAT", "POINT")
|
|
for index, item in enumerate(radius.data):
|
|
item.value = 0.03 + index * 0.005
|
|
color = obj.data.attributes.new("web_color", "FLOAT_COLOR", "POINT")
|
|
for index, item in enumerate(color.data):
|
|
item.color = (index / 4.0, 0.4, 0.8, 1.0)
|
|
return obj
|
|
|
|
|
|
def build_volume():
|
|
data = bpy.data.volumes.new("WebVolumeData")
|
|
data.filepath = "//missing_web_volume.vdb"
|
|
return link_object("WebVolumeObject", data)
|
|
|
|
|
|
def main(output_path):
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
build_curve()
|
|
build_surface()
|
|
build_text()
|
|
build_metaball()
|
|
build_point_cloud()
|
|
build_curves()
|
|
build_hair()
|
|
bpy.ops.file.pack_all()
|
|
build_volume()
|
|
bpy.context.scene.frame_start = 1
|
|
bpy.context.scene.frame_end = 24
|
|
os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
|
|
bpy.ops.wm.save_as_mainfile(filepath=os.path.abspath(output_path))
|
|
print(f"nonmesh-fixture-generated output={os.path.abspath(output_path)}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if "--" not in sys.argv or len(sys.argv) <= sys.argv.index("--") + 1:
|
|
raise SystemExit("usage: blender -b --python generate-nonmesh-fixture.py -- output.blend")
|
|
main(sys.argv[sys.argv.index("--") + 1])
|