Exemplo n.º 1
0
static void collection_object_cache_fill(ListBase *lb, Collection *collection, int parent_restrict)
{
  int child_restrict = collection->flag | parent_restrict;

  for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
    Base *base = BLI_findptr(lb, cob->ob, offsetof(Base, object));

    if (base == NULL) {
      base = MEM_callocN(sizeof(Base), "Object Base");
      base->object = cob->ob;
      BLI_addtail(lb, base);
    }

    int object_restrict = base->object->restrictflag;

    if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) &&
        ((object_restrict & OB_RESTRICT_VIEWPORT) == 0)) {
      base->flag |= BASE_ENABLED_VIEWPORT;
    }

    if (((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) &&
        ((object_restrict & OB_RESTRICT_RENDER) == 0)) {
      base->flag |= BASE_ENABLED_RENDER;
    }
  }

  for (CollectionChild *child = collection->children.first; child; child = child->next) {
    collection_object_cache_fill(lb, child->collection, child_restrict);
  }
}
Exemplo n.º 2
0
/* Check if the ID appears in the paths specified by the KeyingSet */
bool ANIM_keyingset_find_id(KeyingSet *ks, ID *id)
{
	/* sanity checks */
	if (ELEM(NULL, ks, id))
		return false;

	return BLI_findptr(&ks->paths, id, offsetof(KS_Path, id)) != NULL;
}
Exemplo n.º 3
0
static short layer_collection_sync(ViewLayer *view_layer,
                                   const ListBase *lb_scene,
                                   ListBase *lb_layer,
                                   ListBase *new_object_bases,
                                   short parent_exclude,
                                   short parent_restrict,
                                   short parent_layer_restrict)
{
  /* TODO: support recovery after removal of intermediate collections, reordering, ..
   * For local edits we can make editing operating do the appropriate thing, but for
   * linking we can only sync after the fact. */

  /* Remove layer collections that no longer have a corresponding scene collection. */
  for (LayerCollection *lc = lb_layer->first; lc;) {
    /* Note ID remap can set lc->collection to NULL when deleting collections. */
    LayerCollection *lc_next = lc->next;
    Collection *collection = (lc->collection) ?
                                 BLI_findptr(lb_scene,
                                             lc->collection,
                                             offsetof(CollectionChild, collection)) :
                                 NULL;

    if (!collection) {
      if (lc == view_layer->active_collection) {
        view_layer->active_collection = NULL;
      }

      /* Free recursively. */
      layer_collection_free(view_layer, lc);
      BLI_freelinkN(lb_layer, lc);
    }

    lc = lc_next;
  }

  /* Add layer collections for any new scene collections, and ensure order is the same. */
  ListBase new_lb_layer = {NULL, NULL};
  short runtime_flag = 0;

  for (const CollectionChild *child = lb_scene->first; child; child = child->next) {
    Collection *collection = child->collection;
    LayerCollection *lc = BLI_findptr(lb_layer, collection, offsetof(LayerCollection, collection));

    if (lc) {
      BLI_remlink(lb_layer, lc);
      BLI_addtail(&new_lb_layer, lc);
    }
    else {
      lc = layer_collection_add(&new_lb_layer, collection);
      lc->flag = parent_exclude;
    }

    /* Collection restrict is inherited. */
    short child_restrict = parent_restrict;
    short child_layer_restrict = parent_layer_restrict;
    if (!(collection->flag & COLLECTION_IS_MASTER)) {
      child_restrict |= collection->flag;
      child_layer_restrict |= lc->flag;
    }

    /* Sync child collections. */
    short child_runtime_flag = layer_collection_sync(view_layer,
                                                     &collection->children,
                                                     &lc->layer_collections,
                                                     new_object_bases,
                                                     lc->flag,
                                                     child_restrict,
                                                     child_layer_restrict);

    /* Layer collection exclude is not inherited. */
    if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
      lc->runtime_flag = 0;
      continue;
    }
    else {
      lc->runtime_flag = child_runtime_flag;
    }

    if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) &&
        ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) {
      lc->runtime_flag |= LAYER_COLLECTION_VISIBLE;
    }

    /* Sync objects, except if collection was excluded. */
    for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
      if (cob->ob == NULL) {
        continue;
      }

      void **base_p;
      Base *base;
      if (BLI_ghash_ensure_p(view_layer->object_bases_hash, cob->ob, &base_p)) {
        /* Move from old base list to new base list. Base might have already
         * been moved to the new base list and the first/last test ensure that
         * case also works. */
        base = *base_p;
        if (!ELEM(base, new_object_bases->first, new_object_bases->last)) {
          BLI_remlink(&view_layer->object_bases, base);
          BLI_addtail(new_object_bases, base);
        }
      }
      else {
        /* Create new base. */
        base = object_base_new(cob->ob);
        *base_p = base;
        BLI_addtail(new_object_bases, base);
      }

      if ((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) {
        base->flag_from_collection |= BASE_ENABLED_VIEWPORT;
        if ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0) {
          base->flag_from_collection |= BASE_VISIBLE;
          if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0)) {
            base->flag_from_collection |= BASE_SELECTABLE;
          }
        }
      }

      if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
        base->flag_from_collection |= BASE_ENABLED_RENDER;
      }

      /* Holdout and indirect only */
      if (lc->flag & LAYER_COLLECTION_HOLDOUT) {
        base->flag_from_collection |= BASE_HOLDOUT;
      }
      if (lc->flag & LAYER_COLLECTION_INDIRECT_ONLY) {
        base->flag_from_collection |= BASE_INDIRECT_ONLY;
      }

      lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS;

      /* Make sure flags on base are usable right away. */
      BKE_base_eval_flags(base);
    }

    runtime_flag |= lc->runtime_flag;
  }

  /* Replace layer collection list with new one. */
  *lb_layer = new_lb_layer;
  BLI_assert(BLI_listbase_count(lb_scene) == BLI_listbase_count(lb_layer));

  return runtime_flag;
}
Exemplo n.º 4
0
/* OB_DUPLIPARTS */
static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem *psys)
{
	Scene *scene = ctx->scene;
	Object *par = ctx->object;
	bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER;
	bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);

	GroupObject *go;
	Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
	DupliObject *dob;
	ParticleDupliWeight *dw;
	ParticleSettings *part;
	ParticleData *pa;
	ChildParticle *cpa = NULL;
	ParticleKey state;
	ParticleCacheKey *cache;
	float ctime, pa_time, scale = 1.0f;
	float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0;
	float (*obmat)[4];
	int a, b, hair = 0;
	int totpart, totchild, totgroup = 0 /*, pa_num */;
	const bool dupli_type_hack = !BKE_scene_use_new_shading_nodes(scene);

	int no_draw_flag = PARS_UNEXIST;

	if (psys == NULL) return;

	part = psys->part;

	if (part == NULL)
		return;

	if (!psys_check_enabled(par, psys))
		return;

	if (!for_render)
		no_draw_flag |= PARS_NO_DISP;

	ctime = BKE_scene_frame_get(scene); /* NOTE: in old animsys, used parent object's timeoffset... */

	totpart = psys->totpart;
	totchild = psys->totchild;

	BLI_srandom((unsigned int)(31415926 + psys->seed));

	if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
		ParticleSimulationData sim = {NULL};
		sim.scene = scene;
		sim.ob = par;
		sim.psys = psys;
		sim.psmd = psys_get_modifier(par, psys);
		/* make sure emitter imat is in global coordinates instead of render view coordinates */
		invert_m4_m4(par->imat, par->obmat);

		/* first check for loops (particle system object used as dupli object) */
		if (part->ren_as == PART_DRAW_OB) {
			if (ELEM(part->dup_ob, NULL, par))
				return;
		}
		else { /*PART_DRAW_GR */
			if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject))
				return;

			if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) {
				return;
			}
		}

		/* if we have a hair particle system, use the path cache */
		if (part->type == PART_HAIR) {
			if (psys->flag & PSYS_HAIR_DONE)
				hair = (totchild == 0 || psys->childcache) && psys->pathcache;
			if (!hair)
				return;

			/* we use cache, update totchild according to cached data */
			totchild = psys->totchildcache;
			totpart = psys->totcached;
		}

		psys_check_group_weights(part);

		psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);

		/* gather list of objects or single object */
		if (part->ren_as == PART_DRAW_GR) {
			if (ctx->do_update) {
				BKE_group_handle_recalc_and_update(ctx->eval_ctx, scene, par, part->dup_group);
			}

			if (part->draw & PART_DRAW_COUNT_GR) {
				for (dw = part->dupliweights.first; dw; dw = dw->next)
					totgroup += dw->count;
			}
			else {
				for (go = part->dup_group->gobject.first; go; go = go->next)
					totgroup++;
			}

			/* we also copy the actual objects to restore afterwards, since
			 * BKE_object_where_is_calc_time will change the object which breaks transform */
			oblist = MEM_callocN((size_t)totgroup * sizeof(Object *), "dupgroup object list");
			obcopylist = MEM_callocN((size_t)totgroup * sizeof(Object), "dupgroup copy list");

			if (part->draw & PART_DRAW_COUNT_GR && totgroup) {
				dw = part->dupliweights.first;

				for (a = 0; a < totgroup; dw = dw->next) {
					for (b = 0; b < dw->count; b++, a++) {
						oblist[a] = dw->ob;
						obcopylist[a] = *dw->ob;
					}
				}
			}
			else {
				go = part->dup_group->gobject.first;
				for (a = 0; a < totgroup; a++, go = go->next) {
					oblist[a] = go->ob;
					obcopylist[a] = *go->ob;
				}
			}
		}
		else {
			ob = part->dup_ob;
			obcopy = *ob;
		}

		if (totchild == 0 || part->draw & PART_DRAW_PARENT)
			a = 0;
		else
			a = totpart;

		for (pa = psys->particles; a < totpart + totchild; a++, pa++) {
			if (a < totpart) {
				/* handle parent particle */
				if (pa->flag & no_draw_flag)
					continue;

				/* pa_num = pa->num; */ /* UNUSED */
				pa_time = pa->time;
				size = pa->size;
			}
			else {
				/* handle child particle */
				cpa = &psys->child[a - totpart];

				/* pa_num = a; */ /* UNUSED */
				pa_time = psys->particles[cpa->parent].time;
				size = psys_get_child_size(psys, cpa, ctime, NULL);
			}

			/* some hair paths might be non-existent so they can't be used for duplication */
			if (hair && psys->pathcache &&
			    ((a < totpart && psys->pathcache[a]->segments < 0) ||
			     (a >= totpart && psys->childcache[a - totpart]->segments < 0)))
			{
				continue;
			}

			if (part->ren_as == PART_DRAW_GR) {
				/* prevent divide by zero below [#28336] */
				if (totgroup == 0)
					continue;

				/* for groups, pick the object based on settings */
				if (part->draw & PART_DRAW_RAND_GR)
					b = BLI_rand() % totgroup;
				else
					b = a % totgroup;

				ob = oblist[b];
				obmat = oblist[b]->obmat;
			}
			else {
				obmat = ob->obmat;
			}

			if (hair) {
				/* hair we handle separate and compute transform based on hair keys */
				if (a < totpart) {
					cache = psys->pathcache[a];
					psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale);
				}
				else {
					cache = psys->childcache[a - totpart];
					psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale);
				}

				copy_v3_v3(pamat[3], cache->co);
				pamat[3][3] = 1.0f;

			}
			else {
				/* first key */
				state.time = ctime;
				if (psys_get_particle_state(&sim, a, &state, 0) == 0) {
					continue;
				}
				else {
					float tquat[4];
					normalize_qt_qt(tquat, state.rot);
					quat_to_mat4(pamat, tquat);
					copy_v3_v3(pamat[3], state.co);
					pamat[3][3] = 1.0f;
				}
			}

			if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
				for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) {

					copy_m4_m4(tmat, oblist[b]->obmat);
					/* apply particle scale */
					mul_mat3_m4_fl(tmat, size * scale);
					mul_v3_fl(tmat[3], size * scale);
					/* group dupli offset, should apply after everything else */
					if (!is_zero_v3(part->dup_group->dupli_ofs))
						sub_v3_v3(tmat[3], part->dup_group->dupli_ofs);
					/* individual particle transform */
					mul_m4_m4m4(mat, pamat, tmat);

					dob = make_dupli(ctx, go->ob, mat, a, false, false);
					dob->particle_system = psys;
					if (use_texcoords)
						psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
				}
			}
			else {
				/* to give ipos in object correct offset */
				BKE_object_where_is_calc_time(scene, ob, ctime - pa_time);

				copy_v3_v3(vec, obmat[3]);
				obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;

				/* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */
				if ((part->draw & PART_DRAW_ROTATE_OB) == 0) {
					float xvec[3], q[4], size_mat[4][4], original_size[3];

					mat4_to_size(original_size, obmat);
					size_to_mat4(size_mat, original_size);

					xvec[0] = -1.f;
					xvec[1] = xvec[2] = 0;
					vec_to_quat(q, xvec, ob->trackflag, ob->upflag);
					quat_to_mat4(obmat, q);
					obmat[3][3] = 1.0f;

					/* add scaling if requested */
					if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0)
						mul_m4_m4m4(obmat, obmat, size_mat);
				}
				else if (part->draw & PART_DRAW_NO_SCALE_OB) {
					/* remove scaling */
					float size_mat[4][4], original_size[3];

					mat4_to_size(original_size, obmat);
					size_to_mat4(size_mat, original_size);
					invert_m4(size_mat);

					mul_m4_m4m4(obmat, obmat, size_mat);
				}

				mul_m4_m4m4(tmat, pamat, obmat);
				mul_mat3_m4_fl(tmat, size * scale);

				copy_m4_m4(mat, tmat);

				if (part->draw & PART_DRAW_GLOBAL_OB)
					add_v3_v3v3(mat[3], mat[3], vec);

				dob = make_dupli(ctx, ob, mat, a, false, false);
				dob->particle_system = psys;
				if (use_texcoords)
					psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
				/* XXX blender internal needs this to be set to dupligroup to render
				 * groups correctly, but we don't want this hack for cycles */
				if (dupli_type_hack && ctx->group)
					dob->type = OB_DUPLIGROUP;
			}
		}

		/* restore objects since they were changed in BKE_object_where_is_calc_time */
		if (part->ren_as == PART_DRAW_GR) {
			for (a = 0; a < totgroup; a++)
				*(oblist[a]) = obcopylist[a];
		}
		else
			*ob = obcopy;
	}

	/* clean up */
	if (oblist)
		MEM_freeN(oblist);
	if (obcopylist)
		MEM_freeN(obcopylist);

	if (psys->lattice_deform_data) {
		end_latt_deform(psys->lattice_deform_data);
		psys->lattice_deform_data = NULL;
	}
}
Exemplo n.º 5
0
Base *BKE_scene_base_find(Scene *scene, Object *ob)
{
	return BLI_findptr(&scene->base, ob, offsetof(Base, object));
}