Esempio n. 1
0
def deduplicate_trimesh_vertices(trimesh):
    """
    Accepts a `TriMesh` and returns a new `TriMesh` with duplicate vertices removed
    """
    def do_vert_hash(vert):
        return hash(str(set(vert)))

    new_verts = []
    new_faces = []

    seen_verts = {}
    for face in trimesh.faces:
        face_points = [trimesh.vs[i] for i in face]
        new_face = []
        for vert in face_points:
            vert_hash = do_vert_hash(vert)
            if vert_hash in seen_verts:
                index = seen_verts[vert_hash]
            else:
                new_verts.append(vert)
                index = len(new_verts) - 1
                seen_verts[vert_hash] = index

            new_face.append(index)
        new_faces.append(new_face)

    new_trimesh = TriMesh()
    new_trimesh.vs = np.array(new_verts)
    new_trimesh.faces = np.array(new_faces)
    return new_trimesh
Esempio n. 2
0
    def importFile(self, filename, invertfaces=False):
        """Import an OFF file.

        If invertfaces is True the orientation of each face is reversed.
        """

        self.invertfaces = invertfaces

        self.texcoord_flag = False
        self.color_flag = False
        self.normal_flag = False
        self.four_flag = False
        self.ndim_flag = False
        self.ndim = 3
        self.is_trimesh = True

        self.fhandle = file(filename)

        # Read the header
        z = self.readLine()
        self.parseHeaderKeyWord(z)

        # nOFF?
        if self.ndim_flag:
            # Read the dimension of vertices
            z = self.readLine()
            self.ndim = int(z)
            if self.ndim>3:
                raise ValueError("A vertex space dimension of %d is not supported"%(self.ndim))

        # Read the number of vertices and faces...
        z = self.readLine().split(" ")
        self.numverts = int(z[0])
        self.numfaces = int(z[1])

        # Start with a TriMeshGeom
        # (this will be later converted into a PolyhedronGeom if faces
        # with more than 3 vertices are encountered)
        self.geom = TriMeshGeom()
        self.geom.verts.resize(self.numverts)
        self.geom.faces.resize(self.numfaces)

        # Read the vertices...
        self.readVertices()

        # Read the faces...
        self.readFaces()

        self.fhandle.close()

        # Create the actual object...
        nodename = os.path.basename(filename)
        nodename = os.path.splitext(nodename)[0]
        nodename = nodename.replace(" ","_")
        if self.is_trimesh:
            n = TriMesh(name=nodename)
        else:
            n = Polyhedron(name=nodename)
        n.geom = self.geom
Esempio n. 3
0
    def importFile(self, filename):
        """Import an IFS file."""

        f = file(filename, "rb")

        # Check the header...
        s = self.readString(f)
        if s!="IFS":
            raise ValueError('The file "%s" is is not a IFS file.'%filename)

        # Read (and ignore) the version number
        s = f.read(4)
        ver = struct.unpack("<f", s)[0]

        # Read the model name
        modelname = self.readString(f)

        # Create the mesh geom
        tm = TriMeshGeom()

        # Read vertices...
        s = self.readString(f)
        if s!="VERTICES":
            raise ValueError("Vertices chunk expected, got '%s' instead."%s)

        s = f.read(4)
        numverts = int(struct.unpack("<I", s)[0])
        tm.verts.resize(numverts)

        for i in range(numverts):
            s = f.read(12)
            x,y,z = struct.unpack("<fff", s)
            tm.verts[i] = vec3(x,y,z)

        # Read faces...
        s = self.readString(f)
        if s!="TRIANGLES":
            raise ValueError("Triangle chunk expected, got '%s' instead."%s)
            
        s = f.read(4)
        numfaces = int(struct.unpack("<I", s)[0])
        tm.faces.resize(numfaces)

        for i in range(numfaces):
            s = f.read(12)
            a,b,c = struct.unpack("<III", s)
            tm.faces[i] = (int(a), int(b), int(c))

        # Create a world object
        obj = TriMesh(name=modelname)
        obj.geom = tm
Esempio n. 4
0
    def importFile(self, filename):
        """Import an IFS file."""

        f = file(filename, "rb")

        # Check the header...
        s = self.readString(f)
        if s != "IFS":
            raise ValueError('The file "%s" is is not a IFS file.' % filename)

        # Read (and ignore) the version number
        s = f.read(4)
        ver = struct.unpack("<f", s)[0]

        # Read the model name
        modelname = self.readString(f)

        # Create the mesh geom
        tm = TriMeshGeom()

        # Read vertices...
        s = self.readString(f)
        if s != "VERTICES":
            raise ValueError("Vertices chunk expected, got '%s' instead." % s)

        s = f.read(4)
        numverts = int(struct.unpack("<I", s)[0])
        tm.verts.resize(numverts)

        for i in range(numverts):
            s = f.read(12)
            x, y, z = struct.unpack("<fff", s)
            tm.verts[i] = vec3(x, y, z)

        # Read faces...
        s = self.readString(f)
        if s != "TRIANGLES":
            raise ValueError("Triangle chunk expected, got '%s' instead." % s)

        s = f.read(4)
        numfaces = int(struct.unpack("<I", s)[0])
        tm.faces.resize(numfaces)

        for i in range(numfaces):
            s = f.read(12)
            a, b, c = struct.unpack("<III", s)
            tm.faces[i] = (int(a), int(b), int(c))

        # Create a world object
        obj = TriMesh(name=modelname)
        obj.geom = tm
Esempio n. 5
0
def check_gradient(args):
    """
    Compare the exact gradient to the result of
    the finite differences algorithm `optimize.approx_fprime`

    This is for debugging the gradient
    """
    trimesh = TriMesh.FromOBJ_FileName(args.in_obj)

    trimesh = util.deduplicate_trimesh_vertices(trimesh)

    NUM_VERTS = len(trimesh.vs)

    energy_function = energy_lookup[args.energy]

    energy_only = lambda x: energy_function(
        x, trimesh, gradient_mode=0, NUM_VERTS=NUM_VERTS)
    grad_only = lambda x: energy_function(
        x, trimesh, gradient_mode=1, NUM_VERTS=NUM_VERTS)

    # the first guess at the solution is the object itself
    first_guess = trimesh.vs.reshape(NUM_VERTS * 3)

    approximate_gradient = \
        optimize.approx_fprime(first_guess, energy_only, [0.01])

    extact_gradient = grad_only(first_guess)

    print "The difference between exact and numerical grad is: {}".format(
        norm(approximate_gradient - extact_gradient))
