コード例 #1
0
ファイル: polyfill2d.c プロジェクト: linkedinyou/blender-git
static bool kdtree2d_isect_tri(
        struct KDTree2D *tree,
        const unsigned int ind[3])
{
	const float *vs[3];
	unsigned int i;
	struct KDRange2D bounds[2] = {
	    {FLT_MAX, -FLT_MAX},
	    {FLT_MAX, -FLT_MAX},
	};
	float tri_center[2] = {0.0f, 0.0f};

	for (i = 0; i < 3; i++) {
		vs[i] = tree->coords[ind[i]];

		add_v2_v2(tri_center, vs[i]);

		CLAMP_MAX(bounds[0].min, vs[i][0]);
		CLAMP_MIN(bounds[0].max, vs[i][0]);
		CLAMP_MAX(bounds[1].min, vs[i][1]);
		CLAMP_MIN(bounds[1].max, vs[i][1]);
	}

	mul_v2_fl(tri_center, 1.0f / 3.0f);

	return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]);
}
コード例 #2
0
ファイル: MOD_normal_edit.c プロジェクト: mgschwan/blensor
static void generate_vert_coordinates(
        DerivedMesh *dm, Object *ob, Object *ob_center, const float offset[3],
        const int num_verts, float (*r_cos)[3], float r_size[3])
{
	float min_co[3], max_co[3];
	float diff[3];
	bool do_diff = false;

	INIT_MINMAX(min_co, max_co);

	dm->getVertCos(dm, r_cos);

	/* Get size (i.e. deformation of the spheroid generating normals), either from target object, or own geometry. */
	if (ob_center) {
		/* Not we are not interested in signs here - they are even troublesome actually, due to security clamping! */
		abs_v3_v3(r_size, ob_center->size);
	}
	else {
		minmax_v3v3_v3_array(min_co, max_co, r_cos, num_verts);
		/* Set size. */
		sub_v3_v3v3(r_size, max_co, min_co);
	}

	/* Error checks - we do not want one or more of our sizes to be null! */
	if (is_zero_v3(r_size)) {
		r_size[0] = r_size[1] = r_size[2] = 1.0f;
	}
	else {
		CLAMP_MIN(r_size[0], FLT_EPSILON);
		CLAMP_MIN(r_size[1], FLT_EPSILON);
		CLAMP_MIN(r_size[2], FLT_EPSILON);
	}

	if (ob_center) {
		float inv_obmat[4][4];

		/* Translate our coordinates so that center of ob_center is at (0, 0, 0). */
		/* Get ob_center (world) coordinates in ob local coordinates.
		 * No need to take into account ob_center's space here, see T44027. */
		invert_m4_m4(inv_obmat, ob->obmat);
		mul_v3_m4v3(diff, inv_obmat, ob_center->obmat[3]);
		negate_v3(diff);

		do_diff = true;
	}
	else if (!is_zero_v3(offset)) {
		negate_v3_v3(diff, offset);

		do_diff = true;
	}
	/* Else, no need to change coordinates! */

	if (do_diff) {
		int i = num_verts;
		while (i--) {
			add_v3_v3(r_cos[i], diff);
		}
	}
}
コード例 #3
0
ファイル: expr_pylike_eval.c プロジェクト: dfelinto/blender
/* Add one operation and track stack usage. */
static ExprOp *parse_add_op(ExprParseState *state, eOpCode code, int stack_delta)
{
  /* track evaluation stack depth */
  state->stack_ptr += stack_delta;
  CLAMP_MIN(state->stack_ptr, 0);
  CLAMP_MIN(state->max_stack, state->stack_ptr);

  /* allocate the new instruction */
  ExprOp *op = parse_alloc_ops(state, 1);
  memset(op, 0, sizeof(ExprOp));
  op->opcode = code;
  return op;
}
コード例 #4
0
/**
* Apply smooth for thickness to stroke point (use pressure)
* \param gps: Stroke to smooth
* \param i: Point index
* \param inf: Amount of smoothing to apply
*/
bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf)
{
	bGPDspoint *ptb = &gps->points[i];

	/* Do nothing if not enough points */
	if (gps->totpoints <= 2) {
		return false;
	}

	/* Compute theoretical optimal value using distances */
	bGPDspoint *pta, *ptc;
	int before = i - 1;
	int after = i + 1;

	CLAMP_MIN(before, 0);
	CLAMP_MAX(after, gps->totpoints - 1);

	pta = &gps->points[before];
	ptc = &gps->points[after];

	/* the optimal value is the corresponding to the interpolation of the pressure
	 * at the distance of point b
	 */
	float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
	float optimal = (1.0f - fac) * pta->pressure + fac * ptc->pressure;

	/* Based on influence factor, blend between original and optimal */
	ptb->pressure = (1.0f - inf) * ptb->pressure + inf * optimal;

	return true;
}
コード例 #5
0
/* cache init */
static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
{
  bGPdata *gpd = (bGPdata *)ob->data;

  GpencilBatchCache *cache = gpencil_batch_get_element(ob);

  if (!cache) {
    cache = MEM_callocN(sizeof(*cache), __func__);
    ob->runtime.gpencil_cache = cache;
  }
  else {
    memset(cache, 0, sizeof(*cache));
  }

  cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd);

  cache->is_dirty = true;

  cache->cache_frame = cfra;

  /* create array of derived frames equal to number of layers */
  cache->tot_layers = BLI_listbase_count(&gpd->layers);
  CLAMP_MIN(cache->tot_layers, 1);
  cache->derived_array = MEM_callocN(sizeof(struct bGPDframe) * cache->tot_layers, "Derived GPF");

  return cache;
}
コード例 #6
0
ファイル: MOD_gpencilmirror.c プロジェクト: dfelinto/blender
static int getDuplicationFactor(GpencilModifierData *md)
{
  MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
  int factor = 1;
  /* create a duplication for each axis */
  for (int xi = 0; xi < 3; ++xi) {
    if (mmd->flag & (GP_MIRROR_AXIS_X << xi)) {
      factor++;
    }
  }
  CLAMP_MIN(factor, 1);

  return factor;
}
コード例 #7
0
ファイル: screen_geometry.c プロジェクト: dfelinto/blender
/**
 * \param bounds_rect: Either window or screen bounds.
 * Used to exclude edges along window/screen edges.
 */
