Exemplo n.º 1
0
def intersect_from_objects(a, b, depsgraph, eps_threshold=0.01):
    print(a.full_mesh, b.full_mesh)
    for acomp in a.full_mesh:
        acomp = BVHTree.FromObject(acomp, depsgraph, epsilon=eps_threshold)
        for bcomp in b.full_mesh:
            bcomp = BVHTree.FromObject(bcomp, depsgraph, epsilon=eps_threshold)
            print(acomp.overlap(bcomp))
            if acomp.overlap(bcomp) != []:
                return True
    return False
Exemplo n.º 2
0
def get_obj_mesh_bvht(obj, depsgraph, applyModifiers=True, world_space=True):
    if applyModifiers:
        if world_space:
            depsgraph.objects[obj.name].data.transform(obj.matrix_world)
            bvh = BVHTree.FromObject(obj, depsgraph)
            depsgraph.objects[obj.name].data.transform(obj.matrix_world.inverted())
            return bvh
        else:
            return BVHTree.FromObject(obj, depsgraph)
    else:
        if world_space:
            return BVHTree.FromPolygons([obj.matrix_world @ v.co for v in obj.data.vertices], [p.vertices for p in obj.data.polygons])
        else:
            return BVHTree.FromPolygons([v.co for v in obj.data.vertices], [p.vertices for p in obj.data.polygons])
Exemplo n.º 3
0
    def execute(self, context):
        self.points.clear()
        bvh = BVHTree.FromObject(context.object, context.depsgraph)

        # Get object data
        # TODO: Make these into properties stored external to the operator
        camera = bpy.data.objects['Camera']

        # Find out which direction the camera is pointing
        angle_x = camera.data.angle_x
        angle_y = camera.data.angle_y

        self.points = self.scan(bvh, angle_x, angle_y, self.count_x, self.count_y, 
                                camera.location, camera.rotation_euler)
        try:
            exists = bpy.data.meshes['scan']
            bpy.data.meshes.remove(exists)
        except KeyError:
            pass
        
        try:
            obj = bpy.data.objects['scan']
            bpy.data.objects.remove(obj)
        except KeyError:
            pass
        # Add a mesh to the scene containing the points
        mesh = bpy.data.meshes.new("scan")
        mesh.from_pydata(self.points, [], [])

        obj = bpy.data.objects.new('scan', mesh)
        bpy.context.collection.objects.link(obj)
        # obj.select = False

        return {'FINISHED'}
Exemplo n.º 4
0
 def process(self):
     Points, Colors = self.inputs
     obj = bpy.data.objects[self.object_ref]  # triangulate faces
     bvh = BVHTree.FromObject(obj,
                              bpy.context.scene,
                              deform=True,
                              render=False,
                              cage=False,
                              epsilon=0.0)
     point = Points.sv_get()[0]
     color = Colors.sv_get()[0]
     ran = range(3)
     image = bpy.data.images[self.image]
     width, height = image.size
     uvMap = obj.data.uv_layers[0].data
     pixels = np.array(image.pixels[:]).reshape(width, height, 4)
     for P, C in zip(point, safc(point, color)):
         loc, norm, ind, dist = bvh.find_nearest(P)
         found_poly = obj.data.polygons[ind]
         verticesIndices = found_poly.vertices
         p1, p2, p3 = [
             obj.data.vertices[verticesIndices[i]].co for i in ran
         ]
         uvMapIndices = found_poly.loop_indices
         uv1, uv2, uv3 = [uvMap[uvMapIndices[i]].uv.to_3d() for i in ran]
         V = barycentric_transform(loc, p1, p2, p3, uv1, uv2, uv3)
         Vx, Vy = int(V.x * (width - 1)), int(V.y * (height - 1))
         pixels[Vy, Vx] = C
     image.pixels = pixels.flatten().tolist()
Exemplo n.º 5
0
def CreateBVHTree(self, context):
    bvh = BVHTree.FromObject(self.ExtrudeObject,
                             context.evaluated_depsgraph_get(),
                             deform=False,
                             cage=False,
                             epsilon=0.0)
    self.BVHTree = bvh
    size = len(self.ExtrudeObject.data.vertices)
    kd = kdtree.KDTree(size)

    for i in self.ExtrudeObject.data.vertices:
        kd.insert(self.ExtrudeObject.matrix_world @ i.co.copy(), i.index)

    kd.balance()
    self.KDTree = kd

    size = len(self.MainObject.data.vertices)
    size2 = len(self.MainObject.data.edges)
    size3 = len(self.MainObject.data.polygons)
    kd2 = kdtree.KDTree(size + size2 + size3)

    for i in self.MainObject.data.vertices:
        kd2.insert(self.MainObject.matrix_world @ i.co, i.index)

    for i in self.MainObject.data.edges:
        pos = (self.MainObject.data.vertices[i.vertices[0]].co +
               self.MainObject.data.vertices[i.vertices[1]].co) / 2
        kd2.insert(self.MainObject.matrix_world @ pos, i.index + size)

    for i in self.MainObject.data.polygons:
        kd2.insert(self.MainObject.matrix_world @ i.center,
                   i.index + size + size2)

    kd2.balance()
    self.KDTreeSnap = kd2
Exemplo n.º 6
0
 def constructMapping(self):
     c = bpy.context
     owner_mesh = self.id_data
     if (not createmapping):
         return
     try:
         map_to = c.scene.objects[self.map_to_mesh]
         btree = BVHTree.FromObject(map_to, c.scene)
         n_count = len(owner_mesh.data.vertices)
         self.mapped_points.clear()
         for vid, v in enumerate(owner_mesh.data.vertices):
             mapped_point = self.mapped_points.add()
             x, y, z = v.co.to_tuple()
             co, n, i, d = btree.find_nearest(Vector((x, y, z)))
             #Also check if the normals deviation is < 45 degrees
             #                 if(co and n and i and d and (n.normalized().dot(v.normal.normalized()) > 0.75)):
             if (co and n and i and d and
                 (n.normalized().dot(v.normal.normalized()) > 0.95)):
                 #                 if(co and n and i and d):
                 face = map_to.data.polygons[i]
                 u, v, w, ratio, isinside, vid1, vid2, vid3 = getBarycentricCoordinateFromPolygonFace(
                     co, face, map_to, snapping=False, extra_info=True)
                 mapped_point.bary_ratios = [u, v, w]
                 mapped_point.bary_indices = [vid1, vid2, vid3]
             else:
                 mapped_point.is_valid = False
     except KeyError:
         print('MAP TO MESH NEEDS TO BE SET BEFORE CONSTRUCTING A MAPPING')
         raise