Esempio n. 6
0
    def __init__(self, **kwargs):
        GLUTWindow.__init__(self)

        kwargs.setdefault('background_color', (.3, .3, .3))
        kwargs.setdefault('mesh', TriMesh())
        kwargs.setdefault('linestrips', [])
        kwargs.setdefault('points', [])
        kwargs.setdefault('camera', Camera())
        kwargs.setdefault('draw_faces', True)
        kwargs.setdefault('draw_edges', True)
        kwargs.setdefault('draw_linestrips', True)
        kwargs.setdefault('draw_points', True)

        self.background_color = kwargs['background_color']
        self.mesh = kwargs['mesh']
        self.linestrips = kwargs['linestrips']
        self.points = kwargs['points']
        self.camera = kwargs['camera']
        self.draw_faces = kwargs['draw_faces']
        self.draw_edges = kwargs['draw_edges']
        self.draw_linestrips = kwargs['draw_linestrips']
        self.draw_points = kwargs['draw_points']

        ## I don't want dynamic binding here because
        ## subclasses' constructors haven't run yet
        TriMeshWindow.reset(self)
Esempio n. 7
0
    def asTriMesh( self ):
        if 0 in self.data.shape:
            raise Warning('empty image')

        from trimesh import TriMesh
        grid = TriMesh.grid( self.data.shape[1] - 1, self.data.shape[2] - 1 )
        return grid
Esempio n. 8
0
def main():
    if len(sys.argv) != 2:
        print >> sys.stderr, 'Usage:', sys.argv[0], 'mesh.obj'
        sys.exit(-1)

    mesh_path = sys.argv[1]
    pid = view_mesh(TriMesh.FromOBJ_FileName(mesh_path), mesh_path)
    print 'Background process id:', pid
Esempio n. 9
0
def grid2trimesh( grid, four_eight = False, mask = None ):
    vs, faces, uvs = grid2vertices_and_faces_and_uvs( grid, four_eight = four_eight )
    
    from trimesh import TriMesh
    
    mesh = TriMesh()
    mesh.vs = vs
    mesh.faces = faces
    if uvs is not None:
        assert len( uvs ) == len( vs )
        mesh.uvs = uvs
    
    if mask is not None:
        mask = asarray( mask, dtype = bool )
        assert mask.shape == grid.shape
        
        #'''
        print( 'Removing masked vertices...' )
        remove_vs_indices = [ vi for vi in xrange(len( mesh.vs )) if not mask[ mask.shape[0] - 1 - mesh.vs[vi][1], mesh.vs[vi][0] ] ]
        #print( 'remove_vs_indices:' )
        #print( remove_vs_indices )
        mesh.remove_vertex_indices( remove_vs_indices )
        print( 'Finished removing masked vertices.' )
        '''
        ## Alternative
        def vi_in_mask( vi ): return mask[ mask.shape[0] - 1 - mesh.vs[vi][1], mesh.vs[vi][0] ]
        print( 'Removing faces between masked and unmasked vertices...' )
        remove_face_indices = [ fi for fi in xrange(len( mesh.faces )) if len(set([ vi_in_mask( vi ) for vi in mesh.faces[fi]])) != 1 ]
        #print( 'remove_face_indices:' )
        #print( remove_face_indices )
        mesh.remove_face_indices( remove_face_indices )
        print( 'Finished removing faces between masked and unmasked vertices.' )
        #'''
    
    return mesh
Esempio n. 10
0
 def buildmesh( self, levels ):
     '''builds a list of triangle meshs starting with an icosadehron
     this base mesh is subdivided into many levels
     each lower level has 4 times as many faces
     subdivided points are normalized to lie on the surface of the sphere'''
     lpyramid = [TriMesh.icosa()]
     for i in xrange(0, levels):
         lnext = lpyramid[i].subdivide()
         lnext.normalizepoints()
         lpyramid.append(lnext)
         
     self.mesh = lpyramid[-1]
     self.mesh.name = 'sphere'
Esempio n. 11
0
    def importFile(self, filename, flags=GEOM_INIT_ALL, parent=None):
        """Import a 3DS file."""

        self.filename = filename
        self.ddds = _core.File3ds()
        self.ddds.load(filename)
#        f = self.ddds.current_frame
        f = getScene().timer().frame
        if f<self.ddds.segment_from:
            f = self.ddds.segment_from
        if f>self.ddds.segment_to:
            f = self.ddds.segment_to
        self.ddds.eval(f)

        # Create a dictionary containing all available meshes.
        # Key is the mesh name. This is used to check if all meshes have
        # been processed (i.e. if there were corresponding nodes).
        self.meshes = {}
        m = self.ddds.meshes()
        while m!=None:
            if self.meshes.has_key(m.name):
                print "Warning: Duplicate mesh names in 3ds file"
            self.meshes[m.name] = m
            m = m.next()

        # Create objects...
        self.materials = {}
        self.createObject(self.ddds.nodes(), parent=parent, flags=flags)
        del self.materials

        # Create TriMeshes for all left over meshes...
        for n in self.meshes:
            mesh = self.meshes[n]
            tm = TriMeshGeom()
            mesh.initGeom(tm, flags)
            worldobj = TriMesh(name = mesh.name, parent=parent)
            worldobj.geom = tm

        self.ddds.free()
