コード例 #1
0
 def regenerate(self):
     if not self.obj: return
     mesh = self.obj.getData(mesh=True)
     panelimage = mesh.faces[0].image
     panelimage.getSize()  # force load
     Window.WaitCursor(1)
     Window.DrawProgressBar(0, 'Panel regions')
     for n in range(1, PanelRegionHandler.REGIONCOUNT + 1):
         Window.DrawProgressBar(n / 6.0, 'Panel regions')
         img = mesh.faces[n].image
         if img != panelimage:
             (width, height) = img.size
             xoff = self.obj.getProperty('x%d' % n).data
             yoff = self.obj.getProperty('y%d' % n).data
             for y in range(height):
                 for x in range(width):
                     rgba = panelimage.getPixelI(xoff + x, yoff + y)
                     if not rgba[3]:
                         img.setPixelI(
                             x, y,
                             (102, 102, 255, 255))  # hilite transparent
                     else:
                         img.setPixelI(x, y, rgba[:3] + [255])
             img.glFree()  # force reload
             img.pack()  # repack
     mesh.update()
     Window.RedrawAll(0)
     Window.DrawProgressBar(1, 'Finished')
     Window.WaitCursor(0)
コード例 #2
0
def file_callback(filename):
    obj = NETimport(filename)
    try:
        obj.doimport()
        Blender.Scene.GetCurrent().update()
    except ParseError, e:
        Window.WaitCursor(0)
        Window.DrawProgressBar(0, 'ERROR')
        if e.type == ParseError.HEADER:
            msg = 'This is not a valid X-Plane v6, v7 or v8 OBJ file'
        elif e.type == ParseError.NAME:
            msg = 'Missing dataref or light name at line %s\n' % obj.m.lineno
        elif e.type == ParseError.MISC:
            msg = '%s at line %s' % (e.value, obj.m.lineno)
        else:
            thing = ParseError.TEXT[e.type]
            if e.value:
                msg = 'Expecting a %s, found "%s" at line %s' % (
                    thing, e.value, obj.m.lineno)
            else:
                msg = 'Missing %s at line %s' % (thing, obj.m.lineno)
        print "ERROR:\t%s\n" % msg
        Draw.PupMenu("ERROR%%t|%s" % msg)
        Window.RedrawAll()
        Window.DrawProgressBar(1, 'ERROR')
コード例 #3
0
    def export(self, scene):
        theObjects = scene.objects

        print "Starting OBJ export to " + self.filename
        if not checkFile(self.filename):
            return

        Blender.Window.WaitCursor(1)
        Window.DrawProgressBar(0, "Examining textures")
        self.texture = getTexture(self, theObjects, self.iscsl, 7)
        if self.regions:
            (pwidth, pheight) = PanelRegionHandler().panelimage().size
            for img, (n, x1, y1, width, height) in self.regions.iteritems():
                self.regions[img] = (float(x1) / pwidth, float(y1) / pheight,
                                     float(width) / pwidth,
                                     float(height) / pheight)

        #clock=time.clock()	# Processor time

        self.file = open(self.filename, "w")
        self.writeHeader()
        self.writeObjects(theObjects)
        checkLayers(self, theObjects)
        self.file.close()

        Window.DrawProgressBar(1, "Finished")
        #print "%s CPU time" % (time.clock()-clock)
        print "Finished - exported %s primitives\n" % self.nprim
        if self.log:
            r = Draw.PupMenu(("Exported %s primitives%%t|" % self.nprim) +
                             '|'.join([a[0] for a in self.log]))
            if r > 0: raise ExportError(None, self.log[r - 1][1])
        else:
            Draw.PupMenu("Exported %s primitives%%t|OK" % self.nprim)
コード例 #4
0
def file_callback (filename):
    print "Starting DSF import from " + filename
    Window.WaitCursor(1)

    if 1:#XXXtry:
        xppath=normpath(join(dirname(filename),pardir,pardir,pardir,pardir))
        dirs=[i.lower() for i in listdir(xppath)]
        if 'default scenery' in dirs and 'custom scenery' not in dirs:
            xppath=normpath(join(xppath,pardir))

        # Process libraries
        Window.DrawProgressBar(0, "Scanning libraries")
        for d in listdir(xppath):
            if d.lower()=='custom scenery':
                readLIBs(join(xppath,d), libterrain)
                break
        for d in listdir(xppath):
            if d.lower()=='resources':
                for d2 in listdir(join(xppath,d)):
                    if d2.lower()=='default scenery':
                        readLIBs(join(xppath,d,d2), libterrain)
                        break
                break

        Window.DrawProgressBar(0, "Importing")
        readDSF(filename)
    elif 0:#except IOError, e:
        Window.WaitCursor(0)
        Window.DrawProgressBar(1, "ERROR")
        print("ERROR:\t%s.\n" % e.strerror)
        Draw.PupMenu("ERROR: %s" % e.strerror)
        return
    elif 0:#except:
        Window.WaitCursor(0)
        Window.DrawProgressBar(1, "ERROR")
        print("ERROR:\tCan't read DSF.\n")
        Draw.PupMenu("ERROR: Can't read DSF")
        return
    else:
        Window.WaitCursor(0)
    Window.DrawProgressBar(1, "Finished")
    Window.RedrawAll()
    print "Finished\n"
コード例 #5
0
def copy_morphs(_from, _to, PREF_SEL_ONLY, PREF_NO_XCROSS):
    ob_from, me_from, world_verts_from, from_morph_key = _from
    ob_to, me_to, world_verts_to, dummy = _to
    del dummy

    # insert base key at frame 1, using relative keys
    me_to.insertKey(1, 'relative')

    # list of snap indices
    snap_indices = [
        get_snap_idx(co, world_verts_from, PREF_NO_XCROSS)
        for idx, co in world_verts_to
    ]

    # create keys
    for i, from_key_block in enumerate(me_from.key.blocks[1:]):

        # report progress
        Window.DrawProgressBar(
            0.01 + 0.98 * (i / float(len(me_from.key.blocks) - 1)),
            'Copy "%s" -> "%s" ' % (ob_from.name, ob_to.name))

        # get deformation
        morph = [
            vec_new - vec_old
            for (vec_new, vec_old
                 ) in zip(from_key_block.data, me_from.key.blocks[0].data)
        ]

        # deform me_to
        for me_to_vert, me_to_vert_base, snap_idx in zip(
                me_to.vertices, me_to.key.blocks[0].data, snap_indices):
            me_to_vert.co[0] = me_to_vert_base[0] + morph[snap_idx][0]
            me_to_vert.co[1] = me_to_vert_base[1] + morph[snap_idx][1]
            me_to_vert.co[2] = me_to_vert_base[2] + morph[snap_idx][2]

        # insert shape key
        me_to.insertKey(1, 'relative')
        me_to.key.blocks[-1].name = from_key_block.name

    # reset mesh to base morph
    for me_to_vert, me_to_vert_base in zip(me_to.vertices,
                                           me_to.key.blocks[0].data):
        me_to_vert.co[0] = me_to_vert_base[0]
        me_to_vert.co[1] = me_to_vert_base[1]
        me_to_vert.co[2] = me_to_vert_base[2]

    # copy ipo if there is one
    if me_from.key.ipo:
        me_to.key.ipo = me_from.key.ipo

    me_to.update()
コード例 #6
0
def doScript():
	# Main script Function
	# Consists of choosing between 2 loops, one with a redraw, one without, see comments for why
	
	global CUROFFS
	
	translateParams()
	
	total = len(PARAMS['ImagePaths'])
	broken = 0
	
	if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop
		for i, path in enumerate(PARAMS['ImagePaths']):
			CUROFFS = i # Could be passed to the import Function, but I chose a global instead
			Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))		
			imgImport(path)		
			Blender.Redraw()		
			if Blender.Get('version') >= 246:
				if Window.TestBreak():
					broken = 1
					break
	else:
		for i, path in enumerate(PARAMS['ImagePaths']):
			CUROFFS = i
			Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
			imgImport(path)
			if Blender.Get('version') >= 246:
				if Window.TestBreak():
					broken = 1
					break
				
	if broken:
		Window.DrawProgressBar(1.0, "Script Execution Aborted")
	else:
		Window.DrawProgressBar(1.0, "Finished Importing")
		
	Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along
	
	return
コード例 #7
0
def main():

    scn = bpy.data.scenes.active
    ob = scn.objects.active
    if not ob or ob.type != 'Mesh':
        return

    is_editmode = Window.EditMode()
    if is_editmode:
        Window.EditMode(0)

    mousedown_wait()  # so the menu items clicking dosnt trigger the mouseclick

    Window.DrawProgressBar(0.0, '')
    Window.DrawProgressBar(0.1, '(1 of 3) Click on a face corner')

    # wait for a click
    mouse_buttons = Window.GetMouseButtons()
    while not mouse_buttons & LMB:
        sys.sleep(10)
        mouse_buttons = Window.GetMouseButtons()

        # Allow for RMB cancel
        if mouse_buttons & RMB:
            return

    while mouse_buttons & LMB:
        sys.sleep(10)
        mouse_buttons = Window.GetMouseButtons()

    Window.DrawProgressBar(0.2, '(2 of 3 ) Click confirms the U coords')

    mousedown_wait()

    obmat = ob.matrixWorld
    screen_x, screen_y = Window.GetMouseCoords()
    mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat)

    if not mouseInView or not OriginA:
        return

    me = ob.getData(mesh=1)

    # Get the face under the mouse
    face_click, isect, side = BPyMesh.pickMeshRayFace(me, OriginA, DirectionA)
    if not face_click:
        return

    proj_z_component = face_click.no
    if not face_click:
        return

    # Find the face vertex thats closest to the mouse,
    # this vert will be used as the corner to map from.
    best_v = None
    best_length = 10000000
    vi1 = None
    for i, v in enumerate(face_click.v):
        l = (v.co - isect).length
        if l < best_length:
            best_v = v
            best_length = l
            vi1 = i

    # now get the 2 edges in the face that connect to v
    # we can work it out fairly easerly
    if len(face_click) == 4:
        if vi1 == 0: vi2, vi3 = 3, 1
        elif vi1 == 1: vi2, vi3 = 0, 2
        elif vi1 == 2: vi2, vi3 = 1, 3
        elif vi1 == 3: vi2, vi3 = 2, 0
    else:
        if vi1 == 0: vi2, vi3 = 2, 1
        elif vi1 == 1: vi2, vi3 = 0, 2
        elif vi1 == 2: vi2, vi3 = 1, 0

    face_corner_main = face_click.v[vi1].co
    face_corner_a = face_click.v[vi2].co
    face_corner_b = face_click.v[vi3].co

    line_a_len = (face_corner_a - face_corner_main).length
    line_b_len = (face_corner_b - face_corner_main).length

    orig_cursor = Window.GetCursorPos()
    Window.SetCursorPos(face_corner_main.x, face_corner_main.y,
                        face_corner_main.z)

    SHIFT = Window.Qual.SHIFT
    MODE = 0  # firstclick, 1, secondclick
    mouse_buttons = Window.GetMouseButtons()

    project_mat = Matrix([0, 0, 0], [0, 0, 0], [0, 0, 0])

    def get_face_coords(f):
        f_uv = f.uv
        return [(v.co - face_corner_main, f_uv[i]) for i, v in enumerate(f.v)]

    if me.faceUV == False:
        me.faceUV = True

    coords = [(co, uv) for f in me.faces if f.sel
              for co, uv in get_face_coords(f)]

    coords_orig = [uv.copy() for co, uv in coords]
    USE_MODIFIER = using_modifier(ob)

    while 1:
        if mouse_buttons & LMB:
            if MODE == 0:
                mousedown_wait()
                Window.DrawProgressBar(
                    0.8, '(3 of 3 ) Click confirms the V coords')
                MODE = 1  # second click

                # Se we cont continually set the length and get float error
                proj_y_component_orig = proj_y_component.copy()
            else:
                break

        elif mouse_buttons & RMB:
            # Restore old uvs
            for i, uv_orig in enumerate(coords_orig):
                coords[i][1][:] = uv_orig
            break

        mouse_buttons = Window.GetMouseButtons()
        screen_x, screen_y = Window.GetMouseCoords()
        mouseInView, OriginA, DirectionA = mouseViewRay(
            screen_x, screen_y, obmat)

        if not mouseInView:
            continue

        # Do a ray tri intersection, not clipped by the tri
        new_isect = Intersect(face_corner_main, face_corner_a, face_corner_b,
                              DirectionA, OriginA, False)
        new_isect_alt = new_isect + DirectionA * 0.0001

        # The distance from the mouse cursor ray vector to the edge
        line_isect_a_pair = LineIntersect(new_isect, new_isect_alt,
                                          face_corner_main, face_corner_a)
        line_isect_b_pair = LineIntersect(new_isect, new_isect_alt,
                                          face_corner_main, face_corner_b)

        # SHIFT to flip the axis.
        is_shift = Window.GetKeyQualifiers() & SHIFT

        if MODE == 0:
            line_dist_a = (line_isect_a_pair[0] - line_isect_a_pair[1]).length
            line_dist_b = (line_isect_b_pair[0] - line_isect_b_pair[1]).length

            if line_dist_a < line_dist_b:
                proj_x_component = face_corner_a - face_corner_main
                y_axis_length = line_b_len
                x_axis_length = (line_isect_a_pair[1] -
                                 face_corner_main).length
            else:
                proj_x_component = face_corner_b - face_corner_main
                y_axis_length = line_a_len
                x_axis_length = (line_isect_b_pair[1] -
                                 face_corner_main).length

            proj_y_component = proj_x_component.cross(proj_z_component)

            proj_y_component.length = 1 / y_axis_length
            proj_x_component.length = 1 / x_axis_length

            if is_shift: proj_x_component.negate()

        else:
            proj_y_component[:] = proj_y_component_orig
            if line_dist_a < line_dist_b:
                proj_y_component.length = 1 / (line_isect_a_pair[1] -
                                               new_isect).length
            else:
                proj_y_component.length = 1 / (line_isect_b_pair[1] -
                                               new_isect).length

            if is_shift: proj_y_component.negate()

        # Use the existing matrix to make a new 3x3 projecton matrix
        project_mat[0][:] = -proj_y_component
        project_mat[1][:] = -proj_x_component
        project_mat[2][:] = proj_z_component

        # Apply the projection matrix
        for proj_co, uv in coords:
            uv[:] = (project_mat * proj_co)[0:2]

        if USE_MODIFIER:
            me.update()

        Window.Redraw(Window.Types.VIEW3D)

    Window.SetCursorPos(*orig_cursor)
    if is_editmode:
        Window.EditMode(1)

    Window.RedrawAll()
コード例 #8
0
            else:
                proj_y_component.length = 1 / (line_isect_b_pair[1] -
                                               new_isect).length

            if is_shift: proj_y_component.negate()

        # Use the existing matrix to make a new 3x3 projecton matrix
        project_mat[0][:] = -proj_y_component
        project_mat[1][:] = -proj_x_component
        project_mat[2][:] = proj_z_component

        # Apply the projection matrix
        for proj_co, uv in coords:
            uv[:] = (project_mat * proj_co)[0:2]

        if USE_MODIFIER:
            me.update()

        Window.Redraw(Window.Types.VIEW3D)

    Window.SetCursorPos(*orig_cursor)
    if is_editmode:
        Window.EditMode(1)

    Window.RedrawAll()


if __name__ == '__main__':
    main()
    Window.DrawProgressBar(1.0, '')
コード例 #9
0
def vertexGradientPick(ob, MODE):
    #MODE 0 == VWEIGHT,  1 == VCOL

    me = ob.getData(mesh=1)
    if not me.faceUV: me.faceUV = True

    Window.DrawProgressBar(0.0, '')

    mousedown_wait()

    if MODE == 0:
        act_group = me.activeGroup
        if act_group == None:
            mousedown_wait()
            Draw.PupMenu('Error, mesh has no active group.')
            return

    # Loop until click
    Window.DrawProgressBar(0.25, 'Click to set gradient start')
    mouseup()

    obmat = ob.matrixWorld
    screen_x, screen_y = Window.GetMouseCoords()
    mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat)
    if not mouseInView or not OriginA:
        return

    # get the mouse weight

    if MODE == 0:
        pickValA = BPyMesh.pickMeshGroupWeight(me, act_group, OriginA,
                                               DirectionA)
    if MODE == 1:
        pickValA = BPyMesh.pickMeshGroupVCol(me, OriginA, DirectionA)

    Window.DrawProgressBar(0.75, 'Click to set gradient end')
    mouseup()

    TOALPHA = Window.GetKeyQualifiers() & Window.Qual.SHIFT

    screen_x, screen_y = Window.GetMouseCoords()
    mouseInView, OriginB, DirectionB = mouseViewRay(screen_x, screen_y, obmat)
    if not mouseInView or not OriginB:
        return

    if not TOALPHA:  # Only get a second opaque value if we are not blending to alpha
        if MODE == 0:
            pickValB = BPyMesh.pickMeshGroupWeight(me, act_group, OriginB,
                                                   DirectionB)
        else:
            pickValB = BPyMesh.pickMeshGroupVCol(me, OriginB, DirectionB)
    else:
        if MODE == 0: pickValB = 0.0
        else: pickValB = [0.0, 0.0, 0.0]  # Dummy value

    # Neither points touched a face
    if pickValA == pickValB == None:
        return

    # clicking on 1 non face is fine. just set the weight to 0.0
    if pickValA == None:
        pickValA = 0.0

        # swap A/B
        OriginA, OriginB = OriginB, OriginA
        DirectionA, DirectionB = DirectionB, DirectionA
        pickValA, pickValB = pickValA, pickValB

        TOALPHA = True

    if pickValB == None:
        pickValB = 0.0
        TOALPHA = True

    # set up 2 lines so we can measure their distances and calc the gradient

    # make a line 90d to the grad in screenspace.
    if (OriginA - OriginB
        ).length <= eps:  # Persp view. same origin different direction
        cross_grad = DirectionA.cross(DirectionB)
        ORTHO = False

    else:  # Ortho - Same direction, different origin
        cross_grad = DirectionA.cross(OriginA - OriginB)
        ORTHO = True

    cross_grad.normalize()
    cross_grad = cross_grad * 100

    lineA = (OriginA, OriginA + (DirectionA * 100))
    lineB = (OriginB, OriginB + (DirectionB * 100))

    if not ORTHO:
        line_angle = AngleBetweenVecs(lineA[1], lineB[1]) / 2
        line_mid = (lineA[1] + lineB[1]) * 0.5

    VSEL = [False] * (len(me.verts))

    # Get the selected faces and apply the selection to the verts.
    for f in me.faces:
        if f.sel:
            for v in f.v:
                VSEL[v.index] = True
    groupNames, vWeightDict = BPyMesh.meshWeight2Dict(me)

    def grad_weight_from_co(v):
        '''
		Takes a vert and retuens its gradient radio between A and B
		'''

        if not VSEL[v.index]:  # Not bart of a selected face?
            return None, None

        v_co = v.co
        # make a line 90d to the 2 lines the user clicked.
        vert_line = (v_co - cross_grad, v_co + cross_grad)

        xA = LineIntersect(vert_line[0], vert_line[1], lineA[0], lineA[1])
        xB = LineIntersect(vert_line[0], vert_line[1], lineB[0], lineB[1])

        if not xA or not xB:  # Should never happen but support it anyhow
            return None, None

        wA = (xA[0] - xA[1]).length
        wB = (xB[0] - xB[1]).length

        wTot = wA + wB
        if not wTot:  # lines are on the same point.
            return None, None
        '''
		Get the length of the line between both intersections on the 
		2x view lines.
		if the dist between  lineA+VertLine and lineB+VertLine is 
		greater then the lenth between lineA and lineB intersection points, it means
		that the verts are not inbetween the 2 lines.
		'''
        lineAB_length = (xA[1] - xB[1]).length

        # normalzie
        wA = wA / wTot
        wB = wB / wTot

        if ORTHO:  # Con only use line length method with parelelle lines
            if wTot > lineAB_length + eps:
                # vert is outside the range on 1 side. see what side of the grad
                if wA > wB: wA, wB = 1.0, 0.0
                else: wA, wB = 0.0, 1.0
        else:
            # PERSP, lineA[0] is the same origin as lineB[0]

            # Either xA[0] or xB[0]  can be used instead of a possible x_mid between the 2
            # as long as the point is inbetween lineA and lineB it dosent matter.
            a = AngleBetweenVecs(lineA[0] - xA[0], line_mid)
            if a > line_angle:
                # vert is outside the range on 1 side. see what side of the grad
                if wA > wB: wA, wB = 1.0, 0.0
                else: wA, wB = 0.0, 1.0

        return wA, wB

    grad_weights = [grad_weight_from_co(v) for v in me.verts]

    if MODE == 0:
        for v in me.verts:
            i = v.index
            if VSEL[i]:
                wA, wB = grad_weights[i]
                if wA != None:  # and wB
                    if TOALPHA:
                        # Do alpha by using the exiting weight for
                        try:
                            pickValB = vWeightDict[i][act_group]
                        except:
                            pickValB = 0.0  # The weights not there? assume zero
                    # Mix2 2 opaque weights
                    vWeightDict[i][act_group] = pickValB * wA + pickValA * wB

    else:  # MODE==1 VCol
        for f in me.faces:
            if f.sel:
                f_v = f.v
                for i in xrange(len(f_v)):
                    v = f_v[i]
                    wA, wB = grad_weights[v.index]

                    c = f.col[i]

                    if TOALPHA:
                        pickValB = c.r, c.g, c.b

                    c.r = int(pickValB[0] * wA + pickValA[0] * wB)
                    c.g = int(pickValB[1] * wA + pickValA[1] * wB)
                    c.b = int(pickValB[2] * wA + pickValA[2] * wB)

    # Copy weights back to the mesh.
    BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)
    Window.DrawProgressBar(1.0, '')
コード例 #10
0
        layers = []
        if isinstance(e.objs, tuple):
            (o, mesh, faces) = e.objs
            o.select(1)
            layers = o.layers
            for f in mesh.faces:
                f.sel = 0
            if faces:
                for f in faces:
                    f.sel = 1
                for i in range(len(mesh.faces)):
                    if mesh.faces[i] == faces[0]:
                        mesh.activeFace = i
                        break
        else:
            for o in e.objs:
                o.select(1)
                for layer in o.layers:
                    if (layer <= 3
                            or not o.Layers & 7) and not layer in layers:
                        layers.append(layer)
        Window.ViewLayers(layers)
        Window.RedrawAll()
    if e.msg:
        Window.WaitCursor(0)
        Window.DrawProgressBar(0, 'ERROR')
        print "ERROR:\t%s.\n" % e.msg
        Draw.PupMenu("ERROR%%t|%s" % e.msg)
        Window.DrawProgressBar(1, 'ERROR')
    if obj and obj.file: obj.file.close()
コード例 #11
0
    def writeObjects(self, theObjects):

        if self.layermask == 1:
            lseq = [1]
        else:
            lseq = [1, 2, 4]

        h = PanelRegionHandler()

        # Count the objects
        nobj = 0
        objlen = 1
        for layer in lseq:
            for object in theObjects:
                if object.Layer & layer:
                    objlen = objlen + 1

        if self.optimise:
            npasses = Face.BUCKET + 1
        else:
            npasses = 1
        objlen = objlen * (2 + npasses)

        for layer in lseq:
            meshes = []

            self.updateLayer(layer)

            # 1st pass: Build meshes
            for o in range(len(theObjects) - 1, -1, -1):
                object = theObjects[o]
                if not object.Layer & layer or h.isHandlerObj(object):
                    continue

                Window.DrawProgressBar(
                    float(nobj) / objlen,
                    "Exporting %s%% ..." % (nobj * 100 / objlen))
                nobj = nobj + 1

                objType = object.getType()
                if objType == "Mesh":
                    if isLight(object):
                        print 'Warn:\tIgnoring custom light "%s"' % object.name
                        self.log.append(
                            ('Ignoring custom light "%s"' % object.name,
                             [object]))
                    elif not isLine(object, self.linewidth):
                        meshes.append(self.sortMesh(object, layer))
                elif objType == "Lamp":
                    pass  # Handled later
                elif objType == 'Empty':
                    for prop in object.getAllProperties():
                        if prop.type in ['INT', 'FLOAT'
                                         ] and prop.name.startswith('group '):
                            self.file.write(
                                "\nATTR_layer_group\t%s\t%d\t//\n\n" %
                                (prop.name[6:].strip(), int(prop.data)))
                #elif objType not in ['Camera','Lattice']:
                #    print 'Warn:\tIgnoring %s "%s"' % (objType.lower(), object.name)
                #    self.log.append(('Ignoring %s "%s"' % (objType.lower(), object.name), [object]))

            # Hack! Find a kosher panel texture and put it last
            if self.iscockpit:
                panelsorted = 0
                i = len(meshes) - 1
                while i >= 0 and not panelsorted:
                    if meshes[i].faces:
                        for j in range(len(meshes[i].faces)):
                            if meshes[i].faces[j].kosher:
                                mesh = MyMesh(meshes[i].name)
                                mesh.faces.append(meshes[i].faces[j])
                                meshes[i].faces[j] = 0  # Remove original face
                                meshes.append(mesh)
                                panelsorted = 1
                                break
                    i = i - 1

            # 2nd to 2**n+1th pass: Output meshes
            for passno in range(npasses):
                strips = []
                for i in range(len(meshes)):
                    Window.DrawProgressBar(
                        float(nobj) / objlen,
                        "Exporting %s%% ..." % (nobj * 100 / objlen))
                    nobj = nobj + 1

                    if meshes[i]:
                        self.makeStrips(strips, meshes[i], passno)

                for (strip, firstvertex, name) in strips:
                    if len(strip) > 1 and len(strip[0].v) == 3:
                        self.writeStrip(strip, firstvertex, name)
                for (strip, firstvertex, name) in strips:
                    if len(strip) == 1 and len(strip[0].v) == 3:
                        self.writeStrip(strip, firstvertex, name)
                for (strip, firstvertex, name) in strips:
                    if len(strip) > 1 and len(strip[0].v) == 4:
                        self.writeStrip(strip, firstvertex, name)
                for (strip, firstvertex, name) in strips:
                    if len(strip) == 1 and len(strip[0].v) == 4:
                        self.writeStrip(strip, firstvertex, name)

            # last pass: Output Lines and Lamps
            for o in range(len(theObjects) - 1, -1, -1):
                object = theObjects[o]
                if not object.Layer & layer:
                    continue

                Window.DrawProgressBar(
                    float(nobj) / objlen,
                    "Exporting %s%% ..." % (nobj * 100 / objlen))
                nobj = nobj + 1

                objType = object.getType()
                if objType == "Mesh" and isLine(object, self.linewidth):
                    self.writeLine(object)
                elif objType == "Lamp":
                    self.writeLamp(object)

        self.file.write("end\t\t\t// eof\n\n")
        self.file.write(
            "// Built with Blender %4.2f. Exported with XPlane2Blender %s.\n" %
            (float(Blender.Get('version')) / 100, self.version))
コード例 #12
0
def packIslands(islandList):
    if USER_FILL_HOLES:
        Window.DrawProgressBar(0.1, 'Merging Islands (Ctrl: skip merge)...')
        mergeUvIslands(islandList)  # Modify in place

    # Now we have UV islands, we need to pack them.

    # Make a synchronised list with the islands
    # so we can box pak the islands.
    packBoxes = []

    # Keep a list of X/Y offset so we can save time by writing the
    # uv's and packed data in one pass.
    islandOffsetList = []

    islandIdx = 0

    while islandIdx < len(islandList):
        minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])

        w, h = maxx - minx, maxy - miny

        if USER_ISLAND_MARGIN:
            minx -= USER_ISLAND_MARGIN  # *w
            miny -= USER_ISLAND_MARGIN  # *h
            maxx += USER_ISLAND_MARGIN  # *w
            maxy += USER_ISLAND_MARGIN  # *h

            # recalc width and height
            w, h = maxx - minx, maxy - miny

        if w < 0.00001 or h < 0.00001:
            del islandList[islandIdx]
            islandIdx -= 1
            continue
        '''Save the offset to be applied later,
		we could apply to the UVs now and allign them to the bottom left hand area
		of the UV coords like the box packer imagines they are
		but, its quicker just to remember their offset and
		apply the packing and offset in 1 pass '''
        islandOffsetList.append((minx, miny))

        # Add to boxList. use the island idx for the BOX id.
        packBoxes.append([0, 0, w, h])
        islandIdx += 1

    # Now we have a list of boxes to pack that syncs
    # with the islands.

    #print '\tPacking UV Islands...'
    Window.DrawProgressBar(0.7, 'Packing %i UV Islands...' % len(packBoxes))

    time1 = sys.time()
    packWidth, packHeight = Geometry.BoxPack2D(packBoxes)

    # print 'Box Packing Time:', sys.time() - time1

    #if len(pa	ckedLs) != len(islandList):
    #	raise "Error packed boxes differes from original length"

    #print '\tWriting Packed Data to faces'
    Window.DrawProgressBar(0.8, 'Writing Packed Data to faces')

    # Sort by ID, so there in sync again
    islandIdx = len(islandList)
    # Having these here avoids devide by 0
    if islandIdx:

        if USER_STRETCH_ASPECT:
            # Maximize to uv area?? Will write a normalize function.
            xfactor = 1.0 / packWidth
            yfactor = 1.0 / packHeight
        else:
            # Keep proportions.
            xfactor = yfactor = 1.0 / max(packWidth, packHeight)

    while islandIdx:
        islandIdx -= 1
        # Write the packed values to the UV's

        xoffset = packBoxes[islandIdx][0] - islandOffsetList[islandIdx][0]
        yoffset = packBoxes[islandIdx][1] - islandOffsetList[islandIdx][1]

        for f in islandList[
                islandIdx]:  # Offsetting the UV's so they fit in there packed box
            for uv in f.uv:
                uv.x = (uv.x + xoffset) * xfactor
                uv.y = (uv.y + yoffset) * yfactor
コード例 #13
0
def mergeUvIslands(islandList):
    global USER_FILL_HOLES
    global USER_FILL_HOLES_QUALITY

    # Pack islands to bottom LHS
    # Sync with island

    #islandTotFaceArea = [] # A list of floats, each island area
    #islandArea = [] # a list of tuples ( area, w,h)

    decoratedIslandList = []

    islandIdx = len(islandList)
    while islandIdx:
        islandIdx -= 1
        minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])
        w, h = maxx - minx, maxy - miny

        totFaceArea = 0
        offset = Vector(minx, miny)
        for f in islandList[islandIdx]:
            for uv in f.uv:
                uv -= offset

            totFaceArea += f.area

        islandBoundsArea = w * h
        efficiency = abs(islandBoundsArea - totFaceArea)

        # UV Edge list used for intersections as well as unique points.
        edges, uniqueEdgePoints = island2Edge(islandList[islandIdx])

        decoratedIslandList.append([
            islandList[islandIdx], totFaceArea, efficiency, islandBoundsArea,
            w, h, edges, uniqueEdgePoints
        ])

    # Sort by island bounding box area, smallest face area first.
    # no.. chance that to most simple edge loop first.
    decoratedIslandListAreaSort = decoratedIslandList[:]

    try:
        decoratedIslandListAreaSort.sort(key=lambda A: A[3])
    except:
        decoratedIslandListAreaSort.sort(lambda A, B: cmp(A[3], B[3]))

    # sort by efficiency, Least Efficient first.
    decoratedIslandListEfficSort = decoratedIslandList[:]
    # decoratedIslandListEfficSort.sort(lambda A, B: cmp(B[2], A[2]))

    try:
        decoratedIslandListEfficSort.sort(key=lambda A: -A[2])
    except:
        decoratedIslandListEfficSort.sort(lambda A, B: cmp(B[2], A[2]))

    # ================================================== THESE CAN BE TWEAKED.
    # This is a quality value for the number of tests.
    # from 1 to 4, generic quality value is from 1 to 100
    USER_STEP_QUALITY = ((USER_FILL_HOLES_QUALITY - 1) / 25.0) + 1

    # If 100 will test as long as there is enough free space.
    # this is rarely enough, and testing takes a while, so lower quality speeds this up.

    # 1 means they have the same quality
    USER_FREE_SPACE_TO_TEST_QUALITY = 1 + ((
        (100 - USER_FILL_HOLES_QUALITY) / 100.0) * 5)

    #print 'USER_STEP_QUALITY', USER_STEP_QUALITY
    #print 'USER_FREE_SPACE_TO_TEST_QUALITY', USER_FREE_SPACE_TO_TEST_QUALITY

    removedCount = 0

    areaIslandIdx = 0
    ctrl = Window.Qual.CTRL
    BREAK = False
    while areaIslandIdx < len(decoratedIslandListAreaSort) and not BREAK:
        sourceIsland = decoratedIslandListAreaSort[areaIslandIdx]
        # Alredy packed?
        if not sourceIsland[0]:
            areaIslandIdx += 1
        else:
            efficIslandIdx = 0
            while efficIslandIdx < len(
                    decoratedIslandListEfficSort) and not BREAK:

                if Window.GetKeyQualifiers() & ctrl:
                    BREAK = True
                    break

                # Now we have 2 islands, is the efficience of the islands lowers theres an
                # increasing likely hood that we can fit merge into the bigger UV island.
                # this ensures a tight fit.

                # Just use figures we have about user/unused area to see if they might fit.

                targetIsland = decoratedIslandListEfficSort[efficIslandIdx]


                if sourceIsland[0] == targetIsland[0] or\
                not targetIsland[0] or\
                not sourceIsland[0]:
                    pass
                else:

                    # ([island, totFaceArea, efficiency, islandArea, w,h])
                    # Waisted space on target is greater then UV bounding island area.

                    # if targetIsland[3] > (sourceIsland[2]) and\ #
                    # print USER_FREE_SPACE_TO_TEST_QUALITY, 'ass'
                    if targetIsland[2] > (sourceIsland[1] * USER_FREE_SPACE_TO_TEST_QUALITY) and\
                    targetIsland[4] > sourceIsland[4] and\
                    targetIsland[5] > sourceIsland[5]:

                        # DEBUG # print '%.10f  %.10f' % (targetIsland[3], sourceIsland[1])

                        # These enough spare space lets move the box until it fits

                        # How many times does the source fit into the target x/y
                        blockTestXUnit = targetIsland[4] / sourceIsland[4]
                        blockTestYUnit = targetIsland[5] / sourceIsland[5]

                        boxLeft = 0

                        # Distllllance we can move between whilst staying inside the targets bounds.
                        testWidth = targetIsland[4] - sourceIsland[4]
                        testHeight = targetIsland[5] - sourceIsland[5]

                        # Increment we move each test. x/y
                        xIncrement = (testWidth /
                                      (blockTestXUnit *
                                       ((USER_STEP_QUALITY / 50) + 0.1)))
                        yIncrement = (testHeight /
                                      (blockTestYUnit *
                                       ((USER_STEP_QUALITY / 50) + 0.1)))

                        # Make sure were not moving less then a 3rg of our width/height
                        if xIncrement < sourceIsland[4] / 3:
                            xIncrement = sourceIsland[4]
                        if yIncrement < sourceIsland[5] / 3:
                            yIncrement = sourceIsland[5]

                        boxLeft = 0  # Start 1 back so we can jump into the loop.
                        boxBottom = 0  #-yIncrement

                        ##testcount= 0

                        while boxBottom <= testHeight:
                            # Should we use this? - not needed for now.
                            #if Window.GetKeyQualifiers() & ctrl:
                            #	BREAK= True
                            #	break

                            ##testcount+=1
                            #print 'Testing intersect'
                            Intersect = islandIntersectUvIsland(
                                sourceIsland, targetIsland,
                                Vector(boxLeft, boxBottom))
                            #print 'Done', Intersect
                            if Intersect == 1:  # Line intersect, dont bother with this any more
                                pass

                            if Intersect == 2:  # Source inside target
                                '''
								We have an intersection, if we are inside the target 
								then move us 1 whole width accross,
								Its possible this is a bad idea since 2 skinny Angular faces
								could join without 1 whole move, but its a lot more optimal to speed this up
								since we have alredy tested for it.
								
								It gives about 10% speedup with minimal errors.
								'''
                                #print 'ass'
                                # Move the test allong its width + SMALL_NUM
                                #boxLeft += sourceIsland[4] + SMALL_NUM
                                boxLeft += sourceIsland[4]
                            elif Intersect == 0:  # No intersection?? Place it.
                                # Progress
                                removedCount += 1
                                Window.DrawProgressBar(
                                    0.0,
                                    'Merged: %i islands, Ctrl to finish early.'
                                    % removedCount)

                                # Move faces into new island and offset
                                targetIsland[0].extend(sourceIsland[0])
                                offset = Vector(boxLeft, boxBottom)

                                for f in sourceIsland[0]:
                                    for uv in f.uv:
                                        uv += offset

                                sourceIsland[0][:] = []  # Empty

                                # Move edge loop into new and offset.
                                # targetIsland[6].extend(sourceIsland[6])
                                #while sourceIsland[6]:
                                targetIsland[6].extend( [ (\
                                  (e[0]+offset, e[1]+offset, e[2])\
                                ) for e in sourceIsland[6] ] )

                                sourceIsland[6][:] = []  # Empty

                                # Sort by edge length, reverse so biggest are first.

                                try:
                                    targetIsland[6].sort(key=lambda A: A[2])
                                except:
                                    targetIsland[6].sort(
                                        lambda B, A: cmp(A[2], B[2]))

                                targetIsland[7].extend(sourceIsland[7])
                                offset = Vector(boxLeft, boxBottom, 0)
                                for p in sourceIsland[7]:
                                    p += offset

                                sourceIsland[7][:] = []

                                # Decrement the efficiency
                                targetIsland[1] += sourceIsland[
                                    1]  # Increment totFaceArea
                                targetIsland[2] -= sourceIsland[
                                    1]  # Decrement efficiency
                                # IF we ever used these again, should set to 0, eg
                                sourceIsland[
                                    2] = 0  # No area if anyone wants to know

                                break

                            # INCREMENR NEXT LOCATION
                            if boxLeft > testWidth:
                                boxBottom += yIncrement
                                boxLeft = 0.0
                            else:
                                boxLeft += xIncrement
                        ##print testcount

                efficIslandIdx += 1
        areaIslandIdx += 1

    # Remove empty islands
    i = len(islandList)
    while i:
        i -= 1
        if not islandList[i]:
            del islandList[i]  # Can increment islands removed here.
コード例 #14
0
def main(arg):
    print('\nStarting morph copy...')

    # get selected meshes
    scn = Blender.Scene.GetCurrent()
    obs = [ob for ob in self.context.selected_objects if ob.type == 'MESH']
    if not obs:
        Blender.Draw.PupMenu(
            'Error%t|2 or more mesh objects need to be selected.|aborting.')
        return

    PREF_QUALITY = Blender.Draw.Create(0)
    PREF_NO_XCROSS = Blender.Draw.Create(0)
    PREF_SEL_ONLY = Blender.Draw.Create(0)

    pup_block = [
        ('Quality:', PREF_QUALITY, 0, 4,
         'Generate interpolated verts for a higher quality result.'),
        ('No X Crossing', PREF_NO_XCROSS,
         'Do not snap across the zero X axis'),
        '',
        '"Update Selected" copies',
        'active object weights to',
        'selected verts on the other',
        'selected mesh objects.',
        ('Update Selected', PREF_SEL_ONLY,
         'Only copy new morphs to selected verts on the target mesh. '
         '(use active object as source)'),
    ]

    if not Blender.Draw.PupBlock("Copy morphs for %i meshes" % len(obs),
                                 pup_block):
        return

    PREF_SEL_ONLY = PREF_SEL_ONLY.val
    PREF_NO_XCROSS = PREF_NO_XCROSS.val
    PREF_QUALITY = PREF_QUALITY.val

    # XXX quality ignored for now due to bug in subdivide
    if PREF_QUALITY:
        print('\tQuality not yet implemented due to subdivide bug in Blender.')
        print('\tFalling back on quality level 0.')
        PREF_QUALITY = 0

    act_ob = scn.objects.active
    if PREF_SEL_ONLY and (act_ob is None):
        Blender.Draw.PupMenu(
            'Error%t|When dealing with 2 or more meshes with morphs|There must be an active object|to be used as a source|aborting.'
        )
        return

    # saves editmode state and exit editmode if it is enabled
    # (cannot make changes mesh data in editmode)
    is_editmode = Window.EditMode()
    Window.EditMode(0)
    Window.WaitCursor(1)
    t = sys.time()

    sel = []
    from_data = None

    for ob in obs:
        me = ob.getData(mesh=1)
        morph_key = me.key

        # If this is the only mesh with a morph key OR if its one of
        # many, but its active.
        if (morph_key
                and ((ob is act_ob and PREF_SEL_ONLY) or (not PREF_SEL_ONLY))):
            if from_data:
                Blender.Draw.PupMenu(
                    'More then 1 mesh has morphs, only select 1 mesh with '
                    'morphs. Aborting.')
                return
            else:
                # This uses worldspace_verts_idx which gets (idx,co)
                # pairs, then zsorts.
                if PREF_QUALITY:
                    for _ob in obs:
                        _ob.sel = 0
                    ob.sel = 1
                    Object.Duplicate(mesh=1)
                    ob = scn.objects.active
                    me = ob.getData(mesh=1)
                    # morphs will be the same
                    print(('\tGenerating higher %ix quality weights.' %
                           PREF_QUALITY))
                    subdivMesh(me, PREF_QUALITY)
                    scn.unlink(ob)
                from_data = (ob, me, worldspace_verts_zsort(me, ob), morph_key)

        else:
            data = (ob, me, worldspace_verts(me, ob), morph_key)
            sel.append(data)

    if not from_data:
        Blender.Draw.PupMenu('Error%t|No mesh with morphs found.')
        return

    if not sel:
        Blender.Draw.PupMenu(
            'Error%t|Select 2 or more mesh objects, aborting.')
        # We can't unlink the mesh, but at least remove its data.
        if PREF_QUALITY:
            from_data[1].vertices = None
        return

    # Now do the copy.
    print(('\tCopying from "%s" to %i other mesh(es).' %
           (from_data[0].name, len(sel))))
    for data in sel:
        copy_morphs(from_data, data, PREF_SEL_ONLY, PREF_NO_XCROSS)

    # We can't unlink the mesh, but at least remove its data.
    if PREF_QUALITY:
        from_data[1].vertices = None

    print(('Morph copy finished in %.2f seconds' % (sys.time() - t)))
    Window.DrawProgressBar(1.0, '')
    Window.WaitCursor(0)
    if is_editmode:
        Window.EditMode(1)
