示例#1
0
static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
	bool do_draw = false;
	int exit_code = OPERATOR_RUNNING_MODAL;
	RulerInfo *ruler_info = op->customdata;
	ScrArea *sa = ruler_info->sa;
	ARegion *ar = ruler_info->ar;
	RegionView3D *rv3d = ar->regiondata;

	/* its possible to change  spaces while running the operator [#34894] */
	if (UNLIKELY(ar != CTX_wm_region(C))) {
		exit_code = OPERATOR_FINISHED;
		goto exit;
	}

	switch (event->type) {
		case LEFTMOUSE:
			if (event->val == KM_RELEASE) {
				if (ruler_info->state == RULER_STATE_DRAG) {
					/* rubber-band angle removal */
					RulerItem *ruler_item = ruler_item_active_get(ruler_info);
					if (ruler_item && (ruler_item->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
						if (!BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
							ruler_item->flag &= ~RULERITEM_USE_ANGLE;
							do_draw = true;
						}
					}
					if (ruler_info->snap_flag & RULER_SNAP_OK) {
						ruler_info->snap_flag &= ~RULER_SNAP_OK;
						do_draw = true;
					}
					ruler_info->state = RULER_STATE_NORMAL;
				}
			}
			else {
				if (ruler_info->state == RULER_STATE_NORMAL) {

					if (event->ctrl ||
					    /* weak - but user friendly */
					    (ruler_info->items.first == NULL))
					{
						View3D *v3d = CTX_wm_view3d(C);
						const bool use_depth = (v3d->drawtype >= OB_SOLID);

						/* Create new line */
						RulerItem *ruler_item_prev = ruler_item_active_get(ruler_info);
						RulerItem *ruler_item;
						/* check if we want to drag an existing point or add a new one */
						ruler_info->state = RULER_STATE_DRAG;

						ruler_item = ruler_item_add(ruler_info);
						ruler_item_active_set(ruler_info, ruler_item);

						if (use_depth) {
							/* snap the first point added, not essential but handy */
							ruler_item->co_index = 0;
							view3d_ruler_item_mousemove(C, ruler_info, event->mval, false, true);
							copy_v3_v3(ruler_info->drag_start_co, ruler_item->co[ruler_item->co_index]);
						}
						else {
							/* initial depth either previous ruler, view offset */
							if (ruler_item_prev) {
								copy_v3_v3(ruler_info->drag_start_co, ruler_item_prev->co[ruler_item_prev->co_index]);
							}
							else {
								negate_v3_v3(ruler_info->drag_start_co, rv3d->ofs);
							}

							copy_v3_v3(ruler_item->co[0], ruler_info->drag_start_co);
							view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
						}

						copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
						ruler_item->co_index = 2;

						do_draw = true;
					}
					else {
						float mval_fl[2] = {UNPACK2(event->mval)};
						RulerItem *ruler_item_pick;
						int co_index;

						/* select and drag */
						if (view3d_ruler_pick(ruler_info, mval_fl, &ruler_item_pick, &co_index)) {
							if (co_index == -1) {
								if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
									/* Add Center Point */
									ruler_item_active_set(ruler_info, ruler_item_pick);
									ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
									ruler_item_pick->co_index = 1;
									ruler_info->state = RULER_STATE_DRAG;

									/* find the factor */
									{
										float co_ss[2][2];
										float fac;

										ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
										ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);

										fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
										CLAMP(fac, 0.0f, 1.0f);

										interp_v3_v3v3(ruler_item_pick->co[1],
										               ruler_item_pick->co[0],
										               ruler_item_pick->co[2], fac);
									}

									/* update the new location */
									view3d_ruler_item_mousemove(C, ruler_info, event->mval,
									                            event->shift != 0, event->ctrl != 0);
									do_draw = true;
								}
							}
							else {
								ruler_item_active_set(ruler_info, ruler_item_pick);
								ruler_item_pick->co_index = co_index;
								ruler_info->state = RULER_STATE_DRAG;

								/* store the initial depth */
								copy_v3_v3(ruler_info->drag_start_co, ruler_item_pick->co[ruler_item_pick->co_index]);

								do_draw = true;
							}
						}
						else {
							exit_code = OPERATOR_PASS_THROUGH;
						}

					}
				}
			}
			break;
		case CKEY:
		{
			if (event->ctrl) {
				RulerItem *ruler_item = ruler_item_active_get(ruler_info);
				if (ruler_item) {
					const int prec = 8;
					char numstr[256];
					Scene *scene = CTX_data_scene(C);
					UnitSettings *unit = &scene->unit;

					ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
					WM_clipboard_text_set((void *) numstr, false);
				}
			}
			break;
		}
		case RIGHTCTRLKEY:
		case LEFTCTRLKEY:
		{
			WM_event_add_mousemove(C);
			break;
		}
		case MOUSEMOVE:
		{
			if (ruler_info->state == RULER_STATE_DRAG) {
				if (view3d_ruler_item_mousemove(C, ruler_info, event->mval,
				                                event->shift != 0, event->ctrl != 0))
				{
					do_draw = true;
				}
			}
			break;
		}
		case ESCKEY:
		{
			do_draw = true;
			exit_code = OPERATOR_CANCELLED;
			break;
		}
		case RETKEY:
		{
			view3d_ruler_to_gpencil(C, ruler_info);
			do_draw = true;
			exit_code = OPERATOR_FINISHED;
			break;
		}
		case DELKEY:
		{
			if (event->val == KM_PRESS) {
				if (ruler_info->state == RULER_STATE_NORMAL) {
					RulerItem *ruler_item = ruler_item_active_get(ruler_info);
					if (ruler_item) {
						RulerItem *ruler_item_other = ruler_item->prev ? ruler_item->prev : ruler_item->next;
						ruler_item_remove(ruler_info, ruler_item);
						ruler_item_active_set(ruler_info, ruler_item_other);
						do_draw = true;
					}
				}
			}
			break;
		}
		default:
			exit_code = OPERATOR_PASS_THROUGH;
			break;

	}

	if (do_draw) {
		view3d_ruler_header_update(sa);

		/* all 3d views draw rulers */
		WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
	}

exit:
	if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
		WM_cursor_modal_restore(ruler_info->win);

		view3d_ruler_end(C, ruler_info);
		view3d_ruler_free(ruler_info);
		op->customdata = NULL;

		ED_area_headerprint(sa, NULL);
	}

	return exit_code;
}
示例#2
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;
	}
}
示例#3
0
/* set the current pose as the restpose */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
	bArmature *arm = BKE_armature_from_object(ob);
	bPose *pose;
	bPoseChannel *pchan;
	EditBone *curbone;
	
	/* don't check if editmode (should be done by caller) */
	if (ob->type != OB_ARMATURE)
		return OPERATOR_CANCELLED;
	if (BKE_object_obdata_is_libdata(ob)) {
		BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); /* error_libdata(); */
		return OPERATOR_CANCELLED;
	}

	/* helpful warnings... */
	/* TODO: add warnings to be careful about actions, applying deforms first, etc. */
	if (ob->adt && ob->adt->action)
		BKE_report(op->reports, RPT_WARNING,
		           "Actions on this armature will be destroyed by this new rest pose as the "
		           "transforms stored are relative to the old rest pose");

	/* Get editbones of active armature to alter */
	ED_armature_to_edit(arm);
	
	/* get pose of active object and move it out of posemode */
	pose = ob->pose;
	
	for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
		curbone = ED_armature_bone_find_name(arm->edbo, pchan->name);
		
		/* simply copy the head/tail values from pchan over to curbone */
		copy_v3_v3(curbone->head, pchan->pose_head);
		copy_v3_v3(curbone->tail, pchan->pose_tail);
		
		/* fix roll:
		 *	1. find auto-calculated roll value for this bone now
		 *	2. remove this from the 'visual' y-rotation
		 */
		{
			float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
			float delta[3], eul[3];
			
			/* obtain new auto y-rotation */
			sub_v3_v3v3(delta, curbone->tail, curbone->head);
			vec_roll_to_mat3(delta, 0.0f, premat);
			invert_m3_m3(imat, premat);
			
			/* get pchan 'visual' matrix */
			copy_m3_m4(pmat, pchan->pose_mat);
			
			/* remove auto from visual and get euler rotation */
			mul_m3_m3m3(tmat, imat, pmat);
			mat3_to_eul(eul, tmat);
			
			/* just use this euler-y as new roll value */
			curbone->roll = eul[1];
		}
		
		/* clear transform values for pchan */
		zero_v3(pchan->loc);
		zero_v3(pchan->eul);
		unit_qt(pchan->quat);
		unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
		pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
		
		/* set anim lock */
		curbone->flag |= BONE_UNKEYED;
	}
	
	/* convert editbones back to bones, and then free the edit-data */
	ED_armature_from_edit(arm);
	ED_armature_edit_free(arm);
	
	/* flush positions of posebones */
	BKE_pose_where_is(scene, ob);
	
	/* fix parenting of objects which are bone-parented */
	applyarmature_fix_boneparents(scene, ob);
	
	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
	
	return OPERATOR_FINISHED;
}
int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *py_value)
{
	int ret = 0;
	void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer);

	if (UNLIKELY(value == NULL)) {
		return -1;
	}

	switch (py_layer->type) {
		case CD_MDEFORMVERT:
		{
			ret = BPy_BMDeformVert_AssignPyObject(value, py_value);
			break;
		}
		case CD_PROP_FLT:
		{
			float tmp_val = PyFloat_AsDouble(py_value);
			if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
				PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
				ret = -1;
			}
			else {
				*(float *)value = tmp_val;
			}
			break;
		}
		case CD_PROP_INT:
		{
			int tmp_val = PyLong_AsLong(py_value);
			if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
				PyErr_Format(PyExc_TypeError, "expected an int, not a %.200s", Py_TYPE(py_value)->tp_name);
				ret = -1;
			}
			else {
				*(int *)value = tmp_val;
			}
			break;
		}
		case CD_PROP_STR:
		{
			MStringProperty *mstring = value;
			char *tmp_val;
			Py_ssize_t tmp_val_len;
			if (UNLIKELY(PyBytes_AsStringAndSize(py_value, &tmp_val, &tmp_val_len) == -1)) {
				PyErr_Format(PyExc_TypeError, "expected bytes, not a %.200s", Py_TYPE(py_value)->tp_name);
				ret = -1;
			}
			else {
				if (tmp_val_len > sizeof(mstring->s))
					tmp_val_len = sizeof(mstring->s);
				memcpy(mstring->s, tmp_val, tmp_val_len);
				mstring->s_len = tmp_val_len;
			}
			break;
		}
		case CD_MTEXPOLY:
		{
			ret = BPy_BMTexPoly_AssignPyObject(value, py_value);
			break;
		}
		case CD_MLOOPUV:
		{
			ret = BPy_BMLoopUV_AssignPyObject(value, py_value);
			break;
		}
		case CD_MLOOPCOL:
		{
			ret = BPy_BMLoopColor_AssignPyObject(value, py_value);
			break;
		}
		case CD_SHAPEKEY:
		{
			float tmp_val[3];
			if (UNLIKELY(mathutils_array_parse(tmp_val, 3, 3, py_value, "BMVert[shape] = value") == -1)) {
				ret = -1;
			}
			else {
				copy_v3_v3((float *)value, tmp_val);
			}
			break;
		}
		case CD_BWEIGHT:
		{
			float tmp_val = PyFloat_AsDouble(py_value);
			if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
				PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
				ret = -1;
			}
			else {
				*(float *)value = CLAMPIS(tmp_val, 0.0f, 1.0f);
			}
			break;
		}
		case CD_CREASE:
		{
			float tmp_val = PyFloat_AsDouble(py_value);
			if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
				PyErr_Format(PyExc_TypeError, "expected a float, not a %.200s", Py_TYPE(py_value)->tp_name);
				ret = -1;
			}
			else {
				*(float *)value = CLAMPIS(tmp_val, 0.0f, 1.0f);
			}
			break;
		}
		default:
		{
			PyErr_SetString(PyExc_AttributeError, "readonly / unsupported type");
			ret = -1;
			break;
		}
	}

	return ret;
}
示例#5
0
static void walkEvent(bContext *C, wmOperator *UNUSED(op), WalkInfo *walk, const wmEvent *event)
{
	if (event->type == TIMER && event->customdata == walk->timer) {
		walk->redraw = true;
	}
	else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {

		walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
		walk->moffset[1] += event->mval[1] - walk->prev_mval[1];

		copy_v2_v2_int(walk->prev_mval, event->mval);

		if ((walk->center_mval[0] != event->mval[0]) ||
		    (walk->center_mval[1] != event->mval[1]))
		{
			walk->redraw = true;

			if (wm_event_is_last_mousemove(event)) {
				wmWindow *win = CTX_wm_window(C);

#ifdef __APPLE__
				if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) ||
				    (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2))
#endif
				{
					WM_cursor_warp(win,
					               walk->ar->winrct.xmin + walk->center_mval[0],
					               walk->ar->winrct.ymin + walk->center_mval[1]);
					copy_v2_v2_int(walk->prev_mval, walk->center_mval);
				}
			}
		}
	}
	else if (event->type == NDOF_MOTION) {
		/* do these automagically get delivered? yes. */
		// puts("ndof motion detected in walk mode!");
		// static const char *tag_name = "3D mouse position";

		const wmNDOFMotionData *incoming_ndof = event->customdata;
		switch (incoming_ndof->progress) {
			case P_STARTING:
				/* start keeping track of 3D mouse position */
#ifdef NDOF_WALK_DEBUG
				puts("start keeping track of 3D mouse position");
#endif
				/* fall-through */
			case P_IN_PROGRESS:
				/* update 3D mouse position */
#ifdef NDOF_WALK_DEBUG
				putchar('.'); fflush(stdout);
#endif
				if (walk->ndof == NULL) {
					// walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
					walk->ndof = MEM_dupallocN(incoming_ndof);
					// walk->ndof = malloc(sizeof(wmNDOFMotionData));
				}
				else {
					memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
				}
				break;
			case P_FINISHING:
				/* stop keeping track of 3D mouse position */
#ifdef NDOF_WALK_DEBUG
				puts("stop keeping track of 3D mouse position");
#endif
				if (walk->ndof) {
					MEM_freeN(walk->ndof);
					// free(walk->ndof);
					walk->ndof = NULL;
				}

				/* update the time else the view will jump when 2D mouse/timer resume */
				walk->time_lastdraw = PIL_check_seconds_timer();

				break;
			default:
				break; /* should always be one of the above 3 */
		}
	}
	/* handle modal keymap first */
	else if (event->type == EVT_MODAL_MAP) {
		switch (event->val) {
			case WALK_MODAL_CANCEL:
				walk->state = WALK_CANCEL;
				break;
			case WALK_MODAL_CONFIRM:
				walk->state = WALK_CONFIRM;
				break;

			case WALK_MODAL_ACCELERATE:
				base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
				break;
			case WALK_MODAL_DECELERATE:
				base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
				break;

			/* implement WASD keys */
			case WALK_MODAL_DIR_FORWARD:
				walk->active_directions |= WALK_BIT_FORWARD;
				break;
			case WALK_MODAL_DIR_BACKWARD:
				walk->active_directions |= WALK_BIT_BACKWARD;
				break;
			case WALK_MODAL_DIR_LEFT:
				walk->active_directions |= WALK_BIT_LEFT;
				break;
			case WALK_MODAL_DIR_RIGHT:
				walk->active_directions |= WALK_BIT_RIGHT;
				break;
			case WALK_MODAL_DIR_UP:
				walk->active_directions |= WALK_BIT_UP;
				break;
			case WALK_MODAL_DIR_DOWN:
				walk->active_directions |= WALK_BIT_DOWN;
				break;

			case WALK_MODAL_DIR_FORWARD_STOP:
				walk->active_directions &= ~WALK_BIT_FORWARD;
				break;
			case WALK_MODAL_DIR_BACKWARD_STOP:
				walk->active_directions &= ~WALK_BIT_BACKWARD;
				break;
			case WALK_MODAL_DIR_LEFT_STOP:
				walk->active_directions &= ~WALK_BIT_LEFT;
				break;
			case WALK_MODAL_DIR_RIGHT_STOP:
				walk->active_directions &= ~WALK_BIT_RIGHT;
				break;
			case WALK_MODAL_DIR_UP_STOP:
				walk->active_directions &= ~WALK_BIT_UP;
				break;
			case WALK_MODAL_DIR_DOWN_STOP:
				walk->active_directions &= ~WALK_BIT_DOWN;
				break;

			case WALK_MODAL_FAST_ENABLE:
				walk->is_fast = true;
				break;
			case WALK_MODAL_FAST_DISABLE:
				walk->is_fast = false;
				break;
			case WALK_MODAL_SLOW_ENABLE:
				walk->is_slow = true;
				break;
			case WALK_MODAL_SLOW_DISABLE:
				walk->is_slow = false;
				break;

#define JUMP_SPEED_MIN 1.0f
#define JUMP_TIME_MAX 0.2f /* s */
#define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height)

			case WALK_MODAL_JUMP_STOP:
				if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) {
					float t;

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

					/* reduce the veolocity, if JUMP wasn't hold for long enough */
					t = min_ff(t, JUMP_TIME_MAX);
					walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX;

					/* when jumping, duration is how long it takes before we start going down */
					walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);

					/* no more increase of jump speed */
					walk->gravity_state = WALK_GRAVITY_STATE_ON;
				}
				break;
			case WALK_MODAL_JUMP:
				if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
				    (walk->gravity_state == WALK_GRAVITY_STATE_OFF) &&
				    (walk->teleport.state == WALK_TELEPORT_STATE_OFF))
				{
					/* no need to check for ground,
					 * walk->gravity wouldn't be off
					 * if we were over a hole */
					walk->gravity_state = WALK_GRAVITY_STATE_JUMP;
					walk->speed_jump = JUMP_SPEED_MAX;

					walk->teleport.initial_time = PIL_check_seconds_timer();
					copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);

					/* using previous vec because WASD keys are not called when SPACE is */
					copy_v2_v2(walk->teleport.direction, walk->dvec_prev);

					/* when jumping, duration is how long it takes before we start going down */
					walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
				}

				break;

			case WALK_MODAL_TELEPORT:
			{
				float loc[3], nor[3];
				float distance;
				bool ret = walk_ray_cast(C, walk->rv3d, walk, loc, nor, &distance);

				/* in case we are teleporting middle way from a jump */
				walk->speed_jump = 0.0f;

				if (ret) {
					WalkTeleport *teleport = &walk->teleport;
					teleport->state = WALK_TELEPORT_STATE_ON;
					teleport->initial_time = PIL_check_seconds_timer();
					teleport->duration = U.walk_navigation.teleport_time;

					teleport->navigation_mode = walk->navigation_mode;
					walk_navigation_mode_set(C, walk, WALK_MODE_FREE);

					copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);

					/* stop the camera from a distance (camera height) */
					normalize_v3(nor);
					mul_v3_fl(nor, walk->view_height);
					add_v3_v3(loc, nor);

					sub_v3_v3v3(teleport->direction, loc, teleport->origin);
				}
				else {
					walk->teleport.state = WALK_TELEPORT_STATE_OFF;
				}
				break;
			}

#undef JUMP_SPEED_MAX
#undef JUMP_TIME_MAX
#undef JUMP_SPEED_MIN

			case WALK_MODAL_TOGGLE:
				if (walk->navigation_mode == WALK_MODE_GRAVITY) {
					walk_navigation_mode_set(C, walk, WALK_MODE_FREE);
				}
				else { /* WALK_MODE_FREE */
					walk_navigation_mode_set(C, walk, WALK_MODE_GRAVITY);
				}
				break;
		}
	}
}
示例#6
0
static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
{
	ParticleData *pa=NULL;
	float min[3], max[3], delta[3], d;
	MVert *mv, *mvert = dm->getVertDataArray(dm,0);
	int totvert=dm->getNumVerts(dm), from=psys->part->from;
	int i, j, k, p, res=psys->part->grid_res, size[3], axis;

	/* find bounding box of dm */
	if (totvert > 0) {
		mv=mvert;
		copy_v3_v3(min, mv->co);
		copy_v3_v3(max, mv->co);
		mv++;
		for (i = 1; i < totvert; i++, mv++) {
			minmax_v3v3_v3(min, max, mv->co);
		}
	}
	else {
		zero_v3(min);
		zero_v3(max);
	}

	sub_v3_v3v3(delta, max, min);

	/* determine major axis */
	axis = axis_dominant_v3_single(delta);
	 
	d = delta[axis]/(float)res;

	size[axis] = res;
	size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d);
	size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d);

	/* float errors grrr.. */
	size[(axis+1)%3] = MIN2(size[(axis+1)%3],res);
	size[(axis+2)%3] = MIN2(size[(axis+2)%3],res);

	size[0] = MAX2(size[0], 1);
	size[1] = MAX2(size[1], 1);
	size[2] = MAX2(size[2], 1);

	/* no full offset for flat/thin objects */
	min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f;
	min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f;
	min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f;

	for (i=0,p=0,pa=psys->particles; i<res; i++) {
		for (j=0; j<res; j++) {
			for (k=0; k<res; k++,p++,pa++) {
				pa->fuv[0] = min[0] + (float)i*d;
				pa->fuv[1] = min[1] + (float)j*d;
				pa->fuv[2] = min[2] + (float)k*d;
				pa->flag |= PARS_UNEXIST;
				pa->hair_index = 0; /* abused in volume calculation */
			}
		}
	}

	/* enable particles near verts/edges/faces/inside surface */
	if (from==PART_FROM_VERT) {
		float vec[3];

		pa=psys->particles;

		min[0] -= d/2.0f;
		min[1] -= d/2.0f;
		min[2] -= d/2.0f;

		for (i=0,mv=mvert; i<totvert; i++,mv++) {
			sub_v3_v3v3(vec,mv->co,min);
			vec[0]/=delta[0];
			vec[1]/=delta[1];
			vec[2]/=delta[2];
			pa[((int)(vec[0] * (size[0] - 1))  * res +
			    (int)(vec[1] * (size[1] - 1))) * res +
			    (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST;
		}
	}
	else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
		float co1[3], co2[3];

		MFace *mface= NULL, *mface_array;
		float v1[3], v2[3], v3[3], v4[4], lambda;
		int a, a1, a2, a0mul, a1mul, a2mul, totface;
		int amax= from==PART_FROM_FACE ? 3 : 1;

		totface=dm->getNumTessFaces(dm);
		mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
		
		for (a=0; a<amax; a++) {
			if (a==0) { a0mul=res*res; a1mul=res; a2mul=1; }
			else if (a==1) { a0mul=res; a1mul=1; a2mul=res*res; }
			else { a0mul=1; a1mul=res*res; a2mul=res; }

			for (a1=0; a1<size[(a+1)%3]; a1++) {
				for (a2=0; a2<size[(a+2)%3]; a2++) {
					mface= mface_array;

					pa = psys->particles + a1*a1mul + a2*a2mul;
					copy_v3_v3(co1, pa->fuv);
					co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f;
					copy_v3_v3(co2, co1);
					co2[a] += delta[a] + 0.001f*d;
					co1[a] -= 0.001f*d;
					
					/* lets intersect the faces */
					for (i=0; i<totface; i++,mface++) {
						copy_v3_v3(v1, mvert[mface->v1].co);
						copy_v3_v3(v2, mvert[mface->v2].co);
						copy_v3_v3(v3, mvert[mface->v3].co);

						if (isect_axial_line_segment_tri_v3(a, co1, co2, v2, v3, v1, &lambda)) {
							if (from==PART_FROM_FACE)
								(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
							else /* store number of intersections */
								(pa+(int)(lambda*size[a])*a0mul)->hair_index++;
						}
						else if (mface->v4) {
							copy_v3_v3(v4, mvert[mface->v4].co);

							if (isect_axial_line_segment_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
								if (from==PART_FROM_FACE)
									(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
								else
									(pa+(int)(lambda*size[a])*a0mul)->hair_index++;
							}
						}
					}

					if (from==PART_FROM_VOLUME) {
						int in=pa->hair_index%2;
						if (in) pa->hair_index++;
						for (i=0; i<size[0]; i++) {
							if (in || (pa+i*a0mul)->hair_index%2)
								(pa+i*a0mul)->flag &= ~PARS_UNEXIST;
							/* odd intersections == in->out / out->in */
							/* even intersections -> in stays same */
							in=(in + (pa+i*a0mul)->hair_index) % 2;
						}
					}
				}
			}
		}
	}

	if (psys->part->flag & PART_GRID_HEXAGONAL) {
		for (i=0,p=0,pa=psys->particles; i<res; i++) {
			for (j=0; j<res; j++) {
				for (k=0; k<res; k++,p++,pa++) {
					if (j%2)
						pa->fuv[0] += d/2.f;

					if (k%2) {
						pa->fuv[0] += d/2.f;
						pa->fuv[1] += d/2.f;
					}
				}
			}
		}
	}

	if (psys->part->flag & PART_GRID_INVERT) {
		for (i=0; i<size[0]; i++) {
			for (j=0; j<size[1]; j++) {
				pa=psys->particles + res*(i*res + j);
				for (k=0; k<size[2]; k++, pa++) {
					pa->flag ^= PARS_UNEXIST;
				}
			}
		}
	}

	if (psys->part->grid_rand > 0.f) {
		float rfac = d * psys->part->grid_rand;
		for (p=0,pa=psys->particles; p<psys->totpart; p++,pa++) {
			if (pa->flag & PARS_UNEXIST)
				continue;

			pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f);
			pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f);
			pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f);
		}
	}
}
示例#7
0
/**
 * Sets the depth from #StrokeElem.mval
 */
