Exemple #1
0
/* Used when canceling transforms - return rigidbody and object to initial states */
void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
{
	RigidBodyOb *rbo = ob->rigidbody_object;

	/* return rigid body and object to their initial states */
	copy_v3_v3(rbo->pos, ob->loc);
	copy_v3_v3(ob->loc, loc);

	if (ob->rotmode > 0) {
		eulO_to_quat(rbo->orn, ob->rot, ob->rotmode);
		copy_v3_v3(ob->rot, rot);
	}
	else if (ob->rotmode == ROT_MODE_AXISANGLE) {
		axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle);
		copy_v3_v3(ob->rotAxis, rotAxis);
		ob->rotAngle = rotAngle;
	}
	else {
		copy_qt_qt(rbo->orn, ob->quat);
		copy_qt_qt(ob->quat, quat);
	}
	if (rbo->physics_object) {
		/* allow passive objects to return to original transform */
		if (rbo->type == RBO_TYPE_PASSIVE)
			RB_body_set_kinematic_state(rbo->physics_object, TRUE);
		RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn);
	}
	// RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop)
}
Exemple #2
0
static int Quaternion_angle_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
{
	float tquat[4];
	float len;

	float axis[3], angle_dummy;
	float angle;

	if (BaseMath_ReadCallback(self) == -1)
		return -1;

	len = normalize_qt_qt(tquat, self->quat);
	quat_to_axis_angle(axis, &angle_dummy, tquat);

	angle = PyFloat_AsDouble(value);

	if (angle == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
		PyErr_SetString(PyExc_TypeError,
		                "Quaternion.angle = value: float expected");
		return -1;
	}

	angle = angle_wrap_rad(angle);

	quat__axis_angle_sanitize(axis, &angle);

	axis_angle_to_quat(self->quat, axis, angle);
	mul_qt_fl(self->quat, len);

	if (BaseMath_WriteCallback(self) == -1)
		return -1;

	return 0;
}
Exemple #3
0
//----------------------------------mathutils.Quaternion() --------------
static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	PyObject *seq = NULL;
	double angle = 0.0f;
	float quat[QUAT_SIZE] = {0.0f, 0.0f, 0.0f, 0.0f};

	if (kwds && PyDict_Size(kwds)) {
		PyErr_SetString(PyExc_TypeError,
		                "mathutils.Quaternion(): "
		                "takes no keyword args");
		return NULL;
	}

	if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle))
		return NULL;

	switch (PyTuple_GET_SIZE(args)) {
		case 0:
			break;
		case 1:
			if (mathutils_array_parse(quat, QUAT_SIZE, QUAT_SIZE, seq, "mathutils.Quaternion()") == -1)
				return NULL;
			break;
		case 2:
			if (mathutils_array_parse(quat, 3, 3, seq, "mathutils.Quaternion()") == -1)
				return NULL;
			angle = angle_wrap_rad(angle); /* clamp because of precision issues */
			axis_angle_to_quat(quat, quat, angle);
			break;
			/* PyArg_ParseTuple assures no more then 2 */
	}
	return Quaternion_CreatePyObject(quat, Py_NEW, type);
}
Exemple #4
0
static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
{
	float tquat[4];
	float len;

	float axis[3];
	float angle;

	if (BaseMath_ReadCallback(self) == -1)
		return -1;

	len = normalize_qt_qt(tquat, self->quat);
	quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */

	if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1)
		return -1;

	quat__axis_angle_sanitize(axis, &angle);

	axis_angle_to_quat(self->quat, axis, angle);
	mul_qt_fl(self->quat, len);

	if (BaseMath_WriteCallback(self) == -1)
		return -1;

	return 0;
}
Exemple #5
0
void view3d_align_axis_to_vector(View3D *v3d, RegionView3D *rv3d, int axisidx, float vec[3])
{
	float alignaxis[3] = {0.0, 0.0, 0.0};
	float norm[3], axis[3], angle, new_quat[4];
	
	if(axisidx > 0) alignaxis[axisidx-1]= 1.0;
	else alignaxis[-axisidx-1]= -1.0;

	normalize_v3_v3(norm, vec);

	angle= (float)acos(dot_v3v3(alignaxis, norm));
	cross_v3_v3v3(axis, alignaxis, norm);
	axis_angle_to_quat( new_quat,axis, -angle);
	
	rv3d->view= RV3D_VIEW_USER;
	
	if (rv3d->persp==RV3D_CAMOB && v3d->camera) {
		/* switch out of camera view */
		float orig_ofs[3];
		float orig_dist= rv3d->dist;
		float orig_lens= v3d->lens;
		
		copy_v3_v3(orig_ofs, rv3d->ofs);
		rv3d->persp= RV3D_PERSP;
		rv3d->dist= 0.0;
		ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, NULL, &v3d->lens);
		smooth_view(NULL, NULL, NULL, NULL, NULL, orig_ofs, new_quat, &orig_dist, &orig_lens); // XXX
	} else {
		if (rv3d->persp==RV3D_CAMOB) rv3d->persp= RV3D_PERSP; /* switch out of camera mode */
		smooth_view(NULL, NULL, NULL, NULL, NULL, NULL, new_quat, NULL, NULL); // XXX
	}
}
static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
						DerivedMesh *derivedData,
						int UNUSED(useRenderParams),
						int UNUSED(isFinalCalc))
{
	DerivedMesh *dm = derivedData, *result;
	ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
	ParticleSimulationData sim;
	ParticleSystem *psys= NULL;
	ParticleData *pa= NULL, *pars= NULL;
	MFace *mface, *orig_mface;
	MVert *mvert, *orig_mvert;
	int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
	short track=ob->trackflag%3, trackneg, axis = pimd->axis;
	float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
	float *size=NULL;

	trackneg=((ob->trackflag>2)?1:0);

	if(pimd->ob==ob){
		pimd->ob= NULL;
		return derivedData;
	}

	if(pimd->ob){
		psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
		if(psys==NULL || psys->totpart==0)
			return derivedData;
	}
	else return derivedData;

	if(pimd->flag & eParticleInstanceFlag_Parents)
		totpart+=psys->totpart;
	if(pimd->flag & eParticleInstanceFlag_Children){
		if(totpart==0)
			first_particle=psys->totpart;
		totpart+=psys->totchild;
	}

	if(totpart==0)
		return derivedData;

	sim.scene = md->scene;
	sim.ob = pimd->ob;
	sim.psys = psys;
	sim.psmd = psys_get_modifier(pimd->ob, psys);

	if(pimd->flag & eParticleInstanceFlag_UseSize) {
		int p;
		float *si;
		si = size = MEM_callocN(totpart * sizeof(float), "particle size array");

		if(pimd->flag & eParticleInstanceFlag_Parents) {
			for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
				*si = pa->size;
		}

		if(pimd->flag & eParticleInstanceFlag_Children) {
			ChildParticle *cpa = psys->child;

			for(p=0; p<psys->totchild; p++, cpa++, si++) {
				*si = psys_get_child_size(psys, cpa, 0.0f, NULL);
			}
		}
	}

	pars=psys->particles;

	totvert=dm->getNumVerts(dm);
	totface=dm->getNumFaces(dm);

	maxvert=totvert*totpart;
	maxface=totface*totpart;

	psys->lattice=psys_get_lattice(&sim);

	if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){

		float min_r[3], max_r[3];
		INIT_MINMAX(min_r, max_r);
		dm->getMinMax(dm, min_r, max_r);
		min_co=min_r[track];
		max_co=max_r[track];
	}

	result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);

	mvert=result->getVertArray(result);
	orig_mvert=dm->getVertArray(dm);

	for(i=0; i<maxvert; i++){
		MVert *inMV;
		MVert *mv = mvert + i;
		ParticleKey state;

		inMV = orig_mvert + i%totvert;
		DM_copy_vert_data(dm, result, i%totvert, i, 1);
		*mv = *inMV;

		/*change orientation based on object trackflag*/
		copy_v3_v3(temp_co, mv->co);
		mv->co[axis]=temp_co[track];
		mv->co[(axis+1)%3]=temp_co[(track+1)%3];
		mv->co[(axis+2)%3]=temp_co[(track+2)%3];

		if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
			float ran = 0.0f;
			if(pimd->random_position != 0.0f) {
				BLI_srandom(psys->seed + (i/totvert)%totpart);
				ran = pimd->random_position * BLI_frand();
			}

			if(pimd->flag & eParticleInstanceFlag_KeepShape) {
				state.time = pimd->position * (1.0f - ran);
			}
			else {
				state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);

				if(trackneg)
					state.time=1.0f-state.time;

				mv->co[axis] = 0.0;
			}

			psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);

			normalize_v3(state.vel);

			/* TODO: incremental rotations somehow */
			if(state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
				state.rot[0] = 1;
				state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
			}
			else {
				float temp[3] = {0.0f,0.0f,0.0f};
				temp[axis] = 1.0f;

				cross_v3_v3v3(cross, temp, state.vel);

				/* state.vel[axis] is the only component surviving from a dot product with the axis */
				axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
			}

		}
		else{
			state.time=-1.0;
			psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
		}

		mul_qt_v3(state.rot,mv->co);
		if(pimd->flag & eParticleInstanceFlag_UseSize)
			mul_v3_fl(mv->co, size[i/totvert]);
		VECADD(mv->co,mv->co,state.co);
	}

	mface=result->getFaceArray(result);
	orig_mface=dm->getFaceArray(dm);

	for(i=0; i<maxface; i++){
		MFace *inMF;
		MFace *mf = mface + i;

		if(pimd->flag & eParticleInstanceFlag_Parents){
			if(i/totface>=psys->totpart){
				if(psys->part->childtype==PART_CHILD_PARTICLES)
					pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
				else
					pa= NULL;
			}
			else
				pa=pars+i/totface;
		}
		else{
			if(psys->part->childtype==PART_CHILD_PARTICLES)
				pa=psys->particles+(psys->child+i/totface)->parent;
			else
				pa= NULL;
		}

		if(pa){
			if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
			if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
			if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
		}

		inMF = orig_mface + i%totface;
		DM_copy_face_data(dm, result, i%totface, i, 1);
		*mf = *inMF;

		mf->v1+=(i/totface)*totvert;
		mf->v2+=(i/totface)*totvert;
		mf->v3+=(i/totface)*totvert;
		if(mf->v4)
			mf->v4+=(i/totface)*totvert;
	}

	CDDM_calc_edges(result);
	CDDM_calc_normals(result);

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

	if(size)
		MEM_freeN(size);

	return result;
}
static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *arg)
{
	Scene *scene = CTX_data_scene(C);
	UnitSettings *unit = &scene->unit;
	RulerItem *ruler_item;
	RulerInfo *ruler_info = arg;
	RegionView3D *rv3d = ruler_info->ar->regiondata;
//	ARegion *ar = ruler_info->ar;
	const float cap_size = 4.0f;
	const float bg_margin = 4.0f * U.pixelsize;
	const float bg_radius = 4.0f * U.pixelsize;
	const float arc_size = 64.0f * U.pixelsize;
#define ARC_STEPS 24
	const int arc_steps = ARC_STEPS;
	int i;
	//unsigned int color_act = 0x666600;
	unsigned int color_act = 0xffffff;
	unsigned int color_base = 0x0;
	unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80};
	unsigned char color_text[3];
	unsigned char color_wire[3];

	/* anti-aliased lines for more consistent appearance */
	glEnable(GL_LINE_SMOOTH);

	BLF_enable(blf_mono_font, BLF_ROTATION);
	BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
	BLF_rotation(blf_mono_font, 0.0f);

	UI_GetThemeColor3ubv(TH_TEXT, color_text);
	UI_GetThemeColor3ubv(TH_WIRE, color_wire);

	for (ruler_item = ruler_info->items.first, i = 0; ruler_item; ruler_item = ruler_item->next, i++) {
		const bool is_act = (i == ruler_info->item_active);
		float dir_ruler[2];
		float co_ss[3][2];
		int j;

		/* should these be checked? - ok for now not to */
		for (j = 0; j < 3; j++) {
			ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
		}

		glEnable(GL_BLEND);

		cpack(is_act ? color_act : color_base);

		if (ruler_item->flag & RULERITEM_USE_ANGLE) {
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j++) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			cpack(0xaaaaaa);
			setlinestyle(3);
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j++) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			setlinestyle(0);

			/* arc */
			{
				float dir_tmp[3];
				float co_tmp[3];
				float arc_ss_coords[ARC_STEPS + 1][2];

				float dir_a[3];
				float dir_b[3];
				float quat[4];
				float axis[3];
				float angle;
				const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) *
				                        min_fff(arc_size,
				                                len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
				                                len_v2v2(co_ss[2], co_ss[1]) / 2.0f));

				sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
				sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
				normalize_v3(dir_a);
				normalize_v3(dir_b);

				cross_v3_v3v3(axis, dir_a, dir_b);
				angle = angle_normalized_v3v3(dir_a, dir_b);

				axis_angle_to_quat(quat, axis, angle / arc_steps);

				copy_v3_v3(dir_tmp, dir_a);

				glColor3ubv(color_wire);

				for (j = 0; j <= arc_steps; j++) {
					madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
					ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP);
					mul_qt_v3(quat, dir_tmp);
				}

				glEnableClientState(GL_VERTEX_ARRAY);
				glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords);
				glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1);
				glDisableClientState(GL_VERTEX_ARRAY);
			}

			/* text */
			{
				char numstr[256];
				float numstr_size[2];
				float pos[2];
				const int prec = 2;  /* XXX, todo, make optional */

				ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);

				BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);

				pos[0] = co_ss[1][0] + (cap_size * 2.0f);
				pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);

				/* draw text (bg) */
				glColor4ubv(color_back);
				uiSetRoundBox(UI_CNR_ALL);
				uiRoundBox(pos[0] - bg_margin,                  pos[1] - bg_margin,
				           pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
				           bg_radius);
				/* draw text */
				glColor3ubv(color_text);
				BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
				BLF_rotation(blf_mono_font, 0.0f);
				BLF_draw(blf_mono_font, numstr, sizeof(numstr));
			}

			/* capping */
			{
				float rot_90_vec_a[2];
				float rot_90_vec_b[2];
				float cap[2];

				sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
				rot_90_vec_a[0] = -dir_ruler[1];
				rot_90_vec_a[1] =  dir_ruler[0];
				normalize_v2(rot_90_vec_a);

				sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
				rot_90_vec_b[0] = -dir_ruler[1];
				rot_90_vec_b[1] =  dir_ruler[0];
				normalize_v2(rot_90_vec_b);

				glEnable(GL_BLEND);

				glColor3ubv(color_wire);

				glBegin(GL_LINES);

				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
				glVertex2fv(cap);

				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
				glVertex2fv(cap);

				/* angle vertex */
				glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
				glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
				glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
				glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
				glEnd();

				glDisable(GL_BLEND);
			}
		}
		else {
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j += 2) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			cpack(0xaaaaaa);
			setlinestyle(3);
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j += 2) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			setlinestyle(0);

			sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);

			/* text */
			{
				char numstr[256];
				float numstr_size[2];
				const int prec = 6;  /* XXX, todo, make optional */
				float pos[2];

				ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);

				BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);

				mid_v2_v2v2(pos, co_ss[0], co_ss[2]);

				/* center text */
				pos[0] -= numstr_size[0] / 2.0f;
				pos[1] -= numstr_size[1] / 2.0f;

				/* draw text (bg) */
				glColor4ubv(color_back);
				uiSetRoundBox(UI_CNR_ALL);
				uiRoundBox(pos[0] - bg_margin,                  pos[1] - bg_margin,
				           pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
				           bg_radius);
				/* draw text */
				glColor3ubv(color_text);
				BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
				BLF_draw(blf_mono_font, numstr, sizeof(numstr));
			}

			/* capping */
			{
				float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
				float cap[2];

				normalize_v2(rot_90_vec);

				glEnable(GL_BLEND);
				glColor3ubv(color_wire);

				glBegin(GL_LINES);
				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
				glVertex2fv(cap);

				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
				glVertex2fv(cap);
				glEnd();

				glDisable(GL_BLEND);
			}
		}
	}

	glDisable(GL_LINE_SMOOTH);

	BLF_disable(blf_mono_font, BLF_ROTATION);

