[Blender] Доработаны процедуры ретопологии мешей
This commit is contained in:
parent
45e0d29ea0
commit
6560a4359d
9 changed files with 188 additions and 204 deletions
|
@ -15,6 +15,7 @@ __version__ = "0.2"
|
|||
import time
|
||||
import FreeCAD
|
||||
import logging
|
||||
import math
|
||||
import xml
|
||||
import sys
|
||||
import xml.sax
|
||||
|
@ -24,7 +25,7 @@ import bpy
|
|||
from bpy_extras.node_shader_utils import PrincipledBSDFWrapper
|
||||
from import_fcstd.handler import FreeCAD_xml_handler
|
||||
from import_fcstd.import_hierarchy import import_hierarchy
|
||||
from import_fcstd.materials import set_fem_mat
|
||||
from import_fcstd.import_materials import import_materials
|
||||
from import_fcstd.is_object_solid import is_object_solid
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -32,7 +33,8 @@ logging.basicConfig(level=logging.INFO)
|
|||
|
||||
|
||||
def obj_importer(filename,
|
||||
tessellation,
|
||||
linear_deflection,
|
||||
angular_deflection,
|
||||
update=False,
|
||||
placement=True,
|
||||
skiphidden=True,
|
||||
|
@ -42,8 +44,6 @@ def obj_importer(filename,
|
|||
|
||||
"""Reads a FreeCAD .FCStd file and creates Blender objects"""
|
||||
|
||||
TRIANGULATE = True # set to True to triangulate all faces (will loose multimaterial info)
|
||||
|
||||
guidata = {}
|
||||
zdoc = zipfile.ZipFile(filename)
|
||||
if zdoc:
|
||||
|
@ -78,7 +78,7 @@ def obj_importer(filename,
|
|||
return {'CANCELLED'}
|
||||
|
||||
# import some FreeCAD modules needed below. After "import FreeCAD" these modules become available
|
||||
import Part
|
||||
import Part, Mesh, MeshPart
|
||||
|
||||
def hascurves(shape):
|
||||
|
||||
|
@ -87,8 +87,14 @@ def obj_importer(filename,
|
|||
return True
|
||||
return False
|
||||
|
||||
fcstd_collection = bpy.data.collections.new("FreeCAD import")
|
||||
bpy.context.scene.collection.children.link(fcstd_collection)
|
||||
parts_collection = bpy.data.collections.new("Import Parts")
|
||||
bpy.context.scene.collection.children.link(parts_collection)
|
||||
|
||||
# collect all materials
|
||||
fem_mats = []
|
||||
for fem_mat in doc.Objects:
|
||||
if fem_mat.isDerivedFrom("App::MaterialObjectPython"):
|
||||
fem_mats.append(fem_mat)
|
||||
|
||||
for obj in doc.Objects:
|
||||
# logger.debug("Importing",obj.Label)
|
||||
|
@ -100,6 +106,12 @@ def obj_importer(filename,
|
|||
# TODO add parent visibility check
|
||||
continue
|
||||
|
||||
# process simple parts only
|
||||
if not obj.isDerivedFrom("Part::Feature"):
|
||||
logger.debug('%s is not simple part', obj.Label)
|
||||
continue
|
||||
|
||||
# process solids only
|
||||
if not is_object_solid(obj):
|
||||
logger.debug('%s is not solid', obj.Label)
|
||||
continue
|
||||
|
@ -107,107 +119,25 @@ def obj_importer(filename,
|
|||
verts = []
|
||||
edges = []
|
||||
faces = []
|
||||
matindex = [] # face to material relationship
|
||||
faceedges = [] # a placeholder to store edges that belong to a face
|
||||
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
# !!!
|
||||
# create mesh from shape
|
||||
shape = obj.Shape
|
||||
if placement:
|
||||
# !!!
|
||||
placement = obj.Placement
|
||||
shape = obj.Shape.copy()
|
||||
shape.Placement = placement.inverse().multiply(shape.Placement)
|
||||
if shape.Faces:
|
||||
# !!!
|
||||
if TRIANGULATE:
|
||||
# triangulate and make faces
|
||||
rawdata = shape.tessellate(tessellation)
|
||||
for v in rawdata[0]:
|
||||
verts.append([v.x,v.y,v.z])
|
||||
for f in rawdata[1]:
|
||||
faces.append(f)
|
||||
for face in shape.Faces:
|
||||
for e in face.Edges:
|
||||
faceedges.append(e.hashCode())
|
||||
else:
|
||||
# !!!
|
||||
# write FreeCAD faces as polygons when possible
|
||||
time_start = time.time()
|
||||
for face in shape.Faces:
|
||||
if (len(face.Wires) > 1) or (not isinstance(face.Surface,Part.Plane)) or hascurves(face):
|
||||
# !!!
|
||||
# face has holes or is curved, so we need to triangulate it
|
||||
rawdata = face.tessellate(tessellation)
|
||||
for v in rawdata[0]:
|
||||
vl = [v.x,v.y,v.z]
|
||||
if not vl in verts:
|
||||
verts.append(vl)
|
||||
for f in rawdata[1]:
|
||||
nf = []
|
||||
for vi in f:
|
||||
nv = rawdata[0][vi]
|
||||
nf.append(verts.index([nv.x,nv.y,nv.z]))
|
||||
faces.append(nf)
|
||||
matindex.append(len(rawdata[1]))
|
||||
else:
|
||||
# !!!
|
||||
f = []
|
||||
ov = face.OuterWire.OrderedVertexes
|
||||
for v in ov:
|
||||
vl = [v.X,v.Y,v.Z]
|
||||
if not vl in verts:
|
||||
verts.append(vl)
|
||||
f.append(verts.index(vl))
|
||||
# FreeCAD doesn't care about verts order. Make sure our loop goes clockwise
|
||||
c = face.CenterOfMass
|
||||
v1 = ov[0].Point.sub(c)
|
||||
v2 = ov[1].Point.sub(c)
|
||||
n = face.normalAt(0,0)
|
||||
if (v1.cross(v2)).getAngle(n) > 1.57:
|
||||
f.reverse() # inverting verts order if the direction is couterclockwise
|
||||
faces.append(f)
|
||||
matindex.append(1)
|
||||
for e in face.Edges:
|
||||
faceedges.append(e.hashCode())
|
||||
logger.debug('faces time is %s', (time.time() - time_start))
|
||||
for edge in shape.Edges:
|
||||
# !!!
|
||||
# Treat remaining edges (that are not in faces)
|
||||
if not (edge.hashCode() in faceedges):
|
||||
if hascurves(edge):
|
||||
dv = edge.discretize(9) # TODO use tessellation value
|
||||
for i in range(len(dv)-1):
|
||||
dv1 = [dv[i].x,dv[i].y,dv[i].z]
|
||||
dv2 = [dv[i+1].x,dv[i+1].y,dv[i+1].z]
|
||||
if not dv1 in verts:
|
||||
verts.append(dv1)
|
||||
if not dv2 in verts:
|
||||
verts.append(dv2)
|
||||
edges.append([verts.index(dv1),verts.index(dv2)])
|
||||
else:
|
||||
e = []
|
||||
for vert in edge.Vertexes:
|
||||
# TODO discretize non-linear edges
|
||||
v = [vert.X,vert.Y,vert.Z]
|
||||
if not v in verts:
|
||||
verts.append(v)
|
||||
e.append(verts.index(v))
|
||||
edges.append(e)
|
||||
# create mesh from shape
|
||||
shape = obj.Shape
|
||||
if placement:
|
||||
placement = obj.Placement
|
||||
shape = obj.Shape.copy()
|
||||
shape.Placement = placement.inverse().multiply(shape.Placement)
|
||||
meshfromshape = doc.addObject("Mesh::Feature","Mesh")
|
||||
meshfromshape.Mesh = MeshPart.meshFromShape(
|
||||
Shape=shape,
|
||||
LinearDeflection=linear_deflection,
|
||||
AngularDeflection=math.radians(angular_deflection),
|
||||
Relative=False)
|
||||
|
||||
elif obj.isDerivedFrom("Mesh::Feature"):
|
||||
# convert freecad mesh to blender mesh
|
||||
mesh = obj.Mesh
|
||||
if placement:
|
||||
placement = obj.Placement
|
||||
mesh = obj.Mesh.copy() # in meshes, this zeroes the placement
|
||||
t = mesh.Topology
|
||||
verts = [[v.x,v.y,v.z] for v in t[0]]
|
||||
faces = t[1]
|
||||
t = meshfromshape.Mesh.Topology
|
||||
verts = [[v.x,v.y,v.z] for v in t[0]]
|
||||
faces = t[1]
|
||||
|
||||
if verts and (faces or edges):
|
||||
# !!!
|
||||
if verts and faces:
|
||||
# create or update object with mesh and material data
|
||||
bobj = None
|
||||
bmat = None
|
||||
|
@ -225,7 +155,6 @@ def obj_importer(filename,
|
|||
# update only the mesh of existing object. Don't touch materials
|
||||
bobj.data = bmesh
|
||||
else:
|
||||
# !!!
|
||||
# create new object
|
||||
bobj = bpy.data.objects.new(obj.Label, bmesh)
|
||||
if placement:
|
||||
|
@ -239,17 +168,19 @@ def obj_importer(filename,
|
|||
bobj.rotation_mode = m
|
||||
bobj.scale = (scale, scale, scale)
|
||||
|
||||
if obj.Name in guidata:
|
||||
# !!!
|
||||
# one material for the whole object
|
||||
for fem_mat in doc.Objects:
|
||||
set_fem_mat(obj, bobj, fem_mat)
|
||||
# one material for the whole object
|
||||
for fem_mat in fem_mats:
|
||||
for ref in fem_mat.References:
|
||||
if ref[0].Label == bobj.name:
|
||||
import_materials(bobj, fem_mat)
|
||||
|
||||
parts_collection.objects.link(bobj)
|
||||
|
||||
# construct assembly hierarchy
|
||||
obj_parent = obj.getParentGeoFeatureGroup()
|
||||
if obj_parent:
|
||||
import_hierarchy(obj, bobj, scale)
|
||||
|
||||
fcstd_collection.objects.link(bobj)
|
||||
if select:
|
||||
bpy.context.view_layer.objects.active = bobj
|
||||
bobj.select_set(True)
|
||||
|
|
|
@ -34,6 +34,14 @@ def empty_importer(path_json):
|
|||
fori = tuple(pivot_pose['orientation'].values())
|
||||
bori = (fori[3],)+fori[:3]
|
||||
|
||||
if not bpy.data.collections.get('Import LCS'):
|
||||
lcs_collection = bpy.data.collections.new("Import LCS")
|
||||
bpy.context.scene.collection.children.link(lcs_collection)
|
||||
bpy.context.view_layer.active_layer_collection = \
|
||||
bpy.context.view_layer.layer_collection.children['Import LCS']
|
||||
else:
|
||||
lcs_collection = bpy.data.collections['Import LCS']
|
||||
|
||||
bpy.ops.object.empty_add(
|
||||
type='ARROWS', radius=0.1, align='WORLD',
|
||||
location=(0, 0, 0), rotation=(0, 0, 0))
|
||||
|
@ -43,6 +51,7 @@ def empty_importer(path_json):
|
|||
pivot_obj.location = loc
|
||||
pivot_obj.rotation_quaternion = bori
|
||||
pivot_obj.rotation_mode = 'XYZ'
|
||||
pivot_obj.show_in_front = True
|
||||
|
||||
if pivot_parent_name:
|
||||
pivot_obj.parent = bpy.data.objects[pivot_parent_name]
|
||||
|
|
|
@ -21,10 +21,19 @@ logging.basicConfig(level=logging.INFO)
|
|||
|
||||
def import_hierarchy(fc_obj, b_obj, scale):
|
||||
"""FreeCAD object, Blender object, scene scale"""
|
||||
|
||||
if not bpy.data.collections.get('Import Hierarchy'):
|
||||
hierarchy_collection = bpy.data.collections.new("Import Hierarchy")
|
||||
bpy.context.scene.collection.children.link(hierarchy_collection)
|
||||
bpy.context.view_layer.active_layer_collection = \
|
||||
bpy.context.view_layer.layer_collection.children['Import Hierarchy']
|
||||
else:
|
||||
hierarchy_collection = bpy.data.collections['Import Hierarchy']
|
||||
|
||||
obj_parent = fc_obj.getParentGeoFeatureGroup()
|
||||
obj_child_name = None
|
||||
while obj_parent:
|
||||
if bpy.context.scene.objects.get(obj_parent.Label):
|
||||
if hierarchy_collection.objects.get(obj_parent.Label):
|
||||
empty = bpy.data.objects[obj_parent.Label]
|
||||
else:
|
||||
bpy.ops.object.empty_add(
|
||||
|
@ -40,11 +49,12 @@ def import_hierarchy(fc_obj, b_obj, scale):
|
|||
q = (placement.Rotation.Q[3],)+placement.Rotation.Q[:3]
|
||||
empty.rotation_quaternion = (q)
|
||||
empty.rotation_mode = rm
|
||||
if b_obj.parent:
|
||||
bpy.data.objects[obj_child_name].parent = empty
|
||||
else:
|
||||
if not b_obj.parent:
|
||||
b_obj.parent = empty
|
||||
else:
|
||||
bpy.data.objects[obj_child_name].parent = empty
|
||||
obj_child_name = obj_parent.Label
|
||||
obj_parent = obj_parent.getParentGeoFeatureGroup()
|
||||
empty.select_set(False)
|
||||
logger.debug('Add parent %s to object %s', empty.name, b_obj.name)
|
||||
|
||||
|
|
78
cg/blender/import_fcstd/import_materials.py
Normal file
78
cg/blender/import_fcstd/import_materials.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2023 Ilia Kurochkin <brothermechanic@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
import logging
|
||||
import sys
|
||||
import bpy
|
||||
from bpy_extras.node_shader_utils import PrincipledBSDFWrapper
|
||||
from utils.shininess_to_roughness import shiny_to_rough
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
def import_materials(bobj, fem_mat):
|
||||
""" Build Blender Shader from FreeCAD's FEM material """
|
||||
fem_mat_name = fem_mat.Material['Name']
|
||||
|
||||
if fem_mat_name in bpy.data.materials:
|
||||
if len(bobj.material_slots) < 1:
|
||||
bobj.data.materials.append(bpy.data.materials[fem_mat_name])
|
||||
else:
|
||||
bobj.material_slots[0].material = bpy.data.materials[fem_mat_name]
|
||||
else:
|
||||
if 'DiffuseColor' in fem_mat.Material.keys():
|
||||
d_col_str = fem_mat.Material['DiffuseColor']
|
||||
d_col4 = tuple(
|
||||
map(float, d_col_str[1:-1].split(', ')))
|
||||
d_col = d_col4[:-1]
|
||||
else:
|
||||
d_col = (0.5, 0.5, 0.5)
|
||||
if 'Father' in fem_mat.Material.keys():
|
||||
if fem_mat.Material['Father'] == 'Metal':
|
||||
me = 1
|
||||
else:
|
||||
me = 0
|
||||
else:
|
||||
me = 0
|
||||
if 'Shininess' in fem_mat.Material.keys():
|
||||
shiny = float(fem_mat.Material['Shininess'])
|
||||
if shiny == 0:
|
||||
rg = 0.5
|
||||
else:
|
||||
rg = shiny_to_rough(shiny)
|
||||
else:
|
||||
rg = 0.5
|
||||
if 'EmissiveColor' in fem_mat.Material.keys():
|
||||
e_col_str = fem_mat.Material['EmissiveColor']
|
||||
e_col4 = tuple(
|
||||
map(float, e_col_str[1:-1].split(', ')))
|
||||
e_col = e_col4[:-1]
|
||||
else:
|
||||
e_col = (0.0, 0.0, 0.0)
|
||||
if 'Transparency' in fem_mat.Material.keys():
|
||||
tr_str = fem_mat.Material['Transparency']
|
||||
alpha = 1.0 - float(tr_str)
|
||||
else:
|
||||
alpha = 1.0
|
||||
|
||||
bmat = bpy.data.materials.new(name=fem_mat_name)
|
||||
bmat.use_nodes = True
|
||||
principled = PrincipledBSDFWrapper(bmat, is_readonly=False)
|
||||
principled.base_color = d_col
|
||||
principled.metallic = me
|
||||
principled.roughness = rg
|
||||
principled.emission_color = e_col
|
||||
principled.alpha = alpha
|
||||
bobj.data.materials.append(bmat)
|
||||
|
||||
logger.debug('Assign %s to object %s', fem_mat_name, bobj.name)
|
|
@ -1,78 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2023 Ilia Kurochkin <brothermechanic@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
import logging
|
||||
import sys
|
||||
import bpy
|
||||
from bpy_extras.node_shader_utils import PrincipledBSDFWrapper
|
||||
from utils.shininess_to_roughness import shiny_to_rough
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
def set_fem_mat(obj, bobj, fem_mat):
|
||||
if fem_mat.isDerivedFrom("App::MaterialObjectPython"):
|
||||
if fem_mat.References[0][0].Name == obj.Name:
|
||||
fem_mat_name = fem_mat.Material['Name']
|
||||
if 'DiffuseColor' in fem_mat.Material.keys():
|
||||
d_col_str = fem_mat.Material['DiffuseColor']
|
||||
d_col4 = tuple(
|
||||
map(float, d_col_str[1:-1].split(', ')))
|
||||
d_col = d_col4[:-1]
|
||||
else:
|
||||
d_col = (0.5, 0.5, 0.5)
|
||||
if 'Father' in fem_mat.Material.keys():
|
||||
if fem_mat.Material['Father'] == 'Metal':
|
||||
me = 1
|
||||
else:
|
||||
me = 0
|
||||
else:
|
||||
me = 0
|
||||
if 'Shininess' in fem_mat.Material.keys():
|
||||
shiny = float(fem_mat.Material['Shininess'])
|
||||
if shiny == 0:
|
||||
rg = 0.5
|
||||
else:
|
||||
rg = shiny_to_rough(shiny)
|
||||
else:
|
||||
rg = 0.5
|
||||
if 'EmissiveColor' in fem_mat.Material.keys():
|
||||
e_col_str = fem_mat.Material['EmissiveColor']
|
||||
e_col4 = tuple(
|
||||
map(float, e_col_str[1:-1].split(', ')))
|
||||
e_col = e_col4[:-1]
|
||||
else:
|
||||
e_col = (0.0, 0.0, 0.0)
|
||||
if 'Transparency' in fem_mat.Material.keys():
|
||||
tr_str = fem_mat.Material['Transparency']
|
||||
alpha = 1.0 - float(tr_str)
|
||||
else:
|
||||
alpha = 1.0
|
||||
|
||||
logger.debug('Assign %s to object %s', fem_mat_name, obj.Label)
|
||||
|
||||
if fem_mat_name in bpy.data.materials:
|
||||
if len(bobj.material_slots) < 1:
|
||||
bobj.data.materials.append(bpy.data.materials[fem_mat_name])
|
||||
else:
|
||||
bobj.material_slots[0].material = bpy.data.materials[fem_mat_name]
|
||||
else:
|
||||
bmat = bpy.data.materials.new(name=fem_mat_name)
|
||||
bmat.use_nodes = True
|
||||
principled = PrincipledBSDFWrapper(bmat, is_readonly=False)
|
||||
principled.base_color = d_col
|
||||
principled.metallic = me
|
||||
principled.roughness = rg
|
||||
principled.emission_color = e_col
|
||||
principled.alpha = alpha
|
||||
bobj.data.materials.append(bmat)
|
|
@ -43,7 +43,7 @@ def asset_setup(transforms=True, sharpness=True, shading=True):
|
|||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.mesh.select_mode(type='EDGE')
|
||||
bpy.ops.mesh.edges_select_sharp( sharpness = math.radians(30) )
|
||||
bpy.ops.mesh.edges_select_sharp( sharpness = math.radians(10) )
|
||||
bpy.ops.mesh.mark_sharp()
|
||||
bpy.ops.mesh.select_all(action='SELECT')
|
||||
bpy.ops.uv.smart_project()
|
||||
|
@ -57,9 +57,6 @@ def asset_setup(transforms=True, sharpness=True, shading=True):
|
|||
bpy.context.view_layer.objects.active.modifiers["decimate"].decimate_type = "DISSOLVE"
|
||||
bpy.context.view_layer.objects.active.modifiers["decimate"].angle_limit = 0.00872665
|
||||
bpy.context.object.modifiers["decimate"].show_expanded = 0
|
||||
bpy.context.view_layer.objects.active.modifiers.new(type='WEIGHTED_NORMAL', name='weightednormal')
|
||||
bpy.context.view_layer.objects.active.modifiers["weightednormal"].keep_sharp = 1
|
||||
bpy.context.object.modifiers["weightednormal"].show_expanded = 0
|
||||
bpy.context.view_layer.objects.active.modifiers.new(type='TRIANGULATE', name='triangulate')
|
||||
bpy.context.object.modifiers["triangulate"].keep_custom_normals = 1
|
||||
bpy.context.object.modifiers["triangulate"].show_expanded = 0
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
; Robossembler_ABS-Dark-Rough
|
||||
; (c) 2023 brothermechanic (CC-BY 3.0)
|
||||
|
||||
[General]
|
||||
Name = Robossembler_ABS-Dark-Rough
|
||||
Description = Generic ABS material for Robossembler project's pipeline.
|
||||
Father = Thermoplast
|
||||
|
||||
[Mechanical]
|
||||
Density = 1060 kg/m^3
|
||||
PoissonRatio = 0.37
|
||||
UltimateTensileStrength = 38.8 MPa
|
||||
YieldStrength = 44.1 MPa
|
||||
YoungsModulus = 2300 MPa
|
||||
|
||||
[Thermal]
|
||||
SpecificHeat = 2050 J/kg/K
|
||||
ThermalConductivity = 0.158 W/m/K
|
||||
ThermalExpansionCoefficient = 0.000093 m/m/K
|
||||
|
||||
[Rendering]
|
||||
DiffuseColor = (0.1, 0.1, 0.1, 1.0)
|
||||
EmissiveColor = (0.0, 0.0, 0.0, 1.0)
|
||||
Shininess = 35
|
||||
TexturePath = ~/texture.jpg
|
||||
Transparency = 0.0
|
||||
|
||||
[VectorRendering]
|
||||
ViewColor = (0.0, 0.0, 1.0, 1.0)
|
||||
|
||||
[UserDefined]
|
||||
usernum = 0.0
|
||||
userstr = String
|
|
@ -1,8 +1,8 @@
|
|||
; Robossembler_ABS-Grey-Rough
|
||||
; Robossembler_ABS-White-Rough
|
||||
; (c) 2023 brothermechanic (CC-BY 3.0)
|
||||
|
||||
[General]
|
||||
Name = Robossembler_ABS-Grey-Rough
|
||||
Name = Robossembler_ABS-White-Rough
|
||||
Description = Generic ABS material for Robossembler project's pipeline.
|
||||
Father = Thermoplast
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@ logging.basicConfig(level=logging.INFO)
|
|||
|
||||
|
||||
def freecad_asset_pipeline(fcstd_path,
|
||||
tessellation,
|
||||
linear_deflection,
|
||||
angular_deflection,
|
||||
mesh_export_path=None,
|
||||
json_path=None,
|
||||
blend_path=None,
|
||||
|
@ -38,7 +39,7 @@ def freecad_asset_pipeline(fcstd_path,
|
|||
cleanup_orphan_data()
|
||||
|
||||
# import objects
|
||||
obj_importer(fcstd_path, tessellation)
|
||||
obj_importer(fcstd_path, linear_deflection, angular_deflection)
|
||||
|
||||
# import lcs
|
||||
if json_path is None:
|
||||
|
@ -80,7 +81,9 @@ if __name__ == '__main__':
|
|||
parser.add_argument(
|
||||
'--fcstd_path', type=str, help='Path to source FreeCAD scene', required=True)
|
||||
parser.add_argument(
|
||||
'--tessellation', type=int, help='Tessellation number', default=10, required=False)
|
||||
'--linear_deflection', type=float, help='Max linear distance error', default=0.1, required=False)
|
||||
parser.add_argument(
|
||||
'--angular_deflection', type=float, help='Max angular distance error', default=20.0, required=False)
|
||||
parser.add_argument(
|
||||
'--mesh_export_path', type=str, help='Path for export meshes', required=False)
|
||||
parser.add_argument(
|
||||
|
@ -92,7 +95,8 @@ if __name__ == '__main__':
|
|||
args = parser.parse_args()
|
||||
|
||||
freecad_asset_pipeline(args.fcstd_path,
|
||||
args.tessellation,
|
||||
args.linear_deflection,
|
||||
args.angular_deflection,
|
||||
args.mesh_export_path,
|
||||
args.json_path,
|
||||
args.blend_path,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue