Example #1
0
def scatter_object(leaf_candidates, ob, dupli_object, leaf_size):
    if dupli_object == None: # return when leaf object is not specified
        return
    leafs = [] # container for all created leafs
    collection = bpy.context.scene.collection # get scene collection
    ob_transform = ob.matrix_world
    for position, direction, length, radius, is_end in leaf_candidates:
        new_leaf = dupli_object.copy() # copy leaf object
        new_leaf.data = new_leaf.data.copy()
        dir_rot = Vector((1,0,0)).rotation_difference(direction) # rotation of new leaf
        
        loc, rot, scale = new_leaf.matrix_world.decompose()
        mat_scale = Matrix() # scale of new leaf
        random_scale = 1 + ((random()-.5) * .4)
        for i in range(3):
            mat_scale[i][i] = scale[i] * random_scale
        new_leaf.matrix_world = ob_transform @ ((Matrix.Translation(position) @ dir_rot.to_matrix().to_4x4() @ mat_scale))
        c =random()
        color_vertices(new_leaf, (c,c,c,c))
        leafs.append(new_leaf)
        collection.objects.link(new_leaf)
    
    bpy.ops.object.select_all(action='DESELECT') # deselecting everything so no unwanted object will be joined as a leaf
    for leaf in leafs:
        leaf.select_set(state=True) # selecting all leafs
    ob.select_set(state=True) # selecting twig
    bpy.context.view_layer.objects.active = ob # make twig the active object so that leafs are joined to it
    bpy.ops.object.join() # join leafs to twig
Example #2
0
def OBB(vecs, r_indices=None, eps=1e-6):
    """Convex hull を用いたOBBを返す。
    Z->Y->Xの順で長さが最少となる軸を求める。
    :param vecs: list of Vector
    :type vecs: list | tuple
    :param r_indices: listを渡すとconvexhullの結果を格納する
    :type r_indices: None | list
    :param eps: 種々の計算の閾値
    :return:
        (matrix, obb_size)
        matrix:
            type: Matrx
            OBBの回転と中心を表す。vecsが二次元ベクトルの場合は3x3, 三次元なら4x4。
        obb_size:
            type: Vector
            OBBの各軸の長さ。vecsと同じ次元。
    :rtype: (Matrix, Vector)
    """

    if not vecs:
        return None, None

    # 2D ----------------------------------------------------------------------
    if len(vecs[0]) == 2:
        mat = Matrix.Identity(3)
        bb_size = Vector((0, 0))

        indices = convex_hull_2d(vecs, eps)
        if r_indices:
            r_indices[:] = indices

        if len(indices) == 1:
            mat.col[2][:2] = vecs[0]
        elif len(indices) == 2:
            v1 = vecs[indices[0]]
            v2 = vecs[indices[1]]
            xaxis = (v2 - v1).normalized()
            angle = math.atan2(xaxis[1], xaxis[0])
            mat2 = Matrix.Rotation(angle, 2)
            mat.col[0][:2] = mat2.col[0]
            mat.col[1][:2] = mat2.col[1]
            mat.col[2][:2] = (v1 + v2) / 2
            bb_size[0] = (v2 - v1).length
        else:
            yaxis = _closest_axis_on_plane(vecs, indices)
            angle = math.atan2(yaxis[1], yaxis[0]) - math.pi / 2  # X軸
            mat2 = Matrix.Rotation(angle, 2)
            imat2 = Matrix.Rotation(-angle, 2)
            rotvecs = [imat2 * v for v in vecs]
            loc = Vector((0, 0))
            for i in range(2):
                rotvecs.sort(key=lambda v: v[i])
                bb_size[i] = rotvecs[-1][i] - rotvecs[0][i]
                loc[i] = (rotvecs[0][i] + rotvecs[-1][i]) / 2
            mat.col[0][:2] = mat2.col[0]
            mat.col[1][:2] = mat2.col[1]
            mat.col[2][:2] = mat2 * loc
        return mat, bb_size

    # 3D ----------------------------------------------------------------------
    mat = Matrix.Identity(4)
    bb_size = Vector((0, 0, 0))

    indices = convex_hull(vecs, eps)

    if r_indices:
        r_indices[:] = indices

    if isinstance(indices[0], int):  # 2d
        if len(indices) == 1:
            mat.col[3][:3] = vecs[0]
            return mat, bb_size
        
        elif len(indices) == 2:
            # 同一線上
            v1 = vecs[indices[0]]
            v2 = vecs[indices[1]]
            xaxis = (v2 - v1).normalized()
            quat = Vector((1, 0, 0)).rotation_difference(xaxis)
            mat = quat.to_matrix().to_4x4()
            mat.col[3][:3] = (v1 + v2) / 2
            bb_size[0] = (v2 - v1).length
            return mat, bb_size

        else:
            # 同一平面上
            medium = reduce(lambda a, b: a + b, vecs) / len(vecs)
            v1 = max(vecs, key=lambda v: (v - medium).length)
            v2 = max(vecs, key=lambda v: (v - v1).length)
            line = v2 - v1
            v3 = max(vecs, key=lambda v: line.cross(v - v1).length)
            zaxis = geom.normal(v1, v2, v3)
            if zaxis[2] < 0.0:
                zaxis.negate()

            quat = zaxis.rotation_difference(Vector((0, 0, 1)))
            rotvecs = [quat * v for v in vecs]
            indices_2d = indices

    else:  # 3d
        indices_set = set(chain(*indices))
        zaxis = None
        dist = 0.0
        # 最も距離の近い面(平面)と頂点を求める
        for tri in indices:
            v1, v2, v3 = [vecs[i] for i in tri]
            normal = geom.normal(v1, v2, v3)
            d = 0.0
            for v4 in (vecs[i] for i in indices_set if i not in tri):
                f = abs(geom.distance_point_to_plane(v4, v1, normal))
                d = max(f, d)
            if zaxis is None or d < dist:
                zaxis = -normal
                dist = d

        quat = zaxis.rotation_difference(Vector((0, 0, 1)))
        rotvecs = [(quat * v).to_2d() for v in vecs]
        indices_2d = convex_hull_2d(rotvecs, eps)

    yaxis = _closest_axis_on_plane(rotvecs, indices_2d)
    yaxis = quat.inverted() * yaxis.to_3d()

    xaxis = yaxis.cross(zaxis)
    xaxis.normalize()  # 不要?

    mat.col[0][:3] = xaxis
    mat.col[1][:3] = yaxis
    mat.col[2][:3] = zaxis

    # OBBの大きさと中心を求める
    imat = mat.inverted()
    rotvecs = [imat * v for v in vecs]
    loc = Vector()
    for i in range(3):
        rotvecs.sort(key=lambda v: v[i])
        bb_size[i] = rotvecs[-1][i] - rotvecs[0][i]
        loc[i] = (rotvecs[0][i] + rotvecs[-1][i]) / 2
    mat.col[3][:3] = mat * loc
    return mat, bb_size
