Пример #1
0
static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UNUSED(val), ParticleData *pa)
{
	KDTreeNearest ptn[11];
	float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
	int neighbors = BLI_kdtree_find_nearest_n__normal(bbd->sim->psys->tree, pa->state.co, pa->prev_state.ave, ptn, 11);
	int n;
	int ret = 0;

	if (neighbors > 1) {
		for (n=1; n<neighbors; n++) {
			add_v3_v3(loc, bbd->sim->psys->particles[ptn[n].index].prev_state.co);
			add_v3_v3(vec, bbd->sim->psys->particles[ptn[n].index].prev_state.vel);
		}

		mul_v3_fl(loc, 1.0f/((float)neighbors - 1.0f));
		mul_v3_fl(vec, 1.0f/((float)neighbors - 1.0f));

		sub_v3_v3(loc, pa->prev_state.co);
		sub_v3_v3(vec, pa->prev_state.vel);

		add_v3_v3(bbd->wanted_co, vec);
		add_v3_v3(bbd->wanted_co, loc);
		bbd->wanted_speed = len_v3(bbd->wanted_co);

		ret = 1;
	}
	return ret;
}
/**
 * finalize after accumulation.
 */
static void calc_tangent_ortho(float ts[3][3])
{
	float v_tan_a[3], v_tan_b[3];
	float t_vec_a[3], t_vec_b[3];

	normalize_v3(ts[2]);

	copy_v3_v3(v_tan_a, ts[0]);
	copy_v3_v3(v_tan_b, ts[1]);

	cross_v3_v3v3(ts[1], ts[2], v_tan_a);
	mul_v3_fl(ts[1], dot_v3v3(ts[1], v_tan_b) < 0.0f ? -1.0f : 1.0f);

	/* orthognalise tangent */
	mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], v_tan_a));
	sub_v3_v3v3(ts[0], v_tan_a, t_vec_a);

	/* orthognalise bitangent */
	mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], ts[1]));
	mul_v3_v3fl(t_vec_b, ts[0], dot_v3v3(ts[0], ts[1]) / dot_v3v3(v_tan_a, v_tan_a));
	sub_v3_v3(ts[1], t_vec_a);
	sub_v3_v3(ts[1], t_vec_b);

	normalize_v3(ts[0]);
	normalize_v3(ts[1]);
}
Пример #3
0
float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
{
	float v1_proj[3], v2_proj[3], tproj[3];
	float angle;

	sub_v3_v3v3(v1_proj, v1, v2);
	sub_v3_v3v3(v2_proj, v3, v2);

	/* project the vectors onto the axis */
	project_v3_v3v3(tproj, v1_proj, axis);
	sub_v3_v3(v1_proj, tproj);

	project_v3_v3v3(tproj, v2_proj, axis);
	sub_v3_v3(v2_proj, tproj);

	angle = angle_v3v3(v1_proj, v2_proj);

	/* calculate the sign (reuse 'tproj') */
	cross_v3_v3v3(tproj, v2_proj, v1_proj);
	if (dot_v3v3(tproj, axis) < 0.0f) {
		angle = ((float)(M_PI * 2.0)) - angle;
	}

	return angle;
}
Пример #4
0
static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
{
	BoidParticle *bpa = pa->boid;
	BoidRuleAverageSpeed *asbr = (BoidRuleAverageSpeed*)rule;
	float vec[3] = {0.0f, 0.0f, 0.0f};

	if (asbr->wander > 0.0f) {
		/* abuse pa->r_ave for wandering */
		bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
		bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
		bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));

		normalize_v3(bpa->wander);

		copy_v3_v3(vec, bpa->wander);

		mul_qt_v3(pa->prev_state.rot, vec);

		copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);

		mul_v3_fl(bbd->wanted_co, 1.1f);

		add_v3_v3(bbd->wanted_co, vec);

		/* leveling */
		if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
			project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
			mul_v3_fl(vec, asbr->level);
			sub_v3_v3(bbd->wanted_co, vec);
		}
	}
	else {
		copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);

		/* may happen at birth */
		if (dot_v2v2(bbd->wanted_co, bbd->wanted_co)==0.0f) {
			bbd->wanted_co[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
			bbd->wanted_co[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
			bbd->wanted_co[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
		}
		
		/* leveling */
		if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
			project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
			mul_v3_fl(vec, asbr->level);
			sub_v3_v3(bbd->wanted_co, vec);
		}

	}
	bbd->wanted_speed = asbr->speed * val->max_speed;
	
	return 1;
}
Пример #5
0
bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval[2], const bool do_fallback)
{
	RegionView3D *rv3d = ar->regiondata;
	float dvec[3];
	int mval_cpy[2];
	eV3DProjStatus ret;

	ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);

	if (ret == V3D_PROJ_RET_OK) {
		const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]),
		                         (float)(mval_cpy[1] - mval[1])};
		const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL);
		ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
		sub_v3_v3(fp, dvec);

		return true;
	}
	else {
		/* fallback to the view center */
		if (do_fallback) {
			negate_v3_v3(fp, rv3d->ofs);
			return view3d_get_view_aligned_coordinate(ar, fp, mval, false);
		}
		else {
			return false;
		}
	}
}
Пример #6
0
void sk_flattenStroke(SK_Stroke *stk, int start, int end)
{
	float normal[3], distance[3];
	float limit;
	int i, total;

	total = end - start + 1;

	copy_v3_v3(normal, stk->points[start].no);

	sub_v3_v3v3(distance, stk->points[end].p, stk->points[start].p);
	project_v3_v3v3(normal, distance, normal);
	limit = normalize_v3(normal);

	for (i = 1; i < total - 1; i++) {
		float d = limit * i / total;
		float offset[3];
		float *p = stk->points[start + i].p;

		sub_v3_v3v3(distance, p, stk->points[start].p);
		project_v3_v3v3(distance, distance, normal);

		copy_v3_v3(offset, normal);
		mul_v3_fl(offset, d);

		sub_v3_v3(p, distance);
		add_v3_v3(p, offset);
	}
}
Пример #7
0
/* returns standard diameter */
static float new_primitive_matrix(bContext *C, float *loc, float *rot, float primmat[][4])
{
	Object *obedit = CTX_data_edit_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
	
	unit_m4(primmat);

	eul_to_mat3(rmat, rot);
	invert_m3(rmat);
	
	/* inverse transform for initial rotation and object */
	copy_m3_m4(mat, obedit->obmat);
	mul_m3_m3m3(cmat, rmat, mat);
	invert_m3_m3(imat, cmat);
	copy_m4_m3(primmat, imat);

	/* center */
	copy_v3_v3(primmat[3], loc);
	sub_v3_v3(primmat[3], obedit->obmat[3]);
	invert_m3_m3(imat, mat);
	mul_m3_v3(imat, primmat[3]);

	return v3d ? v3d->grid : 1.0f;
}
Пример #8
0
/**
 * angle between 2 vectors defined by 3 coords, about an axis. */