コード例 #15
0
def readDSF(path):
    baddsf=(0, "Invalid DSF file", path)

    h=file(path, 'rb')
    h.seek(0, 2)
    hlen=h.tell()
    h.seek(0, 0)
    if h.read(8)!='XPLNEDSF' or unpack('<I',h.read(4))!=(1,) or h.read(4)!='DAEH':
        raise IOError, baddsf
    (l,)=unpack('<I', h.read(4))
    headend=h.tell()+l-8
    if h.read(4)!='PORP':
        raise IOError, baddsf
    (l,)=unpack('<I', h.read(4))
    properties=[]
    c=h.read(l-9).split('\0')
    h.read(1)
    overlay=0
    for i in range(0, len(c)-1, 2):
        if c[i]=='sim/overlay': overlay=int(c[i+1])
        elif c[i]=='sim/south': lat=int(c[i+1])
        elif c[i]=='sim/west': lon=int(c[i+1])
        properties.append((c[i],c[i+1]))
    h.seek(headend)
    if overlay:
        # Overlay DSF - bail early
        h.close()
        raise IOError, (0, "This is an overlay DSF", path)

    # Definitions Atom
    if h.read(4)!='NFED':
        raise IOError, baddsf
    (l,)=unpack('<I', h.read(4))
    defnend=h.tell()+l-8
    terrain=objects=polygons=network=[]
    while h.tell()<defnend:
        c=h.read(4)
        (l,)=unpack('<I', h.read(4))
        if l==8:
            pass	# empty
        elif c=='TRET':
            terrain=h.read(l-9).replace('\\','/').replace(':','/').split('\0')
            h.read(1)
        elif c=='TJBO':
            objects=h.read(l-9).replace('\\','/').replace(':','/').split('\0')
            h.read(1)
        elif c=='YLOP':
            polygons=h.read(l-9).replace('\\','/').replace(':','/').split('\0')
            h.read(1)
        elif c=='WTEN':
            networks=h.read(l-9).replace('\\','/').replace(':','/').split('\0')
            h.read(1)
        else:
            h.seek(l-8, 1)

    # Geodata Atom
    if h.read(4)!='DOEG':
        raise IOError, baddsf
    (l,)=unpack('<I', h.read(4))
    geodend=h.tell()+l-8
    pool=[]
    scal=[]
    while h.tell()<geodend:
        c=h.read(4)
        (l,)=unpack('<I', h.read(4))
        if c=='LOOP':
            thispool=[]
            (n,)=unpack('<I', h.read(4))
            (p,)=unpack('<B', h.read(1))
            for i in range(p):
                thisplane=[]
                (e,)=unpack('<B', h.read(1))
                if e==0 or e==1:
                    last=0
                    for j in range(n):
                        (d,)=unpack('<H', h.read(2))
                        if e==1: d=(last+d)&65535
                        thisplane.append(d)
                        last=d
                elif e==2 or e==3:
                    last=0
                    while(len(thisplane))<n:
                        (r,)=unpack('<B', h.read(1))
                        if (r&128):
                            (d,)=unpack('<H', h.read(2))
                            for j in range(r&127):
                                if e==3:
                                    thisplane.append((last+d)&65535)
                                    last=(last+d)&65535
                                else:
                                    thisplane.append(d)
                        else:
                            for j in range(r):
                                (d,)=unpack('<H', h.read(2))
                                if e==3: d=(last+d)&65535
                                thisplane.append(d)
                                last=d
                else:
                    raise IOError, baddsf
                thispool.append(thisplane)
            pool.append(thispool)
        elif c=='LACS':
            thisscal=[]
            for i in range(0, l-8, 8):
                d=unpack('<2f', h.read(8))
                thisscal.append(d)
            scal.append(thisscal)
        else:
            h.seek(l-8, 1)

    # Rescale pool and transform to one list per entry
    if len(scal)!=len(pool): raise(IOError)
    newpool=[]
    for i in range(len(pool)):
        curpool=pool[i]
        n=len(curpool[0])
        newpool=[[] for j in range(n)]
        for plane in range(len(curpool)):
            (scale,offset)=scal[i][plane]
            scale=scale/65535
            for j in range(n):
                newpool[j].append(curpool[plane][j]*scale+offset)
        pool[i]=newpool

    # Commands Atom
    if h.read(4)!='SDMC':
        raise IOError, baddsf
    (l,)=unpack('<I', h.read(4))
    cmdsend=h.tell()+l-8
    curpool=0
    idx=0
    near=0
    far=-1
    flags=0	# 0=physical, 1=overlay
    f=[[[],[]] for i in range(len(terrain))]
    v=[[[],[]] for i in range(len(terrain))]
    t=[[[],[]] for i in range(len(terrain))]
    pscale=99.0/(hlen-geodend)
    progress=0
    while h.tell()<cmdsend:
        now=int((h.tell()-geodend)*pscale)
        if progress!=now:
            progress=now
            Window.DrawProgressBar(progress/100.0, "Importing %2d%%"%progress)

        (c,)=unpack('<B', h.read(1))
        if c==1:	# Coordinate Pool Select
            (curpool,)=unpack('<H', h.read(2))

        elif c==2:	# Junction Offset Select
            h.read(4)	# not implemented

        elif c==3:	# Set Definition
            (idx,)=unpack('<B', h.read(1))

        elif c==4:	# Set Definition
            (idx,)=unpack('<H', h.read(2))

        elif c==5:	# Set Definition
            (idx,)=unpack('<I', h.read(4))

        elif c==6:	# Set Road Subtype
            h.read(1)	# not implemented

        elif c==7:	# Object
            h.read(2)	# not implemented

        elif c==8:	# Object Range
            h.read(4)	# not implemented

        elif c==9:	# Network Chain
            (l,)=unpack('<B', h.read(1))
            h.read(l*2)	# not implemented

        elif c==10:	# Network Chain Range
            h.read(4)	# not implemented

        elif c==11:	# Network Chain
            (l,)=unpack('<B', h.read(1))
            h.read(l*4)	# not implemented

        elif c==12:	# Polygon
            (param,l)=unpack('<HB', h.read(3))
            h.read(l*2)	# not implemented

        elif c==13:	# Polygon Range (DSF2Text uses this one)
            (param,first,last)=unpack('<HHH', h.read(6))	# not implemented

        elif c==14:	# Nested Polygon
            (param,n)=unpack('<HB', h.read(3))
            for i in range(n):
                (l,)=unpack('<B', h.read(1))
                h.read(l*2)	# not implemented

        elif c==15:	# Nested Polygon Range (DSF2Text uses this one too)
            (param,n)=unpack('<HB', h.read(3))
            h.read((n+1)*2)	# not implemented

        elif c==16:	# Terrain Patch
            pass

        elif c==17:	# Terrain Patch w/ flags
            (flags,)=unpack('<B', h.read(1))
            flags-=1

        elif c==18:	# Terrain Patch w/ flags & LOD
            (flags,near,far)=unpack('<Bff', h.read(9))
            flags-=1

        elif c==23:	# Patch Triangle
            (l,)=unpack('<B', h.read(1))
            n=len(v[idx][flags])
            for i in range(n,n+l,3):
                f[idx][flags].append([i+2,i+1,i])
            for i in range(l):
                (d,)=unpack('<H', h.read(2))
                p=pool[curpool][d]
                v[idx][flags].append([(p[0]-lon)*hscale,
                                      (p[1]-lat)*hscale, p[2]*vscale])
                if len(p)>=7:
                    t[idx][flags].append([p[5],p[6]])


        elif c==24:	# Patch Triangle - cross-pool
            (l,)=unpack('<B', h.read(1))
            n=len(v[idx][flags])
            for i in range(n,n+l,3):
                f[idx][flags].append([i+2,i+1,i])
            for i in range(l):
                (c,d)=unpack('<HH', h.read(4))
                p=pool[c][d]
                v[idx][flags].append([(p[0]-lon)*hscale,
                                      (p[1]-lat)*hscale, p[2]*vscale])
                if len(p)>=7:
                    t[idx][flags].append([p[5],p[6]])

        elif c==25:	# Patch Triangle Range
            (first,last)=unpack('<HH', h.read(4))
            n=len(v[idx][flags])
            for i in range(n,n+last-first,3):
                f[idx][flags].append([i+2,i+1,i])
            for d in range(first,last):
                p=pool[curpool][d]
                v[idx][flags].append([(p[0]-lon)*hscale,
                                      (p[1]-lat)*hscale, p[2]*vscale])
                if len(p)>=7:
                    t[idx][flags].append([p[5],p[6]])

        #elif c==26:	# Patch Triangle Strip (not used by DSF2Text)
        #elif c==27:
        #elif c==28:

        elif c==29:	# Patch Triangle Fan
            (l,)=unpack('<B', h.read(1))
            n=len(v[idx][flags])
            for i in range(1,l-1):
                f[idx][flags].append([n+i+1,n+i,n])
            for i in range(l):
                (d,)=unpack('<H', h.read(2))
                p=pool[curpool][d]
                v[idx][flags].append([(p[0]-lon)*hscale,
                                      (p[1]-lat)*hscale, p[2]*vscale])
                if len(p)>=7:
                    t[idx][flags].append([p[5],p[6]])

        elif c==30:	# Patch Triangle Fan - cross-pool
            (l,)=unpack('<B', h.read(1))
            n=len(v[idx][flags])
            for i in range(1,l-1):
                f[idx][flags].append([n+i+1,n+i,n])
            for i in range(l):
                (c,d)=unpack('<HH', h.read(4))
                p=pool[c][d]
                v[idx][flags].append([(p[0]-lon)*hscale,
                                      (p[1]-lat)*hscale, p[2]*vscale])
                if len(p)>=7:
                    t[idx][flags].append([p[5],p[6]])

        elif c==31:	# Patch Triangle Fan Range
            (first,last)=unpack('<HH', h.read(4))
            n=len(v[idx][flags])
            for i in range(1,last-first-1):
                f[idx][flags].append([n+i+1,n+i,n])
            for d in range(first, last):
                p=pool[curpool][d]
                v[idx][flags].append([(p[0]-lon)*hscale,
                                      (p[1]-lat)*hscale, p[2]*vscale])
                if len(p)>=7:
                    t[idx][flags].append([p[5],p[6]])

        elif c==32:	# Comment
            (l,)=unpack('<B', h.read(1))
            h.read(l)

        elif c==33:	# Comment
            (l,)=unpack('<H', h.read(2))
            h.read(l)

        elif c==34:	# Comment
            (l,)=unpack('<I', h.read(4))
            h.read(l)

        else:
            raise IOError, (c, "Unrecognised command (%d)" % c, c)

    h.close()

    Window.DrawProgressBar(0.99, "Realising")

    scene=Scene.GetCurrent()
    scene.layers=[1,2]

    for flags in [0]:# was [1,0]:	# overlay first so overlays
        for idx in range(len(terrain)):
            if not f[idx][flags]: continue
            if idx:
                name=basename(terrain[idx])[:-4]
                if flags: name=name+'.2'
                if terrain[idx] in libterrain:
                    (texture, angle, xscale, zscale)=readTER(libterrain[terrain[idx]])
                elif exists(join(dirname(path), pardir, pardir, terrain[idx])):
                    (texture, angle, xscale, zscale)=readTER(abspath(join(dirname(path), pardir, pardir, terrain[idx])))
                else:
                    raise IOError(0, 'Terrain %s not found' % terrain[idx], terrain[idx])
                try:
                    mat=Material.Get(name)
                except:
                    mat=Material.New(name)
                    mat.rgbCol=[1.0, 1.0, 1.0]
                    mat.spec=0
                    try:
                        img=Image.Get(basename(texture))
                    except:
                        img=Image.Load(texture)
                    tex=Texture.New(name)
                    tex.setType('Image')
                    tex.image=img
                    mat.setTexture(0, tex)
                    if flags:
                        mat.zOffset=1
                        mat.mode |= Material.Modes.ZTRANSP
                    mtex=mat.getTextures()[0]
                    mtex.size=(xscale*250, zscale*250, 0)
                    mtex.zproj=Texture.Proj.NONE
                    if t[idx][flags]:
                        mtex.texco=Texture.TexCo.UV
                    else:
                        mtex.texco=Texture.TexCo.GLOB
            else:
                name=terrain[idx]
                mat=Material.New(terrain[idx])
                mat.rgbCol=[0.1, 0.1, 0.2]
                mat.spec=0

            mesh=Mesh.New(name)
            mesh.mode &= ~(Mesh.Modes.TWOSIDED|Mesh.Modes.AUTOSMOOTH)
            mesh.mode |= Mesh.Modes.NOVNORMALSFLIP
            mesh.materials += [mat]
            mesh.verts.extend(v[idx][flags])
            mesh.faces.extend(f[idx][flags])
            if t[idx][flags]:
                faceno=0
                for face in mesh.faces:
                    face.uv=[Vector(t[idx][flags][i][0], t[idx][flags][i][1]) for i in f[idx][flags][faceno]]
                    face.image=img
                    faceno+=1
            mesh.update()

            ob = Object.New("Mesh", name)
            ob.link(mesh)
            scene.objects.link(ob)
            ob.Layer=flags+1
            ob.addProperty('terrain', terrain[idx])

            mesh.sel=True
            mesh.remDoubles(0.001)	# must be after linked to object
            mesh.sel=False

        if 0:	# Unreliable
            for face in mesh.faces:
                for v in face.verts:
                    if v.co[2]!=0.0:
                        break
                else:
                    face.mat=1	# water

    lamp=Lamp.New("Lamp", "Sun")
    ob = Object.New("Lamp", "Sun")
    ob.link(lamp)
    scene.objects.link(ob)
    lamp.type=1
    ob.Layer=3
    ob.setLocation(500, 500, 1000)