Exemplo n.º 7
0
def get_obj_dup_meshes(obj_snap_mode, convert_instances, context, add_active_obj=False):
    """Get all meshes"""

    objects_array = None
    active_obj = context.active_object
    if obj_snap_mode == 'Selected':
        objects_array = [obj for obj in context.selected_objects if obj != active_obj]
    else:
        objects_array = [obj for obj in context.visible_objects if obj != active_obj]

	# add active obj
    if add_active_obj is True and active_obj:
        objects_array.append(active_obj)

    listObjMatrix = []
    depsgraph = context.evaluated_depsgraph_get()

    for obj in objects_array:
        BVHTree.FromObject(obj, depsgraph)  # Update BVHTree (FIX)
        if obj.type == 'MESH':
            listObjMatrix.append((obj, obj.matrix_world.copy()))

    # convert particles and dupligroups
    if convert_instances is True:
        for dup in depsgraph.object_instances:
            if dup.is_instance:  # Real dupli instance
                obj_dupli = dup.instance_object
                listObjMatrix.append( (obj_dupli, dup.matrix_world.copy()) )

    return listObjMatrix
Exemplo n.º 8
0
 def process(self):
     Points = self.inputs[1]
     Colors = self.outputs[0]
     if Colors.is_linked:
         dps = get_sv_depsgraph()
         obj = self.inputs[0].sv_get()[0]  # triangulate faces
         bvh = BVHTree.FromObject(obj, dps)
         point = Points.sv_get()[0]
         outc = []
         ran = range(3)
         image = bpy.data.images[self.image]
         width, height = image.size  # Must be exactly the same vertically and horizontally, square image.
         pixels = np.array(image.pixels[:]).reshape(width, height, 4)
         uvMap = obj.data.uv_layers[0].data
         for P in point:
             loc, norm, ind, dist = bvh.find_nearest(P)
             found_poly = obj.data.polygons[ind]
             verticesIndices = found_poly.vertices
             p1, p2, p3 = [
                 obj.data.vertices[verticesIndices[i]].co for i in ran
             ]
             uvMapIndices = found_poly.loop_indices
             uv1, uv2, uv3 = [
                 uvMap[uvMapIndices[i]].uv.to_3d() for i in ran
             ]
             V = barycentric_transform(loc, p1, p2, p3, uv1, uv2, uv3)
             outc.append(pixels[int(V.y * (width - 1)),
                                int(V.x * (height - 1))].tolist())
         Colors.sv_set([outc])
Exemplo n.º 9
0
 def process(self):
     Points = self.inputs[0]
     Colors = self.outputs[0]
     if Colors.is_linked:
         obj = bpy.data.objects[self.object_ref]  # triangulate faces
         bvh = BVHTree.FromObject(obj,
                                  bpy.context.scene,
                                  deform=True,
                                  render=False,
                                  cage=False,
                                  epsilon=0.0)
         point = Points.sv_get()[0]
         outc = []
         ran = range(3)
         image = bpy.data.images[self.image]
         width, height = image.size
         pixels = np.array(image.pixels[:]).reshape(width, height, 4)
         uvMap = obj.data.uv_layers[0].data
         for P in point:
             loc, norm, ind, dist = bvh.find_nearest(P)
             found_poly = obj.data.polygons[ind]
             verticesIndices = found_poly.vertices
             p1, p2, p3 = [
                 obj.data.vertices[verticesIndices[i]].co for i in ran
             ]
             uvMapIndices = found_poly.loop_indices
             uv1, uv2, uv3 = [
                 uvMap[uvMapIndices[i]].uv.to_3d() for i in ran
             ]
             V = barycentric_transform(loc, p1, p2, p3, uv1, uv2, uv3)
             outc.append(pixels[int(V.x * (width - 1)),
                                int(V.y * (height - 1))].tolist())
         Colors.sv_set([outc])
Exemplo n.º 10
0
    def invoke(self, context, event):

        wm = context.window_manager
        self._timer = wm.event_timer_add(0.01, context.window)
        wm.modal_handler_add(self)

        settings = get_settings()
        self.align_meth = settings.align_meth
        self.start = time.time()
        self.align_obj = context.object
        self.base_obj = [
            obj for obj in context.selected_objects if obj != self.align_obj
        ][0]
        self.base_bvh = BVHTree.FromObject(self.base_obj, context.scene)
        self.align_obj.rotation_mode = 'QUATERNION'

        self.vlist = []
        #figure out if we need to do any inclusion/exclusion
        group_lookup = {g.name: g.index for g in self.align_obj.vertex_groups}
        if 'icp_include' in self.align_obj.vertex_groups:
            group = group_lookup['icp_include']

            for v in self.align_obj.data.vertices:
                for g in v.groups:
                    if g.group == group and g.weight > 0.9:
                        self.vlist.append(v.index)

        elif 'icp_exclude' in self.align_obj.vertex_groups:
            group = group_lookup['icp_exclude']
            for v in self.align_obj.data.vertices:
                v_groups = [g.group for g in v.groups]
                if group not in v_groups:
                    self.vlist.append(v.index)
                else:
                    for g in v.groups:
                        if g.group == group and g.weight < 0.1:
                            self.vlist.append(v.index)

        #unfortunate way to do this..
        else:
            self.vlist = [v.index for v in self.align_obj.data.vertices]
            #vlist = [range(0,len(align_obj.data.vertices]  #perhaps much smarter

        settings = get_settings()
        self.thresh = settings.min_start
        self.sample_fraction = settings.sample_fraction
        self.iters = settings.icp_iterations
        self.target_d = settings.target_d
        self.use_target = settings.use_target
        self.sample_factor = round(1 / self.sample_fraction)
        self.redraw_frequency = settings.redraw_frequency

        self.total_iters = 0
        self.converged = False
        self.conv_t_list = [self.target_d * 2] * 5  #store last 5 translations
        self.conv_r_list = [None] * 5

        return {'RUNNING_MODAL'}
