Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
recherche:residence_polygones:mesh2svg2paper [2025/11/09 16:54]
emoc [Utilisation de Simplify]
recherche:residence_polygones:mesh2svg2paper [2025/11/11 16:31] (Version actuelle)
emoc [Utiliser vpype]
Ligne 26: Ligne 26:
   * Geomview object file format (.off),   * Geomview object file format (.off),
   * VRML 2.0 - export only (.wrl).   * VRML 2.0 - export only (.wrl).
 +Exemple :
 +  ctmconv parasect.obj parasect.stl
 +
 +===== Infos sur un objet 3D en ligne de commande =====
 +
 +Nombre de points, de faces, etc.
 +
 +Avec **assimp-utils**
 +  sudo apt install assimp-utils
 +  assimp info teapot.obj
 +  ​
 +Assimp pour Open Asset Import Library
 +  * https://​github.com/​assimp/​assimp
 +  * https://​the-asset-importer-lib-documentation.readthedocs.io/​en/​latest/​
 +===== Affichage d'​objets STL =====
 +
 +Avec GMSH : https://​gmsh.info/​ qui est aussi capable d'une multitude d'​autres choses (en GUI ou CLI)
 +
 +{{:​recherche:​residence_polygones:​gmsh.png?​direct&​600|}}
 +
  
 ===== Installation de Go ===== ===== Installation de Go =====