float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3])
{
	float v1_proj[3], v2_proj[3], tproj[3];

	sub_v3_v3v3(v1_proj, v1, v2);
	sub_v3_v3v3(v2_proj, v3, v2);

	/* project the vectors onto the axis */
	project_v3_v3v3(tproj, v1_proj, axis);
	sub_v3_v3(v1_proj, tproj);

	project_v3_v3v3(tproj, v2_proj, axis);
	sub_v3_v3(v2_proj, tproj);

	return angle_v3v3(v1_proj, v2_proj);
}
Пример #9
0
static void viewAxisCorrectCenter(TransInfo *t, float t_con_center[3])
{
	if (t->spacetype == SPACE_VIEW3D) {
		// View3D *v3d = t->sa->spacedata.first;
		const float min_dist = 1.0f;  /* v3d->near; */
		float dir[3];
		float l;

		sub_v3_v3v3(dir, t_con_center, t->viewinv[3]);
		if (dot_v3v3(dir, t->viewinv[2]) < 0.0f) {
			negate_v3(dir);
		}
		project_v3_v3v3(dir, dir, t->viewinv[2]);

		l = len_v3(dir);

		if (l < min_dist) {
			float diff[3];
			normalize_v3_v3(diff, t->viewinv[2]);
			mul_v3_fl(diff, min_dist - l);

			sub_v3_v3(t_con_center, diff);
		}
	}
}
Пример #10
0
static int set_origin_exec(bContext *C, wmOperator *op)
{
  SpaceClip *sc = CTX_wm_space_clip(C);
  MovieClip *clip = ED_space_clip_get_clip(sc);
  MovieTracking *tracking = &clip->tracking;
  Scene *scene = CTX_data_scene(C);
  Object *camera = get_camera_with_movieclip(scene, clip);
  int selected_count = count_selected_bundles(C);

  if (selected_count == 0) {
    BKE_report(op->reports,
               RPT_ERROR,
               "At least one track with bundle should be selected to "
               "define origin position");

    return OPERATOR_CANCELLED;
  }

  Object *object = get_orientation_object(C);
  if (object == NULL) {
    BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on");
    return OPERATOR_CANCELLED;
  }

  MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
  ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);

  float median[3] = {0.0f, 0.0f, 0.0f};
  zero_v3(median);
  for (MovieTrackingTrack *track = tracksbase->first; track != NULL; track = track->next) {
    if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_HAS_BUNDLE)) {
      add_v3_v3(median, track->bundle_pos);
    }
  }
  mul_v3_fl(median, 1.0f / selected_count);

  float mat[4][4], vec[3];
  BKE_tracking_get_camera_object_matrix(scene, camera, mat);
  mul_v3_m4v3(vec, mat, median);

  if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
    sub_v3_v3(object->loc, vec);
  }
  else {
    object_solver_inverted_matrix(scene, object, mat);
    mul_v3_m4v3(vec, mat, vec);
    copy_v3_v3(object->loc, vec);
  }

  DEG_id_tag_update(&clip->id, 0);
  DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);

  WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
  WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);

  return OPERATOR_FINISHED;
}
Пример #11
0
/* project a vector on a plane defined by normal and a plane point p */
void project_v3_plane(float v[3], const float n[3], const float p[3])
{
	float vector[3];
	float mul;

	sub_v3_v3v3(vector, v, p);
	mul = dot_v3v3(vector, n) / len_squared_v3(n);

	mul_v3_v3fl(vector, n, mul);

	sub_v3_v3(v, vector);
}
Пример #12
0
float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3])
{
	int len = 2 + abs(end - start);
	
	if (len > 2)
	{
		float avg_t = 0.0f;
		float s_t = 0.0f;
		float s_xyz = 0.0f;
		int i;
		
		/* First pass, calculate average */
		for (i = start; i <= end; i++)
		{
			float v[3];
			
			IT_peek(iter, i);
			sub_v3_v3v3(v, iter->p, v0);
			avg_t += dot_v3v3(v, n);
		}
		
		avg_t /= dot_v3v3(n, n);
		avg_t += 1.0f; /* adding start (0) and end (1) values */
		avg_t /= len;
		
		/* Second pass, calculate s_xyz and s_t */
		for (i = start; i <= end; i++)
		{
			float v[3], d[3];
			float dt;
			
			IT_peek(iter, i);
			sub_v3_v3v3(v, iter->p, v0);
			project_v3_v3v3(d, v, n);
			sub_v3_v3(v, d);
			
			dt = len_v3(d) - avg_t;
			
			s_t += dt * dt;
			s_xyz += dot_v3v3(v, v);
		}
		
		/* adding start(0) and end(1) values to s_t */
		s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
		
		return 1.0f - s_xyz / s_t; 
	}
	else
	{
		return 1.0f;
	}
}
Пример #13
0
void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4])
{
	float mat3[3][3];

	copy_m3_m4(mat3, mat);
	/* We want normalized matrix here, to be consistent with ebone_to_mat. */
	BLI_ASSERT_UNIT_M3(mat3);

	sub_v3_v3(ebone->tail, ebone->head);
	copy_v3_v3(ebone->head, mat[3]);
	add_v3_v3(ebone->tail, mat[3]);
	ED_armature_ebone_from_mat3(ebone, mat3);
}
Пример #14
0
/* OB_DUPLIGROUP */
static void make_duplis_group(const DupliContext *ctx)
{
	bool for_render = ctx->eval_ctx->for_render;
	Object *ob = ctx->object;
	Group *group;
	GroupObject *go;
	float group_mat[4][4];
	int id;
	bool animated, hide;

	if (ob->dup_group == NULL) return;
	group = ob->dup_group;

	/* combine group offset and obmat */
	unit_m4(group_mat);
	sub_v3_v3(group_mat[3], group->dupli_ofs);
	mul_m4_m4m4(group_mat, ob->obmat, group_mat);
	/* don't access 'ob->obmat' from now on. */

	/* handles animated groups */

	/* we need to check update for objects that are not in scene... */
	if (ctx->do_update) {
		/* note: update is optional because we don't always need object
		 * transformations to be correct. Also fixes bug [#29616]. */
		BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, ob, group);
	}

	animated = BKE_group_is_animated(group, ob);

	for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
		/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
		if (go->ob != ob) {
			float mat[4][4];

			/* group dupli offset, should apply after everything else */
			mul_m4_m4m4(mat, group_mat, go->ob->obmat);

			/* check the group instance and object layers match, also that the object visible flags are ok. */
			hide = (go->ob->lay & group->layer) == 0 ||
			       (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);

			make_dupli(ctx, go->ob, mat, id, animated, hide);

			/* recursion */
			make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
		}
	}
}
Пример #15
0
static void tracking_scale_reconstruction(ListBase *tracksbase, MovieTrackingReconstruction *reconstruction,
                                          const float scale[3])
{
	MovieTrackingTrack *track;
	int i;
	float first_camera_delta[3] = {0.0f, 0.0f, 0.0f};

	if (reconstruction->camnr > 0) {
		mul_v3_v3v3(first_camera_delta, reconstruction->cameras[0].mat[3], scale);
	}

	for (i = 0; i < reconstruction->camnr; i++) {
		MovieReconstructedCamera *camera = &reconstruction->cameras[i];
		mul_v3_v3(camera->mat[3], scale);
		sub_v3_v3(camera->mat[3], first_camera_delta);
	}

	for (track = tracksbase->first; track; track = track->next) {
		if (track->flag & TRACK_HAS_BUNDLE) {
			mul_v3_v3(track->bundle_pos, scale);
			sub_v3_v3(track->bundle_pos, first_camera_delta);
		}
	}
}
Пример #16
0
static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
                                  const float no_f[3], const short no_s[3])
{
	DupliObject *dob;
	vertexDupliData *vdd= userData;
	float vec[3], q2[4], mat[3][3], tmat[4][4], obmat[4][4];
	int origlay;
	
	mul_v3_m4v3(vec, vdd->pmat, co);
	sub_v3_v3(vec, vdd->pmat[3]);
	add_v3_v3(vec, vdd->obmat[3]);
	
	copy_m4_m4(obmat, vdd->obmat);
	copy_v3_v3(obmat[3], vec);
	
	if (vdd->par->transflag & OB_DUPLIROT) {
		if (no_f) {
			vec[0]= -no_f[0]; vec[1]= -no_f[1]; vec[2]= -no_f[2];
		}
		else if (no_s) {
			vec[0]= -no_s[0]; vec[1]= -no_s[1]; vec[2]= -no_s[2];
		}
		
		vec_to_quat( q2,vec, vdd->ob->trackflag, vdd->ob->upflag);
		
		quat_to_mat3( mat,q2);
		copy_m4_m4(tmat, obmat);
		mul_m4_m4m3(obmat, tmat, mat);
	}

	origlay = vdd->ob->lay;
	
	dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS, vdd->animated);

	/* restore the original layer so that each dupli will have proper dob->origlay */
	vdd->ob->lay = origlay;

	if (vdd->orco)
		copy_v3_v3(dob->orco, vdd->orco[index]);
	
	if (vdd->ob->transflag & OB_DUPLI) {
		float tmpmat[4][4];
		copy_m4_m4(tmpmat, vdd->ob->obmat);
		copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
		object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->level+1, vdd->animated);
		copy_m4_m4(vdd->ob->obmat, tmpmat);
	}
}
Пример #17
0
/**
 * Calculate a 3d direction vector from 2d window coordinates.
 * This direction vector starts and the view in the direction of the 2d window coordinates.
 * In orthographic view all window coordinates yield the same vector.
 *
 * \note doesn't rely on ED_view3d_calc_zfac
 * for perspective view, get the vector direction to
 * the mouse cursor as a normalized vector.
 *
 * \param ar The region (used for the window width and height).
 * \param mval The area relative 2d location (such as event->mval converted to floats).
 * \param out The resulting normalized world-space direction vector.
 */