Example #3
0
def OBB(vecs, r_indices=None, eps=1e-6):
    """Convex hull を用いたOBBを返す。
    Z->Y->Xの順で長さが最少となる軸を求める。
    :param vecs: list of Vector
    :type vecs: list | tuple
    :param r_indices: listを渡すとconvexhullの結果を格納する
    :type r_indices: None | list
    :param eps: 種々の計算の閾値
    :return:
        (matrix, obb_size)
        matrix:
            type: Matrx
            OBBの回転と中心を表す。vecsが二次元ベクトルの場合は3x3, 三次元なら4x4。
        obb_size:
            type: Vector
            OBBの各軸の長さ。vecsと同じ次元。
    :rtype: (Matrix, Vector)
    """

    if not vecs:
        return None, None

    # 2D ----------------------------------------------------------------------
    if len(vecs[0]) == 2:
        mat = Matrix.Identity(3)
        bb_size = Vector((0, 0))

        indices = convex_hull_2d(vecs, eps)
        if r_indices:
            r_indices[:] = indices

        if len(indices) == 1:
            mat.col[2][:2] = vecs[0]
        elif len(indices) == 2:
            v1 = vecs[indices[0]]
            v2 = vecs[indices[1]]
            xaxis = (v2 - v1).normalized()
            angle = math.atan2(xaxis[1], xaxis[0])
            mat2 = Matrix.Rotation(angle, 2)
            mat.col[0][:2] = mat2.col[0]
            mat.col[1][:2] = mat2.col[1]
            mat.col[2][:2] = (v1 + v2) / 2
            bb_size[0] = (v2 - v1).length
        else:
            yaxis = _closest_axis_on_plane(vecs, indices)
            angle = math.atan2(yaxis[1], yaxis[0]) - math.pi / 2  # X軸
            mat2 = Matrix.Rotation(angle, 2)
            imat2 = Matrix.Rotation(-angle, 2)
            rotvecs = [imat2 * v for v in vecs]
            loc = Vector((0, 0))
            for i in range(2):
                rotvecs.sort(key=lambda v: v[i])
                bb_size[i] = rotvecs[-1][i] - rotvecs[0][i]
                loc[i] = (rotvecs[0][i] + rotvecs[-1][i]) / 2
            mat.col[0][:2] = mat2.col[0]
            mat.col[1][:2] = mat2.col[1]
            mat.col[2][:2] = mat2 * loc
        return mat, bb_size

    # 3D ----------------------------------------------------------------------
    mat = Matrix.Identity(4)
    bb_size = Vector((0, 0, 0))

    indices = convex_hull(vecs, eps)

    if r_indices:
        r_indices[:] = indices

    if isinstance(indices[0], int):  # 2d
        if len(indices) == 1:
            mat.col[3][:3] = vecs[0]
            return mat, bb_size

        elif len(indices) == 2:
            # 同一線上
            v1 = vecs[indices[0]]
            v2 = vecs[indices[1]]
            xaxis = (v2 - v1).normalized()
            quat = Vector((1, 0, 0)).rotation_difference(xaxis)
            mat = quat.to_matrix().to_4x4()
            mat.col[3][:3] = (v1 + v2) / 2
            bb_size[0] = (v2 - v1).length
            return mat, bb_size

        else:
            # 同一平面上
            medium = reduce(lambda a, b: a + b, vecs) / len(vecs)
            v1 = max(vecs, key=lambda v: (v - medium).length)
            v2 = max(vecs, key=lambda v: (v - v1).length)
            line = v2 - v1
            v3 = max(vecs, key=lambda v: line.cross(v - v1).length)
            zaxis = geom.normal(v1, v2, v3)
            if zaxis[2] < 0.0:
                zaxis.negate()

            quat = zaxis.rotation_difference(Vector((0, 0, 1)))
            rotvecs = [quat * v for v in vecs]
            indices_2d = indices

    else:  # 3d
        indices_set = set(chain(*indices))
        zaxis = None
        dist = 0.0
        # 最も距離の近い面(平面)と頂点を求める
        for tri in indices:
            v1, v2, v3 = [vecs[i] for i in tri]
            normal = geom.normal(v1, v2, v3)
            d = 0.0
            for v4 in (vecs[i] for i in indices_set if i not in tri):
                f = abs(geom.distance_point_to_plane(v4, v1, normal))
                d = max(f, d)
            if zaxis is None or d < dist:
                zaxis = -normal
                dist = d

        quat = zaxis.rotation_difference(Vector((0, 0, 1)))
        rotvecs = [(quat * v).to_2d() for v in vecs]
        indices_2d = convex_hull_2d(rotvecs, eps)

    yaxis = _closest_axis_on_plane(rotvecs, indices_2d)
    yaxis = quat.inverted() * yaxis.to_3d()

    xaxis = yaxis.cross(zaxis)
    xaxis.normalize()  # 不要?

    mat.col[0][:3] = xaxis
    mat.col[1][:3] = yaxis
    mat.col[2][:3] = zaxis

    # OBBの大きさと中心を求める
    imat = mat.inverted()
    rotvecs = [imat * v for v in vecs]
    loc = Vector()
    for i in range(3):
        rotvecs.sort(key=lambda v: v[i])
        bb_size[i] = rotvecs[-1][i] - rotvecs[0][i]
        loc[i] = (rotvecs[0][i] + rotvecs[-1][i]) / 2
    mat.col[3][:3] = mat * loc
    return mat, bb_size
