Example #1
0
def GetBestViewAxis(context):
    #Gets the axis closest to cameras view vector.
    region = context.region
    rv3d = context.region_data
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, (region.width/2.0, region.height/2.0))    
    xAxis = Vector((1, 0, 0))
    yAxis = Vector((0, 1, 0))
    zAxis = Vector((0, 0, 1))
    a1 = xAxis.angle(view_vector)
    a1d = abs((a1 * 180 / 3.14) - 90)
    a2 = yAxis.angle(view_vector)
    a2d = abs((a2 * 180 / 3.14) - 90)
    a3 = zAxis.angle(view_vector)
    a3d = abs((a3 * 180 / 3.14) - 90)
    
    A = max(a1d, a2d,a3d)
    
    if A == a1d:
        dir = -1
        if a1 * 180 / 3.14 > 90:
            dir = 1
        return Vector((dir, 0, 0)), 'X', abs((a1 * 180 / 3.14) - 90)
    if A == a2d:
        dir = -1
        if a2 * 180 / 3.14 > 90:
            dir = 1
        return Vector((0, dir, 0)), 'Y', abs((a2 * 180 / 3.14) - 90)
    if A == a3d:
        dir = -1
        if a3 * 180 / 3.14 > 90:
            dir = 1
        return Vector((0, 0, dir)), 'Z', abs((a3 * 180 / 3.14) - 90)
Example #2
0
def draw_arrow_head(ob, vecFrom, vecTo):
    if ob is None:
        return

    direction = Vector(vecTo) - Vector(vecFrom)
    print(direction)
    # direction.resize_2d()
    # print(direction)
    angle = direction.angle(Vector((0, 1, 0)))

    # form a 2d rotation matrix
    mat = Matrix().Rotation(angle, 2)

    # middle point
    middle = (Vector(vecTo) + Vector(vecFrom)) / 2.0

    bgl.glEnable(bgl.GL_BLEND)
    bgl.glBegin(bgl.GL_LINE_STRIP)
    for v in arrow_head:
        xy = Vector(v) * 1.0 * mat
        xy.resize_3d()
        newPos = xy + middle
        bgl.glVertex3f(*newPos)
        bgl.glLineWidth(2)
        bgl.glColor4f(0.0, 0.0, 0.0, 0.5)
    bgl.glEnd()
Example #3
0
def Circle(name = 'Circle',
         size = (1., 1.),
         subdivisions = 32,
         normal = None,
         fill_type = 'NOTHING',
         location = (0., 0., 0.),
         rotation = (0., 0., 0.),
         *args, **kw):

    if size == None:
        scale = (1., 1., 1.)
    elif isinstance(size, (float, int)):
        scale = (size, size, 1.)
    elif hasattr(size, "__iter__"):
        scale = (size[0], size[1], 1.)


    if normal:
        vector = Vector(normal)
        zaxis = Vector([0.,0.,1.])
        angle = zaxis.angle(vector)
        axis = zaxis.cross(vector)
        rotation = mathutils.Matrix.Rotation(angle, 4, axis).to_euler()


    bpy.ops.mesh.primitive_circle_add(
        vertices=int(subdivisions), radius=1.,
        location=Vector(location), rotation=Vector(rotation) ) #, \
        #layers=[True]+[False]*19)
    obj = Mesh(Blender.active_object)
    obj.name = name
    if Blender.auto_shade_smooth():
        obj.shade_smooth()

    return obj
Example #4
0
def Cone(name = 'Cone',
         vector = (0.,0.,1.),
         radius1 = 1., radius2 = 0.,
         subdivisions = 32,
         end_fill_type = 'NGON',
         location = (0., 0., 0.),
         *args, **kw):

    vector = Vector(vector)
    zaxis = Vector([0.,0.,1.])
    angle = zaxis.angle(vector)
    axis = zaxis.cross(vector)
    rotation = mathutils.Matrix.Rotation(angle, 4, axis).to_euler()

    bpy.ops.mesh.primitive_cone_add(
        vertices=int(subdivisions),
        radius1=float(radius1), radius2=float(radius2), \
        location=Vector(location), rotation=Vector(rotation), \
        end_fill_type=end_fill_type, \
        depth=float(vector.length) )#, layers=[True]+[False]*19)
    obj = Mesh(Blender.active_object)
    obj.name = name
    if Blender.auto_shade_smooth():
        obj.shade_smooth()

    return obj
    def test_orthogonal(self):

        angle_90d = math.pi / 2.0
        for v in vector_data:
            v = Vector(v)
            if v.length_squared != 0.0:
                self.assertAlmostEqual(v.angle(v.orthogonal()), angle_90d)
def get_rotation_quaternion_from_normal(normal: mathutils.Vector):
    """
    Construct the rotation quaternion to rotate the specified normal vector
    onto the (0.0, 0.0, 1.0) vector

    :param normal: The normal vector used to construct the rotation quaternion

    :returns: The rotation quaternion to align the normal with the z-axis
    """
    vec_z = mathutils.Vector((0.0, 0.0, 1.0))
    theta = normal.angle(vec_z)  # angle
    axis = normal.cross(vec_z)  # axis
    axis.normalize()

    sin_theta = math.sin(theta / 2.0)
    q_rot = mathutils.Quaternion((math.cos(theta / 2.0), axis.x * sin_theta,
                                  axis.y * sin_theta, axis.z * sin_theta))

    q_norm = mathutils.Quaternion((0.0, normal.x, normal.y, normal.z))
    rot = q_rot * q_norm * q_rot.conjugated()

    print(normal)
    print(axis)
    print(mathutils.Vector((rot.x, rot.y, rot.z)))

    return q_rot
Example #7
0
    def viewrotate_apply(self, context, event):
        # FIXME
        vod = self.vod
        x, y = event.x, event.y
        if context.user_preferences.inputs.view_rotate_method == 'TRACKBALL':
            newvec = calctrackballvec(context.region, event.x, event.y)
            dvec = newvec - vod.trackvec
            angle = (dvec.length / (2.0 * TRACKBALLSIZE)) * math.pi
            angle = angle_wrap_rad(angle)

            axis = vod.trackvec.cross(newvec)
            q1 = Quaternion(axis, angle)
            vod.viewquat = q1 * vod.oldquat

            self.viewrotate_apply_dyn_ofs(vod.viewquat)
        else:
            zvec_global = Vector([0, 0, 1])
            sensitivity = 0.007
            m = vod.viewquat.to_matrix()
            m_inv = m.inverted()

            if (zvec_global - m_inv.col[2]).length > 0.001:
                xaxis = zvec_global.closs(m_inv.col[0])
                if xaxis.dot(m_inv.col[0]) < 0:
                    xaxis.negate()
                fac = zvec_global.angle(m_inv.col[2]) / math.pi
                fac = abs(fac - 0.5) * 2
                fac *= fac
                xaxis = xaxis.lerp(m_inv.col[0], fac)
            else:
                xaxis = m_inv[0].copy()
            quat_local_x = Quaternion(xaxis, sensitivity * - (y - vod.oldy))
            quat_local_x = vod.viewquat * quat_local_x

            def axis_angle_to_quat_single(axis, angle):
                angle_half = angle * 0.5
                angle_cos = math.cos(angle_half)
                angle_sin = math.sin(angle_half)
                axis_index = ['X', 'Y', 'Z'].index(axis)
                q = Quaternion([angle_cos, 0, 0, 0])
                q[axis_index + 1] = angle_sin
                return q
            quat_global_z = axis_angle_to_quat_single(
                'Z', sensitivity * vod.reverse * (x - vod.oldx))
            vod.viewquat = quat_local_x * quat_global_z

            self.viewrotate_apply_dyn_ofs(vod.viewquat)

        vod.viewquat.normalize()
        context.region_data.view_rotation = vod.viewquat.inverted()
        if vod.axis_snap:
            self.viewrotate_apply_snap(vod)

        vod.oldx = x
        vod.oldy = y

        ED_view3d_camera_lock_sync(vod.v3d, context.region_data)

        context.region.tag_redraw()
        pass
    def sort(self):

        # align to Y axis
        align_axis = Vector((0, 1))

        rotated_faces = []
        for face in self.faces:
            edge = face.getLongestEdge()
            edge_vector = Vector(edge[1]) - Vector(edge[0])

            # change vector direction to positive
            if edge[0][0] > edge[1][0]:
                edge_vector = Vector(edge[0]) - Vector(edge[1])

            angle = align_axis.angle(edge_vector)
            face.rotate(angle, 'center')
            center = face.getCenter()
            edge = face.getLongestEdge()

            # rotate the way that all other vertices is on the right side
            if edge[0][0] > center[0]:
                face.rotate(math.radians(180), 'center')

            # aligh to Y axis
            edge = face.getLongestEdge()
            point = Vector(edge[1])
            target = Vector((self.x, self.y))
            face.translate(point, target)

            rotated_faces.append(face)

        self.faces = rotated_faces
Example #9
0
def getScreenLookAxis(context, location=None):
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = region.width / 2.0, region.height / 2.0
    if (location is not None):
        coord = view3d_utils.location_3d_to_region_2d(region, rv3d, location)

    if (not coord):
        return Vector((0.0, 0.0, 0.0)), 0


#     depth = Vector((0.0, 0.0, 0.0));
#     origin = 0.0, 0.0;
#     down = 0.0, 1.0;
#     right = 1.0, 0.0;

#     o_vector = view3d_utils.region_2d_to_location_3d(region, rv3d, origin, depth_location=depth);
#     r_vector = view3d_utils.region_2d_to_location_3d(region, rv3d, right, depth_location=depth) - o_vector;
#     d_vector = view3d_utils.region_2d_to_location_3d(region, rv3d, down, depth_location=depth) - o_vector;

#     r_vector.normalize();
#     d_vector.normalize();
#     print('VIEW VECTOR ::: ', o_vector, r_vector, d_vector);
    base_view = Vector((0.0, 1.0, 0.0))
    #     base_view = Vector((0.0, 0.0, 1.0));
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
    view_vector.normalize()

    axis = base_view.cross(view_vector)
    angle = base_view.angle(view_vector)

    axis.normalize()

    return axis, math.degrees(angle)
Example #10
0
    def test_orthogonal(self):

        angle_90d = math.pi / 2.0
        for v in vector_data:
            v = Vector(v)
            if v.length_squared != 0.0:
                self.assertAlmostEqual(v.angle(v.orthogonal()), angle_90d)
Example #11
0
def set_body_position_orientation():
    """ Le point '18' est au centre de [8, 11] soit au centre du bassin.
    Il ne vient pas de COCO !
    Le bone spine suit les rotation de 18 sur Z
    """
    # Position 8 à droite 11 à gauche
    if gl.points[8] and gl.points[11]:

        x = (gl.spheres[8].worldPosition[0] +
             gl.spheres[11].worldPosition[0]) / 2
        y = (gl.spheres[8].worldPosition[1] +
             gl.spheres[11].worldPosition[1]) / 2
        z = (gl.spheres[8].worldPosition[2] +
             gl.spheres[11].worldPosition[2]) / 2

        gl.spheres[18].worldPosition = [x, y, z]
        gl.spheres[18].worldScale = [
            1.5 * gl.scale, 1.5 * gl.scale, 1.5 * gl.scale
        ]

    # Rotation: direction = de 11 à 8
    if gl.points[8] and gl.points[11]:
        try:
            a = gl.spheres[8].worldPosition
            b = gl.spheres[11].worldPosition
            direction = (b - a).normalized()
            axis_align = Vector((1.0, 0.0, 0.0))
            angle = axis_align.angle(direction)
            axis = axis_align.cross(direction)
            quat = Quaternion(axis, angle)
            gl.spheres[18].localOrientation = quat.to_euler('XYZ')
        except:
            pass
Example #12
0
def apply_objet_position_orientation(objet_point_1, objet_point_2, objet):
    """Valable pour un objet seulement.
    objet_point_1, objet_point_2 sont 2 objets Blender:
        ils définissent un vecteur.
    L'objet objet est orienté suivant ce vecteur,
        si objet_point_2 n'est pas None
    et positionné en objet_point_1.
    """

    if objet_point_2:
        try:
            a = objet_point_1.worldPosition
            b = objet_point_2.worldPosition

            direction = (b - a).normalized()
            axis_align = Vector((1.0, 0.0, 0.0))

            angle = axis_align.angle(direction)
            axis = axis_align.cross(direction)

            quat = Quaternion(axis, angle)
            objet.localOrientation = quat.to_euler('XYZ')

            sc = (b - a).length
            # Les coefficients correspondent à la taille des objects cube
            # qui représentent les os
            objet.localScale = [
                sc * 5 * gl.scale, 0.2 * gl.scale, 0.2 * gl.scale
            ]
        except:
            pass

    # Apply position
    objet.worldPosition = objet_point_1.worldPosition
 def is_bmvert_collinear(self, v):
     le = v.link_edges
     if len(le) == 2:
         vec1 = Vector(v.co - le[0].other_vert(v).co)
         vec2 = Vector(v.co - le[1].other_vert(v).co)
         if abs(vec1.angle(vec2)) >= 3.1415:
             return True
     return False
Example #14
0
    def draw_gems(self, context, ratio_w=1, ratio_h=1):
        from_scene_scale = unit.Scale(context).from_scene

        view_normal = Vector((0.0, 0.0, 1.0)) @ self.region_3d.view_matrix
        angle_thold = pi / 1.8

        fontid = 0
        blf.size(fontid, self.prefs.view_font_size_gem_size, 72)
        blf.color(fontid, 0.0, 0.0, 0.0, 1.0)

        shader = gpu.shader.from_builtin("2D_UNIFORM_COLOR")
        depsgraph = context.depsgraph

        for dup in depsgraph.object_instances:

            if dup.is_instance:
                ob = dup.instance_object.original
            else:
                ob = dup.object.original

            if "gem" not in ob or (self.use_select and not ob.select_get()):
                continue

            shader.bind()

            ob_stone = ob["gem"]["stone"]
            ob_cut = ob["gem"]["cut"]
            ob_size = tuple(round(x, 2) for x in from_scene_scale(ob.dimensions, batch=True))

            for stone, cut, size, size_fmt, color in self.gems_raw:
                if ob_stone == stone and ob_cut == cut and ob_size == size:
                    shader.uniform_float("color", color)
                    break

            me = ob.to_mesh(depsgraph, True)
            me.transform(dup.matrix_world)
            verts = me.vertices

            for poly in me.polygons:
                if view_normal.angle(poly.normal) < angle_thold:
                    cos = [
                        loc_3d_to_2d(self.region, self.region_3d, verts[v].co, ratio_w, ratio_h)
                        for v in poly.vertices
                    ]
                    batch = batch_for_shader(shader, "TRI_FAN", {"pos": cos})
                    batch.draw(shader)

            bpy.data.meshes.remove(me)

            # Size
            # -----------------------------

            ob_loc = dup.matrix_world.translation.to_tuple()
            loc_x, loc_y = loc_3d_to_2d(self.region, self.region_3d, ob_loc, ratio_w, ratio_h)
            dim_x, dim_y = blf.dimensions(fontid, size_fmt)

            blf.position(fontid, loc_x - dim_x / 2, loc_y - dim_y / 2, 0.0)
            blf.draw(fontid, size_fmt)
Example #15
0
def func_constrain_axis_mmb(self, context, key, value, angle):
    if len(self.tab) > 1:
        angle = 0
    if key == 'MIDDLEMOUSE':
        if value == 'PRESS':
            if self.handle_axes == None:
                args = (self, context, angle)
                self.handle_axes = bpy.types.SpaceSequenceEditor.draw_handler_add(
                    draw_axes, args, 'PREVIEW', 'POST_PIXEL')
            self.choose_axis = True
            self.pos_clic = self.mouse_pos
        if value == 'RELEASE':
            self.choose_axis = False
            if self.pos_clic == self.mouse_pos:
                self.axis_x = self.axis_y = True
                if self.handle_axes:
                    bpy.types.SpaceSequenceEditor.draw_handler_remove(
                        self.handle_axes, 'PREVIEW')
                    self.handle_axes = None
    if self.choose_axis:
        vec_axis_z = Vector((0, 0, 1))
        vec_axis_x = Vector((1, 0, 0))
        vec_axis_x.rotate(Quaternion(vec_axis_z, math.radians(angle)))
        vec_axis_x = vec_axis_x.to_2d()
        vec_axis_y = Vector((0, 1, 0))
        vec_axis_y.rotate(Quaternion(vec_axis_z, math.radians(angle)))
        vec_axis_y = vec_axis_y.to_2d()

        ang_x = math.degrees(
            vec_axis_x.angle(self.mouse_pos - self.center_area))
        ang_y = math.degrees(
            vec_axis_y.angle(self.mouse_pos - self.center_area))

        if ang_x > 90:
            ang_x = 180 - ang_x
        if ang_y > 90:
            ang_y = 180 - ang_y

        if ang_x < ang_y:
            self.axis_x = True
            self.axis_y = False
        else:
            self.axis_x = False
            self.axis_y = True