Exemplo n.º 11
0
def scanmap(mapname):

    print("Initializing " + mapname + " " +
          str(datetime.datetime.now().time()))
    scale = 1
    matrix = np.zeros((SCAN_WIDTH, SCAN_WIDTH, SCAN_HEIGHT), dtype=int)

    ###########################################################################
    join_map()  # <--- Problematic area
    ###########################################################################

    scene = bpy.context.scene
    print("Creating grid")
    source_dsts = grid_init(scale, SCAN_WIDTH, SCAN_WIDTH)

    print("Initializing tree")
    for obj in bpy.context.scene.objects:
        if obj.type == 'MESH':
            objt = obj
            tree = BVHTree.FromObject(obj, scene)

    print("Starting scan of " + mapname + ": " +
          str(datetime.datetime.now().time()))
    for z in range(SCAN_HEIGHT):  # Posun na Z
        for idxx, line in enumerate(source_dsts):
            for idxy, sccube in enumerate(line):
                H_1 = [sccube[0], sccube[2] + z * scale, sccube[1]]
                v = Vector(list(H_1))
                matc = 1

                loc, norm, polid, dist = tree.find_nearest(v)
                pog = objt.data.polygons[polid]
                slot = objt.material_slots[pog.material_index]
                mat = slot.material
                if mat is not None:
                    matc = mat.diffuse_color
                if dist <= 0.9:
                    matrix[idxy][idxx][z] = matc
                #print("Pt " + str(idxx) + " " + str(idxy) + " completed at " + str(datetime.datetime.now().time()))
            #print("Line " + str(idxx) + " completed at " + str(datetime.datetime.now().time()))

        print("Map " + mapname + " layer completed: " + str(z) + " at " +
              str(datetime.datetime.now().time()))

    filename = 'export_mat_' + mapname
    print("Writing to file" + filename)
    with open(filename, 'a') as f:
        for z in range(SCAN_HEIGHT):
            f.write('\n')
            f.write('Layer: ' + str(z))
            for x in range(SCAN_WIDTH):
                f.write('\n')
                for y in range(SCAN_WIDTH):
                    f.write(str(matrix[y][x][z]))

    print(mapname + " DONE")
Exemplo n.º 12
0
def RayCast(obj, start, end):
    """ Ray cast wraper """
    scn = bpy.context.scene
    bvh = tree.FromObject(obj, scn)
    localStart = obj.matrix_world.inverted() * start
    localEnd = obj.matrix_world.inverted() * end
    direction = localEnd - localStart
    ray = bvh.ray_cast(localStart, direction,
                       get_distance(localEnd, localStart))
    return (ray[2])
Exemplo n.º 13
0
def RayCast(obj, start, end):
    """ Ray cast wraper """
    deps = bpy.context.view_layer.depsgraph
    bvh = tree.FromObject(obj, deps)
    localStart = obj.matrix_world.inverted() @ start
    localEnd = obj.matrix_world.inverted() @ end
    direction = localEnd - localStart
    ray = bvh.ray_cast(localStart, direction,
                       get_distance(localEnd, localStart))
    return (ray[2])
Exemplo n.º 14
0
 def __init__(self, scn, ground, method='OBJ'):
     self.method = method  # 'BVH' or 'OBJ'
     self.scn = scn
     self.ground = ground
     self.bbox = getBBOX.fromObj(ground, applyTransform=True)
     self.mw = self.ground.matrix_world
     self.mwi = self.mw.inverted()
     if self.method == 'BVH':
         self.bvh = BVHTree.FromObject(self.ground,
                                       bpy.context.depsgraph,
                                       deform=True)
Exemplo n.º 15
0
    def obj_ray_cast(obj, matrix):
        """Wrapper for ray casting that moves the ray into object space"""

        # get the ray relative to the object
        matrix_inv = matrix.inverted()
        ray_origin_obj = matrix_inv * ray_origin
        ray_target_obj = matrix_inv * ray_target
        ray_direction_obj = ray_target_obj - ray_origin_obj
        d = ray_direction_obj.length

        ray_direction_obj.normalize()

        # cast the ray
        if context.mode == 'OBJECT':
            #print("object")

            if obj.modifiers == 0:
                bvh = BVHTree.FromObject(obj, context.scene)
                location, normal, face_index, d = bvh.ray_cast(
                    ray_origin_obj, ray_direction_obj)
            else:
                scene = bpy.context.scene
                #obj = obj.to_mesh(scene, apply_modifiers=True, settings='PREVIEW')
                bvh = BVHTree.FromObject(obj, context.scene)
                location, normal, face_index, d = bvh.ray_cast(
                    ray_origin_obj, ray_direction_obj)
                #success, location, normal, face_index = obj.ray_cast(ray_origin_obj, ray_direction_obj)
                #bpy.data.meshes.remove(obj)

        elif context.mode == 'EDIT_MESH':
            obj.update_from_editmode()
            bvh = BVHTree.FromBMesh(bmesh.from_edit_mesh(obj.data))
            location, normal, face_index, d = bvh.ray_cast(
                ray_origin_obj, ray_direction_obj)

        if face_index != -1:
            return location, normal, face_index
        else:
            return None, None, None
    def invoke(self, context, event):
        self.x1 = self.x2 = event.mouse_region_x
        self.y1 = self.y2 = event.mouse_region_y

        # Load the object's BVH, we'll use it for ray casting
        self.bvh = BVHTree.FromObject(context.vertex_paint_object,
                                      context.view_layer.depsgraph)

        # Draw the starting pixel
        draw_face_op_main(self, context)

        context.window_manager.modal_handler_add(self)
        return {"RUNNING_MODAL"}
