예제 #1
0
static void
value_combo_spin_edited (GtkCellRendererText *cell,
                         const gchar *path,
                         const gchar *new_text,
                         GladeEPropAttrs *eprop_attrs)
{
  GtkTreeIter iter;
  PangoAttrType type;

  if (!gtk_tree_model_get_iter_from_string (eprop_attrs->model, &iter, path))
    return;

  gtk_tree_model_get (eprop_attrs->model, &iter, COLUMN_TYPE, &type, -1);

  /* Reset the column */
  if (new_text && (*new_text == '\0' || strcmp (new_text, _("None")) == 0))
    {
      gtk_list_store_set (GTK_LIST_STORE (eprop_attrs->model), &iter,
                          COLUMN_TEXT, _("<Enter Value>"),
                          COLUMN_NAME_WEIGHT, PANGO_WEIGHT_NORMAL,
                          COLUMN_TEXT_STYLE, PANGO_STYLE_ITALIC,
                          COLUMN_TEXT_FG, "Grey", -1);
    }
  else
    gtk_list_store_set (GTK_LIST_STORE (eprop_attrs->model), &iter,
                        COLUMN_TEXT, new_text,
                        COLUMN_NAME_WEIGHT, PANGO_WEIGHT_BOLD,
                        COLUMN_TEXT_STYLE, PANGO_STYLE_NORMAL,
                        COLUMN_TEXT_FG, "Black", -1);

  sync_object (eprop_attrs, FALSE);

}
예제 #2
0
void FEMSystem::mesh_position_set()
{
  // If we don't need to move the mesh, we're done
  if (_mesh_sys != this)
    return;

  MeshBase& mesh = this->get_mesh();

  AutoPtr<DiffContext> con = this->build_context();
  FEMContext &_femcontext = libmesh_cast_ref<FEMContext&>(*con);
  this->init_context(_femcontext);

  // Move every mesh element we can
  MeshBase::const_element_iterator el =
    mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator end_el =
    mesh.active_local_elements_end();

  for ( ; el != end_el; ++el)
    {
      // We need the algebraic data
      _femcontext.pre_fe_reinit(*this, *el);
      // And when asserts are on, we also need the FE so
      // we can assert that the mesh data is of the right type.
#ifndef NDEBUG
      _femcontext.elem_fe_reinit();
#endif

      // This code won't handle moving subactive elements
      libmesh_assert(!_femcontext.elem->has_children());

      _femcontext.elem_position_set(1.);
    }

  // We've now got positions set on all local nodes (and some
  // semilocal nodes); let's request positions for non-local nodes
  // from their processors.

  SyncNodalPositions sync_object(mesh);
  Parallel::sync_dofobject_data_by_id
    (mesh.nodes_begin(), mesh.nodes_end(), sync_object);
}
예제 #3
0
static void
value_toggled (GtkCellRendererToggle *cell_renderer,
               gchar *path,
               GladeEPropAttrs *eprop_attrs)
{
  gboolean active;
  GtkTreeIter iter;
  PangoAttrType type;

  if (!gtk_tree_model_get_iter_from_string (eprop_attrs->model, &iter, path))
    return;

  gtk_tree_model_get (eprop_attrs->model, &iter,
                      COLUMN_TOGGLE_DOWN, &active, COLUMN_TYPE, &type, -1);

  gtk_list_store_set (GTK_LIST_STORE (eprop_attrs->model), &iter,
                      COLUMN_NAME_WEIGHT, PANGO_WEIGHT_BOLD,
                      COLUMN_TOGGLE_DOWN, !active, -1);

  sync_object (eprop_attrs, FALSE);
}
예제 #4
0
static int sync_node(PNode *n)
{
	PNode	*target;
	int	sync = 1;

	if((target = nodedb_lookup(n->id)) == NULL)
	{
		LOG_WARN(("Couldn't look up existing (target) node for %u--aborting sync", n->id));
		return 0;
	}
	/* First sync node-head data, such as name and tags. */
	sync &= sync_head(n, target);
	switch(n->type)
	{
	case V_NT_OBJECT:
		sync &= sync_object((NodeObject *) n, (NodeObject *) target);
		break;
	case V_NT_GEOMETRY:
		sync &= sync_geometry((NodeGeometry *) n, (NodeGeometry *) target);
		break;
	case V_NT_MATERIAL:
		sync &= sync_material((NodeMaterial *) n, (NodeMaterial *) target);
		break;
	case V_NT_BITMAP:
		sync &= sync_bitmap((NodeBitmap *) n, (NodeBitmap *) target);
		break;
	case V_NT_TEXT:
		sync &= sync_text((NodeText *) n, (NodeText *) target);
		break;
	case V_NT_CURVE:
		sync &= sync_curve((NodeCurve *) n, (NodeCurve *) target);
		break;
	case V_NT_AUDIO:
		sync &= sync_audio((NodeAudio *) n, (NodeAudio *) target);
		break;
	default:
		printf("Can't sync node of type %d\n", n->type);
	}
	return sync;
}
예제 #5
0
void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
{
	/* layer data */
	uint scene_layer = render_layer.scene_layer;
	
	if(!motion) {
		/* prepare for sync */
		light_map.pre_sync();
		mesh_map.pre_sync();
		object_map.pre_sync();
		mesh_synced.clear();
	}

	/* object loop */
	BL::Scene::objects_iterator b_ob;

	for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
		bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render();
		uint ob_layer = get_layer(b_ob->layers());

		if(!hide && (ob_layer & scene_layer)) {
			if(b_ob->is_duplicator()) {
				/* dupli objects */
				object_create_duplilist(*b_ob, b_scene);

				BL::Object::dupli_list_iterator b_dup;
				int b_index = 0;

				for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
					Transform tfm = get_transform(b_dup->matrix());
					BL::Object b_dup_ob = b_dup->object();
					bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();

					if(!(b_dup->hide() || dup_hide))
						sync_object(*b_ob, b_index, b_dup_ob, tfm, ob_layer, motion);

					b_index++;
				}

				object_free_duplilist(*b_ob);

				hide = true;
			}

			/* check if we should render or hide particle emitter */
			BL::Object::particle_systems_iterator b_psys;
			bool render_emitter = false;

			for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
				if(b_psys->settings().use_render_emitter()) {
					hide = false;
					render_emitter = true;
				}
				else if(!render_emitter)
					hide = true;
			}

			if(!hide) {
				/* object itself */
				Transform tfm = get_transform(b_ob->matrix_world());
				sync_object(*b_ob, 0, *b_ob, tfm, ob_layer, motion);
			}
		}
	}

	if(!motion) {
		sync_background_light();

		/* handle removed data and modified pointers */
		if(light_map.post_sync())
			scene->light_manager->tag_update(scene);
		if(mesh_map.post_sync())
			scene->mesh_manager->tag_update(scene);
		if(object_map.post_sync())
			scene->object_manager->tag_update(scene);
		mesh_synced.clear();
	}
}
예제 #6
0
void LaplaceMeshSmoother::smooth(unsigned int n_iterations)
{
  if (!_initialized)
    this->init();

  // Don't smooth the nodes on the boundary...
  // this would change the mesh geometry which
  // is probably not something we want!
  std::vector<bool> on_boundary;
  MeshTools::find_boundary_nodes(_mesh, on_boundary);

  // Ensure that the find_boundary_nodes() function returned a properly-sized vector
  if (on_boundary.size() != _mesh.max_node_id())
    libmesh_error_msg("MeshTools::find_boundary_nodes() returned incorrect length vector!");

  // We can only update the nodes after all new positions were
  // determined. We store the new positions here
  std::vector<Point> new_positions;

  for (unsigned int n=0; n<n_iterations; n++)
    {
      new_positions.resize(_mesh.max_node_id());

      {
        MeshBase::node_iterator       it     = _mesh.local_nodes_begin();
        const MeshBase::node_iterator it_end = _mesh.local_nodes_end();
        for (; it != it_end; ++it)
          {
            Node * node = *it;

            if (node == libmesh_nullptr)
              libmesh_error_msg("[" << _mesh.processor_id() << "]: Node iterator returned NULL pointer.");

            // leave the boundary intact
            // Only relocate the nodes which are vertices of an element
            // All other entries of _graph (the secondary nodes) are empty
            if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0))
              {
                Point avg_position(0.,0.,0.);

                for (unsigned j=0; j<_graph[node->id()].size(); ++j)
                  {
                    // Will these nodal positions always be available
                    // or will they refer to remote nodes?  This will
                    // fail an assertion in the latter case, which
                    // shouldn't occur if DistributedMesh is working
                    // correctly.
                    const Point & connected_node = _mesh.point(_graph[node->id()][j]);

                    avg_position.add( connected_node );
                  } // end for(j)

                // Compute the average, store in the new_positions vector
                new_positions[node->id()] = avg_position / static_cast<Real>(_graph[node->id()].size());
              } // end if
          } // end for
      } // end scope


      // now update the node positions (local node positions only)
      {
        MeshBase::node_iterator it           = _mesh.local_nodes_begin();
        const MeshBase::node_iterator it_end = _mesh.local_nodes_end();
        for (; it != it_end; ++it)
          {
            Node * node = *it;

            if (!on_boundary[node->id()] && (_graph[node->id()].size() > 0))
              {
                // Should call Point::op=
                // libMesh::out << "Setting node id " << node->id() << " to position " << new_positions[node->id()];
                _mesh.node_ref(node->id()) = new_positions[node->id()];
              }
          } // end for
      } // end scope

      // Now the nodes which are ghosts on this processor may have been moved on
      // the processors which own them.  So we need to synchronize with our neighbors
      // and get the most up-to-date positions for the ghosts.
      SyncNodalPositions sync_object(_mesh);
      Parallel::sync_dofobject_data_by_id
        (_mesh.comm(), _mesh.nodes_begin(), _mesh.nodes_end(), sync_object);

    } // end for n_iterations

  // finally adjust the second order nodes (those located between vertices)
  // these nodes will be located between their adjacent nodes
  // do this element-wise
  MeshBase::element_iterator       el  = _mesh.active_elements_begin();
  const MeshBase::element_iterator end = _mesh.active_elements_end();

  for (; el != end; ++el)
    {
      // Constant handle for the element
      const Elem * elem = *el;

      // get the second order nodes (son)
      // their element indices start at n_vertices and go to n_nodes
      const unsigned int son_begin = elem->n_vertices();
      const unsigned int son_end   = elem->n_nodes();

      // loop over all second order nodes (son)
      for (unsigned int son=son_begin; son<son_end; son++)
        {
          // Don't smooth second-order nodes which are on the boundary
          if (!on_boundary[elem->node_id(son)])
            {
              const unsigned int n_adjacent_vertices =
                elem->n_second_order_adjacent_vertices(son);

              // calculate the new position which is the average of the
              // position of the adjacent vertices
              Point avg_position(0,0,0);
              for (unsigned int v=0; v<n_adjacent_vertices; v++)
                avg_position +=
                  _mesh.point( elem->node_id( elem->second_order_adjacent_vertex(son,v) ) );

              _mesh.node_ref(elem->node_id(son)) = avg_position / n_adjacent_vertices;
            }
        }
    }
}
예제 #7
0
void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, float motion_time)
{
  /* layer data */
  bool motion = motion_time != 0.0f;

  if (!motion) {
    /* prepare for sync */
    light_map.pre_sync();
    mesh_map.pre_sync();
    object_map.pre_sync();
    particle_system_map.pre_sync();
    motion_times.clear();
  }
  else {
    mesh_motion_synced.clear();
  }

  /* initialize culling */
  BlenderObjectCulling culling(scene, b_scene);

  /* object loop */
  bool cancel = false;
  bool use_portal = false;

  BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();

  BL::Depsgraph::object_instances_iterator b_instance_iter;
  for (b_depsgraph.object_instances.begin(b_instance_iter);
       b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
       ++b_instance_iter) {
    BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
    BL::Object b_ob = b_instance.object();

    /* load per-object culling data */
    culling.init_object(scene, b_ob);

    /* test if object needs to be hidden */
    const bool show_self = b_instance.show_self();
    const bool show_particles = b_instance.show_particles();

    if (show_self || show_particles) {
      /* object itself */
      sync_object(b_depsgraph,
                  b_view_layer,
                  b_instance,
                  motion_time,
                  show_self,
                  show_particles,
                  culling,
                  &use_portal);
    }

    cancel = progress.get_cancel();
  }

  progress.set_sync_status("");

  if (!cancel && !motion) {
    sync_background_light(use_portal);

    /* handle removed data and modified pointers */
    if (light_map.post_sync())
      scene->light_manager->tag_update(scene);
    if (mesh_map.post_sync())
      scene->mesh_manager->tag_update(scene);
    if (object_map.post_sync())
      scene->object_manager->tag_update(scene);
    if (particle_system_map.post_sync())
      scene->particle_system_manager->tag_update(scene);
  }

  if (motion)
    mesh_motion_synced.clear();
}
예제 #8
0
void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
{
	/* layer data */
	uint scene_layer = render_layer.scene_layer;
	
	if(!motion) {
		/* prepare for sync */
		light_map.pre_sync();
		mesh_map.pre_sync();
		object_map.pre_sync();
		mesh_synced.clear();
		particle_system_map.pre_sync();
	}
	else {
		mesh_motion_synced.clear();
	}

	/* object loop */
	BL::Scene::objects_iterator b_ob;
	BL::Scene b_sce = b_scene;
	/* modifier result type (not exposed as enum in C++ API)
	 * 1 : eModifierMode_Realtime
	 * 2 : eModifierMode_Render
	 */
	int dupli_settings = preview ? 1 : 2;

	bool cancel = false;

	for(; b_sce && !cancel; b_sce = b_sce.background_set()) {
		for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end() && !cancel; ++b_ob) {
			bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render();
			uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob));
			hide = hide || !(ob_layer & scene_layer);

			if(!hide) {
				progress.set_sync_status("Synchronizing object", (*b_ob).name());

				if(b_ob->is_duplicator() && !object_render_hide_duplis(*b_ob)) {
					/* dupli objects */
					b_ob->dupli_list_create(b_scene, dupli_settings);

					BL::Object::dupli_list_iterator b_dup;

					for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
						Transform tfm = get_transform(b_dup->matrix());
						BL::Object b_dup_ob = b_dup->object();
						bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();
						bool in_dupli_group = (b_dup->type() == BL::DupliObject::type_GROUP);
						bool hide_tris;

						if(!(b_dup->hide() || dup_hide || object_render_hide(b_dup_ob, false, in_dupli_group, hide_tris))) {
							/* the persistent_id allows us to match dupli objects
							 * between frames and updates */
							BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id();

							/* sync object and mesh or light data */
							Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion, hide_tris);

							/* sync possible particle data, note particle_id
							 * starts counting at 1, first is dummy particle */
							if(!motion && object) {
								sync_dupli_particle(*b_ob, *b_dup, object);
							}

						}
					}

					b_ob->dupli_list_clear();
				}

				/* test if object needs to be hidden */
				bool hide_tris;

				if(!object_render_hide(*b_ob, true, true, hide_tris)) {
					/* object itself */
					Transform tfm = get_transform(b_ob->matrix_world());
					sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion, hide_tris);
				}
			}

			cancel = progress.get_cancel();
		}
	}

	progress.set_sync_status("");

	if(!cancel && !motion) {
		sync_background_light();

		/* handle removed data and modified pointers */
		if(light_map.post_sync())
			scene->light_manager->tag_update(scene);
		if(mesh_map.post_sync())
			scene->mesh_manager->tag_update(scene);
		if(object_map.post_sync())
			scene->object_manager->tag_update(scene);
		if(particle_system_map.post_sync())
			scene->particle_system_manager->tag_update(scene);
		mesh_synced.clear();
	}

	if(motion)
		mesh_motion_synced.clear();
}
예제 #9
0
static void
value_icon_activate (GtkCellRendererToggle *cell_renderer,
                     gchar *path,
                     GladeEPropAttrs *eprop_attrs)
{
  GtkWidget *dialog;
  GtkTreeIter iter;
  PangoAttrType type;
  AttrEditType edit_type;
  GdkRGBA color = {0,};
  gchar *text = NULL, *new_text;

  /* Find type etc */
  if (!gtk_tree_model_get_iter_from_string (eprop_attrs->model, &iter, path))
    return;

  gtk_tree_model_get (eprop_attrs->model, &iter,
                      COLUMN_TEXT, &text,
                      COLUMN_TYPE, &type, 
		      COLUMN_EDIT_TYPE, &edit_type, -1);

  /* Launch dialog etc. */
  switch (edit_type)
    {
      case EDIT_COLOR:
        dialog = gtk_color_chooser_dialog_new (_("Select a color"),
                                               GTK_WINDOW (glade_app_get_window ()));
        /* Get response etc... */
        if (text && gdk_rgba_parse (&color, text))
          gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (dialog), &color);

        gtk_dialog_run (GTK_DIALOG (dialog));

        gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &color);
        
        /* Use GdkColor string format */
        if (((guint8)(color.red * 0xFF)) * 0x101 == (guint16)(color.red * 0xFFFF) &&
            ((guint8)(color.green * 0xFF)) * 0x101 == (guint16)(color.green * 0xFFFF) &&
            ((guint8)(color.blue * 0xFF)) * 0x101 == (guint16)(color.blue * 0xFFFF))
          new_text = g_strdup_printf ("#%02X%02X%02X",
                                      (guint8)(color.red * 0xFF),
                                      (guint8)(color.green * 0xFF),
                                      (guint8)(color.blue * 0xFF));
        else
          new_text = g_strdup_printf ("#%04X%04X%04X",
                                      (guint16)(color.red * 0xFFFF),
                                      (guint16)(color.green * 0xFFFF),
                                      (guint16)(color.blue * 0xFFFF));

        gtk_list_store_set (GTK_LIST_STORE (eprop_attrs->model), &iter,
                            COLUMN_TEXT, new_text,
                            COLUMN_NAME_WEIGHT, PANGO_WEIGHT_BOLD,
                            COLUMN_TEXT_STYLE, PANGO_STYLE_NORMAL,
                            COLUMN_TEXT_FG, "Black", -1);
        g_free (new_text);

        gtk_widget_destroy (dialog);
        break;

      case EDIT_FONT:
        dialog = gtk_font_chooser_dialog_new (_("Select a font"),
                                              GTK_WINDOW (glade_app_get_window ()));

        /* Get response etc... */
        if (text)
          gtk_font_chooser_set_font (GTK_FONT_CHOOSER (dialog), text);

        gtk_dialog_run (GTK_DIALOG (dialog));

        new_text = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (dialog));

        gtk_list_store_set (GTK_LIST_STORE (eprop_attrs->model), &iter,
                            COLUMN_TEXT, new_text,
                            COLUMN_NAME_WEIGHT, PANGO_WEIGHT_BOLD,
                            COLUMN_TEXT_STYLE, PANGO_STYLE_NORMAL,
                            COLUMN_TEXT_FG, "Black", -1);
        g_free (new_text);

        gtk_widget_destroy (dialog);
        break;

      default:
        break;
    }

  sync_object (eprop_attrs, FALSE);

  g_free (text);
}
예제 #10
0
static void
glade_eprop_attrs_show_dialog (GtkWidget *dialog_button,
                               GladeEditorProperty *eprop)
{
  GladeEPropAttrs *eprop_attrs = GLADE_EPROP_ATTRS (eprop);
  GtkWidget *dialog, *parent, *vbox, *sw, *tree_view;
  GladeProperty *property;
  GList *old_attributes;
  gint res;

  property = glade_editor_property_get_property (eprop);
  parent   = gtk_widget_get_toplevel (GTK_WIDGET (eprop));


  /* Keep a copy for commit time... */
  old_attributes = g_value_dup_boxed (glade_property_inline_value (property));

  dialog = gtk_dialog_new_with_buttons (_("Setup Text Attributes"),
                                        GTK_WINDOW (parent),
                                        GTK_DIALOG_MODAL |
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                                        GTK_STOCK_CLEAR, GLADE_RESPONSE_CLEAR,
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                        GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
  gtk_widget_show (vbox);

  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);

  gtk_box_pack_start (GTK_BOX
                      (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), vbox,
                      TRUE, TRUE, 0);

  sw = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_show (sw);
  gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
  gtk_widget_set_size_request (sw, 400, 200);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);

  tree_view = glade_eprop_attrs_view (eprop);
  glade_eprop_attrs_populate_view (eprop, GTK_TREE_VIEW (tree_view));

  gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));

  gtk_widget_show (tree_view);
  gtk_container_add (GTK_CONTAINER (sw), tree_view);

  /* Run the dialog */
  res = gtk_dialog_run (GTK_DIALOG (dialog));
  if (res == GTK_RESPONSE_OK)
    {
      /* Update from old attributes so that there a property change 
       * sitting on the undo stack.
       */
      glade_property_set (property, old_attributes);
      sync_object (eprop_attrs, TRUE);
    }
  else if (res == GLADE_RESPONSE_CLEAR)
    {
      GValue value = { 0, };
      g_value_init (&value, GLADE_TYPE_ATTR_GLIST);
      g_value_set_boxed (&value, NULL);
      glade_editor_property_commit (eprop, &value);
      g_value_unset (&value);
    }

  /* Clean up ...
   */
  gtk_widget_destroy (dialog);

  g_object_unref (G_OBJECT (eprop_attrs->model));
  eprop_attrs->model = NULL;

  glade_attr_list_free (old_attributes);
}
예제 #11
0
void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
{
	/* layer data */
	uint scene_layer = render_layer.scene_layer;
	uint layer = render_layer.layer;
	
	/* prepare for sync */
	light_map.pre_sync();
	mesh_map.pre_sync();
	object_map.pre_sync();
	mesh_synced.clear();

	/* object loop */
	BL::Scene::objects_iterator b_ob;

	for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
		bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
		uint ob_layer = get_layer(b_ob->layers());

		if(!hide && (ob_layer & scene_layer)) {
			uint visibility = PATH_RAY_ALL;
			
			if(!(ob_layer & layer))
				visibility &= ~PATH_RAY_CAMERA;

			if(b_ob->is_duplicator()) {
				/* dupli objects */
				object_create_duplilist(*b_ob, b_scene);

				BL::Object::dupli_list_iterator b_dup;
				int b_index = 0;

				for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
					Transform tfm = get_transform(b_dup->matrix());
					sync_object(*b_ob, b_index, b_dup->object(), tfm, visibility);
					b_index++;
				}

				object_free_duplilist(*b_ob);

				/* check if we should render duplicator */
				hide = true;
				BL::Object::particle_systems_iterator b_psys;

				for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
					if(b_psys->settings().use_render_emitter())
						hide = false;
			}

			if(!hide) {
				/* object itself */
				Transform tfm = get_transform(b_ob->matrix_world());
				sync_object(*b_ob, 0, *b_ob, tfm, visibility);
			}
		}
	}

	/* handle removed data and modified pointers */
	if(light_map.post_sync())
		scene->light_manager->tag_update(scene);
	if(mesh_map.post_sync())
		scene->mesh_manager->tag_update(scene);
	if(object_map.post_sync())
		scene->object_manager->tag_update(scene);
	mesh_synced.clear();
}