コード例 #16
0
def file_callback (filename):
    try:
        bgl=file(filename,'rb')
    except:
        Draw.PupMenu("ERROR%%t|Can't open %s" % filename)
        return

    bgldir=dirname(filename)

    guid=None
    friendly=None
    texnames=[]	# list of texture file names
    matlist=[]	# fs9 materials
    mats=[]	# list of Blender Materials
    inde=[]
    vert=[]
    tran=[]
    amap=[]	# fsx map
    scen=[]	# (child, peer, matrix, parent)

    data={}	# (material, vert, inde, scene) by LOD
    plat={}	# (surface, vertices) by scene
    atta=[]	# (name, scene)
    attobjs=[]
    atteffects=[]
    partcount=0

    Window.WaitCursor(1)
    Window.DrawProgressBar(0, "Opening ...")
    try:
        (c,size,endmdl)=container(bgl,0)
        assert (c=='RIFF')
        assert (bgl.read(4) in ['MDL9','MDLX'])
        while bgl.tell()<endmdl:
            (c,size,end1)=container(bgl,1)
            if c=='MDLG':	# FSX guid
                guid='{%x-%x-%x-%x%x-%x%x%x%x%x%x}' % unpack('<IHH8B',bgl.read(size))
                if debug: print guid
            elif c=='MDLH':
                if size==36:	# FS9 header
                    (size,reserved,reserved,radius,reserved,reserved,reserved,reserved,reserved)=unpack('<9I', bgl.read(size))
                    if debug: print radius
                else:
                    bgl.seek(size,1)
            elif c=='MDLN':	# FSX friendly name
                friendly=bgl.read(size).strip('\0').strip()
                if debug: print friendly
            elif c=='MDLD':	# FSX data
                while bgl.tell()<end1:
                    Window.DrawProgressBar(float(bgl.tell())/(endmdl+endmdl), "Reading ...")
                    (c,size,end2)=container(bgl,2)
                    if c=='TEXT':
                        texnames=[bgl.read(64).strip('\0').strip() for i in range(0,size,64)]
                    elif c=='MATE':
                        mats.extend([getmaterialx(bgl.read(120), bgldir, texnames) for i in range(0,size,120)])
                    elif c=='INDE':
                        # reverse order of vertices in each triangle
                        for i in range(size/6):
                            t=list(unpack('<3H', bgl.read(6)))
                            t.reverse()
                            inde.extend(t)
                    elif c=='VERB':
                        while bgl.tell()<end2:
                            (c,size,end3)=container(bgl,3)
                            if c=='VERT':
                                vert.append([tuple([round(i,VROUND) for i in unpack('<8f',bgl.read(32))]) for j in range(0,size,32)])
                            else:
                                bgl.seek(size,1)
                    elif c=='TRAN':
                        for i in range(0,size,64):
                            tran.append(Matrix(*[unpack('<4f',bgl.read(16)) for j in range(4)]))
                    elif c=='AMAP':
                        for i in range(0,size,8):
                            (a,b)=unpack('<2I',bgl.read(8))
                            amap.append(b)
                    elif c=='SCEN':
                        # Assumed to be after TRAN and AMAP sections
                        count=size/8
                        for i in range(count):
                            (child,peer,offset,unk)=unpack('<4h',bgl.read(8))
                            thismatrix=tran[amap[offset/8]]
                            scen.append((child,peer,thismatrix,-1))
                    elif c=='LODT':
                        while bgl.tell()<end2:
                            (c,size,end3)=container(bgl,3)
                            if c=='LODE':
                                (lod,)=unpack('<I', bgl.read(4))
                                while bgl.tell()<end3:
                                    (c,size,end4)=container(bgl,4)
                                    if c=='PART':
                                        (typ,sceneg,material,verb,voff,vcount,ioff,icount,mouserect)=unpack('<9I', bgl.read(36))
                                        if debug: print lod, typ,sceneg,material,verb,voff,vcount,ioff,icount,mouserect
                                        assert (typ==1)	# TRIANGLE_LIST
                                        if not lod in data: data[lod]=[]
                                        data[lod].append((mats[material], vert[verb][voff:voff+vcount], inde[ioff:ioff+icount], sceneg))
                                        partcount+=1
                                    else:
                                        bgl.seek(size,1)
                            else:
                                bgl.seek(size,1)
                    elif c=='PLAL':
                        while bgl.tell()<end2:
                            (c,size,end3)=container(bgl,3)
                            if c=='PLAT':
                                (surface,sceneg,numvert,v0x,v0y,v0z,v1x,v1y,v1z,v2x,v2y,v2z)=unpack('<3I9f', bgl.read(48))
                                assert (numvert==3)
                                #print (surface,scene,numvert,v0x,v0y,v0z,v1x,v1y,v1z,v2x,v2y,v2z)
                                if not sceneg in plat: plat[sceneg]={}
                                plat[sceneg][((round(v2x,VROUND),round(v2y,VROUND),round(v2z,VROUND)),(round(v1x,VROUND),round(v1y,VROUND),round(v1z,VROUND)),(round(v0x,VROUND),round(v0y,VROUND),round(v0z,VROUND)))]=surface
                            else:
                                bgl.seek(size,1)
                    elif c=='REFL':
                        while bgl.tell()<end2:
                            (c,size,end3)=container(bgl,3)
                            if c=='REFP':
                                (sceneg,size)=unpack('<II', bgl.read(8))

                                atta.append((bgl.read(size).strip('\0').strip(),sceneg))
                            else:
                                bgl.seek(size,1)
                    elif c=='ATTO':
                        while bgl.tell()<end2:
                            (unk,flags,size)=unpack('<IHH', bgl.read(8))
                            d=bgl.read(size)
                            if flags==2:	# Attached object
                                attobjs.append((d[40:-5], '{%x-%x-%x-%x%x-%x%x%x%x%x%x}' % unpack('<IHH8B', d[20:36])))
                            elif flags==4:	# Attached effect
                                p=d[100:-5].split('\0')	# params, attachpt
                                atteffects.append((p[1], d[20:100].strip(' \0'), p[0]))
                            elif debug:
                                print "Unknown attach %d:\n%s" % (flags, d)
                    else:
                        bgl.seek(size,1)
            elif c=='EXTE':	# FS9 data
                while bgl.tell()<end1:
                    Window.DrawProgressBar(float(bgl.tell())/(endmdl+endmdl), "Reading ...")
                    (c,size,end2)=container(bgl,2)
                    if c=='TEXT':
                        (bglop,count,reserved)=unpack('<HHI', bgl.read(8))
                        assert(bglop==0xb7)
                        texnames=[unpack('<4I', bgl.read(16)) + (bgl.read(64).strip('\0').strip(),) for i in range(count)]
                        assert (bgl.read(2)=='\x22\0')	# return
                    elif c=='MATE':
                        (bglop,count,reserved)=unpack('<HHI', bgl.read(8))
                        assert(bglop==0xb6)
                        matlist.extend([unpack('<17f', bgl.read(17*4)) for i in range(count)])
                        assert (bgl.read(2)=='\x22\0')	# return
                    elif c=='VERT':
                        (bglop,count,reserved)=unpack('<HHI', bgl.read(8))
                        assert(bglop==0xb5)
                        vert.extend([tuple([round(i,VROUND) for i in unpack('<8f',bgl.read(32))]) for j in range(count)])
                        assert (bgl.read(2)=='\x22\0')	# return
                    elif c=='BGL ':
                        code=bgl.read(size)
                        lods=[0]
                        lodno=0
                        while lodno<len(lods):
                            ip=0
                            lod=lods[lodno]
                            sceneg=0
                            curmat=None
                            stack=[]
                            if debug: print "LOD >", lod
                            while True:
                                (bglop,)=unpack('<H', code[ip:ip+2])
                                if debug: print "%s%04x: %02x" % ('  '*len(stack), ip, bglop)
                                ip+=2
                                # mostly just opcodes from BGLFP.doc
                                if bglop==0x0d:		# BGL_JUMP
                                    (offset,)=unpack('<h', code[ip:ip+2])
                                    ip=ip-2+offset
                                elif bglop==0x22:	# BGLOP_RETURN
                                    ip=stack.pop()
                                elif bglop==0x23:	# BGLOP_CALL
                                    (offset,)=unpack('<h', code[ip:ip+2])
                                    stack.append(ip+2)
                                    ip=ip-2+offset
                                elif bglop==0x24:	# BGLOP_IFIN1
                                    ip+=8	# assume true
                                elif bglop==0x39:	# BGLOP_IFMASK
                                    ip+=6	# assume true
                                elif bglop==0x5f:	# BGLOP_IFSIZEV
                                    (offset,r,pixels)=unpack('<hHH', code[ip:ip+6])
                                    newlod=int(0.5+radius*2475.0/r)
                                    if newlod not in lods:
                                        lods.append(newlod)
                                    if lod<newlod:
                                        ip=ip-2+offset
                                    else:
                                        ip+=6
                                elif bglop==0x88:	# BGLOP_JUMP_32
                                    (offset,)=unpack('<i', code[ip:ip+4])
                                    ip=ip-2+offset
                                elif bglop==0x89:	# BGLOP_JUMP_32
                                    (offset,)=unpack('<i', code[ip:ip+4])
                                    assert (offset==-1)
                                    ip=ip+4
                                elif bglop==0x8a:	# BGLOP_CALL_32
                                    (offset,)=unpack('<i', code[ip:ip+4])
                                    stack.append(ip+4)
                                    ip=ip-2+offset
                                elif bglop==0xa7:	# BGLOP_SPRITE_VICALL
                                    ip+=20	# ignore
                                elif bglop==0xb3:	# BGLOP_IFINF1
                                    ip+=14	# assume true
                                elif bglop==0xb8:	# BGLOP_SET_MATERIAL
                                    (m,t)=unpack('<hh', code[ip:ip+4])
                                    ip+=4
                                    curmat=getmaterial9(bgldir, m, matlist, t, texnames)
                                elif bglop==0xb9:	# BGLOP_DRAW_TRILIST
                                    (voff,vcount,icount)=unpack('<3H', code[ip:ip+6])
                                    ip+=6
                                    inde=unpack('<%dH' % icount, code[ip:ip+2*icount])
                                    ip+=2*icount
                                    if debug: print "DATA:", lod, sceneg, voff,vcount,icount
                                    if not lod in data: data[lod]=[]
                                    data[lod].append((curmat, vert[voff:voff+vcount], inde, sceneg))
                                    partcount+=1
                                elif bglop==0xbd:	# BGLOP_END
                                    break
                                elif bglop==0xc4:	# BGLOP_SET_MATRIX_INDIRECT
                                    (sceneg,)=unpack('<H', code[ip:ip+2])
                                    ip+=2
                                else:
                                    assert 0
                            lodno+=1

                        # Shift LODs up
                        lods.sort()
                        lods.append(100)
                        for i in range(len(lods)-1,0,-1):
                            data[lods[i]]=data[lods[i-1]]
                        data[lods[0]].pop()

                    elif c=='TRAN':
                        for i in range(0,size,64):
                            tran.append(Matrix(*[unpack('<4f',bgl.read(16)) for j in range(4)]))
                            if debug:
                                print i/64
                                print tran[i/64]
                    elif c=='ANIC':
                        anicbase=bgl.tell()
                        amap=bgl.read(size)
                    elif c=='SCEN':
                        # Assumed to be after TRAN and ANIC sections
                        (count,)=unpack('<H', bgl.read(2))
                        scen=[None for i in range(count)]
                        for i in range(count):
                            (n,child,peer,size,offset)=unpack('<4hi', bgl.read(12))
                            offset=bgl.tell()-12+offset-anicbase
                            if size==6:	# Static
                                (bglop,src,dst)=unpack('<3H', amap[offset:offset+6])
                                assert (bglop==0xc6)
                                thismatrix=tran[src]
                            else:	# Animation
                                (x,y,z,dst)=unpack('<3fh', amap[offset+size-14:offset+size])
                                thismatrix=TranslationMatrix(Vector(x,y,z,0))

                            scen[n]=(child,peer,thismatrix,-1)
                    elif c=='PLAT':
                        (count,)=unpack('<I', bgl.read(4))
                        s=[]
                        for i in range(count):
                            (sceneg,offset,numvert,surface)=unpack('<HhHH', bgl.read(8))
                            assert (numvert==3)	# triangle
                            s.append((sceneg,surface))
                        # Assumes in order so can ignore offset
                        for i in range(count):
                            (sceneg,surface)=s[i]
                            (v0x,v0y,v0z,v1x,v1y,v1z,v2x,v2y,v2z)=unpack('9f', bgl.read(36))
                            if not sceneg in plat: plat[sceneg]={}
                            plat[sceneg][((round(v0x,VROUND),round(v0y,VROUND),round(v0z,VROUND)),(round(v1x,VROUND),round(v1y,VROUND),round(v1z,VROUND)),(round(v2x,VROUND),round(v2y,VROUND),round(v2z,VROUND)))]=surface

                    elif c=='ATTA':
                        (count,)=unpack('<I', bgl.read(4))
                        s=[]
                        for i in range(count):
                            (sceneg,offset)=unpack('<Hh', bgl.read(4))
                            s.append((sceneg))
                        # Assumes in order so can ignore offset
                        for i in range(count):
                            name=''
                            while True:
                                c=bgl.read(1)
                                if c=='\0': break
                                name=name+c
                            atta.append((name.strip(),s[i]))
                    elif c=='ATTO':		# same as FSX
                        while bgl.tell()<end2:
                            (unk,flags,size)=unpack('<IHH', bgl.read(8))
                            d=bgl.read(size)
                            if flags==2:	# Attached object
                                attobjs.append((d[40:-5], '{%x-%x-%x-%x%x-%x%x%x%x%x%x}' % unpack('<IHH8B', d[20:36])))
                            elif flags==4:	# Attached effect
                                p=d[100:-5].split('\0')	# params, attachpt
                                atteffects.append((p[1], d[20:100].strip(' \0'), p[0]))
                            elif debug:
                                print "Unknown attach %d:\n%s" % (flags, d)
                    else:
                        bgl.seek(size,1)
            else:
                bgl.seek(size,1)

        bgl.close()

        # Invert Child/Peer pointers to get parents
        for i in range(len(scen)):
            (child, peer, thismatrix, parent)=scen[i]
            if child!=-1:	# child's parent is me
                (xchild, xpeer, xmatrix, xparent)=scen[child]
                scen[child]=(xchild, xpeer, xmatrix, i)
            if peer!=-1:	# peer's parent is my parent
                assert (peer>i)
                (xchild, xpeer, xmatrix, xparent)=scen[peer]
                scen[peer]=(xchild, xpeer, xmatrix, parent)
        if debug:
            print "TRAN Matrices", len(tran)
            for i in range(len(tran)):
                print i
                print tran[i]
            #print "Animation map", len(amap)
            #for i in range(len(amap)):
            #    print i, '->', amap[i]
            print "Scene Graph", len(scen)
            for i in range(len(scen)):
                (child, peer, thismatrix, parent)=scen[i]
                print i, child, peer, parent
                print thismatrix

        scene=Scene.GetCurrent()
        lods=data.keys()
        lods.sort()
        lods.reverse()
        partno=0.0
        for layer in range(len(lods)):
            for (material, vert, inde, sceneg) in data[lods[layer]]:
                Window.DrawProgressBar(0.5+partno/(partcount+partcount), "Adding ...")
                (child, peer, finalmatrix, parent)=scen[sceneg]
                #print lods[layer]
                #print sceneg, child, peer, parent
                while parent!=-1:
                    (child, peer, thismatrix, parent)=scen[parent]
                    finalmatrix=finalmatrix*thismatrix
                #print finalmatrix
                if not layer and sceneg in plat:
                    adddata(scene, layer+1, material, vert, inde, finalmatrix, plat[sceneg])
                else:
                    adddata(scene, layer+1, material, vert, inde, finalmatrix)
                partno+=1
        if debug:
            for (sceneg,verts) in plat.iteritems():
                if verts:
                    print "Unallocated platforms: sceneg=%d, %d:" % (sceneg, len(verts.keys()))
                    for v in verts.keys():
                        for vt in v: print "%.4f %.4f %.4f" % vt
                        print

        # Attach points
        attachpoints={}
        for (name, sceneg) in atta:
            (child, peer, finalmatrix, parent)=scen[sceneg]
            while parent!=-1:
                (child, peer, thismatrix, parent)=scen[parent]
                finalmatrix=finalmatrix*thismatrix
            attachpoints[name]=addattach(scene, name, finalmatrix)
        for (name, obj) in attobjs:
            attachpoints[name].addProperty('guid', obj)
        for (name, effect, params) in atteffects:
            attachpoints[name].addProperty('effectName', effect)
            if params: attachpoints[name].addProperty('effectParams', params)


        addprops(scene, lods)

        Window.DrawProgressBar(1, "Finished")
        Window.WaitCursor(0)

    except:
        bgl.close()
        Window.DrawProgressBar(1, "ERROR")
        Window.WaitCursor(0)
        Draw.PupMenu("ERROR%%t|Can't read %s - is this a FSX MDL format file?" % filename)