#undef ARC_STEPS

	/* draw snap */
	if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG)) {
		ruler_item = ruler_item_active_get(ruler_info);
		if (ruler_item) {
			/* size from drawSnapping */
			const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
			float co_ss[3];
			ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP);

			cpack(color_act);
			circ(co_ss[0], co_ss[1], size * U.pixelsize);
		}
	}

}
static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
{
#define WALK_ROTATE_FAC 2.2f /* more is faster */
#define WALK_TOP_LIMIT DEG2RADF(85.0f)
#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
#define WALK_MOVE_SPEED base_speed
#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)

	/* walk mode - Ctrl+Shift+F
	 * a walk loop where the user can move move the view as if they are in a walk game
	 */
	RegionView3D *rv3d = walk->rv3d;
	ARegion *ar = walk->ar;

	float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
	float dvec[3] = {0.0f, 0.0f, 0.0f}; /* this is the direction that's added to the view offset per redraw */

	/* Camera Uprighting variables */
	float upvec[3] = {0.0f, 0.0f, 0.0f}; /* stores the view's up vector */

	int moffset[2]; /* mouse offset from the views center */
	float tmp_quat[4]; /* used for rotating the view */

#ifdef NDOF_WALK_DEBUG
	{
		static unsigned int iteration = 1;
		printf("walk timer %d\n", iteration++);
	}
#endif

	{
		/* mouse offset from the center */
		copy_v2_v2_int(moffset, walk->moffset);

		/* apply moffset so we can re-accumulate */
		walk->moffset[0] = 0;
		walk->moffset[1] = 0;

		/* revert mouse */
		if (walk->is_reversed) {
			moffset[1] = -moffset[1];
		}

		/* Should we redraw? */
		if ((walk->active_directions) ||
		    moffset[0] || moffset[1] ||
		    walk->teleport.state == WALK_TELEPORT_STATE_ON ||
		    walk->gravity_state != WALK_GRAVITY_STATE_OFF)
		{
			float dvec_tmp[3];

			/* time how fast it takes for us to redraw,
			 * this is so simple scenes don't walk too fast */
			double time_current;
			float time_redraw;
#ifdef NDOF_WALK_DRAW_TOOMUCH
			walk->redraw = 1;
#endif
			time_current = PIL_check_seconds_timer();
			time_redraw = (float)(time_current - walk->time_lastdraw);

			walk->time_lastdraw = time_current;

			/* base speed in m/s */
			walk->speed = WALK_MOVE_SPEED;

			if (walk->is_fast) {
				walk->speed *= WALK_BOOST_FACTOR;
			}
			else if (walk->is_slow) {
				walk->speed *= 1.0f / WALK_BOOST_FACTOR;
			}

			copy_m3_m4(mat, rv3d->viewinv);

			{
				/* rotate about the X axis- look up/down */
				if (moffset[1]) {
					float angle;
					float y;

					/* relative offset */
					y = (float) moffset[1] / ar->winy;

					/* speed factor */
					y *= WALK_ROTATE_FAC;

					/* user adjustement factor */
					y *= walk->mouse_speed;

					/* clamp the angle limits */
					/* it ranges from 90.0f to -90.0f */
					angle = -asinf(rv3d->viewmat[2][2]);

					if (angle > WALK_TOP_LIMIT && y > 0.0f)
						y = 0.0f;

					else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f)
						y = 0.0f;

					copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
					mul_m3_v3(mat, upvec);
					/* Rotate about the relative up vec */
					axis_angle_to_quat(tmp_quat, upvec, -y);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
				}

				/* rotate about the Y axis- look left/right */
				if (moffset[0]) {
					float x;

					/* if we're upside down invert the moffset */
					copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
					mul_m3_v3(mat, upvec);

					if (upvec[2] < 0.0f)
						moffset[0] = -moffset[0];

					/* relative offset */
					x = (float) moffset[0] / ar->winx;

					/* speed factor */
					x *= WALK_ROTATE_FAC;

					/* user adjustement factor */
					x *= walk->mouse_speed;

					copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);

					/* Rotate about the relative up vec */
					axis_angle_normalized_to_quat(tmp_quat, upvec, x);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
				}
			}

			/* WASD - 'move' translation code */
			if ((walk->active_directions) &&
			    (walk->gravity_state == WALK_GRAVITY_STATE_OFF))
			{

				short direction;
				zero_v3(dvec);

				if ((walk->active_directions & WALK_BIT_FORWARD) ||
				    (walk->active_directions & WALK_BIT_BACKWARD))
				{

					direction = 0;

					if ((walk->active_directions & WALK_BIT_FORWARD))
						direction += 1;

					if ((walk->active_directions & WALK_BIT_BACKWARD))
						direction -= 1;

					copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
					mul_m3_v3(mat, dvec_tmp);

					if (walk->navigation_mode == WALK_MODE_GRAVITY) {
						dvec_tmp[2] = 0.0f;
					}

					normalize_v3(dvec_tmp);
					add_v3_v3(dvec, dvec_tmp);

				}

				if ((walk->active_directions & WALK_BIT_LEFT) ||
				    (walk->active_directions & WALK_BIT_RIGHT))
				{

					direction = 0;

					if ((walk->active_directions & WALK_BIT_LEFT))
						direction += 1;

					if ((walk->active_directions & WALK_BIT_RIGHT))
						direction -= 1;

					dvec_tmp[0] = direction * rv3d->viewinv[0][0];
					dvec_tmp[1] = direction * rv3d->viewinv[0][1];
					dvec_tmp[2] = 0.0f;

					normalize_v3(dvec_tmp);
					add_v3_v3(dvec, dvec_tmp);

				}

				if ((walk->active_directions & WALK_BIT_UP) ||
				    (walk->active_directions & WALK_BIT_DOWN))
				{

					if (walk->navigation_mode == WALK_MODE_FREE) {

						direction = 0;

						if ((walk->active_directions & WALK_BIT_UP))
							direction -= 1;

						if ((walk->active_directions & WALK_BIT_DOWN))
							direction = 1;

						copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
						add_v3_v3(dvec, dvec_tmp);
					}
				}

				/* apply movement */
				mul_v3_fl(dvec, walk->speed * time_redraw);
			}

			/* stick to the floor */
			if (walk->navigation_mode == WALK_MODE_GRAVITY &&
			    ELEM(walk->gravity_state,
			         WALK_GRAVITY_STATE_OFF,
			         WALK_GRAVITY_STATE_START))
			{

				bool ret;
				float ray_distance;
				float difference = -100.0f;
				float fall_distance;

				ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);

				if (ret) {
					difference = walk->view_height - ray_distance;
				}

				/* the distance we would fall naturally smoothly enough that we
				 * can manually drop the object without activating gravity */
				fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;

				if (fabsf(difference) < fall_distance) {
					/* slope/stairs */
					dvec[2] -= difference;

					/* in case we switched from FREE to GRAVITY too close to the ground */
					if (walk->gravity_state == WALK_GRAVITY_STATE_START)
						walk->gravity_state = WALK_GRAVITY_STATE_OFF;
				}
				else {
					/* hijack the teleport variables */
					walk->teleport.initial_time = PIL_check_seconds_timer();
					walk->gravity_state = WALK_GRAVITY_STATE_ON;
					walk->teleport.duration = 0.0f;

					copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
					copy_v2_v2(walk->teleport.direction, dvec);

				}
			}

			/* Falling or jumping) */
			if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
				float t;
				float z_cur, z_new;
				bool ret;
				float ray_distance, difference = -100.0f;

				/* delta time */
				t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);

				/* keep moving if we were moving */
				copy_v2_v2(dvec, walk->teleport.direction);

				z_cur = walk->rv3d->viewinv[3][2];
				z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;

				/* jump */
				z_new += t * walk->speed_jump * walk->grid;

				/* duration is the jump duration */
				if (t > walk->teleport.duration) {

					/* check to see if we are landing */
					ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance);

					if (ret) {
						difference = walk->view_height - ray_distance;
					}

					if (difference > 0.0f) {
						/* quit falling, lands at "view_height" from the floor */
						dvec[2] -= difference;
						walk->gravity_state = WALK_GRAVITY_STATE_OFF;
						walk->speed_jump = 0.0f;
					}
					else {
						/* keep falling */
						dvec[2] = z_cur - z_new;
					}
				}
				else {
					/* keep going up (jump) */
					dvec[2] = z_cur - z_new;
				}
			}

			/* Teleport */
			else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
				float t; /* factor */
				float new_loc[3];
				float cur_loc[3];

				/* linear interpolation */
				t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
				t /= walk->teleport.duration;

				/* clamp so we don't go past our limit */
				if (t >= 1.0f) {
					t = 1.0f;
					walk->teleport.state = WALK_TELEPORT_STATE_OFF;
					walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode);
				}

				mul_v3_v3fl(new_loc, walk->teleport.direction, t);
				add_v3_v3(new_loc, walk->teleport.origin);

				copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
				sub_v3_v3v3(dvec, cur_loc, new_loc);
			}

			if (rv3d->persp == RV3D_CAMOB) {
				Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
				if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0f;
				if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0f;
				if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0f;
			}

			/* scale the movement to the scene size */
			mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
			add_v3_v3(rv3d->ofs, dvec_tmp);

			if (rv3d->persp == RV3D_CAMOB) {
				const bool do_rotate = (moffset[0] || moffset[1]);
				const bool do_translate = (walk->speed != 0.0f);
				walkMoveCamera(C, walk, do_rotate, do_translate);
			}
		}
		else {
			/* we're not redrawing but we need to update the time else the view will jump */
			walk->time_lastdraw = PIL_check_seconds_timer();
		}
		/* end drawing */
		copy_v3_v3(walk->dvec_prev, dvec);
	}

	return OPERATOR_FINISHED;
