Files
workinf_Blender_Wasm/tools/web/generate-nonmesh-fixture.py
2026-08-12 04:47:48 -04:00

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])