Exemplo n.º 17
0
 def __init__(self, mesh_filepath, samples_filepath, n_rays=1000):
     bpy.ops.import_mesh.stl(filepath = mesh_filepath)
     self.mesh = bpy.context.object
     #BVH tree is a technique for speeding up the ray - mesh intersection calculations
     self.tree = BVHTree.FromObject(self.mesh, bpy.context.scene)
     self.samples = []
     with open(samples_filepath) as samplesfile:
         rdr = csv.reader(samplesfile, quoting=csv.QUOTE_NONNUMERIC)
         for line in rdr:
             new_sample = Sample(location=Vector(line), n_rays=n_rays)
             self.samples.append(new_sample)
     for sample in self.samples:
         self.intersect_cosrays(sample=sample)
         sample.in_rock_lengths = get_lengths_from_intersections(sample.ray_intersections)
         sample.calculate_shielding_factor(particle_attenuation_length=208, m=2.2)
Exemplo n.º 18
0
def getMappedContourSegments(context, subject, reference, isocontours, reference_meshnames=[]):
    bvhtree = BVHTree.FromObject(subject, context.scene);
    
    mappedcontours = [];
    references = [];
    
    if(len(subject.multimaps)):
        for mname in reference_meshnames:
            mappedcontours.append([]);
            references.append(bpy.data.objects[mname]);
    else:
        mappedcontours.append([]);
    
        
    for segment in isocontours:
        co_start = segment['start'];
        co_end = segment['end'];
        
        co_s, n, index1, distance = bvhtree.find(co_start);
        co_e, n, index2, distance = bvhtree.find(co_end);
        
        u1, v1, w1 = getBarycentricValue(context, subject, subject.data.polygons[index1], co_s);
        u2, v2, w2 = getBarycentricValue(context, subject, subject.data.polygons[index2], co_e);
        
        if(len(subject.multimaps)):
            for index, mmap in enumerate(subject.multimaps):
                reference = references[index];
                map_co_s_1, map_co_s_2, map_co_s_3 = getTriangleMappedPoints(subject, reference, subject.data.polygons[index1], mmap.map_items);
                map_co_e_1, map_co_e_2, map_co_e_3 = getTriangleMappedPoints(subject, reference, subject.data.polygons[index2], mmap.map_items);
                
                map_co_start = getGeneralCartesianFromBarycentre([u1, v1, w1], [map_co_s_1, map_co_s_2, map_co_s_3]);
                map_co_end = getGeneralCartesianFromBarycentre([u2, v2, w2], [map_co_e_1, map_co_e_2, map_co_e_3]);
                
                mapped_segment = {'start':map_co_start, 'end':map_co_end, 'contour_index':segment['contour_index']};
                mappedcontours[index].append(mapped_segment);                
        
        else:
            map_co_s_1, map_co_s_2, map_co_s_3 = getTriangleMappedPoints(subject, reference, subject.data.polygons[index1]);
            map_co_e_1, map_co_e_2, map_co_e_3 = getTriangleMappedPoints(subject, reference, subject.data.polygons[index2]);
            
            map_co_start = getGeneralCartesianFromBarycentre([u1, v1, w1], [map_co_s_1, map_co_s_2, map_co_s_3]);
            map_co_end = getGeneralCartesianFromBarycentre([u2, v2, w2], [map_co_e_1, map_co_e_2, map_co_e_3]);
            
            mapped_segment = {'start':map_co_start, 'end':map_co_end, 'contour_index':segment['contour_index']};
            mappedcontours[0].append(mapped_segment);
    
    return mappedcontours;
Exemplo n.º 19
0
def mft_selected_objects_and_duplis(self, context):
    """Loop over (object, matrix) pairs (mesh only)"""

    listObjMatrix = []
    depsgraph = context.evaluated_depsgraph_get()

    for obj in self.drawOnObjects:
        BVHTree.FromObject(obj, depsgraph)  # Update BVHTree (FIX)
        if obj.type == 'MESH':
            listObjMatrix.append((obj, obj.matrix_world.copy()))

        # convert particles and dupligroups
        for dup in depsgraph.object_instances:
            if dup.is_instance:  # Real dupli instance
                obj_dupli = dup.instance_object
                listObjMatrix.append((obj_dupli, dup.matrix_world.copy()))

    return listObjMatrix
Exemplo n.º 20
0
    def constructMappingBVH(self, owner_mesh, map_to):
        c = bpy.context
        btree = BVHTree.FromObject(map_to, c.scene)
        n_count = len(owner_mesh.data.vertices)
        self.mapped_points.clear()
        for vid, v in enumerate(owner_mesh.data.vertices):
            mapped_point = self.mapped_points.add()
            x, y, z = v.co.to_tuple()
            co, n, i, d = btree.find_nearest(Vector((x, y, z)))
            if (co and n and i and d):
                face = map_to.data.polygons[i]
                u, v, w, ratio, isinside, vid1, vid2, vid3 = getBarycentricCoordinateFromPolygonFace(
                    co, face, map_to, snapping=False, extra_info=True)
                mapped_point.bary_ratios = [u, v, w]
                mapped_point.bary_indices = [vid1, vid2, vid3]
            else:
                mapped_point.is_valid = False

        self.mapping_is_valid = True
        return True