#undef WALK_ROTATE_FAC
#undef WALK_ZUP_CORRECT_FAC
#undef WALK_ZUP_CORRECT_ACCEL
#undef WALK_SMOOTH_FAC
#undef WALK_TOP_LIMIT
#undef WALK_BOTTOM_LIMIT
#undef WALK_MOVE_SPEED
#undef WALK_BOOST_FACTOR
}
static int walkApply_ndof(bContext *C, WalkInfo *walk)
{
	/* shorthand for oft-used variables */
	wmNDOFMotionData *ndof = walk->ndof;
	const float dt = ndof->dt;
	RegionView3D *rv3d = walk->rv3d;
	const int flag = U.ndof_flag;

#if 0
	bool do_rotate = (flag & NDOF_SHOULD_ROTATE) && (walk->pan_view == false);
	bool do_translate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)) != 0;
#endif

	bool do_rotate = true;
	bool do_translate = true;

	float view_inv[4];
	invert_qt_qt(view_inv, rv3d->viewquat);

	rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */

	if (do_translate) {
		const float forward_sensitivity  = 1.0f;
		const float vertical_sensitivity = 0.4f;
		const float lateral_sensitivity  = 0.6f;

		float speed = 10.0f; /* blender units per second */
		/* ^^ this is ok for default cube scene, but should scale with.. something */

		float trans[3] = {lateral_sensitivity  * ndof->tvec[0],
		                  vertical_sensitivity * ndof->tvec[1],
		                  forward_sensitivity  * ndof->tvec[2]};

		if (walk->is_slow)
			speed *= 0.2f;

		mul_v3_fl(trans, speed * dt);

		/* transform motion from view to world coordinates */
		mul_qt_v3(view_inv, trans);

		if (flag & NDOF_FLY_HELICOPTER) {
			/* replace world z component with device y (yes it makes sense) */
			trans[2] = speed * dt * vertical_sensitivity * ndof->tvec[1];
		}

		if (rv3d->persp == RV3D_CAMOB) {
			/* respect camera position locks */
			Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
			if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.0f;
			if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.0f;
			if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.0f;
		}

		if (!is_zero_v3(trans)) {
			/* move center of view opposite of hand motion (this is camera mode, not object mode) */
			sub_v3_v3(rv3d->ofs, trans);
			do_translate = true;
		}
		else {
			do_translate = false;
		}
	}

	if (do_rotate) {
		const float turn_sensitivity = 1.0f;

		float rotation[4];
		float axis[3];
		float angle = turn_sensitivity * ndof_to_axis_angle(ndof, axis);

		if (fabsf(angle) > 0.0001f) {
			do_rotate = true;

			if (walk->is_slow)
				angle *= 0.2f;

			/* transform rotation axis from view to world coordinates */
			mul_qt_v3(view_inv, axis);

			/* apply rotation to view */
			axis_angle_to_quat(rotation, axis, angle);
			mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);

			if (flag & NDOF_LOCK_HORIZON) {
				/* force an upright viewpoint
				 * TODO: make this less... sudden */
				float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */
				float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */

				/* find new inverse since viewquat has changed */
				invert_qt_qt(view_inv, rv3d->viewquat);
				/* could apply reverse rotation to existing view_inv to save a few cycles */

				/* transform view vectors to world coordinates */
				mul_qt_v3(view_inv, view_horizon);
				mul_qt_v3(view_inv, view_direction);


				/* find difference between view & world horizons
				 * true horizon lives in world xy plane, so look only at difference in z */
				angle = -asinf(view_horizon[2]);

#ifdef NDOF_WALK_DEBUG
				printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle));