static bool stroke_elem_project(
        const struct CurveDrawData *cdd,
        const int mval_i[2], const float mval_fl[2],
        float surface_offset, const float radius,
        float r_location_world[3], float r_normal_world[3])
{
	View3D *v3d = cdd->vc.v3d;
	ARegion *ar = cdd->vc.ar;
	RegionView3D *rv3d = cdd->vc.rv3d;

	bool is_location_world_set = false;

	/* project to 'location_world' */
	if (cdd->project.use_plane) {
		/* get the view vector to 'location' */
		float ray_origin[3], ray_direction[3];
		ED_view3d_win_to_ray(cdd->vc.ar, v3d, mval_fl, ray_origin, ray_direction, false);

		float lambda;
		if (isect_ray_plane_v3(ray_origin, ray_direction, cdd->project.plane, &lambda, true)) {
			madd_v3_v3v3fl(r_location_world, ray_origin, ray_direction, lambda);
			if (r_normal_world) {
				zero_v3(r_normal_world);
			}
			is_location_world_set = true;
		}
	}
	else {
		const ViewDepths *depths = rv3d->depths;
		if (depths &&
		    ((unsigned int)mval_i[0] < depths->w) &&
		    ((unsigned int)mval_i[1] < depths->h))
		{
			const double depth = (double)depth_read_zbuf(&cdd->vc, mval_i[0], mval_i[1]);
			if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
				if (depth_unproject(ar, &cdd->mats, mval_i, depth, r_location_world)) {
					is_location_world_set = true;
					if (r_normal_world) {
						zero_v3(r_normal_world);
					}

					if (surface_offset != 0.0f) {
						const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
						float normal[3];
						if (depth_read_normal(&cdd->vc, &cdd->mats, mval_i, normal)) {
							madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
							if (r_normal_world) {
								copy_v3_v3(r_normal_world, normal);
							}
						}
					}
				}
			}
		}
	}

	if (is_location_world_set) {
		if (cdd->project.use_offset) {
			add_v3_v3(r_location_world, cdd->project.offset);
		}
	}

	return is_location_world_set;
}
示例#8
0
/* create imbuf with brush color */
static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
{
	Scene *scene = painter->scene;
	Brush *brush = painter->brush;

	rctf tex_mapping = painter->tex_mapping;
	rctf mask_mapping = painter->mask_mapping;
	struct ImagePool *pool = painter->pool;

	bool use_masking = painter->cache.use_masking;
	bool use_color_correction = painter->cache.use_color_correction;
	bool use_float = painter->cache.use_float;
	bool is_texbrush = painter->cache.is_texbrush;
	bool is_maskbrush = painter->cache.is_maskbrush;

	float alpha = (use_masking)? 1.0f: BKE_brush_alpha_get(scene, brush);
	int radius = BKE_brush_size_get(scene, brush);
	int xoff = -size * 0.5f + 0.5f;
	int yoff = -size * 0.5f + 0.5f;

	int x, y, thread = 0;
	float brush_rgb[3];

	/* allocate image buffer */
	ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect);

	/* get brush color */
	if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
		copy_v3_v3(brush_rgb, brush->rgb);

		if (use_color_correction)
			srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
	}
	else {
		brush_rgb[0] = 1.0f;
		brush_rgb[1] = 1.0f;
		brush_rgb[2] = 1.0f;
	}

	/* fill image buffer */
	for (y = 0; y < size; y++) {
		for (x = 0; x < size; x++) {
			/* sample texture and multiply with brush color */
			float texco[3], rgba[4];

			if (is_texbrush) {
				brush_imbuf_tex_co(&tex_mapping, x, y, texco);
				BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
				mul_v3_v3(rgba, brush_rgb);
			}
			else {
				copy_v3_v3(rgba, brush_rgb);
				rgba[3] = 1.0f;
			}

			if (is_maskbrush) {
				brush_imbuf_tex_co(&mask_mapping, x, y, texco);
				rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
			}

			/* when not using masking, multiply in falloff and strength */
			if (!use_masking) {
				float xy[2] = {x + xoff, y + yoff};
				float len = len_v2(xy);

				rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius);
			}

			if (use_float) {
				/* write to float pixel */
				float *dstf = ibuf->rect_float + (y * size + x) * 4;
				mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */
				dstf[3] = rgba[3];
			}
			else {
				/* write to byte pixel */
				unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4;

				rgb_float_to_uchar(dst, rgba);
				dst[3] = FTOCHAR(rgba[3]);
			}
		}
	}

	return ibuf;
}
示例#9
0
/* update rectangular section of the brush image */
static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
                                       int origx, int origy, int w, int h, int xt, int yt)
{
	Scene *scene = painter->scene;
	Brush *brush = painter->brush;

	rctf tex_mapping = painter->tex_mapping;
	rctf mask_mapping = painter->mask_mapping;
	struct ImagePool *pool = painter->pool;

	bool use_masking = painter->cache.use_masking;
	bool use_color_correction = painter->cache.use_color_correction;
	bool use_float = painter->cache.use_float;
	bool is_texbrush = painter->cache.is_texbrush;
	bool is_maskbrush = painter->cache.is_maskbrush;
	bool use_texture_old = (oldtexibuf != NULL);

	int x, y, thread = 0;
	float brush_rgb[3];

	ImBuf *ibuf = painter->cache.ibuf;
	ImBuf *texibuf = painter->cache.texibuf;
	unsigned short *mask = painter->cache.mask;

	/* get brush color */
	if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
		copy_v3_v3(brush_rgb, brush->rgb);

		if (use_color_correction)
			srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
	}
	else {
		brush_rgb[0] = 1.0f;
		brush_rgb[1] = 1.0f;
		brush_rgb[2] = 1.0f;
	}

	/* fill pixes */
	for (y = origy; y < h; y++) {
		for (x = origx; x < w; x++) {
			/* sample texture and multiply with brush color */
			float texco[3], rgba[4];

			if (!use_texture_old) {
				if (is_texbrush) {
					brush_imbuf_tex_co(&tex_mapping, x, y, texco);
					BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool);
					mul_v3_v3(rgba, brush_rgb);
				}
				else {
					copy_v3_v3(rgba, brush_rgb);
					rgba[3] = 1.0f;
				}

				if (is_maskbrush) {
					brush_imbuf_tex_co(&mask_mapping, x, y, texco);
					rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
				}
			}

			if (use_float) {
				/* handle float pixel */
				float *bf = ibuf->rect_float + (y * ibuf->x + x) * 4;
				float *tf = texibuf->rect_float + (y * texibuf->x + x) * 4;

				/* read from old texture buffer */
				if (use_texture_old) {
					float *otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
					copy_v4_v4(rgba, otf);
				}

				/* write to new texture buffer */
				copy_v4_v4(tf, rgba);

				/* if not using masking, multiply in the mask now */
				if (!use_masking) {
					unsigned short *m = mask + (y * ibuf->x + x);
					rgba[3] *= *m * (1.0f / 65535.0f);
				}

				/* output premultiplied float image, mf was already premultiplied */
				mul_v3_v3fl(bf, rgba, rgba[3]);
				bf[3] = rgba[3];
			}
			else {
				unsigned char crgba[4];

				/* handle byte pixel */
				unsigned char *b = (unsigned char *)ibuf->rect + (y * ibuf->x + x) * 4;
				unsigned char *t = (unsigned char *)texibuf->rect + (y * texibuf->x + x) * 4;

				/* read from old texture buffer */
				if (use_texture_old) {
					unsigned char *ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4;
					crgba[0] = ot[0];
					crgba[1] = ot[1];
					crgba[2] = ot[2];
					crgba[3] = ot[3];
				}
				else
					rgba_float_to_uchar(crgba, rgba);

				/* write to new texture buffer */
				t[0] = crgba[0];
				t[1] = crgba[1];
				t[2] = crgba[2];
				t[3] = crgba[3];

				/* if not using masking, multiply in the mask now */
				if (!use_masking) {
					unsigned short *m = mask + (y * ibuf->x + x);
					crgba[3] = (crgba[3] * (*m)) / 65535;
				}

				/* write to brush image buffer */
				b[0] = crgba[0];
				b[1] = crgba[1];
				b[2] = crgba[2];
				b[3] = crgba[3];
			}
		}
	}
}
/**
 * \brief Mesh -> BMesh
 *
 * \warning This function doesn't calculate face normals.
 */
void BM_mesh_bm_from_me(
        BMesh *bm, Mesh *me,
        const bool calc_face_normal, const bool set_key, int act_key_nr)
{
	MVert *mvert;
	MEdge *medge;
	MLoop *mloop;
	MPoly *mp;
	KeyBlock *actkey, *block;
	BMVert *v, **vtable = NULL;
	BMEdge *e, **etable = NULL;
	BMFace *f;
	float (*keyco)[3] = NULL;
	int totuv, totloops, i, j;

	int cd_vert_bweight_offset;
	int cd_edge_bweight_offset;
	int cd_edge_crease_offset;
	int cd_shape_keyindex_offset;

	/* free custom data */
	/* this isnt needed in most cases but do just incase */
	CustomData_free(&bm->vdata, bm->totvert);
	CustomData_free(&bm->edata, bm->totedge);
	CustomData_free(&bm->ldata, bm->totloop);
	CustomData_free(&bm->pdata, bm->totface);

	if (!me || !me->totvert) {
		if (me) { /*no verts? still copy customdata layout*/
			CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_ASSIGN, 0);
			CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_ASSIGN, 0);

			CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
			CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
			CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
			CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
		}
		return; /* sanity check */
	}

	vtable = MEM_mallocN(sizeof(void **) * me->totvert, "mesh to bmesh vtable");

	CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);

	/* make sure uv layer names are consisten */
	totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	for (i = 0; i < totuv; i++) {
		int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
		CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
	}

	if ((act_key_nr != 0) && (me->key != NULL)) {
		actkey = BLI_findlink(&me->key->block, act_key_nr - 1);
	}
	else {
		actkey = NULL;
	}

	if (me->key) {
		CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);

		/* check if we need to generate unique ids for the shapekeys.
		 * this also exists in the file reading code, but is here for
		 * a sanity check */
		if (!me->key->uidgen) {
			fprintf(stderr,
			        "%s had to generate shape key uid's in a situation we shouldn't need to! "
			        "(bmesh internal error)\n",
			        __func__);

			me->key->uidgen = 1;
			for (block = me->key->block.first; block; block = block->next) {
				block->uid = me->key->uidgen++;
			}
		}

		if (actkey && actkey->totelem == me->totvert) {
			keyco = actkey->data;
			bm->shapenr = act_key_nr;
		}

		for (i = 0, block = me->key->block.first; block; block = block->next, i++) {
			CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
			                           CD_ASSIGN, NULL, 0, block->name);

			j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
			bm->vdata.layers[j].uid = block->uid;
		}
	}

	CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
	CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
	CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
	CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);

	BM_mesh_cd_flag_apply(bm, me->cd_flag);

	cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
	cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
	cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);
	cd_shape_keyindex_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1;

	for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
		v = vtable[i] = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD);
		BM_elem_index_set(v, i); /* set_ok */

		/* transfer flag */
		v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT);

		/* this is necessary for selection counts to work properly */
		if (mvert->flag & SELECT) {
			BM_vert_select_set(bm, v, true);
		}

		normal_short_to_float_v3(v->no, mvert->no);

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);

		if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f);

		/* set shapekey data */
		if (me->key) {
			/* set shape key original index */
			if (cd_shape_keyindex_offset != -1) BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i);

			for (block = me->key->block.first, j = 0; block; block = block->next, j++) {
				float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, j);

				if (co) {
					copy_v3_v3(co, ((float *)block->data) + 3 * i);
				}
			}
		}
	}

	bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */

	if (!me->totedge) {
		MEM_freeN(vtable);
		return;
	}

	etable = MEM_mallocN(sizeof(void **) * me->totedge, "mesh to bmesh etable");

	medge = me->medge;
	for (i = 0; i < me->totedge; i++, medge++) {
		e = etable[i] = BM_edge_create(bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD);
		BM_elem_index_set(e, i); /* set_ok */

		/* transfer flags */
		e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT);

		/* this is necessary for selection counts to work properly */
		if (medge->flag & SELECT) {
			BM_edge_select_set(bm, e, true);
		}

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);

		if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f);
		if (cd_edge_crease_offset  != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset,  (float)medge->crease  / 255.0f);

	}

	bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */

	mloop = me->mloop;
	mp = me->mpoly;
	for (i = 0, totloops = 0; i < me->totpoly; i++, mp++) {
		BMLoop *l_iter;
		BMLoop *l_first;

		f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart,
		                              bm, vtable, etable);

		if (UNLIKELY(f == NULL)) {
			printf("%s: Warning! Bad face in mesh"
			       " \"%s\" at index %d!, skipping\n",
			       __func__, me->id.name + 2, i);
			continue;
		}

		/* don't use 'i' since we may have skipped the face */
		BM_elem_index_set(f, bm->totface - 1); /* set_ok */

		/* transfer flag */
		f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL);

		/* this is necessary for selection counts to work properly */
		if (mp->flag & ME_FACE_SEL) {
			BM_face_select_set(bm, f, true);
		}

		f->mat_nr = mp->mat_nr;
		if (i == me->act_face) bm->act_face = f;

		j = mp->loopstart;
		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
		do {
			/* don't use 'j' since we may have skipped some faces, hence some loops. */
			BM_elem_index_set(l_iter, totloops++); /* set_ok */

			/* Save index of correspsonding MLoop */
			CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
		} while ((l_iter = l_iter->next) != l_first);

		/* Copy Custom Data */
		CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);

		if (calc_face_normal) {
			BM_face_normal_update(f);
		}
	}

	bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */

	if (me->mselect && me->totselect != 0) {

		BMVert **vert_array = MEM_mallocN(sizeof(BMVert *) * bm->totvert, "VSelConv");
		BMEdge **edge_array = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, "ESelConv");
		BMFace **face_array = MEM_mallocN(sizeof(BMFace *) * bm->totface, "FSelConv");
		MSelect *msel;

#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
		{
#pragma omp section
			{ BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)vert_array, bm->totvert); }
#pragma omp section
			{ BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edge_array, bm->totedge); }