Exemplo n.º 21
0
    def start_object(self, obj):

        options = self.options
        context = self.context

        depsgraph = context.evaluated_depsgraph_get()

        # The object to bake.
        self.active_object = obj
        self.active_mesh = self.active_object.data

        # Objects that we'll check AO on.
        self.bake_cast_objects = BakeAO.get_cast_objects(self.context, self.options)

        print("{} object(s) contributing to bake of '{}'".format(len(self.bake_cast_objects), self.active_object.name))

        print("Creating BVH trees...")

        # Finally, get all the BVH tree objects from each object.
        self.bake_object_cache = [(bake_obj, BVHTree.FromObject(bake_obj, depsgraph), bake_obj.matrix_world.inverted(), bake_obj.matrix_world.inverted().to_3x3()) for bake_obj in self.bake_cast_objects]

        # Make sure to set our seed here, too.
        np.random.seed(self.options.seed)

        self.points_to_bake = []

        mesh = self.active_mesh
        mesh.calc_normals_split()

        print("Finding all points to be baked...")
        for poly in mesh.polygons:

            for poly_vertex_index in range(len(poly.vertices)):
                vertex_index = poly.vertices[poly_vertex_index]
                loop_index = poly.loop_indices[poly_vertex_index]

                self.points_to_bake.append(BakeVertexPoint(mesh.vertices[vertex_index].co, mesh.loops[loop_index].normal, vertex_index, loop_index))

        self.last_point_index = 0

        return False
Exemplo n.º 22
0
    def invoke(self, context, event):
        depsgraph = bpy.context.depsgraph
        ob = bpy.context.active_object
        obj_eval = depsgraph.objects.get(ob.name, None)

        particleObj = self.particleObj = obj_eval
        global EVAL_PARTICLE_OBJ
        EVAL_PARTICLE_OBJ = obj_eval
        # particleObj = self.particleObj = context.active_object
        self.diagonal = diagonal = pow(particleObj.dimensions[0], 2) + pow(particleObj.dimensions[1], 2) + \
            pow(particleObj.dimensions[2], 2)  # diagonal -to normalize some values
        self.sourceSurface_BVHT = BVHTree.FromObject(
            particleObj, context.depsgraph
        )  # only for chair with children - calculate in once on init
        self.sourceSurface_BVHT_world = get_obj_mesh_bvht(particleObj,
                                                          context.depsgraph,
                                                          applyModifiers=True,
                                                          world_space=True)

        partsysMod = self.particleObj.particle_systems.active  # use last
        diagonal = self.diagonal

        #find and add to ignore list particles with same root
        # pointsList_hair = []
        # ignore_list = []
        # for i,particle in enumerate(partsysMod.particles):  # for strand point
        #     if particle.hair_keys[0] not in pointsList_hair:
        #         pointsList_hair.append(particle.hair_keys[0])  # DONE: exclude duplicates if first strand[0] in list already
        #     else:
        #         ignore_list.append(i)
        # self.particle_duplicates_ids = ignore_list
        bpy.ops.particle.select_all(action='SELECT')
        bpy.ops.particle.remove_doubles()
        bpy.ops.particle.select_all(action='DESELECT')

        self.create_hair(context)
        self._timer = context.window_manager.event_timer_add(
            0.2, window=context.window)
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}
Exemplo n.º 23
0
 def process(self):
     bvh = []
     if self.Mod == "FromObject":
         for i in self.inputs[0].sv_get():
             bvh.append(
                 BVHTree.FromObject(i,
                                    bpy.context.scene,
                                    deform=True,
                                    render=False,
                                    cage=False,
                                    epsilon=0.0))
     elif self.Mod == "FromBMesh":
         for i in self.inputs[0].sv_get():
             bvh.append(BVHTree.FromBMesh(i))
     else:
         for i, i2 in zip(self.inputs[1].sv_get(), self.inputs[2].sv_get()):
             bvh.append(
                 BVHTree.FromPolygons(i,
                                      i2,
                                      all_triangles=False,
                                      epsilon=0.0))
     self.outputs[0].sv_set(bvh)
Exemplo n.º 24
0
    def bvhtree_from_object(self, context, object):
        # bm = bmesh.new()
        # mesh = object.to_mesh()
        # bm.from_mesh(mesh)
        # bm.transform(object.matrix_world)

        # bvhtree = BVHTree.FromBMesh(bm)

        # object.data.transform(object.matrix_world)

        # bpy.context.view_layer.depsgraph.update()
        # bm.free()

        # bvhtree = BVHTree.FromObject(object, bpy.context.view_layer.depsgraph )

        snapSurface = object
        context.view_layer.depsgraph.objects[snapSurface.name].data.transform(
            snapSurface.matrix_world)
        sourceSurface_BVHT = BVHTree.FromObject(snapSurface,
                                                context.view_layer.depsgraph)
        context.view_layer.depsgraph.objects[snapSurface.name].data.transform(
            snapSurface.matrix_world.inverted())
        return sourceSurface_BVHT