#endif

				/* rotate view so view horizon = world horizon */
				axis_angle_to_quat(rotation, view_direction, angle);
				mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
			}

			rv3d->view = RV3D_VIEW_USER;
		}
		else {
			do_rotate = false;
		}
	}

	if (do_translate || do_rotate) {
		walk->redraw = true;

		if (rv3d->persp == RV3D_CAMOB) {
			walkMoveCamera(C, walk, do_rotate, do_translate);
		}
	}

	return OPERATOR_FINISHED;
}
Exemple #10
0
static int flyApply(bContext *C, FlyInfo *fly)
{
#define FLY_ROTATE_FAC 2.5f /* more is faster */
#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
#define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */

	/* fly mode - Shift+F
	 * a fly loop where the user can move move the view as if they are flying
	 */
	RegionView3D *rv3d = fly->rv3d;
	ARegion *ar = fly->ar;

	float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
	float dvec[3] = {0, 0, 0}; /* this is the direction thast added to the view offset per redraw */

	/* Camera Uprighting variables */
	float upvec[3] = {0, 0, 0}; /* stores the view's up vector */

	float moffset[2]; /* mouse offset from the views center */
	float tmp_quat[4]; /* used for rotating the view */

//	int cent_orig[2], /* view center */
//XXX- can avoid using //   cent[2], /* view center modified */
	int xmargin, ymargin; /* x and y margin are define the safe area where the mouses movement wont rotate the view */

#ifdef NDOF_FLY_DEBUG
	{
		static unsigned int iteration = 1;
		printf("fly timer %d\n", iteration++);
	}
#endif

	xmargin = ar->winx / 20.0f;
	ymargin = ar->winy / 20.0f;

	// UNUSED
	// cent_orig[0] = ar->winrct.xmin + ar->winx / 2;
	// cent_orig[1] = ar->winrct.ymin + ar->winy / 2;

	{

		/* mouse offset from the center */
		moffset[0] = fly->mval[0] - ar->winx / 2;
		moffset[1] = fly->mval[1] - ar->winy / 2;

		/* enforce a view margin */
		if      (moffset[0] >  xmargin) moffset[0] -= xmargin;
		else if (moffset[0] < -xmargin) moffset[0] += xmargin;
		else                            moffset[0] =  0;

		if      (moffset[1] >  ymargin) moffset[1] -= ymargin;
		else if (moffset[1] < -ymargin) moffset[1] += ymargin;
		else                            moffset[1] =  0;


		/* scale the mouse movement by this value - scales mouse movement to the view size
		 * moffset[0] / (ar->winx-xmargin * 2) - window size minus margin (same for y)
		 *
		 * the mouse moves isn't linear */

		if (moffset[0]) {
			moffset[0] /= ar->winx - (xmargin * 2);
			moffset[0] *= fabsf(moffset[0]);
		}

		if (moffset[1]) {
			moffset[1] /= ar->winy - (ymargin * 2);
			moffset[1] *= fabsf(moffset[1]);
		}

		/* Should we redraw? */
		if ((fly->speed != 0.0f) ||
		    moffset[0] || moffset[1] ||
		    (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
		    (fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
		    dvec[0] || dvec[1] || dvec[2])
		{
			float dvec_tmp[3];

			/* time how fast it takes for us to redraw,
			 * this is so simple scenes don't fly too fast */
			double time_current;
			float time_redraw;
			float time_redraw_clamped;
#ifdef NDOF_FLY_DRAW_TOOMUCH
			fly->redraw = 1;
#endif
			time_current = PIL_check_seconds_timer();
			time_redraw = (float)(time_current - fly->time_lastdraw);
			time_redraw_clamped = min_ff(0.05f, time_redraw); /* clamp redraw time to avoid jitter in roll correction */
			fly->time_lastdraw = time_current;

			/* Scale the time to use shift to scale the speed down- just like
			 * shift slows many other areas of blender down */
			if (fly->use_precision)
				fly->speed = fly->speed * (1.0f - time_redraw_clamped);

			copy_m3_m4(mat, rv3d->viewinv);

			if (fly->pan_view == true) {
				/* pan only */
				dvec_tmp[0] = -moffset[0];
				dvec_tmp[1] = -moffset[1];
				dvec_tmp[2] = 0;

				if (fly->use_precision) {
					dvec_tmp[0] *= 0.1f;
					dvec_tmp[1] *= 0.1f;
				}

				mul_m3_v3(mat, dvec_tmp);
				mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid);
			}
			else {
				float roll; /* similar to the angle between the camera's up and the Z-up,
				             * but its very rough so just roll */

				/* rotate about the X axis- look up/down */
				if (moffset[1]) {
					upvec[0] = 1;
					upvec[1] = 0;
					upvec[2] = 0;
					mul_m3_v3(mat, upvec);
					/* Rotate about the relative up vec */
					axis_angle_to_quat(tmp_quat, upvec, (float)moffset[1] * time_redraw * -FLY_ROTATE_FAC);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);

					if (fly->xlock != FLY_AXISLOCK_STATE_OFF)
						fly->xlock = FLY_AXISLOCK_STATE_ACTIVE;  /* check for rotation */
					if (fly->zlock != FLY_AXISLOCK_STATE_OFF)
						fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
					fly->xlock_momentum = 0.0f;
				}

				/* rotate about the Y axis- look left/right */
				if (moffset[0]) {

					/* if we're upside down invert the moffset */
					upvec[0] = 0.0f;
					upvec[1] = 1.0f;
					upvec[2] = 0.0f;
					mul_m3_v3(mat, upvec);

					if (upvec[2] < 0.0f)
						moffset[0] = -moffset[0];

					/* make the lock vectors */
					if (fly->zlock) {
						upvec[0] = 0.0f;
						upvec[1] = 0.0f;
						upvec[2] = 1.0f;
					}
					else {
						upvec[0] = 0.0f;
						upvec[1] = 1.0f;
						upvec[2] = 0.0f;
						mul_m3_v3(mat, upvec);
					}

					/* Rotate about the relative up vec */
					axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);

					if (fly->xlock != FLY_AXISLOCK_STATE_OFF)
						fly->xlock = FLY_AXISLOCK_STATE_ACTIVE;  /* check for rotation */
					if (fly->zlock != FLY_AXISLOCK_STATE_OFF)
						fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
				}

				if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) {
					upvec[0] = 1.0f;
					upvec[1] = 0.0f;
					upvec[2] = 0.0f;
					mul_m3_v3(mat, upvec);

					/* make sure we have some z rolling */
					if (fabsf(upvec[2]) > 0.00001f) {
						roll = upvec[2] * 5.0f;
						upvec[0] = 0.0f; /* rotate the view about this axis */
						upvec[1] = 0.0f;
						upvec[2] = 1.0f;

						mul_m3_v3(mat, upvec);
						/* Rotate about the relative up vec */
						axis_angle_to_quat(tmp_quat, upvec,
						                   roll * time_redraw_clamped * fly->zlock_momentum * FLY_ZUP_CORRECT_FAC);
						mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);

						fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL;
					}
					else {
						fly->zlock = FLY_AXISLOCK_STATE_IDLE; /* don't check until the view rotates again */
						fly->zlock_momentum = 0.0f;
					}
				}

				/* only apply xcorrect when mouse isn't applying x rot */
				if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) {
					upvec[0] = 0;
					upvec[1] = 0;
					upvec[2] = 1;
					mul_m3_v3(mat, upvec);
					/* make sure we have some z rolling */
					if (fabsf(upvec[2]) > 0.00001f) {
						roll = upvec[2] * -5.0f;

						upvec[0] = 1.0f; /* rotate the view about this axis */
						upvec[1] = 0.0f;
						upvec[2] = 0.0f;

						mul_m3_v3(mat, upvec);

						/* Rotate about the relative up vec */
						axis_angle_to_quat(tmp_quat, upvec, roll * time_redraw_clamped * fly->xlock_momentum * 0.1f);
						mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);

						fly->xlock_momentum += 0.05f;
					}
					else {
						fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */
						fly->xlock_momentum = 0.0f;
					}
				}

				if (fly->axis == -1) {
					/* pause */
					zero_v3(dvec_tmp);
				}
				else if (!fly->use_freelook) {
					/* Normal operation */
					/* define dvec, view direction vector */
					zero_v3(dvec_tmp);
					/* move along the current axis */
					dvec_tmp[fly->axis] = 1.0f;

					mul_m3_v3(mat, dvec_tmp);
				}
				else {
					normalize_v3_v3(dvec_tmp, fly->dvec_prev);
					if (fly->speed < 0.0f) {
						negate_v3(dvec_tmp);
					}
				}

				mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f);
			}

			/* impose a directional lag */
			interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * 5.0f))));

			if (rv3d->persp == RV3D_CAMOB) {
				Object *lock_ob = fly->root_parent ? fly->root_parent : fly->v3d->camera;
				if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0;
				if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0;
				if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0;
			}

			add_v3_v3(rv3d->ofs, dvec);

			if (rv3d->persp == RV3D_CAMOB) {
				const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
				                        (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
				                        ((moffset[0] || moffset[1]) && !fly->pan_view));
				const bool do_translate = (fly->speed != 0.0f || fly->pan_view);
				flyMoveCamera(C, rv3d, fly, do_rotate, do_translate);
			}

		}
		else {
			/* we're not redrawing but we need to update the time else the view will jump */
			fly->time_lastdraw = PIL_check_seconds_timer();
		}
		/* end drawing */
		copy_v3_v3(fly->dvec_prev, dvec);
	}

	return OPERATOR_FINISHED;
}
Exemple #11
0
int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
	BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
	bPoseChannel* pchan = self->m_posechannel;
	PyObject *item;
	float joints[3];
	float quat[4];

	if (!PySequence_Check(value) || PySequence_Size(value) != 3) {
		PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats");
		return PY_SET_ATTR_FAIL;
	}
	for (int i=0; i<3; i++) {
		item = PySequence_GetItem(value, i); /* new ref */
		joints[i] = PyFloat_AsDouble(item);
		Py_DECREF(item);
		if (joints[i] == -1.0f && PyErr_Occurred()) {
			PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats");
			return PY_SET_ATTR_FAIL;
		}
	}

	int flag = 0;
	if (!(pchan->ikflag & BONE_IK_NO_XDOF))
		flag |= 1;
	if (!(pchan->ikflag & BONE_IK_NO_YDOF))
		flag |= 2;
	if (!(pchan->ikflag & BONE_IK_NO_ZDOF))
		flag |= 4;
	unit_qt(quat);
	switch (flag) {
	case 0:	// fixed joint
		break;
	case 1:	// X only
		joints[1] = joints[2] = 0.f;
		eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
		break;
	case 2:	// Y only
		joints[0] = joints[2] = 0.f;
		eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
		break;
	case 3:	// X+Y
		joints[2] = 0.f;
		eulO_to_quat( quat,joints, EULER_ORDER_ZYX);
		break;
	case 4:	// Z only
		joints[0] = joints[1] = 0.f;
		eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
		break;
	case 5:	// X+Z
		// X and Z are components of an equivalent rotation axis
		joints[1] = 0;
		axis_angle_to_quat( quat,joints, len_v3(joints));
		break;
	case 6:	// Y+Z
		joints[0] = 0.f;
		eulO_to_quat( quat,joints, EULER_ORDER_XYZ);
		break;
	case 7: // X+Y+Z
		// equivalent axis
		axis_angle_to_quat( quat,joints, len_v3(joints));
		break;
	}
	if (pchan->rotmode > 0) {
		quat_to_eulO( joints, pchan->rotmode,quat);
		copy_v3_v3(pchan->eul, joints);
	} else
		copy_qt_qt(pchan->quat, quat);
	return PY_SET_ATTR_SUCCESS;
}
Exemple #12
0
/* tries to realize the wanted velocity taking all constraints into account */
void boid_body(BoidBrainData *bbd, ParticleData *pa)
{
	BoidSettings *boids = bbd->part->boids;
	BoidParticle *bpa = pa->boid;
	BoidValues val;
	EffectedPoint epoint;
	float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3];
	float dvec[3], bvec[3];
	float new_dir[3], new_speed;
	float old_dir[3], old_speed;
	float wanted_dir[3];
	float q[4], mat[3][3]; /* rotation */
	float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f};
	float force[3] = {0.0f, 0.0f, 0.0f};
	float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep;

	set_boid_values(&val, boids, pa);

	/* make sure there's something in new velocity, location & rotation */
	copy_particle_key(&pa->state, &pa->prev_state, 0);

	if (bbd->part->flag & PART_SIZEMASS)
		pa_mass*=pa->size;

	/* if boids can't fly they fall to the ground */
	if ((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && psys_uses_gravity(bbd->sim))
		bpa->data.mode = eBoidMode_Falling;

	if (bpa->data.mode == eBoidMode_Falling) {
		/* Falling boids are only effected by gravity. */
		acc[2] = bbd->sim->scene->physics_settings.gravity[2];
	}
	else {
		/* figure out acceleration */
		float landing_level = 2.0f;
		float level = landing_level + 1.0f;
		float new_vel[3];

		if (bpa->data.mode == eBoidMode_Liftoff) {
			bpa->data.mode = eBoidMode_InAir;
			bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
		}
		else if (bpa->data.mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) {
			/* auto-leveling & landing if close to ground */

			bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
			
			/* level = how many particle sizes above ground */
			level = (pa->prev_state.co[2] - ground_co[2])/(2.0f * pa->size) - 0.5f;

			landing_level = - boids->landing_smoothness * pa->prev_state.vel[2] * pa_mass;

			if (pa->prev_state.vel[2] < 0.0f) {
				if (level < 1.0f) {
					bbd->wanted_co[0] = bbd->wanted_co[1] = bbd->wanted_co[2] = 0.0f;
					bbd->wanted_speed = 0.0f;
					bpa->data.mode = eBoidMode_Falling;
				}
				else if (level < landing_level) {
					bbd->wanted_speed *= (level - 1.0f)/landing_level;
					bbd->wanted_co[2] *= (level - 1.0f)/landing_level;
				}
			}
		}

		copy_v3_v3(old_dir, pa->prev_state.ave);
		new_speed = normalize_v3_v3(wanted_dir, bbd->wanted_co);

		/* first check if we have valid direction we want to go towards */
		if (new_speed == 0.0f) {
			copy_v3_v3(new_dir, old_dir);
		}
		else {
			float old_dir2[2], wanted_dir2[2], nor[3], angle;
			copy_v2_v2(old_dir2, old_dir);
			normalize_v2(old_dir2);
			copy_v2_v2(wanted_dir2, wanted_dir);
			normalize_v2(wanted_dir2);

			/* choose random direction to turn if wanted velocity */
			/* is directly behind regardless of z-coordinate */
			if (dot_v2v2(old_dir2, wanted_dir2) < -0.99f) {
				wanted_dir[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
				wanted_dir[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
				wanted_dir[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
				normalize_v3(wanted_dir);
			}

			/* constrain direction with maximum angular velocity */
			angle = saacos(dot_v3v3(old_dir, wanted_dir));
			angle = min_ff(angle, val.max_ave);

			cross_v3_v3v3(nor, old_dir, wanted_dir);
			axis_angle_to_quat(q, nor, angle);
			copy_v3_v3(new_dir, old_dir);
			mul_qt_v3(q, new_dir);
			normalize_v3(new_dir);

			/* save direction in case resulting velocity too small */
			axis_angle_to_quat(q, nor, angle*dtime);
			copy_v3_v3(pa->state.ave, old_dir);
			mul_qt_v3(q, pa->state.ave);
			normalize_v3(pa->state.ave);
		}

		/* constrain speed with maximum acceleration */
		old_speed = len_v3(pa->prev_state.vel);
		
		if (bbd->wanted_speed < old_speed)
			new_speed = MAX2(bbd->wanted_speed, old_speed - val.max_acc);
		else
			new_speed = MIN2(bbd->wanted_speed, old_speed + val.max_acc);

		/* combine direction and speed */
		copy_v3_v3(new_vel, new_dir);
		mul_v3_fl(new_vel, new_speed);

		/* maintain minimum flying velocity if not landing */
		if (level >= landing_level) {
			float len2 = dot_v2v2(new_vel, new_vel);
			float root;

			len2 = MAX2(len2, val.min_speed*val.min_speed);
			root = sasqrt(new_speed*new_speed - len2);

			new_vel[2] = new_vel[2] < 0.0f ? -root : root;

			normalize_v2(new_vel);
			mul_v2_fl(new_vel, sasqrt(len2));
		}

		/* finally constrain speed to max speed */
		new_speed = normalize_v3(new_vel);
		mul_v3_fl(new_vel, MIN2(new_speed, val.max_speed));

		/* get acceleration from difference of velocities */
		sub_v3_v3v3(acc, new_vel, pa->prev_state.vel);

		/* break acceleration to components */
		project_v3_v3v3(tan_acc, acc, pa->prev_state.ave);
		sub_v3_v3v3(nor_acc, acc, tan_acc);
	}

	/* account for effectors */
	pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
	pdDoEffectors(bbd->sim->psys->effectors, bbd->sim->colliders, bbd->part->effector_weights, &epoint, force, NULL);

	if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
		float length = normalize_v3(force);

		length = MAX2(0.0f, length - boids->land_stick_force);

		mul_v3_fl(force, length);
	}
	
	add_v3_v3(acc, force);

	/* store smoothed acceleration for nice banking etc. */
	madd_v3_v3fl(bpa->data.acc, acc, dtime);
	mul_v3_fl(bpa->data.acc, 1.0f / (1.0f + dtime));

	/* integrate new location & velocity */

	/* by regarding the acceleration as a force at this stage we*/
	/* can get better control allthough it's a bit unphysical	*/
	mul_v3_fl(acc, 1.0f/pa_mass);

	copy_v3_v3(dvec, acc);
	mul_v3_fl(dvec, dtime*dtime*0.5f);
	
	copy_v3_v3(bvec, pa->prev_state.vel);
	mul_v3_fl(bvec, dtime);
	add_v3_v3(dvec, bvec);
	add_v3_v3(pa->state.co, dvec);

	madd_v3_v3fl(pa->state.vel, acc, dtime);

	//if (bpa->data.mode != eBoidMode_InAir)
	bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);

	/* change modes, constrain movement & keep track of down vector */
	switch (bpa->data.mode) {
		case eBoidMode_InAir:
		{
			float grav[3];

			grav[0] = 0.0f;
			grav[1] = 0.0f;
			grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;

			/* don't take forward acceleration into account (better banking) */
			if (dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) {
				project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
				sub_v3_v3v3(dvec, bpa->data.acc, dvec);
			}
			else {
				copy_v3_v3(dvec, bpa->data.acc);
			}

			/* gather apparent gravity */
			madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
			normalize_v3(bpa->gravity);

			/* stick boid on goal when close enough */
			if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
				bpa->data.mode = eBoidMode_Climbing;
				bpa->ground = bbd->goal_ob;
				boid_find_ground(bbd, pa, ground_co, ground_nor);
				boid_climb(boids, pa, ground_co, ground_nor);
			}
			else if (pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
				/* land boid when below ground */
				if (boids->options & BOID_ALLOW_LAND) {
					pa->state.co[2] = ground_co[2] + pa->size * boids->height;
					pa->state.vel[2] = 0.0f;
					bpa->data.mode = eBoidMode_OnLand;
				}
				/* fly above ground */
				else if (bpa->ground) {
					pa->state.co[2] = ground_co[2] + pa->size * boids->height;
					pa->state.vel[2] = 0.0f;
				}
			}
			break;
		}
		case eBoidMode_Falling:
		{
			float grav[3];

			grav[0] = 0.0f;
			grav[1] = 0.0f;
			grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;


			/* gather apparent gravity */
			madd_v3_v3fl(bpa->gravity, grav, dtime);
			normalize_v3(bpa->gravity);

			if (boids->options & BOID_ALLOW_LAND) {
				/* stick boid on goal when close enough */
				if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
					bpa->data.mode = eBoidMode_Climbing;
					bpa->ground = bbd->goal_ob;
					boid_find_ground(bbd, pa, ground_co, ground_nor);
					boid_climb(boids, pa, ground_co, ground_nor);
				}
				/* land boid when really near ground */
				else if (pa->state.co[2] <= ground_co[2] + 1.01f * pa->size * boids->height) {
					pa->state.co[2] = ground_co[2] + pa->size * boids->height;
					pa->state.vel[2] = 0.0f;
					bpa->data.mode = eBoidMode_OnLand;
				}
				/* if we're falling, can fly and want to go upwards lets fly */
				else if (boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f)
					bpa->data.mode = eBoidMode_InAir;
			}
			else
				bpa->data.mode = eBoidMode_InAir;
			break;
		}
		case eBoidMode_Climbing:
		{
			boid_climb(boids, pa, ground_co, ground_nor);
			//float nor[3];
			//copy_v3_v3(nor, ground_nor);

			///* gather apparent gravity to r_ve */
			//madd_v3_v3fl(pa->r_ve, ground_nor, -1.0);
			//normalize_v3(pa->r_ve);

			///* raise boid it's size from surface */
			//mul_v3_fl(nor, pa->size * boids->height);
			//add_v3_v3v3(pa->state.co, ground_co, nor);

			///* remove normal component from velocity */
			//project_v3_v3v3(v, pa->state.vel, ground_nor);
			//sub_v3_v3v3(pa->state.vel, pa->state.vel, v);
			break;
		}
		case eBoidMode_OnLand:
		{
			/* stick boid on goal when close enough */
			if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
				bpa->data.mode = eBoidMode_Climbing;
				bpa->ground = bbd->goal_ob;
				boid_find_ground(bbd, pa, ground_co, ground_nor);
				boid_climb(boids, pa, ground_co, ground_nor);
			}
			/* ground is too far away so boid falls */
			else if (pa->state.co[2]-ground_co[2] > 1.1f * pa->size * boids->height)
				bpa->data.mode = eBoidMode_Falling;
			else {
				/* constrain to surface */
				pa->state.co[2] = ground_co[2] + pa->size * boids->height;
				pa->state.vel[2] = 0.0f;
			}

			if (boids->banking > 0.0f) {
				float grav[3];
				/* Don't take gravity's strength in to account, */
				/* otherwise amount of banking is hard to control. */
				negate_v3_v3(grav, ground_nor);

				project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
				sub_v3_v3v3(dvec, bpa->data.acc, dvec);

				/* gather apparent gravity */
				madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
				normalize_v3(bpa->gravity);
			}
			else {
				/* gather negative surface normal */
				madd_v3_v3fl(bpa->gravity, ground_nor, -1.0f);
				normalize_v3(bpa->gravity);
			}
			break;
		}
	}

	/* save direction to state.ave unless the boid is falling */
	/* (boids can't effect their direction when falling) */
	if (bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1f*pa->size) {
		copy_v3_v3(pa->state.ave, pa->state.vel);
		pa->state.ave[2] *= bbd->part->boids->pitch;
		normalize_v3(pa->state.ave);
	}

	/* apply damping */
	if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing))
		mul_v3_fl(pa->state.vel, 1.0f - 0.2f*bbd->part->dampfac);

	/* calculate rotation matrix based on forward & down vectors */
	if (bpa->data.mode == eBoidMode_InAir) {
		copy_v3_v3(mat[0], pa->state.ave);

		project_v3_v3v3(dvec, bpa->gravity, pa->state.ave);
		sub_v3_v3v3(mat[2], bpa->gravity, dvec);
		normalize_v3(mat[2]);
	}
	else {
		project_v3_v3v3(dvec, pa->state.ave, bpa->gravity);
		sub_v3_v3v3(mat[0], pa->state.ave, dvec);
		normalize_v3(mat[0]);

		copy_v3_v3(mat[2], bpa->gravity);
	}
	negate_v3(mat[2]);
	cross_v3_v3v3(mat[1], mat[2], mat[0]);
	
	/* apply rotation */
	mat3_to_quat_is_ok(q, mat);
	copy_qt_qt(pa->state.rot, q);
}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	DerivedMesh *dm = derivedData, *result;
	ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
	ParticleSimulationData sim;
	ParticleSystem *psys = NULL;
	ParticleData *pa = NULL;
	MPoly *mpoly, *orig_mpoly;
	MLoop *mloop, *orig_mloop;
	MVert *mvert, *orig_mvert;
	int totvert, totpoly, totloop /* , totedge */;
	int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
	int k, p, p_skip;
	short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
	float max_co = 0.0, min_co = 0.0, temp_co[3];
	float *size = NULL;

	trackneg = ((ob->trackflag > 2) ? 1 : 0);

	if (pimd->ob == ob) {
		pimd->ob = NULL;
		return derivedData;
	}

	if (pimd->ob) {
		psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
		if (psys == NULL || psys->totpart == 0)
			return derivedData;
	}
	else {
		return derivedData;
	}

	if (pimd->flag & eParticleInstanceFlag_Parents)
		totpart += psys->totpart;
	if (pimd->flag & eParticleInstanceFlag_Children) {
		if (totpart == 0)
			first_particle = psys->totpart;
		totpart += psys->totchild;
	}

	if (totpart == 0)
		return derivedData;

	sim.scene = md->scene;
	sim.ob = pimd->ob;
	sim.psys = psys;
	sim.psmd = psys_get_modifier(pimd->ob, psys);

	if (pimd->flag & eParticleInstanceFlag_UseSize) {
		float *si;
		si = size = MEM_callocN(totpart * sizeof(float), "particle size array");

		if (pimd->flag & eParticleInstanceFlag_Parents) {
			for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
				*si = pa->size;
		}

		if (pimd->flag & eParticleInstanceFlag_Children) {
			ChildParticle *cpa = psys->child;

			for (p = 0; p < psys->totchild; p++, cpa++, si++) {
				*si = psys_get_child_size(psys, cpa, 0.0f, NULL);
			}
		}
	}

	totvert = dm->getNumVerts(dm);
	totpoly = dm->getNumPolys(dm);
	totloop = dm->getNumLoops(dm);
	/* totedge = dm->getNumEdges(dm); */ /* UNUSED */

	/* count particles */
	maxvert = 0;
	maxpoly = 0;
	maxloop = 0;

	for (p = 0; p < totpart; p++) {
		if (particle_skip(pimd, psys, p))
			continue;

		maxvert += totvert;
		maxpoly += totpoly;
		maxloop += totloop;
	}

	psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);

	if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
		float min[3], max[3];
		INIT_MINMAX(min, max);
		dm->getMinMax(dm, min, max);
		min_co = min[track];
		max_co = max[track];
	}

	result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);

	mvert = result->getVertArray(result);
	orig_mvert = dm->getVertArray(dm);

	mpoly = result->getPolyArray(result);
	orig_mpoly = dm->getPolyArray(dm);
	mloop = result->getLoopArray(result);
	orig_mloop = dm->getLoopArray(dm);

	for (p = 0, p_skip = 0; p < totpart; p++) {
		float prev_dir[3];
		float frame[4]; /* frame orientation quaternion */
		
		/* skip particle? */
		if (particle_skip(pimd, psys, p))
			continue;

		/* set vertices coordinates */
		for (k = 0; k < totvert; k++) {
			ParticleKey state;
			MVert *inMV;
			MVert *mv = mvert + p_skip * totvert + k;

			inMV = orig_mvert + k;
			DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
			*mv = *inMV;

			/*change orientation based on object trackflag*/
			copy_v3_v3(temp_co, mv->co);
			mv->co[axis] = temp_co[track];
			mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
			mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];

			/* get particle state */
			if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
			    (pimd->flag & eParticleInstanceFlag_Path))
			{
				float ran = 0.0f;
				if (pimd->random_position != 0.0f) {
					ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
				}

				if (pimd->flag & eParticleInstanceFlag_KeepShape) {
					state.time = pimd->position * (1.0f - ran);
				}
				else {
					state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);

					if (trackneg)
						state.time = 1.0f - state.time;

					mv->co[axis] = 0.0;
				}

				psys_get_particle_on_path(&sim, first_particle + p, &state, 1);

				normalize_v3(state.vel);

				/* Incrementally Rotating Frame (Bishop Frame) */
				if (k == 0) {
					float hairmat[4][4];
					float mat[3][3];
					
					if (first_particle + p < psys->totpart)
						pa = psys->particles + first_particle + p;
					else {
						ChildParticle *cpa = psys->child + (p - psys->totpart);
						pa = psys->particles + cpa->parent;
					}
					psys_mat_hair_to_global(sim.ob, sim.psmd->dm, sim.psys->part->from, pa, hairmat);
					copy_m3_m4(mat, hairmat);
					/* to quaternion */
					mat3_to_quat(frame, mat);
					
					/* note: direction is same as normal vector currently,
					 * but best to keep this separate so the frame can be
					 * rotated later if necessary
					 */
					copy_v3_v3(prev_dir, state.vel);
				}
				else {
					float rot[4];
					
					/* incrementally rotate along bend direction */
					rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
					mul_qt_qtqt(frame, rot, frame);
					
					copy_v3_v3(prev_dir, state.vel);
				}
				
				copy_qt_qt(state.rot, frame);