#pragma omp section
			{ BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)face_array, bm->totface); }
		}

		for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) {
			switch (msel->type) {
				case ME_VSEL:
					BM_select_history_store(bm, (BMElem *)vert_array[msel->index]);
					break;
				case ME_ESEL:
					BM_select_history_store(bm, (BMElem *)edge_array[msel->index]);
					break;
				case ME_FSEL:
					BM_select_history_store(bm, (BMElem *)face_array[msel->index]);
					break;
			}
		}

		MEM_freeN(vert_array);
		MEM_freeN(edge_array);
		MEM_freeN(face_array);
	}
	else {
		me->totselect = 0;
		if (me->mselect) {
			MEM_freeN(me->mselect);
			me->mselect = NULL;
		}
	}

	MEM_freeN(vtable);
	MEM_freeN(etable);
}
示例#11
0
/* check for null, before calling! */
static void bone_connect_to_existing_parent(EditBone *bone)
{
	bone->flag |= BONE_CONNECTED;
	copy_v3_v3(bone->head, bone->parent->tail);
	bone->rad_head = bone->parent->rad_tail;
}
示例#12
0
/* float to float pixels, output 4-channel RGBA */
void IMB_buffer_float_from_float(float *rect_to, const float *rect_from,
                                 int channels_from, int profile_to, int profile_from, bool predivide,
                                 int width, int height, int stride_to, int stride_from)
{
	int x, y;

	/* we need valid profiles */
	BLI_assert(profile_to != IB_PROFILE_NONE);
	BLI_assert(profile_from != IB_PROFILE_NONE);

	if (channels_from == 1) {
		/* single channel input */
		for (y = 0; y < height; y++) {
			const float *from = rect_from + stride_from * y;
			float *to = rect_to + stride_to * y * 4;

			for (x = 0; x < width; x++, from++, to += 4)
				to[0] = to[1] = to[2] = to[3] = from[0];
		}
	}
	else if (channels_from == 3) {
		/* RGB input */
		for (y = 0; y < height; y++) {
			const float *from = rect_from + stride_from * y * 3;
			float *to = rect_to + stride_to * y * 4;

			if (profile_to == profile_from) {
				/* no color space conversion */
				for (x = 0; x < width; x++, from += 3, to += 4) {
					copy_v3_v3(to, from);
					to[3] = 1.0f;
				}
			}
			else if (profile_to == IB_PROFILE_LINEAR_RGB) {
				/* convert from sRGB to linear */
				for (x = 0; x < width; x++, from += 3, to += 4) {
					srgb_to_linearrgb_v3_v3(to, from);
					to[3] = 1.0f;
				}
			}
			else if (profile_to == IB_PROFILE_SRGB) {
				/* convert from linear to sRGB */
				for (x = 0; x < width; x++, from += 3, to += 4) {
					linearrgb_to_srgb_v3_v3(to, from);
					to[3] = 1.0f;
				}
			}
		}
	}
	else if (channels_from == 4) {
		/* RGBA input */
		for (y = 0; y < height; y++) {
			const float *from = rect_from + stride_from * y * 4;
			float *to = rect_to + stride_to * y * 4;

			if (profile_to == profile_from) {
				/* same profile, copy */
				memcpy(to, from, sizeof(float) * 4 * width);
			}
			else if (profile_to == IB_PROFILE_LINEAR_RGB) {
				/* convert to sRGB to linear */
				if (predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4)
						srgb_to_linearrgb_predivide_v4(to, from);
				}
				else {
					for (x = 0; x < width; x++, from += 4, to += 4)
						srgb_to_linearrgb_v4(to, from);
				}
			}
			else if (profile_to == IB_PROFILE_SRGB) {
				/* convert from linear to sRGB */
				if (predivide) {
					for (x = 0; x < width; x++, from += 4, to += 4)
						linearrgb_to_srgb_predivide_v4(to, from);
				}
				else {
					for (x = 0; x < width; x++, from += 4, to += 4)
						linearrgb_to_srgb_v4(to, from);
				}
			}
		}
	}
}
示例#13
0
文件: cloth.c 项目: DrangPo/blender
static void cloth_hair_update_bending_targets(ClothModifierData *clmd)
{
	Cloth *cloth = clmd->clothObject;
	LinkNode *search = NULL;
	float hair_frame[3][3], dir_old[3], dir_new[3];
	int prev_mn; /* to find hair chains */
	
	if (!clmd->hairdata)
		return;
	
	/* XXX Note: we need to propagate frames from the root up,
	 * but structural hair springs are stored in reverse order.
	 * The bending springs however are then inserted in the same
	 * order as vertices again ...
	 * This messy situation can be resolved when solver data is
	 * generated directly from a dedicated hair system.
	 */
	
	prev_mn = -1;
	for (search = cloth->springs; search; search = search->next) {
		ClothSpring *spring = search->link;
		ClothHairData *hair_ij, *hair_kl;
		bool is_root = spring->kl != prev_mn;
		
		if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) {
			continue;
		}
		
		hair_ij = &clmd->hairdata[spring->ij];
		hair_kl = &clmd->hairdata[spring->kl];
		if (is_root) {
			/* initial hair frame from root orientation */
			copy_m3_m3(hair_frame, hair_ij->rot);
			/* surface normal is the initial direction,
			 * parallel transport then keeps it aligned to the hair direction
			 */
			copy_v3_v3(dir_new, hair_frame[2]);
		}
		
		copy_v3_v3(dir_old, dir_new);
		sub_v3_v3v3(dir_new, cloth->verts[spring->mn].x, cloth->verts[spring->kl].x);
		normalize_v3(dir_new);
		
#if 0
		if (clmd->debug_data && (spring->ij == 0 || spring->ij == 1)) {
			float a[3], b[3];
			
			copy_v3_v3(a, cloth->verts[spring->kl].x);
//			BKE_sim_debug_data_add_dot(clmd->debug_data, cloth_vert ? cloth_vert->x : key->co, 1, 1, 0, "frames", 8246, p, k);
			
			mul_v3_v3fl(b, hair_frame[0], clmd->sim_parms->avg_spring_len);
			BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 1, 0, 0, "frames", 8247, spring->kl, spring->mn);
			
			mul_v3_v3fl(b, hair_frame[1], clmd->sim_parms->avg_spring_len);
			BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 0, 1, 0, "frames", 8248, spring->kl, spring->mn);
			
			mul_v3_v3fl(b, hair_frame[2], clmd->sim_parms->avg_spring_len);
			BKE_sim_debug_data_add_vector(clmd->debug_data, a, b, 0, 0, 1, "frames", 8249, spring->kl, spring->mn);
		}
#endif
		
		/* get local targets for kl/mn vertices by putting rest targets into the current frame,
		 * then multiply with the rest length to get the actual goals
		 */
		
		mul_v3_m3v3(spring->target, hair_frame, hair_kl->rest_target);
		mul_v3_fl(spring->target, spring->restlen);
		
		/* move frame to next hair segment */
		cloth_parallel_transport_hair_frame(hair_frame, dir_old, dir_new);
		
		prev_mn = spring->mn;
	}
}
示例#14
0
文件: cloth.c 项目: DrangPo/blender
static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float UNUSED(framenr), int first)
{
	int i = 0;
	MVert *mvert = NULL;
	ClothVertex *verts = NULL;
	float (*shapekey_rest)[3] = NULL;
	float tnull[3] = {0, 0, 0};
	Cloth *cloth = NULL;
	float maxdist = 0;

	// If we have a clothObject, free it. 
	if ( clmd->clothObject != NULL ) {
		cloth_free_modifier ( clmd );
		if (G.debug_value > 0)
			printf("cloth_free_modifier cloth_from_object\n");
	}

	// Allocate a new cloth object.
	clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" );
	if ( clmd->clothObject ) {
		clmd->clothObject->old_solver_type = 255;
		// clmd->clothObject->old_collision_type = 255;
		cloth = clmd->clothObject;
		clmd->clothObject->edgeset = NULL;
	}
	else if (!clmd->clothObject) {
		modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject");
		return 0;
	}

	// mesh input objects need DerivedMesh
	if ( !dm )
		return 0;

	DM_ensure_looptri(dm);
	cloth_from_mesh ( clmd, dm );

	// create springs
	clmd->clothObject->springs = NULL;
	clmd->clothObject->numsprings = -1;

	if ( clmd->sim_parms->shapekey_rest )
		shapekey_rest = dm->getVertDataArray ( dm, CD_CLOTH_ORCO );

	mvert = dm->getVertArray (dm);

	verts = clmd->clothObject->verts;

	// set initial values
	for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) {
		if (first) {
			copy_v3_v3(verts->x, mvert[i].co);

			mul_m4_v3(ob->obmat, verts->x);

			if ( shapekey_rest ) {
				verts->xrest= shapekey_rest[i];
				mul_m4_v3(ob->obmat, verts->xrest);
			}
			else
				verts->xrest = verts->x;
		}
		
		/* no GUI interface yet */
		verts->mass = clmd->sim_parms->mass; 
		verts->impulse_count = 0;

		if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
			verts->goal= clmd->sim_parms->defgoal;
		else
			verts->goal= 0.0f;

		verts->flags = 0;
		copy_v3_v3 ( verts->xold, verts->x );
		copy_v3_v3 ( verts->xconst, verts->x );
		copy_v3_v3 ( verts->txold, verts->x );
		copy_v3_v3 ( verts->tx, verts->x );
		mul_v3_fl(verts->v, 0.0f);

		verts->impulse_count = 0;
		copy_v3_v3 ( verts->impulse, tnull );
	}
	
	// apply / set vertex groups
	// has to be happen before springs are build!
	cloth_apply_vgroup (clmd, dm);

	if ( !cloth_build_springs ( clmd, dm ) ) {
		cloth_free_modifier ( clmd );
		modifier_setError(&(clmd->modifier), "Cannot build springs");
		printf("cloth_free_modifier cloth_build_springs\n");
		return 0;
	}
	
	for ( i = 0; i < dm->getNumVerts(dm); i++) {
		if ((!(cloth->verts[i].flags & CLOTH_VERT_FLAG_PINNED)) && (cloth->verts[i].goal > ALMOST_ZERO)) {
			cloth_add_spring (clmd, i, i, 0.0, CLOTH_SPRING_TYPE_GOAL);
		}
	}
	
	// init our solver
	BPH_cloth_solver_init(ob, clmd);
	
	if (!first)
		BKE_cloth_solver_set_positions(clmd);

	clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, MAX2(clmd->coll_parms->epsilon, clmd->coll_parms->distance_repel) );
	
	for (i = 0; i < dm->getNumVerts(dm); i++) {
		maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0f));
	}
	
	clmd->clothObject->bvhselftree = bvhselftree_build_from_cloth ( clmd, maxdist );

	return 1;
}
/**
 * This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh.
 * The Linear system is LV = d
 * Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates
 * The Laplacian Matrix is computes as a
 * Lij = sum(Wij) (if i == j)
 * Lij = Wij (if i != j)
 * Wij is weight between vertex Vi and vertex Vj, we use cotangent weight
 *
 * The Differential Coordinate is computes as a
 * di = Vi * sum(Wij) - sum(Wij * Vj)
 * Where :
 * di is the Differential Coordinate i
 * sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj)
 * sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood.
 *
 * This Laplacian Matrix is described in the paper:
 * Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324,
 * New York, USA
 *
 * The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper:
 * Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes,
 * Conference on Graphics Patterns and Images, SIBGRAPI, 2013
 *
 * The computation of Differential Coordinates is described in the paper:
 * Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing,
 * 2004. p. 179-188.
 */