Exemplo n.º 25
0
    def execute(self, context):
        selected = bpy.context.selected_objects
        obj = selected[-1]
        surf = bpy.context.scene.objects['surface']

        loc = bpy.context.scene.cursor_location

        bvh = BVHTree.FromObject(surf, bpy.context.scene)

        loc = surf.matrix_world.inverted() * loc
        (loc, normal, index, dist) = bvh.find_nearest(loc)
        if self.use_smooth:
            normal = smooth_normal(surf, loc, index)
        loc = surf.matrix_world * loc

        bpy.ops.object.duplicate()
        new_obj = bpy.context.selected_objects[-1]

        (unused, surf_rot, unused) = surf.matrix_world.decompose()
        (unused, obj_rot, scale) = obj.matrix_world.decompose()

        normal = surf_rot * normal
        vec = obj_rot * Vector((0.0, 0.0, 1.0))

        q = vec.rotation_difference(normal)
        q = Quaternion().slerp(q, self.align_with_normal)
        mat_scale = Matrix()
        for i in range(3):
            mat_scale[i][i] = scale[i]
        new_obj.matrix_world = (Matrix.Translation(loc) *
                                q.to_matrix().to_4x4() *
                                obj_rot.to_matrix().to_4x4() * mat_scale)

        bpy.context.scene.objects.active = new_obj

        return {'FINISHED'}
    def execute(self, context):
        settings = get_addon_preferences()
        align_meth = settings.align_meth
        start = time.time()
        align_obj = context.object
        base_obj = [
            obj for obj in context.selected_objects if obj != align_obj
        ][0]
        base_bvh = BVHTree.FromObject(base_obj, context.scene)
        align_obj.rotation_mode = 'QUATERNION'

        vlist = []
        #figure out if we need to do any inclusion/exclusion
        group_lookup = {g.name: g.index for g in align_obj.vertex_groups}
        if 'icp_include' in align_obj.vertex_groups:
            group = group_lookup['icp_include']

            for v in align_obj.data.vertices:
                for g in v.groups:
                    if g.group == group and g.weight > 0.9:
                        vlist.append(v.index)

        elif 'icp_exclude' in align_obj.vertex_groups:
            group = group_lookup['icp_exclude']
            for v in align_obj.data.vertices:
                v_groups = [g.group for g in v.groups]
                if group not in v_groups:
                    vlist.append(v.index)
                else:
                    for g in v.groups:
                        if g.group == group and g.weight < 0.1:
                            vlist.append(v.index)

        #unfortunate way to do this..
        else:
            vlist = [v.index for v in align_obj.data.vertices]

        settings = get_addon_preferences()
        thresh = settings.min_start
        sample = settings.sample_fraction
        iters = settings.icp_iterations
        target_d = settings.target_d
        use_target = settings.use_target
        factor = round(1 / sample)

        n = 0
        converged = False
        conv_t_list = [target_d * 2] * 5  #store last 5 translations
        conv_r_list = [None] * 5

        while n < iters and not converged:

            (A, B, d_stats) = make_pairs(align_obj,
                                         base_obj,
                                         base_bvh,
                                         vlist,
                                         thresh,
                                         factor,
                                         calc_stats=use_target)

            if align_meth == '0':  #rigid transform
                M = affine_matrix_from_points(A,
                                              B,
                                              shear=False,
                                              scale=False,
                                              usesvd=True)
            elif align_meth == '1':  # rot, loc, scale
                M = affine_matrix_from_points(A,
                                              B,
                                              shear=False,
                                              scale=True,
                                              usesvd=True)

            new_mat = Matrix.Identity(4)
            for y in range(0, 4):
                for z in range(0, 4):
                    new_mat[y][z] = M[y][z]

            align_obj.matrix_world = align_obj.matrix_world * new_mat
            trans = new_mat.to_translation()
            quat = new_mat.to_quaternion()

            align_obj.update_tag()
            context.scene.update()

            if d_stats:
                i = fmod(n, 5)
                conv_t_list[i] = trans.length
                conv_r_list[i] = abs(quat.angle)

                if all(d < target_d for d in conv_t_list):
                    converged = True

                    print('Converged in %s iterations' % str(n + 1))
                    print('Final Translation: %f ' % conv_t_list[i])
                    print('Final Avg Dist: %f' % d_stats[0])
                    print('Final St Dev %f' % d_stats[1])
                    print('Avg last 5 rotation angle: %f' %
                          np.mean(conv_r_list))

            n += 1
        time_taken = time.time() - start
        if use_target and not converged:
            print('Maxed out iterations')
            print('Final Translation: %f ' % conv_t_list[i])
            print('Final Avg Dist: %f' % d_stats[0])
            print('Final St Dev %f' % d_stats[1])
            print('Avg last 5 rotation angle: %f' % np.mean(conv_r_list))

        print('Aligned obj in %f sec' % time_taken)
        return {'FINISHED'}
Exemplo n.º 27
0
    def execute(self, context):
        ch = bpy.context.active_object
        sel = bpy.context.selected_objects
        obj = sel[0] if sel[1] == ch else sel[1]
        amt = ch.parent

        bvh = BVHTree.FromObject(ch, bpy.context.scene)

        obj.vertex_groups.clear()

        for g in ch.vertex_groups:
            obj.vertex_groups.new(g.name)

        closest_idx = np.zeros(len(obj.data.vertices), dtype=np.int)
        closest_dist = np.zeros(len(obj.data.vertices))

        for v in obj.data.vertices:
            loc = obj.matrix_world * v.co  # to world
            loc = ch.matrix_world.inverted() * loc  # to child
            (loc, normal, index, dist) = bvh.find_nearest(loc)
            # loc = ch.matrix_world * loc # to world
            # loc = obj.matrix_world.inverted() * loc # to obj
            # v.co = loc

            closest_idx[v.index] = index
            closest_dist[v.index] = dist

        ttl = 5

        n_obj_v = len(obj.data.vertices)
        obj_connected = [[] for i in range(n_obj_v)]

        for e in obj.data.edges:
            v_1 = e.vertices[0]
            v_2 = e.vertices[1]
            obj_connected[v_1].append(v_2)
            obj_connected[v_2].append(v_1)

        n_ch_v = len(ch.data.vertices)
        ch_connected = [[] for i in range(n_ch_v)]

        for e in ch.data.edges:
            v_1 = e.vertices[0]
            v_2 = e.vertices[1]
            ch_connected[v_1].append(v_2)
            ch_connected[v_2].append(v_1)

        # reassigned = True
        '''for i in range(10):
            print('i:', i)
            reassigned = 0
            for v in obj.data.vertices:
                if v.index % 100 == 0:
                    print('v.index:', v.index, 'reassigned:', reassigned)
                for neigh in obj_connected[v.index]:
                    # print('neigh:', neigh)
                    delta = np.linalg.norm(v.co - obj.data.vertices[neigh].co)
                    thresh = 50 * delta
                    
                    w_dist = _walk_dist(ch.data.vertices,
                        closest_idx[neigh],
                        closest_idx[v.index],
                        ch_connected, thresh)
                    # print('_walk_dist done')
                    # delta = closest_dist[v.index] - closest_dist[neigh]
                    
                    if w_dist > thresh:
                        closest_idx[v.index] = closest_idx[neigh]
                        closest_dist[v.index] = np.linalg.norm(
                            obj.data.vertices[v.index].co -
                            ch.data.vertices[closest_idx[v.index]].co)
                        reassigned += 1
                        # print('reassigned!')
                        break
            if reassigned == 0:
                break'''

        for v in obj.data.vertices:
            # N = _neighbors(obj.data.vertices, v.index, ttl, connected)

            # dists = closest_dist[N]
            # indices = closest_idx[N]
            # order = np.argsort(dists)
            # dists = dists[order]
            # indices = indices[order]
            # med_dist = dists[len(N) // 2]
            # med_idx = indices[len(N) // 2]

            index = closest_idx[v.index]
            f_ch = ch.data.polygons[index]
            weights = [0.0] * len(obj.vertex_groups)
            n_vert = len(f_ch.vertices)
            for v_ch_idx in f_ch.vertices:
                v_ch = ch.data.vertices[v_ch_idx]
                for ge in v_ch.groups:
                    weights[ge.group] += ge.weight

            for g in obj.vertex_groups:
                if weights[g.index] > 0:
                    g.add([v.index], weights[g.index] / n_vert, 'ADD')

        obj.parent = amt
        obj.matrix_parent_inverse = amt.matrix_world.inverted()

        mod = obj.modifiers.new('Armature', 'ARMATURE')
        mod.object = amt

        return {'FINISHED'}