#if 0
				/* Absolute Frame (Frenet Frame) */
				if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
					unit_qt(state.rot);
				}
				else {
					float cross[3];
					float temp[3] = {0.0f, 0.0f, 0.0f};
					temp[axis] = 1.0f;
					
					cross_v3_v3v3(cross, temp, state.vel);
					
					/* state.vel[axis] is the only component surviving from a dot product with the axis */
					axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
				}
#endif
			}
			else {
				state.time = -1.0;
				psys_get_particle_state(&sim, first_particle + p, &state, 1);
			}

			mul_qt_v3(state.rot, mv->co);
			if (pimd->flag & eParticleInstanceFlag_UseSize)
				mul_v3_fl(mv->co, size[p]);
			add_v3_v3(mv->co, state.co);
		}

		/* create polys and loops */
		for (k = 0; k < totpoly; k++) {
			MPoly *inMP = orig_mpoly + k;
			MPoly *mp = mpoly + p_skip * totpoly + k;

			DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
			*mp = *inMP;
			mp->loopstart += p_skip * totloop;

			{
				MLoop *inML = orig_mloop + inMP->loopstart;
				MLoop *ml = mloop + mp->loopstart;
				int j = mp->totloop;

				DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
				for (; j; j--, ml++, inML++) {
					ml->v = inML->v + (p_skip * totvert);
				}
			}
		}

		p_skip++;
	}

	CDDM_calc_edges(result);

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

	if (size)
		MEM_freeN(size);

	result->dirty |= DM_DIRTY_NORMALS;

	return result;
}
Exemple #14
0
static void v3d_posearmature_buts(uiLayout *layout, Object *ob)
{
//	uiBlock *block= uiLayoutGetBlock(layout);
//	bArmature *arm;
	bPoseChannel *pchan;
//	TransformProperties *tfp= v3d->properties_storage;
	PointerRNA pchanptr;
	uiLayout *col;
//	uiLayout *row;
//	uiBut *but;

	pchan= get_active_posechannel(ob);

//	row= uiLayoutRow(layout, 0);
	
	if (!pchan)	{
		uiItemL(layout, "No Bone Active", ICON_NONE);
		return; 
	}

	RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &pchanptr);

	col= uiLayoutColumn(layout, 0);
	
	/* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.)
	 * but oldskool UI shows in eulers always. Do we want to be able to still display in Eulers?
	 * Maybe needs RNA/ui options to display rotations as different types... */
	v3d_transform_butsR(col, &pchanptr);