Esempio n. 12
0
    def importFile(self, filename, flags=GEOM_INIT_ALL, parent=None):
        """Import a 3DS file."""

        self.filename = filename
        self.ddds = _core.File3ds()
        self.ddds.load(filename)
        #        f = self.ddds.current_frame
        f = getScene().timer().frame
        if f < self.ddds.segment_from:
            f = self.ddds.segment_from
        if f > self.ddds.segment_to:
            f = self.ddds.segment_to
        self.ddds.eval(f)

        # Create a dictionary containing all available meshes.
        # Key is the mesh name. This is used to check if all meshes have
        # been processed (i.e. if there were corresponding nodes).
        self.meshes = {}
        m = self.ddds.meshes()
        while m != None:
            if m.name in self.meshes:
                print("Warning: Duplicate mesh names in 3ds file")
            self.meshes[m.name] = m
            m = m.next()

        # Create objects...
        self.materials = {}
        self.createObject(self.ddds.nodes(), parent=parent, flags=flags)
        del self.materials

        # Create TriMeshes for all left over meshes...
        for n in self.meshes:
            mesh = self.meshes[n]
            tm = TriMeshGeom()
            mesh.initGeom(tm, flags)
            worldobj = TriMesh(name=mesh.name, parent=parent)
            worldobj.geom = tm

        self.ddds.free()
Esempio n. 13
0
def optimize_energy(args):
    print "loading {}".format(args.in_obj)
    trimesh = TriMesh.FromOBJ_FileName(args.in_obj)

    energy_function = energy_lookup[args.energy]

    # a lot of meshes have duplicate vertices associated
    # with adjacent faces, clean that up.
    trimesh = util.deduplicate_trimesh_vertices(trimesh)

    NUM_VERTS = len(trimesh.vs)

    # curry different versions of the energy function and the starting mesh
    # these are now functions of a single variable that can be optimized
    energy_only = lambda x: energy_function(
        x, trimesh, gradient_mode=0, NUM_VERTS=NUM_VERTS)
    energy_and_grad = lambda x: energy_function(
        x, trimesh, gradient_mode=2, NUM_VERTS=NUM_VERTS)

    # the first guess at the solution is the object itself
    first_guess = trimesh.vs.reshape(NUM_VERTS * 3)

    print "starting optimization for mesh with {} verts".format(NUM_VERTS)
    result = \
        optimize.minimize(
            fun=energy_and_grad if args.exact_grad else energy_only,
            x0=first_guess,
            options={'disp': True},
            method="L-BFGS-B",
            constraints=None,
            jac=args.exact_grad)

    final_mesh_verts = result.x.reshape(NUM_VERTS, 3)

    trimesh.vs = final_mesh_verts
    print "writing: {}".format(args.out_obj)
    trimesh.write_OBJ(args.out_obj)
Esempio n. 14
0
def grid2trimesh(grid, four_eight=False, mask=None):
    vs, faces, uvs = grid2vertices_and_faces_and_uvs(grid,
                                                     four_eight=four_eight)

    from trimesh import TriMesh

    mesh = TriMesh()
    mesh.vs = vs
    mesh.faces = faces
    if uvs is not None:
        assert len(uvs) == len(vs)
        mesh.uvs = uvs

    if mask is not None:
        mask = asarray(mask, dtype=bool)
        assert mask.shape == grid.shape

        #'''
        print('Removing masked vertices...')
        remove_vs_indices = [
            vi for vi in xrange(len(mesh.vs))
            if not mask[mask.shape[0] - 1 - mesh.vs[vi][1], mesh.vs[vi][0]]
        ]
        #print( 'remove_vs_indices:' )
        #print( remove_vs_indices )
        mesh.remove_vertex_indices(remove_vs_indices)
        print('Finished removing masked vertices.')
        '''
        ## Alternative
        def vi_in_mask( vi ): return mask[ mask.shape[0] - 1 - mesh.vs[vi][1], mesh.vs[vi][0] ]
        print( 'Removing faces between masked and unmasked vertices...' )
        remove_face_indices = [ fi for fi in xrange(len( mesh.faces )) if len(set([ vi_in_mask( vi ) for vi in mesh.faces[fi]])) != 1 ]
        #print( 'remove_face_indices:' )
        #print( remove_face_indices )
        mesh.remove_face_indices( remove_face_indices )
        print( 'Finished removing faces between masked and unmasked vertices.' )
        #'''

    return mesh
Esempio n. 15
0
    def createObject(self, node, parent=None, flags=GEOM_INIT_ALL):
        """
        \param node (\c Lib3dsNode) Current node
        \param parent (\c WorldObject) Parent object or None
        \param flags (\c int) Flags for mesh creation

        \todo worldtransform als Slot
        \todo Pivot so setzen wie in 3DS
        """
        if node==None:
            return

        worldobj = None
        auto_insert = True
        if parent!=None:
            auto_insert = False

        # Object?
        if node.type==TYPE_OBJECT:
            if node.name!="$$$DUMMY" and node.name!="_Quader01":
                data = node.object_data
                mesh = self.ddds.meshByName(node.name)
                if self.meshes.has_key(mesh.name):
                    del self.meshes[mesh.name]
#                print "###",node.name,"###"
#                print "Node matrix:"
#                print node.matrix
#                print "Pivot:",data.pivot
#                print "Mesh matrix:"
#                print mesh.matrix
                tm = TriMeshGeom()
                mesh.initGeom(tm, flags)

                if parent==None:
                    PT = mat4().translation(-data.pivot)
                    m = node.matrix*PT*mesh.matrix.inverse()
                else:
                    PT = mat4().translation(-data.pivot)
                    m = node.matrix*PT*mesh.matrix.inverse()
                    # worldtransform von Parent bestimmen...
                    pworldtransform = parent.worldtransform
#                    pworldtransform = parent.localTransform()
#                    p = parent.parent
#                    while p!=None:
#                        pworldtransform = p.localTransform()*pworldtransform
#                        p = p.parent
                    m = pworldtransform.inverse()*m
                worldobj = TriMesh(name=node.name,
#                                   pivot=data.pivot,
                                   transform=m,
                                   auto_insert=auto_insert)
                worldobj.geom = tm

                # Set the materials
                matnames = mesh.materialNames()
                worldobj.setNumMaterials(len(matnames))
                for i in range(len(matnames)):
                    if matnames[i]=="":
                        material = GLMaterial()  
                    # Was the material already instantiated?
                    elif matnames[i] in self.materials:
                        material = self.materials[matnames[i]]
                    else:
                        mat = self.ddds.materialByName(matnames[i])