static void initLaplacianMatrix(LaplacianSystem *sys)
{
	float v1[3], v2[3], v3[3], v4[3], no[3];
	float w2, w3, w4;
	int i, j, fi;
	bool has_4_vert;
	unsigned int idv1, idv2, idv3, idv4;

	for (fi = 0; fi < sys->total_faces; fi++) {
		const unsigned int *vidf = sys->faces[fi];

		idv1 = vidf[0];
		idv2 = vidf[1];
		idv3 = vidf[2];
		idv4 = vidf[3];

		has_4_vert = vidf[3] ? 1 : 0;
		if (has_4_vert) {
			normal_quad_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3], sys->co[idv4]);
			add_v3_v3(sys->no[idv4], no);
			i = 4;
		}
		else {
			normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);
			i = 3;
		}
		add_v3_v3(sys->no[idv1], no);
		add_v3_v3(sys->no[idv2], no);
		add_v3_v3(sys->no[idv3], no);

		for (j = 0; j < i; j++) {
			idv1 = vidf[j];
			idv2 = vidf[(j + 1) % i];
			idv3 = vidf[(j + 2) % i];
			idv4 = has_4_vert ? vidf[(j + 3) % i] : 0;

			copy_v3_v3(v1, sys->co[idv1]);
			copy_v3_v3(v2, sys->co[idv2]);
			copy_v3_v3(v3, sys->co[idv3]);
			if (has_4_vert) {
				copy_v3_v3(v4, sys->co[idv4]);
			}

			if (has_4_vert) {

				w2 = (cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2)) / 2.0f;
				w3 = (cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3)) / 2.0f;
				w4 = (cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1)) / 2.0f;

				sys->delta[idv1][0] -= v4[0] * w4;
				sys->delta[idv1][1] -= v4[1] * w4;
				sys->delta[idv1][2] -= v4[2] * w4;

				nlRightHandSideAdd(0, idv1, -v4[0] * w4);
				nlRightHandSideAdd(1, idv1, -v4[1] * w4);
				nlRightHandSideAdd(2, idv1, -v4[2] * w4);

				nlMatrixAdd(idv1, idv4, -w4);
			}
			else {
				w2 = cotangent_tri_weight_v3(v3, v1, v2);
				w3 = cotangent_tri_weight_v3(v2, v3, v1);
				w4 = 0.0f;
			}

			sys->delta[idv1][0] += v1[0] * (w2 + w3 + w4);
			sys->delta[idv1][1] += v1[1] * (w2 + w3 + w4);
			sys->delta[idv1][2] += v1[2] * (w2 + w3 + w4);

			sys->delta[idv1][0] -= v2[0] * w2;
			sys->delta[idv1][1] -= v2[1] * w2;
			sys->delta[idv1][2] -= v2[2] * w2;

			sys->delta[idv1][0] -= v3[0] * w3;
			sys->delta[idv1][1] -= v3[1] * w3;
			sys->delta[idv1][2] -= v3[2] * w3;

			nlMatrixAdd(idv1, idv2, -w2);
			nlMatrixAdd(idv1, idv3, -w3);
			nlMatrixAdd(idv1, idv1, w2 + w3 + w4);

		}
	}
}
示例#16
0
static int object_shape_key_mirror(bContext *C, Object *ob)
{
	KeyBlock *kb;
	Key *key;

	key= ob_get_key(ob);
	if(key==NULL)
		return 0;
	
	kb= BLI_findlink(&key->block, ob->shapenr-1);

	if(kb) {
		int i1, i2;
		float *fp1, *fp2;
		float tvec[3];
		char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");


		if(ob->type==OB_MESH) {
			Mesh *me= ob->data;
			MVert *mv;

			mesh_octree_table(ob, NULL, NULL, 's');

			for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) {
				i2= mesh_get_x_mirror_vert(ob, i1);
				if(i2==i1) {
					fp1= ((float *)kb->data) + i1*3;
					fp1[0] = -fp1[0];
					tag_elem[i1]= 1;
				}
				else if(i2 != -1) {
					if(tag_elem[i1]==0 && tag_elem[i2]==0) {
						fp1= ((float *)kb->data) + i1*3;
						fp2= ((float *)kb->data) + i2*3;

						copy_v3_v3(tvec,	fp1);
						copy_v3_v3(fp1,	fp2);
						copy_v3_v3(fp2,	tvec);

						/* flip x axis */
						fp1[0] = -fp1[0];
						fp2[0] = -fp2[0];
					}
					tag_elem[i1]= tag_elem[i2]= 1;
				}
			}

			mesh_octree_table(ob, NULL, NULL, 'e');
		}
		else if (ob->type == OB_LATTICE) {
			Lattice *lt= ob->data;
			int i1, i2;
			float *fp1, *fp2;
			int u, v, w;
			/* half but found up odd value */
			const int pntsu_half = (((lt->pntsu / 2) + (lt->pntsu % 2))) ;

			/* currently editmode isnt supported by mesh so
			 * ignore here for now too */

			/* if(lt->editlatt) lt= lt->editlatt->latt; */

			for(w=0; w<lt->pntsw; w++) {
				for(v=0; v<lt->pntsv; v++) {
					for(u=0; u<pntsu_half; u++) {
						int u_inv= (lt->pntsu - 1) - u;
						float tvec[3];
						if(u == u_inv) {
							i1= LT_INDEX(lt, u, v, w);
							fp1= ((float *)kb->data) + i1*3;
							fp1[0]= -fp1[0];
						}
						else {
							i1= LT_INDEX(lt, u, v, w);
							i2= LT_INDEX(lt, u_inv, v, w);

							fp1= ((float *)kb->data) + i1*3;
							fp2= ((float *)kb->data) + i2*3;

							copy_v3_v3(tvec, fp1);
							copy_v3_v3(fp1, fp2);
							copy_v3_v3(fp2, tvec);
							fp1[0]= -fp1[0];
							fp2[0]= -fp2[0];
						}
					}
				}
			}
		}

		MEM_freeN(tag_elem);
	}
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);

	return 1;
}
static void rotateDifferentialCoordinates(LaplacianSystem *sys)
{
	float alpha, beta, gamma;
	float pj[3], ni[3], di[3];
	float uij[3], dun[3], e2[3], pi[3], fni[3], vn[4][3];
	int i, j, lvin, num_fni, k, fi;
	int *fidn;

	for (i = 0; i < sys->total_verts; i++) {
		copy_v3_v3(pi, sys->co[i]);
		copy_v3_v3(ni, sys->no[i]);
		k = sys->unit_verts[i];
		copy_v3_v3(pj, sys->co[k]);
		sub_v3_v3v3(uij, pj, pi);
		mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
		sub_v3_v3(uij, dun);
		normalize_v3(uij);
		cross_v3_v3v3(e2, ni, uij);
		copy_v3_v3(di, sys->delta[i]);
		alpha = dot_v3v3(ni, di);
		beta = dot_v3v3(uij, di);
		gamma = dot_v3v3(e2, di);

		pi[0] = nlGetVariable(0, i);
		pi[1] = nlGetVariable(1, i);
		pi[2] = nlGetVariable(2, i);
		zero_v3(ni);
		num_fni = 0;
		num_fni = sys->ringf_map[i].count;
		for (fi = 0; fi < num_fni; fi++) {
			const unsigned int *vin;
			fidn = sys->ringf_map[i].indices;
			vin = sys->faces[fidn[fi]];
			lvin = vin[3] ? 4 : 3;
			for (j = 0; j < lvin; j++) {
				vn[j][0] = nlGetVariable(0, vin[j]);
				vn[j][1] = nlGetVariable(1, vin[j]);
				vn[j][2] = nlGetVariable(2, vin[j]);
				if (vin[j] == sys->unit_verts[i]) {
					copy_v3_v3(pj, vn[j]);
				}
			}

			if (lvin == 3) {
				normal_tri_v3(fni, vn[0], vn[1], vn[2]);
			}
			else if (lvin == 4) {
				normal_quad_v3(fni, vn[0], vn[1], vn[2], vn[3]);
			}
			add_v3_v3(ni, fni);
		}

		normalize_v3(ni);
		sub_v3_v3v3(uij, pj, pi);
		mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
		sub_v3_v3(uij, dun);
		normalize_v3(uij);
		cross_v3_v3v3(e2, ni, uij);
		fni[0] = alpha * ni[0] + beta * uij[0] + gamma * e2[0];
		fni[1] = alpha * ni[1] + beta * uij[1] + gamma * e2[1];
		fni[2] = alpha * ni[2] + beta * uij[2] + gamma * e2[2];

		if (len_squared_v3(fni) > FLT_EPSILON) {
			nlRightHandSideSet(0, i, fni[0]);
			nlRightHandSideSet(1, i, fni[1]);
			nlRightHandSideSet(2, i, fni[2]);
		}
		else {
			nlRightHandSideSet(0, i, sys->delta[i][0]);
			nlRightHandSideSet(1, i, sys->delta[i][1]);
			nlRightHandSideSet(2, i, sys->delta[i][2]);
		}
	}
}
示例#18
0
/* TODO, use define for 'texfall' arg */
void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
{
    ImBuf *ibuf;
    float xy[2], rgba[4], *dstf;
    int x, y, rowbytes, xoff, yoff, imbflag;
    const int radius = BKE_brush_size_get(scene, brush);
    unsigned char *dst, crgb[3];
    const float alpha = BKE_brush_alpha_get(scene, brush);
    float brush_rgb[3];

    imbflag = (flt) ? IB_rectfloat : IB_rect;
    xoff = -bufsize / 2.0f + 0.5f;
    yoff = -bufsize / 2.0f + 0.5f;
    rowbytes = bufsize * 4;

    if (*outbuf)
        ibuf = *outbuf;
    else
        ibuf = IMB_allocImBuf(bufsize, bufsize, 32, imbflag);

    if (flt) {
        copy_v3_v3(brush_rgb, brush->rgb);
        if (use_color_correction) {
            srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb);
        }

        for (y = 0; y < ibuf->y; y++) {
            dstf = ibuf->rect_float + y * rowbytes;

            for (x = 0; x < ibuf->x; x++, dstf += 4) {
                xy[0] = x + xoff;
                xy[1] = y + yoff;

                if (texfall == 0) {
                    copy_v3_v3(dstf, brush_rgb);
                    dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
                }
                else if (texfall == 1) {
                    BKE_brush_sample_tex(scene, brush, xy, dstf, 0);
                }
                else {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    mul_v3_v3v3(dstf, rgba, brush_rgb);
                    dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
                }
            }
        }
    }
    else {
        float alpha_f; /* final float alpha to convert to char */
        rgb_float_to_uchar(crgb, brush->rgb);

        for (y = 0; y < ibuf->y; y++) {
            dst = (unsigned char *)ibuf->rect + y * rowbytes;

            for (x = 0; x < ibuf->x; x++, dst += 4) {
                xy[0] = x + xoff;
                xy[1] = y + yoff;

                if (texfall == 0) {
                    alpha_f = alpha * BKE_brush_curve_strength(brush, len_v2(xy), radius);

                    dst[0] = crgb[0];
                    dst[1] = crgb[1];
                    dst[2] = crgb[2];
                    dst[3] = FTOCHAR(alpha_f);
                }
                else if (texfall == 1) {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    rgba_float_to_uchar(dst, rgba);
                }
                else if (texfall == 2) {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    mul_v3_v3(rgba, brush->rgb);
                    alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);

                    rgb_float_to_uchar(dst, rgba);

                    dst[3] = FTOCHAR(alpha_f);
                }
                else {
                    BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
                    alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);

                    dst[0] = crgb[0];
                    dst[1] = crgb[1];
                    dst[2] = crgb[2];
                    dst[3] = FTOCHAR(alpha_f);
                }
            }
        }
    }

    *outbuf = ibuf;
}
void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3],
                                    float n1[3], float n2[3], float n3[3],
                                    bool fm, bool em1, bool em2, bool em3)
{
	float *fv[3], *fn[3];
#if 0
	float len;
#endif
	unsigned int i, j;
	IndexedFaceSet::FaceEdgeMark marks = 0;

	// initialize the bounding box by the first vertex
	if (ls->currentIndex == 0) {
		copy_v3_v3(ls->minBBox, v1);
		copy_v3_v3(ls->maxBBox, v1);
	}

	fv[0] = v1; fn[0] = n1;
	fv[1] = v2; fn[1] = n2;
	fv[2] = v3; fn[2] = n3;
	for (i = 0; i < 3; i++) {

		copy_v3_v3(ls->pv, fv[i]);
		copy_v3_v3(ls->pn, fn[i]);

		// update the bounding box
		for (j = 0; j < 3; j++) {
			if (ls->minBBox[j] > ls->pv[j])
				ls->minBBox[j] = ls->pv[j];

			if (ls->maxBBox[j] < ls->pv[j])
				ls->maxBBox[j] = ls->pv[j];
		}

#if 0
		len = len_v3v3(fv[i], fv[(i + 1) % 3]);
		if (_minEdgeSize > len)
			_minEdgeSize = len;
#endif

		*ls->pvi = ls->currentIndex;
		*ls->pni = ls->currentIndex;
		*ls->pmi = ls->currentMIndex;

		ls->currentIndex += 3;
		ls->pv += 3;
		ls->pn += 3;

		ls->pvi++;
		ls->pni++;
		ls->pmi++;
	}

	if (fm)
		marks |= IndexedFaceSet::FACE_MARK;
	if (em1)
		marks |= IndexedFaceSet::EDGE_MARK_V1V2;
	if (em2)
		marks |= IndexedFaceSet::EDGE_MARK_V2V3;
	if (em3)
		marks |= IndexedFaceSet::EDGE_MARK_V3V1;
	*(ls->pm++) = marks;
}
示例#20
0
/**
 * Find nearest returns index, and -1 if no node is found.
 */