Exemplo n.º 28
0
    def execute_slow_ParallelTransport(self, context):
        snapTargetName = context.active_object.targetObjPointer
        snapTarget = bpy.data.objects[snapTargetName]
        Curve = context.active_object

        #apply transformation to prevetn 90 deg offset bug
        snapTarget.data.transform(snapTarget.matrix_world)
        if Curve.mode == 'EDIT':  # to make transfrom() work in edit mode
            bpy.ops.object.mode_set(mode="OBJECT")
            Curve.data.transform(Curve.matrix_world)
            bpy.ops.object.mode_set(mode="EDIT")
        else:
            Curve.data.transform(Curve.matrix_world)

        if self.resetTilt:
            self.resetTiltFunction(Curve.data)

        curveData = Curve.data
        snapTarget_BVHT_tree = BVHTree.FromObject(
            snapTarget,
            context.depsgraph)  # render eg use subsurf render settin

        for i, polyline in enumerate(curveData.splines):  # for strand point
            strand_len = len(
                polyline.bezier_points) if polyline.type == 'BEZIER' else len(
                    polyline.points)
            if polyline.type == 'NURBS' or polyline.type == 'POLY':
                if self.onlySelection:
                    spline_selection_mask = np.zeros(strand_len, dtype=np.bool)
                    polyline.points.foreach_get('select',
                                                spline_selection_mask)
                    if not any(spline_selection_mask):
                        continue  # if not even one pointis selected
                points = polyline.points
            else:
                if self.onlySelection:
                    spline_selection_mask = np.zeros(strand_len, dtype=np.bool)
                    polyline.bezier_points.foreach_get('select_control_point',
                                                       spline_selection_mask)
                    if not any(spline_selection_mask):
                        continue  # if not even one point is selected
                points = polyline.bezier_points
            # helper for tangetnt function (to detect last point on cuve)
            prevAngle = 0
            corrective_angles = np.zeros(strand_len, dtype=np.float16)
            current_tilt = np.zeros(strand_len, dtype=np.float16)
            points.foreach_get('tilt', current_tilt)
            (T, N) = parallel_transport_TNB(points)
            strand_Ts = [Vector((i)) for i in T]
            strand_Ns = [Vector((i)) for i in N]
            for j, (point_T, point_N,
                    curvePoint) in enumerate(zip(strand_Ts, strand_Ns,
                                                 points)):  # for strand point
                pointOnMeshLoc, normSnapTarget, face_index, distance, isInside = \
                    self.find_nearest(curvePoint.co.xyz, snapTarget_BVHT_tree, 11)
                vecSurfaceHit = curvePoint.co.xyz - pointOnMeshLoc
                if isInside:  # if curve point is outside snapSurface flip it
                    vecSurfaceHit *= -1
                vectSurfHitProjected90 = point_T.cross(vecSurfaceHit)
                vectSurfHitProjectedToTangent = vectSurfHitProjected90.cross(
                    point_T)
                # angle = biTangentCurve.angle(vectSurfHitProjectedToTangent)  #unsigned angle <0, 180>
                angle = self.angle_signed(
                    point_N, vectSurfHitProjectedToTangent,
                    point_T) - math.pi / 2  # a,b, vN  - signed (-180, 180)
                corrective_angles[j] = angle + 1.57  # add 90deg fix
                prevAngle = angle
            if strand_len >= 4:
                corrective_angles[1] = (corrective_angles[2] +
                                        corrective_angles[3]) / 2
                corrective_angles[0] = (corrective_angles[1] +
                                        corrective_angles[2]) / 2
            elif strand_len == 3:
                corrective_angles[0] = (corrective_angles[1] +
                                        corrective_angles[2]) / 2
            if self.onlySelection:
                current_tilt[spline_selection_mask] += corrective_angles[
                    spline_selection_mask]
            else:
                current_tilt = corrective_angles
            points.foreach_set('tilt', current_tilt)  # in radians
            # manually smooth first two points cos they are usually broken

        snapTarget.data.transform(snapTarget.matrix_world.inverted())
        if Curve.mode == 'EDIT':  # to make transfrom() work in edit mode
            bpy.ops.object.mode_set(mode="OBJECT")
            Curve.data.transform(Curve.matrix_world.inverted())
            bpy.ops.object.transform_apply(location=False,
                                           rotation=True,
                                           scale=False)
            bpy.ops.object.mode_set(mode="EDIT")
        else:
            Curve.data.transform(Curve.matrix_world.inverted())
            bpy.ops.object.transform_apply(location=False,
                                           rotation=True,
                                           scale=False)
        return {"FINISHED"}