Ligne 220: Ligne 240:
  
 **TODO : permettre la rotation de la vue** **TODO : permettre la rotation de la vue**
 +
 +===== rendu wireframe avec blender CLI + gif =====
 +
 +{{:​recherche:​residence_polygones:​teapot_wire.gif?​direct|}}
 +
 +Script python blender à utiliser en ligne de commande avec 
 +  blender --background --python blender_teapot_wireframe_views.py
 +
 +<​accordion>​
 +<panel title="​blender_teapot_wireframe_views.py (cliquer pour afficher le code)">​
 +<code python blender_teapot_wireframe_views.py>​
 +# Blender 3.4.1 
 +# Debian 12 @ tenko
 +#​ 20251109,​ résidence polygones @ Fablab des portes logiques
 +
 +import bpy
 +import math
 +
 +# -------------------------------
 +# Rendu wireframe "​propre"​ 600x600
 +# -------------------------------
 +
 +# Supprimer tous les objets existants
 +bpy.ops.wm.read_factory_settings(use_empty=True)
 +
 +# Importer le STL
 +bpy.ops.import_mesh.stl(filepath="​teapot.stl"​)
 +obj = bpy.context.selected_objects[0]
 +
 +# Supprimer tous les matériaux existants
 +obj.data.materials.clear()
 +
 +# Ajouter un modifier wireframe
 +mod = obj.modifiers.new(name="​WireframeMod",​ type='​WIREFRAME'​)
 +mod.thickness = 0.02  # épaisseur des lignes
 +
 +# Créer un matériau noir shadeless pour le wireframe
 +mat = bpy.data.materials.new(name="​WireMat"​)
 +mat.diffuse_color = (0, 0, 0, 1)
 +mat.use_nodes = True
 +bsdf = mat.node_tree.nodes.get("​Principled BSDF")
 +bsdf.inputs['​Base Color'​].default_value = (0, 0, 0, 1)
 +bsdf.inputs['​Specular'​].default_value = 0
 +bsdf.inputs['​Roughness'​].default_value = 1
 +obj.data.materials.append(mat)
 +
 +# Ajouter une caméra
 +cam_data = bpy.data.cameras.new(name="​Camera"​)
 +cam_object = bpy.data.objects.new("​Camera",​ cam_data)
 +bpy.context.collection.objects.link(cam_object)
 +bpy.context.scene.camera = cam_object
 +
 +# Paramètres de rendu
 +scene = bpy.context.scene
 +scene.render.image_settings.file_format = '​PNG'​
 +scene.render.resolution_x = 600
 +scene.render.resolution_y = 600
 +scene.render.film_transparent = False  # fond blanc
 +# scene.render.film_transparent_glass = False
 +
 +# Désactiver l’anti-aliasing
 +# scene.render.use_antialiasing = False
 +scene.render.engine = '​BLENDER_EEVEE' ​ # moteur Eevee plus simple
 +# Eevee anti-aliasing quasi désactivé
 +scene.eevee.taa_render_samples = 1
 +
 +# Récupérer la scène
 +scene = bpy.context.scene
 +
 +# Créer un monde si nécessaire
 +if scene.world is None:
 +    world = bpy.data.worlds.new("​World"​)
 +    scene.world = world
 +
 +# Couleur de fond blanc
 +scene.world.use_nodes = True
 +bg = scene.world.node_tree.nodes['​Background'​]
 +bg.inputs['​Color'​].default_value = (1, 1, 1, 1)  # blanc
 +
 +# Centrer la caméra autour de l'​objet
 +center = obj.location
 +
 +# Paramètres rotation
 +n_views = 30
 +radius = 10   # distance caméra
 +elevation = 5
 +
 +for i in range(n_views):​
 +    angle = 2 * math.pi * i / n_views
 +    cam_object.location.x = center.x + radius * math.cos(angle)
 +    cam_object.location.y = center.y + radius * math.sin(angle)
 +    cam_object.location.z = center.z + elevation
 +    ​
 +    # Orienter la caméra vers le centre
 +    direction = center - cam_object.location
 +    rot_quat = direction.to_track_quat('​-Z',​ '​Y'​)
 +    cam_object.rotation_euler = rot_quat.to_euler()
 +    ​
 +    # Nom du fichier
 +    scene.render.filepath = f"​teapot_wire_{i:​02d}.png"​
 +    ​
 +    # Rendu
 +    bpy.ops.render.render(write_still=True)
 +</​code>​
 +</​panel>​
 +</​accordion>​
 +
 +Ensuite on peut assembler les images avec 
 +  convert teapot_wire_*.png -threshold 50% -colors 2 -resize 600x600 teapot_wire.gif
 +
 +{{:​recherche:​residence_polygones:​teapot_facewire.gif?​direct|}}
 +  ​
 +Version alternative qui affiche également les faces (et masque les faces cachées)
 +  blender --background --python blender_teapot_facewire.py ​                                      # calculer les rendus d'​image
 +  convert teapot_facewire_*.png -threshold 50% -colors 2 -resize 300x300 teapot_facewire.gif ​    # préparer l'​animation
 +
 +<​accordion>​
 +<panel title="​blender_teapot_facewire.py (cliquer pour afficher le code)">​
 +<code python blender_teapot_facewire.py>​
 +# Blender 3.4.1 
 +# Debian 12 @ tenko
 +# 20251109, résidence polygones @ Fablab des portes logiques
 +
 +# En ligne 65 on peut choisir : fond transparent ou fond monochrome (changement de couleur en ligne 77)
 +
 +import bpy
 +import math
 +
 +# -------------------------------
 +# Configuration de la scène
 +# -------------------------------
 +
 +# Supprimer tous les objets existants
 +bpy.ops.wm.read_factory_settings(use_empty=True)
 +
 +# Importer le STL
 +bpy.ops.import_mesh.stl(filepath="​teapot.stl"​)
 +obj = bpy.context.selected_objects[0]
 +
 +# Supprimer tous les matériaux existants
 +obj.data.materials.clear()
 +
 +# -------------------------------
 +# Matériau blanc pour les faces
 +# -------------------------------
 +mat = bpy.data.materials.new("​FaceWhite"​)
 +mat.use_nodes = True
 +bsdf = mat.node_tree.nodes["​Principled BSDF"]
 +bsdf.inputs['​Base Color'​].default_value = (1, 1, 1, 1)  # blanc
 +bsdf.inputs['​Specular'​].default_value = 0
 +obj.data.materials.append(mat)
 +
 +# -------------------------------
 +# Matériau Wireframe noir
 +# -------------------------------
 +# Ajouter un modifier wireframe
 +mod = obj.modifiers.new(name="​WireframeMod",​ type='​WIREFRAME'​)
 +mod.thickness = 0.02
 +mod.use_replace = False  # conserve faces originales
 +
 +# Création d’un second matériau pour le wireframe
 +wire_mat = bpy.data.materials.new("​WireBlack"​)
 +wire_mat.use_nodes = True
 +nodes = wire_mat.node_tree.nodes
 +bsdf_wire = nodes.get("​Principled BSDF")
 +bsdf_wire.inputs['​Base Color'​].default_value = (0, 0, 0, 1)  # noir
 +bsdf_wire.inputs['​Specular'​].default_value = 0
 +obj.data.materials.append(wire_mat)
 +
 +# Associer le modifier wireframe au matériau noir
 +mod.material_offset = 1  # utilise le second matériau
 +
 +# -------------------------------
 +# Caméra
 +# -------------------------------
 +cam_data = bpy.data.cameras.new(name="​Camera"​)
 +cam_object = bpy.data.objects.new("​Camera",​ cam_data)
 +bpy.context.collection.objects.link(cam_object)
 +bpy.context.scene.camera = cam_object
 +
 +# Paramètres de rendu
 +scene = bpy.context.scene
 +scene.render.image_settings.file_format = '​PNG'​
 +scene.render.resolution_x = 600
 +scene.render.resolution_y = 600
 +scene.render.film_transparent = True  # False : fond blanc, True : fond transparent
 +scene.render.engine = '​BLENDER_EEVEE'​
 +scene.eevee.taa_render_samples = 1  # anti-aliasing minimal
 +
 +# Fond blanc
 +if scene.world is None:
 +    world = bpy.data.worlds.new("​World"​)
 +    scene.world = world
 +scene.world.use_nodes = True
 +bg = scene.world.node_tree.nodes['​Background'​]
 +bg.inputs['​Color'​].default_value = (1, 1, 1, 1)  # blanc
 +
 +# -------------------------------
 +# Paramètres rotation
 +# -------------------------------
 +center = obj.location
 +n_views = 30
 +radius = 10
 +elevation = 5
 +
 +# -------------------------------
 +# Générer les images
 +# -------------------------------
 +for i in range(n_views):​
 +    angle = 2 * math.pi * i / n_views
 +    cam_object.location.x = center.x + radius * math.cos(angle)
 +    cam_object.location.y = center.y + radius * math.sin(angle)
 +    cam_object.location.z = center.z + elevation
 +    ​
 +    # Orienter la caméra vers le centre de l'​objet
 +    direction = center - cam_object.location
 +    rot_quat = direction.to_track_quat('​-Z',​ '​Y'​)
 +    cam_object.rotation_euler = rot_quat.to_euler()
 +    ​
 +    # Nom du fichier
 +    scene.render.filepath = f"​teapot_facewire_{i:​02d}.png"​
 +    ​
 +    # Rendu
 +    bpy.ops.render.render(write_still=True)
 +</​code>​
 +</​panel>​
 +</​accordion>​
 +===== Blender Export Paper Model =====
 +
 +Un add-on pour Blender permet de «déplier» un objet 3D : [[recherche:​residence_polygones:​blender_export_paper_model|Export Paper Model]]
 +
 +
 +===== Utiliser vpype =====
 +
 +Sur Linux Debian 12, en suivant les indications de https://​vpype.readthedocs.io/​en/​latest/​install.html#​linux
 +
 +  sudo apt-get install pipx
 +  pipx ensurepath
 +  pipx install "​vpype[all]"​
 +  vpype --version ​            # vpype 1.15.0
 +  vpype random show           # ooooooooooooooooooh !
 +
 +J'​ajoute **deduplicate**,​ plugin vpype pour enlever les lignes en doublon dans un fichier svg https://​github.com/​LoicGoulefert/​deduplicate
 +  pipx inject vpype deduplicate
 +  vpype --help ​                  # pour confirmer que l'​installation s'est bien passée : deduplicate apparaît dans la partie Plugins
 +Ainsi que **occult**, plugin vpype pour masquer les faces cachées d'un fichier svg https://​github.com/​LoicGoulefert/​occult
 +  pipx inject vpype vpype-occult
 +  vpype --help ​                  # pour confirmer que l'​installation s'est bien passée : occult apparaît dans la partie Plugins
 +
 +Exemple d'​utilisation
 +  ~/​go/​bin/​simplify -f 0.5 teapot.stl teapot-0.5.stl ​                            # simplification de l'​objet 3D
 +  ctmconv teapot-0.5.stl teapot-0.5.obj ​                                         # conversion au format OBJ
 +  ~/​go/​bin/​obj2svg teapot-0.5.obj ​                                               # création de 2 fichiers PNG et SVG
 +   vpype read teapot-0.5.obj.svg deduplicate write teapot-0.5.obj_dedup.svg ​  # déduplication des arêtes en double dans le fichier SVG
 +
 +
  
  