#                        print "Material:",matnames[i]
#                        print "  self_illum:",mat.self_illum
#                        print "  self_ilpct:",mat.self_ilpct
                        material = Material3DS(name = matnames[i],
                                               ambient = mat.ambient,
                                               diffuse = mat.diffuse,
                                               specular = mat.specular,
                                               shininess = mat.shininess,
                                               shin_strength = mat.shin_strength,
                                               use_blur = mat.use_blur,
                                               transparency = mat.transparency,
                                               falloff = mat.falloff,
                                               additive = mat.additive,
                                               use_falloff = mat.use_falloff,
                                               self_illum = mat.self_illum,
                                               self_ilpct = getattr(mat, "self_ilpct", 0),
                                               shading = mat.shading,
                                               soften = mat.soften,
                                               face_map = mat.face_map,
                                               two_sided = mat.two_sided,
                                               map_decal = mat.map_decal,
                                               use_wire = mat.use_wire,
                                               use_wire_abs = mat.use_wire_abs,
                                               wire_size = mat.wire_size,
                                               texture1_map = self._createTexMap(mat.texture1_map),
                                               texture2_map = self._createTexMap(mat.texture2_map),
                                               opacity_map = self._createTexMap(mat.opacity_map),
                                               bump_map = self._createTexMap(mat.bump_map),
                                               specular_map = self._createTexMap(mat.specular_map),
                                               shininess_map = self._createTexMap(mat.shininess_map),
                                               self_illum_map = self._createTexMap(mat.self_illum_map),
                                               reflection_map = self._createTexMap(mat.reflection_map)
                                               )
                        self.materials[matnames[i]] = material
                    worldobj.setMaterial(material, i)
                
        # Camera?
        elif node.type==TYPE_CAMERA:
            cam = self.ddds.cameraByName(node.name)
#            print "Camera:",node.name
#            print "  Roll:",cam.roll
#            print node.matrix
            # Convert the FOV from horizontal to vertical direction
            # (Todo: What aspect ratio to use?)
            fov = degrees(atan(480/640.0*tan(radians(cam.fov/2.0))))*2.0
            worldobj = TargetCamera(name = node.name,
                                    pos = cam.position,
                                    target = cam.target,
                                    fov = fov,
                                    auto_insert = auto_insert)
        # Light?
        elif node.type==TYPE_LIGHT:
            lgt = self.ddds.lightByName(node.name)
            worldobj = self._createLight(node, lgt, auto_insert)

        if worldobj!=None and parent!=None:
            parent.addChild(worldobj)

        if worldobj!=None:
            self.createObject(node.childs(), worldobj, flags=flags)
        else:
            self.createObject(node.childs(), parent, flags=flags)
        self.createObject(node.next(), parent, flags=flags)
Esempio n. 16
0
    def testmulti( solver_kind = SeamSolver.kplane): #kfree ): #kzup ):
        '''computes frustum/mesh intersection and other stuff
        build a pyramid, build frustums and find seams'''
        levels       = 5
        nfrustums    = 25
        frustumscale = .4
        squishscale  = .1
        seed         = seedarg()

        solver = SeamSolver( levels, solver_kind )
    
        meshlist = [solver.mesh]

        squish = numpy.identity(4)

        if solver_kind == SeamSolver.kplane:
            squishvec = num.randunitpt( seed )
            squish = num.vecspace( squishvec  )
            meshlist.append( vecmesh( squishvec, 'squish' ) )
        if solver_kind in (SeamSolver.kzup, SeamSolver.kplane):
            squish[2, :] *= squishscale

        frustums = randfrustums( nfrustums, 
                                 frustumscale,
                                 solver, 
                                 squish,
                                 seed )

        solver.markfrustums(frustums)

        solver.mesh.uvzeros()
        solver.mesh.uvs[:, 0] = 1-solver.vertweight
        solver.mesh.uvs[:, 1] = solver.vertvis

        seams = solver.run()

        if seams:
            dummy, vis, f = seams[0]
            
            polevec = num.pointmatrixmult( num.Z, f.ctw )
            meshlist.append( vecmesh( polevec[0], 'pole' ) )

            seamslice = TriMesh.cube()
            seamslice.points[:, 0] *= .5
            seamslice.points[:, 0] -= .5
            seamslice.points[:, 0] *= 1.1
            seamslice.points[:, 1] *= solver.mesh.edgestats()[-1]
            seamslice.points[:, 1] *= solver.slicetolerance_halfwidth
            seamslice.points[:, 2] *= 1.1

            seamslice.xform( f.ctw )
            seamslice.name = 'seam'
            meshlist.append( seamslice )

            flat = solver.mesh.copy().polar(f)
            flat.name = 'unwrap'
            meshlist.append( flat )

            solver.mesh.uvs[vis] = 1, 1 
        else:
            print('no seams found')
Esempio n. 17
0
 def end(self, name):
     faces = []
     for i in range(self.numfaces):
         faces.append(range(i * 3, i * 3 + 3))
     TriMesh(name=name, verts=self.verts, faces=faces)