コード例 #17
0
def copy_bone_influences(_from, _to, PREF_SEL_ONLY, PREF_NO_XCROSS):
    ob_from, me_from, world_verts_from, from_groups = _from
    ob_to, me_to, world_verts_to, dummy = _to
    del dummy

    def getSnapIdx(seek_vec, vecs):
        '''
		Returns the closest vec to snap_points
		'''

        # First seek the closest Z axis vert idx/v
        seek_vec_x, seek_vec_y, seek_vec_z = seek_vec

        from_vec_idx = 0

        len_vecs = len(vecs)

        upidx = len_vecs - 1
        loidx = 0

        while from_vec_idx < len_vecs and vecs[from_vec_idx][1].z < seek_vec_z:
            from_vec_idx += 1

        # Clamp if we overstepped.
        if from_vec_idx >= len_vecs:
            from_vec_idx -= 1

        close_dist = (vecs[from_vec_idx][1] - seek_vec).length
        close_idx = vecs[from_vec_idx][0]

        upidx = from_vec_idx + 1
        loidx = from_vec_idx - 1

        # Set uselo/useup. This means we can keep seeking up/down.
        if upidx >= len_vecs: useup = False
        else: useup = True

        if loidx < 0: uselo = False
        else: uselo = True

        # Seek up/down to find the closest v to seek vec.
        while uselo or useup:
            if useup:
                if upidx >= len_vecs:
                    useup = False
                else:
                    i, v = vecs[upidx]
                    if (not PREF_NO_XCROSS) or (
                        (v.x >= -SMALL_NUM and seek_vec_x >= -SMALL_NUM) or
                        (v.x <= SMALL_NUM
                         and seek_vec_x <= SMALL_NUM)):  # enfoce  xcrossing
                        if v.z - seek_vec_z > close_dist:
                            # the verticle distance is greater then the best distance sofar. we can stop looking up.
                            useup = False
                        elif abs(seek_vec_y - v.y) < close_dist and abs(
                                seek_vec_x - v.x) < close_dist:
                            # This is in the limit measure it.
                            l = (seek_vec - v).length
                            if l < close_dist:
                                close_dist = l
                                close_idx = i
                    upidx += 1

            if uselo:

                if loidx == 0:
                    uselo = False
                else:
                    i, v = vecs[loidx]
                    if (not PREF_NO_XCROSS) or (
                        (v.x >= -SMALL_NUM and seek_vec_x >= -SMALL_NUM) or
                        (v.x <= SMALL_NUM
                         and seek_vec_x <= SMALL_NUM)):  # enfoce  xcrossing
                        if seek_vec_z - v.z > close_dist:
                            # the verticle distance is greater then the best distance sofar. we can stop looking up.
                            uselo = False
                        elif abs(seek_vec_y - v.y) < close_dist and abs(
                                seek_vec_x - v.x) < close_dist:
                            # This is in the limit measure it.
                            l = (seek_vec - v).length
                            if l < close_dist:
                                close_dist = l
                                close_idx = i
                    loidx -= 1

        return close_idx

    to_groups = me_to.getVertGroupNames(
    )  # if not PREF_SEL_ONLY will always be []
    from_groups = me_from.getVertGroupNames()

    if PREF_SEL_ONLY:  # remove selected verts from all groups.
        vsel = [v.index for v in me_to.verts if v.sel]
        for group in to_groups:
            me_to.removeVertsFromGroup(group, vsel)
    else:  # Add all groups.
        for group in from_groups:
            me_to.addVertGroup(group)

    add_ = Mesh.AssignModes.ADD

    for i, co in enumerate(world_verts_to):
        if (not PREF_SEL_ONLY) or (PREF_SEL_ONLY and me_to.verts[i].sel):

            Window.DrawProgressBar(
                0.99 * (i / float(len(world_verts_to))),
                'Copy "%s" -> "%s" ' % (ob_from.name, ob_to.name))

            from_idx = getSnapIdx(co, world_verts_from)
            from_infs = me_from.getVertexInfluences(from_idx)

            for group, weight in from_infs:

                # Add where needed.
                if PREF_SEL_ONLY and group not in to_groups:
                    me_to.addVertGroup(group)
                    to_groups.append(group)

                me_to.assignVertsToGroup(group, [i], weight, add_)

    me_to.update()
コード例 #18
0
def main():
    print '\nStarting BoneWeight Copy...'
    scn = Blender.Scene.GetCurrent()
    contextSel = Object.GetSelected()
    if not contextSel:
        Blender.Draw.PupMenu(
            'Error%t|2 or more mesh objects need to be selected.|aborting.')
        return

    PREF_QUALITY = Blender.Draw.Create(0)
    PREF_NO_XCROSS = Blender.Draw.Create(0)
    PREF_SEL_ONLY = Blender.Draw.Create(0)

    pup_block = [\
    ('Quality:', PREF_QUALITY, 0, 4, 'Generate interpolated verts for a higher quality result.'),\
    ('No X Crossing', PREF_NO_XCROSS, 'Do not snap across the zero X axis'),\
    '',\
    '"Update Selected" copies',\
    'active object weights to',\
    'selected verts on the other',\
    'selected mesh objects.',\
    ('Update Selected', PREF_SEL_ONLY, 'Only copy new weights to selected verts on the target mesh. (use active object as source)'),\
    ]

    if not Blender.Draw.PupBlock("Copy Weights for %i Meshs" % len(contextSel),
                                 pup_block):
        return

    PREF_SEL_ONLY = PREF_SEL_ONLY.val
    PREF_NO_XCROSS = PREF_NO_XCROSS.val
    quality = PREF_QUALITY.val

    act_ob = scn.objects.active
    if PREF_SEL_ONLY and act_ob == None:
        Blender.Draw.PupMenu(
            'Error%t|When dealing with 2 or more meshes with vgroups|There must be an active object|to be used as a source|aborting.'
        )
        return

    sel = []
    from_data = None

    for ob in contextSel:
        if ob.type == 'Mesh':
            me = ob.getData(mesh=1)
            groups = me.getVertGroupNames()

            # If this is the only mesh with a group OR if its one of many, but its active.
            if groups and ((ob == act_ob and PREF_SEL_ONLY) or
                           (not PREF_SEL_ONLY)):
                if from_data:
                    Blender.Draw.PupMenu(
                        'More then 1 mesh has vertex weights, only select 1 mesh with weights. aborting.'
                    )
                    return
                else:
                    # This uses worldspace_verts_idx which gets (idx,co) pairs, then zsorts.
                    if quality:
                        for _ob in contextSel:
                            _ob.sel = 0
                        ob.sel = 1
                        Object.Duplicate(mesh=1)
                        ob = scn.objects.active
                        me = ob.getData(mesh=1)
                        # groups will be the same
                        print '\tGenerating higher %ix quality weights.' % quality
                        subdivMesh(me, quality)
                        scn.unlink(ob)
                    from_data = (ob, me, worldspace_verts_idx(me, ob), groups)

            else:
                data = (ob, me, worldspace_verts(me, ob), groups)
                sel.append(data)

    if not from_data:
        Blender.Draw.PupMenu('Error%t|No mesh with vertex groups found.')
        return

    if not sel:
        Blender.Draw.PupMenu(
            'Error%t|Select 2 or more mesh objects, aborting.')
        if quality: from_data[1].verts = None
        return

    t = Blender.sys.time()
    Window.WaitCursor(1)

    # Now do the copy.
    print '\tCopying from "%s" to %i other mesh(es).' % (from_data[0].name,
                                                         len(sel))
    for data in sel:
        copy_bone_influences(from_data, data, PREF_SEL_ONLY, PREF_NO_XCROSS)

    # We cant unlink the mesh, but at least remove its data.
    if quality:
        from_data[1].verts = None

    print 'Copy Complete in %.6f sec' % (Blender.sys.time() - t)
    Window.DrawProgressBar(1.0, '')
    Window.WaitCursor(0)