Ligne 226: Ligne 502:
 **removeduplicatelines** : une extension inkscape qui enlève les segments dupliqués : https://​cutlings.datafil.no/​inkscape-extension-removeduplicatelines/​ \\ **removeduplicatelines** : une extension inkscape qui enlève les segments dupliqués : https://​cutlings.datafil.no/​inkscape-extension-removeduplicatelines/​ \\
  
-**deduplicate** plugin vpype pour enlever les lignes en doublon dans un fichier svg https://​github.com/​LoicGoulefert/​deduplicate 
  
-**occult** plugin vpype pour masquer les faces cachées d'un fichier svg https://​github.com/​LoicGoulefert/​occult 
  
 **vpype** «vpype is an extensible CLI pipeline utility which aims to be the Swiss Army knife for creating, modifying and/or optimizing plotter-ready vector graphics» https://​vpype.readthedocs.io/​en/​latest/​install.html#​linux **vpype** «vpype is an extensible CLI pipeline utility which aims to be the Swiss Army knife for creating, modifying and/or optimizing plotter-ready vector graphics» https://​vpype.readthedocs.io/​en/​latest/​install.html#​linux
  • recherche/residence_polygones/mesh2svg2paper.1762703646.txt.gz
  • Dernière modification: 2025/11/09 16:54
  • par emoc