Esempio n. 18
0
    def createObject(self, node, parent=None, flags=GEOM_INIT_ALL):
        """
        \param node (\c Lib3dsNode) Current node
        \param parent (\c WorldObject) Parent object or None
        \param flags (\c int) Flags for mesh creation

        \todo worldtransform als Slot
        \todo Pivot so setzen wie in 3DS
        """
        if node == None:
            return

        worldobj = None
        auto_insert = True
        if parent != None:
            auto_insert = False

        # Object?
        if node.type == TYPE_OBJECT:
            if node.name != "$$$DUMMY" and node.name != "_Quader01":
                data = node.object_data
                mesh = self.ddds.meshByName(node.name)
                if mesh.name in self.meshes:
                    del self.meshes[mesh.name]
                #                print "###",node.name,"###"
                #                print "Node matrix:"
                #                print node.matrix
                #                print "Pivot:",data.pivot
                #                print "Mesh matrix:"
                #                print mesh.matrix
                tm = TriMeshGeom()
                mesh.initGeom(tm, flags)

                if parent == None:
                    PT = mat4().translation(-data.pivot)
                    m = node.matrix * PT * mesh.matrix.inverse()
                else:
                    PT = mat4().translation(-data.pivot)
                    m = node.matrix * PT * mesh.matrix.inverse()
                    # worldtransform von Parent bestimmen...
                    pworldtransform = parent.worldtransform
                    #                    pworldtransform = parent.localTransform()
                    #                    p = parent.parent
                    #                    while p!=None:
                    #                        pworldtransform = p.localTransform()*pworldtransform
                    #                        p = p.parent
                    m = pworldtransform.inverse() * m
                worldobj = TriMesh(
                    name=node.name,
                    #                                   pivot=data.pivot,
                    transform=m,
                    auto_insert=auto_insert,
                )
                worldobj.geom = tm

                # Set the materials
                matnames = mesh.materialNames()
                worldobj.setNumMaterials(len(matnames))
                for i in range(len(matnames)):
                    if matnames[i] == "":
                        material = GLMaterial()
                    # Was the material already instantiated?
                    elif matnames[i] in self.materials:
                        material = self.materials[matnames[i]]
                    else:
                        mat = self.ddds.materialByName(matnames[i])
                        #                        print "Material:",matnames[i]
                        #                        print "  self_illum:",mat.self_illum
                        #                        print "  self_ilpct:",mat.self_ilpct
                        material = Material3DS(
                            name=matnames[i],
                            ambient=mat.ambient,
                            diffuse=mat.diffuse,
                            specular=mat.specular,
                            shininess=mat.shininess,
                            shin_strength=mat.shin_strength,
                            use_blur=mat.use_blur,
                            transparency=mat.transparency,
                            falloff=mat.falloff,
                            additive=mat.additive,
                            use_falloff=mat.use_falloff,
                            self_illum=mat.self_illum,
                            self_ilpct=getattr(mat, "self_ilpct", 0),
                            shading=mat.shading,
                            soften=mat.soften,
                            face_map=mat.face_map,
                            two_sided=mat.two_sided,
                            map_decal=mat.map_decal,
                            use_wire=mat.use_wire,
                            use_wire_abs=mat.use_wire_abs,
                            wire_size=mat.wire_size,
                            texture1_map=self._createTexMap(mat.texture1_map),
                            texture2_map=self._createTexMap(mat.texture2_map),
                            opacity_map=self._createTexMap(mat.opacity_map),
                            bump_map=self._createTexMap(mat.bump_map),
                            specular_map=self._createTexMap(mat.specular_map),
                            shininess_map=self._createTexMap(mat.shininess_map),
                            self_illum_map=self._createTexMap(mat.self_illum_map),
                            reflection_map=self._createTexMap(mat.reflection_map),
                        )
                        self.materials[matnames[i]] = material
                    worldobj.setMaterial(material, i)

        # Camera?
        elif node.type == TYPE_CAMERA:
            cam = self.ddds.cameraByName(node.name)
            #            print "Camera:",node.name
            #            print "  Roll:",cam.roll
            #            print node.matrix
            # Convert the FOV from horizontal to vertical direction
            # (Todo: What aspect ratio to use?)
            fov = degrees(atan(480 / 640.0 * tan(radians(cam.fov / 2.0)))) * 2.0
            worldobj = TargetCamera(
                name=node.name, pos=cam.position, target=cam.target, fov=fov, auto_insert=auto_insert
            )
        # Light?
        elif node.type == TYPE_LIGHT:
            lgt = self.ddds.lightByName(node.name)
            worldobj = self._createLight(node, lgt, auto_insert)

        if worldobj != None and parent != None:
            parent.addChild(worldobj)

        if worldobj != None:
            self.createObject(node.childs(), worldobj, flags=flags)
        else:
            self.createObject(node.childs(), parent, flags=flags)
        self.createObject(node.next(), parent, flags=flags)
Esempio n. 19
0

    import time 
    start_time=time.clock()

    images=np.asfarray(Image.open(input_image_path).convert('RGB')).reshape((-1,3))
    hull=ConvexHull(images)
    origin_hull=hull
    # visualize_hull(hull)
    write_convexhull_into_obj_file(hull, output_rawhull_obj_file)




    N=500
    mesh=TriMesh.FromOBJ_FileName(output_rawhull_obj_file)
    print ('original vertices number:',len(mesh.vs))


    for i in range(N):

        print ('loop:', i)
        
        old_num=len(mesh.vs)
        mesh=TriMesh.FromOBJ_FileName(output_rawhull_obj_file)
        mesh=remove_one_edge_by_finding_smallest_adding_volume_with_test_conditions(mesh,option=2)
        newhull=ConvexHull(mesh.vs)
        write_convexhull_into_obj_file(newhull, output_rawhull_obj_file)

        print ('current vertices number:', len(mesh.vs))
Esempio n. 20
0
    def createTriMesh(self, parent=None, name=None):
        """Create a triangle mesh from the current set of faces.

        This method may only be called if the faces really have only
        3 vertices.

        Returns the TriMesh object.
        """

        # Build lookup tables (so that only the verts that are really
        # required are stored in the TriMesh)
        #
        # Key: Original vertex index - Value: New vertex index
        vert_lut = {}
        has_normals = True
        has_tverts = True
        iv = 0
        for f in self.faces:
            for v,tv,n in f:
                if v not in vert_lut:
                    vert_lut[v] = iv
                    iv+=1
                if tv==None:
                    has_tverts = False
                if n==None:
                    has_normals = False

        numfaces = len(self.faces)
        numverts = len(vert_lut)

        tm = TriMeshGeom()
        tm.verts.resize(numverts)
        tm.faces.resize(numfaces)

        # Set vertices
        for v in vert_lut:
            newidx = vert_lut[v]
            tm.verts[newidx] = self.verts[v]

        # Set faces
        idx = 0
        for i,f in enumerate(self.faces):
            fi = []
            for v,tv,n in f:
                fi.append(vert_lut[v])
            tm.faces[i] = fi

        # Create variable N for storing the normals
        if has_normals:
            tm.newVariable("N", FACEVARYING, NORMAL)
            N = tm.slot("N")
            idx = 0
            for f in self.faces:
                for v,tv,n in f:
                    N[idx] = self.normals[n]
                    idx += 1

        # Set texture vertices
        if has_tverts:
            tm.newVariable("st", FACEVARYING, FLOAT, 2)
            st = tm.slot("st")
            idx = 0
            for f in self.faces:
                for v,tv,n in f:
                    st[idx] = self.tverts[tv]
                    idx += 1

        obj = TriMesh(name=name, parent=parent)
        obj.geom = tm
        # Set the materials
        self.initMaterial(obj)
        return obj