void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3])
{
	RegionView3D *rv3d = ar->regiondata;

	if (rv3d->is_persp) {
		out[0] = 2.0f * (mval[0] / ar->winx) - 1.0f;
		out[1] = 2.0f * (mval[1] / ar->winy) - 1.0f;
		out[2] = -0.5f;
		mul_project_m4_v3(rv3d->persinv, out);
		sub_v3_v3(out, rv3d->viewinv[3]);
	}
	else {
		negate_v3_v3(out, rv3d->viewinv[2]);
	}
	normalize_v3(out);
}
Пример #18
0
/* Note this modifies nos_new in-place. */
static void mix_normals(
        const float mix_factor, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
        const float mix_limit, const short mix_mode,
        const int num_verts, MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], const int num_loops)
{
	/* Mix with org normals... */
	float *facs = NULL, *wfac;
	float (*no_new)[3], (*no_old)[3];
	int i;

	if (dvert) {
		facs = MEM_malloc_arrayN((size_t)num_loops, sizeof(*facs), __func__);
		BKE_defvert_extract_vgroup_to_loopweights(
		            dvert, defgrp_index, num_verts, mloop, num_loops, facs, use_invert_vgroup);
	}

	for (i = num_loops, no_new = nos_new, no_old = nos_old, wfac = facs; i--; no_new++, no_old++, wfac++) {
		const float fac = facs ? *wfac * mix_factor : mix_factor;

		switch (mix_mode) {
			case MOD_NORMALEDIT_MIX_ADD:
				add_v3_v3(*no_new, *no_old);
				normalize_v3(*no_new);
				break;
			case MOD_NORMALEDIT_MIX_SUB:
				sub_v3_v3(*no_new, *no_old);
				normalize_v3(*no_new);
				break;
			case MOD_NORMALEDIT_MIX_MUL:
				mul_v3_v3(*no_new, *no_old);
				normalize_v3(*no_new);
				break;
			case MOD_NORMALEDIT_MIX_COPY:
				break;
		}

		interp_v3_v3v3_slerp_safe(
		        *no_new, *no_old, *no_new,
		        (mix_limit < (float)M_PI) ? min_ff(fac, mix_limit / angle_v3v3(*no_new, *no_old)) : fac);
	}

	MEM_SAFE_FREE(facs);
}
Пример #19
0
static void pointdensity_cache_object(Scene *scene, PointDensity *pd, Object *ob)
{
	int i;
	DerivedMesh *dm;
	MVert *mvert = NULL;

	dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
	mvert = dm->getVertArray(dm);	/* local object space */

	pd->totpoints = dm->getNumVerts(dm);
	if (pd->totpoints == 0) {
		return;
	}

	pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);

	for (i = 0; i < pd->totpoints; i++, mvert++) {
		float co[3];

		copy_v3_v3(co, mvert->co);

		switch (pd->ob_cache_space) {
			case TEX_PD_OBJECTSPACE:
				break;
			case TEX_PD_OBJECTLOC:
				mul_m4_v3(ob->obmat, co);
				sub_v3_v3(co, ob->loc);
				break;
			case TEX_PD_WORLDSPACE:
			default:
				mul_m4_v3(ob->obmat, co);
				break;
		}

		BLI_bvhtree_insert(pd->point_tree, i, co, 1);
	}

	BLI_bvhtree_balance(pd->point_tree);
	dm->release(dm);

}
Пример #20
0
/* OB_DUPLIGROUP */
static void make_duplis_group(const DupliContext *ctx)
{
	bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
	Object *ob = ctx->object;
	Group *group;
	GroupObject *go;
	float group_mat[4][4];
	int id;
	bool animated, hide;

	if (ob->dup_group == NULL) return;
	group = ob->dup_group;

	/* combine group offset and obmat */
	unit_m4(group_mat);
	sub_v3_v3(group_mat[3], group->dupli_ofs);
	mul_m4_m4m4(group_mat, ob->obmat, group_mat);
	/* don't access 'ob->obmat' from now on. */

	/* handles animated groups */

	/* we need to check update for objects that are not in scene... */
	if (ctx->do_update) {
		/* note: update is optional because we don't always need object
		 * transformations to be correct. Also fixes bug [#29616]. */
		BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, ob, group);
	}

	animated = BKE_group_is_animated(group, ob);

	for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
		/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
		if (go->ob != ob) {
			float mat[4][4];

			/* Special case for instancing dupli-groups, see: T40051
			 * this object may be instanced via dupli-verts/faces, in this case we don't want to render
			 * (blender convention), but _do_ show in the viewport.
			 *
			 * Regular objects work fine but not if we're instancing dupli-groups,
			 * because the rules for rendering aren't applied to objects they instance.
			 * We could recursively pass down the 'hide' flag instead, but that seems unnecessary.
			 */
			if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) {
				continue;
			}

			/* group dupli offset, should apply after everything else */
			mul_m4_m4m4(mat, group_mat, go->ob->obmat);

			/* check the group instance and object layers match, also that the object visible flags are ok. */
			hide = (go->ob->lay & group->layer) == 0 ||
			       (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);

			make_dupli(ctx, go->ob, mat, id, animated, hide);

			/* recursion */
			make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
		}
	}
}
Пример #21
0
/* only creates a table for a single channel in CurveMapping */
static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
{
	CurveMapPoint *cmp = cuma->curve;
	BezTriple *bezt;
	float *fp, *allpoints, *lastpoint, curf, range;
	int a, totpoint;
	
	if (cuma->curve == NULL) return;
	
	/* default rect also is table range */
	cuma->mintable = clipr->xmin;
	cuma->maxtable = clipr->xmax;
	
	/* hrmf... we now rely on blender ipo beziers, these are more advanced */
	bezt = MEM_callocN(cuma->totpoint * sizeof(BezTriple), "beztarr");
	
	for (a = 0; a < cuma->totpoint; a++) {
		cuma->mintable = MIN2(cuma->mintable, cmp[a].x);
		cuma->maxtable = MAX2(cuma->maxtable, cmp[a].x);
		bezt[a].vec[1][0] = cmp[a].x;
		bezt[a].vec[1][1] = cmp[a].y;
		if (cmp[a].flag & CUMA_VECTOR)
			bezt[a].h1 = bezt[a].h2 = HD_VECT;
		else
			bezt[a].h1 = bezt[a].h2 = HD_AUTO;
	}
	
	for (a = 0; a < cuma->totpoint; a++) {
		if (a == 0)
			calchandle_curvemap(bezt, NULL, bezt + 1, 0);
		else if (a == cuma->totpoint - 1)
			calchandle_curvemap(bezt + a, bezt + a - 1, NULL, 0);
		else
			calchandle_curvemap(bezt + a, bezt + a - 1, bezt + a + 1, 0);
	}
	
	/* first and last handle need correction, instead of pointing to center of next/prev, 
	 * we let it point to the closest handle */
	if (cuma->totpoint > 2) {
		float hlen, nlen, vec[3];
		
		if (bezt[0].h2 == HD_AUTO) {
			
			hlen = len_v3v3(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */
			/* clip handle point */
			copy_v3_v3(vec, bezt[1].vec[0]);
			if (vec[0] < bezt[0].vec[1][0])
				vec[0] = bezt[0].vec[1][0];
			
			sub_v3_v3(vec, bezt[0].vec[1]);
			nlen = len_v3(vec);
			if (nlen > FLT_EPSILON) {
				mul_v3_fl(vec, hlen / nlen);
				add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]);
				sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
			}
		}
		a = cuma->totpoint - 1;
		if (bezt[a].h2 == HD_AUTO) {
			
			hlen = len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
			/* clip handle point */
			copy_v3_v3(vec, bezt[a - 1].vec[2]);
			if (vec[0] > bezt[a].vec[1][0])
				vec[0] = bezt[a].vec[1][0];
			
			sub_v3_v3(vec, bezt[a].vec[1]);
			nlen = len_v3(vec);
			if (nlen > FLT_EPSILON) {
				mul_v3_fl(vec, hlen / nlen);
				add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]);
				sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec);
			}
		}
	}	
	/* make the bezier curve */
	if (cuma->table)
		MEM_freeN(cuma->table);
	totpoint = (cuma->totpoint - 1) * CM_RESOL;
	fp = allpoints = MEM_callocN(totpoint * 2 * sizeof(float), "table");
	
	for (a = 0; a < cuma->totpoint - 1; a++, fp += 2 * CM_RESOL) {
		correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a + 1].vec[0], bezt[a + 1].vec[1]);
		BKE_curve_forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a + 1].vec[0][0], bezt[a + 1].vec[1][0], fp, CM_RESOL - 1, 2 * sizeof(float));
		BKE_curve_forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a + 1].vec[0][1], bezt[a + 1].vec[1][1], fp + 1, CM_RESOL - 1, 2 * sizeof(float));
	}
	
	/* store first and last handle for extrapolation, unit length */
	cuma->ext_in[0] = bezt[0].vec[0][0] - bezt[0].vec[1][0];
	cuma->ext_in[1] = bezt[0].vec[0][1] - bezt[0].vec[1][1];
	range = sqrt(cuma->ext_in[0] * cuma->ext_in[0] + cuma->ext_in[1] * cuma->ext_in[1]);
	cuma->ext_in[0] /= range;
	cuma->ext_in[1] /= range;

	a = cuma->totpoint - 1;
	cuma->ext_out[0] = bezt[a].vec[1][0] - bezt[a].vec[2][0];
	cuma->ext_out[1] = bezt[a].vec[1][1] - bezt[a].vec[2][1];
	range = sqrt(cuma->ext_out[0] * cuma->ext_out[0] + cuma->ext_out[1] * cuma->ext_out[1]);
	cuma->ext_out[0] /= range;
	cuma->ext_out[1] /= range;
	
	/* cleanup */
	MEM_freeN(bezt);

	range = CM_TABLEDIV * (cuma->maxtable - cuma->mintable);
	cuma->range = 1.0f / range;
	
	/* now make a table with CM_TABLE equal x distances */
	fp = allpoints;
	lastpoint = allpoints + 2 * (totpoint - 1);
	cmp = MEM_callocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "dist table");

	for (a = 0; a <= CM_TABLE; a++) {
		curf = cuma->mintable + range * (float)a;
		cmp[a].x = curf;
		
		/* get the first x coordinate larger than curf */
		while (curf >= fp[0] && fp != lastpoint) {
			fp += 2;
		}
		if (fp == allpoints || (curf >= fp[0] && fp == lastpoint))
			cmp[a].y = curvemap_calc_extend(cuma, curf, allpoints, lastpoint);
		else {
			float fac1 = fp[0] - fp[-2];
			float fac2 = fp[0] - curf;
			if (fac1 > FLT_EPSILON)
				fac1 = fac2 / fac1;
			else
				fac1 = 0.0f;
			cmp[a].y = fac1 * fp[-1] + (1.0f - fac1) * fp[1];
		}
	}
	
	MEM_freeN(allpoints);
	cuma->table = cmp;
}
Пример #22
0
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	Object *obact = CTX_data_active_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float imat[3][3], bmat[3][3];
	float center_global[3];
	float offset_global[3];
	int a;

	if (use_offset) {
		if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
		    snap_calc_active_center(C, true, center_global))
		{
			/* pass */
		}
		else {
			snap_curs_to_sel_ex(C, center_global);
		}
		sub_v3_v3v3(offset_global, snap_target_global, center_global);
	}

	if (obedit) {
		float snap_target_local[3];
		
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		/* get the cursor in object space */
		sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
		mul_m3_v3(imat, snap_target_local);

		if (use_offset) {
			float offset_local[3];

			mul_v3_m3v3(offset_local, imat, offset_global);

			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				add_v3_v3(tv->loc, offset_local);
			}
		}
		else {
			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				copy_v3_v3(tv->loc, snap_target_local);
			}
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else if (obact && (obact->mode & OB_MODE_POSE)) {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		bPoseChannel *pchan;
		bArmature *arm = obact->data;
		float snap_target_local[3];

		invert_m4_m4(obact->imat, obact->obmat);
		mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global);

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_SELECTED) &&
			    (PBONE_VISIBLE(arm, pchan->bone)) &&
			    /* if the bone has a parent and is connected to the parent,
			     * don't do anything - will break chain unless we do auto-ik.
			     */
			    (pchan->bone->flag & BONE_CONNECTED) == 0)
			{
				pchan->bone->flag |= BONE_TRANSFORM;
			}
			else {
				pchan->bone->flag &= ~BONE_TRANSFORM;
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_TRANSFORM) &&
			    /* check that our parents not transformed (if we have one) */
			    ((pchan->bone->parent &&
			      BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
			{
				/* Get position in pchan (pose) space. */
				float cursor_pose[3];

				if (use_offset) {
					mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]);
					add_v3_v3(cursor_pose, offset_global);

					mul_m4_v3(obact->imat, cursor_pose);
					BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
				}
				else {
					BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
				}

				/* copy new position */
				if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
					pchan->loc[0] = cursor_pose[0];
				if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
					pchan->loc[1] = cursor_pose[1];
				if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
					pchan->loc[2] = cursor_pose[2];

				/* auto-keyframing */
				ED_autokeyframe_pchan(C, scene, obact, pchan, ks);
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			pchan->bone->flag &= ~BONE_TRANSFORM;
		}

		obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);

		DAG_id_tag_update(&obact->id, OB_RECALC_DATA);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
		Main *bmain = CTX_data_main(C);

		ListBase ctx_data_list;
		CollectionPointerLink *ctx_ob;
		Object *ob;

		CTX_data_selected_editable_objects(C, &ctx_data_list);

		/* reset flags */
		for (ob = bmain->object.first; ob; ob = ob->id.next) {
			ob->flag &= ~OB_DONE;
		}

		/* tag objects we're transforming */
		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;
			ob->flag |= OB_DONE;
		}

		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;

			if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {

				float cursor_parent[3];  /* parent-relative */

				if (use_offset) {
					add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
				}
				else {
					copy_v3_v3(cursor_parent, snap_target_global);
				}

				sub_v3_v3(cursor_parent, ob->obmat[3]);

				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);

					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, cursor_parent);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += cursor_parent[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += cursor_parent[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += cursor_parent[2];

				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}

		BLI_freelistN(&ctx_data_list);
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
Пример #23
0
/* calculates offset for co, based on fractal, sphere or smooth settings  */
static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc,
                     BMVert *vsta, BMVert *vend)
{
	float tvec[3], fac;
	float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
	int i;

	copy_v3_v3(co, v->co);

	if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
		normalize_v3(co);
		mul_v3_fl(co, params->smooth);
	}
	else if (params->use_smooth) {
		/* we calculate an offset vector vec1[], to be added to *co */
		float len, nor[3], nor1[3], nor2[3], val;

		sub_v3_v3v3(nor, vsta->co, vend->co);
		len = 0.5f * normalize_v3(nor);

		copy_v3_v3(nor1, vsta->no);
		copy_v3_v3(nor2, vend->no);

		/* cosine angle */
		fac = dot_v3v3(nor, nor1);
		mul_v3_v3fl(tvec, nor1, fac);

		/* cosine angle */
		fac = -dot_v3v3(nor, nor2);
		madd_v3_v3fl(tvec, nor2, fac);

		/* falloff for multi subdivide */
		val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
		val = bmesh_subd_falloff_calc(params->smooth_falloff, val);

		if (params->use_smooth_even) {
			val *= BM_vert_calc_shell_factor(v);
		}

		mul_v3_fl(tvec, params->smooth * val * len);

		add_v3_v3(co, tvec);
	}

	if (params->use_fractal) {
		const float len = len_v3v3(vsta->co, vend->co);
		float normal[3], co2[3], base1[3], base2[3];

		fac = params->fractal * len;

		mid_v3_v3v3(normal, vsta->no, vend->no);
		ortho_basis_v3v3_v3(base1, base2, normal);

		add_v3_v3v3(co2, v->co, params->fractal_ofs);
		mul_v3_fl(co2, 10.0f);

		tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
		tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
		tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);

		/* add displacement */
		madd_v3_v3fl(co, normal, tvec[0]);
		madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
		madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
	}

	/* apply the new difference to the rest of the shape keys,
	 * note that this doesn't take rotations into account, we _could_ support
	 * this by getting the normals and coords for each shape key and
	 * re-calculate the smooth value for each but this is quite involved.
	 * for now its ok to simply apply the difference IMHO - campbell */
	sub_v3_v3v3(tvec, v->co, co);

	if (params->shape_info.totlayer > 1) {
		/* skip the last layer since its the temp */
		i = params->shape_info.totlayer - 1;
		co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
		while (i--) {
			BLI_assert(co != BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp));
			sub_v3_v3(co += 3, tvec);
		}
	}
}
Пример #24
0
static void cuboid_do(
        CastModifierData *cmd, Object *ob, DerivedMesh *dm,
        float (*vertexCos)[3], int numVerts)
{
	MDeformVert *dvert = NULL;
	Object *ctrl_ob = NULL;

	int i, defgrp_index;
	bool has_radius = false;
	short flag;
	float fac = cmd->fac;
	float facm = 1.0f - fac;
	const float fac_orig = fac;
	float min[3], max[3], bb[8][3];
	float center[3] = {0.0f, 0.0f, 0.0f};
	float mat[4][4], imat[4][4];

	flag = cmd->flag;

	ctrl_ob = cmd->object;

	/* now we check which options the user wants */

	/* 1) (flag was checked in the "if (ctrl_ob)" block above) */
	/* 2) cmd->radius > 0.0f: only the vertices within this radius from
	 * the center of the effect should be deformed */
	if (cmd->radius > FLT_EPSILON) has_radius = 1;

	/* 3) if we were given a vertex group name,
	 * only those vertices should be affected */
	modifier_get_vgroup(ob, dm, cmd->defgrp_name, &dvert, &defgrp_index);

	if (ctrl_ob) {
		if (flag & MOD_CAST_USE_OB_TRANSFORM) {
			invert_m4_m4(imat, ctrl_ob->obmat);
			mul_m4_m4m4(mat, imat, ob->obmat);
			invert_m4_m4(imat, mat);
		}

		invert_m4_m4(ob->imat, ob->obmat);
		mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]);
	}

	if ((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
		for (i = 0; i < 3; i++) {
			min[i] = -cmd->radius;
			max[i] = cmd->radius;
		}
	}
	else if (!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
		for (i = 0; i < 3; i++) {
			min[i] = -cmd->size;
			max[i] = cmd->size;
		}
	}
	else {
		/* get bound box */
		/* We can't use the object's bound box because other modifiers
		 * may have changed the vertex data. */
		INIT_MINMAX(min, max);

		/* Cast's center is the ob's own center in its local space,
		 * by default, but if the user defined a control object, we use
		 * its location, transformed to ob's local space. */
		if (ctrl_ob) {
			float vec[3];

			/* let the center of the ctrl_ob be part of the bound box: */
			minmax_v3v3_v3(min, max, center);

			for (i = 0; i < numVerts; i++) {
				sub_v3_v3v3(vec, vertexCos[i], center);
				minmax_v3v3_v3(min, max, vec);
			}
		}
		else {
			for (i = 0; i < numVerts; i++) {
				minmax_v3v3_v3(min, max, vertexCos[i]);
			}
		}

		/* we want a symmetric bound box around the origin */
		if (fabsf(min[0]) > fabsf(max[0])) max[0] = fabsf(min[0]);
		if (fabsf(min[1]) > fabsf(max[1])) max[1] = fabsf(min[1]);
		if (fabsf(min[2]) > fabsf(max[2])) max[2] = fabsf(min[2]);
		min[0] = -max[0];
		min[1] = -max[1];
		min[2] = -max[2];
	}

	/* building our custom bounding box */
	bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
	bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
	bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
	bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
	bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
	bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];

	/* ready to apply the effect, one vertex at a time */
	for (i = 0; i < numVerts; i++) {
		int octant, coord;
		float d[3], dmax, apex[3], fbb;
		float tmp_co[3];

		copy_v3_v3(tmp_co, vertexCos[i]);
		if (ctrl_ob) {
			if (flag & MOD_CAST_USE_OB_TRANSFORM) {
				mul_m4_v3(mat, tmp_co);
			}
			else {
				sub_v3_v3(tmp_co, center);
			}
		}

		if (has_radius) {
			if (fabsf(tmp_co[0]) > cmd->radius ||
			    fabsf(tmp_co[1]) > cmd->radius ||
			    fabsf(tmp_co[2]) > cmd->radius)
			{
				continue;
			}
		}

		if (dvert) {
			const float weight = defvert_find_weight(&dvert[i], defgrp_index);
			if (weight == 0.0f) {
				continue;
			}

			fac = fac_orig * weight;
			facm = 1.0f - fac;
		}

		/* The algo used to project the vertices to their
		 * bounding box (bb) is pretty simple:
		 * for each vertex v:
		 * 1) find in which octant v is in;
		 * 2) find which outer "wall" of that octant is closer to v;
		 * 3) calculate factor (var fbb) to project v to that wall;
		 * 4) project. */

		/* find in which octant this vertex is in */
		octant = 0;
		if (tmp_co[0] > 0.0f) octant += 1;
		if (tmp_co[1] > 0.0f) octant += 2;
		if (tmp_co[2] > 0.0f) octant += 4;

		/* apex is the bb's vertex at the chosen octant */
		copy_v3_v3(apex, bb[octant]);

		/* find which bb plane is closest to this vertex ... */
		d[0] = tmp_co[0] / apex[0];
		d[1] = tmp_co[1] / apex[1];
		d[2] = tmp_co[2] / apex[2];

		/* ... (the closest has the higher (closer to 1) d value) */
		dmax = d[0];
		coord = 0;
		if (d[1] > dmax) {
			dmax = d[1];
			coord = 1;
		}
		if (d[2] > dmax) {
			/* dmax = d[2]; */ /* commented, we don't need it */
			coord = 2;
		}

		/* ok, now we know which coordinate of the vertex to use */

		if (fabsf(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
			continue;

		/* finally, this is the factor we wanted, to project the vertex
		 * to its bounding box (bb) */
		fbb = apex[coord] / tmp_co[coord];

		/* calculate the new vertex position */
		if (flag & MOD_CAST_X)
			tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
		if (flag & MOD_CAST_Y)
			tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
		if (flag & MOD_CAST_Z)
			tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;

		if (ctrl_ob) {
			if (flag & MOD_CAST_USE_OB_TRANSFORM) {
				mul_m4_v3(imat, tmp_co);
			}
			else {
				add_v3_v3(tmp_co, center);
			}
		}

		copy_v3_v3(vertexCos[i], tmp_co);
	}
}
Пример #25
0
static void sphere_do(
        CastModifierData *cmd, Object *ob, DerivedMesh *dm,
        float (*vertexCos)[3], int numVerts)
{
	MDeformVert *dvert = NULL;

	Object *ctrl_ob = NULL;

	int i, defgrp_index;
	bool has_radius = false;
	short flag, type;
	float len = 0.0f;
	float fac = cmd->fac;
	float facm = 1.0f - fac;
	const float fac_orig = fac;
	float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
	float mat[4][4], imat[4][4];

	flag = cmd->flag;
	type = cmd->type; /* projection type: sphere or cylinder */

	if (type == MOD_CAST_TYPE_CYLINDER) 
		flag &= ~MOD_CAST_Z;

	ctrl_ob = cmd->object;

	/* spherify's center is {0, 0, 0} (the ob's own center in its local
	 * space), by default, but if the user defined a control object,
	 * we use its location, transformed to ob's local space */
	if (ctrl_ob) {
		if (flag & MOD_CAST_USE_OB_TRANSFORM) {
			invert_m4_m4(imat, ctrl_ob->obmat);
			mul_m4_m4m4(mat, imat, ob->obmat);
			invert_m4_m4(imat, mat);
		}

		invert_m4_m4(ob->imat, ob->obmat);
		mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]);
	}

	/* now we check which options the user wants */

	/* 1) (flag was checked in the "if (ctrl_ob)" block above) */
	/* 2) cmd->radius > 0.0f: only the vertices within this radius from
	 * the center of the effect should be deformed */
	if (cmd->radius > FLT_EPSILON) has_radius = 1;

	/* 3) if we were given a vertex group name,
	 * only those vertices should be affected */
	modifier_get_vgroup(ob, dm, cmd->defgrp_name, &dvert, &defgrp_index);

	if (flag & MOD_CAST_SIZE_FROM_RADIUS) {
		len = cmd->radius;
	}
	else {
		len = cmd->size;
	}

	if (len <= 0) {
		for (i = 0; i < numVerts; i++) {
			len += len_v3v3(center, vertexCos[i]);
		}
		len /= numVerts;

		if (len == 0.0f) len = 10.0f;
	}

	for (i = 0; i < numVerts; i++) {
		float tmp_co[3];

		copy_v3_v3(tmp_co, vertexCos[i]);
		if (ctrl_ob) {
			if (flag & MOD_CAST_USE_OB_TRANSFORM) {
				mul_m4_v3(mat, tmp_co);
			}
			else {
				sub_v3_v3(tmp_co, center);
			}
		}

		copy_v3_v3(vec, tmp_co);

		if (type == MOD_CAST_TYPE_CYLINDER)
			vec[2] = 0.0f;

		if (has_radius) {
			if (len_v3(vec) > cmd->radius) continue;
		}

		if (dvert) {
			const float weight = defvert_find_weight(&dvert[i], defgrp_index);
			if (weight == 0.0f) {
				continue;
			}

			fac = fac_orig * weight;
			facm = 1.0f - fac;
		}

		normalize_v3(vec);

		if (flag & MOD_CAST_X)
			tmp_co[0] = fac * vec[0] * len + facm * tmp_co[0];
		if (flag & MOD_CAST_Y)
			tmp_co[1] = fac * vec[1] * len + facm * tmp_co[1];
		if (flag & MOD_CAST_Z)
			tmp_co[2] = fac * vec[2] * len + facm * tmp_co[2];

		if (ctrl_ob) {
			if (flag & MOD_CAST_USE_OB_TRANSFORM) {
				mul_m4_v3(imat, tmp_co);
			}
			else {
				add_v3_v3(tmp_co, center);
			}
		}

		copy_v3_v3(vertexCos[i], tmp_co);
	}
}
Пример #26
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;
	}
}
Пример #27
0
/**
 * Creates a #View3DControl handle and sets up
 * the view for first-person style navigation.
 */