int BLI_kdtree_find_nearest(
        const KDTree *tree, const float co[3],
        KDTreeNearest *r_nearest)
{
	const KDTreeNode *nodes = tree->nodes;
	const KDTreeNode *root, *min_node;
	uint *stack, defaultstack[KD_STACK_INIT];
	float min_dist, cur_dist;
	uint totstack, cur = 0;

#ifdef DEBUG
	BLI_assert(tree->is_balanced == true);
#endif

	if (UNLIKELY(tree->root == KD_NODE_UNSET))
		return -1;

	stack = defaultstack;
	totstack = KD_STACK_INIT;

	root = &nodes[tree->root];
	min_node = root;
	min_dist = len_squared_v3v3(root->co, co);

	if (co[root->d] < root->co[root->d]) {
		if (root->right != KD_NODE_UNSET)
			stack[cur++] = root->right;
		if (root->left != KD_NODE_UNSET)
			stack[cur++] = root->left;
	}
	else {
		if (root->left != KD_NODE_UNSET)
			stack[cur++] = root->left;
		if (root->right != KD_NODE_UNSET)
			stack[cur++] = root->right;
	}

	while (cur--) {
		const KDTreeNode *node = &nodes[stack[cur]];

		cur_dist = node->co[node->d] - co[node->d];

		if (cur_dist < 0.0f) {
			cur_dist = -cur_dist * cur_dist;

			if (-cur_dist < min_dist) {
				cur_dist = len_squared_v3v3(node->co, co);
				if (cur_dist < min_dist) {
					min_dist = cur_dist;
					min_node = node;
				}
				if (node->left != KD_NODE_UNSET)
					stack[cur++] = node->left;
			}
			if (node->right != KD_NODE_UNSET)
				stack[cur++] = node->right;
		}
		else {
			cur_dist = cur_dist * cur_dist;

			if (cur_dist < min_dist) {
				cur_dist = len_squared_v3v3(node->co, co);
				if (cur_dist < min_dist) {
					min_dist = cur_dist;
					min_node = node;
				}
				if (node->right != KD_NODE_UNSET)
					stack[cur++] = node->right;
			}
			if (node->left != KD_NODE_UNSET)
				stack[cur++] = node->left;
		}
		if (UNLIKELY(cur + 3 > totstack)) {
			stack = realloc_nodes(stack, &totstack, defaultstack != stack);
		}
	}

	if (r_nearest) {
		r_nearest->index = min_node->index;
		r_nearest->dist = sqrtf(min_dist);
		copy_v3_v3(r_nearest->co, min_node->co);
	}

	if (stack != defaultstack)
		MEM_freeN(stack);

	return min_node->index;
}
示例#21
0
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
                       GPUTexture *tex, float min[3], float max[3],
                       int res[3], float dx, float UNUSED(base_scale), float viewnormal[3],
                       GPUTexture *tex_shadow, GPUTexture *tex_flame)
{
	int i, j, k, n, good_index;
	float d /*, d0 */ /* UNUSED */, dd, ds;
	float *points = NULL;
	int numpoints = 0;
	float cor[3] = {1.0f, 1.0f, 1.0f};
	int gl_depth = 0, gl_blend = 0;

	/* draw slices of smoke is adapted from c++ code authored
	 * by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */
	float cv[][3] = {
		{1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
		{1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
	};

	/* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
	float edges[12][2][3] = {
		{{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},

		{{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},

		{{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
	};

	unsigned char *spec_data;
	float *spec_pixels;
	GPUTexture *tex_spec;

	/* Fragment program to calculate the view3d of smoke */
	/* using 4 textures, density, shadow, flame and flame spectrum */
	const char *shader_basic =
	        "!!ARBfp1.0\n"
	        "PARAM dx = program.local[0];\n"
	        "PARAM darkness = program.local[1];\n"
	        "PARAM render = program.local[2];\n"
	        "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
	        "TEMP temp, shadow, flame, spec, value;\n"
	        "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
	        "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
	        "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
	        "TEX spec, flame.r, texture[3], 1D;\n"
	        /* calculate shading factor from density */
	        "MUL value.r, temp.a, darkness.a;\n"
	        "MUL value.r, value.r, dx.r;\n"
	        "MUL value.r, value.r, f.r;\n"
	        "EX2 temp, -value.r;\n"
	        /* alpha */
	        "SUB temp.a, 1.0, temp.r;\n"
	        /* shade colors */
	        "MUL temp.r, temp.r, shadow.r;\n"
	        "MUL temp.g, temp.g, shadow.r;\n"
	        "MUL temp.b, temp.b, shadow.r;\n"
	        "MUL temp.r, temp.r, darkness.r;\n"
	        "MUL temp.g, temp.g, darkness.g;\n"
	        "MUL temp.b, temp.b, darkness.b;\n"
	        /* for now this just replace smoke shading if rendering fire */
	        "CMP result.color, render.r, temp, spec;\n"
	        "END\n";

	/* color shader */
	const char *shader_color =
	        "!!ARBfp1.0\n"
	        "PARAM dx = program.local[0];\n"
	        "PARAM darkness = program.local[1];\n"
	        "PARAM render = program.local[2];\n"
	        "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n"
	        "TEMP temp, shadow, flame, spec, value;\n"
	        "TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
	        "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
	        "TEX flame, fragment.texcoord[0], texture[2], 3D;\n"
	        "TEX spec, flame.r, texture[3], 1D;\n"
	        /* unpremultiply volume texture */
	        "RCP value.r, temp.a;\n"
	        "MUL temp.r, temp.r, value.r;\n"
	        "MUL temp.g, temp.g, value.r;\n"
	        "MUL temp.b, temp.b, value.r;\n"
	        /* calculate shading factor from density */
	        "MUL value.r, temp.a, darkness.a;\n"
	        "MUL value.r, value.r, dx.r;\n"
	        "MUL value.r, value.r, f.r;\n"
	        "EX2 value.r, -value.r;\n"
	        /* alpha */
	        "SUB temp.a, 1.0, value.r;\n"
	        /* shade colors */
	        "MUL temp.r, temp.r, shadow.r;\n"
	        "MUL temp.g, temp.g, shadow.r;\n"
	        "MUL temp.b, temp.b, shadow.r;\n"
	        "MUL temp.r, temp.r, value.r;\n"
	        "MUL temp.g, temp.g, value.r;\n"
	        "MUL temp.b, temp.b, value.r;\n"
	        /* for now this just replace smoke shading if rendering fire */
	        "CMP result.color, render.r, temp, spec;\n"
	        "END\n";

	GLuint prog;

	
	float size[3];

	if (!tex) {
		printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
		return;
	}

#ifdef DEBUG_DRAW_TIME
	TIMEIT_START(draw);
#endif

	/* generate flame spectrum texture */
	#define SPEC_WIDTH 256
	#define FIRE_THRESH 7
	#define MAX_FIRE_ALPHA 0.06f
	#define FULL_ON_FIRE 100
	spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char));
	flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000);
	spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float));
	for (i = 0; i < 16; i++) {
		for (j = 0; j < 16; j++) {
			for (k = 0; k < SPEC_WIDTH; k++) {
				int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
				if (k >= FIRE_THRESH) {
					spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f;
					spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f;
					spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f;
					spec_pixels[index + 3] = MAX_FIRE_ALPHA * (
					        (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
				}
				else {
					spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f;
				}
			}
		}
	}

	tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);

	sub_v3_v3v3(size, max, min);

	/* maxx, maxy, maxz */
	cv[0][0] = max[0];
	cv[0][1] = max[1];
	cv[0][2] = max[2];
	/* minx, maxy, maxz */
	cv[1][0] = min[0];
	cv[1][1] = max[1];
	cv[1][2] = max[2];
	/* minx, miny, maxz */
	cv[2][0] = min[0];
	cv[2][1] = min[1];
	cv[2][2] = max[2];
	/* maxx, miny, maxz */
	cv[3][0] = max[0];
	cv[3][1] = min[1];
	cv[3][2] = max[2];

	/* maxx, maxy, minz */
	cv[4][0] = max[0];
	cv[4][1] = max[1];
	cv[4][2] = min[2];
	/* minx, maxy, minz */
	cv[5][0] = min[0];
	cv[5][1] = max[1];
	cv[5][2] = min[2];
	/* minx, miny, minz */
	cv[6][0] = min[0];
	cv[6][1] = min[1];
	cv[6][2] = min[2];
	/* maxx, miny, minz */
	cv[7][0] = max[0];
	cv[7][1] = min[1];
	cv[7][2] = min[2];

	copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */
	copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */
	copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */

	copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */
	copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */
	copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */

	copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */
	copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */
	copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */
	copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */

	// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
	// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);

	edges[0][1][2] = size[2];
	edges[1][1][2] = size[2];
	edges[2][1][2] = size[2];
	edges[3][1][2] = size[2];

	edges[4][1][1] = size[1];
	edges[5][1][1] = size[1];
	edges[6][1][1] = size[1];
	edges[7][1][1] = size[1];

	edges[8][1][0] = size[0];
	edges[9][1][0] = size[0];
	edges[10][1][0] = size[0];
	edges[11][1][0] = size[0];

	glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
	glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);

	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);

	/* find cube vertex that is closest to the viewer */
	for (i = 0; i < 8; i++) {
		float x, y, z;

		x = cv[i][0] - viewnormal[0] * size[0] * 0.5f;
		y = cv[i][1] - viewnormal[1] * size[1] * 0.5f;
		z = cv[i][2] - viewnormal[2] * size[2] * 0.5f;

		if ((x >= min[0]) && (x <= max[0]) &&
		    (y >= min[1]) && (y <= max[1]) &&
		    (z >= min[2]) && (z <= max[2]))
		{
			break;
		}
	}

	if (i >= 8) {
		/* fallback, avoid using buffer over-run */
		i = 0;
	}

	// printf("i: %d\n", i);
	// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);

	if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) {
		glEnable(GL_FRAGMENT_PROGRAM_ARB);
		glGenProgramsARB(1, &prog);

		glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
		/* set shader */
		if (sds->active_fields & SM_ACTIVE_COLORS)
			glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color);
		else
			glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic);

		/* cell spacing */
		glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
		/* custom parameter for smoke style (higher = thicker) */
		if (sds->active_fields & SM_ACTIVE_COLORS)
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0);
		else
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
	}
	else
		printf("Your gfx card does not support 3D View smoke drawing.\n");

	GPU_texture_bind(tex, 0);
	if (tex_shadow)
		GPU_texture_bind(tex_shadow, 1);
	else
		printf("No volume shadow\n");

	if (tex_flame) {
		GPU_texture_bind(tex_flame, 2);
		GPU_texture_bind(tex_spec, 3);
	}

	if (!GPU_non_power_of_two_support()) {
		cor[0] = (float)res[0] / (float)power_of_2_max_i(res[0]);
		cor[1] = (float)res[1] / (float)power_of_2_max_i(res[1]);
		cor[2] = (float)res[2] / (float)power_of_2_max_i(res[2]);
	}

	/* our slices are defined by the plane equation a*x + b*y +c*z + d = 0
	 * (a,b,c), the plane normal, are given by viewdir
	 * d is the parameter along the view direction. the first d is given by
	 * inserting previously found vertex into the plane equation */

	/* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
	ds = (fabsf(viewnormal[0]) * size[0] + fabsf(viewnormal[1]) * size[1] + fabsf(viewnormal[2]) * size[2]);
	dd = max_fff(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
	n = 0;
	good_index = i;

	// printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);

	points = MEM_callocN(sizeof(float) * 12 * 3, "smoke_points_preview");

	while (1) {
		float p0[3];
		float tmp_point[3], tmp_point2[3];

		if (dd * (float)n > ds)
			break;

		copy_v3_v3(tmp_point, viewnormal);
		mul_v3_fl(tmp_point, -dd * ((ds / dd) - (float)n));
		add_v3_v3v3(tmp_point2, cv[good_index], tmp_point);
		d = dot_v3v3(tmp_point2, viewnormal);

		// printf("my d: %f\n", d);

		/* intersect_edges returns the intersection points of all cube edges with
		 * the given plane that lie within the cube */
		numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);

		// printf("points: %d\n", numpoints);

		if (numpoints > 2) {
			copy_v3_v3(p0, points);

			/* sort points to get a convex polygon */
			for (i = 1; i < numpoints - 1; i++) {
				for (j = i + 1; j < numpoints; j++) {
					if (!convex(p0, viewnormal, &points[j * 3], &points[i * 3])) {
						float tmp2[3];
						copy_v3_v3(tmp2, &points[j * 3]);
						copy_v3_v3(&points[j * 3], &points[i * 3]);
						copy_v3_v3(&points[i * 3], tmp2);
					}
				}
			}

			/* render fire slice */
			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0);
			glBegin(GL_POLYGON);
			glColor3f(1.0, 1.0, 1.0);
			for (i = 0; i < numpoints; i++) {
				glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
				             (points[i * 3 + 1] - min[1]) * cor[1] / size[1],
				             (points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
				glVertex3f(points[i * 3 + 0] / fabsf(ob->size[0]),
				           points[i * 3 + 1] / fabsf(ob->size[1]),
				           points[i * 3 + 2] / fabsf(ob->size[2]));
			}
			glEnd();

			/* render smoke slice */
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0);
			glBegin(GL_POLYGON);
			glColor3f(1.0, 1.0, 1.0);
			for (i = 0; i < numpoints; i++) {
				glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0],
				             (points[i * 3 + 1] - min[1]) * cor[1] / size[1],
				             (points[i * 3 + 2] - min[2]) * cor[2] / size[2]);
				glVertex3f(points[i * 3 + 0] / fabsf(ob->size[0]),
				           points[i * 3 + 1] / fabsf(ob->size[1]),
				           points[i * 3 + 2] / fabsf(ob->size[2]));
			}
			glEnd();
		}
		n++;
	}

#ifdef DEBUG_DRAW_TIME
	printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
	TIMEIT_END(draw);
#endif

	if (tex_shadow)
		GPU_texture_unbind(tex_shadow);
	GPU_texture_unbind(tex);
	if (tex_flame) {
		GPU_texture_unbind(tex_flame);
		GPU_texture_unbind(tex_spec);
	}
	GPU_texture_free(tex_spec);

	free(spec_data);
	free(spec_pixels);

	if (GLEW_ARB_fragment_program) {
		glDisable(GL_FRAGMENT_PROGRAM_ARB);
		glDeleteProgramsARB(1, &prog);
	}


	MEM_freeN(points);

	if (!gl_blend) {
		glDisable(GL_BLEND);
	}

	if (gl_depth) {
		glEnable(GL_DEPTH_TEST);
		glDepthMask(GL_TRUE);
	}
}
示例#22
0
/**
 * A version of #BLI_kdtree_find_nearest which runs a callback
 * to filter out values.
 *
 * \param filter_cb: Filter find results,
 * Return codes: (1: accept, 0: skip, -1: immediate exit).
 */
int BLI_kdtree_find_nearest_cb(
        const KDTree *tree, const float co[3],
        int (*filter_cb)(void *user_data, int index, const float co[3], float dist_sq), void *user_data,
        KDTreeNearest *r_nearest)
{
	const KDTreeNode *nodes = tree->nodes;
	const KDTreeNode *min_node = NULL;

	uint *stack, defaultstack[KD_STACK_INIT];
	float min_dist = FLT_MAX, cur_dist;
	uint totstack, cur = 0;

#ifdef DEBUG
	BLI_assert(tree->is_balanced == true);
#endif

	if (UNLIKELY(tree->root == KD_NODE_UNSET))
		return -1;

	stack = defaultstack;
	totstack = KD_STACK_INIT;

#define NODE_TEST_NEAREST(node) \
{ \
	const float dist_sq = len_squared_v3v3((node)->co, co); \
	if (dist_sq < min_dist) { \
		const int result = filter_cb(user_data, (node)->index, (node)->co, dist_sq); \
		if (result == 1) { \
			min_dist = dist_sq; \
			min_node = node; \
		} \
		else if (result == 0) { \
			/* pass */ \
		} \
		else { \
			BLI_assert(result == -1); \
			goto finally; \
		} \
	} \
} ((void)0)

	stack[cur++] = tree->root;

	while (cur--) {
		const KDTreeNode *node = &nodes[stack[cur]];

		cur_dist = node->co[node->d] - co[node->d];

		if (cur_dist < 0.0f) {
			cur_dist = -cur_dist * cur_dist;

			if (-cur_dist < min_dist) {
				NODE_TEST_NEAREST(node);

				if (node->left != KD_NODE_UNSET)
					stack[cur++] = node->left;
			}
			if (node->right != KD_NODE_UNSET)
				stack[cur++] = node->right;
		}
		else {
			cur_dist = cur_dist * cur_dist;

			if (cur_dist < min_dist) {
				NODE_TEST_NEAREST(node);

				if (node->right != KD_NODE_UNSET)
					stack[cur++] = node->right;
			}
			if (node->left != KD_NODE_UNSET)
				stack[cur++] = node->left;
		}
		if (UNLIKELY(cur + 3 > totstack)) {
			stack = realloc_nodes(stack, &totstack, defaultstack != stack);
		}
	}

#undef NODE_TEST_NEAREST


finally:
	if (stack != defaultstack)
		MEM_freeN(stack);

	if (min_node) {
		if (r_nearest) {
			r_nearest->index = min_node->index;
			r_nearest->dist = sqrtf(min_dist);
			copy_v3_v3(r_nearest->co, min_node->co);
		}

		return min_node->index;
	}
	else {
		return -1;
	}
}
示例#23
0
/**
 * The main function for copying DerivedMesh data into BMesh.
 *
 * \note The mesh may already have geometry. see 'is_init'
 */