def compute_color(input_im, N):

    ######***********************************************************************************************

    #### 3D case: use method in paper: "Progressive Hulls for Intersection Applications"
    #### also using trimesh.py interface from yotam gingold

    def visualize_hull(hull, groundtruth_hull=None):
        from matplotlib import pyplot as plt

        fig = plt.figure(figsize=(8, 8))
        ax = fig.add_subplot(1, 1, 1, projection='3d')
        vertex = hull.points[hull.vertices]
        ax.scatter(vertex[:, 0],
                   vertex[:, 1],
                   vertex[:, 2],
                   marker='*',
                   color='red',
                   s=40,
                   label='class')

        #     num=hull.simplices.shape[0]
        #     points=[]
        #     normals=[]
        #     for i in range(num):
        #         face=hull.points[hull.simplices[i]]
        #         avg_point=(face[0]+face[1]+face[2])/3.0
        #         points.append(avg_point)
        #     points=np.asarray(points)

        #     ax.quiver(points[:,0],points[:,1],points[:,2],hull.equations[:,0],hull.equations[:,1],hull.equations[:,2],length=0.01)

        for simplex in hull.simplices:
            faces = hull.points[simplex]
            xs = list(faces[:, 0])
            xs.append(faces[0, 0])
            ys = list(faces[:, 1])
            ys.append(faces[0, 1])
            zs = list(faces[:, 2])
            zs.append(faces[0, 2])
            #         print xs,ys,zs
            plt.plot(xs, ys, zs, 'k-')

        if groundtruth_hull != None:
            groundtruth_vertex = groundtruth_hull.points[
                groundtruth_hull.vertices]
            ax.scatter(groundtruth_vertex[:, 0],
                       groundtruth_vertex[:, 1],
                       groundtruth_vertex[:, 2],
                       marker='o',
                       color='green',
                       s=80,
                       label='class')

        plt.title("3D Scatter Plot")
        plt.show()

    from trimesh import TriMesh

    def write_convexhull_into_obj_file(hull, output_rawhull_obj_file):
        hvertices = hull.points[hull.vertices]
        points_index = -1 * np.ones(hull.points.shape[0], dtype=int)
        points_index[hull.vertices] = np.arange(len(hull.vertices))
        #### start from index 1 in obj files!!!!!
        hfaces = np.array([points_index[hface]
                           for hface in hull.simplices]) + 1

        #### to make sure each faces's points are countclockwise order.
        for index in range(len(hfaces)):
            face = hvertices[hfaces[index] - 1]
            normals = hull.equations[index, :3]
            p0 = face[0]
            p1 = face[1]
            p2 = face[2]

            n = np.cross(p1 - p0, p2 - p0)
            if np.dot(normals, n) < 0:
                hfaces[index][[1, 0]] = hfaces[index][[0, 1]]

        myfile = open(output_rawhull_obj_file, 'w')
        for index in range(hvertices.shape[0]):
            myfile.write('v ' + str(hvertices[index][0]) + ' ' +
                         str(hvertices[index][1]) + ' ' +
                         str(hvertices[index][2]) + '\n')
        for index in range(hfaces.shape[0]):
            myfile.write('f ' + str(hfaces[index][0]) + ' ' +
                         str(hfaces[index][1]) + ' ' + str(hfaces[index][2]) +
                         '\n')
        myfile.close()

    def edge_normal_test(vertices, faces, old_face_index_list, v0_ind, v1_ind):
        selected_old_face_list = []
        central_two_face_list = []

        for index in old_face_index_list:
            face = faces[index]
            face_temp = np.array(face).copy()
            face_temp = list(face_temp)

            if v0_ind in face_temp:
                face_temp.remove(v0_ind)
            if v1_ind in face_temp:
                face_temp.remove(v1_ind)
            if len(
                    face_temp
            ) == 2:  ### if left 2 points, then this face is what we need.
                selected_old_face = [
                    np.asarray(vertices[face[i]]) for i in range(len(face))
                ]
                selected_old_face_list.append(np.asarray(selected_old_face))
            if len(
                    face_temp
            ) == 1:  ##### if left 1 points, then this face is central face.
                central_two_face = [
                    np.asarray(vertices[face[i]]) for i in range(len(face))
                ]
                central_two_face_list.append(np.asarray(central_two_face))

        assert (len(central_two_face_list) == 2)
        if len(central_two_face_list) + len(selected_old_face_list) != len(
                old_face_index_list):
            print 'error!!!!!!'

        central_two_face_normal_list = []
        neighbor_face_dot_normal_list = []

        for face in central_two_face_list:
            n = np.cross(face[1] - face[0], face[2] - face[0])
            n = n / np.sqrt(np.dot(n, n))
            central_two_face_normal_list.append(n)

        avg_edge_normal = np.average(np.array(central_two_face_normal_list),
                                     axis=0)

        for face in selected_old_face_list:
            n = np.cross(face[1] - face[0], face[2] - face[0])
            neighbor_face_dot_normal_list.append(np.dot(avg_edge_normal, n))

        if (np.array(neighbor_face_dot_normal_list) >= 0.0 - 1e-5).all():
            return 1
        else:
            return 0

    def compute_tetrahedron_volume(face, point):
        n = np.cross(face[1] - face[0], face[2] - face[0])
        return abs(np.dot(n, point - face[0])) / 6.0

    #### this is different from function: remove_one_edge_by_finding_smallest_adding_volume(mesh)
    #### add some test conditions to accept new vertex.
    #### if option ==1, return a new convexhull.
    #### if option ==2, return a new mesh (using trimesh.py)
    def remove_one_edge_by_finding_smallest_adding_volume_with_test_conditions(
            mesh, option):

        edges = mesh.get_edges()
        mesh.get_halfedges()
        faces = mesh.faces
        vertices = mesh.vs

        temp_list1 = []
        temp_list2 = []
        count = 0

        for edge_index in range(len(edges)):

            edge = edges[edge_index]
            vertex1 = edge[0]
            vertex2 = edge[1]
            face_index1 = mesh.vertex_face_neighbors(vertex1)
            face_index2 = mesh.vertex_face_neighbors(vertex2)

            face_index = list(set(face_index1) | set(face_index2))
            related_faces = [faces[index] for index in face_index]
            old_face_list = []

            #### now find a point, so that for each face in related_faces will create a positive volume tetrahedron using this point.
            ### minimize c*x. w.r.t. A*x<=b
            c = np.zeros(3)
            A = []
            b = []

            for index in range(len(related_faces)):
                face = related_faces[index]
                p0 = vertices[face[0]]
                p1 = vertices[face[1]]
                p2 = vertices[face[2]]
                old_face_list.append(np.asarray([p0, p1, p2]))

                n = np.cross(p1 - p0, p2 - p0)

                #### Currently use this line. without this line, test_fourcolors results are not good.
                n = n / np.sqrt(
                    np.dot(n, n)
                )  ##### use normalized face normals means distance, not volume

                A.append(n)
                b.append(np.dot(n, p0))
                c += n

    ########### now use cvxopt.solvers.lp solver

            A = -np.asfarray(A)
            b = -np.asfarray(b)

            c = np.asfarray(c)
            cvxopt.solvers.options['show_progress'] = False
            #cvxopt.solvers.options['glpk'] = dict(msg_lev='GLP_MSG_OFF')

            #res = cvxopt.solvers.lp( cvxopt.matrix(c), cvxopt.matrix(A), cvxopt.matrix(b), solver='glpk' ) # After installing another version of lapacke.h, this one is goofed now!!!
            res = cvxopt.solvers.lp(cvxopt.matrix(c), cvxopt.matrix(A),
                                    cvxopt.matrix(b))

            #res = linprog(-1*c, A_ub=A, b_ub=-1*b, method = 'simplex',options={'disp':False})

            if res['status'] == 'optimal':

                newpoint = np.asfarray(res['x']).squeeze()

                ######## using objective function to calculate (volume) or (distance to face) as priority.
                #             volume=res['primal objective']+b.sum()

                ####### manually compute volume as priority,so no relation with objective function
                tetra_volume_list = []
                for each_face in old_face_list:
                    tetra_volume_list.append(
                        compute_tetrahedron_volume(each_face, newpoint))
                volume = np.asarray(tetra_volume_list).sum()

                temp_list1.append((count, volume, vertex1, vertex2))
                temp_list2.append(newpoint)
                count += 1

            # else:
            #     print 'cvxopt.solvers.lp is not optimal ', res['status'], np.asfarray( res['x'] ).squeeze()
            #     if res['status']!='unknown': ### means solver failed
            #         ##### check our test to see if the solver fails normally
            #         if edge_normal_test(vertices,faces,face_index,vertex1,vertex2)==1: ### means all normal dot value are positive
            #             print '!!!edge_normal_neighbor_normal_dotvalue all positive, but solver fails'

        if option == 1:
            if len(temp_list1) == 0:
                print 'all fails'
                hull = ConvexHull(mesh.vs)
            else:
                min_tuple = min(temp_list1, key=lambda x: x[1])
                # print min_tuple
                final_index = min_tuple[0]
                final_point = temp_list2[final_index]
                # print 'final_point ', final_point
                new_total_points = mesh.vs
                new_total_points.append(final_point)

                hull = ConvexHull(np.array(new_total_points))
            return hull

        if option == 2:

            if len(temp_list1) == 0:
                print 'all fails'
            else:
                min_tuple = min(temp_list1, key=lambda x: x[1])
                # print min_tuple
                final_index = min_tuple[0]
                final_point = temp_list2[final_index]
                # print 'final_point ', final_point

                v1_ind = min_tuple[2]
                v2_ind = min_tuple[3]

                face_index1 = mesh.vertex_face_neighbors(v1_ind)
                face_index2 = mesh.vertex_face_neighbors(v2_ind)

                face_index = list(set(face_index1) | set(face_index2))
                related_faces_vertex_ind = [
                    faces[index] for index in face_index
                ]

                old2new = mesh.remove_vertex_indices([v1_ind, v2_ind])

                ### give the index to new vertex.
                new_vertex_index = current_vertices_num = len(
                    old2new[old2new != -1])

                ### create new face with new vertex index.
                new_faces_vertex_ind = []

                for face in related_faces_vertex_ind:
                    new_face = [
                        new_vertex_index
                        if x == v1_ind or x == v2_ind else old2new[x]
                        for x in face
                    ]
                    if len(list(set(new_face))) == len(new_face):
                        new_faces_vertex_ind.append(new_face)

                ##### do not clip coordinates to[0,255]. when simplification done, clip.
                mesh.vs.append(final_point)

                ##### clip coordinates during simplification!
                # mesh.vs.append(final_point.clip(0.0,255.0))

                for face in new_faces_vertex_ind:
                    mesh.faces.append(face)
                mesh.topology_changed()

            return mesh