コード例 #19
0
def getUvIslands(faceGroups, me):

    # Get seams so we dont cross over seams
    edge_seams = {}  # shoudl be a set
    SEAM = Mesh.EdgeFlags.SEAM
    for ed in me.edges:
        if ed.flag & SEAM:
            edge_seams[ed.key] = None  # dummy var- use sets!
    # Done finding seams

    islandList = []

    Window.DrawProgressBar(
        0.0,
        'Splitting %d projection groups into UV islands:' % len(faceGroups))
    #print '\tSplitting %d projection groups into UV islands:' % len(faceGroups),
    # Find grouped faces

    faceGroupIdx = len(faceGroups)

    while faceGroupIdx:
        faceGroupIdx -= 1
        faces = faceGroups[faceGroupIdx]

        if not faces:
            continue

        # Build edge dict
        edge_users = {}

        for i, f in enumerate(faces):
            for ed_key in f.edge_keys:
                if edge_seams.has_key(ed_key):  # DELIMIT SEAMS! ;)
                    edge_users[ed_key] = []  # so as not to raise an error
                else:
                    try:
                        edge_users[ed_key].append(i)
                    except:
                        edge_users[ed_key] = [i]

        # Modes
        # 0 - face not yet touched.
        # 1 - added to island list, and need to search
        # 2 - touched and searched - dont touch again.
        face_modes = [0] * len(faces)  # initialize zero - untested.

        face_modes[0] = 1  # start the search with face 1

        newIsland = []

        newIsland.append(faces[0])

        ok = True
        while ok:

            ok = True
            while ok:
                ok = False
                for i in xrange(len(faces)):
                    if face_modes[i] == 1:  # search
                        for ed_key in faces[i].edge_keys:
                            for ii in edge_users[ed_key]:
                                if i != ii and face_modes[ii] == 0:
                                    face_modes[ii] = ok = 1  # mark as searched
                                    newIsland.append(faces[ii])

                        # mark as searched, dont look again.
                        face_modes[i] = 2

            islandList.append(newIsland)

            ok = False
            for i in xrange(len(faces)):
                if face_modes[i] == 0:
                    newIsland = []
                    newIsland.append(faces[i])

                    face_modes[i] = ok = 1
                    break
            # if not ok will stop looping

    Window.DrawProgressBar(
        0.1, 'Optimizing Rotation for %i UV Islands' % len(islandList))

    for island in islandList:
        optiRotateUvIsland(island)

    return islandList
コード例 #20
0
def main():
    scn = Scene.GetCurrent()
    act_ob = scn.getActiveObject()
    if act_ob.getType() != 'Mesh':
        act_ob = None

    sel = [
        ob for ob in Object.GetSelected() if ob.getType() == 'Mesh'
        if ob != act_ob
    ]
    if not sel and not act_ob:
        Draw.PupMenu('Error, select a mesh as your active object')
        return

    # Defaults
    PREF_EDITMESH_ONLY = Draw.Create(1)
    PREF_MIRROR_LOCATION = Draw.Create(1)
    PREF_XMID_SNAP = Draw.Create(1)
    PREF_MAX_DIST = Draw.Create(0.02)
    PREF_XZERO_THRESH = Draw.Create(0.002)

    #PREF_MODE= Draw.Create(0) # THIS IS TOOO CONFUSING, HAVE 2 BUTTONS AND MAKE THE MODE FROM THEM.
    PREF_MODE_L2R = Draw.Create(1)
    PREF_MODE_R2L = Draw.Create(0)

    PREF_SEL_ONLY = Draw.Create(1)
    PREF_EDGE_USERS = Draw.Create(0)
    # Weights
    PREF_MIRROR_WEIGHTS = Draw.Create(0)
    PREF_FLIP_NAMES = Draw.Create(1)
    PREF_CREATE_FLIP_NAMES = Draw.Create(1)

    pup_block = [\
    ('EditMesh Only', PREF_EDITMESH_ONLY, 'If disabled, will mirror all selected meshes.'),\
    'Left (-), Right (+)',\
    ('Left > Right', PREF_MODE_L2R, 'Copy from the Left to Right of the mesh. Enable Both for a mid loc/weight.'),\
    ('Right > Left', PREF_MODE_R2L, 'Copy from the Right to Left of the mesh. Enable Both for a mid loc/weight.'),\
    '',\
    ('MaxDist:', PREF_MAX_DIST, 0.0, 1.0, 'Generate interpolated verts so closer vert weights can be copied.'),\
    ('XZero limit:', PREF_XZERO_THRESH, 0.0, 1.0, 'Mirror verts above this distance from the middle, else lock to X/zero.'),\
    ('Sel Verts Only', PREF_SEL_ONLY, 'Only mirror selected verts. Else try and mirror all'),\
    ('Edge Users', PREF_EDGE_USERS, 'Only match up verts that have the same number of edge users.'),\
    'Location Prefs',\
    ('Mirror Location', PREF_MIRROR_LOCATION, 'Mirror vertex locations.'),\
    ('XMidSnap Verts', PREF_XMID_SNAP, 'Snap middle verts to X Zero (uses XZero limit)'),\
    'Weight Prefs',\
    ('Mirror Weights', PREF_MIRROR_WEIGHTS, 'Mirror vertex locations.'),\
    ('Flip Groups', PREF_FLIP_NAMES, 'Mirror flip names.'),\
    ('New Flip Groups', PREF_CREATE_FLIP_NAMES, 'Make new groups for flipped names.'),\
    ]

    if not Draw.PupBlock("X Mirror mesh tool", pup_block):
        return

    # WORK OUT THE MODE 0
    # PREF_MODE, 0:middle, 1: Left. 2:Right.
    PREF_MODE_R2L = PREF_MODE_R2L.val
    PREF_MODE_L2R = PREF_MODE_L2R.val

    if PREF_MODE_R2L and PREF_MODE_L2R:
        PREF_MODE = 0  # Middle
    elif not PREF_MODE_R2L and PREF_MODE_L2R:
        PREF_MODE = 1  # Left to Right
    elif PREF_MODE_R2L and not PREF_MODE_L2R:
        PREF_MODE = 2  # Right to Left
    else:  # Neither Selected. Do middle anyway
        PREF_MODE = 0

    PREF_EDITMESH_ONLY = PREF_EDITMESH_ONLY.val
    PREF_MIRROR_LOCATION = PREF_MIRROR_LOCATION.val
    PREF_XMID_SNAP = PREF_XMID_SNAP.val
    PREF_MAX_DIST = PREF_MAX_DIST.val
    PREF_XZERO_THRESH = PREF_XZERO_THRESH.val
    PREF_SEL_ONLY = PREF_SEL_ONLY.val
    PREF_EDGE_USERS = PREF_EDGE_USERS.val
    # weights
    PREF_MIRROR_WEIGHTS = PREF_MIRROR_WEIGHTS.val
    PREF_FLIP_NAMES = PREF_FLIP_NAMES.val
    PREF_CREATE_FLIP_NAMES = PREF_CREATE_FLIP_NAMES.val

    t = sys.time()

    is_editmode = Window.EditMode()  # Exit Editmode.
    if is_editmode: Window.EditMode(0)
    Mesh.Mode(Mesh.SelectModes['VERTEX'])
    Window.WaitCursor(1)

    if act_ob:
        mesh_mirror(act_ob.getData(mesh=1), PREF_MIRROR_LOCATION,
                    PREF_XMID_SNAP, PREF_MAX_DIST, PREF_XZERO_THRESH,
                    PREF_MODE, PREF_SEL_ONLY, PREF_EDGE_USERS,
                    PREF_MIRROR_WEIGHTS, PREF_FLIP_NAMES,
                    PREF_CREATE_FLIP_NAMES)
    if (not PREF_EDITMESH_ONLY) and sel:
        for ob in sel:
            mesh_mirror(ob.getData(mesh=1), PREF_MIRROR_LOCATION,
                        PREF_XMID_SNAP, PREF_MAX_DIST, PREF_XZERO_THRESH,
                        PREF_MODE, PREF_SEL_ONLY, PREF_EDGE_USERS,
                        PREF_MIRROR_WEIGHTS, PREF_FLIP_NAMES,
                        PREF_CREATE_FLIP_NAMES)

    if is_editmode: Window.EditMode(1)
    Window.WaitCursor(0)
    Window.DrawProgressBar(1.0, '')
    Window.RedrawAll()

    print 'Mirror done in %.6f sec.' % (sys.time() - t)
コード例 #21
0
def main():
    global USER_FILL_HOLES
    global USER_FILL_HOLES_QUALITY
    global USER_STRETCH_ASPECT
    global USER_ISLAND_MARGIN

    objects = bpy.data.scenes.active.objects

    # we can will tag them later.
    obList = [ob for ob in objects.context if ob.type == 'Mesh']

    # Face select object may not be selected.
    ob = objects.active
    if ob and ob.sel == 0 and ob.type == 'Mesh':
        # Add to the list
        obList = [ob]
    del objects

    if not obList:
        Draw.PupMenu('error, no selected mesh objects')
        return

    # Create the variables.
    USER_PROJECTION_LIMIT = Draw.Create(66)
    USER_ONLY_SELECTED_FACES = Draw.Create(1)
    USER_SHARE_SPACE = Draw.Create(1)  # Only for hole filling.
    USER_STRETCH_ASPECT = Draw.Create(1)  # Only for hole filling.
    USER_ISLAND_MARGIN = Draw.Create(0.0)  # Only for hole filling.
    USER_FILL_HOLES = Draw.Create(0)
    USER_FILL_HOLES_QUALITY = Draw.Create(50)  # Only for hole filling.
    USER_VIEW_INIT = Draw.Create(0)  # Only for hole filling.
    USER_AREA_WEIGHT = Draw.Create(1)  # Only for hole filling.


    pup_block = [\
    'Projection',\
    ('Angle Limit:', USER_PROJECTION_LIMIT, 1, 89, 'lower for more projection groups, higher for less distortion.'),\
    ('Selected Faces Only', USER_ONLY_SELECTED_FACES, 'Use only selected faces from all selected meshes.'),\
    ('Init from view', USER_VIEW_INIT, 'The first projection will be from the view vector.'),\
    ('Area Weight', USER_AREA_WEIGHT, 'Weight projections vector by face area.'),\
    '',\
    '',\
    '',\
    'UV Layout',\
    ('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\
    ('Stretch to bounds', USER_STRETCH_ASPECT, 'Stretch the final output to texture bounds.'),\
    ('Island Margin:', USER_ISLAND_MARGIN, 0.0, 0.5, 'Margin to reduce bleed from adjacent islands.'),\
    'Fill in empty areas',\
    ('Fill Holes', USER_FILL_HOLES, 'Fill in empty areas reduced texture waistage (slow).'),\
    ('Fill Quality:', USER_FILL_HOLES_QUALITY, 1, 100, 'Depends on fill holes, how tightly to fill UV holes, (higher is slower)'),\
    ]

    # Reuse variable
    if len(obList) == 1:
        ob = "Unwrap %i Selected Mesh"
    else:
        ob = "Unwrap %i Selected Meshes"

    # HACK, loop until mouse is lifted.
    '''
	while Window.GetMouseButtons() != 0:
		sys.sleep(10)
	'''

    if not Draw.PupBlock(ob % len(obList), pup_block):
        return
    del ob

    # Convert from being button types
    USER_PROJECTION_LIMIT = USER_PROJECTION_LIMIT.val
    USER_ONLY_SELECTED_FACES = USER_ONLY_SELECTED_FACES.val
    USER_SHARE_SPACE = USER_SHARE_SPACE.val
    USER_STRETCH_ASPECT = USER_STRETCH_ASPECT.val
    USER_ISLAND_MARGIN = USER_ISLAND_MARGIN.val
    USER_FILL_HOLES = USER_FILL_HOLES.val
    USER_FILL_HOLES_QUALITY = USER_FILL_HOLES_QUALITY.val
    USER_VIEW_INIT = USER_VIEW_INIT.val
    USER_AREA_WEIGHT = USER_AREA_WEIGHT.val

    USER_PROJECTION_LIMIT_CONVERTED = cos(USER_PROJECTION_LIMIT * DEG_TO_RAD)
    USER_PROJECTION_LIMIT_HALF_CONVERTED = cos(
        (USER_PROJECTION_LIMIT / 2) * DEG_TO_RAD)

    # Toggle Edit mode
    is_editmode = Window.EditMode()
    if is_editmode:
        Window.EditMode(0)
    # Assume face select mode! an annoying hack to toggle face select mode because Mesh dosent like faceSelectMode.

    if USER_SHARE_SPACE:
        # Sort by data name so we get consistant results
        try:
            obList.sort(key=lambda ob: ob.getData(name_only=1))
        except:
            obList.sort(lambda ob1, ob2: cmp(ob1.getData(name_only=1),
                                             ob2.getData(name_only=1)))

        collected_islandList = []

    Window.WaitCursor(1)

    time1 = sys.time()

    # Tag as False se we dont operate on teh same mesh twice.
    bpy.data.meshes.tag = False

    for ob in obList:
        me = ob.getData(mesh=1)

        if me.tag or me.lib:
            continue

        # Tag as used
        me.tag = True

        if not me.faceUV:  # Mesh has no UV Coords, dont bother.
            me.faceUV = True

        if USER_ONLY_SELECTED_FACES:
            meshFaces = [thickface(f) for f in me.faces if f.sel]
        else:
            meshFaces = map(thickface, me.faces)

        if not meshFaces:
            continue

        Window.DrawProgressBar(
            0.1, 'SmartProj UV Unwrapper, mapping "%s", %i faces.' %
            (me.name, len(meshFaces)))

        # =======
        # Generate a projection list from face normals, this is ment to be smart :)

        # make a list of face props that are in sync with meshFaces
        # Make a Face List that is sorted by area.
        # meshFaces = []

        # meshFaces.sort( lambda a, b: cmp(b.area , a.area) ) # Biggest first.
        try:
            meshFaces.sort(key=lambda a: -a.area)
        except:
            meshFaces.sort(lambda a, b: cmp(b.area, a.area))

        # remove all zero area faces
        while meshFaces and meshFaces[-1].area <= SMALL_NUM:
            # Set their UV's to 0,0
            for uv in meshFaces[-1].uv:
                uv.zero()
            meshFaces.pop()

        # Smallest first is slightly more efficient, but if the user cancels early then its better we work on the larger data.

        # Generate Projection Vecs
        # 0d is   1.0
        # 180 IS -0.59846

        # Initialize projectVecs
        if USER_VIEW_INIT:
            # Generate Projection
            projectVecs = [
                Vector(Window.GetViewVector()) *
                ob.matrixWorld.copy().invert().rotationPart()
            ]  # We add to this allong the way
        else:
            projectVecs = []

        newProjectVec = meshFaces[0].no
        newProjectMeshFaces = []  # Popping stuffs it up.

        # Predent that the most unique angke is ages away to start the loop off
        mostUniqueAngle = -1.0

        # This is popped
        tempMeshFaces = meshFaces[:]

        # This while only gathers projection vecs, faces are assigned later on.
        while 1:
            # If theres none there then start with the largest face

            # add all the faces that are close.
            for fIdx in xrange(len(tempMeshFaces) - 1, -1, -1):
                # Use half the angle limit so we dont overweight faces towards this
                # normal and hog all the faces.
                if newProjectVec.dot(tempMeshFaces[fIdx].no
                                     ) > USER_PROJECTION_LIMIT_HALF_CONVERTED:
                    newProjectMeshFaces.append(tempMeshFaces.pop(fIdx))

            # Add the average of all these faces normals as a projectionVec
            averageVec = Vector(0, 0, 0)
            if USER_AREA_WEIGHT:
                for fprop in newProjectMeshFaces:
                    averageVec += (fprop.no * fprop.area)
            else:
                for fprop in newProjectMeshFaces:
                    averageVec += fprop.no

            if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0:  # Avoid NAN
                projectVecs.append(averageVec.normalize())

            # Get the next vec!
            # Pick the face thats most different to all existing angles :)
            mostUniqueAngle = 1.0  # 1.0 is 0d. no difference.
            mostUniqueIndex = 0  # dummy

            for fIdx in xrange(len(tempMeshFaces) - 1, -1, -1):
                angleDifference = -1.0  # 180d difference.

                # Get the closest vec angle we are to.
                for p in projectVecs:
                    temp_angle_diff = p.dot(tempMeshFaces[fIdx].no)

                    if angleDifference < temp_angle_diff:
                        angleDifference = temp_angle_diff

                if angleDifference < mostUniqueAngle:
                    # We have a new most different angle
                    mostUniqueIndex = fIdx
                    mostUniqueAngle = angleDifference

            if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED:
                #print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces)
                # Now weight the vector to all its faces, will give a more direct projection
                # if the face its self was not representive of the normal from surrounding faces.

                newProjectVec = tempMeshFaces[mostUniqueIndex].no
                newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)]

            else:
                if len(projectVecs) >= 1:  # Must have at least 2 projections
                    break

        # If there are only zero area faces then its possible
        # there are no projectionVecs
        if not len(projectVecs):
            Draw.PupMenu(
                'error, no projection vecs where generated, 0 area faces can cause this.'
            )
            return

        faceProjectionGroupList = [[] for i in xrange(len(projectVecs))]

        # MAP and Arrange # We know there are 3 or 4 faces here

        for fIdx in xrange(len(meshFaces) - 1, -1, -1):
            fvec = meshFaces[fIdx].no
            i = len(projectVecs)

            # Initialize first
            bestAng = fvec.dot(projectVecs[0])
            bestAngIdx = 0

            # Cycle through the remaining, first alredy done
            while i - 1:
                i -= 1

                newAng = fvec.dot(projectVecs[i])
                if newAng > bestAng:  # Reverse logic for dotvecs
                    bestAng = newAng
                    bestAngIdx = i

            # Store the area for later use.
            faceProjectionGroupList[bestAngIdx].append(meshFaces[fIdx])

        # Cull faceProjectionGroupList,

        # Now faceProjectionGroupList is full of faces that face match the project Vecs list
        for i in xrange(len(projectVecs)):
            # Account for projectVecs having no faces.
            if not faceProjectionGroupList[i]:
                continue

            # Make a projection matrix from a unit length vector.
            MatProj = VectoMat(projectVecs[i])

            # Get the faces UV's from the projected vertex.
            for f in faceProjectionGroupList[i]:
                f_uv = f.uv
                for j, v in enumerate(f.v):
                    f_uv[j][:] = (MatProj * v.co)[:2]

        if USER_SHARE_SPACE:
            # Should we collect and pack later?
            islandList = getUvIslands(faceProjectionGroupList, me)
            collected_islandList.extend(islandList)

        else:
            # Should we pack the islands for this 1 object?
            islandList = getUvIslands(faceProjectionGroupList, me)
            packIslands(islandList)

        # update the mesh here if we need to.

    # We want to pack all in 1 go, so pack now
    if USER_SHARE_SPACE:
        Window.DrawProgressBar(0.9, "Box Packing for all objects...")
        packIslands(collected_islandList)

    print "Smart Projection time: %.2f" % (sys.time() - time1)
    # Window.DrawProgressBar(0.9, "Smart Projections done, time: %.2f sec." % (sys.time() - time1))

    if is_editmode:
        Window.EditMode(1)

    Window.DrawProgressBar(1.0, "")
    Window.WaitCursor(0)
    Window.RedrawAll()