Example #16
0
def sun_animation_points(gravity_direction: Vector, north_direction: Vector,
                         scene_bbox: Vector, radius: float,
                         points_count: int) -> List[Vector]:
    """Sample sun lamp position points.

    Arguments:
        gravity_direction {Vector} -- world's gravity direction vector
        north_direction {Vector} -- world's north direction vector
        scene_center {Vector} -- current scene center
        radius {float} -- radius of the animation
        points_count {int} -- desired number of points

    Raises:
        ValueError: if gravity and north directions aren't orthogonal

    Returns:
        List[Vector] -- list of animation points
    """

    # TODO add more realistic sun paths using geolocation and seasons ?

    # sanity check: axes must be orthogonal
    angle = round(gravity_direction.angle(north_direction), 2)
    if angle != round((pi / 2), 2):
        msg = "`gravity_direction` and `north_direction` aren't orthogonal (angle={})!".format(
            degrees(angle))
        logger.error(msg)
        raise ValueError(msg)

    center = scene_bbox.floor_center  # scene_center
    # get the half-vector
    h = -gravity_direction - north_direction
    h.normalize()
    # get the rotation axis
    axis = h.copy()
    axis.rotate(Quaternion(north_direction.cross(gravity_direction), pi / 2))

    b = h.copy()
    b.rotate(Quaternion(axis, pi / 2))

    pts = []
    for i in range(points_count * 2):
        theta = 2 * pi * (i / (points_count * 2))

        # circle
        x = center.x + radius * cos(theta) * b.x + radius * sin(theta) * h.x
        y = center.y + radius * cos(theta) * b.y + radius * sin(theta) * h.y
        z = center.z + radius * cos(theta) * b.z + radius * sin(theta) * h.z
        if z > scene_bbox.z_min:
            continue

        p = Vector((x, y, z)) - center
        pts.append(p)
        #bpy.ops.mesh.primitive_uv_sphere_add(radius=0.01, location=p)

    return pts
Example #17
0
def get_direction_of_verts(a, b):
    direction = (a - b).normalized()
    axis_align = Vector((0.0, 0.0, 1.0))

    angle = axis_align.angle(direction)
    axis = axis_align.cross(direction)

    q = Quaternion(axis, angle)

    return q.to_euler('XYZ')
def set_bonded(atom,b):
    """Sets the positions of all atoms bonded to atom.
    
    atom: Atom object
    rotate: Boolean defining whether or not to rotate tetrahedron around the z-axis
    b: bond length
    """
    x = 0
    y = 0
    z = 0
    b = b*sqrt(atom.radius)
    
    bonds = atom.bonds
    
    #Differences in position between central atom and bonded atom
    for item in bonds:
        if isinstance(item, Atom):
            x = atom.pos[0] - item.pos[0]
            y = atom.pos[1] - item.pos[1]
            z = atom.pos[2] - item.pos[2]
            break
   
    n = math.radians(109.5)
    n2 = pi*2/3

    #Represents tetrahedron base centered at (0,0,0)
    v1 = Vector((b*sin(n),0,b*cos(n)))
    v2 = Vector((b*cos(n2),b*sin(n2),b*cos(n)))
    v3 = Vector((b*cos(2*n2),b*sin(2*n2),b*cos(n)))
    
    offset = (Vector((atom.pos)))

    top= Vector((0,0,-b))
    diff = Vector((x,y,z))

    axis = top.cross(diff)
    a = -(top.angle(diff, 0))
    
    m = Matrix.Rotation(a,3,axis)
    #Rotates the tetrahedron base to align itself with the starting vector
    v1 = v1*m
    v2 = v2*m
    v3 = v3*m
    
    #Sets the positions of bonded atoms to locations in the tetrahedron, scales bond lengths and moves tetrahedron
    if len(bonds) >1:
        if isinstance(bonds[1], Atom):
            bonds[1].pos = v1*sqrt(bonds[1].radius)+offset
    if len(bonds) >2:
        if isinstance(bonds[2], Atom):
            bonds[2].pos = v2*sqrt(bonds[2].radius)+offset
    if len(bonds)>3:
        if isinstance(bonds[3],Atom):
            bonds[3].pos = v3*sqrt(bonds[3].radius)+offset
Example #19
0
    def calcFaceByNormal(self, points, normal, face):
        a = [ t - u for t,u in zip(points[1], points[0])]   # vector a = point[1] - point[0]
        b = [ t - u for t,u in zip(points[2], points[0])]   # vector b = point[2] - point[0]
        # normal = a x b = (a2b3-a3b2)i-(a1b3-a3b1)j+(a1b2-a2b1)k.
        myNormal = Vector([a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0]])
        angle = myNormal.angle(Vector(normal))

        # if vectors are in opposite direction change points order
        if angle > math.pi/2 or angle < -math.pi/2:
            return (face[1], face[0], face[2])
        return face
def getValues():
    '''Return mesh data values (z, slope or az) for classification'''
    scn = bpy.context.scene
    obj = bpy.context.view_layer.objects.active
    #make a temp mesh with modifiers apply
    #mesh = obj.data #modifiers not apply
    mesh = obj.to_mesh(scn, apply_modifiers=True, settings='PREVIEW')
    mesh.transform(obj.matrix_world)
    #
    mode = scn.analysisMode
    if mode == 'HEIGHT':
        values = [vertex.co.z for vertex in mesh.vertices]
    elif mode == 'SLOPE':
        z = Vector((0, 0, 1))
        m = obj.matrix_world
        values = [
            math.degrees(z.angle(m * face.normal)) for face in mesh.polygons
        ]
    elif mode == 'ASPECT':
        y = Vector((0, 1, 0))
        m = obj.matrix_world
        #values =  [math.degrees(y.angle(m * face.normal)) for face in mesh.polygons]
        values = []
        for face in mesh.polygons:
            normal = face.normal.copy()
            normal.z = 0  #project vector into XY plane
            try:
                a = math.degrees(y.angle(m * normal))
            except ValueError:
                pass  #zero length vector as no angle
            else:
                #returned angle is between 0° (north) to 180° (south)
                #we must correct it to get angle between 0 to 360°
                if normal.x < 0:
                    a = 360 - a
                values.append(a)
    values.sort()
    #remove temp mesh
    bpy.data.meshes.remove(mesh)

    return values
Example #21
0
def getValues():
	'''Return mesh data values (z, slope or az) for classification'''
	scn = bpy.context.scene
	obj = scn.objects.active
	#make a temp mesh with modifiers apply
	#mesh = obj.data #modifiers not apply
	mesh = obj.to_mesh(scn, apply_modifiers=True, settings='PREVIEW')
	mesh.transform(obj.matrix_world)
	#
	mode = scn.analysisMode
	if mode == 'HEIGHT':
		values = [vertex.co.z for vertex in mesh.vertices]
	elif mode == 'SLOPE':
		z = Vector((0,0,1))
		m = obj.matrix_world
		values =  [math.degrees(z.angle(m * face.normal)) for face in mesh.polygons]
	elif mode == 'ASPECT':
		y = Vector((0,1,0))
		m = obj.matrix_world
		#values =  [math.degrees(y.angle(m * face.normal)) for face in mesh.polygons]
		values = []
		for face in mesh.polygons:
			normal = face.normal.copy()
			normal.z = 0 #project vector into XY plane
			try:
				a = math.degrees(y.angle(m * normal))
			except ValueError:
				pass#zero length vector as no angle
			else:
				#returned angle is between 0° (north) to 180° (south)
				#we must correct it to get angle between 0 to 360°
				if normal.x <0:
					a = 360 - a
				values.append(a)
	values.sort()
	#remove temp mesh
	bpy.data.meshes.remove(mesh)

	return values
    def calcRotAngle(self, axis, nor_x, nor_y, nor_z):
        theta = 0
        vector_z = Vector((0.0, 0.0, 1.0))
        vector_n = None
        vector_cross = None

        if axis == 'X':
            vector_n = Vector((0.0, nor_y, nor_z))
            theta = vector_z.angle(vector_n, 999)
            vector_cross = vector_n.cross(vector_z)
            if vector_cross.x < 0:
                theta = -(theta)
        elif axis == 'Y':
            vector_n = Vector((nor_x, 0.0, nor_z))
            theta = vector_z.angle(vector_n, 999)
            vector_cross = vector_n.cross(vector_z)
            if vector_cross.y < 0:
                theta = -(theta)
        else:
            pass

        return theta
    def calcRotAngle(self, axis, nor_x, nor_y, nor_z):
        theta = 0
        vector_z = Vector((0.0, 0.0, 1.0))
        vector_n = None
        vector_cross = None

        if axis == 'X':
            vector_n = Vector((0.0, nor_y, nor_z))
            theta = vector_z.angle(vector_n, 999)
            vector_cross = vector_n.cross(vector_z)
            if vector_cross.x < 0:
                theta = -(theta)
        elif axis == 'Y':
            vector_n = Vector((nor_x, 0.0, nor_z))
            theta = vector_z.angle(vector_n, 999)
            vector_cross = vector_n.cross(vector_z)
            if vector_cross.y < 0:
                theta = -(theta)
        else:
            pass

        return theta
Example #24
0
def vec_roll_to_mat3(vec, roll):
    target = Vector((0, 1, 0))
    nor = vec.normalized()
    axis = target.cross(nor)
    if axis.dot(axis) > 0.000001:
        axis.normalize()
        theta = target.angle(nor)
        bMatrix = Matrix.Rotation(theta, 3, axis)
    else:
        updown = 1 if target.dot(nor) > 0 else -1
        bMatrix = Matrix.Scale(updown, 3)
    rMatrix = Matrix.Rotation(roll, 3, nor)
    mat = rMatrix * bMatrix
    return mat
def get_angle_signed(v1: Vector, v2: Vector, n: Vector) -> float:
    # Implementing this idea:
    # https://math.stackexchange.com/questions/1027476/calculating-clockwise-anti-clockwise-angles-from-a-point
    matrix: Matrix = Matrix((v1, v2, n))
    matrix.transpose()
    det = matrix.determinant()
    angle = v1.angle(v2)

    if det < 0:  # clockwise
        return angle
    elif det > 0:  # anticlockwise
        return -angle
    else:
        return 0
Example #26
0
def vec_roll_to_mat3(vec, roll):
	target = Vector((0,1,0))
	nor = vec.normalized()
	axis = target.cross(nor)
	if axis.dot(axis) > 0.000001:
		axis.normalize()
		theta = target.angle(nor)
		bMatrix = Matrix.Rotation(theta, 3, axis)
	else:
		updown = 1 if target.dot(nor) > 0 else -1
		bMatrix = Matrix.Scale(updown, 3)
	rMatrix = Matrix.Rotation(roll, 3, nor)
	mat = rMatrix * bMatrix
	return mat
Example #27
0
def vec_roll_to_quat(vec, roll):
    vec.normalize()
    target = Vector((0, 1, 0))
    axis = target.cross(vec)
    if (axis.dot(axis) > 1.0e-9):
        axis.normalize
        theta = target.angle(vec)
        q = Quaternion(axis, theta)
    else:
        if (dot(axis, vec) > 0):
            q = Quaternion()
        else:
            q = Quaternion((0, 0, 0, 1))
    q_roll = Quaternion(vec, roll)
    return q_roll * q
Example #28
0
def vec_roll_to_mat3(vec, roll):
    target = Vector((0, 0.1, 0))
    nor = vec.normalized()
    axis = target.cross(nor)
    if axis.dot(axis) > 0.0000000001: # this seems to be the problem for some bones, no idea how to fix
        axis.normalize()
        theta = target.angle(nor)
        bMatrix = Matrix.Rotation(theta, 3, axis)
    else:
        updown = 1 if target.dot(nor) > 0 else -1
        bMatrix = Matrix.Scale(updown, 3)               
        bMatrix[2][2] = 1.0

    rMatrix = Matrix.Rotation(roll, 3, nor)
    mat = rMatrix @ bMatrix
    return mat
Example #29
0
def getScreenLookAxis(context):
    scene = context.scene
    region = context.region
    rv3d = context.region_data
    coord = region.width/2.0, region.height/2.0;
    
    base_view = Vector((0.0, 1.0, 0.0));
#     base_view = Vector((0.0, 0.0, -1.0));
    view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord);
    view_vector.normalize();
    
    axis = base_view.cross(view_vector);
    angle = base_view.angle(view_vector);
#     print('VIEW VECTOR ::: ', view_vector);
    axis.normalize();
    
    return axis, math.degrees(angle);    
Example #30
0
def generate_facet_data(verts, faces, face_color, vector_light):
    out_verts = []
    out_vcols = []
    concat_verts = out_verts.extend
    concat_vcols = out_vcols.extend
    for face in faces:
        vecs = [verts[j] for j in face]
        concat_verts(vecs)

        normal_no = Vector(normal(*vecs))
        normal_no = (normal_no.angle(vector_light, 0)) / pi

        r = (normal_no * face_color[0]) - 0.1
        g = (normal_no * face_color[1]) - 0.1
        b = (normal_no * face_color[2]) - 0.1
        vcol = (r + 0.2, g + 0.2, b + 0.2, 1.0)
        concat_vcols([vcol, vcol, vcol])

    return out_verts, out_vcols
Example #31
0
def too_unwarp(obj):
    dg = bpy.context.evaluated_depsgraph_get()
    lq = obj.evaluated_get(dg)
    cam = bpy.data.objects['Camera']
    ng = bpy.context.evaluated_depsgraph_get()
    cq = cam.evaluated_get(ng)
    cam_direction = cq.matrix_world.to_quaternion() @ Vector((0.0, 0.0, -1.0))
    mat = lq.matrix_world
    nos = []
    for v in lq.data.vertices:
        nos.append(mat @ v.normal)
    mean = Vector(np.mean(nos, axis=0))
    for v in nos:
        ndc = mean.angle(v)
        if ndc > math.radians(70):
            return False
    if cam_direction.angle(mean) < math.radians(110):
        return False
    return True
def compute_edge_angles_degrees(ob,ids):
    me = ob.data    
    # Get a BMesh representation
    bm = bmesh.new()   # create an empty BMesh
    bm.from_mesh(me)   # fill it in from a Mesh
    all_angles = []
    all_degrees = np.zeros_like(ids)
    
    for i, id in enumerate(ids):
        edges = []
        prev_edge=0
        #print("Searching all edges for vert: ", id)
        
        for edge in bm.edges:
            if (edge.verts[0].index == id or edge.verts[1].index == id):
                #print("edge found:", edge)
                edges.append(edge)
                if (isVisibleEdge(edge,ids)):
                    all_degrees[i]+=1    
            else:
                continue  
            
        for edge in edges:        
            if (prev_edge == 0):
                prev_edge = edge
                continue
            #print("edge pair: ", prev_edge, edge) #edge.verts[0].index
            v00 = edge.verts[0]     
            v01 = edge.verts[1]    
            v10 = prev_edge.verts[0]     
            v11 = prev_edge.verts[1]
            v0 = Vector(v00.co) - Vector(v01.co)
            v1 = Vector(v10.co) - Vector(v11.co)
            #print("Angle: ", math.degrees(v0.angle(v1))) 
            all_angles.append(v0.angle(v1))   
            prev_edge = edge
            
    #print("All degrees: ",all_degrees)        
    return all_angles, all_degrees         
Example #33
0
    def from_other(cls, obj):
        """Constructs a Spherical object from a Quaternion, Euler, or Matrix rotation object from the mathutils library.
        """
        if type(obj) is cls:
            return obj
        obj = to_quat(obj)

        # first, rotate the +Z unit vector by the object to replicate the effect of rot_quat without roll_quat
        z_axis = Vector((0, 0, 1))
        z_axis.rotate(obj)
        # calculate the inverse of rot_quat, which is the rotation that moves the new position of the unit vector to
        # its original position on the +Z axis
        inv_rot_quat = Quaternion(z_axis.cross(Vector((0, 0, 1))),
                                  z_axis.angle(Vector((0, 0, 1))))
        # extract roll_quat by left-multiplying by the inverse of rot_quat
        roll_quat = inv_rot_quat @ obj

        # calculate theta and phi from the new position of the unit vector, as well as roll directly from roll_quat
        theta = np.arctan2(z_axis.y, z_axis.x)
        phi = np.arccos(np.clip(z_axis.z, -1, 1))
        roll = roll_quat.to_euler().z - theta
        return cls(theta, phi, roll)
Example #34
0
def extrude(bm,faces,m_x,m_y,m_z):
    operat_faces=faces
    n = Vector((0,0,0))
    for i in operate_faces:
        #print("face:",i.normal)
        n += i.normal

    r = bmesh.ops.extrude_face_region(bm,geom=operate_faces)

    verts = [e for e in r['geom'] if isinstance(e, bmesh.types.BMVert)]
    faces = [e for e in r['geom'] if isinstance(e, bmesh.types.BMFace)]
    
    clear_select(bm)
    
    z = mathutils.Vector((0,0,1))
    axis = n.cross(z)
    angle = n.angle(z)
    R = mathutils.Matrix.Rotation(angle,4,axis)
    bmesh.ops.translate(bm, vec = Vector((m_x,m_y,m_z)),space=R,verts = verts )
    bmesh.ops.delete(bm, geom=operate_faces, context=5)
    
    return faces
    def modal_rotate_tool(self, context, eventd):
        cx,cy = self.action_center
        mx,my = eventd['mouse']
        px,py = self.prev_pos #mode_pos

        if eventd['press'] in {'RET', 'NUMPAD_ENTER', 'LEFTMOUSE'}:
            self.tool_fn('commit', eventd)
            return 'main'

        if eventd['press'] in {'ESC', 'RIGHTMOUSE'}:
            self.tool_fn('undo', eventd)
            return 'main'

        if eventd['type'] == 'MOUSEMOVE':
            vp = Vector((px-cx,py-cy,0))
            vm = Vector((mx-cx,my-cy,0))
            ang = vp.angle(vm) * (-1 if vp.cross(vm).z<0 else 1)
            self.tool_rot += ang
            self.tool_fn(self.tool_rot, eventd)
            self.prev_pos = (mx,my)
            return ''

        return ''