# ************ compute ************

    output_rawhull_obj_file = 'misc_param/temp' + "-rawconvexhull.obj"
    E_vertice_num = 4

    import time
    start_time = time.clock()

    #images=np.asfarray(Image.open(input_image_path).convert('RGB')).reshape((-1,3))
    all_colors = input_im.reshape((-1, 3))

    ## insert a white and black pixel to make sure we got one [somtimes max-project does not have dark pixels]
    #all_colors[1,:] = np.asarray([0,0,0])
    #all_colors[0,:] = np.asarray([191,191,191]) # white pixels are uninformative

    #hull=ConvexHull(images)
    hull = ConvexHull(all_colors)
    origin_hull = hull
    write_convexhull_into_obj_file(hull, output_rawhull_obj_file)

    mesh = TriMesh.FromOBJ_FileName(output_rawhull_obj_file)
    print '- Original hull vertices number:', len(mesh.vs)

    for i in range(500):
        old_num = len(mesh.vs)
        mesh = TriMesh.FromOBJ_FileName(output_rawhull_obj_file)

        #print len(mesh.vs)
        mesh = remove_one_edge_by_finding_smallest_adding_volume_with_test_conditions(
            mesh, option=2)
        newhull = ConvexHull(mesh.vs)
        write_convexhull_into_obj_file(newhull, output_rawhull_obj_file)

        pigments_colors = newhull.points[newhull.vertices].clip(
            0, 255).round().astype(np.uint8)
        pigments_colors = pigments_colors.reshape(
            (pigments_colors.shape[0], 1, pigments_colors.shape[1]))
        #print pigments_colors.shape

        # add white to make sure (Not optimal, Heuristic)
        pigments_colors = np.vstack(
            (pigments_colors, np.asarray([191, 191, 191]).reshape(1, 1, 3)))

        white_index = []
        black_index = []
        #del_color = []

        for i in range(pigments_colors.shape[0]):
            if pigments_colors[i, 0, 0] > 190.0 and pigments_colors[
                    i, 0, 1] > 190.0 and pigments_colors[i, 0, 2] > 190.0:
                #print '- White color detected and deleted' # dont wanna keep whie, not informative
                white_index.append(i)

            if pigments_colors[i, 0, 0] < 15.0 and pigments_colors[
                    i, 0, 1] < 15.0 and pigments_colors[i, 0, 2] < 15.0:
                black_index.append(i)

        #assert len(black_index) > 0
        #assert len(white_index) < 2	# more than 1 white
        #if len(white_index) == 0: print '- No white pixels found, you got one extra layer, decrease number of colors (N)!'
        #print len(white_index)

        # make sure blck is the first color
        #print black_index, pigments_colors.shape
        #temp2 = pigments_colors[black_index,:]
        #pigments_colors[black_index,:] = pigments_colors[0,:]
        #pigments_colors[0,:] = temp2
        #if 0 in set(white_index):
        #		white_index[0] = black_index[0]

        # erase gray and white
        pigments_colors = np.delete(pigments_colors,
                                    white_index + black_index,
                                    axis=0)

        # insert [0, 0, 0] (Not optimal, Heuristic solution)
        pigments_colors = np.vstack(
            (np.asarray([0, 0, 0]).reshape(1, 1, 3), pigments_colors))

        #print len(newhull.vertices)
        if pigments_colors.shape[
                0] == N + 1:  # colors + black bakground + possible white
            #print 'FFFFF: '
            #print pigments_colors
            color_vertices = np.asfarray(
                pigments_colors.reshape(pigments_colors.shape[0], 3))
            break

        #if len(mesh.vs)==old_num or len(mesh.vs)<=E_vertice_num:
        #print '- Final vertices number', len(mesh.vs)
        #break

    #color_vertices =  np.asfarray(pigments_colors.reshape(pigments_colors.shape[0],3))

    newhull = ConvexHull(mesh.vs)
    write_convexhull_into_obj_file(newhull, output_rawhull_obj_file)

    end_time = time.clock()
    print 'time: ', end_time - start_time

    print '- Computed color vertices from the image:'
    print color_vertices
    print color_vertices.shape
    return color_vertices