struct View3DCameraControl *ED_view3d_cameracontrol_aquire(
    Scene *scene, View3D *v3d, RegionView3D *rv3d,
    const bool use_parent_root)
{
    View3DCameraControl *vctrl;

    vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);

    /* Store context */
    vctrl->ctx_scene = scene;
    vctrl->ctx_v3d = v3d;
    vctrl->ctx_rv3d = rv3d;

    vctrl->use_parent_root = use_parent_root;

    vctrl->persp_backup = rv3d->persp;
    vctrl->dist_backup = rv3d->dist;

    /* check for flying ortho camera - which we cant support well
     * we _could_ also check for an ortho camera but this is easier */
    if ((rv3d->persp == RV3D_CAMOB) &&
            (rv3d->is_persp == false))
    {
        ((Camera *)v3d->camera->data)->type = CAM_PERSP;
        vctrl->is_ortho_cam = true;
    }

    if (rv3d->persp == RV3D_CAMOB) {
        Object *ob_back;
        if (use_parent_root && (vctrl->root_parent = v3d->camera->parent)) {
            while (vctrl->root_parent->parent)
                vctrl->root_parent = vctrl->root_parent->parent;
            ob_back = vctrl->root_parent;
        }
        else {
            ob_back = v3d->camera;
        }

        /* store the original camera loc and rot */
        vctrl->obtfm = BKE_object_tfm_backup(ob_back);

        BKE_object_where_is_calc(scene, v3d->camera);
        negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);

        rv3d->dist = 0.0;
    }
    else {
        float tvec[3];
        /* perspective or ortho */
        if (rv3d->persp == RV3D_ORTHO)
            rv3d->persp = RV3D_PERSP;  /* if ortho projection, make perspective */

        copy_qt_qt(vctrl->rot_backup, rv3d->viewquat);
        copy_v3_v3(vctrl->ofs_backup, rv3d->ofs);

        /* the dist defines a vector that is infront of the offset
         * to rotate the view about.
         * this is no good for fly mode because we
         * want to rotate about the viewers center.
         * but to correct the dist removal we must
         * alter offset so the view doesn't jump. */

        rv3d->dist = 0.0f;

        copy_v3_fl3(tvec, 0.0f, 0.0f, vctrl->dist_backup);
        mul_mat3_m4_v3(rv3d->viewinv, tvec);
        sub_v3_v3(rv3d->ofs, tvec);
        /* Done with correcting for the dist */
    }

    ED_view3d_to_m4(vctrl->view_mat_prev, rv3d->ofs, rv3d->viewquat, rv3d->dist);

    return vctrl;
}
Пример #28
0
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	RegionView3D *rv3d = CTX_wm_region_data(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float gridf, imat[3][3], bmat[3][3], vec[3];
	int a;

	gridf = rv3d->gridview;

	if (obedit) {
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		tv = tvs.transverts;
		for (a = 0; a < tvs.transverts_tot; a++, tv++) {
			copy_v3_v3(vec, tv->loc);
			mul_m3_v3(bmat, vec);
			add_v3_v3(vec, obedit->obmat[3]);
			vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
			vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
			vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
			sub_v3_v3(vec, obedit->obmat[3]);
			
			mul_m3_v3(imat, vec);
			copy_v3_v3(tv->loc, vec);
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
		{
			if (ob->mode & OB_MODE_POSE) {
				bPoseChannel *pchan;
				bArmature *arm = ob->data;
				
				invert_m4_m4(ob->imat, ob->obmat);
				
				for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
					if (pchan->bone->flag & BONE_SELECTED) {
						if (pchan->bone->layer & arm->layer) {
							if ((pchan->bone->flag & BONE_CONNECTED) == 0) {
								float nLoc[3];
								
								/* get nearest grid point to snap to */
								copy_v3_v3(nLoc, pchan->pose_mat[3]);
								/* We must operate in world space! */
								mul_m4_v3(ob->obmat, nLoc);
								vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
								vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
								vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
								/* Back in object space... */
								mul_m4_v3(ob->imat, vec);
								
								/* Get location of grid point in pose space. */
								BKE_armature_loc_pose_to_bone(pchan, vec, vec);
								
								/* adjust location */
								if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
									pchan->loc[0] = vec[0];
								if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
									pchan->loc[1] = vec[1];
								if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
									pchan->loc[2] = vec[2];

								/* auto-keyframing */
								ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
							}
							/* if the bone has a parent and is connected to the parent,
							 * don't do anything - will break chain unless we do auto-ik.
							 */
						}
					}
				}
				ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
				
				DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
			}
			else {
				vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf);
				vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf);
				vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf);
				
				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
					
					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, vec);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += vec[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += vec[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += vec[2];
				
				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}
		CTX_DATA_END;
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
Пример #29
0
static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
                                ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
                                DerivedMesh *to_explode)
{
	DerivedMesh *explode, *dm = to_explode;
	MFace *mf = NULL, *mface;
	/* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */
	ParticleSimulationData sim = {NULL};
	ParticleData *pa = NULL, *pars = psmd->psys->particles;
	ParticleKey state, birth;
	EdgeHash *vertpahash;
	EdgeHashIterator *ehi;
	float *vertco = NULL, imat[4][4];
	float rot[4];
	float cfra;
	/* float timestep; */
	const int *facepa = emd->facepa;
	int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
	int i, v, u;
	unsigned int ed_v1, ed_v2, mindex = 0;
	MTFace *mtface = NULL, *mtf;

	totface = dm->getNumTessFaces(dm);
	totvert = dm->getNumVerts(dm);
	mface = dm->getTessFaceArray(dm);
	totpart = psmd->psys->totpart;

	sim.scene = scene;
	sim.ob = ob;
	sim.psys = psmd->psys;
	sim.psmd = psmd;

	/* timestep = psys_get_timestep(&sim); */

	cfra = BKE_scene_frame_get(scene);

	/* hash table for vertice <-> particle relations */
	vertpahash = BLI_edgehash_new(__func__);

	for (i = 0; i < totface; i++) {
		if (facepa[i] != totpart) {
			pa = pars + facepa[i];

			if ((pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) ||
			    (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) ||
			    (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0))
			{
				delface++;
				continue;
			}
		}

		/* do mindex + totvert to ensure the vertex index to be the first
		 * with BLI_edgehashIterator_getKey */
		if (facepa[i] == totpart || cfra < (pars + facepa[i])->time)
			mindex = totvert + totpart;
		else 
			mindex = totvert + facepa[i];

		mf = &mface[i];

		/* set face vertices to exist in particle group */
		BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, NULL);
		BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL);
		BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL);
		if (mf->v4)
			BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, NULL);
	}

	/* make new vertice indexes & count total vertices after duplication */
	ehi = BLI_edgehashIterator_new(vertpahash);
	for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
		BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
		totdup++;
	}
	BLI_edgehashIterator_free(ehi);

	/* the final duplicated vertices */
	explode = CDDM_from_template_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
	mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
	/*dupvert = CDDM_get_verts(explode);*/

	/* getting back to object space */
	invert_m4_m4(imat, ob->obmat);

	psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);

	/* duplicate & displace vertices */
	ehi = BLI_edgehashIterator_new(vertpahash);
	for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
		MVert source;
		MVert *dest;

		/* get particle + vertex from hash */
		BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
		ed_v2 -= totvert;
		v = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));

		dm->getVert(dm, ed_v1, &source);
		dest = CDDM_get_vert(explode, v);

		DM_copy_vert_data(dm, explode, ed_v1, v, 1);
		*dest = source;

		if (ed_v2 != totpart) {
			/* get particle */
			pa = pars + ed_v2;

			psys_get_birth_coords(&sim, pa, &birth, 0, 0);

			state.time = cfra;
			psys_get_particle_state(&sim, ed_v2, &state, 1);

			vertco = CDDM_get_vert(explode, v)->co;
			mul_m4_v3(ob->obmat, vertco);

			sub_v3_v3(vertco, birth.co);

			/* apply rotation, size & location */
			sub_qt_qtqt(rot, state.rot, birth.rot);
			mul_qt_v3(rot, vertco);

			if (emd->flag & eExplodeFlag_PaSize)
				mul_v3_fl(vertco, pa->size);

			add_v3_v3(vertco, state.co);

			mul_m4_v3(imat, vertco);
		}
	}
	BLI_edgehashIterator_free(ehi);

	/*map new vertices to faces*/
	for (i = 0, u = 0; i < totface; i++) {
		MFace source;
		int orig_v4;

		if (facepa[i] != totpart) {
			pa = pars + facepa[i];

			if (pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) continue;
			if (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) continue;
			if (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0) continue;
		}

		dm->getTessFace(dm, i, &source);
		mf = CDDM_get_tessface(explode, u);
		
		orig_v4 = source.v4;

		if (facepa[i] != totpart && cfra < pa->time)
			mindex = totvert + totpart;
		else 
			mindex = totvert + facepa[i];

		source.v1 = edgecut_get(vertpahash, source.v1, mindex);
		source.v2 = edgecut_get(vertpahash, source.v2, mindex);
		source.v3 = edgecut_get(vertpahash, source.v3, mindex);
		if (source.v4)
			source.v4 = edgecut_get(vertpahash, source.v4, mindex);

		DM_copy_tessface_data(dm, explode, i, u, 1);

		*mf = source;

		/* override uv channel for particle age */
		if (mtface) {
			float age = (cfra - pa->time) / pa->lifetime;
			/* Clamp to this range to avoid flipping to the other side of the coordinates. */
			CLAMP(age, 0.001f, 0.999f);

			mtf = mtface + u;

			mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age;
			mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f;
		}

		test_index_face(mf, &explode->faceData, u, (orig_v4 ? 4 : 3));
		u++;
	}

	/* cleanup */
	BLI_edgehash_free(vertpahash, NULL);

	/* finalization */
	CDDM_calc_edges_tessface(explode);
	CDDM_tessfaces_to_faces(explode);
	explode->dirty |= DM_DIRTY_NORMALS;

	if (psmd->psys->lattice_deform_data) {
		end_latt_deform(psmd->psys->lattice_deform_data);
		psmd->psys->lattice_deform_data = NULL;
	}

	return explode;
}
Пример #30
0
/* Code adapted from:
 * "GPU-based Volume Rendering, Real-time Volume Graphics", AK Peters/CRC Press
 */