Example #36
0
def DEF_atom_pdb_main(use_mesh,Ball_azimuth,Ball_zenith,
               Ball_radius_factor,radiustype,Ball_distance_factor,
               use_stick,Stick_sectors,Stick_diameter,put_to_center,
               use_camera,use_lamp,path_datafile):

    # The list of all atoms as read from the PDB file.
    all_atoms  = []

    # The list of all sticks.
    all_sticks = []

    # List of materials
    atom_material_list = []

    # A list of ALL objects which are loaded (needed for selecting the loaded
    # structure.
    atom_object_list = []


    # ------------------------------------------------------------------------
    # INITIALIZE THE ELEMENT LIST

    ATOM_PDB_ELEMENTS[:] = []

    for item in ATOM_PDB_ELEMENTS_DEFAULT:

        # All three radii into a list
        radii = [item[4],item[5],item[6]]
        # The handling of the ionic radii will be done later. So far, it is an
        # empty list.
        radii_ionic = []

        li = CLASS_atom_pdb_Elements(item[0],item[1],item[2],item[3],
                                     radii,radii_ionic)
        ATOM_PDB_ELEMENTS.append(li)


    # ------------------------------------------------------------------------
    # READING DATA OF ATOMS


    if DEF_atom_pdb_custom_datafile(path_datafile):
        print("Custom data file is loaded.")

    # Open the file ...
    ATOM_PDB_FILEPATH_p = io.open(ATOM_PDB_FILEPATH, "r")

    #Go to the line, in which "ATOM" or "HETATM" appears.
    for line in ATOM_PDB_FILEPATH_p:
        split_list = line.split(' ')
        if "ATOM" in split_list[0]:
            break
        if "HETATM" in split_list[0]:
            break

    j = 0
    # This is in fact an endless 'while loop', ...
    while j > -1:

        # ... the loop is broken here (EOF) ...
        if line == "":
            break

        # If there is a "TER" we need to put empty entries into the lists
        # in order to not destroy the order of atom numbers and same numbers
        # used for sticks. "TER? What is that?" TER indicates the end of a
        # list of ATOM/HETATM records for a chain.
        if "TER" in line:
            short_name = "TER"
            name = "TER"
            radius = 0.0
            color = [0,0,0]
            location = Vector((0,0,0))
            # Append the TER into the list. Material remains empty so far.
            all_atoms.append(CLASS_atom_pdb_atom(short_name,
                                                 name,
                                                 location,
                                                 radius,
                                                 color,[]))
        # If 'ATOM or 'HETATM' appears in the line then do ...
        elif "ATOM" in line or "HETATM" in line:

            # What follows is due to deviations which appear from PDB to
            # PDB file. It is very special. PLEASE, DO NOT CHANGE! From here ...
            short_name = line[13:14]
            if short_name.isupper() == True:
                if line[14:15].islower() == True:
                    short_name = short_name + line[14:15]
            else:
                short_name = line[12:13]
                if short_name.isupper() == True:
                    if line[13:14].islower() == True:
                        short_name = short_name + line[13:14]
            # ... to here.

            # Go through all elements and find the element of the current atom.
            FLAG_FOUND = False
            for element in ATOM_PDB_ELEMENTS:
                if str.upper(short_name) == str.upper(element.short_name):
                    # Give the atom its proper names, color and radius:
                    short_name = str.upper(element.short_name)
                    name = element.name
                    # int(radiustype) => type of radius:
                    # pre-defined (0), atomic (1) or van der Waals (2)
                    radius = float(element.radii[int(radiustype)])
                    color = element.color
                    FLAG_FOUND = True
                    break

            # Is it a vacancy or an 'unknown atom' ?
            if FLAG_FOUND == False:
                # Give this atom also a name. If it is an 'X' then it is a
                # vacancy. Otherwise ...
                if "X" in short_name:
                    short_name = "VAC"
                    name = "Vacancy"
                    radius = float(ATOM_PDB_ELEMENTS[-3].radii[int(radiustype)])
                    color = ATOM_PDB_ELEMENTS[-3].color
                # ... take what is written in the PDB file. These are somewhat
                # unknown atoms. This should never happen, the element list is
                # almost complete. However, we do this due to security reasons.
                else:
                    short_name = str.upper(short_name)
                    name = str.upper(short_name)
                    radius = float(ATOM_PDB_ELEMENTS[-2].radii[int(radiustype)])
                    color = ATOM_PDB_ELEMENTS[-2].color

            # x,y and z are at fixed positions in the PDB file.
            x = float(line[30:38].rsplit()[0])
            y = float(line[38:46].rsplit()[0])
            z = float(line[46:55].rsplit()[0])

            location = Vector((x,y,z))

            j += 1

            # Append the atom to the list. Material remains empty so far.
            all_atoms.append(CLASS_atom_pdb_atom(short_name,
                                             name,
                                             location,
                                             radius,
                                             color,[]))

        line = ATOM_PDB_FILEPATH_p.readline()
        line = line[:-1]

    ATOM_PDB_FILEPATH_p.close()
    # From above it can be clearly seen that j is now the number of all atoms.
    Number_of_total_atoms = j


    # ------------------------------------------------------------------------
    # MATERIAL PROPERTIES FOR ATOMS


    # The list that contains info about all types of atoms is created
    # here. It is used for building the material properties for
    # instance (see below).
    atom_all_types_list = []

    for atom in all_atoms:
        FLAG_FOUND = False
        for atom_type in atom_all_types_list:
            # If the atom name is already in the list, FLAG on 'True'.
            if atom_type[0] == atom.name:
                FLAG_FOUND = True
                break
        # No name in the current list has been found? => New entry.
        if FLAG_FOUND == False:
            # Stored are: Atom label (e.g. 'Na'), the corresponding atom
            # name (e.g. 'Sodium') and its color.
            atom_all_types_list.append([atom.name, atom.element, atom.color])

    # The list of materials is built.
    # Note that all atoms of one type (e.g. all hydrogens) get only ONE
    # material! This is good because then, by activating one atom in the
    # Blender scene and changing the color of this atom, one changes the color
    # of ALL atoms of the same type at the same time.

    # Create first a new list of materials for each type of atom
    # (e.g. hydrogen)
    for atom_type in atom_all_types_list:
        material = bpy.data.materials.new(atom_type[1])
        material.name = atom_type[0]
        material.diffuse_color = atom_type[2]
        atom_material_list.append(material)

    # Now, we go through all atoms and give them a material. For all atoms ...
    for atom in all_atoms:
        # ... and all materials ...
        for material in atom_material_list:
            # ... select the correct material for the current atom via
            # comparison of names ...
            if atom.name in material.name:
                # ... and give the atom its material properties.
                # However, before we check, if it is a vacancy, because then it
                # gets some additional preparation. The vacancy is represented
                # by a transparent cube.
                if atom.name == "Vacancy":
                    material.transparency_method = 'Z_TRANSPARENCY'
                    material.alpha = 1.3
                    material.raytrace_transparency.fresnel = 1.6
                    material.raytrace_transparency.fresnel_factor = 1.6
                    material.use_transparency = True
                # The atom gets its properties.
                atom.material = material


    # ------------------------------------------------------------------------
    # READING DATA OF STICKS


    # Open the PDB file again such that the file pointer is in the first
    # line ... . Stupid, I know ... ;-)
    ATOM_PDB_FILEPATH_p = io.open(ATOM_PDB_FILEPATH, "r")

    split_list = line.split(' ')

    # Go to the first entry
    if "CONECT" not in split_list[0]:
        for line in ATOM_PDB_FILEPATH_p:
            split_list = line.split(' ')
            if "CONECT" in split_list[0]:
                break

    Number_of_sticks = 0
    sticks_double = 0
    j = 0
    # This is in fact an endless while loop, ...
    while j > -1:

        # ... which is broken here (EOF) ...
        if line == "":
            break
        # ... or here, when no 'CONECT' appears anymore.
        if "CONECT" not in line:
            break

        # The strings of the atom numbers do have a clear position in the file
        # (From 7 to 12, from 13 to 18 and so on.) and one needs to consider
        # this. One could also use the split function but then one gets into
        # trouble if there are many atoms: For instance, it may happen that one
        # has
        #                   CONECT 11111  22244444
        #
        # In Fact it means that atom No. 11111 has a connection with atom
        # No. 222 but also with atom No. 44444. The split function would give
        # me only two numbers (11111 and 22244444), which is wrong.

        # Cut spaces from the right and 'CONECT' at the beginning
        line = line.rstrip()
        line = line[6:]
        # Amount of loops
        length = len(line)
        loops  = int(length/5)

        # List of atoms
        atom_list = []
        for i in range(loops):
            number = line[5*i:5*(i+1)].rsplit()
            if number != []:
                if number[0].isdigit() == True:
                    atom_number = int(number[0])
                    atom_list.append(atom_number)

        # The first atom is connected with all the others in the list.
        atom1 = atom_list[0]

        # For all the other atoms in the list do:
        for each_atom in atom_list[1:]:

            # The second, third, ... partner atom
            atom2 = each_atom

            # Note that in a PDB file, sticks of one atom pair can appear a
            # couple of times. (Only god knows why ...)
            # So, does a stick between the considered atoms already exist?
            FLAG_BAR = False
            for k in range(Number_of_sticks):
                if ((all_sticks[k].atom1 == atom1 and all_sticks[k].atom2 == atom2) or
                    (all_sticks[k].atom2 == atom1 and all_sticks[k].atom1 == atom2)):
                    sticks_double += 1
                    # If yes, then FLAG on 'True'.
                    FLAG_BAR       = True
                    break

            # If the stick is not yet registered (FLAG_BAR == False), then
            # register it!
            if FLAG_BAR == False:
                all_sticks.append(CLASS_atom_pdb_stick(atom1,atom2))
                Number_of_sticks += 1
                j += 1

        line = ATOM_PDB_FILEPATH_p.readline()
        line = line.rstrip()

    ATOM_PDB_FILEPATH_p.close()
    # So far, all atoms and sticks have been registered.


    # ------------------------------------------------------------------------
    # TRANSLATION OF THE STRUCTURE TO THE ORIGIN


    # It may happen that the structure in a PDB file already has an offset
    # If chosen, the structure is first put into the center of the scene
    # (the offset is substracted).

    if put_to_center == True:

        sum_vec = Vector((0.0,0.0,0.0))

        # Sum of all atom coordinates
        sum_vec = sum([atom.location for atom in all_atoms], sum_vec)

        # Then the average is taken
        sum_vec = sum_vec / Number_of_total_atoms

        # After, for each atom the center of gravity is substracted
        for atom in all_atoms:
            atom.location -= sum_vec


    # ------------------------------------------------------------------------
    # SCALING


    # Take all atoms and adjust their radii and scale the distances.
    for atom in all_atoms:
        atom.location *= Ball_distance_factor


    # ------------------------------------------------------------------------
    # DETERMINATION OF SOME GEOMETRIC PROPERTIES


    # In the following, some geometric properties of the whole object are
    # determined: center, size, etc.
    sum_vec = Vector((0.0,0.0,0.0))

    # First the center is determined. All coordinates are summed up ...
    sum_vec = sum([atom.location for atom in all_atoms], sum_vec)

    # ... and the average is taken. This gives the center of the object.
    object_center_vec = sum_vec / Number_of_total_atoms

    # Now, we determine the size.The farest atom from the object center is
    # taken as a measure. The size is used to place well the camera and light
    # into the scene.
    object_size_vec = [atom.location - object_center_vec for atom in all_atoms]
    object_size = 0.0
    object_size = max(object_size_vec).length


    # ------------------------------------------------------------------------
    # CAMERA AND LAMP

    camera_factor = 15.0

    # If chosen a camera is put into the scene.
    if use_camera == True:

        # Assume that the object is put into the global origin. Then, the
        # camera is moved in x and z direction, not in y. The object has its
        # size at distance math.sqrt(object_size) from the origin. So, move the
        # camera by this distance times a factor of camera_factor in x and z.
        # Then add x, y and z of the origin of the object.
        object_camera_vec = Vector((math.sqrt(object_size) * camera_factor,
                                    0.0,
                                    math.sqrt(object_size) * camera_factor))
        camera_xyz_vec = object_center_vec + object_camera_vec

        # Create the camera
        current_layers=bpy.context.scene.layers
        bpy.ops.object.camera_add(view_align=False, enter_editmode=False,
                               location=camera_xyz_vec,
                               rotation=(0.0, 0.0, 0.0), layers=current_layers)
        # Some properties of the camera are changed.
        camera = bpy.context.scene.objects.active
        camera.name = "A_camera"
        camera.data.name = "A_camera"
        camera.data.lens = 45
        camera.data.clip_end = 500.0

        # Here the camera is rotated such it looks towards the center of
        # the object. The [0.0, 0.0, 1.0] vector along the z axis
        z_axis_vec             = Vector((0.0, 0.0, 1.0))
        # The angle between the last two vectors
        angle                  = object_camera_vec.angle(z_axis_vec, 0)
        # The cross-product of z_axis_vec and object_camera_vec
        axis_vec               = z_axis_vec.cross(object_camera_vec)
        # Rotate 'axis_vec' by 'angle' and convert this to euler parameters.
        # 4 is the size of the matrix.
        euler                  = Matrix.Rotation(angle, 4, axis_vec).to_euler()
        camera.rotation_euler  = euler

        # Rotate the camera around its axis by 90° such that we have a nice
        # camera position and view onto the object.
        bpy.ops.transform.rotate(value=(90.0*2*math.pi/360.0,),
                                 axis=object_camera_vec,
                                 constraint_axis=(False, False, False),
                                 constraint_orientation='GLOBAL',
                                 mirror=False, proportional='DISABLED',
                                 proportional_edit_falloff='SMOOTH',
                                 proportional_size=1, snap=False,
                                 snap_target='CLOSEST', snap_point=(0, 0, 0),
                                 snap_align=False, snap_normal=(0, 0, 0),
                                 release_confirm=False)


        # This does not work, I don't know why.
        #
        #for area in bpy.context.screen.areas:
        #    if area.type == 'VIEW_3D':
        #        area.spaces[0].region_3d.view_perspective = 'CAMERA'


    # Here a lamp is put into the scene, if chosen.
    if use_lamp == True:

        # This is the distance from the object measured in terms of %
        # of the camera distance. It is set onto 50% (1/2) distance.
        lamp_dl = math.sqrt(object_size) * 15 * 0.5
        # This is a factor to which extend the lamp shall go to the right
        # (from the camera  point of view).
        lamp_dy_right = lamp_dl * (3.0/4.0)

        # Create x, y and z for the lamp.
        object_lamp_vec = Vector((lamp_dl,lamp_dy_right,lamp_dl))
        lamp_xyz_vec = object_center_vec + object_lamp_vec

        # Create the lamp
        current_layers=bpy.context.scene.layers
        bpy.ops.object.lamp_add (type = 'POINT', view_align=False,
                                 location=lamp_xyz_vec,
                                 rotation=(0.0, 0.0, 0.0),
                                 layers=current_layers)
        # Some properties of the lamp are changed.
        lamp = bpy.context.scene.objects.active
        lamp.data.name = "A_lamp"
        lamp.name = "A_lamp"
        lamp.data.distance = 500.0
        lamp.data.energy = 3.0
        lamp.data.shadow_method = 'RAY_SHADOW'

        bpy.context.scene.world.light_settings.use_ambient_occlusion = True
        bpy.context.scene.world.light_settings.ao_factor = 0.2


    # ------------------------------------------------------------------------
    # SOME OUTPUT ON THE CONSOLE


    print()
    print()
    print()
    print(ATOM_PDB_STRING)
    print()
    print("Total number of atoms   : " + str(Number_of_total_atoms))
    print("Total number of sticks  : " + str(Number_of_sticks))
    print("Center of object        : ", object_center_vec)
    print("Size of object          : ", object_size)
    print()


    # ------------------------------------------------------------------------
    # SORTING THE ATOMS


    # Lists of atoms of one type are created. Example:
    # draw_all_atoms = [ data_hydrogen,data_carbon,data_nitrogen ]
    # data_hydrogen = [["Hydrogen", Material_Hydrogen, Vector((x,y,z)), 109], ...]

    draw_all_atoms = []

    # Go through the list which contains all types of atoms. It is the list,
    # which has been created on the top during reading the PDB file.
    # Example: atom_all_types_list = ["hydrogen", "carbon", ...]
    for atom_type in atom_all_types_list:

        # Don't draw 'TER atoms'.
        if atom_type[0] == "TER":
            continue

        # This is the draw list, which contains all atoms of one type (e.g.
        # all hydrogens) ...
        draw_all_atoms_type = []

        # Go through all atoms ...
        for atom in all_atoms:
            # ... select the atoms of the considered type via comparison ...
            if atom.name == atom_type[0]:
                # ... and append them to the list 'draw_all_atoms_type'.
                draw_all_atoms_type.append([atom.name,
                                           atom.material,
                                           atom.location,
                                           atom.radius])

        # Now append the atom list to the list of all types of atoms
        draw_all_atoms.append(draw_all_atoms_type)


    # ------------------------------------------------------------------------
    # DRAWING THE ATOMS


    # This is the number of all atoms which are put into the scene.
    bpy.ops.object.select_all(action='DESELECT')

    # For each list of atoms of ONE type (e.g. Hydrogen)
    for draw_all_atoms_type in draw_all_atoms:

        # Create first the vertices composed of the coordinates of all
        # atoms of one type
        atom_vertices = []
        for atom in draw_all_atoms_type:
            # In fact, the object is created in the World's origin.
            # This is why 'object_center_vec' is substracted. At the end
            # the whole object is translated back to 'object_center_vec'.
            atom_vertices.append( atom[2] - object_center_vec )

        # Build the mesh
        atom_mesh = bpy.data.meshes.new("Mesh_"+atom[0])
        atom_mesh.from_pydata(atom_vertices, [], [])
        atom_mesh.update()
        new_atom_mesh = bpy.data.objects.new(atom[0], atom_mesh)
        bpy.context.scene.objects.link(new_atom_mesh)

        # Now, build a representative sphere (atom)
        current_layers=bpy.context.scene.layers

        if atom[0] == "Vacancy":
            bpy.ops.mesh.primitive_cube_add(
                            view_align=False, enter_editmode=False,
                            location=(0.0, 0.0, 0.0),
                            rotation=(0.0, 0.0, 0.0),
                            layers=current_layers)
        else:
            # NURBS balls
            if use_mesh == False:
                bpy.ops.surface.primitive_nurbs_surface_sphere_add(
                            view_align=False, enter_editmode=False,
                            location=(0,0,0), rotation=(0.0, 0.0, 0.0),
                            layers=current_layers)
            # UV balls
            else:
                bpy.ops.mesh.primitive_uv_sphere_add(
                            segments=Ball_azimuth, ring_count=Ball_zenith,
                            size=1, view_align=False, enter_editmode=False,
                            location=(0,0,0), rotation=(0, 0, 0),
                            layers=current_layers)

        ball = bpy.context.scene.objects.active
        ball.scale  = (atom[3]*Ball_radius_factor,) * 3

        if atom[0] == "Vacancy":
            ball.name = "Cube_"+atom[0]
        else:
            ball.name = "Ball (NURBS)_"+atom[0]
        ball.active_material = atom[1]
        ball.parent = new_atom_mesh
        new_atom_mesh.dupli_type = 'VERTS'
        # The object is back translated to 'object_center_vec'.
        new_atom_mesh.location = object_center_vec
        atom_object_list.append(new_atom_mesh)

    print()


    # ------------------------------------------------------------------------
    # DRAWING THE STICKS


    if use_stick == True and all_sticks != []:

        # Create a new material with the corresponding color. The
        # color is taken from the all_atom list, it is the last entry
        # in the data file (index -1).
        bpy.ops.object.material_slot_add()
        stick_material = bpy.data.materials.new(ATOM_PDB_ELEMENTS[-1].name)
        stick_material.diffuse_color = ATOM_PDB_ELEMENTS[-1].color

        vertices = []
        faces    = []
        dl = 0.2

        i = 0
        # For all sticks, do ...
        for stick in all_sticks:

            # What follows is school mathematics! :-)
            v1 = all_atoms[stick.atom2-1].location
            v2 = all_atoms[stick.atom1-1].location

            dv = (v1 - v2)

            n  = dv / dv.length
            # m  = v1 - dv / 2.0  # UNUSED

            gamma = -n * v1
            b     = v1 + gamma * n
            n_b   = b / b.length

            loops = int(dv.length / dl)

            for j in range(loops):

                g = v1 - n * dl / 2.0 - n * dl * j

                p1 = g + n_b * Stick_diameter
                p2 = g - n_b * Stick_diameter
                p3 = g - n_b.cross(n) * Stick_diameter
                p4 = g + n_b.cross(n) * Stick_diameter

                vertices.append(p1)
                vertices.append(p2)
                vertices.append(p3)
                vertices.append(p4)
                faces.append((i*4+0,i*4+2,i*4+1,i*4+3))
                i += 1

        mesh = bpy.data.meshes.new("Sticks")
        mesh.from_pydata(vertices, [], faces)
        mesh.update()
        new_mesh = bpy.data.objects.new("Sticks", mesh)
        bpy.context.scene.objects.link(new_mesh)

        current_layers = bpy.context.scene.layers
        stick_cylinder = DEF_atom_pdb_build_stick(Stick_diameter, dl, Stick_sectors)


        stick_cylinder.active_material = stick_material
        stick_cylinder.parent = new_mesh
        new_mesh.dupli_type = 'FACES'
        atom_object_list.append(new_mesh)


    # ------------------------------------------------------------------------
    # SELECT ALL LOADED OBJECTS
    bpy.ops.object.select_all(action='DESELECT')
    obj = None
    for obj in atom_object_list:
        obj.select = True

    # activate the last selected object (perhaps another should be active?)
    if obj:
        bpy.context.scene.objects.active = obj

    print("\n\nAll atoms (%d) and sticks (%d) have been drawn - finished.\n\n"
           % (Number_of_total_atoms,Number_of_sticks))


    return Number_of_total_atoms