ScrEdge *screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map,
                                                  const rcti *bounds_rect,
                                                  const int mx,
                                                  const int my)
{
  int safety = U.widget_unit / 10;

  CLAMP_MIN(safety, 2);

  for (ScrEdge *se = area_map->edgebase.first; se; se = se->next) {
    if (screen_geom_edge_is_horizontal(se)) {
      if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) {
        short min, max;
        min = MIN2(se->v1->vec.x, se->v2->vec.x);
        max = MAX2(se->v1->vec.x, se->v2->vec.x);

        if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max) {
          return se;
        }
      }
    }
    else {
      if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) {
        short min, max;
        min = MIN2(se->v1->vec.y, se->v2->vec.y);
        max = MAX2(se->v1->vec.y, se->v2->vec.y);

        if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max) {
          return se;
        }
      }
    }
  }

  return NULL;
}
コード例 #8
0
ファイル: armature_update.c プロジェクト: mgschwan/blensor
/* Tag the bones in the chain formed by the given bone for IK */
static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip)
{
	bPoseChannel *pchan, *pchanRoot = NULL;
	bPoseChannel *pchanChain[255];
	bConstraint *con = NULL;
	bSplineIKConstraint *ikData = NULL;
	float boneLengths[255], *jointPoints;
	float totLength = 0.0f;
	bool free_joints = 0;
	int segcount = 0;

	/* find the SplineIK constraint */
	for (con = pchan_tip->constraints.first; con; con = con->next) {
		if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
			ikData = con->data;

			/* target can only be curve */
			if ((ikData->tar == NULL) || (ikData->tar->type != OB_CURVE))
				continue;
			/* skip if disabled */
			if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)))
				continue;

			/* otherwise, constraint is ok... */
			break;
		}
	}
	if (con == NULL)
		return;

	/* make sure that the constraint targets are ok
	 *     - this is a workaround for a depsgraph bug...
	 */
	if (ikData->tar) {
		/* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
		 *       currently for paths to work it needs to go through the bevlist/displist system (ton)
		 */

		/* only happens on reload file, but violates depsgraph still... fix! */
		if (ELEM(NULL,  ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
			BKE_displist_make_curveTypes(scene, ikData->tar, 0);
			
			/* path building may fail in EditMode after removing verts [#33268]*/
			if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
				/* BLI_assert(cu->path != NULL); */
				return;
			}
		}
	}

	/* find the root bone and the chain of bones from the root to the tip
	 * NOTE: this assumes that the bones are connected, but that may not be true... */
	for (pchan = pchan_tip; pchan && (segcount < ikData->chainlen); pchan = pchan->parent, segcount++) {
		/* store this segment in the chain */
		pchanChain[segcount] = pchan;

		/* if performing rebinding, calculate the length of the bone */
		boneLengths[segcount] = pchan->bone->length;
		totLength += boneLengths[segcount];
	}

	if (segcount == 0)
		return;
	else
		pchanRoot = pchanChain[segcount - 1];

	/* perform binding step if required */
	if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) {
		float segmentLen = (1.0f / (float)segcount);
		int i;

		/* setup new empty array for the points list */
		if (ikData->points)
			MEM_freeN(ikData->points);
		ikData->numpoints = ikData->chainlen + 1;
		ikData->points = MEM_mallocN(sizeof(float) * ikData->numpoints, "Spline IK Binding");

		/* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */
		ikData->points[0] = 1.0f;

		/* perform binding of the joints to parametric positions along the curve based
		 * proportion of the total length that each bone occupies
		 */
		for (i = 0; i < segcount; i++) {
			/* 'head' joints, traveling towards the root of the chain
			 *  - 2 methods; the one chosen depends on whether we've got usable lengths
			 */
			if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) {
				/* 1) equi-spaced joints */
				ikData->points[i + 1] = ikData->points[i] - segmentLen;
			}
			else {
				/* 2) to find this point on the curve, we take a step from the previous joint
				 *    a distance given by the proportion that this bone takes
				 */
				ikData->points[i + 1] = ikData->points[i] - (boneLengths[i] / totLength);
			}
		}

		/* spline has now been bound */
		ikData->flag |= CONSTRAINT_SPLINEIK_BOUND;
	}

	/* disallow negative values (happens with float precision) */
	CLAMP_MIN(ikData->points[segcount], 0.0f);

	/* apply corrections for sensitivity to scaling on a copy of the bind points,
	 * since it's easier to determine the positions of all the joints beforehand this way
	 */
	if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) {
		float splineLen, maxScale;
		int i;

		/* make a copy of the points array, that we'll store in the tree
		 *     - although we could just multiply the points on the fly, this approach means that
		 *       we can introduce per-segment stretchiness later if it is necessary
		 */
		jointPoints = MEM_dupallocN(ikData->points);
		free_joints = 1;

		/* get the current length of the curve */
		/* NOTE: this is assumed to be correct even after the curve was resized */
		splineLen = ikData->tar->curve_cache->path->totdist;

		/* calculate the scale factor to multiply all the path values by so that the
		 * bone chain retains its current length, such that
		 *     maxScale * splineLen = totLength
		 */
		maxScale = totLength / splineLen;

		/* apply scaling correction to all of the temporary points */
		/* TODO: this is really not adequate enough on really short chains */
		for (i = 0; i < segcount; i++)
			jointPoints[i] *= maxScale;
	}
	else {
		/* just use the existing points array */
		jointPoints = ikData->points;
		free_joints = 0;
	}

	/* make a new Spline-IK chain, and store it in the IK chains */
	/* TODO: we should check if there is already an IK chain on this, since that would take precedence... */
	{
		/* make new tree */
		tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree");
		tree->type = CONSTRAINT_TYPE_SPLINEIK;

		tree->chainlen = segcount;

		/* copy over the array of links to bones in the chain (from tip to root) */
		tree->chain = MEM_mallocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain");
		memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount);

		/* store reference to joint position array */
		tree->points = jointPoints;
		tree->free_points = free_joints;

		/* store references to different parts of the chain */
		tree->root = pchanRoot;
		tree->con = con;
		tree->ikData = ikData;

		/* AND! link the tree to the root */
		BLI_addtail(&pchanRoot->siktree, tree);
	}

	/* mark root channel having an IK tree */
	pchanRoot->flag |= POSE_IKSPLINE;
}
コード例 #9
0
ファイル: view3d_walk.c プロジェクト: Bforartists/Bforartists
static void walkEvent(bContext *C, wmOperator *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)) {

#ifdef USE_TABLET_SUPPORT
		if (walk->is_cursor_first) {
			/* wait until we get the 'warp' event */
			if ((walk->center_mval[0] == event->mval[0]) &&
			    (walk->center_mval[1] == event->mval[1]))
			{
				walk->is_cursor_first = false;
			}
			else {
				/* note, its possible the system isn't giving us the warp event
				 * ideally we shouldn't have to worry about this, see: T45361 */
				wmWindow *win = CTX_wm_window(C);
				WM_cursor_warp(win,
				               walk->ar->winrct.xmin + walk->center_mval[0],
				               walk->ar->winrct.ymin + walk->center_mval[1]);
			}
			return;
		}

		if ((walk->is_cursor_absolute == false) && WM_event_is_absolute(event)) {
			walk->is_cursor_absolute = true;
			copy_v2_v2_int(walk->prev_mval, event->mval);
			copy_v2_v2_int(walk->center_mval, event->mval);
			/* without this we can't turn 180d */
			CLAMP_MIN(walk->mouse_speed, 4.0f);
		}
#endif  /* USE_TABLET_SUPPORT */


		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;

#ifdef USE_TABLET_SUPPORT
			if (walk->is_cursor_absolute) {
				/* pass */
			}
			else
#endif
			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, op, 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, op, walk, WALK_MODE_FREE);
				}
				else { /* WALK_MODE_FREE */
					walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
				}
				break;
		}
	}
}
コード例 #10
0
static void node_shader_exec_normal_map(
        void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata),
        bNodeStack **in, bNodeStack **out)
{
	if (data) {
		ShadeInput *shi = ((ShaderCallData *)data)->shi;

		NodeShaderNormalMap *nm = node->storage;

		float strength, vecIn[3];
		nodestack_get_vec(&strength, SOCK_FLOAT, in[0]);
		nodestack_get_vec(vecIn, SOCK_VECTOR, in[1]);

		vecIn[0] = -2 * (vecIn[0] - 0.5f);
		vecIn[1] =  2 * (vecIn[1] - 0.5f);
		vecIn[2] =  2 * (vecIn[2] - 0.5f);

		CLAMP_MIN(strength, 0.0f);

		float *N = shi->nmapnorm;
		int uv_index = 0;
		switch (nm->space) {
			case SHD_SPACE_TANGENT:
				if (nm->uv_map[0]) {
					/* find uv map by name */
					for (int i = 0; i < shi->totuv; i++) {
						if (STREQ(shi->uv[i].name, nm->uv_map)) {
							uv_index = i;
							break;
						}
					}
				}
				else {
					uv_index = shi->actuv;
				}

				float *T = shi->tangents[uv_index];

				float B[3];
				cross_v3_v3v3(B, N, T);
				mul_v3_fl(B, T[3]);

				for (int j = 0; j < 3; j++)
					out[0]->vec[j] = vecIn[0] * T[j] + vecIn[1] * B[j] + vecIn[2] * N[j];
				interp_v3_v3v3(out[0]->vec, N, out[0]->vec, strength);
				if (shi->use_world_space_shading) {
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), out[0]->vec);
				}
				break;

			case SHD_SPACE_OBJECT:
			case SHD_SPACE_BLENDER_OBJECT:
				if (shi->use_world_space_shading) {
					mul_mat3_m4_v3((float (*)[4])RE_object_instance_get_matrix(shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB), vecIn);
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), N);
				}
				else
					mul_mat3_m4_v3((float (*)[4])RE_object_instance_get_matrix(shi->obi, RE_OBJECT_INSTANCE_MATRIX_LOCALTOVIEW), vecIn);
				interp_v3_v3v3(out[0]->vec, N, vecIn, strength);
				break;

			case SHD_SPACE_WORLD:
			case SHD_SPACE_BLENDER_WORLD:
				if (shi->use_world_space_shading)
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEWINV_MATRIX), N);
				else
					mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), vecIn);
				interp_v3_v3v3(out[0]->vec, N, vecIn, strength);
				break;
		}
		if (shi->use_world_space_shading) {
			negate_v3(out[0]->vec);
		}
		normalize_v3(out[0]->vec);
	}
}
コード例 #11
0
/**
 * Apply smooth to stroke point
 * \param gps: Stroke to smooth
 * \param i: Point index
 * \param inf: Amount of smoothing to apply
 * \param affect_pressure: Apply smoothing to pressure values too?
 */
bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure)
{
	bGPDspoint *pt = &gps->points[i];
	float pressure = 0.0f;
	float sco[3] = {0.0f};

	/* Do nothing if not enough points to smooth out */
	if (gps->totpoints <= 2) {
		return false;
	}

	/* Only affect endpoints by a fraction of the normal strength,
	 * to prevent the stroke from shrinking too much
	 */
	if ((i == 0) || (i == gps->totpoints - 1)) {
		inf *= 0.1f;
	}

	/* Compute smoothed coordinate by taking the ones nearby */
	/* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
	{
		// XXX: this is hardcoded to look at 2 points on either side of the current one (i.e. 5 items total)
		const int   steps = 2;
		const float average_fac = 1.0f / (float)(steps * 2 + 1);
		int step;

		/* add the point itself */
		madd_v3_v3fl(sco, &pt->x, average_fac);

		if (affect_pressure) {
			pressure += pt->pressure * average_fac;
		}

		/* n-steps before/after current point */
		// XXX: review how the endpoints are treated by this algorithm
		// XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
		for (step = 1; step <= steps; step++) {
			bGPDspoint *pt1, *pt2;
			int before = i - step;
			int after = i + step;

			CLAMP_MIN(before, 0);
			CLAMP_MAX(after, gps->totpoints - 1);

			pt1 = &gps->points[before];
			pt2 = &gps->points[after];

			/* add both these points to the average-sum (s += p[i]/n) */
			madd_v3_v3fl(sco, &pt1->x, average_fac);
			madd_v3_v3fl(sco, &pt2->x, average_fac);

#if 0
			/* XXX: Disabled because get weird result */
			/* do pressure too? */
			if (affect_pressure) {
				pressure += pt1->pressure * average_fac;
				pressure += pt2->pressure * average_fac;
			}
#endif
		}
	}

	/* Based on influence factor, blend between original and optimal smoothed coordinate */
	interp_v3_v3v3(&pt->x, &pt->x, sco, inf);