Exemplo n.º 29
0
    def execute(self, context):
        obj = bpy.context.active_object
        surf = bpy.context.scene.objects['surface']
        growth = bpy.context.scene.objects['growth']

        verts_growth = growth.data.vertices
        verts_surf = surf.data.vertices
        verts_obj = obj.data.vertices

        bvh_surf = BVHTree.FromObject(surf, bpy.context.scene)
        bvh_obj = BVHTree.FromObject(obj, bpy.context.scene)

        connected = [[] for i in range(len(verts_surf))]
        for e in surf.data.edges:
            connected[e.vertices[0]].append(e.vertices[1])
            connected[e.vertices[1]].append(e.vertices[0])

        obj_z = [v.co[2] for v in verts_obj]
        obj_h = max(obj_z) - min(obj_z)
        print('obj_h:', obj_h)

        obj_radius = [np.linalg.norm([v.co[0], v.co[1], 0]) for v in verts_obj]
        obj_radius = np.max(obj_radius)
        print('obj_radius:', obj_radius)

        loc = growth.matrix_world * verts_growth[-1].co
        loc = surf.matrix_world.inverted() * loc
        (loc, normal, index, dist) = bvh_surf.find_nearest(loc)
        dist = [
            np.linalg.norm(verts_surf[v].co - loc)
            for v in surf.data.polygons[index].vertices
        ]
        v_from = surf.data.polygons[index].vertices[np.argmin(dist)]
        f_from = index
        print('v_from:', v_from, 'f_from:', f_from)

        loc = bpy.context.scene.cursor_location
        loc = surf.matrix_world.inverted() * loc
        (loc, normal, index, dist) = bvh_surf.find_nearest(loc)
        dist = [
            np.linalg.norm(verts_surf[v].co - loc)
            for v in surf.data.polygons[index].vertices
        ]
        v_to = surf.data.polygons[index].vertices[np.argmin(dist)]
        f_to = index
        print('v_to:', v_to, 'f_to:', f_to)

        (cumdist, path) = _dijkstra(verts_surf, v_from, v_to, connected)

        for i in range(1, len(path)):
            v = verts_surf[path[i]]
            z = cumdist[i]

            obj_z = np.mod(z, obj_h)
            print('v.co:', v.co, 'z:', z, 'obj_z:', obj_z)

            (loc, normal, index, dist) = bvh_surf.find_nearest(v.co)
            normal = _smooth_normal(surf, loc, index)

            radius = []
            for angle in np.linspace(0, 2 * np.pi, 10)[:-1]:
                dx = np.cos(angle)
                dy = np.sin(angle)
                (loc, _, _, _) = bvh_obj.ray_cast(
                    Vector((dx * obj_radius * 2, dy * obj_radius * 2, obj_z)),
                    Vector((-dx, -dy, 0)))
                radius.append(np.linalg.norm([loc[0], loc[1], 0]))
            print('radius:', radius)
            radius = np.max(radius)

            verts_growth.add(1)
            verts_growth[-1].co = v.co + Vector(radius * normal)

        return {'FINISHED'}
Exemplo n.º 30
0
    def invoke(self, context, event):
        active_obj = context.active_object
        sourceSurface = None
        self.source_grid_mesh = None
        if active_obj.type == 'CURVE':
            if active_obj.hair_grid_settings.was_created_from_grid and active_obj.targetObjPointer in bpy.data.objects.keys(
            ):  # obtain source grid surface, that hair was generated from
                self.source_curve = active_obj.name  # somewho if I refrence sourceSurface, then in execute it is lost. So use name instead
                sourceSurface = bpy.data.objects[active_obj.targetObjPointer]
            else:
                self.report({
                    'INFO'
                }, 'Selected is not recognized as generated from grid surface. Cancelling'
                            )
                return {"CANCELLED"}
        elif active_obj.type == 'MESH':
            for face in active_obj.data.polygons:
                if len(face.edge_keys) != 4:
                    self.report({
                        'INFO'
                    }, 'Non quad polygon detected. This operation works on quad only meshes'
                                )
                    return {"CANCELLED"}
            sourceSurface = active_obj

        if sourceSurface is None:
            self.report({
                'INFO'
            }, 'Select grid mesh type or generated curve hairs first. Cancelling'
                        )
            return {"CANCELLED"}
        if self.source_curve:  #if operator wa executed on curve use its settigns
            self.load_settings(bpy.data.objects[
                self.source_curve])  #load settings from cure hairs
        else:
            self.load_settings(sourceSurface)  #else from target mesh

        # Get a BMesh representation
        me = sourceSurface.data
        bm = bmesh.new()  # create an empty BMesh
        bm.from_mesh(me)
        bm.edges.ensure_lookup_table()
        sharp_edges = [e for e in bm.edges if not e.smooth]
        if len(sharp_edges) == 0:
            self.report(
                {'INFO'},
                'No edges marked as sharp! Mark one border edge loop as sharp')
            bm.free()
            return {"CANCELLED"}
        sharp_boundary_edges = [e for e in sharp_edges if e.is_boundary]
        if len(sharp_boundary_edges) == 0:
            self.report({
                'INFO'
            }, 'None of sharp edges are boundary edges! Mark one border edge loop as sharp'
                        )
            bm.free()
            return {"CANCELLED"}
        if len(sharp_boundary_edges) == 1:
            self.hairMethod = 'vert'
        bm.free()

        self.sourceSurface_BVHT = BVHTree.FromObject(
            sourceSurface, context.depsgraph)  # TODO: broken in 2.8
        # to normalize some values
        self.diagonal = math.sqrt(
            pow(sourceSurface.dimensions[0], 2) +
            pow(sourceSurface.dimensions[1], 2) +
            pow(sourceSurface.dimensions[2], 2))
        self.source_grid_mesh = sourceSurface.name  # somewho if I refrence sourceSurface, then in execute it is lost. So use name instead
        return self.execute(context)