Example #37
0
    def modal(self, context, event):
        context.area.tag_redraw()

        # Tooltip
        tooltip_text = "Shift: Scale Constraint; Ctrl+MouseWheel, Ctrl+Shift+MouseWheel, +-, Ctrl++, ctrl+-: Change Segments; Shift+LeftClick: Uniform Scale; C: CenterCursor; O: Orient on Surface; R: Rotate, S: Scale"
        context.area.header_text_set(tooltip_text)

        m_coords = event.mouse_region_x, event.mouse_region_y
        rv3d = context.region_data

        if event.type in {'MIDDLEMOUSE'}:
            # allow navigation
            return {'PASS_THROUGH'}

        elif event.type == 'O' and event.value == 'PRESS':
            if self.orient_on_surface:
                self.orient_on_surface = False
            else:
                self.orient_on_surface = True

            return {'RUNNING_MODAL'}

        elif event.type == 'C' and event.value == 'PRESS':
            if self.center_is_cursor:
                self.center_is_cursor = False
            else:
                self.center_is_cursor = True

            return {'RUNNING_MODAL'}

        elif event.type == 'M' and event.value == 'PRESS':
            if self.median_center:
                self.median_center = False
            else:
                self.median_center = True

            return {'RUNNING_MODAL'}

        elif event.type == 'R' and event.value == 'PRESS':
            if self.new_prim:
                if self.tool_mode == 'ROTATE':
                    self.tool_mode = self.tool_mode_before_deform
                    self.tool_mode_before_deform = None
                    return {'RUNNING_MODAL'}
                else:
                    self.deform_mouse_pos = m_coords
                    self.tool_mode_before_deform = self.tool_mode
                    self.tool_mode = 'ROTATE'
            else:
                return {'RUNNING_MODAL'}

            return {'RUNNING_MODAL'}

        elif event.type == 'S' and event.value == 'PRESS':
            if self.new_prim:
                if self.tool_mode == 'SCALE':
                    self.tool_mode = self.tool_mode_before_deform
                    self.tool_mode_before_deform = None
                    return {'RUNNING_MODAL'}
                else:
                    self.deform_mouse_pos = m_coords
                    self.tool_mode_before_deform = self.tool_mode
                    self.tool_mode = 'SCALE'
            else:
                return {'RUNNING_MODAL'}

            return {'RUNNING_MODAL'}

        elif event.type == 'Z' and event.value == 'PRESS' and event.ctrl:
            # delete object with Ctrl+Z
            if self.history_objects:
                del_obj = self.history_objects[-1][0]
                del self.history_objects[-1]

                # remove old primitive
                objs = bpy.data.objects
                objs.remove(objs[del_obj.name], True)

                self.new_prim = None
                self.hit_pos = None
                self.hit_dir = None
                self.prim_side_vec = None
                self.prim_front_vec = None

                self.tool_mode = 'IDLE'

                context.scene.update()
                context.area.tag_redraw()

            return {'RUNNING_MODAL'}


        elif event.type in {'WHEELUPMOUSE', 'WHEELDOWNMOUSE', 'NUMPAD_MINUS', 'MINUS', 'NUMPAD_PLUS', 'EQUAL'}:

            # just pass it if cloning
            if self.prim_type == 'Clone':
                if event.type in {'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
                    # allow navigation
                    return {'PASS_THROUGH'}
                else:
                    return {'RUNNING_MODAL'}

            # CHANGE SEGMENTS HERE
            if self.new_prim:
                if event.type in {'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:

                    if event.ctrl:
                        # Meka less/more segments
                        if event.type == 'WHEELUPMOUSE':
                            if self.prim_type == 'Sphere':
                                if event.shift:
                                    self.sphere_segments[1] = self.sphere_segments[1] + 1
                                else:
                                    self.sphere_segments[0] = self.sphere_segments[0] + 1

                            elif self.prim_type == 'Capsule':
                                if event.shift:
                                    self.capsule_segments[1] = self.capsule_segments[1] + 1
                                else:
                                    self.capsule_segments[0] = self.capsule_segments[0] + 1

                            else:
                                self.circle_segments[0] += 1
                        else:
                            if self.prim_type == 'Sphere':
                                if event.shift:
                                    self.sphere_segments[1] = self.sphere_segments[1] - 1
                                    self.sphere_segments[1] = max(self.sphere_segments[1], 3)
                                else:
                                    self.sphere_segments[0] = self.sphere_segments[0] - 1
                                    self.sphere_segments[0] = max(self.sphere_segments[0], 3)

                            elif self.prim_type == 'Capsule':
                                if event.shift:
                                    self.capsule_segments[1] = self.capsule_segments[1] - 1
                                    self.capsule_segments[1] = max(self.capsule_segments[1], 1)
                                else:
                                    self.capsule_segments[0] = self.capsule_segments[0] - 1
                                    self.capsule_segments[0] = max(self.capsule_segments[0], 3)

                            else:
                                self.circle_segments[0] -= 1
                                self.circle_segments[0] = max(self.circle_segments[0], 3)
                    else:
                        # allow navigation
                        return {'PASS_THROUGH'}

                elif event.type in {'NUMPAD_PLUS', 'EQUAL'} and event.value == 'PRESS':
                    if self.prim_type == 'Sphere':
                        if event.ctrl:
                            self.sphere_segments[1] = self.sphere_segments[1] + 1
                        else:
                            self.sphere_segments[0] = self.sphere_segments[0] + 1

                    elif self.prim_type == 'Capsule':
                        if event.ctrl:
                            self.capsule_segments[1] = self.capsule_segments[1] + 1
                        else:
                            self.capsule_segments[0] = self.capsule_segments[0] + 1

                    else:
                        self.circle_segments[0] += 1

                elif event.type in {'NUMPAD_MINUS', 'MINUS'} and event.value == 'PRESS':
                    if self.prim_type == 'Sphere':
                        if event.ctrl:
                            self.sphere_segments[1] = self.sphere_segments[1] - 1
                            self.sphere_segments[1] = max(self.sphere_segments[1], 3)
                        else:
                            self.sphere_segments[0] = self.sphere_segments[0] - 1
                            self.sphere_segments[0] = max(self.sphere_segments[0], 3)

                    elif self.prim_type == 'Capsule':
                        if event.ctrl:
                            self.capsule_segments[1] = self.capsule_segments[1] - 1
                            self.capsule_segments[1] = max(self.capsule_segments[1], 1)
                        else:
                            self.capsule_segments[0] = self.capsule_segments[0] - 1
                            self.capsule_segments[0] = max(self.capsule_segments[0], 3)

                    else:
                        self.circle_segments[0] -= 1
                        self.circle_segments[0] = max(self.circle_segments[0], 3)

                if self.prim_type in {'Sphere','Capsule'}:
                    del self.history_objects[-1]

                    # If Edit Mode
                    if self.edit_obj:
                        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

                    segments = self.sphere_segments
                    if self.prim_type == 'Capsule':
                        segments = self.capsule_segments

                    # Replace Object Primitive
                    if self.tool_mode == 'IDLE':
                        self.new_prim = replace_prim(self.new_prim, segments, self.prim_type, context)
                    else:
                        self.new_prim = replace_prim(self.new_prim, segments, 'Circle', context)

                    self.history_objects.append([self.new_prim, self.hit_pos])

                    # If Edit Mode
                    if self.edit_obj:
                        bpy.ops.object.select_all(action='DESELECT')
                        self.new_prim.show_wire = True
                        self.new_prim.show_all_edges = True
                        self.edit_obj.select = True
                        context.scene.objects.active = self.edit_obj
                        bpy.ops.object.mode_set(mode='EDIT', toggle=False)

                else:
                    del self.history_objects[-1]

                    # If Edit Mode
                    if self.edit_obj:
                        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

                    # Replace Object Primitive
                    if self.tool_mode == 'IDLE':
                        self.new_prim = replace_prim(self.new_prim, self.circle_segments, self.prim_type, context)
                    else:
                        if self.prim_type == 'Cube' or self.prim_type == 'Plane':
                            self.new_prim = replace_prim(self.new_prim, self.circle_segments, 'Plane', context)
                        else:
                            self.new_prim = replace_prim(self.new_prim, self.circle_segments, 'Circle', context)

                    self.history_objects.append([self.new_prim, self.hit_pos])

                    # If Edit Mode
                    if self.edit_obj:
                        bpy.ops.object.select_all(action='DESELECT')
                        self.new_prim.show_wire = True
                        self.new_prim.show_all_edges = True
                        self.edit_obj.select = True
                        context.scene.objects.active = self.edit_obj
                        bpy.ops.object.mode_set(mode='EDIT', toggle=False)

            else:
                # allow navigation
                return {'PASS_THROUGH'}

        # FINISH THE TOOL!
        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            # If Edit Mode. Join Primitives
            if self.edit_obj:
                bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
                bpy.ops.object.select_all(action='DESELECT')

                for his_obj in self.history_objects:
                    his_obj[0].select = True

                self.edit_obj.select = True
                context.scene.objects.active = self.edit_obj

                bpy.ops.object.join()
                bpy.ops.object.mode_set(mode='EDIT', toggle=False)            

            # For non Edit Mode
            else:
                #bpy.ops.object.select_all(action='DESELECT')
                cursor_origin = context.scene.cursor_location.copy()

                for his_obj in self.history_objects:
                    bpy.ops.object.select_all(action='DESELECT')
                    his_obj[0].select = True

                    # apply scale
                    if self.prim_type != 'Clone':
                        context.scene.objects.active = his_obj[0]
                        bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

                    # set object position to hit
                    if his_obj[0].location != his_obj[1]:
                        context.scene.cursor_location = his_obj[1].copy()
                        bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

                    # apply/fix rotation
                    if round(math.degrees(his_obj[0].rotation_euler.x)) in {-0.0, 0.0, 90.0, 180.0, -180.0, -90.0}:
                        if round(math.degrees(his_obj[0].rotation_euler.y)) in {-0.0, 0.0, 90.0, 180.0, -180.0, -90.0}:
                            if round(math.degrees(his_obj[0].rotation_euler.z)) in {-0.0, 0.0, 90.0, 180.0, -180.0, -90.0}:
                                bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)

                context.scene.cursor_location = cursor_origin
                bpy.ops.object.select_all(action='DESELECT')

            # clean
            clean(context, self)
            context.area.header_text_set()
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            self.tool_mode == 'IDLE'

            return {'FINISHED'}

        # LEFTMOUSE CLICK
        if event.type == 'LEFTMOUSE':
            if self.tool_mode in {'ROTATE', 'SCALE'}:
                return {'RUNNING_MODAL'}

            if self.tool_mode == 'IDLE' and event.value == 'PRESS':
                do_create_prim = False  # check if we found hit
                is_autoaxis = False

                # If Edit Mode
                if self.edit_obj:
                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

                # make raycast only one time!
                ray_result = ut_base.get_mouse_raycast(context, self.obj_matrices, m_coords)

                # If Edit Mode
                if self.edit_obj:
                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

                if ray_result[0] and self.orient_on_surface and not self.center_is_cursor:
                    self.hit_pos = ray_result[2].copy()
                    self.hit_dir = ray_result[1].copy().normalized()
                    do_create_prim = True
                else:
                    # make auto pick according to 3d cursor
                    if ray_result[0] and not self.orient_on_surface and not self.center_is_cursor:
                        ray_result_auto =  auto_pick(context, ray_result[2], event)
                    else:
                        ray_result_auto =  auto_pick(context, None, event)

                    if self.center_is_cursor:
                        self.hit_pos = context.scene.cursor_location
                    else:
                        self.hit_pos = ray_result_auto[0].copy()

                    self.hit_dir = ray_result_auto[1].copy().normalized()

                    do_create_prim = True
                    is_autoaxis = True

                # CREATE PRIMITIVE!
                if do_create_prim:

                    # If Edit Mode
                    if self.edit_obj:
                        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

                    # Do Create Primitive
                    if self.prim_type == 'Sphere':
                        new_prim = create_prim(context, event, self.hit_pos, self.hit_dir, self.sphere_segments, is_autoaxis, 'Circle', self)
                    elif self.prim_type == 'Capsule':
                        new_prim = create_prim(context, event, self.hit_pos, self.hit_dir, self.capsule_segments, is_autoaxis, 'Circle', self)
                    elif self.prim_type in {'Cube','Plane'}:
                        new_prim = create_prim(context, event, self.hit_pos, self.hit_dir, None, is_autoaxis, 'Plane', self)
                    elif self.prim_type == 'Clone':
                        new_prim = create_prim(context, event, self.hit_pos, self.hit_dir, None, is_autoaxis, 'Clone', self)
                    else:
                        new_prim = create_prim(context, event, self.hit_pos, self.hit_dir, self.circle_segments, is_autoaxis, 'Circle', self)

                    self.new_prim = new_prim[0]
                    self.history_objects.append([self.new_prim, self.hit_pos])
                    self.prim_side_vec = new_prim[1].copy()
                    self.prim_front_vec = new_prim[2].copy()
                    self.tool_mode = 'DRAW_1'

                    # If Edit Mode
                    if self.edit_obj:
                        bpy.ops.object.select_all(action='DESELECT')
                        self.new_prim.show_wire = True
                        self.new_prim.show_all_edges = True
                        self.edit_obj.select = True
                        context.scene.objects.active = self.edit_obj
                        bpy.ops.object.mode_set(mode='EDIT', toggle=False)

            # Change tool state to Draw_2. Create depth
            elif self.tool_mode == 'IDLE_2' and event.value == 'PRESS':
                # If Edit Mode
                if self.edit_obj:
                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

                # Replace Plane and Circle
                del self.history_objects[-1]
                if self.prim_type == 'Sphere':
                    self.new_prim = replace_prim(self.new_prim, self.sphere_segments, self.prim_type, context)
                elif self.prim_type == 'Capsule':
                    self.new_prim = replace_prim(self.new_prim, self.capsule_segments, self.prim_type, context)
                else:
                    self.new_prim = replace_prim(self.new_prim, self.circle_segments, self.prim_type, context)

                self.history_objects.append([self.new_prim, self.hit_pos])

                # If Edit Mode
                if self.edit_obj:
                    bpy.ops.object.select_all(action='DESELECT')
                    self.new_prim.show_wire = True
                    self.new_prim.show_all_edges = True
                    self.edit_obj.select = True
                    context.scene.objects.active = self.edit_obj
                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

                self.tool_mode = 'DRAW_2'

            if event.value == 'RELEASE':

                # change tool state. Wait for Draw_2 state
                if self.tool_mode == 'DRAW_1':

                    # set to IDLE if this is Plane Primitive
                    if self.prim_type in {'Plane', 'Circle', 'Clone'}:
                        self.tool_mode = 'IDLE'
                        return {'RUNNING_MODAL'}

                    if self.new_prim.scale[0] == 0 or self.new_prim.scale[1] == 0:
                        # remove primitive with 0,0,0 scale
                        objs = bpy.data.objects
                        del self.history_objects[-1]
                        objs.remove(objs[self.new_prim.name], True)
                        self.new_prim = None
                        self.prim_side_vec = None
                        self.prim_front_vec = None
                        self.tool_mode = 'IDLE'
                    else:
                        self.tool_mode = 'IDLE_2'

                else:
                    # go to standard state
                    self.tool_mode = 'IDLE'

        # TOOL WORK
        # Draw Primitive X and Y
        if self.tool_mode == 'DRAW_1':
            plane_pos = ut_base.get_mouse_on_plane(context, self.hit_pos, self.hit_dir, m_coords)

            if plane_pos:
                if event.shift:
                    if self.prim_type == 'Clone':
                        self.new_prim.scale = self.objects_to_clone[0].scale.copy()
                    else:
                        # Make the same scale with Shift key
                        new_dist = (plane_pos - self.hit_pos).length

                        self.new_prim.scale[0] = new_dist
                        self.new_prim.scale[1] = new_dist

                else:
                    if self.prim_type == 'Clone':
                        new_dist = (plane_pos - self.hit_pos).length

                        self.new_prim.scale[0] = self.objects_to_clone[0].scale[0] * new_dist
                        self.new_prim.scale[1] = self.objects_to_clone[0].scale[1] * new_dist
                        self.new_prim.scale[2] = self.objects_to_clone[0].scale[2] * new_dist

                    else:
                        dist_x = mathu.geometry.distance_point_to_plane(plane_pos, self.hit_pos, self.prim_side_vec)
                        dist_y = mathu.geometry.distance_point_to_plane(plane_pos, self.hit_pos, self.prim_front_vec)

                        self.new_prim.scale[0] = abs(dist_x)
                        self.new_prim.scale[1] = abs(dist_y)

        # Draw Primitive Z Depth
        elif self.tool_mode == 'DRAW_2':


            if event.shift:
                # Make the same scale with Shift key
                new_dist = self.new_prim.scale[0]
                if self.new_prim.scale[0] < self.new_prim.scale[1]:
                    new_dist = self.new_prim.scale[1]

                if not self.median_center:
                    self.new_prim.scale[2] = new_dist

                    # set new location
                    mult_vec = self.hit_dir.copy()
                    mult_vec[0] *= (new_dist)
                    mult_vec[1] *= (new_dist)
                    mult_vec[2] *= (new_dist)
                    self.new_prim.location = self.hit_pos + mult_vec

                else:
                    self.new_prim.scale[2] = new_dist

            else:
                view_front_vec = rv3d.view_rotation * Vector((0.0, 0.0, -1.0)).normalized()
                plane_pos = ut_base.get_mouse_on_plane(context, self.hit_pos, view_front_vec, m_coords)
                new_dist = (plane_pos - self.hit_pos).length

                if not self.median_center:
                    self.new_prim.scale[2] = abs(new_dist) / 2

                    # set new location
                    mult_vec = self.hit_dir.copy()
                    mult_vec[0] *= (new_dist / 2)
                    mult_vec[1] *= (new_dist / 2)
                    mult_vec[2] *= (new_dist / 2)
                    self.new_prim.location = self.hit_pos + mult_vec
                else:
                    self.new_prim.scale[2] = (abs(new_dist) / 2) * 2

        # Rotate Primitive
        elif self.tool_mode == 'ROTATE':
            obj_pos_2d = view3d_utils.location_3d_to_region_2d(context.region, rv3d, self.new_prim.location)

            if obj_pos_2d:
                new_prim_mat = self.new_prim.matrix_world
                v1 = Vector(self.deform_mouse_pos) - obj_pos_2d
                v1 = Vector((v1[0], v1[1], 0)).normalized()
                v2 = Vector(m_coords) - obj_pos_2d
                v2 = Vector((v2[0], v2[1], 0)).normalized()

                rot_angle = v1.angle(v2)

                if rot_angle != 0:

                    # check if negative angle
                    if v1.cross(v2)[2] < 0:
                        rot_angle = -rot_angle

                    rot_axis = (new_prim_mat[0][2], new_prim_mat[1][2], new_prim_mat[2][2])

                    # if edit obj
                    if self.edit_obj:
                        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
                        bpy.ops.object.select_all(action='DESELECT')
                        act_temp = context.scene.objects.active
                        #temp_sel = self.new_prim.select
                        self.new_prim.select = True
                        context.scene.objects.active = self.new_prim

                    # do rotation
                    bpy.ops.transform.rotate(value=rot_angle, axis=rot_axis)
                    self.deform_mouse_pos = m_coords

                    # if edit obj
                    if self.edit_obj:
                        self.new_prim.select = False
                        context.scene.objects.active = act_temp
                        bpy.ops.object.mode_set(mode='EDIT', toggle=False)

        # Rotate Primitive
        elif self.tool_mode == 'SCALE':
            obj_pos_2d = view3d_utils.location_3d_to_region_2d(context.region, rv3d, self.new_prim.location)

            if obj_pos_2d:
                v1 = Vector(self.deform_mouse_pos) - obj_pos_2d
                v2 = Vector(m_coords) - obj_pos_2d

                # do scale
                self.new_prim.scale *= (v2.length / v1.length)
                self.deform_mouse_pos = m_coords

                # fix position for non median primitives
                if not self.median_center and self.tool_mode_before_deform == 'IDLE' and self.prim_type != 'Clone':
                    mult_vec = self.hit_dir.copy()
                    mult_vec[0] *= (self.new_prim.scale[2])
                    mult_vec[1] *= (self.new_prim.scale[2])
                    mult_vec[2] *= (self.new_prim.scale[2])
                    self.new_prim.location = self.hit_pos + mult_vec

        return {'RUNNING_MODAL'}
def create_mesh(data_list, 
                AFMdata, 
                use_smooth, 
                scale_size,
                scale_height,
                use_camera,
                use_lamp):
    # This is for the image name.       
    path_list = AFMdata.datfile.strip('/').split('/') 

    number_img = len(data_list)
    image_x_offset_gap = 10.0 * scale_size
    image_x_all = sum(AFMdata.x_size)*scale_size 
    image_x_offset = -(image_x_all+image_x_offset_gap*(number_img-1)) / 2.0
                                
    # For each image do:
    for k, data in enumerate(data_list):
      
        size_x = AFMdata.x_pixel[k]
        size_y = AFMdata.y_pixel[k]
        
        image_scale = AFMdata.x_size[k] / float(AFMdata.x_pixel[k])    
        image_scale = image_scale * scale_size    
        image_x_size = AFMdata.x_size[k] * scale_size        
        image_x_offset += image_x_size / 2.0
      
        image_name = path_list[-1] + "_" + AFMdata.channel[k][1]
        
        data_mesh = []
        data_faces = []

        #print("passed - create_mesh ---- 1")

        for i, line in enumerate(data):
            for j, pixel in enumerate(line):
            
               # The vertices
               data_mesh.append(Vector((float(i) * image_scale, 
                                        float(j) * image_scale, 
                                        float(pixel)*scale_height)))
               
               # The faces
               if i < size_y-1 and j < size_x-1:
                   data_faces.append( [size_x*i+j      , size_x*(i+1)+j, 
                                       size_x*(i+1)+j+1, size_x*i+j+1    ]) 

        #print("passed - create_mesh ---- 2")
               
        # Build the mesh
        surface_mesh = bpy.data.meshes.new("Mesh")
        surface_mesh.from_pydata(data_mesh, [], data_faces)
        surface_mesh.update()
        surface = bpy.data.objects.new(image_name, surface_mesh)
        bpy.context.scene.objects.link(surface)
        bpy.ops.object.select_all(action='DESELECT')        
        surface.select = True 

        bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
        # sum((v.co for v in mesh.vertices), Vector()) / len(mesh.vertices)

        if use_smooth:
            for polygon in surface.data.polygons:
                polygon.use_smooth = True

        surface.location = Vector((0.0, image_x_offset, 0.0)) 
        image_x_offset += image_x_size / 2.0 + image_x_offset_gap

        #print("passed - create_mesh ---- 3")


        
    object_center_vec = Vector((0.0,0.0,0.0))
    object_size = (sum(AFMdata.x_size) * scale_size 
                   +image_x_offset_gap * (len(data_list)-1))

    # ------------------------------------------------------------------------
    # CAMERA AND LAMP
    camera_factor = 20.0
    
    # If chosen a camera is put into the scene.
    if use_camera == True:

        # Assume that the object is put into the global origin. Then, the
        # camera is moved in x and z direction, not in y. The object has its
        # size at distance sqrt(object_size) from the origin. So, move the
        # camera by this distance times a factor of camera_factor in x and z.
        # Then add x, y and z of the origin of the object.
        object_camera_vec = Vector((sqrt(object_size) * camera_factor,
                                    0.0,
                                    sqrt(object_size) * camera_factor))
        camera_xyz_vec = object_center_vec + object_camera_vec

        # Create the camera
        current_layers=bpy.context.scene.layers 
        camera_data = bpy.data.cameras.new("A_camera")
        camera_data.lens = 45
        camera_data.clip_end = 50000.0
        camera = bpy.data.objects.new("A_camera", camera_data)
        camera.location = camera_xyz_vec
        camera.layers = current_layers
        bpy.context.scene.objects.link(camera) 

        # Here the camera is rotated such it looks towards the center of
        # the object. The [0.0, 0.0, 1.0] vector along the z axis
        z_axis_vec             = Vector((0.0, 0.0, 1.0))
        # The angle between the last two vectors
        angle                  = object_camera_vec.angle(z_axis_vec, 0)
        # The cross-product of z_axis_vec and object_camera_vec
        axis_vec               = z_axis_vec.cross(object_camera_vec)
        # Rotate 'axis_vec' by 'angle' and convert this to euler parameters.
        # 4 is the size of the matrix.
        camera.rotation_euler  = Matrix.Rotation(angle, 4, axis_vec).to_euler()

        # Rotate the camera around its axis by 90° such that we have a nice
        # camera position and view onto the object.
        bpy.ops.object.select_all(action='DESELECT')        
        camera.select = True         
        bpy.ops.transform.rotate(value=(90.0*2*pi/360.0),
                                 axis=object_camera_vec,
                                 constraint_axis=(False, False, False),
                                 constraint_orientation='GLOBAL',
                                 mirror=False, proportional='DISABLED',
                                 proportional_edit_falloff='SMOOTH',
                                 proportional_size=1, snap=False,
                                 snap_target='CLOSEST', snap_point=(0, 0, 0),
                                 snap_align=False, snap_normal=(0, 0, 0),
                                 release_confirm=False)

    # Here a lamp is put into the scene, if chosen.
    if use_lamp == True:

        # This is the distance from the object measured in terms of %
        # of the camera distance. It is set onto 50% (1/2) distance.
        lamp_dl = sqrt(object_size) * 15 * 0.5
        # This is a factor to which extend the lamp shall go to the right
        # (from the camera  point of view).
        lamp_dy_right = lamp_dl * (3.0/4.0)

        # Create x, y and z for the lamp.
        object_lamp_vec = Vector((lamp_dl,lamp_dy_right,lamp_dl))
        lamp_xyz_vec = object_center_vec + object_lamp_vec

        # Create the lamp
        current_layers=bpy.context.scene.layers
        lamp_data = bpy.data.lamps.new(name="A_lamp", type="POINT")
        lamp_data.distance = 5000.0
        lamp_data.energy = 3.0
        lamp_data.shadow_method = 'RAY_SHADOW'        
        lamp = bpy.data.objects.new("A_lamp", lamp_data)
        lamp.location = lamp_xyz_vec
        lamp.layers = current_layers
        bpy.context.scene.objects.link(lamp)         

        bpy.context.scene.world.light_settings.use_ambient_occlusion = True
        bpy.context.scene.world.light_settings.ao_factor = 0.1      
Example #39
0
    def bake(self, context, samples=False):
        ''' bake a driver to an action fcurve'''

        # REFACTO add flag to convert between kfs and samples
        def get_action_fcurve(driver):
            obj = driver.fcurve.id_data
            action = obj.animation_data.action # will have animation_data from driver
            if action is None:
                action = obj.animation_data.action = bpy.data.actions.new("%s (BFD)" % obj.name)
            fc = [fc for fc in action.fcurves if fc.data_path == driver.fcurve.data_path and fc.array_index == driver.fcurve.array_index]
            if len(fc):
                return fc[0]
            fc = action.fcurves.new(driver.data_path, driver.array_index)
            return fc

        scene = context.scene
        frame = self.f
        frame_end = self.f + self.bakeframes[self.pc] - 1
        # bake to scene frame range
        self.driver.edit_driver_baking = True
        setattr(self.driver, "bake_pc", self.pc / self.chunks)
        driver = self.driver.fcurve
        obj = driver.id_data

        #action = speaker.animation_data.action

        # make an unbaked fcurve for the driver.
        # check whether there is already an fcurve

        coords = []
        while frame <= frame_end:
            scene.frame_set(frame)
            co = (frame, self.driver.value)
            v = Vector(co)
            if len(coords) > 1:  # enough to linear test
                v1 = Vector(coords[-1]) - v
                v2 = Vector(coords[-2]) - v
                if v1.length and v2.length and v1.angle(v2) < 0.001:
                    coords[-1] = co
                else:
                    coords.append(co)
            else:
                coords.append(co)
            # quick fix try array, then without
            #REFACTO 
            frame += 1
            '''
            # frame by frame kfi
            if self.driver.is_vector:
                driver.id_data.keyframe_insert(driver.data_path,
                                               index=driver.array_index)
            else:
                driver.id_data.keyframe_insert(driver.data_path)

            frame += 1 # REFACTO 
            '''

        fc = get_action_fcurve(self.driver)
        l = len(coords)
        #x = []  # refactor got keyframe_points.foreach_set
        for i in range(l):
            fc.keyframe_points.insert(*coords[i])
        
        if samples:
            fc.convert_to_samples(self.f, frame_end)
        return True
Example #40
0
def import_pdb(Ball_type,
               Ball_azimuth,
               Ball_zenith,
               Ball_radius_factor,
               radiustype,
               Ball_distance_factor,
               use_sticks,
               use_sticks_color,
               use_sticks_smooth,
               use_sticks_bonds, 
               Stick_unit, Stick_dist,
               Stick_sectors,
               Stick_diameter,
               put_to_center,
               use_camera,
               use_lamp,
               filepath_pdb):


    # List of materials
    atom_material_list = []

    # A list of ALL objects which are loaded (needed for selecting the loaded
    # structure.
    atom_object_list = []

    # ------------------------------------------------------------------------
    # INITIALIZE THE ELEMENT LIST

    read_elements()

    # ------------------------------------------------------------------------
    # READING DATA OF ATOMS

    (Number_of_total_atoms, all_atoms) = read_pdb_file(filepath_pdb, radiustype)

    # ------------------------------------------------------------------------
    # MATERIAL PROPERTIES FOR ATOMS

    # The list that contains info about all types of atoms is created
    # here. It is used for building the material properties for
    # instance (see below).
    atom_all_types_list = []

    for atom in all_atoms:
        FLAG_FOUND = False
        for atom_type in atom_all_types_list:
            # If the atom name is already in the list, FLAG on 'True'.
            if atom_type[0] == atom.name:
                FLAG_FOUND = True
                break
        # No name in the current list has been found? => New entry.
        if FLAG_FOUND == False:
            # Stored are: Atom label (e.g. 'Na'), the corresponding atom
            # name (e.g. 'Sodium') and its color.
            atom_all_types_list.append([atom.name, atom.element, atom.color])

    # The list of materials is built.
    # Note that all atoms of one type (e.g. all hydrogens) get only ONE
    # material! This is good because then, by activating one atom in the
    # Blender scene and changing the color of this atom, one changes the color
    # of ALL atoms of the same type at the same time.

    # Create first a new list of materials for each type of atom
    # (e.g. hydrogen)
    for atom_type in atom_all_types_list:
        material = bpy.data.materials.new(atom_type[1])
        material.name = atom_type[0]
        material.diffuse_color = atom_type[2]
        atom_material_list.append(material)

    # Now, we go through all atoms and give them a material. For all atoms ...
    for atom in all_atoms:
        # ... and all materials ...
        for material in atom_material_list:
            # ... select the correct material for the current atom via
            # comparison of names ...
            if atom.name in material.name:
                # ... and give the atom its material properties.
                # However, before we check, if it is a vacancy, because then it
                # gets some additional preparation. The vacancy is represented
                # by a transparent cube.
                if atom.name == "Vacancy":
                    material.transparency_method = 'Z_TRANSPARENCY'
                    material.alpha = 1.3
                    material.raytrace_transparency.fresnel = 1.6
                    material.raytrace_transparency.fresnel_factor = 1.6
                    material.use_transparency = True
                # The atom gets its properties.
                atom.material = material

    # ------------------------------------------------------------------------
    # READING DATA OF STICKS

    all_sticks = read_pdb_file_sticks(filepath_pdb, 
                                      use_sticks_bonds, 
                                      all_atoms)

    # So far, all atoms, sticks and materials have been registered.

    # ------------------------------------------------------------------------
    # TRANSLATION OF THE STRUCTURE TO THE ORIGIN

    # It may happen that the structure in a PDB file already has an offset
    # If chosen, the structure is first put into the center of the scene
    # (the offset is substracted).

    if put_to_center == True:

        sum_vec = Vector((0.0,0.0,0.0))

        # Sum of all atom coordinates
        sum_vec = sum([atom.location for atom in all_atoms], sum_vec)

        # Then the average is taken
        sum_vec = sum_vec / Number_of_total_atoms

        # After, for each atom the center of gravity is substracted
        for atom in all_atoms:
            atom.location -= sum_vec

    # ------------------------------------------------------------------------
    # SCALING

    # Take all atoms and adjust their radii and scale the distances.
    for atom in all_atoms:
        atom.location *= Ball_distance_factor

    # ------------------------------------------------------------------------
    # DETERMINATION OF SOME GEOMETRIC PROPERTIES

    # In the following, some geometric properties of the whole object are
    # determined: center, size, etc.
    sum_vec = Vector((0.0,0.0,0.0))

    # First the center is determined. All coordinates are summed up ...
    sum_vec = sum([atom.location for atom in all_atoms], sum_vec)

    # ... and the average is taken. This gives the center of the object.
    object_center_vec = sum_vec / Number_of_total_atoms

    # Now, we determine the size.The farthest atom from the object center is
    # taken as a measure. The size is used to place well the camera and light
    # into the scene.
    object_size_vec = [atom.location - object_center_vec for atom in all_atoms]
    object_size = 0.0
    object_size = max(object_size_vec).length

    # ------------------------------------------------------------------------
    # CAMERA AND LAMP

    camera_factor = 15.0

    # If chosen a camera is put into the scene.
    if use_camera == True:

        # Assume that the object is put into the global origin. Then, the
        # camera is moved in x and z direction, not in y. The object has its
        # size at distance sqrt(object_size) from the origin. So, move the
        # camera by this distance times a factor of camera_factor in x and z.
        # Then add x, y and z of the origin of the object.
        object_camera_vec = Vector((sqrt(object_size) * camera_factor,
                                    0.0,
                                    sqrt(object_size) * camera_factor))
        camera_xyz_vec = object_center_vec + object_camera_vec

        # Create the camera
        current_layers=bpy.context.scene.layers 
        camera_data = bpy.data.cameras.new("A_camera")
        camera_data.lens = 45
        camera_data.clip_end = 500.0
        camera = bpy.data.objects.new("A_camera", camera_data)
        camera.location = camera_xyz_vec
        camera.layers = current_layers
        bpy.context.scene.objects.link(camera)

        # Here the camera is rotated such it looks towards the center of
        # the object. The [0.0, 0.0, 1.0] vector along the z axis
        z_axis_vec             = Vector((0.0, 0.0, 1.0))
        # The angle between the last two vectors
        angle                  = object_camera_vec.angle(z_axis_vec, 0)
        # The cross-product of z_axis_vec and object_camera_vec
        axis_vec               = z_axis_vec.cross(object_camera_vec)
        # Rotate 'axis_vec' by 'angle' and convert this to euler parameters.
        # 4 is the size of the matrix.
        camera.rotation_euler  = Matrix.Rotation(angle, 4, axis_vec).to_euler()

        # Rotate the camera around its axis by 90° such that we have a nice
        # camera position and view onto the object.
        bpy.ops.object.select_all(action='DESELECT')        
        camera.select = True 
        bpy.ops.transform.rotate(value=(90.0*2*pi/360.0),
                                 axis=object_camera_vec,
                                 constraint_axis=(False, False, False),
                                 constraint_orientation='GLOBAL',
                                 mirror=False, proportional='DISABLED',
                                 proportional_edit_falloff='SMOOTH',
                                 proportional_size=1, snap=False,
                                 snap_target='CLOSEST', snap_point=(0, 0, 0),
                                 snap_align=False, snap_normal=(0, 0, 0),
                                 release_confirm=False)

    # Here a lamp is put into the scene, if chosen.
    if use_lamp == True:

        # This is the distance from the object measured in terms of %
        # of the camera distance. It is set onto 50% (1/2) distance.
        lamp_dl = sqrt(object_size) * 15 * 0.5
        # This is a factor to which extend the lamp shall go to the right
        # (from the camera  point of view).
        lamp_dy_right = lamp_dl * (3.0/4.0)

        # Create x, y and z for the lamp.
        object_lamp_vec = Vector((lamp_dl,lamp_dy_right,lamp_dl))
        lamp_xyz_vec = object_center_vec + object_lamp_vec

        # Create the lamp
        current_layers=bpy.context.scene.layers
        lamp_data = bpy.data.lamps.new(name="A_lamp", type="POINT")
        lamp_data.distance = 500.0
        lamp_data.energy = 3.0
        lamp_data.shadow_method = 'RAY_SHADOW'        
        lamp = bpy.data.objects.new("A_lamp", lamp_data)
        lamp.location = lamp_xyz_vec
        lamp.layers = current_layers
        bpy.context.scene.objects.link(lamp)         

        bpy.context.scene.world.light_settings.use_ambient_occlusion = True
        bpy.context.scene.world.light_settings.ao_factor = 0.2

    # ------------------------------------------------------------------------
    # SORTING THE ATOMS

    # Lists of atoms of one type are created. Example:
    # draw_all_atoms = [ data_hydrogen,data_carbon,data_nitrogen ]
    # data_hydrogen = [["Hydrogen", Material_Hydrogen, Vector((x,y,z)), 109], ...]

    draw_all_atoms = []

    # Go through the list which contains all types of atoms. It is the list,
    # which has been created on the top during reading the PDB file.
    # Example: atom_all_types_list = ["hydrogen", "carbon", ...]
    for atom_type in atom_all_types_list:

        # Don't draw 'TER atoms'.
        if atom_type[0] == "TER":
            continue

        # This is the draw list, which contains all atoms of one type (e.g.
        # all hydrogens) ...
        draw_all_atoms_type = []

        # Go through all atoms ...
        for atom in all_atoms:
            # ... select the atoms of the considered type via comparison ...
            if atom.name == atom_type[0]:
                # ... and append them to the list 'draw_all_atoms_type'.
                draw_all_atoms_type.append([atom.name,
                                           atom.material,
                                           atom.location,
                                           atom.radius])

        # Now append the atom list to the list of all types of atoms
        draw_all_atoms.append(draw_all_atoms_type)

    # ------------------------------------------------------------------------
    # DRAWING THE ATOMS

    # This is the number of all atoms which are put into the scene.
    bpy.ops.object.select_all(action='DESELECT')

    # For each list of atoms of ONE type (e.g. Hydrogen)
    for draw_all_atoms_type in draw_all_atoms:

        # Create first the vertices composed of the coordinates of all
        # atoms of one type
        atom_vertices = []
        for atom in draw_all_atoms_type:
            # In fact, the object is created in the World's origin.
            # This is why 'object_center_vec' is substracted. At the end
            # the whole object is translated back to 'object_center_vec'.
            atom_vertices.append( atom[2] - object_center_vec )

        # Build the mesh
        atom_mesh = bpy.data.meshes.new("Mesh_"+atom[0])
        atom_mesh.from_pydata(atom_vertices, [], [])
        atom_mesh.update()
        new_atom_mesh = bpy.data.objects.new(atom[0], atom_mesh)
        bpy.context.scene.objects.link(new_atom_mesh)

        # Now, build a representative sphere (atom)
        current_layers=bpy.context.scene.layers

        if atom[0] == "Vacancy":
            bpy.ops.mesh.primitive_cube_add(
                            view_align=False, enter_editmode=False,
                            location=(0.0, 0.0, 0.0),
                            rotation=(0.0, 0.0, 0.0),
                            layers=current_layers)
        else:
            # NURBS balls
            if Ball_type == "0":
                bpy.ops.surface.primitive_nurbs_surface_sphere_add(
                            view_align=False, enter_editmode=False,
                            location=(0,0,0), rotation=(0.0, 0.0, 0.0),
                            layers=current_layers)
            # UV balls
            elif Ball_type == "1":
                bpy.ops.mesh.primitive_uv_sphere_add(
                            segments=Ball_azimuth, ring_count=Ball_zenith,
                            size=1, view_align=False, enter_editmode=False,
                            location=(0,0,0), rotation=(0, 0, 0),
                            layers=current_layers)
            # Meta balls
            elif Ball_type == "2":
                bpy.ops.object.metaball_add(type='BALL', view_align=False, 
                            enter_editmode=False, location=(0, 0, 0), 
                            rotation=(0, 0, 0), layers=current_layers)

        ball = bpy.context.scene.objects.active
        ball.scale  = (atom[3]*Ball_radius_factor,) * 3

        if atom[0] == "Vacancy":
            ball.name = "Cube_"+atom[0]
        else:
            ball.name = "Ball_"+atom[0]
        ball.active_material = atom[1]
        ball.parent = new_atom_mesh
        new_atom_mesh.dupli_type = 'VERTS'
        # The object is back translated to 'object_center_vec'.
        new_atom_mesh.location = object_center_vec
        atom_object_list.append(new_atom_mesh)

    # ------------------------------------------------------------------------
    # DRAWING THE STICKS

    if use_sticks == True and all_sticks != []:
            
        dl = Stick_unit
         
        if use_sticks_color == False:   
            bpy.ops.object.material_slot_add()
            stick_material = bpy.data.materials.new(ELEMENTS[-1].name)
            stick_material.diffuse_color = ELEMENTS[-1].color            

        # Sort the sticks and put them into a new list such that ...            
        sticks_all_lists = []
        if use_sticks_color == True:
            for atom_type in atom_all_types_list:
                if atom_type[0] == "TER":
                    continue            
                sticks_list = []
                for stick in all_sticks:
                                
                    for repeat in range(stick.number):
                                    
                        atom1 = copy(all_atoms[stick.atom1-1].location)
                        atom2 = copy(all_atoms[stick.atom2-1].location)               
                   
                        dist =  Stick_diameter * Stick_dist
                   
                        if stick.number == 2: 
                            if repeat == 0:
                                atom1 += (stick.dist * dist)
                                atom2 += (stick.dist * dist)
                            if repeat == 1:
                                atom1 -= (stick.dist * dist) 
                                atom2 -= (stick.dist * dist)                                

                        if stick.number == 3: 
                            if repeat == 0:
                                atom1 += (stick.dist * dist)
                                atom2 += (stick.dist * dist)
                            if repeat == 2:
                                atom1 -= (stick.dist * dist) 
                                atom2 -= (stick.dist * dist)                         

                        dv = atom1 - atom2                
                        n  = dv / dv.length
                        if atom_type[0] == all_atoms[stick.atom1-1].name:
                            location = atom1
                            name     = "_" + all_atoms[stick.atom1-1].name
                            material = all_atoms[stick.atom1-1].material
                            sticks_list.append([name, location, dv, material])
                        if atom_type[0] == all_atoms[stick.atom2-1].name: 
                            location = atom1 - n * dl * int(ceil(dv.length / (2.0 * dl)))
                            name     = "_" + all_atoms[stick.atom2-1].name
                            material = all_atoms[stick.atom2-1].material
                            sticks_list.append([name, location, dv, material])
                              
                if sticks_list != []:       
                    sticks_all_lists.append(sticks_list)
        else:
            sticks_list = []
            for stick in all_sticks:
                        
                if stick.number > 3:
                    stick.number = 1
                 
                for repeat in range(stick.number):              
                                    
                    atom1 = copy(all_atoms[stick.atom1-1].location)
                    atom2 = copy(all_atoms[stick.atom2-1].location)
                   
                    dist =  Stick_diameter * Stick_dist
                   
                    if stick.number == 2: 
                        if repeat == 0:
                            atom1 += (stick.dist * dist)
                            atom2 += (stick.dist * dist)
                        if repeat == 1:
                            atom1 -= (stick.dist * dist) 
                            atom2 -= (stick.dist * dist)                                
                    if stick.number == 3: 
                        if repeat == 0:
                            atom1 += (stick.dist * dist)
                            atom2 += (stick.dist * dist)
                        if repeat == 2:
                            atom1 -= (stick.dist * dist) 
                            atom2 -= (stick.dist * dist) 
            
                    dv = atom1 - atom2                
                    n  = dv / dv.length
                    location = atom1
                    material = stick_material
                    sticks_list.append(["", location, dv, material])

            sticks_all_lists.append(sticks_list)

        # ... the sticks in the list can be drawn:
        for stick_list in sticks_all_lists:
            vertices = []
            faces    = []
            i = 0
            
            # What follows is school mathematics! :-)
            for stick in stick_list:
            
                dv = stick[2]
                v1 = stick[1]
                n  = dv / dv.length
                gamma = -n * v1
                b     = v1 + gamma * n
                n_b   = b / b.length
                
                if use_sticks_color == True:
                    loops = int(ceil(dv.length / (2.0 * dl)))
                else:
                    loops = int(ceil(dv.length / dl))
                    
                for j in range(loops):

                    g  = v1 - n * dl / 2.0 - n * dl * j
                    p1 = g + n_b * Stick_diameter
                    p2 = g - n_b * Stick_diameter
                    p3 = g - n_b.cross(n) * Stick_diameter
                    p4 = g + n_b.cross(n) * Stick_diameter

                    vertices.append(p1)
                    vertices.append(p2)
                    vertices.append(p3)
                    vertices.append(p4)
                    faces.append((i*4+0,i*4+2,i*4+1,i*4+3))
                    i += 1
            
            mesh = bpy.data.meshes.new("Sticks"+stick[0])
            mesh.from_pydata(vertices, [], faces)
            mesh.update()
            new_mesh = bpy.data.objects.new("Sticks"+stick[0], mesh)
            bpy.context.scene.objects.link(new_mesh)

            current_layers = bpy.context.scene.layers
            object_stick = build_stick(Stick_diameter, dl, Stick_sectors)
            stick_cylinder = object_stick[0]
            stick_cylinder.active_material = stick[3]
            stick_cups = object_stick[1]
            stick_cups.active_material = stick[3]            
                   
            if use_sticks_smooth == True: 
                bpy.ops.object.select_all(action='DESELECT')
                stick_cylinder.select = True
                stick_cups.select = True
                bpy.ops.object.shade_smooth()

            stick_cylinder.parent = new_mesh
            stick_cups.parent = new_mesh
            new_mesh.dupli_type = 'FACES'
            atom_object_list.append(new_mesh)

    # ------------------------------------------------------------------------
    # SELECT ALL LOADED OBJECTS
    bpy.ops.object.select_all(action='DESELECT')
    obj = None
    for obj in atom_object_list:
        obj.select = True

    # activate the last selected object (perhaps another should be active?)
    if obj:
        bpy.context.scene.objects.active = obj
Example #41
0
def import_xyz(Ball_type,
               Ball_azimuth,
               Ball_zenith,
               Ball_radius_factor,
               radiustype,
               Ball_distance_factor,
               put_to_center, 
               put_to_center_all,
               use_camera,
               use_lamp,
               filepath_xyz):

    # List of materials
    atom_material_list = []

    # ------------------------------------------------------------------------
    # INITIALIZE THE ELEMENT LIST

    read_elements()

    # ------------------------------------------------------------------------
    # READING DATA OF ATOMS

    Number_of_total_atoms = read_xyz_file(filepath_xyz, 
                                                       radiustype)
                                               
    # We show the atoms of the first frame.
    first_frame = ALL_FRAMES[0]

    # ------------------------------------------------------------------------
    # MATERIAL PROPERTIES FOR ATOMS

    # Create first a new list of materials for each type of atom
    # (e.g. hydrogen)
    for atoms_of_one_type in first_frame:
        # Take the first atom
        atom = atoms_of_one_type[0]
        material = bpy.data.materials.new(atom.name)
        material.name = atom.name
        material.diffuse_color = atom.color
        atom_material_list.append(material)

    # Now, we go through all atoms and give them a material. For all atoms ...
    for atoms_of_one_type in first_frame:
        for atom in atoms_of_one_type:
            # ... and all materials ...
            for material in atom_material_list:
                # ... select the correct material for the current atom via
                # comparison of names ...
                if atom.name in material.name:
                    # ... and give the atom its material properties.
                    # However, before we check if it is a vacancy
                    # The vacancy is represented by a transparent cube.
                    if atom.name == "Vacancy":
                        material.transparency_method = 'Z_TRANSPARENCY'
                        material.alpha = 1.3
                        material.raytrace_transparency.fresnel = 1.6
                        material.raytrace_transparency.fresnel_factor = 1.6
                        material.use_transparency = True
                    # The atom gets its properties.
                    atom.material = material

    # ------------------------------------------------------------------------
    # TRANSLATION OF THE STRUCTURE TO THE ORIGIN

    # It may happen that the structure in a XYZ file already has an offset


    # If chosen, the structure is put into the center of the scene
    # (only the first frame).
    if put_to_center == True and put_to_center_all == False:

        sum_vec = Vector((0.0,0.0,0.0))

        # Sum of all atom coordinates
        for atoms_of_one_type in first_frame:
            sum_vec = sum([atom.location for atom in atoms_of_one_type], sum_vec)

        # Then the average is taken
        sum_vec = sum_vec / Number_of_total_atoms

        # After, for each atom the center of gravity is substracted
        for atoms_of_one_type in first_frame:
            for atom in atoms_of_one_type:
                atom.location -= sum_vec

    # If chosen, the structure is put into the center of the scene
    # (all frames).
    if put_to_center_all == True:

        # For all frames
        for frame in ALL_FRAMES: 

            sum_vec = Vector((0.0,0.0,0.0))

            # Sum of all atom coordinates
            for (i, atoms_of_one_type) in enumerate(frame):

                # This is a guarantee that only the total number of atoms of the
                # first frame is used. Condition is, so far, that the number of
                # atoms in a xyz file is constant. However, sometimes the number
                # may increase (or decrease). If it decreases, the addon crashes.
                # If it increases, only the tot number of atoms of the first frame
                # is used.
                # By time, I will allow varying atom numbers ... but this takes 
                # some time ...
                if i >= Number_of_total_atoms:
                    break

                sum_vec = sum([atom.location for atom in atoms_of_one_type], sum_vec)

            # Then the average is taken
            sum_vec = sum_vec / Number_of_total_atoms

            # After, for each atom the center of gravity is substracted
            for atoms_of_one_type in frame:
                for atom in atoms_of_one_type:
                    atom.location -= sum_vec

   
    # ------------------------------------------------------------------------
    # SCALING

    # Take all atoms and adjust their radii and scale the distances.
    for atoms_of_one_type in first_frame:
        for atom in atoms_of_one_type:
            atom.location *= Ball_distance_factor
    
    # ------------------------------------------------------------------------
    # DETERMINATION OF SOME GEOMETRIC PROPERTIES

    # In the following, some geometric properties of the whole object are
    # determined: center, size, etc.
    sum_vec = Vector((0.0,0.0,0.0))

    # First the center is determined. All coordinates are summed up ...
    for atoms_of_one_type in first_frame:
        sum_vec = sum([atom.location for atom in atoms_of_one_type], sum_vec)

    # ... and the average is taken. This gives the center of the object.
    object_center_vec = sum_vec / Number_of_total_atoms

    # Now, we determine the size.The farthest atom from the object center is
    # taken as a measure. The size is used to place well the camera and light
    # into the scene.

    object_size_vec = []
    for atoms_of_one_type in first_frame:
        object_size_vec += [atom.location - object_center_vec for atom in atoms_of_one_type]

    object_size = 0.0
    object_size = max(object_size_vec).length

    # ------------------------------------------------------------------------
    # CAMERA AND LAMP
    camera_factor = 20.0

    # If chosen a camera is put into the scene.
    if use_camera == True:

        # Assume that the object is put into the global origin. Then, the
        # camera is moved in x and z direction, not in y. The object has its
        # size at distance sqrt(object_size) from the origin. So, move the
        # camera by this distance times a factor of camera_factor in x and z.
        # Then add x, y and z of the origin of the object.
        object_camera_vec = Vector((sqrt(object_size) * camera_factor,
                                    0.0,
                                    sqrt(object_size) * camera_factor))
        camera_xyz_vec = object_center_vec + object_camera_vec

        # Create the camera
        current_layers=bpy.context.scene.layers 
        camera_data = bpy.data.cameras.new("A_camera")
        camera_data.lens = 45
        camera_data.clip_end = 500.0
        camera = bpy.data.objects.new("A_camera", camera_data)
        camera.location = camera_xyz_vec
        camera.layers = current_layers
        bpy.context.scene.objects.link(camera) 

        # Here the camera is rotated such it looks towards the center of
        # the object. The [0.0, 0.0, 1.0] vector along the z axis
        z_axis_vec             = Vector((0.0, 0.0, 1.0))
        # The angle between the last two vectors
        angle                  = object_camera_vec.angle(z_axis_vec, 0)
        # The cross-product of z_axis_vec and object_camera_vec
        axis_vec               = z_axis_vec.cross(object_camera_vec)
        # Rotate 'axis_vec' by 'angle' and convert this to euler parameters.
        # 4 is the size of the matrix.
        camera.rotation_euler  = Matrix.Rotation(angle, 4, axis_vec).to_euler()

        # Rotate the camera around its axis by 90° such that we have a nice
        # camera position and view onto the object.
        bpy.ops.object.select_all(action='DESELECT')        
        camera.select = True         
        bpy.ops.transform.rotate(value=(90.0*2*pi/360.0),
                                 axis=object_camera_vec,
                                 constraint_axis=(False, False, False),
                                 constraint_orientation='GLOBAL',
                                 mirror=False, proportional='DISABLED',
                                 proportional_edit_falloff='SMOOTH',
                                 proportional_size=1, snap=False,
                                 snap_target='CLOSEST', snap_point=(0, 0, 0),
                                 snap_align=False, snap_normal=(0, 0, 0),
                                 release_confirm=False)

    # Here a lamp is put into the scene, if chosen.
    if use_lamp == True:

        # This is the distance from the object measured in terms of %
        # of the camera distance. It is set onto 50% (1/2) distance.
        lamp_dl = sqrt(object_size) * 15 * 0.5
        # This is a factor to which extend the lamp shall go to the right
        # (from the camera  point of view).
        lamp_dy_right = lamp_dl * (3.0/4.0)

        # Create x, y and z for the lamp.
        object_lamp_vec = Vector((lamp_dl,lamp_dy_right,lamp_dl))
        lamp_xyz_vec = object_center_vec + object_lamp_vec

        # Create the lamp
        current_layers=bpy.context.scene.layers
        lamp_data = bpy.data.lamps.new(name="A_lamp", type="POINT")
        lamp_data.distance = 500.0
        lamp_data.energy = 3.0
        lamp_data.shadow_method = 'RAY_SHADOW'        
        lamp = bpy.data.objects.new("A_lamp", lamp_data)
        lamp.location = lamp_xyz_vec
        lamp.layers = current_layers
        bpy.context.scene.objects.link(lamp)         

        bpy.context.scene.world.light_settings.use_ambient_occlusion = True
        bpy.context.scene.world.light_settings.ao_factor = 0.2
        

    # ------------------------------------------------------------------------
    # DRAWING THE ATOMS

    bpy.ops.object.select_all(action='DESELECT')

    # For each list of atoms of ONE type (e.g. Hydrogen)
    for atoms_of_one_type in first_frame:

        # Create first the vertices composed of the coordinates of all
        # atoms of one type
        atom_vertices = []
        for atom in atoms_of_one_type:
            # In fact, the object is created in the World's origin.
            # This is why 'object_center_vec' is substracted. At the end
            # the whole object is translated back to 'object_center_vec'.
            atom_vertices.append( atom.location - object_center_vec )

        # Build the mesh
        atom_mesh = bpy.data.meshes.new("Mesh_"+atom.name)
        atom_mesh.from_pydata(atom_vertices, [], [])
        atom_mesh.update()
        new_atom_mesh = bpy.data.objects.new(atom.name, atom_mesh)
        bpy.context.scene.objects.link(new_atom_mesh)

        # Now, build a representative sphere (atom)
        current_layers=bpy.context.scene.layers

        if atom.name == "Vacancy":
            bpy.ops.mesh.primitive_cube_add(
                            view_align=False, enter_editmode=False,
                            location=(0.0, 0.0, 0.0),
                            rotation=(0.0, 0.0, 0.0),
                            layers=current_layers)
        else:
            # NURBS balls
            if Ball_type == "0":
                bpy.ops.surface.primitive_nurbs_surface_sphere_add(
                            view_align=False, enter_editmode=False,
                            location=(0,0,0), rotation=(0.0, 0.0, 0.0),
                            layers=current_layers)
            # UV balls
            elif Ball_type == "1":
                bpy.ops.mesh.primitive_uv_sphere_add(
                            segments=Ball_azimuth, ring_count=Ball_zenith,
                            size=1, view_align=False, enter_editmode=False,
                            location=(0,0,0), rotation=(0, 0, 0),
                            layers=current_layers)
            # Meta balls
            elif Ball_type == "2":
                bpy.ops.object.metaball_add(type='BALL', view_align=False, 
                            enter_editmode=False, location=(0, 0, 0), 
                            rotation=(0, 0, 0), layers=current_layers)

        ball = bpy.context.scene.objects.active
        ball.scale  = (atom.radius*Ball_radius_factor,) * 3

        if atom.name == "Vacancy":
            ball.name = "Cube_"+atom.name
        else:
            ball.name = "Ball (NURBS)_"+atom.name
        ball.active_material = atom.material
        ball.parent = new_atom_mesh
        new_atom_mesh.dupli_type = 'VERTS'
        # The object is back translated to 'object_center_vec'.
        new_atom_mesh.location = object_center_vec
        STRUCTURE.append(new_atom_mesh)

    # ------------------------------------------------------------------------
    # SELECT ALL LOADED OBJECTS
    
    bpy.ops.object.select_all(action='DESELECT')
    obj = None
    for obj in STRUCTURE:
        obj.select = True
    # activate the last selected object (perhaps another should be active?)
    if obj:
        bpy.context.scene.objects.active = obj
Example #42
0
def camera_light_source(use_camera,
                        use_light,
                        object_center_vec,
                        object_size):

    camera_factor = 15.0

    # If chosen a camera is put into the scene.
    if use_camera == True:

        # Assume that the object is put into the global origin. Then, the
        # camera is moved in x and z direction, not in y. The object has its
        # size at distance sqrt(object_size) from the origin. So, move the
        # camera by this distance times a factor of camera_factor in x and z.
        # Then add x, y and z of the origin of the object.
        object_camera_vec = Vector((sqrt(object_size) * camera_factor,
                                    0.0,
                                    sqrt(object_size) * camera_factor))
        camera_xyz_vec = object_center_vec + object_camera_vec

        # Create the camera
        camera_data = bpy.data.cameras.new("A_camera")
        camera_data.lens = 45
        camera_data.clip_end = 500.0
        camera = bpy.data.objects.new("A_camera", camera_data)
        camera.location = camera_xyz_vec
        bpy.context.collection.objects.link(camera)

        # Here the camera is rotated such it looks towards the center of
        # the object. The [0.0, 0.0, 1.0] vector along the z axis
        z_axis_vec             = Vector((0.0, 0.0, 1.0))
        # The angle between the last two vectors
        angle                  = object_camera_vec.angle(z_axis_vec, 0)
        # The cross-product of z_axis_vec and object_camera_vec
        axis_vec               = z_axis_vec.cross(object_camera_vec)
        # Rotate 'axis_vec' by 'angle' and convert this to euler parameters.
        # 4 is the size of the matrix.
        camera.rotation_euler  = Matrix.Rotation(angle, 4, axis_vec).to_euler()

        # Rotate the camera around its axis by 90° such that we have a nice
        # camera position and view onto the object.
        bpy.ops.object.select_all(action='DESELECT')
        camera.select_set(True)
        
        # Rotate the camera around its axis 'object_camera_vec' by 90° such 
        # that we have a nice camera view onto the object.
        matrix_rotation = Matrix.Rotation(90/360*2*pi, 4, object_camera_vec)
        rotate_object(matrix_rotation, camera)

    # Here a lamp is put into the scene, if chosen.
    if use_light == True:

        # This is the distance from the object measured in terms of %
        # of the camera distance. It is set onto 50% (1/2) distance.
        light_dl = sqrt(object_size) * 15 * 0.5
        # This is a factor to which extend the lamp shall go to the right
        # (from the camera  point of view).
        light_dy_right = light_dl * (3.0/4.0)

        # Create x, y and z for the lamp.
        object_light_vec = Vector((light_dl,light_dy_right,light_dl))
        light_xyz_vec = object_center_vec + object_light_vec

        # Create the lamp
        light_data = bpy.data.lights.new(name="A_light", type="SUN")
        light_data.distance = 500.0
        light_data.energy = 3.0
        lamp = bpy.data.objects.new("A_light", light_data)
        lamp.location = light_xyz_vec
        bpy.context.collection.objects.link(lamp)

        # Some settings for the World: a bit ambient occlusion
        bpy.context.scene.world.light_settings.use_ambient_occlusion = True
        bpy.context.scene.world.light_settings.ao_factor = 0.2
        # Some properties for cycles
        lamp.data.use_nodes = True
        lmp_P_BSDF = lamp.data.node_tree.nodes['Emission']
        lmp_P_BSDF.inputs['Strength'].default_value = 5
    def execute(self, context):
        threshold = 1e-6

        region = context.region
        rv3d = context.region_data
        actob = context.active_object
        mat = actob.matrix_world
        imat = actob.matrix_world.inverted()

        bm = bmesh.from_edit_mesh(actob.data)

        edgelines = self.edgelines  # 描画用
        translines = self.translines  # 描画用

        edgelines[:] = []  # Clear
        translines[:] = []  # Clear

#         mm_relative = self.modal_mouse.relative.to_3d()
#         if mm_relative.length < threshold:
#             mm_relative = Vector((1, 0))
        if self.modal_mouse.lock:
            lock_relative = self.modal_mouse.lock - self.modal_mouse.origin
        else:
            lock_relative = self.modal_mouse.relative
        if lock_relative.length < threshold:
            lock_relative = Vector((1, 0))

        # 座標初期化
        for src, dst in zip(self.bm.verts, bm.verts):
            dst.co = src.co

        new_coordinates = {}  # index: Vector

        for i, eve in enumerate(bm.verts):
            if not eve.select or eve.hide:
                continue

            # 頂点に接続する頂点を求める
            connected_vertices = []
            for eed in (e for e in eve.link_edges if not e.hide):
                connected_vertices.append(eed.other_vert(eve))
            if not connected_vertices:
                continue

            # 辺の長さが0なら、更にその先にある頂点を追加する
            verts = []
            for eve2 in connected_vertices:
                if (eve2.co - eve.co).length < threshold:
                    for eed in (e for e in eve2.link_edges if not e.hide):
                        verts.append(eed.other_vert(eve2))
            connected_vertices.extend(verts)

            # 移動先の頂点を求める
            angles = []
            v1 = eve.co
            v1W = mat * v1
            v1R = vav.project(region, rv3d, v1W).to_2d()
            for eve2 in connected_vertices:
                v2W = mat * eve2.co
                v2R = vav.project(region, rv3d, v2W).to_2d()
                v = v2R - v1R
                if v.length >= threshold:
                    angles.append(lock_relative.angle(v))
                else:
                    angles.append(math.pi * 2)  # 優先度最低
            eve_target = connected_vertices[angles.index(min(angles))]
            v2 = eve_target.co
            v2W = mat * v2
            if self.use_local_coords:
                transvec = v2 - v1
            else:
                transvec = v2W - v1W
            if transvec.length < threshold:
                continue
            
            if self.modal_mouse.lock:
                value = self.value
            else:
                if self.mode == 'DISTANCE':
                    value = min(max(0, self.value), transvec.length)
                else:
                    value = min(max(0.0, self.value), 1.0)
            
            if self.mode == 'DISTANCE':
                transvec.normalize()
            if self.use_local_coords:
                if self.flip:
                    newco = v2 - transvec * value
                else:
                    newco = v1 + transvec * value
            else:
                if self.flip:
                    newco = v2W - transvec * value
                else:
                    newco = v1W + transvec * value
            # edgelines
            for eve2 in connected_vertices:
                vW = mat * eve2.co
                if eve2 == eve_target:
                    translines.append((v1W, vW))
                else:
                    edgelines.append((v1W, vW))
            
            if self.use_local_coords:
                new_coordinates[i] = newco
            else:
                new_coordinates[i] = imat * newco

        # apply
        for i, vec in new_coordinates.items():
            bm.verts[i].co = vec

        bm.normal_update()
        bmesh.update_edit_mesh(actob.data, True, True)

        return {'FINISHED'}
Example #44
0
def create_prim(context, event, hit_world, normal, segments, is_autoaxis, prim_type, self):
        rv3d = context.region_data

        if prim_type == 'Plane':
            bpy.ops.mesh.primitive_plane_add(radius=1)
        elif prim_type == 'Cube':
            bpy.ops.mesh.primitive_cube_add(radius=1)
        elif prim_type == 'Circle':
            bpy.ops.mesh.primitive_circle_add(radius=1, vertices=segments[0], fill_type='NGON')
        elif prim_type == 'Sphere':
            bpy.ops.mesh.primitive_uv_sphere_add(size=1, segments=segments[0], ring_count=segments[1])
        elif prim_type == 'Cylinder':
            bpy.ops.mesh.primitive_cylinder_add(radius=1, vertices=segments[0])
        elif prim_type == 'Cone':
            bpy.ops.mesh.primitive_cone_add(radius1=1, vertices=segments[0])
        elif prim_type == 'Capsule':
            add_mesh_capsule.add_capsule(1, 1, segments[1], segments[0], context)
        elif prim_type == 'Clone':
            orig_obj = self.objects_to_clone[-1]
            bpy.ops.object.select_all(action='DESELECT')
            orig_obj.select = True

            bpy.ops.object.duplicate(linked=True, mode='DUMMY')
            new_clone = context.selected_objects[0]
            context.scene.objects.active = new_clone

        new_prim = bpy.context.object

        # get rotation vectors
        z_neg_vec = Vector((0.0, 0.0, -1.0))
        z_world_angle = z_neg_vec.angle(normal)

        if z_world_angle >= math.radians(180) or z_world_angle <= math.radians(0):
            view_cam_upvec = (rv3d.view_rotation * Vector((0.0, -1.0, 0.0))).normalized()
            view_upvec = view_cam_upvec.copy()
            view_upvec[2] = 0.0

            #if view_upvec[0] == 0 and view_upvec[1] == 0:
                #view_upvec = view_cam_upvec
            if view_upvec[0] > view_upvec[1]:
                view_upvec[0] = 1.0
                view_upvec[1] = 0.0
            else:
                view_upvec[0] = 0.0
                view_upvec[1] = 1.0

            view_upvec = view_upvec.normalized()

        else:
            view_upvec = z_neg_vec

        prim_side_vec = None

        # side vector
        if is_autoaxis is True:
            if normal[0] == 1:
                prim_side_vec = Vector((0, 1, 0))
            elif normal[0] == -1:
                prim_side_vec = Vector((0, -1, 0))
            elif normal[1] == 1:
                prim_side_vec = Vector((-1, 0, 0))
            elif normal[1] == -1:
                prim_side_vec = Vector((1, 0, 0))
            elif normal[2] == 1:
                prim_side_vec = Vector((1, 0, 0))
            elif normal[2] == -1:
                prim_side_vec = Vector((1, 0, 0))
        else:
            prim_side_vec = normal.cross(view_upvec).normalized()

        prim_front_vec = normal.cross(prim_side_vec).normalized()

        # ROTATE CUBE
        final_mat = mathu.Matrix().to_3x3()
        final_mat[0][0], final_mat[1][0], final_mat[2][0] = prim_side_vec[0], prim_side_vec[1], prim_side_vec[2]
        final_mat[0][1], final_mat[1][1], final_mat[2][1] = prim_front_vec[0], prim_front_vec[1], prim_front_vec[2]
        final_mat[0][2], final_mat[1][2], final_mat[2][2] = normal[0], normal[1], normal[2]
        #final_mat = final_mat.normalized()
        #new_prim.matrix_world = final_mat.to_4x4()
        new_prim.rotation_euler = final_mat.to_euler()

        new_prim.location = hit_world.copy()

        return new_prim, prim_side_vec, prim_front_vec
Example #45
0
	def angle_between(self, vec1, vec2):
		vec1 = Vector(vec1)
		vec2 = Vector(vec2)
		
		return vec1.angle(vec2)
Example #46
0
    def pose_layer(self, armature, bone_name, plane, tex, key):
        
        ox,oy,width,height = tex['rect']
    ##            bpy.ops.object.select_all(action='DESELECT')
        bpy.context.scene.objects.active = bpy.data.objects[armature.name]
        #bpy.ops.object.select_pattern(pattern=str(armature.name), case_sensitive=False, extend=True)
        bpy.ops.object.mode_set(mode='POSE')

        #set index
        bone = bpy.context.object.pose.bones[bone_name]
        index = key['index']

        
        if 'loc' in key:
            loc = key['loc']
    ##                loc = self.transformPoint(loc[0], loc[1], width, height)
            bone.location.x = loc[0]
            bone.location.y = -loc[1]
            bone.keyframe_insert(data_path="location", frame=index)
            self.report({'INFO'}, "  bone loc: {0} index: {1}".format(bone_name, index))

        scale = None
        
    ##            http://www.senocular.com/flash/tutorials/transformmatrix/
        if 'skew' in key :
            skew = key['skew']
            scale = (1,1)
            if 'scale' in key:
                scale = key['scale']

            #origin
            #ox, oy = self.transformPoint(ox, oy, width , height)

            #work out longest vector
            v = Vector((ox - width, 0.0,0.0))
            if height > width:
                v = Vector((0.0, oy - height, 0.0))
            
            m = mathutils.Matrix.Identity(3)
            m[0][0] = scale[0]
            m[1][1] = scale[1]
            m[0][1] = skew[0]
            m[1][0] = skew[1]

            r = m * v
            avg = v.angle(r)
            c = v.cross(r)

##            #y transform
##            y = Vector((1.0, 0.0, 0.0))
##            v = m * y
##            angle = v.angle(y)
##            c = v.cross(y)
##
##            #x transform
##            x = Vector((0.0, 1.0, 0.0))
##            v = m * x
##            angle2 = v.angle(x)

##            self.report({'INFO'}, "  angle: {0} angle2: {1}".format(angle, angle2))

##            avg = (angle + angle2)/2.0
            if c[2] < 0:
                avg *= -1

            bone.rotation_euler.z = avg
            bone.keyframe_insert(data_path="rotation_euler", frame=index)

        if 'scale' in key:
            if scale is None:
                scale = key['scale']
            bone.scale.x = scale[0]
            bone.scale.y = scale[1]
            bone.keyframe_insert(data_path="scale", frame=index)

        relative_parent = True

        if 'pivot' in key:
            pivot = key['pivot']
            #pivot is actually the same as origin (just updated in case of switching symbols per layer)
            
            #invertY 
            ox, oy = self.transformPoint(pivot[0], pivot[1], width , height)

            #tail position in image coordinates
            tx = width / 2.0
            ty = height / 2.0

            if not relative_parent:
                #set origin
                plane.location.x =  - ox + tx
                plane.location.y =  - oy
            else:
                bpy.data.armatures[armature.name].bones[bone_name].use_relative_parent = True
                bpy.data.armatures[armature.name].bones[bone_name].use_local_location = False
                plane.location.x =  (-width /2 )+ox
                plane.location.y =  (+height/2) - oy
            plane.keyframe_insert(data_path="location", frame=index)
	def execute(self, context):
		curvepoints = []
		curveobj = context.active_object
		
		bpy.ops.object.empty_add(type='PLAIN_AXES')
		parentobj = context.active_object
		parentobj.name = 'CurveForce'
		
		if len(curveobj.data.splines[0].bezier_points) > 1:
			curvepoints = [v.co for v in curveobj.data.splines[0].bezier_points]
		else:
			curvepoints = [v.co for v in curveobj.data.splines[0].points]
		
		curveobj.parent = parentobj
		context.active_object.select = False
		curveobj.select = True
		
		previousnormal = Vector([0.0,0.0,0.0])
		
		lastStrength = context.window_manager.curveForce_strength
		lastDistance = context.window_manager.curveForce_maxDist
		
		for i in range(len(curvepoints)):
			cpoint = Vector([curvepoints[i][0],curvepoints[i][1],curvepoints[i][2]])
			
			bpy.ops.object.empty_add(type='SINGLE_ARROW',location=(cpoint))
			context.active_object.name = 'ForceObj'
			# turn into forcefield
			bpy.ops.object.forcefield_toggle()
			context.active_object.field.type = 'WIND'
			
			if context.window_manager.curveForce_trailout:
				if i > 0:
					lastStrength = lastStrength * 0.9
					lastDistance = lastDistance * 0.9
			
			context.active_object.field.strength = lastStrength
			context.active_object.field.use_max_distance = True
			context.active_object.field.distance_max = lastDistance
			context.active_object.field.falloff_power = context.window_manager.curveForce_falloffPower
			
			# get the curve's direction between points
			tempnorm = Vector([0,0,0])
			if (i < len(curvepoints) - 1):
				cpoint2 = Vector([curvepoints[i + 1][0],curvepoints[i + 1][1],curvepoints[i + 1][2]])
				tempnorm = cpoint - cpoint2
				if i > 0:
					if abs(previousnormal.length) > 0.0:
						tempnorm = (tempnorm + previousnormal) / 2.0
				previousnormal = tempnorm
			else:
				if curveobj.data.splines[0].use_cyclic_u or curveobj.data.splines[0].use_cyclic_u:
					cpoint2 = Vector([curvepoints[0][0],curvepoints[0][1],curvepoints[0][2]])
					tempnorm = cpoint - cpoint2
					if abs(previousnormal.length) > 0.0:
						tempnorm = (tempnorm + previousnormal) / 2.0
					previousnormal = tempnorm
				else:
					cpoint2 = Vector([curvepoints[i - 1][0],curvepoints[i - 1][1],curvepoints[i - 1][2]])
					tempnorm = cpoint2 - cpoint
					if abs(previousnormal.length) > 0.0:
						tempnorm = (tempnorm + previousnormal) / 2.0
					previousnormal = tempnorm
			
			if abs(tempnorm.length) > 0.0:
				z = Vector((0,0,1))
				angle = tempnorm.angle(z)
				axis = z.cross(tempnorm)
				mat = Matrix.Rotation(angle, 4, axis)
				mat_world = context.active_object.matrix_world * mat
				context.active_object.matrix_world = mat_world
			
			context.active_object.parent = parentobj
			
		
		return {'FINISHED'}
Example #48
0
    def modal(self, context, event):

        mx = event.mouse_x
        my = event.mouse_y

        off = False
        if event.type == "F":
            if event.shift and event.ctrl and not (event.alt) and event.value == "PRESS":
                off = True
        if off or event.type == "ESC" or not (self.rv3d.is_perspective):
            context.window_manager.event_timer_remove(self.movetimer)

            self.cursor_restore(context)
            self.regionui.tag_redraw()
            self.region.tag_redraw()

            del bpy.types.Scene.PreSelOff
            self.area.header_text_set()

            if self.addonprefs.UseLens:
                context.space_data.lens = self.oldlens

            bpy.types.SpaceView3D.draw_handler_remove(self._handle, "WINDOW")
            return {"FINISHED"}

        if event.type in {"LEFT_SHIFT", "RIGHTSHIFT"}:
            if event.value == "PRESS":
                self.runmulti = 1.5
            else:
                self.runmulti = 1

        if event.type == "WHEELUPMOUSE":
            self.addonprefs.Speed *= 1.4
        if event.type == "WHEELDOWNMOUSE":
            self.addonprefs.Speed *= 0.8

        if event.type == self.addonprefs.mouselook:
            if event.value == "PRESS" and self.addonprefs.ActPass:
                self.acton = True
            else:
                self.acton = False
        if self.addonprefs.ActPass == False:
            self.acton = True

        if event.type in {"MOUSEMOVE", "LEFTMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}:
            if event.type == "MOUSEMOVE":
                if mx == self.xcenter and my == self.ycenter:
                    return {"RUNNING_MODAL"}
                self.cursor_reset(context)
            if self.acton and event.type == "MOUSEMOVE" and self.rv3d:
                if self.addonprefs.YMirror:
                    ymult = -1
                else:
                    ymult = 1
                smult = (self.addonprefs.MSens / 10) + 0.1
                dx = mx - self.xcenter
                dy = my - self.ycenter
                cmat = self.rv3d.view_matrix.inverted()
                dxmat = Matrix.Rotation(math.radians(-dx * smult / 5), 3, "Z")
                cmat3 = cmat.copy().to_3x3()
                cmat3.rotate(dxmat)
                cmat4 = cmat3.to_4x4()
                cmat4.translation = cmat.translation
                self.rv3d.view_matrix = cmat4.inverted()
                self.rv3d.update()
                cmat = self.rv3d.view_matrix.inverted()
                dymat = Matrix.Rotation(math.radians(dy * ymult * smult / 5), 3, self.rv3d.view_matrix[0][:3])
                cmat3 = cmat.copy().to_3x3()
                cmat3.rotate(dymat)
                cmat4 = cmat3.to_4x4()
                cmat4.translation = cmat.translation
                tempmat = cmat4.inverted()
                upvec = Vector(tempmat[1][:3])
                downvec = -Vector(tempmat[1][:3])
                if upvec.angle(Vector((0, 0, 1))) < math.radians(90):
                    if downvec.angle(Vector((0, 0, -1))) < math.radians(90):
                        self.rv3d.view_matrix = tempmat
                        self.rv3d.update()
            if mx > self.regionui.x or my < self.regionui.y:
                return {"PASS_THROUGH"}
            else:
                return {"RUNNING_MODAL"}

        if event.type in {self.addonprefs.left1, self.addonprefs.left2, self.addonprefs.left3}:
            if event.value == "PRESS":
                self.leftnav = True
            else:
                self.leftnav = False
        elif event.type in {self.addonprefs.right1, self.addonprefs.right2, self.addonprefs.right3}:
            if event.value == "PRESS":
                self.rightnav = True
            else:
                self.rightnav = False
        elif event.type in {self.addonprefs.forward1, self.addonprefs.forward2, self.addonprefs.forward3}:
            if event.value == "PRESS":
                self.forwardnav = True
            else:
                self.forwardnav = False
        elif event.type in {self.addonprefs.back1, self.addonprefs.back2, self.addonprefs.back3}:
            if event.value == "PRESS":
                self.backnav = True
            else:
                self.backnav = False
        elif event.type in {self.addonprefs.up1, self.addonprefs.up2, self.addonprefs.up3}:
            if event.value == "PRESS":
                self.upnav = True
            else:
                self.upnav = False
        elif event.type in {self.addonprefs.down1, self.addonprefs.down2, self.addonprefs.down3}:
            if event.value == "PRESS":
                self.downnav = True
            else:
                self.downnav = False

        if event.type == "TIMER":
            moved = False
            if self.leftnav:
                moved = True
                self.moveleft()
            if self.rightnav:
                moved = True
                self.moveright()
            if self.forwardnav:
                moved = True
                self.moveforward()
            if self.backnav:
                moved = True
                self.moveback()
            if self.upnav:
                moved = True
                self.moveup()
            if self.downnav:
                moved = True
                self.movedown()

            if moved:
                self.rv3d.update()
                if self.scn.FPS_Walk:
                    self.movetoground()

        if event.type == self.addonprefs.walkmode:
            if event.value == "PRESS":
                self.scn.FPS_Walk = not (self.scn.FPS_Walk)
                if self.scn.FPS_Walk:
                    self.hchange = True
                self.regionui.tag_redraw()

        if event.type == self.addonprefs.teleport:
            if event.value == "PRESS":
                eyevec = -Vector(self.rv3d.view_matrix[2][:3])
                eye = Vector(self.rv3d.view_matrix.inverted().col[3][:3])
                start = eye
                eyevec.length = 10000
                end = start + eyevec
                hit = self.scn.ray_cast(start, end)
                if hit[0]:
                    delta = hit[3] - eye
                    length = delta.length - self.addonprefs.TDistance * self.addonprefs.Scale
                    if length > 0:
                        delta.length = length
                    else:
                        return {"RUNNING_MODAL"}
                    self.rv3d.view_location += delta
                    self.rv3d.update()
                if self.scn.FPS_Walk:
                    self.movetoground()

        return {"RUNNING_MODAL"}