#if 0
	/* XXX: Disabled because get weird result */
	if (affect_pressure) {
		pt->pressure = pressure;
	}
#endif

	return true;
}
コード例 #12
0
ファイル: expr_pylike_eval.c プロジェクト: dfelinto/blender
/**
 * Evaluate the expression with the given parameters.
 * The order and number of parameters must match the names given to parse.
 */
eExprPyLike_EvalStatus BLI_expr_pylike_eval(ExprPyLike_Parsed *expr,
                                            const double *param_values,
                                            int param_values_len,
                                            double *r_result)
{
  *r_result = 0.0;

  if (!BLI_expr_pylike_is_valid(expr)) {
    return EXPR_PYLIKE_INVALID;
  }

#define FAIL_IF(condition) \
  if (condition) { \
    return EXPR_PYLIKE_FATAL_ERROR; \
  } \
  ((void)0)

  /* Check the stack requirement is at least remotely sane and allocate on the actual stack. */
  FAIL_IF(expr->max_stack <= 0 || expr->max_stack > 1000);

  double *stack = BLI_array_alloca(stack, expr->max_stack);

  /* Evaluate expression. */
  ExprOp *ops = expr->ops;
  int sp = 0, pc;

  feclearexcept(FE_ALL_EXCEPT);

  for (pc = 0; pc >= 0 && pc < expr->ops_count; pc++) {
    switch (ops[pc].opcode) {
      /* Arithmetic */
      case OPCODE_CONST:
        FAIL_IF(sp >= expr->max_stack);
        stack[sp++] = ops[pc].arg.dval;
        break;
      case OPCODE_PARAMETER:
        FAIL_IF(sp >= expr->max_stack || ops[pc].arg.ival >= param_values_len);
        stack[sp++] = param_values[ops[pc].arg.ival];
        break;
      case OPCODE_FUNC1:
        FAIL_IF(sp < 1);
        stack[sp - 1] = ops[pc].arg.func1(stack[sp - 1]);
        break;
      case OPCODE_FUNC2:
        FAIL_IF(sp < 2);
        stack[sp - 2] = ops[pc].arg.func2(stack[sp - 2], stack[sp - 1]);
        sp--;
        break;
      case OPCODE_MIN:
        FAIL_IF(sp < ops[pc].arg.ival);
        for (int j = 1; j < ops[pc].arg.ival; j++, sp--) {
          CLAMP_MAX(stack[sp - 2], stack[sp - 1]);
        }
        break;
      case OPCODE_MAX:
        FAIL_IF(sp < ops[pc].arg.ival);
        for (int j = 1; j < ops[pc].arg.ival; j++, sp--) {
          CLAMP_MIN(stack[sp - 2], stack[sp - 1]);
        }
        break;

      /* Jumps */
      case OPCODE_JMP:
        pc += ops[pc].jmp_offset;
        break;
      case OPCODE_JMP_ELSE:
        FAIL_IF(sp < 1);
        if (!stack[--sp]) {
          pc += ops[pc].jmp_offset;
        }
        break;
      case OPCODE_JMP_OR:
      case OPCODE_JMP_AND:
        FAIL_IF(sp < 1);
        if (!stack[sp - 1] == !(ops[pc].opcode == OPCODE_JMP_OR)) {
          pc += ops[pc].jmp_offset;
        }
        else {
          sp--;
        }
        break;

      /* For chaining comparisons, i.e. "a < b < c" as "a < b and b < c" */
      case OPCODE_CMP_CHAIN:
        FAIL_IF(sp < 2);
        /* If comparison fails, return 0 and jump to end. */
        if (!ops[pc].arg.func2(stack[sp - 2], stack[sp - 1])) {
          stack[sp - 2] = 0.0;
          pc += ops[pc].jmp_offset;
        }
        /* Otherwise keep b on the stack and proceed. */
        else {
          stack[sp - 2] = stack[sp - 1];
        }
        sp--;
        break;

      default:
        return EXPR_PYLIKE_FATAL_ERROR;
    }
  }

  FAIL_IF(sp != 1 || pc != expr->ops_count);

#undef FAIL_IF

  *r_result = stack[0];

  /* Detect floating point evaluation errors. */
  int flags = fetestexcept(FE_DIVBYZERO | FE_INVALID);
  if (flags) {
    return (flags & FE_INVALID) ? EXPR_PYLIKE_MATH_ERROR : EXPR_PYLIKE_DIV_BY_ZERO;
  }

  return EXPR_PYLIKE_SUCCESS;
}
コード例 #13
0
void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
                   const ColorManagedDisplaySettings *display_settings)
{
	int a;
	unsigned int nl, na, nr, ng, nb;
	double divl, diva, divr, divg, divb;
	const unsigned char *display_buffer = NULL;
	unsigned int bin_lum[256] = {0},
	             bin_r[256] = {0},
	             bin_g[256] = {0},
	             bin_b[256] = {0},
	             bin_a[256] = {0};
	int ycc_mode = -1;
	void *cache_handle = NULL;
	struct ColormanageProcessor *cm_processor = NULL;

	if (ibuf->rect == NULL && ibuf->rect_float == NULL) return;

	if (scopes->ok == 1) return;

	if (scopes->hist.ymax == 0.f) scopes->hist.ymax = 1.f;

	/* hmmmm */
	if (!(ELEM(ibuf->channels, 3, 4))) return;

	scopes->hist.channels = 3;
	scopes->hist.x_resolution = 256;

	switch (scopes->wavefrm_mode) {
		case SCOPES_WAVEFRM_RGB:
			ycc_mode = -1;
			break;
		case SCOPES_WAVEFRM_LUMA:
		case SCOPES_WAVEFRM_YCC_JPEG:
			ycc_mode = BLI_YCC_JFIF_0_255;
			break;
		case SCOPES_WAVEFRM_YCC_601:
			ycc_mode = BLI_YCC_ITU_BT601;
			break;
		case SCOPES_WAVEFRM_YCC_709:
			ycc_mode = BLI_YCC_ITU_BT709;
			break;
	}

	/* convert to number of lines with logarithmic scale */
	scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y;
	CLAMP_MIN(scopes->sample_lines, 1);
	
	if (scopes->sample_full)
		scopes->sample_lines = ibuf->y;

	/* scan the image */
	for (a = 0; a < 3; a++) {
		scopes->minmax[a][0] = 25500.0f;
		scopes->minmax[a][1] = -25500.0f;
	}
	
	scopes->waveform_tot = ibuf->x * scopes->sample_lines;
	
	if (scopes->waveform_1)
		MEM_freeN(scopes->waveform_1);
	if (scopes->waveform_2)
		MEM_freeN(scopes->waveform_2);
	if (scopes->waveform_3)
		MEM_freeN(scopes->waveform_3);
	if (scopes->vecscope)
		MEM_freeN(scopes->vecscope);
	
	scopes->waveform_1 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 1");
	scopes->waveform_2 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 2");
	scopes->waveform_3 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3");
	scopes->vecscope = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel");
	
	if (ibuf->rect_float) {
		cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
	}
	else {
		display_buffer = (const unsigned char *)IMB_display_buffer_acquire(
		                                            ibuf, view_settings, display_settings, &cache_handle);
	}

	/* Keep number of threads in sync with the merge parts below. */
	ScopesUpdateData data = {
		.scopes = scopes, . ibuf = ibuf,
		.cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode,
		.bin_lum = bin_lum, .bin_r = bin_r, .bin_g = bin_g, .bin_b = bin_b, .bin_a = bin_a,
	};
	ScopesUpdateDataChunk data_chunk = {0};
	INIT_MINMAX(data_chunk.min, data_chunk.max);

	BLI_task_parallel_range_finalize(0, ibuf->y, &data, &data_chunk, sizeof(data_chunk),
	                                 scopes_update_cb, scopes_update_finalize, ibuf->y > 256, false);

	/* test for nicer distribution even - non standard, leave it out for a while */
#if 0
	for (a = 0; a < 256; a++) {
		bin_lum[a] = sqrt (bin_lum[a]);
		bin_r[a] = sqrt(bin_r[a]);
		bin_g[a] = sqrt(bin_g[a]);
		bin_b[a] = sqrt(bin_b[a]);
		bin_a[a] = sqrt(bin_a[a]);
	}
#endif
	
	/* convert hist data to float (proportional to max count) */
	nl = na = nr = nb = ng = 0;
	for (a = 0; a < 256; a++) {
		if (bin_lum[a] > nl) nl = bin_lum[a];
		if (bin_r[a]   > nr) nr = bin_r[a];
		if (bin_g[a]   > ng) ng = bin_g[a];
		if (bin_b[a]   > nb) nb = bin_b[a];
		if (bin_a[a]   > na) na = bin_a[a];
	}
	divl = nl ? 1.0 / (double)nl : 1.0;
	diva = na ? 1.0 / (double)na : 1.0;
	divr = nr ? 1.0 / (double)nr : 1.0;
	divg = ng ? 1.0 / (double)ng : 1.0;
	divb = nb ? 1.0 / (double)nb : 1.0;
	
	for (a = 0; a < 256; a++) {
		scopes->hist.data_luma[a] = bin_lum[a] * divl;
		scopes->hist.data_r[a] = bin_r[a] * divr;
		scopes->hist.data_g[a] = bin_g[a] * divg;
		scopes->hist.data_b[a] = bin_b[a] * divb;
		scopes->hist.data_a[a] = bin_a[a] * diva;
	}

	if (cm_processor)
		IMB_colormanagement_processor_free(cm_processor);
	if (cache_handle)
		IMB_display_buffer_release(cache_handle);
	
	scopes->ok = 1;
}
コード例 #14
0
ファイル: file_draw.c プロジェクト: Rojuinex/Blender
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d. 
 * The controls are laid out as follows:
 *
 * -------------------------------------------
 * | Directory input               | execute |
 * -------------------------------------------
 * | Filename input        | + | - | cancel  |
 * -------------------------------------------
 *
 * The input widgets will stretch to fill any excess space.
 * When there isn't enough space for all controls to be shown, they are
 * hidden in this order: x/-, execute/cancel, input widgets.
 */