#if 0
	uiLayoutAbsoluteBlock(layout);

	if (pchan->rotmode == ROT_MODE_AXISANGLE) {
		float quat[4];
		/* convert to euler, passing through quats... */
		axis_angle_to_quat(quat, pchan->rotAxis, pchan->rotAngle);
		quat_to_eul( tfp->ob_eul,quat);
	}
	else if (pchan->rotmode == ROT_MODE_QUAT)
		quat_to_eul( tfp->ob_eul,pchan->quat);
	else
		copy_v3_v3(tfp->ob_eul, pchan->eul);
	tfp->ob_eul[0]*= 180.0/M_PI;
	tfp->ob_eul[1]*= 180.0/M_PI;
	tfp->ob_eul[2]*= 180.0/M_PI;
	
	uiDefBut(block, LABEL, 0, "Location:",			0, 240, 100, 20, 0, 0, 0, 0, 0, "");
	uiBlockBeginAlign(block);
	
	but= uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:",	0, 220, 120, 19, pchan->loc, -lim, lim, 100, 3, "");
	uiButSetUnitType(but, PROP_UNIT_LENGTH);
	but= uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:",	0, 200, 120, 19, pchan->loc+1, -lim, lim, 100, 3, "");
	uiButSetUnitType(but, PROP_UNIT_LENGTH);
	but= uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:",	0, 180, 120, 19, pchan->loc+2, -lim, lim, 100, 3, "");
	uiButSetUnitType(but, PROP_UNIT_LENGTH);
	uiBlockEndAlign(block);
	
	uiBlockBeginAlign(block);
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED,	125, 220, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Location value from being Transformed");
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED,	125, 200, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Location value from being Transformed");
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED,	125, 180, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Z Location value from being Transformed");
	uiBlockEndAlign(block);
	
	uiDefBut(block, LABEL, 0, "Rotation:",			0, 160, 100, 20, 0, 0, 0, 0, 0, "");
	uiBlockBeginAlign(block);
	uiDefButF(block, NUM, B_ARMATUREPANEL3, "X:",	0, 140, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, "");
	uiDefButF(block, NUM, B_ARMATUREPANEL3, "Y:",	0, 120, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, "");
	uiDefButF(block, NUM, B_ARMATUREPANEL3, "Z:",	0, 100, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, "");
	uiBlockEndAlign(block);
	
	uiBlockBeginAlign(block);
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED,	125, 140, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Rotation value from being Transformed");
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED,	125, 120, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Rotation value from being Transformed");
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED,	125, 100, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Z Rotation value from being Transformed");
	uiBlockEndAlign(block);
	
	uiDefBut(block, LABEL, 0, "Scale:",				0, 80, 100, 20, 0, 0, 0, 0, 0, "");
	uiBlockBeginAlign(block);
	uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:",	0, 60, 120, 19, pchan->size, -lim, lim, 10, 3, "");
	uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:",	0, 40, 120, 19, pchan->size+1, -lim, lim, 10, 3, "");
	uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:",	0, 20, 120, 19, pchan->size+2, -lim, lim, 10, 3, "");
	uiBlockEndAlign(block);
	
	uiBlockBeginAlign(block);
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED,	125, 60, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Scale value from being Transformed");
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED,	125, 40, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Scale value from being Transformed");
	uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED,	125, 20, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects z Scale value from being Transformed");
	uiBlockEndAlign(block);