void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
{
	MVert *mv, *mvert;
	MEdge *me, *medge;
	MPoly /* *mpoly, */ /* UNUSED */ *mp;
	MLoop *mloop;
	BMVert *v, **vtable;
	BMEdge *e, **etable;
	float (*face_normals)[3];
	BMFace *f;
	int i, j, totvert, totedge /* , totface */ /* UNUSED */ ;
	bool is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0);
	bool is_cddm = (dm->type == DM_TYPE_CDDM);  /* duplicate the arrays for non cddm */
	char has_orig_hflag = 0;

	int cd_vert_bweight_offset;
	int cd_edge_bweight_offset;
	int cd_edge_crease_offset;

	if (is_init == FALSE) {
		/* check if we have an origflag */
		has_orig_hflag |= CustomData_has_layer(&bm->vdata, CD_ORIGINDEX) ? BM_VERT : 0;
		has_orig_hflag |= CustomData_has_layer(&bm->edata, CD_ORIGINDEX) ? BM_EDGE : 0;
		has_orig_hflag |= CustomData_has_layer(&bm->pdata, CD_ORIGINDEX) ? BM_FACE : 0;
	}

	/*merge custom data layout*/
	CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT);
	CustomData_bmesh_merge(&dm->edgeData, &bm->edata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_EDGE);
	CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_LOOP);
	CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_FACE);

	if (is_init) {
		BM_mesh_cd_flag_apply(bm, dm->cd_flag);
	}

	cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
	cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
	cd_edge_crease_offset  = CustomData_get_offset(&bm->edata, CD_CREASE);

	totvert = dm->getNumVerts(dm);
	totedge = dm->getNumEdges(dm);
	/* totface = dm->getNumPolys(dm); */ /* UNUSED */

	vtable = MEM_callocN(sizeof(void **) * totvert, __func__);
	etable = MEM_callocN(sizeof(void **) * totedge, __func__);

	/*do verts*/
	mv = mvert = is_cddm ? dm->getVertArray(dm) : dm->dupVertArray(dm);
	for (i = 0; i < totvert; i++, mv++) {
		v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD);
		normal_short_to_float_v3(v->no, mv->no);
		v->head.hflag = BM_vert_flag_from_mflag(mv->flag);
		BM_elem_index_set(v, i); /* set_inline */

		CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data, true);
		vtable[i] = v;

		/* add bevel weight */
		if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mv->bweight / 255.0f);

		if (UNLIKELY(has_orig_hflag & BM_VERT)) {
			int *orig_index = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_ORIGINDEX);
			*orig_index = ORIGINDEX_NONE;
		}
	}
	if (!is_cddm) MEM_freeN(mvert);
	if (is_init) bm->elem_index_dirty &= ~BM_VERT;

	/*do edges*/
	me = medge = is_cddm ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm);
	for (i = 0; i < totedge; i++, me++) {
		//BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL);
		e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD);

		e->head.hflag = BM_edge_flag_from_mflag(me->flag);
		BM_elem_index_set(e, i); /* set_inline */

		CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data, true);
		etable[i] = e;

		if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)me->bweight / 255.0f);
		if (cd_edge_crease_offset  != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset,  (float)me->crease  / 255.0f);

		if (UNLIKELY(has_orig_hflag & BM_EDGE)) {
			int *orig_index = CustomData_bmesh_get(&bm->edata, e->head.data, CD_ORIGINDEX);
			*orig_index = ORIGINDEX_NONE;
		}
	}
	if (!is_cddm) MEM_freeN(medge);
	if (is_init) bm->elem_index_dirty &= ~BM_EDGE;

	/* do faces */
	/* note: i_alt is aligned with bmesh faces which may not always align with mpolys */
	mp = dm->getPolyArray(dm);
	mloop = dm->getLoopArray(dm);
	face_normals = (dm->dirty & DM_DIRTY_NORMALS) ? NULL : CustomData_get_layer(&dm->polyData, CD_NORMAL);
	for (i = 0; i < dm->numPolyData; i++, mp++) {
		BMLoop *l_iter;
		BMLoop *l_first;

		f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart,
		                              bm, vtable, etable);

		if (UNLIKELY(f == NULL)) {
			continue;
		}

		f->head.hflag = BM_face_flag_from_mflag(mp->flag);
		BM_elem_index_set(f, bm->totface - 1); /* set_inline */
		f->mat_nr = mp->mat_nr;

		j = mp->loopstart;
		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
		do {
			/* Save index of correspsonding MLoop */
			CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, j++, &l_iter->head.data, true);
		} while ((l_iter = l_iter->next) != l_first);

		CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data, true);

		if (calc_face_normal) {
			if (face_normals) {
				copy_v3_v3(f->no, face_normals[i]);
			}
			else {
				BM_face_normal_update(f);
			}
		}

		if (UNLIKELY(has_orig_hflag & BM_FACE)) {
			int *orig_index = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_ORIGINDEX);
			*orig_index = ORIGINDEX_NONE;
		}
	}
	if (is_init) bm->elem_index_dirty &= ~BM_FACE;

	MEM_freeN(vtable);
	MEM_freeN(etable);
}
static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3])
{
	float norm[3], vec[3], factor, angle;
	float t_con_center[3];

	if (in[0] == 0.0f && in[1] == 0.0f && in[2] == 0.0f)
		return;

	copy_v3_v3(t_con_center, t->con.center);

	/* checks for center being too close to the view center */
	viewAxisCorrectCenter(t, t_con_center);
	
	angle = fabsf(angle_v3v3(axis, t->viewinv[2]));
	if (angle > (float)M_PI / 2.0f) {
		angle = (float)M_PI - angle;
	}
	angle = RAD2DEGF(angle);

	/* For when view is parallel to constraint... will cause NaNs otherwise
	 * So we take vertical motion in 3D space and apply it to the
	 * constraint axis. Nice for camera grab + MMB */
	if (angle < 5.0f) {
		project_v3_v3v3(vec, in, t->viewinv[1]);
		factor = dot_v3v3(t->viewinv[1], vec) * 2.0f;
		/* since camera distance is quite relative, use quadratic relationship. holding shift can compensate */
		if (factor < 0.0f) factor *= -factor;
		else factor *= factor;

		copy_v3_v3(out, axis);
		normalize_v3(out);
		mul_v3_fl(out, -factor);  /* -factor makes move down going backwards */
	}
	else {
		float v[3], i1[3], i2[3];
		float v2[3], v4[3];
		float norm_center[3];
		float plane[3];

		getViewVector(t, t_con_center, norm_center);
		cross_v3_v3v3(plane, norm_center, axis);

		project_v3_v3v3(vec, in, plane);
		sub_v3_v3v3(vec, in, vec);
		
		add_v3_v3v3(v, vec, t_con_center);
		getViewVector(t, v, norm);

		/* give arbitrary large value if projection is impossible */
		factor = dot_v3v3(axis, norm);
		if (1.0f - fabsf(factor) < 0.0002f) {
			copy_v3_v3(out, axis);
			if (factor > 0) {
				mul_v3_fl(out, 1000000000.0f);
			}
			else {
				mul_v3_fl(out, -1000000000.0f);
			}
		}
		else {
			add_v3_v3v3(v2, t_con_center, axis);
			add_v3_v3v3(v4, v, norm);
			
			isect_line_line_v3(t_con_center, v2, v, v4, i1, i2);
			
			sub_v3_v3v3(v, i2, v);
	
			sub_v3_v3v3(out, i1, t_con_center);

			/* possible some values become nan when
			 * viewpoint and object are both zero */
			if (!finite(out[0])) out[0] = 0.0f;
			if (!finite(out[1])) out[1] = 0.0f;
			if (!finite(out[2])) out[2] = 0.0f;
		}
	}
}
示例#25
0
static int walkApply(bContext *C, 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, 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 void setNearestAxis3d(TransInfo *t)
{
	float zfac;
	float mvec[3], axis[3], proj[3];
	float len[3];
	int i, icoord[2];

	/* calculate mouse movement */
	mvec[0] = (float)(t->mval[0] - t->con.imval[0]);
	mvec[1] = (float)(t->mval[1] - t->con.imval[1]);
	mvec[2] = 0.0f;

	/* we need to correct axis length for the current zoomlevel of view,
	 * this to prevent projected values to be clipped behind the camera
	 * and to overflow the short integers.
	 * The formula used is a bit stupid, just a simplification of the subtraction
	 * of two 2D points 30 pixels apart (that's the last factor in the formula) after
	 * projecting them with window_to_3d_delta and then get the length of that vector.
	 */
	zfac = t->persmat[0][3] * t->center[0] + t->persmat[1][3] * t->center[1] + t->persmat[2][3] * t->center[2] + t->persmat[3][3];
	zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f;

	for (i = 0; i < 3; i++) {
		copy_v3_v3(axis, t->con.mtx[i]);

		mul_v3_fl(axis, zfac);
		/* now we can project to get window coordinate */
		add_v3_v3(axis, t->con.center);
		projectIntView(t, axis, icoord);

		axis[0] = (float)(icoord[0] - t->center2d[0]);
		axis[1] = (float)(icoord[1] - t->center2d[1]);
		axis[2] = 0.0f;

		if (normalize_v3(axis) != 0.0f) {
			project_v3_v3v3(proj, mvec, axis);
			sub_v3_v3v3(axis, mvec, proj);
			len[i] = normalize_v3(axis);
		}
		else {
			len[i] = 10000000000.0f;
		}
	}

	if (len[0] <= len[1] && len[0] <= len[2]) {
		if (t->modifiers & MOD_CONSTRAINT_PLANE) {
			t->con.mode |= (CON_AXIS1 | CON_AXIS2);
			BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s X axis", t->spacename);
		}
		else {
			t->con.mode |= CON_AXIS0;
			BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s X axis", t->spacename);
		}
	}
	else if (len[1] <= len[0] && len[1] <= len[2]) {
		if (t->modifiers & MOD_CONSTRAINT_PLANE) {
			t->con.mode |= (CON_AXIS0 | CON_AXIS2);
			BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Y axis", t->spacename);
		}
		else {
			t->con.mode |= CON_AXIS1;
			BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Y axis", t->spacename);
		}
	}
	else if (len[2] <= len[1] && len[2] <= len[0]) {
		if (t->modifiers & MOD_CONSTRAINT_PLANE) {
			t->con.mode |= (CON_AXIS0 | CON_AXIS1);
			BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Z axis", t->spacename);
		}
		else {
			t->con.mode |= CON_AXIS2;
			BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Z axis", t->spacename);
		}
	}
}
示例#27
0
Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
{
	static int xzproj = 0;   /* this function calls itself... */
	ListBase *editnurb = object_editcurve_get(obedit);
	RegionView3D *rv3d = ED_view3d_context_rv3d(C);
	Nurb *nu = NULL;
	BezTriple *bezt;
	BPoint *bp;
	Curve *cu = (Curve *)obedit->data;
	float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f};
	float umat[4][4], viewmat[4][4];
	float fac;
	int a, b;
	const float grid = 1.0f;
	const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc
	const int stype = (type & CU_PRIMITIVE);
	const bool force_3d = (((Curve *)obedit->data)->flag & CU_3D) != 0; /* could be adding to an existing 3D curve */

	unit_m4(umat);
	unit_m4(viewmat);

	if (rv3d) {
		copy_m4_m4(viewmat, rv3d->viewmat);
		copy_v3_v3(zvec, rv3d->viewinv[2]);
	}

	BKE_nurbList_flag_set(editnurb, 0);

	/* these types call this function to return a Nurb */
	if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) {
		nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim");
		nu->type = cutype;
		nu->resolu = cu->resolu;
		nu->resolv = cu->resolv;
	}

	switch (stype) {
		case CU_PRIM_CURVE: /* curve */
			nu->resolu = cu->resolu;
			if (cutype == CU_BEZIER) {
				if (!force_3d) nu->flag |= CU_2D;
				nu->pntsu = 2;
				nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1");
				bezt = nu->bezt;
				bezt->h1 = bezt->h2 = HD_ALIGN;
				bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
				bezt->radius = 1.0;

				bezt->vec[1][0] += -grid;
				bezt->vec[0][0] += -1.5f * grid;
				bezt->vec[0][1] += -0.5f * grid;
				bezt->vec[2][0] += -0.5f * grid;
				bezt->vec[2][1] +=  0.5f * grid;
				for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);

				bezt++;
				bezt->h1 = bezt->h2 = HD_ALIGN;
				bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
				bezt->radius = bezt->weight = 1.0;

				bezt->vec[0][0] = 0;
				bezt->vec[0][1] = 0;
				bezt->vec[1][0] = grid;
				bezt->vec[1][1] = 0;
				bezt->vec[2][0] = grid * 2;
				bezt->vec[2][1] = 0;
				for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);

				BKE_nurb_handles_calc(nu);
			}
			else {

				nu->pntsu = 4;
				nu->pntsv = 1;
				nu->orderu = 4;
				nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3");

				bp = nu->bp;
				for (a = 0; a < 4; a++, bp++) {
					bp->vec[3] = 1.0;
					bp->f1 = SELECT;
					bp->radius = bp->weight = 1.0;
				}

				bp = nu->bp;
				bp->vec[0] += -1.5f * grid;
				bp++;
				bp->vec[0] += -grid;
				bp->vec[1] +=  grid;
				bp++;
				bp->vec[0] += grid;
				bp->vec[1] += grid;
				bp++;
				bp->vec[0] += 1.5f * grid;

				bp = nu->bp;
				for (a = 0; a < 4; a++, bp++) mul_m4_v3(mat, bp->vec);

				if (cutype == CU_NURBS) {
					nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
					BKE_nurb_knot_calc_u(nu);
				}

			}
			break;
		case CU_PRIM_PATH: /* 5 point path */
			nu->pntsu = 5;
			nu->pntsv = 1;
			nu->orderu = 5;
			nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
			nu->resolu = cu->resolu;
			nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3");

			bp = nu->bp;
			for (a = 0; a < 5; a++, bp++) {
				bp->vec[3] = 1.0;
				bp->f1 = SELECT;
				bp->radius = bp->weight = 1.0;
			}

			bp = nu->bp;
			bp->vec[0] += -2.0f * grid;
			bp++;
			bp->vec[0] += -grid;
			bp++; bp++;
			bp->vec[0] += grid;
			bp++;
			bp->vec[0] += 2.0f * grid;

			bp = nu->bp;
			for (a = 0; a < 5; a++, bp++) mul_m4_v3(mat, bp->vec);

			if (cutype == CU_NURBS) {
				nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */
				BKE_nurb_knot_calc_u(nu);
			}

			break;
		case CU_PRIM_CIRCLE: /* circle */
			nu->resolu = cu->resolu;

			if (cutype == CU_BEZIER) {
				if (!force_3d) nu->flag |= CU_2D;
				nu->pntsu = 4;
				nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1");
				nu->flagu = CU_NURB_CYCLIC;
				bezt = nu->bezt;

				bezt->h1 = bezt->h2 = HD_AUTO;
				bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
				bezt->vec[1][0] += -grid;
				for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
				bezt->radius = bezt->weight = 1.0;

				bezt++;
				bezt->h1 = bezt->h2 = HD_AUTO;
				bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
				bezt->vec[1][1] += grid;
				for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
				bezt->radius = bezt->weight = 1.0;

				bezt++;
				bezt->h1 = bezt->h2 = HD_AUTO;
				bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
				bezt->vec[1][0] += grid;
				for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
				bezt->radius = bezt->weight = 1.0;

				bezt++;
				bezt->h1 = bezt->h2 = HD_AUTO;
				bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
				bezt->vec[1][1] += -grid;
				for (a = 0; a < 3; a++) mul_m4_v3(mat, bezt->vec[a]);
				bezt->radius = bezt->weight = 1.0;

				BKE_nurb_handles_calc(nu);
			}
			else if (cutype == CU_NURBS) { /* nurb */
				nu->pntsu = 8;
				nu->pntsv = 1;
				nu->orderu = 4;
				nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6");
				nu->flagu = CU_NURB_CYCLIC;
				bp = nu->bp;

				for (a = 0; a < 8; a++) {
					bp->f1 = SELECT;
					if (xzproj == 0) {
						bp->vec[0] += nurbcircle[a][0] * grid;
						bp->vec[1] += nurbcircle[a][1] * grid;
					}
					else {
						bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid;
						bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
					}
					if (a & 1) bp->vec[3] = 0.25 * M_SQRT2;
					else bp->vec[3] = 1.0;
					mul_m4_v3(mat, bp->vec);
					bp->radius = bp->weight = 1.0;

					bp++;
				}

				BKE_nurb_knot_calc_u(nu);
			}
			break;
		case CU_PRIM_PATCH: /* 4x4 patch */
			if (cutype == CU_NURBS) { /* nurb */

				nu->pntsu = 4;
				nu->pntsv = 4;
				nu->orderu = 4;
				nu->orderv = 4;
				nu->flag = CU_SMOOTH;
				nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6");
				nu->flagu = 0;
				nu->flagv = 0;
				bp = nu->bp;

				for (a = 0; a < 4; a++) {
					for (b = 0; b < 4; b++) {
						bp->f1 = SELECT;
						fac = (float)a - 1.5f;
						bp->vec[0] += fac * grid;
						fac = (float)b - 1.5f;
						bp->vec[1] += fac * grid;
						if ((a == 1 || a == 2) && (b == 1 || b == 2)) {
							bp->vec[2] += grid;
						}
						mul_m4_v3(mat, bp->vec);
						bp->vec[3] = 1.0;
						bp++;
					}
				}

				BKE_nurb_knot_calc_u(nu);
				BKE_nurb_knot_calc_v(nu);
			}
			break;
		case CU_PRIM_TUBE: /* Cylinder */
			if (cutype == CU_NURBS) {
				nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
				nu->resolu = cu->resolu;
				nu->flag = CU_SMOOTH;
				BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
				vec[0] = vec[1] = 0.0;
				vec[2] = -grid;

				mul_mat3_m4_v3(mat, vec);

				ed_editnurb_translate_flag(editnurb, SELECT, vec);
				ed_editnurb_extrude_flag(cu->editnurb, SELECT);
				mul_v3_fl(vec, -2.0f);
				ed_editnurb_translate_flag(editnurb, SELECT, vec);

				BLI_remlink(editnurb, nu);

				a = nu->pntsu * nu->pntsv;
				bp = nu->bp;
				while (a-- > 0) {
					bp->f1 |= SELECT;
					bp++;
				}
			}
			break;
		case CU_PRIM_SPHERE: /* sphere */
			if (cutype == CU_NURBS) {
				float tmp_cent[3] = {0.f, 0.f, 0.f};
				float tmp_vec[3] = {0.f, 0.f, 1.f};

				nu->pntsu = 5;
				nu->pntsv = 1;
				nu->orderu = 3;
				nu->resolu = cu->resolu;
				nu->resolv = cu->resolv;
				nu->flag = CU_SMOOTH;
				nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6");
				nu->flagu = 0;
				bp = nu->bp;

				for (a = 0; a < 5; a++) {
					bp->f1 = SELECT;
					bp->vec[0] += nurbcircle[a][0] * grid;
					bp->vec[2] += nurbcircle[a][1] * grid;
					if (a & 1) bp->vec[3] = 0.5 * M_SQRT2;
					else bp->vec[3] = 1.0;
					mul_m4_v3(mat, bp->vec);
					bp++;
				}
				nu->flagu = CU_NURB_BEZIER;
				BKE_nurb_knot_calc_u(nu);

				BLI_addtail(editnurb, nu); /* temporal for spin */

				if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
					ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
				else if ((U.flag & USER_ADD_VIEWALIGNED))
					ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
				else
					ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);

				BKE_nurb_knot_calc_v(nu);

				a = nu->pntsu * nu->pntsv;
				bp = nu->bp;
				while (a-- > 0) {
					bp->f1 |= SELECT;
					bp++;
				}
				BLI_remlink(editnurb, nu);
			}
			break;
		case CU_PRIM_DONUT: /* torus */
			if (cutype == CU_NURBS) {
				float tmp_cent[3] = {0.f, 0.f, 0.f};
				float tmp_vec[3] = {0.f, 0.f, 1.f};

				xzproj = 1;
				nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */
				xzproj = 0;
				nu->resolu = cu->resolu;
				nu->resolv = cu->resolv;
				nu->flag = CU_SMOOTH;
				BLI_addtail(editnurb, nu); /* temporal for spin */

				/* same as above */
				if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0)
					ed_editnurb_spin(umat, obedit, tmp_vec, tmp_cent);
				else if ((U.flag & USER_ADD_VIEWALIGNED))
					ed_editnurb_spin(viewmat, obedit, zvec, mat[3]);
				else
					ed_editnurb_spin(umat, obedit, tmp_vec, mat[3]);


				BLI_remlink(editnurb, nu);

				a = nu->pntsu * nu->pntsv;
				bp = nu->bp;
				while (a-- > 0) {
					bp->f1 |= SELECT;
					bp++;
				}

			}
			break;

		default: /* should never happen */
			BLI_assert(!"invalid nurbs type");
			return NULL;
	}

	BLI_assert(nu != NULL);

	if (nu) { /* should always be set */
		nu->flag |= CU_SMOOTH;
		cu->actnu = BLI_listbase_count(editnurb);
		cu->actvert = CU_ACT_NONE;

		BKE_nurb_test2D(nu);
	}

	return nu;
}
示例#28
0
static void rna_Meta_texspace_size_set(PointerRNA *ptr, const float *values)
{
	MetaBall *mb = (MetaBall *)ptr->data;
	
	copy_v3_v3(mb->size, values);
}
/* from/to_world_space : whether from/to particles are in world or hair space
 * from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
 */