static int create_view_aligned_slices(VolumeSlicer *slicer,
                                      const int num_slices,
                                      const float view_dir[3])
{
	const int indices[] = { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5 };

	const float vertices[8][3] = {
	    { slicer->min[0], slicer->min[1], slicer->min[2] },
	    { slicer->max[0], slicer->min[1], slicer->min[2] },
	    { slicer->max[0], slicer->max[1], slicer->min[2] },
	    { slicer->min[0], slicer->max[1], slicer->min[2] },
	    { slicer->min[0], slicer->min[1], slicer->max[2] },
	    { slicer->max[0], slicer->min[1], slicer->max[2] },
	    { slicer->max[0], slicer->max[1], slicer->max[2] },
	    { slicer->min[0], slicer->max[1], slicer->max[2] }
	};

	const int edges[12][2] = {
	    { 0, 1 }, { 1, 2 }, { 2, 3 },
	    { 3, 0 }, { 0, 4 }, { 1, 5 },
	    { 2, 6 }, { 3, 7 }, { 4, 5 },
	    { 5, 6 }, { 6, 7 }, { 7, 4 }
	};

	const int edge_list[8][12] = {
	    { 0, 1, 5, 6, 4, 8, 11, 9, 3, 7, 2, 10 },
	    { 0, 4, 3, 11, 1, 2, 6, 7, 5, 9, 8, 10 },
	    { 1, 5, 0, 8, 2, 3, 7, 4, 6, 10, 9, 11 },
	    { 7, 11, 10, 8, 2, 6, 1, 9, 3, 0, 4, 5 },
	    { 8, 5, 9, 1, 11, 10, 7, 6, 4, 3, 0, 2 },
	    { 9, 6, 10, 2, 8, 11, 4, 7, 5, 0, 1, 3 },
	    { 9, 8, 5, 4, 6, 1, 2, 0, 10, 7, 11, 3 },
	    { 10, 9, 6, 5, 7, 2, 3, 1, 11, 4, 8, 0 }
	};

	/* find vertex that is the furthest from the view plane */
	int max_index = 0;
	float max_dist, min_dist;
	min_dist = max_dist = dot_v3v3(view_dir, vertices[0]);

	for (int i = 1; i < 8; i++) {
		float dist = dot_v3v3(view_dir, vertices[i]);

		if (dist > max_dist) {
			max_dist = dist;
			max_index = i;
		}

		if (dist < min_dist) {
			min_dist = dist;
		}
	}

	max_dist -= FLT_EPSILON;
	min_dist += FLT_EPSILON;

	/* start and direction vectors */
	float vec_start[12][3], vec_dir[12][3];
	/* lambda intersection values */
	float lambda[12], lambda_inc[12];
	float denom = 0.0f;

	float plane_dist = min_dist;
	float plane_dist_inc = (max_dist - min_dist) / (float)num_slices;

	/* for all egdes */
	for (int i = 0; i < 12; i++) {
		copy_v3_v3(vec_start[i], vertices[edges[edge_list[max_index][i]][0]]);
		copy_v3_v3(vec_dir[i],   vertices[edges[edge_list[max_index][i]][1]]);
		sub_v3_v3(vec_dir[i], vec_start[i]);

		denom = dot_v3v3(vec_dir[i], view_dir);

		if (1.0f + denom != 1.0f) {
			lambda_inc[i] = plane_dist_inc / denom;
			lambda[i] = (plane_dist - dot_v3v3(vec_start[i], view_dir)) / denom;
		}
		else {
			lambda[i] = -1.0f;
			lambda_inc[i] = 0.0f;
		}
	}

	float intersections[6][3];
	float dL[12];
	int num_points = 0;
	/* find intersections for each slice, process them in back to front order */
	for (int i = 0; i < num_slices; i++) {
		for (int e = 0; e < 12; e++) {
			dL[e] = lambda[e] + i * lambda_inc[e];
		}

		if ((dL[0] >= 0.0f) && (dL[0] < 1.0f)) {
			madd_v3_v3v3fl(intersections[0], vec_start[0], vec_dir[0], dL[0]);
		}
		else if ((dL[1] >= 0.0f) && (dL[1] < 1.0f)) {
			madd_v3_v3v3fl(intersections[0], vec_start[1], vec_dir[1], dL[1]);
		}
		else if ((dL[3] >= 0.0f) && (dL[3] < 1.0f)) {
			madd_v3_v3v3fl(intersections[0], vec_start[3], vec_dir[3], dL[3]);
		}
		else continue;

		if ((dL[2] >= 0.0f) && (dL[2] < 1.0f)) {
			madd_v3_v3v3fl(intersections[1], vec_start[2], vec_dir[2], dL[2]);
		}
		else if ((dL[0] >= 0.0f) && (dL[0] < 1.0f)) {
			madd_v3_v3v3fl(intersections[1], vec_start[0], vec_dir[0], dL[0]);
		}
		else if ((dL[1] >= 0.0f) && (dL[1] < 1.0f)) {
			madd_v3_v3v3fl(intersections[1], vec_start[1], vec_dir[1], dL[1]);
		}
		else {
			madd_v3_v3v3fl(intersections[1], vec_start[3], vec_dir[3], dL[3]);
		}

		if ((dL[4] >= 0.0f) && (dL[4] < 1.0f)) {
			madd_v3_v3v3fl(intersections[2], vec_start[4], vec_dir[4], dL[4]);
		}
		else if ((dL[5] >= 0.0f) && (dL[5] < 1.0f)) {
			madd_v3_v3v3fl(intersections[2], vec_start[5], vec_dir[5], dL[5]);
		}
		else {
			madd_v3_v3v3fl(intersections[2], vec_start[7], vec_dir[7], dL[7]);
		}

		if ((dL[6] >= 0.0f) && (dL[6] < 1.0f)) {
			madd_v3_v3v3fl(intersections[3], vec_start[6], vec_dir[6], dL[6]);
		}
		else if ((dL[4] >= 0.0f) && (dL[4] < 1.0f)) {
			madd_v3_v3v3fl(intersections[3], vec_start[4], vec_dir[4], dL[4]);
		}
		else if ((dL[5] >= 0.0f) && (dL[5] < 1.0f)) {
			madd_v3_v3v3fl(intersections[3], vec_start[5], vec_dir[5], dL[5]);
		}
		else {
			madd_v3_v3v3fl(intersections[3], vec_start[7], vec_dir[7], dL[7]);
		}

		if ((dL[8] >= 0.0f) && (dL[8] < 1.0f)) {
			madd_v3_v3v3fl(intersections[4], vec_start[8], vec_dir[8], dL[8]);
		}
		else if ((dL[9] >= 0.0f) && (dL[9] < 1.0f)) {
			madd_v3_v3v3fl(intersections[4], vec_start[9], vec_dir[9], dL[9]);
		}
		else {
			madd_v3_v3v3fl(intersections[4], vec_start[11], vec_dir[11], dL[11]);
		}

		if ((dL[10] >= 0.0f) && (dL[10] < 1.0f)) {
			madd_v3_v3v3fl(intersections[5], vec_start[10], vec_dir[10], dL[10]);
		}
		else if ((dL[8] >= 0.0f) && (dL[8] < 1.0f)) {
			madd_v3_v3v3fl(intersections[5], vec_start[8], vec_dir[8], dL[8]);
		}
		else if ((dL[9] >= 0.0f) && (dL[9] < 1.0f)) {
			madd_v3_v3v3fl(intersections[5], vec_start[9], vec_dir[9], dL[9]);
		}
		else {
			madd_v3_v3v3fl(intersections[5], vec_start[11], vec_dir[11], dL[11]);
		}

		for (int e = 0; e < 12; e++) {
			copy_v3_v3(slicer->verts[num_points++], intersections[indices[e]]);
		}
	}

	return num_points;
}