コード例 #22
0
def mesh_mirror(me, PREF_MIRROR_LOCATION, PREF_XMID_SNAP, PREF_MAX_DIST,
                PREF_XZERO_THRESH, PREF_MODE, PREF_SEL_ONLY, PREF_EDGE_USERS,
                PREF_MIRROR_WEIGHTS, PREF_FLIP_NAMES, PREF_CREATE_FLIP_NAMES):
    '''
	PREF_MIRROR_LOCATION, Will we mirror locations?
	PREF_XMID_SNAP, Should we snap verts to X-0?
	PREF_MAX_DIST, Maximum distance to test snapping verts.
	PREF_XZERO_THRESH, How close verts must be to the middle before they are considered X-Zero verts.
	PREF_MODE, 0:middle, 1: Left. 2:Right.
	PREF_SEL_ONLY, only snap the selection
	PREF_EDGE_USERS, match only verts with the same number of edge users.
	PREF_MIRROR_LOCATION, 
	'''

    # Operate on all verts
    if not PREF_SEL_ONLY:
        for v in me.verts:
            v.sel = 1

    if PREF_EDGE_USERS:
        edge_users = [0] * len(me.verts)
        for ed in me.edges:
            edge_users[ed.v1.index] += 1
            edge_users[ed.v2.index] += 1

    if PREF_XMID_SNAP:  # Do we snap locations at all?
        for v in me.verts:
            if v.sel:
                if abs(v.co.x) <= PREF_XZERO_THRESH:
                    v.co.x = 0
                    v.sel = 0

        # alredy de-selected verts
        neg_vts = [v for v in me.verts if v.sel and v.co.x < 0]
        pos_vts = [v for v in me.verts if v.sel and v.co.x > 0]

    else:
        # Use a small margin verts must be outside before we mirror them.
        neg_vts = [v for v in me.verts if v.sel if v.co.x < -PREF_XZERO_THRESH]
        pos_vts = [v for v in me.verts if v.sel if v.co.x > PREF_XZERO_THRESH]

    #*Mirror Location*********************************************************#
    if PREF_MIRROR_LOCATION:
        mirror_pairs = []
        # allign the negative with the positive.
        flipvec = Mathutils.Vector()
        len_neg_vts = float(len(neg_vts))
        for i1, nv in enumerate(neg_vts):
            if nv.sel:  # we may alredy be mirrored, if so well be deselected
                nv_co = nv.co
                for i2, pv in enumerate(pos_vts):
                    if pv.sel:
                        # Enforce edge users.
                        if not PREF_EDGE_USERS or edge_users[i1] == edge_users[
                                i2]:
                            flipvec[:] = pv.co
                            flipvec.x = -flipvec.x
                            l = (nv_co - flipvec).length

                            if l == 0.0:  # Both are alredy mirrored so we dont need to think about them.
                                # De-Select so we dont use again/
                                pv.sel = nv.sel = 0

                            # Record a match.
                            elif l <= PREF_MAX_DIST:

                                # We can adjust the length by the normal, now we know the length is under the limit.
                                # DISABLED, WASNT VERY USEFULL
                                '''
								if PREF_NOR_WEIGHT>0:
									# Get the normal and flipm reuse flipvec
									flipvec[:]= pv.no
									flipvec.x= -flipvec.x
									try:
										ang= Mathutils.AngleBetweenVecs(nv.no, flipvec)/180.0
									except: # on rare occasions angle between vecs will fail.- zero length vec.
										ang= 0
									
									l=l*(1+(ang*PREF_NOR_WEIGHT))
								'''
                                # Record the pairs for sorting to see who will get joined
                                mirror_pairs.append((l, nv, pv))

                # Update every 20 loops
                if i1 % 10 == 0:
                    Window.DrawProgressBar(
                        0.8 * (i1 / len_neg_vts),
                        'Mirror verts %i of %i' % (i1, len_neg_vts))

        Window.DrawProgressBar(0.9, 'Mirror verts: Updating locations')

        # Now we have a list of the pairs we might use, lets find the best and do them first.
        # de-selecting as we go. so we can makke sure not to mess it up.
        try:
            mirror_pairs.sort(key=lambda a: a[0])
        except:
            mirror_pairs.sort(lambda a, b: cmp(a[0], b[0]))

        for dist, v1, v2 in mirror_pairs:  # dist, neg, pos
            if v1.sel and v2.sel:
                if PREF_MODE == 0:  # Middle
                    flipvec[:] = v2.co  # positive
                    flipvec.x = -flipvec.x  # negatve
                    v2.co = v1.co = (flipvec + v1.co) * 0.5  # midway
                    v2.co.x = -v2.co.x
                elif PREF_MODE == 2:  # Left
                    v2.co = v1.co
                    v2.co.x = -v2.co.x
                elif PREF_MODE == 1:  # Right
                    v1.co = v2.co
                    v1.co.x = -v1.co.x
                v1.sel = v2.sel = 0

    #*Mirror Weights**********************************************************#
    if PREF_MIRROR_WEIGHTS:

        groupNames, vWeightDict = BPyMesh.meshWeight2Dict(me)
        mirror_pairs_l2r = []  # Stor a list of matches for these verts.
        mirror_pairs_r2l = []  # Stor a list of matches for these verts.

        # allign the negative with the positive.
        flipvec = Mathutils.Vector()
        len_neg_vts = float(len(neg_vts))

        # Here we make a tuple to look through, if were middle well need to look through both.
        if PREF_MODE == 0:  # Middle
            find_set = ((neg_vts, pos_vts, mirror_pairs_l2r),
                        (pos_vts, neg_vts, mirror_pairs_r2l))
        elif PREF_MODE == 1:  # Left
            find_set = ((neg_vts, pos_vts, mirror_pairs_l2r), )
        elif PREF_MODE == 2:  # Right
            find_set = ((pos_vts, neg_vts, mirror_pairs_r2l), )

        # Do a locational lookup again :/ - This isnt that good form but if we havnt mirrored weights well need to do it anyway.
        # The Difference with this is that we dont need to have 1:1 match for each vert- just get each vert to find another mirrored vert
        # and use its weight.
        # Use  "find_set" so we can do a flipped search L>R and R>L without duplicate code.
        for vtls_A, vtls_B, pair_ls in find_set:
            for i1, vA in enumerate(vtls_A):
                best_len = 1 << 30  # BIGNUM
                best_idx = -1

                # Find the BEST match
                vA_co = vA.co
                for i2, vB in enumerate(vtls_B):
                    # Enforce edge users.
                    if not PREF_EDGE_USERS or edge_users[i1] == edge_users[i2]:
                        flipvec[:] = vB.co
                        flipvec.x = -flipvec.x
                        l = (vA_co - flipvec).length

                        if l < best_len:
                            best_len = l
                            best_idx = i2

                if best_idx != -1:
                    pair_ls.append((vtls_A[i1].index,
                                    vtls_B[best_idx].index))  # neg, pos.

        # Now we can merge the weights
        if PREF_MODE == 0:  # Middle
            newVWeightDict = [vWeightDict[i] for i in xrange(len(me.verts))
                              ]  # Have empty dicts just incase
            for pair_ls in (mirror_pairs_l2r, mirror_pairs_r2l):
                if PREF_FLIP_NAMES:
                    for i1, i2 in pair_ls:
                        flipWeight, groupNames = BPyMesh.dictWeightFlipGroups(
                            vWeightDict[i2], groupNames,
                            PREF_CREATE_FLIP_NAMES)
                        newVWeightDict[i1] = BPyMesh.dictWeightMerge(
                            [vWeightDict[i1], flipWeight])
                else:
                    for i1, i2 in pair_ls:
                        newVWeightDict[i1] = BPyMesh.dictWeightMerge(
                            [vWeightDict[i1], vWeightDict[i2]])

            vWeightDict = newVWeightDict

        elif PREF_MODE == 1:  # Left
            if PREF_FLIP_NAMES:
                for i1, i2 in mirror_pairs_l2r:
                    vWeightDict[i2], groupNames = BPyMesh.dictWeightFlipGroups(
                        vWeightDict[i1], groupNames, PREF_CREATE_FLIP_NAMES)
            else:
                for i1, i2 in mirror_pairs_l2r:
                    vWeightDict[i2] = vWeightDict[
                        i1]  # Warning Multiple instances of the same data, its ok in this case but dont modify later.

        elif PREF_MODE == 2:  # Right
            if PREF_FLIP_NAMES:
                for i1, i2 in mirror_pairs_r2l:
                    vWeightDict[i2], groupNames = BPyMesh.dictWeightFlipGroups(
                        vWeightDict[i1], groupNames, PREF_CREATE_FLIP_NAMES)
            else:
                for i1, i2 in mirror_pairs_r2l:
                    vWeightDict[i2] = vWeightDict[i1]  # Warning, ditto above

        BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)

    me.update()