static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
                               Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
                               float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
{
	ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys);
	ParticleData *pa, *tpa;
	PTCacheEditPoint *edit_point;
	PTCacheEditKey *ekey;
	BVHTreeFromMesh bvhtree= {NULL};
	MFace *mface = NULL, *mf;
	MEdge *medge = NULL, *me;
	MVert *mvert;
	DerivedMesh *dm, *target_dm;
	int numverts;
	int i, k;
	float from_ob_imat[4][4], to_ob_imat[4][4];
	float from_imat[4][4], to_imat[4][4];

	if (!target_psmd->dm)
		return false;
	if (!psys->part || psys->part->type != PART_HAIR)
		return false;
	if (!target_psys->part || target_psys->part->type != PART_HAIR)
		return false;
	
	edit_point = target_edit ? target_edit->points : NULL;
	
	invert_m4_m4(from_ob_imat, ob->obmat);
	invert_m4_m4(to_ob_imat, target_ob->obmat);
	invert_m4_m4(from_imat, from_mat);
	invert_m4_m4(to_imat, to_mat);
	
	if (target_psmd->dm->deformedOnly) {
		/* we don't want to mess up target_psmd->dm when converting to global coordinates below */
		dm = target_psmd->dm;
	}
	else {
		/* warning: this rebuilds target_psmd->dm! */
		dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH | CD_MASK_MFACE);
	}
	target_dm = target_psmd->dm;
	/* don't modify the original vertices */
	dm = CDDM_copy(dm);

	/* BMESH_ONLY, deform dm may not have tessface */
	DM_ensure_tessface(dm);

	numverts = dm->getNumVerts(dm);
	mvert = dm->getVertArray(dm);

	/* convert to global coordinates */
	for (i=0; i<numverts; i++)
		mul_m4_v3(to_mat, mvert[i].co);

	if (dm->getNumTessFaces(dm) != 0) {
		mface = dm->getTessFaceArray(dm);
		bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6);
	}
	else if (dm->getNumEdges(dm) != 0) {
		medge = dm->getEdgeArray(dm);
		bvhtree_from_mesh_edges(&bvhtree, dm, 0.0, 2, 6);
	}
	else {
		dm->release(dm);
		return false;
	}

	for (i = 0, tpa = target_psys->particles, pa = psys->particles;
	     i < target_psys->totpart;
	     i++, tpa++, pa++) {

		float from_co[3];
		BVHTreeNearest nearest;

		if (from_global)
			mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co);
		else
			mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co);
		mul_m4_v3(from_mat, from_co);

		nearest.index = -1;
		nearest.dist_sq = FLT_MAX;

		BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);

		if (nearest.index == -1) {
			if (G.debug & G_DEBUG)
				printf("No nearest point found for hair root!");
			continue;
		}

		if (mface) {
			float v[4][3];
			
			mf = &mface[nearest.index];

			copy_v3_v3(v[0], mvert[mf->v1].co);
			copy_v3_v3(v[1], mvert[mf->v2].co);
			copy_v3_v3(v[2], mvert[mf->v3].co);
			if (mf->v4) {
				copy_v3_v3(v[3], mvert[mf->v4].co);
				interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
			}
			else
				interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
			tpa->foffset = 0.0f;

			tpa->num = nearest.index;
			tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL);
		}
		else {
			me = &medge[nearest.index];

			tpa->fuv[1] = line_point_factor_v3(nearest.co,
			                                   mvert[me->v1].co,
			                                   mvert[me->v2].co);
			tpa->fuv[0] = 1.0f - tpa->fuv[1];
			tpa->fuv[2] = tpa->fuv[3] = 0.0f;
			tpa->foffset = 0.0f;

			tpa->num = nearest.index;
			tpa->num_dmcache = -1;
		}

		/* translate hair keys */
		{
			HairKey *key, *tkey;
			float hairmat[4][4], imat[4][4];
			float offset[3];
			
			if (to_global)
				copy_m4_m4(imat, target_ob->obmat);
			else {
				/* note: using target_dm here, which is in target_ob object space and has full modifiers */
				psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat);
				invert_m4_m4(imat, hairmat);
			}
			mul_m4_m4m4(imat, imat, to_imat);
			
			/* offset in world space */
			sub_v3_v3v3(offset, nearest.co, from_co);
			
			if (edit_point) {
				for (k=0, key=pa->hair, tkey=tpa->hair, ekey = edit_point->keys; k<tpa->totkey; k++, key++, tkey++, ekey++) {
					float co_orig[3];
					
					if (from_global)
						mul_v3_m4v3(co_orig, from_ob_imat, key->co);
					else
						mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
					mul_m4_v3(from_mat, co_orig);
					
					add_v3_v3v3(tkey->co, co_orig, offset);
					
					mul_m4_v3(imat, tkey->co);
					
					ekey->flag |= PEK_USE_WCO;
				}
				
				edit_point++;
			}
			else {
				for (k=0, key=pa->hair, tkey=tpa->hair; k<tpa->totkey; k++, key++, tkey++) {
					float co_orig[3];
					
					if (from_global)
						mul_v3_m4v3(co_orig, from_ob_imat, key->co);
					else
						mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
					mul_m4_v3(from_mat, co_orig);
					
					add_v3_v3v3(tkey->co, co_orig, offset);
					
					mul_m4_v3(imat, tkey->co);
				}
			}
		}
	}

	free_bvhtree_from_mesh(&bvhtree);
	dm->release(dm);

	psys_free_path_cache(target_psys, target_edit);

	PE_update_object(scene, target_ob, 0);

	return true;
}
示例#30
0
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, &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, &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);
		}
	}

}