#endif
}
Exemple #15
0
void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape,
             float amplitude, float flat, short type, short axis, float obmat[4][4], int smooth_start)
{
	float kink[3] = {1.f, 0.f, 0.f}, par_vec[3], q1[4] = {1.f, 0.f, 0.f, 0.f};
	float t, dt = 1.f, result[3];

	if (ELEM(type, PART_KINK_NO, PART_KINK_SPIRAL))
		return;

	CLAMP(time, 0.f, 1.f);

	if (shape != 0.0f && !ELEM(type, PART_KINK_BRAID)) {
		if (shape < 0.0f)
			time = (float)pow(time, 1.f + shape);
		else
			time = (float)pow(time, 1.f / (1.f - shape));
	}

	t = time * freq * (float)M_PI;

	if (smooth_start) {
		dt = fabsf(t);
		/* smooth the beginning of kink */
		CLAMP(dt, 0.f, (float)M_PI);
		dt = sinf(dt / 2.f);
	}

	if (!ELEM(type, PART_KINK_RADIAL)) {
		float temp[3];

		kink[axis] = 1.f;

		if (obmat)
			mul_mat3_m4_v3(obmat, kink);

		mul_qt_v3(par_rot, kink);

		/* make sure kink is normal to strand */
		project_v3_v3v3(temp, kink, par_vel);
		sub_v3_v3(kink, temp);
		normalize_v3(kink);
	}

	copy_v3_v3(result, state->co);
	sub_v3_v3v3(par_vec, par_co, state->co);

	switch (type) {
		case PART_KINK_CURL:
		{
			float curl_offset[3];

			/* rotate kink vector around strand tangent */
			mul_v3_v3fl(curl_offset, kink, amplitude);
			axis_angle_to_quat(q1, par_vel, t);
			mul_qt_v3(q1, curl_offset);

			interp_v3_v3v3(par_vec, state->co, par_co, flat);
			add_v3_v3v3(result, par_vec, curl_offset);
			break;
		}
		case PART_KINK_RADIAL:
		{
			if (flat > 0.f) {
				float proj[3];
				/* flatten along strand */
				project_v3_v3v3(proj, par_vec, par_vel);
				madd_v3_v3fl(result, proj, flat);
			}

			madd_v3_v3fl(result, par_vec, -amplitude * sinf(t));
			break;
		}
		case PART_KINK_WAVE:
		{
			madd_v3_v3fl(result, kink, amplitude * sinf(t));

			if (flat > 0.f) {
				float proj[3];
				/* flatten along wave */
				project_v3_v3v3(proj, par_vec, kink);
				madd_v3_v3fl(result, proj, flat);

				/* flatten along strand */
				project_v3_v3v3(proj, par_vec, par_vel);
				madd_v3_v3fl(result, proj, flat);
			}
			break;
		}
		case PART_KINK_BRAID:
		{
			float y_vec[3] = {0.f, 1.f, 0.f};
			float z_vec[3] = {0.f, 0.f, 1.f};
			float vec_one[3], state_co[3];
			float inp_y, inp_z, length;

			if (par_rot) {
				mul_qt_v3(par_rot, y_vec);
				mul_qt_v3(par_rot, z_vec);
			}

			negate_v3(par_vec);
			normalize_v3_v3(vec_one, par_vec);

			inp_y = dot_v3v3(y_vec, vec_one);
			inp_z = dot_v3v3(z_vec, vec_one);

			if (inp_y > 0.5f) {
				copy_v3_v3(state_co, y_vec);

				mul_v3_fl(y_vec, amplitude * cosf(t));
				mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t));
			}
			else if (inp_z > 0.0f) {
				mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f));
				madd_v3_v3fl(state_co, y_vec, -0.5f);

				mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f));
				mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f));
			}
			else {
				mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f));
				madd_v3_v3fl(state_co, y_vec, -0.5f);

				mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f));
				mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f));
			}

			mul_v3_fl(state_co, amplitude);
			add_v3_v3(state_co, par_co);
			sub_v3_v3v3(par_vec, state->co, state_co);

			length = normalize_v3(par_vec);
			mul_v3_fl(par_vec, MIN2(length, amplitude / 2.f));

			add_v3_v3v3(state_co, par_co, y_vec);
			add_v3_v3(state_co, z_vec);
			add_v3_v3(state_co, par_vec);

			shape = 2.f * (float)M_PI * (1.f + shape);

			if (t < shape) {
				shape = t / shape;
				shape = (float)sqrt((double)shape);
				interp_v3_v3v3(result, result, state_co, shape);
			}
			else {
				copy_v3_v3(result, state_co);
			}
			break;
		}
	}

	/* blend the start of the kink */
	if (dt < 1.f)
		interp_v3_v3v3(state->co, state->co, result, dt);
	else
		copy_v3_v3(state->co, result);
}