Example #4
0
    def execute(self, context):
        active = context.active_object

        bm = bmesh.from_edit_mesh(active.data)
        bm.normal_update()

        selverts = [v for v in bm.verts if v.select]
        selfaces = [f for f in bm.faces if f.select]

        if selfaces:
            boundary = get_boundary_edges(selfaces)
            sequences = get_edges_vert_sequences(selverts,
                                                 boundary,
                                                 debug=False)

            # if there are 2 sequences
            if len(sequences) == 2:
                seq1, seq2 = sequences

                verts1, cyclic1 = seq1
                verts2, cyclic2 = seq2

                if self.flip:
                    verts1, verts2 = verts2, verts1
                    cyclic1, cyclic2 = cyclic2, cyclic1

                # if they are both cyclic and have the same amount of verts,and at least 5
                if cyclic1 == cyclic2 and cyclic1 is True and len(
                        verts1) == len(verts2) and len(verts1) >= 5:
                    smooth = selfaces[0].smooth

                    if smooth:
                        active.data.use_auto_smooth = True

                    # deselect verts
                    for v in verts1 + verts2:
                        v.select_set(False)

                    bm.select_flush(False)

                    # set amount of segments
                    self.segments = len(verts1)

                    # get selection mid points
                    center1 = average_locations([v.co for v in verts1])
                    center2 = average_locations([v.co for v in verts2])

                    # get the radii, and set the radius as an average
                    radius1 = (center1 - verts1[0].co).length
                    radius2 = (center2 - verts2[0].co).length
                    self.radius = (radius1 + radius2) / 2

                    # create point coordinates and face indices
                    thread, bottom, top, height = calculate_thread(
                        segments=self.segments,
                        loops=self.loops,
                        radius=self.radius,
                        depth=self.depth / 100,
                        h1=self.h1,
                        h2=self.h2,
                        h3=self.h3,
                        h4=self.h4,
                        fade=self.fade / 100)

                    if height != 0:

                        # build the faces from those coords and indices
                        verts, faces = self.build_faces(bm,
                                                        thread,
                                                        bottom,
                                                        top,
                                                        smooth=smooth)

                        # scale the thread geometry to fit the selection height
                        selheight = (center1 - center2).length
                        bmesh.ops.scale(bm,
                                        vec=Vector((1, 1, selheight / height)),
                                        space=Matrix(),
                                        verts=verts)

                        # move the thread geometry into alignment with the first selection center
                        bmesh.ops.translate(bm,
                                            vec=center1,
                                            space=Matrix(),
                                            verts=verts)

                        # then rotate it into alignment too, this is done in two steps, first the up vectors are aligned
                        selup = (center2 - center1).normalized()

                        selrot = Vector((0, 0, 1)).rotation_difference(selup)
                        bmesh.ops.rotate(bm,
                                         cent=center1,
                                         matrix=selrot.to_matrix(),
                                         verts=verts,
                                         space=Matrix())

                        # then the first verts are aligned too, get the first vert from the active face if its part of the selection
                        if bm.faces.active and bm.faces.active in selfaces:
                            active_loops = [
                                loop for v in bm.faces.active.verts
                                if v in verts1 for loop in v.link_loops
                                if loop.face == bm.faces.active
                            ]

                            if active_loops[
                                    0].link_loop_next.vert == active_loops[
                                        1].vert:
                                v1 = active_loops[1].vert
                            else:
                                v1 = active_loops[0].vert
                        else:
                            v1 = verts1[0]

                        threadvec = verts[0].co - center1
                        selvec = v1.co - center1

                        matchrot = threadvec.rotation_difference(
                            selvec).normalized()
                        bmesh.ops.rotate(bm,
                                         cent=center1,
                                         matrix=matchrot.to_matrix(),
                                         verts=verts,
                                         space=Matrix())

                        # remove doubles
                        bmesh.ops.remove_doubles(bm,
                                                 verts=verts + verts1 + verts2,
                                                 dist=0.00001)

                        # remove the initially selected faces
                        bmesh.ops.delete(bm, geom=selfaces, context='FACES')

                        # recalculate the normals, usefull when doing inverted thread
                        bmesh.ops.recalc_face_normals(
                            bm, faces=[f for f in faces if f.is_valid])

                        bmesh.update_edit_mesh(active.data)
                    return {'FINISHED'}
        return {'CANCELLED'}
