Beispiel #1
0
/* Sync rigid body and object transformations */
void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
{
	RigidBodyOb *rbo = ob->rigidbody_object;

	/* keep original transform for kinematic and passive objects */
	if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE)
		return;

	/* use rigid body transform after cache start frame if objects is not being transformed */
	if (BKE_rigidbody_check_sim_running(rbw, ctime) && !(ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
		float mat[4][4], size_mat[4][4], size[3];

		normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point
		quat_to_mat4(mat, rbo->orn);
		copy_v3_v3(mat[3], rbo->pos);

		mat4_to_size(size, ob->obmat);
		size_to_mat4(size_mat, size);
		mul_m4_m4m4(mat, mat, size_mat);

		copy_m4_m4(ob->obmat, mat);
	}
	/* otherwise set rigid body transform to current obmat */
	else {
		mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
	}
}
void UnitConverter::calculate_scale(Scene &sce)
{
	PointerRNA scene_ptr, unit_settings;
	PropertyRNA *system_ptr, *scale_ptr;
	RNA_id_pointer_create(&sce.id, &scene_ptr);

	unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings");
	system_ptr    = RNA_struct_find_property(&unit_settings, "system");
	scale_ptr     = RNA_struct_find_property(&unit_settings, "scale_length");

	int   type    = RNA_property_enum_get(&unit_settings, system_ptr);

	float bl_scale;

	switch (type) {
		case USER_UNIT_NONE:
			bl_scale = 1.0; // map 1 Blender unit to 1 Meter
			break;

		case USER_UNIT_METRIC:
			bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
			break;

		default :
			bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
			// it looks like the conversion to Imperial is done implicitly.
			// So nothing to do here.
			break;
	}

	float rescale[3];
	rescale[0] = rescale[1] = rescale[2] = getLinearMeter() / bl_scale;

	size_to_mat4(scale_mat4, rescale);
}
Beispiel #3
0
/**
 * Calculate a rescale factor such that the imported scene's scale
 * is preserved. I.e. 1 meter in the import will also be
 * 1 meter in the current scene.
 * XXX : I am not sure if it is correct to map 1 Blender Unit
 * to 1 Meter for unit type NONE. But it looks reasonable to me.
 */
void bc_match_scale(std::vector<Object *> *objects_done, 
                    Scene &sce,
                    UnitConverter &bc_unit)
{
	Object *ob = NULL;

	PointerRNA scene_ptr, unit_settings;
	PropertyRNA *system_ptr, *scale_ptr;
	RNA_id_pointer_create(&sce.id, &scene_ptr);

	unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings");
	system_ptr = RNA_struct_find_property(&unit_settings, "system");
	scale_ptr = RNA_struct_find_property(&unit_settings, "scale_length");

	int   type  = RNA_property_enum_get(&unit_settings, system_ptr);

	float bl_scale;
	
	switch (type) {
		case USER_UNIT_NONE:
			bl_scale = 1.0; // map 1 Blender unit to 1 Meter
			break;

		case USER_UNIT_METRIC:
			bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
			break;

		default :
			bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
			// it looks like the conversion to Imperial is done implicitly.
			// So nothing to do here.
			break;
	}
	
	float scale_conv = bc_unit.getLinearMeter() / bl_scale;

	float rescale[3];
	rescale[0] = rescale[1] = rescale[2] = scale_conv;

	float size_mat4[4][4];

	float axis_mat4[4][4];
	unit_m4(axis_mat4);

	size_to_mat4(size_mat4, rescale);

	for (std::vector<Object *>::iterator it = objects_done->begin();
			it != objects_done->end();
			++it) 
	{
		ob = *it;
		mult_m4_m4m4(ob->obmat, size_mat4, ob->obmat);
		mult_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
		BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
	}

}
/* Get 4x4 transformation matrix which corresponds to
 * stabilization data and used for easy coordinate
 * transformation.
 *
 * NOTE: The reason it is 4x4 matrix is because it's
 *       used for OpenGL drawing directly.
 */