void file_draw_buttons(const bContext *C, ARegion *ar)
{
	/* Button layout. */
	const int max_x      = ar->winx - 10;
	const int line1_y    = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
	const int line2_y    = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
	const int input_minw = 20;
	const int btn_h      = UI_UNIT_Y;
	const int btn_fn_w   = UI_UNIT_X;
	const int btn_minw   = 80;
	const int btn_margin = 20;
	const int separator  = 4;

	/* Additional locals. */
	char uiblockstr[32];
	int loadbutton;
	int fnumbuttons;
	int min_x       = 10;
	int chan_offs   = 0;
	int available_w = max_x - min_x;
	int line1_w     = available_w;
	int line2_w     = available_w;
	
	uiBut *but;
	uiBlock *block;
	SpaceFile *sfile  = CTX_wm_space_file(C);
	FileSelectParams *params = ED_fileselect_get_params(sfile);
	ARegion *artmp;
	const bool is_browse_only = (sfile->op == NULL);
	
	/* Initialize UI block. */
	BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
	block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);

	/* exception to make space for collapsed region icon */
	for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
		if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) {
			chan_offs = 16;
			min_x += chan_offs;
			available_w -= chan_offs;
		}
	}

	/* Is there enough space for the execute / cancel buttons? */


	if (is_browse_only) {
		loadbutton = 0;
	}
	else {
		const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
		loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
		CLAMP_MIN(loadbutton, btn_minw);
		if (available_w <= loadbutton + separator + input_minw) {
			loadbutton = 0;
		}
	}

	if (loadbutton) {
		line1_w -= (loadbutton + separator);
		line2_w  = line1_w;
	}

	/* Is there enough space for file number increment/decrement buttons? */
	fnumbuttons = 2 * btn_fn_w;
	if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) {
		fnumbuttons = 0;
	}
	else {
		line2_w -= (fnumbuttons + separator);
	}

	/* Text input fields for directory and file. */
	if (available_w > 0) {
		const struct direntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL;
		int overwrite_alert = file_draw_check_exists(sfile);
		const bool is_active_dir = file && file->path && BLI_is_dir(file->path);

		/* callbacks for operator check functions */
		UI_block_func_set(block, file_draw_check_cb, NULL, NULL);

		but = uiDefBut(block, UI_BTYPE_TEXT, -1, "",
		               min_x, line1_y, line1_w - chan_offs, btn_h,
		               params->dir, 0.0, (float)FILE_MAX, 0, 0,
		               TIP_("File path"));
		UI_but_func_complete_set(but, autocomplete_directory, NULL);
		UI_but_flag_enable(but, UI_BUT_NO_UTF8);
		UI_but_flag_disable(but, UI_BUT_UNDO);
		UI_but_funcN_set(but, file_directory_enter_handle, NULL, but);

		/* TODO, directory editing is non-functional while a library is loaded
		 * until this is properly supported just disable it. */
		if (sfile->files && filelist_lib(sfile->files))
			UI_but_flag_enable(but, UI_BUT_DISABLED);

		if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
			but = uiDefBut(block, UI_BTYPE_TEXT, -1, "",
			               min_x, line2_y, line2_w - chan_offs, btn_h,
			               is_active_dir ? (char *)"" : params->file,
			               0.0, (float)FILE_MAXFILE, 0, 0,
			               TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
			UI_but_func_complete_set(but, autocomplete_file, NULL);
			UI_but_flag_enable(but, UI_BUT_NO_UTF8);
			UI_but_flag_disable(but, UI_BUT_UNDO);
			/* silly workaround calling NFunc to ensure this does not get called
			 * immediate ui_apply_but_func but only after button deactivates */
			UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);

			/* check if this overrides a file and if the operator option is used */
			if (overwrite_alert) {
				UI_but_flag_enable(but, UI_BUT_REDALERT);
			}
		}
		
		/* clear func */
		UI_block_func_set(block, NULL, NULL, NULL);
	}
	
	/* Filename number increment / decrement buttons. */
	if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
		UI_block_align_begin(block);
		but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMOUT,
		                    min_x + line2_w + separator - chan_offs, line2_y,
		                    btn_fn_w, btn_h,
		                    TIP_("Decrement the filename number"));
		RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1);

		but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMIN,
		                    min_x + line2_w + separator + btn_fn_w - chan_offs, line2_y,
		                    btn_fn_w, btn_h,
		                    TIP_("Increment the filename number"));
		RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1);
		UI_block_align_end(block);
	}
	
	/* Execute / cancel buttons. */
	if (loadbutton) {
		const struct direntry *file = filelist_file(sfile->files, params->active_file);
		const char *str_exec = (file && file->path && BLI_is_dir(file->path)) ?
		                        /* params->title is already translated! */
		                        IFACE_("Open Directory") : params->title;

		uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, str_exec,
		          max_x - loadbutton, line1_y, loadbutton, btn_h, "");
		uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"),
		          max_x - loadbutton, line2_y, loadbutton, btn_h, "");
	}
	
	UI_block_end(C, block);
	UI_block_draw(C, block);
}