Example #5
0
    def checkFire(self, tembak):
        now = datetime.datetime.now()
        jarak = now - self.lastTimeOfFire

        if tembak == 2:
            #print("trying to fire weapon {0} with time a : {1} and time b : {2}".format(self.name, str(jarak.seconds), str(self.reloadTime)))
            if self.mag > -1:
                if self.ammo > 0:
                    interval = rTimeLeft(jarak, self.interval)
                    if interval <= 0:
                        projectile = None
                        if self.shootOneByOne == False:
                            for barrel in self.barrelsDeviation:
                                if self.hideBarrelAfterShot == True:
                                    barrel.parent.visible = False
                                #print("dp scene ialah " + self.scene.name + " dengan objek " + self.self.name)
                                #ator dp deviation
                                nx = random.random() * self.deviation
                                nx = nx - self.deviation / 2
                                nz = random.random() * self.deviation
                                nz = nz - self.deviation / 2
                                deviation = Euler((nx, 0.0, nz))
                                #print([nx, ny, nz, self.deviation])
                                na = barrel.parent.worldOrientation
                                #na.rotate(deviation)
                                eul = Vector(na.to_euler()) + Vector(deviation)
                                eul = Euler(eul)
                                barrel.worldOrientation = eul.to_matrix()
                                #cek = deviation, na.to_euler(), barrel.worldOrientation.to_euler()
                                #print(cek)
                                projectile = self.scene.addObject(
                                    self.shell, barrel, self.timeToLive)
                        else:
                            barrel = self.barrelsDeviation[
                                self.currentBarrelIndex]
                            if self.hideBarrelAfterShot == True:
                                barrel.parent.visible = False
                            nx = random.random() * self.deviation
                            nx = nx - self.deviation / 2
                            nz = random.random() * self.deviation
                            nz = nz - self.deviation / 2
                            deviation = Euler((nx, 0.0, nz))
                            na = barrel.parent.worldOrientation
                            eul = Vector(na.to_euler()) + Vector(deviation)
                            eul = Euler(eul)
                            barrel.worldOrientation = eul.to_matrix()
                            #print("dp scene ialah " + self.scene.name + " dengan objek " + self.self.name)
                            projectile = self.scene.addObject(
                                self.shell, barrel, self.timeToLive)
                            '''
							if 'type' in projectile:
								if projectile['type'] == "heatSeekingMissile":
									projectile = KX_SeekingMissile(projectile)
								else:
									projectile = KX_Projectile(projectile)
							else:
								projectile = KX_Projectile(projectile)
							self.ammo -= 1
							#print('dp putput = ' + str(self.output))
							#print("dp velocity = " + str(self.velocity))
							projectile.localLinearVelocity = Vector((self.output.x * self.velocity + self.heldBy.localLinearVelocity.x, self.output.y * self.velocity + self.heldBy.localLinearVelocity.y, self.output.z * self.velocity + self.heldBy.localLinearVelocity.z))
							#print('projectile has been shot with speed = {0}'.format(projectile.localLinearVelocity))
							self.lastTimeOfFire = datetime.datetime.now()
							projectile.shotWith = self.name
							projectile.shotBy = self.heldBy
							projectile.scaling = Vector(self.scale)
							projectile.target = self.target
							'''

                            pb = len(self.barrelsDeviation)
                            if pb > 1:
                                self.currentBarrelIndex += 1
                                if self.currentBarrelIndex > pb - 1:
                                    self.currentBarrelIndex = 0
                                #rint(self.currentBarrelIndex)
                        if projectile != None:
                            if 'type' in projectile:
                                if projectile['type'] == "heatSeekingMissile":
                                    projectile = gameobjects.KX_SeekingMissile(
                                        projectile)
                                    projectile.target = self.lockedTo
                                    projectile.lockOnStatus = self.lockOnStatus
                                else:
                                    projectile = gameobjects.KX_Projectile(
                                        projectile)
                            else:
                                projectile = gameobjects.KX_Projectile(
                                    projectile)
                            self.ammo -= 1
                            projectile.localLinearVelocity += Vector(
                                (self.output.x * self.velocity +
                                 self.heldBy.localLinearVelocity.x,
                                 self.output.y * self.velocity +
                                 self.heldBy.localLinearVelocity.y,
                                 self.output.z * self.velocity +
                                 self.heldBy.localLinearVelocity.z))
                            #print('projectile has been shot with speed = {0}'.format(projectile.localLinearVelocity))
                            projectile.lastVelocity = projectile.worldLinearVelocity
                            self.lastTimeOfFire = datetime.datetime.now()
                            projectile.shotWith = self.name
                            projectile.shotBy = self.heldBy
                            projectile.scaling = Vector(self.scale)
                            self.shootCount += 1
        if self.ammo == 0:
            if self.reloadStatus == "standBy":
                self.reloadStatus = "gonnaReload"

        if self.reloadStatus == "awal":
            self.mag -= 1
            self.reloadStatus = "standBy"
        if self.reloadStatus == "gonnaReload":
            self.lastTimeOfFire = datetime.datetime.now()
            jarak = now - self.lastTimeOfFire
            self.reloadTimeLeft = rTimeLeft(jarak, self.reloadTime)
            self.reloadStatus = "isReloading"
        if self.reloadStatus == "isReloading":
            jarak = now - self.lastTimeOfFire
            self.reloadTimeLeft = rTimeLeft(jarak, self.reloadTime)
            if self.reloadTimeLeft <= 0.0:
                self.reloadStatus = "reloaded"
        if self.reloadStatus == "reloaded":
            if self.mag > 0:
                self.mag -= 1
                self.ammo = self.ammoSize
            if self.mag == 0 and self.ammo == 0:
                self.reloadStatus = "abis"
            else:
                self.reloadStatus = "standBy"
                if self.hideBarrelAfterShot == True:
                    for barrel in self.barrels:
                        barrel.visible = True