Esempio n. 22
0
    def createTriMesh(self, parent=None, name=None):
        """Create a triangle mesh from the current set of faces.

        This method may only be called if the faces really have only
        3 vertices.

        Returns the TriMesh object.
        """

        # Build lookup tables (so that only the verts that are really
        # required are stored in the TriMesh)
        #
        # Key: Original vertex index - Value: New vertex index
        vert_lut = {}
        has_normals = True
        has_tverts = True
        iv = 0
        for f in self.faces:
            for v, tv, n in f:
                if v not in vert_lut:
                    vert_lut[v] = iv
                    iv += 1
                if tv == None:
                    has_tverts = False
                if n == None:
                    has_normals = False

        numfaces = len(self.faces)
        numverts = len(vert_lut)

        tm = TriMeshGeom()
        tm.verts.resize(numverts)
        tm.faces.resize(numfaces)

        # Set vertices
        for v in vert_lut:
            newidx = vert_lut[v]
            tm.verts[newidx] = self.verts[v]

        # Set faces
        idx = 0
        for i, f in enumerate(self.faces):
            fi = []
            for v, tv, n in f:
                fi.append(vert_lut[v])
            tm.faces[i] = fi

        # Create variable N for storing the normals
        if has_normals:
            tm.newVariable("N", FACEVARYING, NORMAL)
            N = tm.slot("N")
            idx = 0
            for f in self.faces:
                for v, tv, n in f:
                    N[idx] = self.normals[n]
                    idx += 1

        # Set texture vertices
        if has_tverts:
            tm.newVariable("st", FACEVARYING, FLOAT, 2)
            st = tm.slot("st")
            idx = 0
            for f in self.faces:
                for v, tv, n in f:
                    st[idx] = self.tverts[tv]
                    idx += 1

        obj = TriMesh(name=name, parent=parent)
        obj.geom = tm
        # Set the materials
        self.initMaterial(obj)
        return obj
Esempio n. 23
0
    def importFile(self, filename, invertfaces=False):
        """Import an OFF file.

        If invertfaces is True the orientation of each face is reversed.
        """

        self.invertfaces = invertfaces

        self.texcoord_flag = False
        self.color_flag = False
        self.normal_flag = False
        self.four_flag = False
        self.ndim_flag = False
        self.ndim = 3
        self.is_trimesh = True

        self.fhandle = file(filename)

        # Read the header
        z = self.readLine()
        self.parseHeaderKeyWord(z)

        # nOFF?
        if self.ndim_flag:
            # Read the dimension of vertices
            z = self.readLine()
            self.ndim = int(z)
            if self.ndim > 3:
                raise ValueError(
                    "A vertex space dimension of %d is not supported" %
                    (self.ndim))

        # Read the number of vertices and faces...
        z = self.readLine().split(" ")
        self.numverts = int(z[0])
        self.numfaces = int(z[1])

        # Start with a TriMeshGeom
        # (this will be later converted into a PolyhedronGeom if faces
        # with more than 3 vertices are encountered)
        self.geom = TriMeshGeom()
        self.geom.verts.resize(self.numverts)
        self.geom.faces.resize(self.numfaces)

        # Read the vertices...
        self.readVertices()

        # Read the faces...
        self.readFaces()

        self.fhandle.close()

        # Create the actual object...
        nodename = os.path.basename(filename)
        nodename = os.path.splitext(nodename)[0]
        nodename = nodename.replace(" ", "_")
        if self.is_trimesh:
            n = TriMesh(name=nodename)
        else:
            n = Polyhedron(name=nodename)
        n.geom = self.geom