4

I have a complex 3d model and I want to have a 2d model of it's front view.

This is my complex model:

enter image description here

I want to have a 2d model out of it to look like this but with minimum number of vertices, what I did below is that I set the scale of the model in y-axis to 0 but I don't think this is the right way especially that the number of vertices are still the same and still considered as a complex model:

enter image description here

I need it to still have simple faces as I will assign some vertex groups and different materials to each vertex group as shown below: enter image description here enter image description here

Tak
  • 6,293
  • 7
  • 43
  • 85
  • 1
    How come that you don't have Z fighting issue after scaling Y to 0? – cgslav May 02 '17 at 12:59
  • @LukeD sorry, updated the question as the previous gif didn't have y set to 0. Any solution? – Tak May 02 '17 at 13:03
  • Why do you need that as 3D model? If it should be perfectly flat you can go with sprite with transparency to preserve the silhoutte by rendering with orthographic camera. – Mr Zak May 02 '17 at 13:19
  • @MrZak could you provide an answer showing how please? I need it to have simple faces as I will assign some vertex groups and different materials to each vertex group – Tak May 02 '17 at 13:21
  • Considering your last edit, what is the hint in order to guess which part of the geometry is to be simplified? – lemon May 02 '17 at 13:33
  • Your last edit sheds some light on your result as now it's clear you need a 3d model. You could try to go with the answer provided i.e rendering the silhoutte with freestyle, saving as svg, converting to curve and then to mesh. – Mr Zak May 02 '17 at 13:40
  • Related: https://blender.stackexchange.com/q/23661/599, https://blender.stackexchange.com/q/6385/599 and https://blender.stackexchange.com/q/9287/599 – gandalf3 May 03 '17 at 05:36

2 Answers2

7

One way of doing this:

  1. Set up your scene with an orthographic camera facing the model you want to "flatten".
  2. In the User Preferences, under Add-ons, search for svg and enable Render: Freestyle SVG Exporter and Import-Export: Scalable Vector Graphics (SVG) 1.1 format.
  3. Under the Render properties panel, check to enable Freestyle and Freestyle SVG Export, and under Output set the path to somewhere intuitive (I used the desktop).
  4. In the Render Layers panel, under Freestlye Line Set, uncheck the "Edge Types" Sillhouette, Border, and Crease, and check only the edge type External Contour.
  5. Render the image and an SVG will be placed on your desktop. Under File > Import select Scalable Vector Graphics and select the file on your desktop.
  6. At the center of your scene, the flat monkey head is imported as curves. To clean up the imported svg, I took these measures:
    • Select all of the curves and use Ctrl + J to join.
    • Convert to mesh with Alt + C.
    • In Edit Mode, select all vertices and remove doubles.
    • Select all vertices and make an N-gon Face between them with F. (Not a clean solution, but should work for most 2D-object purposes.)
    • In object mode, set geometry to origin with Shift + Ctrl + Alt + C

Now you have a flat model of your mesh, with only the minimal amount of vertices and no extraneous faces or geometry.

CGEffex
  • 950
  • 5
  • 12
5

A simple script to create a "vectorized style" mesh from a flatten mesh:

enter image description here

The principle is in fact simple:

When flattened each edge correspond:

  • either to 2 faces which have the same normal
  • or to 2 faces with opposite normals

So the script keeps only edges of the second case.

... but I'm not sure this corresponds to what is wanted in the question, specially after the last edits of it... ?

import bpy
import bmesh

#Create a new mesh from a geometry 
def CreateMesh( scene, name, location, vertices, edges, polygons ):
    mesh = bpy.data.meshes.new( name )
    obj = bpy.data.objects.new( name, mesh )
    obj.location = location

    scene.objects.link( obj )
    scene.objects.active = obj
    obj.select = True

    mesh.from_pydata( vertices, edges, polygons )
    mesh.update()    

    return obj

#Determinate edges corresponding to opposite faces and make mesh verts/edges from that
def FlatGeometry( obj ):
    bm = bmesh.new()
    bm.from_mesh( obj.data )
    bm.edges.ensure_lookup_table()
    bm.verts.ensure_lookup_table()
    epsilon = 0.000001

    vertices = []
    edges = []
    vertexCount = 0
    mapping = dict()

    try:
        #Iterate on edges and keep only the one corresponding to opposite faces (ie. f1.normal.dot( f2.normal ) < epsilon
        for e in iter( e for e in bm.edges if e.link_faces and (len(e.link_faces) == 1 or e.link_faces[0].normal.dot(  e.link_faces[1].normal ) < epsilon ) ):
            #First vertex of the edge
            v = e.verts[0]
            if v.index not in mapping: #Not stored
                mapping[v.index] = vertexCount #Store it
                vertices.append( v.co.copy() ) #And its coordinates
                vertexCount += 1 #Next index
            v1 = mapping[v.index] #Get the vertex index
            v = e.verts[1]
            #Second vertex for the edge: same principle
            if v.index not in mapping:
                mapping[v.index] = vertexCount
                vertices.append( v.co.copy() )
                vertexCount += 1
            v2 = mapping[v.index]
            #Create the edge
            edges.append( (v1, v2) )

        return vertices, edges
    finally:
        del bm    


print( '------------' )

obj = bpy.context.object

vertices, edges = FlatGeometry( obj )

CreateMesh( bpy.context.scene, "test", (0,0,0), vertices, edges, [] )

Edit: bug corrected

Changed

                vertices.append( v.co )

by

                vertices.append( v.co.copy() )

... vectors in Python are not structs

lemon
  • 60,295
  • 3
  • 66
  • 136