void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect,
                                             float translation[2], float scale, float angle,
                                             float mat[4][4])
{
	float translation_mat[4][4], rotation_mat[4][4], scale_mat[4][4],
	      center_mat[4][4], inv_center_mat[4][4],
	      aspect_mat[4][4], inv_aspect_mat[4][4];
	float scale_vector[3] = {scale, scale, scale};

	unit_m4(translation_mat);
	unit_m4(rotation_mat);
	unit_m4(scale_mat);
	unit_m4(center_mat);
	unit_m4(aspect_mat);

	/* aspect ratio correction matrix */
	aspect_mat[0][0] = 1.0f / aspect;
	invert_m4_m4(inv_aspect_mat, aspect_mat);

	/* image center as rotation center
	 *
	 * Rotation matrix is constructing in a way rotation happens around image center,
	 * and it's matter of calculating translation in a way, that applying translation
	 * after rotation would make it so rotation happens around median point of tracks
	 * used for translation stabilization.
	 */
	center_mat[3][0] = (float)width / 2.0f;
	center_mat[3][1] = (float)height / 2.0f;
	invert_m4_m4(inv_center_mat, center_mat);

	size_to_mat4(scale_mat, scale_vector);       /* scale matrix */
	add_v2_v2(translation_mat[3], translation);  /* translation matrix */
	rotate_m4(rotation_mat, 'Z', angle);         /* rotation matrix */

	/* compose transformation matrix */
	mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat,
	             scale_mat, inv_center_mat, NULL);
}
Beispiel #5
0
/**
 * Updates cameras from the ``rv3d`` values, optionally auto-keyframing.
 */
void ED_view3d_cameracontrol_update(
    View3DCameraControl *vctrl,
    /* args for keyframing */
    const bool use_autokey,
    struct bContext *C, const bool do_rotate, const bool do_translate)
{
    /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */

    Scene *scene       = vctrl->ctx_scene;
    View3D *v3d        = vctrl->ctx_v3d;
    RegionView3D *rv3d = vctrl->ctx_rv3d;

    ID *id_key;

    /* transform the parent or the camera? */
    if (vctrl->root_parent) {
        Object *ob_update;

        float view_mat[4][4];
        float prev_view_imat[4][4];
        float diff_mat[4][4];
        float parent_mat[4][4];

        invert_m4_m4(prev_view_imat, vctrl->view_mat_prev);
        ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
        mul_m4_m4m4(diff_mat, view_mat, prev_view_imat);
        mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat);

        BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false);

        ob_update = v3d->camera->parent;
        while (ob_update) {
            DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
            ob_update = ob_update->parent;
        }

        copy_m4_m4(vctrl->view_mat_prev, view_mat);

        id_key = &vctrl->root_parent->id;
    }
    else {
        float view_mat[4][4];
        float size_mat[4][4];
        float size_back[3];

        /* even though we handle the size matrix, this still changes over time */
        copy_v3_v3(size_back, v3d->camera->size);

        ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
        size_to_mat4(size_mat, v3d->camera->size);
        mul_m4_m4m4(view_mat, view_mat, size_mat);

        BKE_object_apply_mat4(v3d->camera, view_mat, true, true);

        copy_v3_v3(v3d->camera->size, size_back);

        id_key = &v3d->camera->id;
    }

    /* record the motion */
    if (use_autokey && autokeyframe_cfra_can_key(scene, id_key)) {
        ListBase dsources = {NULL, NULL};

        /* add data-source override for the camera object */
        ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);

        /* insert keyframes
         * 1) on the first frame
         * 2) on each subsequent frame
         *    TODO: need to check in future that frame changed before doing this
         */
        if (do_rotate) {
            struct KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
            ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
        }
        if (do_translate) {
            struct KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
            ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
        }

        /* free temp data */
        BLI_freelistN(&dsources);
    }
}
Beispiel #6
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;
	}
}
Beispiel #7
0
void TransformReader::dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
{
	COLLADABU::Math::Vector3& s = ((COLLADAFW::Scale*)tm)->getScale();
	float size[3] = {(float)s[0], (float)s[1], (float)s[2]};
	size_to_mat4(m, size);
}
Beispiel #8
0
static void flyMoveCamera(bContext *C, RegionView3D *rv3d, FlyInfo *fly,
                            const bool do_rotate, const bool do_translate)
{
	/* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */

	View3D *v3d = fly->v3d;
	Scene *scene = fly->scene;
	ID *id_key;

	/* transform the parent or the camera? */
	if (fly->root_parent) {
		Object *ob_update;

		float view_mat[4][4];
		float prev_view_mat[4][4];
		float prev_view_imat[4][4];
		float diff_mat[4][4];
		float parent_mat[4][4];
		float size_mat[4][4];

		ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist);
		invert_m4_m4(prev_view_imat, prev_view_mat);
		ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
		mult_m4_m4m4(diff_mat, view_mat, prev_view_imat);
		mult_m4_m4m4(parent_mat, diff_mat, fly->root_parent->obmat);

		size_to_mat4(size_mat, fly->root_parent->size);
		mult_m4_m4m4(parent_mat, parent_mat, size_mat);

		BKE_object_apply_mat4(fly->root_parent, parent_mat, true, false);

		// BKE_object_where_is_calc(scene, fly->root_parent);

		ob_update = v3d->camera->parent;
		while (ob_update) {
			DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
			ob_update = ob_update->parent;
		}

		id_key = &fly->root_parent->id;
	}
	else {
		float view_mat[4][4];
		float size_mat[4][4];

		ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
		size_to_mat4(size_mat, v3d->camera->size);
		mult_m4_m4m4(view_mat, view_mat, size_mat);

		BKE_object_apply_mat4(v3d->camera, view_mat, true, false);

		id_key = &v3d->camera->id;
	}

	/* record the motion */
	if (autokeyframe_cfra_can_key(scene, id_key)) {
		ListBase dsources = {NULL, NULL};

		/* add datasource override for the camera object */
		ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);

		/* insert keyframes 
		 *	1) on the first frame
		 *	2) on each subsequent frame
		 *		TODO: need to check in future that frame changed before doing this 
		 */
		if (do_rotate) {
			KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
			ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
		}
		if (do_translate) {
			KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
			ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
		}

		/* free temp data */
		BLI_freelistN(&dsources);
	}
}
Beispiel #9
0
CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type)
{
	CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1);
	ImBuf *ibuf, *obuf;
	float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
	float svec[3]= {scale, scale, scale}, loc[2]= {x, y};

	unit_m4(rmat);
	unit_m4(lmat);
	unit_m4(smat);
	unit_m4(cmat);

	/* image center as rotation center */
	cmat[3][0]= (float)cbuf->x/2.0f;
	cmat[3][1]= (float)cbuf->y/2.0f;
	invert_m4_m4(icmat, cmat);

	size_to_mat4(smat, svec);		/* scale matrix */
	add_v2_v2(lmat[3], loc);		/* tranlation matrix */
	rotate_m4(rmat, 'Z', angle);	/* rotation matrix */

	/* compose transformation matrix */
	mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);

	invert_m4(mat);

	ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
	obuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0);

	if (ibuf && obuf) {
		int i, j;

		ibuf->rect_float= cbuf->rect;
		obuf->rect_float= stackbuf->rect;

		for (j=0; j<cbuf->y; j++) {
			for (i=0; i<cbuf->x;i++) {
				float vec[3]= {i, j, 0};

				mul_v3_m4v3(vec, mat, vec);

				switch(filter_type) {
					case 0:
						neareast_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
						break;
					case 1:
						bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
						break;
					case 2:
						bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
						break;
				}
			}
		}

		IMB_freeImBuf(ibuf);
		IMB_freeImBuf(obuf);
	}

	/* pass on output and free */
	return stackbuf;
}
Beispiel #10
0
void init_tex_mapping(TexMapping *texmap)
{
	float smat[4][4], rmat[4][4], tmat[4][4], proj[4][4], size[3];

	if (texmap->projx == PROJ_X && texmap->projy == PROJ_Y && texmap->projz == PROJ_Z &&
	    is_zero_v3(texmap->loc) && is_zero_v3(texmap->rot) && is_one_v3(texmap->size))
	{
		unit_m4(texmap->mat);

		texmap->flag |= TEXMAP_UNIT_MATRIX;
	}
	else {
		/* axis projection */
		zero_m4(proj);
		proj[3][3] = 1.0f;

		if (texmap->projx != PROJ_N)
			proj[texmap->projx - 1][0] = 1.0f;
		if (texmap->projy != PROJ_N)
			proj[texmap->projy - 1][1] = 1.0f;
		if (texmap->projz != PROJ_N)
			proj[texmap->projz - 1][2] = 1.0f;

		/* scale */
		copy_v3_v3(size, texmap->size);

		if (ELEM(texmap->type, TEXMAP_TYPE_TEXTURE, TEXMAP_TYPE_NORMAL)) {
			/* keep matrix invertible */
			if (fabsf(size[0]) < 1e-5f)
				size[0] = signf(size[0]) * 1e-5f;
			if (fabsf(size[1]) < 1e-5f)
				size[1] = signf(size[1]) * 1e-5f;
			if (fabsf(size[2]) < 1e-5f)
				size[2] = signf(size[2]) * 1e-5f;
		}
		
		size_to_mat4(smat, texmap->size);

		/* rotation */
		eul_to_mat4(rmat, texmap->rot);

		/* translation */
		unit_m4(tmat);
		copy_v3_v3(tmat[3], texmap->loc);

		if (texmap->type == TEXMAP_TYPE_TEXTURE) {
			/* to transform a texture, the inverse transform needs
			 * to be applied to the texture coordinate */
			mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
			invert_m4(texmap->mat);
		}
		else if (texmap->type == TEXMAP_TYPE_POINT) {
			/* forward transform */
			mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
		}
		else if (texmap->type == TEXMAP_TYPE_VECTOR) {
			/* no translation for vectors */
			mul_m4_m4m4(texmap->mat, rmat, smat);
		}
		else if (texmap->type == TEXMAP_TYPE_NORMAL) {
			/* no translation for normals, and inverse transpose */
			mul_m4_m4m4(texmap->mat, rmat, smat);
			invert_m4(texmap->mat);
			transpose_m4(texmap->mat);
		}

		/* projection last */
		mul_m4_m4m4(texmap->mat, texmap->mat, proj);

		texmap->flag &= ~TEXMAP_UNIT_MATRIX;
	}
}
static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4])
{
	Camera *data = (Camera *)camera->data;
	float interocular_distance, convergence_distance;
	short convergence_mode, pivot;
	float sizemat[4][4];

	float fac = 1.0f;
	float fac_signed;

	interocular_distance = data->stereo.interocular_distance;
	convergence_distance = data->stereo.convergence_distance;
	convergence_mode = data->stereo.convergence_mode;
	pivot = data->stereo.pivot;

	if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
	    ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
	{
		camera_model_matrix(camera, r_modelmat);
		return;
	}
	else {
		float size[3];
		mat4_to_size(size, camera->obmat);
		size_to_mat4(sizemat, size);
	}

	if (pivot == CAM_S3D_PIVOT_CENTER)
		fac = 0.5f;

	fac_signed = is_left ? fac : -fac;

	/* rotation */
	if (convergence_mode == CAM_S3D_TOE) {
		float angle;
		float angle_sin, angle_cos;
		float toeinmat[4][4];
		float rotmat[4][4];

		unit_m4(rotmat);

		if (pivot == CAM_S3D_PIVOT_CENTER) {
			fac = -fac;
			fac_signed = -fac_signed;
		}

		angle = atanf((interocular_distance * 0.5f) / convergence_distance) / fac;

		angle_cos = cosf(angle * fac_signed);
		angle_sin = sinf(angle * fac_signed);

		rotmat[0][0] =  angle_cos;
		rotmat[2][0] = -angle_sin;
		rotmat[0][2] =  angle_sin;
		rotmat[2][2] =  angle_cos;

		if (pivot == CAM_S3D_PIVOT_CENTER) {
			/* set the rotation */
			copy_m4_m4(toeinmat, rotmat);
			/* set the translation */
			toeinmat[3][0] = interocular_distance * fac_signed;

			/* transform */
			normalize_m4_m4(r_modelmat, camera->obmat);
			mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);

			/* scale back to the original size */
			mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
		}
		else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */
			/* rotate perpendicular to the interocular line */
			normalize_m4_m4(r_modelmat, camera->obmat);
			mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);

			/* translate along the interocular line */
			unit_m4(toeinmat);
			toeinmat[3][0] = -interocular_distance * fac_signed;
			mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);

			/* rotate to toe-in angle */
			mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);

			/* scale back to the original size */
			mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
		}
	}
	else {
		normalize_m4_m4(r_modelmat, camera->obmat);

		/* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */
		translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f);

		/* scale back to the original size */
		mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
	}
}