/* note; only does current curvemap! */ void curvemapping_changed(CurveMapping *cumap, int rem_doubles) { CurveMap *cuma = cumap->cm + cumap->cur; CurveMapPoint *cmp = cuma->curve; rctf *clipr = &cumap->clipr; float thresh = 0.01f * BLI_rctf_size_x(clipr); float dx = 0.0f, dy = 0.0f; int a; cumap->changed_timestamp++; /* clamp with clip */ if (cumap->flag & CUMA_DO_CLIP) { for (a = 0; a < cuma->totpoint; a++) { if (cmp[a].flag & CUMA_SELECT) { if (cmp[a].x < clipr->xmin) dx = min_ff(dx, cmp[a].x - clipr->xmin); else if (cmp[a].x > clipr->xmax) dx = max_ff(dx, cmp[a].x - clipr->xmax); if (cmp[a].y < clipr->ymin) dy = min_ff(dy, cmp[a].y - clipr->ymin); else if (cmp[a].y > clipr->ymax) dy = max_ff(dy, cmp[a].y - clipr->ymax); } } for (a = 0; a < cuma->totpoint; a++) { if (cmp[a].flag & CUMA_SELECT) { cmp[a].x -= dx; cmp[a].y -= dy; } } } qsort(cmp, cuma->totpoint, sizeof(CurveMapPoint), sort_curvepoints); /* remove doubles, threshold set on 1% of default range */ if (rem_doubles && cuma->totpoint > 2) { for (a = 0; a < cuma->totpoint - 1; a++) { dx = cmp[a].x - cmp[a + 1].x; dy = cmp[a].y - cmp[a + 1].y; if (sqrtf(dx * dx + dy * dy) < thresh) { if (a == 0) { cmp[a + 1].flag |= CUMA_VECTOR; if (cmp[a + 1].flag & CUMA_SELECT) cmp[a].flag |= CUMA_SELECT; } else { cmp[a].flag |= CUMA_VECTOR; if (cmp[a].flag & CUMA_SELECT) cmp[a + 1].flag |= CUMA_SELECT; } break; /* we assume 1 deletion per edit is ok */ } } if (a != cuma->totpoint - 1) curvemap_remove(cuma, 2); } curvemap_make_table(cuma, clipr); }
void MixDarkenOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float inputColor1[4]; float inputColor2[4]; float inputValue[4]; this->m_inputValueOperation->readSampled(inputValue, x, y, sampler); this->m_inputColor1Operation->readSampled(inputColor1, x, y, sampler); this->m_inputColor2Operation->readSampled(inputColor2, x, y, sampler); float value = inputValue[0]; if (this->useValueAlphaMultiply()) { value *= inputColor2[3]; } float valuem = 1.0f - value; output[0] = min_ff(inputColor1[0], inputColor2[0]) * value + inputColor1[0] * valuem; output[1] = min_ff(inputColor1[1], inputColor2[1]) * value + inputColor1[1] * valuem; output[2] = min_ff(inputColor1[2], inputColor2[2]) * value + inputColor1[2] * valuem; output[3] = inputColor1[3]; clampIfNeeded(output); }
void curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy) { int a; float clipminx, clipminy, clipmaxx, clipmaxy; cumap->flag = CUMA_DO_CLIP; if (tot == 4) cumap->cur = 3; /* rhms, hack for 'col' curve? */ clipminx = min_ff(minx, maxx); clipminy = min_ff(miny, maxy); clipmaxx = max_ff(minx, maxx); clipmaxy = max_ff(miny, maxy); BLI_rctf_init(&cumap->curr, clipminx, clipmaxx, clipminy, clipmaxy); cumap->clipr = cumap->curr; cumap->white[0] = cumap->white[1] = cumap->white[2] = 1.0f; cumap->bwmul[0] = cumap->bwmul[1] = cumap->bwmul[2] = 1.0f; for (a = 0; a < tot; a++) { cumap->cm[a].flag = CUMA_EXTEND_EXTRAPOLATE; cumap->cm[a].totpoint = 2; cumap->cm[a].curve = MEM_callocN(2 * sizeof(CurveMapPoint), "curve points"); cumap->cm[a].curve[0].x = minx; cumap->cm[a].curve[0].y = miny; cumap->cm[a].curve[1].x = maxx; cumap->cm[a].curve[1].y = maxy; } cumap->changed_timestamp = 0; }
static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy) { /* get bounding box of underlying dm */ int v, totvert = dm->getNumVerts(dm); float min[3], max[3], delta[3]; MVert *mvert = dm->getVertDataArray(dm, 0); copy_v3_v3(min, mvert->co); copy_v3_v3(max, mvert->co); for (v = 1; v < totvert; v++, mvert++) { min[0] = min_ff(min[0], mvert->co[0]); min[1] = min_ff(min[1], mvert->co[1]); min[2] = min_ff(min[2], mvert->co[2]); max[0] = max_ff(max[0], mvert->co[0]); max[1] = max_ff(max[1], mvert->co[1]); max[2] = max_ff(max[2], mvert->co[2]); } sub_v3_v3v3(delta, max, min); *sx = delta[0]; *sy = delta[1]; *ox = min[0]; *oy = min[1]; }
static void make_box_union(const BoundBox *a, const Box *b, Box *r_out) { r_out->min[0] = min_ff(a->vec[0][0], b->min[0]); r_out->min[1] = min_ff(a->vec[0][1], b->min[1]); r_out->min[2] = min_ff(a->vec[0][2], b->min[2]); r_out->max[0] = max_ff(a->vec[6][0], b->max[0]); r_out->max[1] = max_ff(a->vec[6][1], b->max[1]); r_out->max[2] = max_ff(a->vec[6][2], b->max[2]); }
/** * \return The best angle for fitting the convex hull to an axis aligned bounding box. * * Intended to be used with #BLI_convexhull_2d * * \param points Orded hull points * (result of #BLI_convexhull_2d mapped to a contiguous array). * * \note we could return the index of the best edge too if its needed. */ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n) { unsigned int i, i_prev; float area_best = FLT_MAX; float angle_best = 0.0f; i_prev = n - 1; for (i = 0; i < n; i++) { const float *ev_a = points_hull[i]; const float *ev_b = points_hull[i_prev]; float dvec[2]; sub_v2_v2v2(dvec, ev_a, ev_b); if (normalize_v2(dvec) != 0.0f) { float mat[2][2]; float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; unsigned int j; const float angle = atan2f(dvec[0], dvec[1]); float area; angle_to_mat2(mat, angle); for (j = 0; j < n; j++) { float tvec[2]; mul_v2_m2v2(tvec, mat, points_hull[j]); min[0] = min_ff(min[0], tvec[0]); min[1] = min_ff(min[1], tvec[1]); max[0] = max_ff(max[0], tvec[0]); max[1] = max_ff(max[1], tvec[1]); area = (max[0] - min[0]) * (max[1] - min[1]); if (area > area_best) { break; } } if (area < area_best) { area_best = area; angle_best = angle; } } i_prev = i; } return angle_best; }
static int view_all_exec(bContext *C, wmOperator *op) { SpaceClip *sc; ARegion *ar; int w, h, width, height; float aspx, aspy; int fit_view = RNA_boolean_get(op->ptr, "fit_view"); float zoomx, zoomy; /* retrieve state */ sc = CTX_wm_space_clip(C); ar = CTX_wm_region(C); ED_space_clip_get_size(sc, &w, &h); ED_space_clip_get_aspect(sc, &aspx, &aspy); w = w * aspx; h = h * aspy; /* check if the image will fit in the image with zoom == 1 */ width = BLI_rcti_size_x(&ar->winrct) + 1; height = BLI_rcti_size_y(&ar->winrct) + 1; if (fit_view) { const int margin = 5; /* margin from border */ zoomx = (float) width / (w + 2 * margin); zoomy = (float) height / (h + 2 * margin); sclip_zoom_set(C, min_ff(zoomx, zoomy), NULL); } else { if ((w >= width || h >= height) && (width > 0 && height > 0)) { zoomx = (float) width / w; zoomy = (float) height / h; /* find the zoom value that will fit the image in the image space */ sclip_zoom_set(C, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL); } else sclip_zoom_set(C, 1.0f, NULL); } sc->xof = sc->yof = 0.0f; ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; }
static void object_warp_transverts_minmax_x(TransVertStore *tvs, float mat_view[4][4], const float center_view[3], float *r_min, float *r_max) { /* no need to apply translation and cursor offset for every vertex, delay this */ const float x_ofs = (mat_view[3][0] - center_view[0]); float min = FLT_MAX, max = -FLT_MAX; TransVert *tv; int i; tv = tvs->transverts; for (i = 0; i < tvs->transverts_tot; i++, tv++) { float val; /* convert objectspace->viewspace */ val = dot_m4_v3_row_x(mat_view, tv->loc); min = min_ff(min, val); max = max_ff(max, val); } *r_min = min + x_ofs; *r_max = max + x_ofs; }
void IMB_buffer_float_clamp(float *buf, int width, int height) { int i, total = width * height * 4; for (i = 0; i < total; i++) { buf[i] = min_ff(1.0, buf[i]); } }
void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> * /*clKernelsToCleanUp*/) { cl_kernel defocusKernel = device->COM_clCreateKernel("defocusKernel", NULL); cl_int step = this->getStep(); cl_int maxBlur; cl_float threshold = this->m_threshold; MemoryBuffer *sizeMemoryBuffer = this->m_inputSizeProgram->getInputMemoryBuffer(inputMemoryBuffers); const float max_dim = max(m_width, m_height); cl_float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; maxBlur = (cl_int)min_ff(sizeMemoryBuffer->getMaximumValue() * scalar, (float)this->m_maxBlur); device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 1, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram); device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 2, 4, clMemToCleanUp, inputMemoryBuffers, this->m_inputSizeProgram); device->COM_clAttachOutputMemoryBufferToKernelParameter(defocusKernel, 3, clOutputBuffer); device->COM_clAttachMemoryBufferOffsetToKernelParameter(defocusKernel, 5, outputMemoryBuffer); clSetKernelArg(defocusKernel, 6, sizeof(cl_int), &step); clSetKernelArg(defocusKernel, 7, sizeof(cl_int), &maxBlur); clSetKernelArg(defocusKernel, 8, sizeof(cl_float), &threshold); clSetKernelArg(defocusKernel, 9, sizeof(cl_float), &scalar); device->COM_clAttachSizeToKernelParameter(defocusKernel, 10, this); device->COM_clEnqueueRange(defocusKernel, outputMemoryBuffer, 11, this); }
static void cloth_record_result(ClothModifierData *clmd, ImplicitSolverResult *result, int steps) { ClothSolverResult *sres = clmd->solver_result; if (sres->status) { /* already initialized ? */ /* error only makes sense for successful iterations */ if (result->status == BPH_SOLVER_SUCCESS) { sres->min_error = min_ff(sres->min_error, result->error); sres->max_error = max_ff(sres->max_error, result->error); sres->avg_error += result->error / (float)steps; } sres->min_iterations = min_ii(sres->min_iterations, result->iterations); sres->max_iterations = max_ii(sres->max_iterations, result->iterations); sres->avg_iterations += (float)result->iterations / (float)steps; } else { /* error only makes sense for successful iterations */ if (result->status == BPH_SOLVER_SUCCESS) { sres->min_error = sres->max_error = result->error; sres->avg_error += result->error / (float)steps; } sres->min_iterations = sres->max_iterations = result->iterations; sres->avg_iterations += (float)result->iterations / (float)steps; } sres->status |= result->status; }
void ScreenLensDistortionOperation::updateVariables(float distortion, float dispersion) { m_k[1] = max_ff(min_ff(distortion, 1.0f), -0.999f); // smaller dispersion range for somewhat more control float d = 0.25f * max_ff(min_ff(dispersion, 1.0f), 0.0f); m_k[0] = max_ff(min_ff((m_k[1] + d), 1.0f), -0.999f); m_k[2] = max_ff(min_ff((m_k[1] - d), 1.0f), -0.999f); m_maxk = max_fff(m_k[0], m_k[1], m_k[2]); m_sc = (m_fit && (m_maxk > 0.0f)) ? (1.0f / (1.0f + 2.0f * m_maxk)) : (1.0f / (1.0f + m_maxk)); m_dk4[0] = 4.0f * (m_k[1] - m_k[0]); m_dk4[1] = 4.0f * (m_k[2] - m_k[1]); m_dk4[2] = 0.0f; /* unused */ mul_v3_v3fl(m_k4, m_k, 4.0f); }
/* Expand the bounding box to include a new coordinate */ void BB_expand(BB *bb, const float co[3]) { int i; for (i = 0; i < 3; ++i) { bb->bmin[i] = min_ff(bb->bmin[i], co[i]); bb->bmax[i] = max_ff(bb->bmax[i], co[i]); } }
/** * \return The best angle for fitting the convex hull to an axis aligned bounding box. * * Intended to be used with #BLI_convexhull_2d * * \param points_hull Ordered hull points * (result of #BLI_convexhull_2d mapped to a contiguous array). * * \note we could return the index of the best edge too if its needed. */ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n) { unsigned int i, i_prev; float area_best = FLT_MAX; float dvec_best[2]; /* best angle, delay atan2 */ i_prev = n - 1; for (i = 0; i < n; i++) { const float *ev_a = points_hull[i]; const float *ev_b = points_hull[i_prev]; float dvec[2]; /* 2d rotation matrix */ sub_v2_v2v2(dvec, ev_a, ev_b); if (normalize_v2(dvec) != 0.0f) { /* rotation matrix */ float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; unsigned int j; float area; for (j = 0; j < n; j++) { float tvec[2]; mul_v2_v2_cw(tvec, dvec, points_hull[j]); min[0] = min_ff(min[0], tvec[0]); min[1] = min_ff(min[1], tvec[1]); max[0] = max_ff(max[0], tvec[0]); max[1] = max_ff(max[1], tvec[1]); area = (max[0] - min[0]) * (max[1] - min[1]); if (area > area_best) { break; } } if (area < area_best) { area_best = area; copy_v2_v2(dvec_best, dvec); } } i_prev = i; } return (area_best != FLT_MAX) ? atan2f(dvec_best[0], dvec_best[1]) : 0.0f; }
/* Expand the bounding box to include another bounding box */ void BB_expand_with_bb(BB *bb, BB *bb2) { int i; for (i = 0; i < 3; ++i) { bb->bmin[i] = min_ff(bb->bmin[i], bb2->bmin[i]); bb->bmax[i] = max_ff(bb->bmax[i], bb2->bmax[i]); } }
/* clamp handles to defined size in pixel space */ static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx) { const float minhandle = pixelx * SEQ_HANDLE_SIZE_MIN; const float maxhandle = pixelx * SEQ_HANDLE_SIZE_MAX; float size = CLAMPIS(seq->handsize, minhandle, maxhandle); /* ensure we're not greater than half width */ return min_ff(size, ((float)(seq->enddisp - seq->startdisp) / 2.0f) / pixelx); }
static void calc_ray_shift(rcti *rect, float x, float y, const float source[2], float ray_length) { float co[2] = {(float)x, (float)y}; float dir[2], dist; /* move (x,y) vector toward the source by ray_length distance */ sub_v2_v2v2(dir, co, source); dist = normalize_v2(dir); mul_v2_fl(dir, min_ff(dist, ray_length)); sub_v2_v2(co, dir); int ico[2] = {(int)co[0], (int)co[1]}; BLI_rcti_do_minmax_v(rect, ico); }
static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y) { BakeShade *bs = handle; float disp; if (R.r.bake_flag & R_BAKE_NORMALIZE) { if (R.r.bake_maxdist) disp = (dist + R.r.bake_maxdist) / (R.r.bake_maxdist * 2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/ else disp = dist; } else { disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/ } if (bs->displacement_buffer) { float *displacement = bs->displacement_buffer + (bs->rectx * y + x); *displacement = disp; bs->displacement_min = min_ff(bs->displacement_min, disp); bs->displacement_max = max_ff(bs->displacement_max, disp); } if (bs->rect_float && !bs->vcol) { float *col = bs->rect_float + 4 * (bs->rectx * y + x); col[0] = col[1] = col[2] = disp; col[3] = 1.0f; } else { /* Target is char (LDR). */ unsigned char col[4]; col[0] = col[1] = col[2] = FTOCHAR(disp); col[3] = 255; if (bs->vcol) { /* Vertex color baking. Vcol has no useful alpha channel (it exists * but is used only for vertex painting). */ bs->vcol->r = col[0]; bs->vcol->g = col[1]; bs->vcol->b = col[2]; } else { char *imcol = (char *)(bs->rect + bs->rectx * y + x); copy_v4_v4_char((char *)imcol, (char *)col); } } if (bs->rect_mask) { bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED; } }
void ProjectorLensDistortionOperation::updateDispersion() { if (this->m_dispersionAvailable) { return; } this->lockMutex(); if (!this->m_dispersionAvailable) { float result[4]; this->getInputSocketReader(1)->readSampled(result, 1, 1, COM_PS_NEAREST); this->m_dispersion = result[0]; this->m_kr = 0.25f * max_ff(min_ff(this->m_dispersion, 1.0f), 0.0f); this->m_kr2 = this->m_kr * 20; this->m_dispersionAvailable = true; } this->unlockMutex(); }
static float get_shortest_pattern_side(MovieTrackingMarker *marker) { int i, next; float len_sq = FLT_MAX; for (i = 0; i < 4; i++) { float cur_len; next = (i + 1) % 4; cur_len = len_squared_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]); len_sq = min_ff(cur_len, len_sq); } return sqrtf(len_sq); }
static void getArrowEndPoint(const int width, const int height, const float zoom, const float start_corner[2], const float end_corner[2], float end_point[2]) { float direction[2]; float max_length; sub_v2_v2v2(direction, end_corner, start_corner); direction[0] *= width; direction[1] *= height; max_length = normalize_v2(direction); mul_v2_fl(direction, min_ff(32.0f / zoom, max_length)); direction[0] /= width; direction[1] /= height; add_v2_v2v2(end_point, start_corner, direction); }
/* Note this modifies nos_new in-place. */ static void mix_normals( const float mix_factor, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup, const float mix_limit, const short mix_mode, const int num_verts, MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], const int num_loops) { /* Mix with org normals... */ float *facs = NULL, *wfac; float (*no_new)[3], (*no_old)[3]; int i; if (dvert) { facs = MEM_malloc_arrayN((size_t)num_loops, sizeof(*facs), __func__); BKE_defvert_extract_vgroup_to_loopweights( dvert, defgrp_index, num_verts, mloop, num_loops, facs, use_invert_vgroup); } for (i = num_loops, no_new = nos_new, no_old = nos_old, wfac = facs; i--; no_new++, no_old++, wfac++) { const float fac = facs ? *wfac * mix_factor : mix_factor; switch (mix_mode) { case MOD_NORMALEDIT_MIX_ADD: add_v3_v3(*no_new, *no_old); normalize_v3(*no_new); break; case MOD_NORMALEDIT_MIX_SUB: sub_v3_v3(*no_new, *no_old); normalize_v3(*no_new); break; case MOD_NORMALEDIT_MIX_MUL: mul_v3_v3(*no_new, *no_old); normalize_v3(*no_new); break; case MOD_NORMALEDIT_MIX_COPY: break; } interp_v3_v3v3_slerp_safe( *no_new, *no_old, *no_new, (mix_limit < (float)M_PI) ? min_ff(fac, mix_limit / angle_v3v3(*no_new, *no_old)) : fac); } MEM_SAFE_FREE(facs); }
bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit) { SpaceClip *sc = CTX_wm_space_clip(C); int w, h, frame_width, frame_height; float min[2], max[2]; ED_space_clip_get_size(sc, &frame_width, &frame_height); if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) return false; if (!selected_boundbox(sc, min, max)) return false; /* center view */ clip_view_center_to_point(sc, (max[0] + min[0]) / (2 * frame_width), (max[1] + min[1]) / (2 * frame_height)); w = max[0] - min[0]; h = max[1] - min[1]; /* set zoom to see all selection */ if (w > 0 && h > 0) { int width, height; float zoomx, zoomy, newzoom, aspx, aspy; ED_space_clip_get_aspect(sc, &aspx, &aspy); width = BLI_rcti_size_x(&ar->winrct) + 1; height = BLI_rcti_size_y(&ar->winrct) + 1; zoomx = (float)width / w / aspx; zoomy = (float)height / h / aspy; newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)); if (fit || sc->zoom > newzoom) sc->zoom = newzoom; } return true; }
static void voronoi_finishEdge(VoronoiProcess *process, VoronoiParabola *parabola) { float mx; if (parabola->is_leaf) { MEM_freeN(parabola); return; } if (parabola->edge->direction[0] > 0.0f) mx = max_ff(process->width, parabola->edge->start[0] + 10); else mx = min_ff(0.0f, parabola->edge->start[0] - 10.0f); parabola->edge->end[0] = mx; parabola->edge->end[1] = mx * parabola->edge->f + parabola->edge->g; voronoi_finishEdge(process, parabola->left); voronoi_finishEdge(process, parabola->right); MEM_freeN(parabola); }
static float voronoi_getXOfEdge(VoronoiProcess *process, VoronoiParabola *par, float y) { VoronoiParabola *left = voronoiParabola_getLeftChild(par); VoronoiParabola *right = voronoiParabola_getRightChild(par); float p[2], r[2]; float dp, a1, b1, c1, a2, b2, c2, a, b, c, disc, ry, x1, x2; float ly = process->current_y; copy_v2_v2(p, left->site); copy_v2_v2(r, right->site); dp = 2.0f * (p[1] - y); a1 = 1.0f / dp; b1 = -2.0f * p[0] / dp; c1 = y + dp / 4 + p[0] * p[0] / dp; dp = 2.0f * (r[1] - y); a2 = 1.0f / dp; b2 = -2.0f * r[0] / dp; c2 = ly + dp / 4 + r[0] * r[0] / dp; a = a1 - a2; b = b1 - b2; c = c1 - c2; disc = b * b - 4 * a * c; x1 = (-b + sqrtf(disc)) / (2 * a); x2 = (-b - sqrtf(disc)) / (2 * a); if (p[1] < r[1]) { ry = max_ff(x1, x2); } else { ry = min_ff(x1, x2); } return ry; }
static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); Image *ima; ImBuf *ibuf; const float pad = 32.0f; void *lock; float facx, facy; ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf == NULL) { BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } facx = 1.0f * (ar->sizex - pad) / (ibuf->x * snode->zoom); facy = 1.0f * (ar->sizey - pad) / (ibuf->y * snode->zoom); BKE_image_release_ibuf(ima, ibuf, lock); snode->zoom *= min_ff(facx, facy); snode->xof = 0; snode->yof = 0; ED_region_tag_redraw(ar); WM_main_add_notifier(NC_NODE | ND_DISPLAY, NULL); return OPERATOR_FINISHED; }
void LuminanceMatteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float inColor[4]; this->m_inputImageProgram->readSampled(inColor, x, y, sampler); const float high = this->m_settings->t1; const float low = this->m_settings->t2; const float luminance = IMB_colormanagement_get_luminance(inColor); float alpha; /* one line thread-friend algorithm: * output[0] = min(inputValue[3], min(1.0f, max(0.0f, ((luminance - low) / (high - low)))); */ /* test range */ if (luminance > high) { alpha = 1.0f; } else if (luminance < low) { alpha = 0.0f; } else { /*blend */ alpha = (luminance - low) / (high - low); } /* store matte(alpha) value in [0] to go with * COM_SetAlphaOperation and the Value output */ /* don't make something that was more transparent less transparent */ output[0] = min_ff(alpha, inColor[3]); }
ScatterSettings *scatter_settings_new(float refl, float radius, float ior, float reflfac, float frontweight, float backweight) { ScatterSettings *ss; ss= MEM_callocN(sizeof(ScatterSettings), "ScatterSettings"); /* see [1] and [3] for these formulas */ ss->eta= ior; ss->Fdr= -1.440f/ior*ior + 0.710f/ior + 0.668f + 0.0636f*ior; ss->A= (1.0f + ss->Fdr)/(1.0f - ss->Fdr); ss->ld= radius; ss->ro= min_ff(refl, 0.999f); ss->color= ss->ro*reflfac + (1.0f-reflfac); ss->alpha_= compute_reduced_albedo(ss); ss->sigma= 1.0f/ss->ld; ss->sigma_t_= ss->sigma/sqrtf(3.0f*(1.0f - ss->alpha_)); ss->sigma_s_= ss->alpha_*ss->sigma_t_; ss->sigma_a= ss->sigma_t_ - ss->sigma_s_; ss->D= 1.0f/(3.0f*ss->sigma_t_); ss->zr= 1.0f/ss->sigma_t_; ss->zv= ss->zr + 4.0f*ss->A*ss->D; ss->invsigma_t_= 1.0f/ss->sigma_t_; ss->frontweight= frontweight; ss->backweight= backweight; /* precompute a table of Rd values for quick lookup */ build_Rd_table(ss); return ss; }
/* Evaluate spline IK for a given bone */ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, int index, float ctime) { bSplineIKConstraint *ikData = tree->ikData; float poseHead[3], poseTail[3], poseMat[4][4]; float splineVec[3], scaleFac, radius = 1.0f; /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); copy_v3_v3(poseHead, pchan->pose_head); copy_v3_v3(poseTail, pchan->pose_tail); /* step 1: determine the positions for the endpoints of the bone */ { float vec[4], dir[3], rad; float tailBlendFac = 1.0f; /* determine if the bone should still be affected by SplineIK */ if (tree->points[index + 1] >= 1.0f) { /* spline doesn't affect the bone anymore, so done... */ pchan->flag |= POSE_DONE; return; } else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) { /* blending factor depends on the amount of the bone still left on the chain */ tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]); } /* tail endpoint */ if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) { /* apply curve's object-mode transforms to the position * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) */ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) mul_m4_v3(ikData->tar->obmat, vec); /* convert the position to pose-space, then store it */ mul_m4_v3(ob->imat, vec); interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac); /* set the new radius */ radius = rad; } /* head endpoint */ if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) { /* apply curve's object-mode transforms to the position * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) */ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) mul_m4_v3(ikData->tar->obmat, vec); /* store the position, and convert it to pose space */ mul_m4_v3(ob->imat, vec); copy_v3_v3(poseHead, vec); /* set the new radius (it should be the average value) */ radius = (radius + rad) / 2; } } /* step 2: determine the implied transform from these endpoints * - splineVec: the vector direction that the spline applies on the bone * - scaleFac: the factor that the bone length is scaled by to get the desired amount */ sub_v3_v3v3(splineVec, poseTail, poseHead); scaleFac = len_v3(splineVec) / pchan->bone->length; /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis * - this uses the same method as is used for the Damped Track Constraint (see the code there for details) */ { float dmat[3][3], rmat[3][3], tmat[3][3]; float raxis[3], rangle; /* compute the raw rotation matrix from the bone's current matrix by extracting only the * orientation-relevant axes, and normalizing them */ copy_v3_v3(rmat[0], pchan->pose_mat[0]); copy_v3_v3(rmat[1], pchan->pose_mat[1]); copy_v3_v3(rmat[2], pchan->pose_mat[2]); normalize_m3(rmat); /* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */ normalize_v3(splineVec); /* calculate smallest axis-angle rotation necessary for getting from the * current orientation of the bone, to the spline-imposed direction */ cross_v3_v3v3(raxis, rmat[1], splineVec); rangle = dot_v3v3(rmat[1], splineVec); CLAMP(rangle, -1.0f, 1.0f); rangle = acosf(rangle); /* multiply the magnitude of the angle by the influence of the constraint to * control the influence of the SplineIK effect */ rangle *= tree->con->enforce; /* construct rotation matrix from the axis-angle rotation found above * - this call takes care to make sure that the axis provided is a unit vector first */ axis_angle_to_mat3(dmat, raxis, rangle); /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates, * while still maintaining roll control from the existing bone animation */ mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */ normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */ copy_m4_m3(poseMat, tmat); } /* step 4: set the scaling factors for the axes */ { /* only multiply the y-axis by the scaling factor to get nice volume-preservation */ mul_v3_fl(poseMat[1], scaleFac); /* set the scaling factors of the x and z axes from... */ switch (ikData->xzScaleMode) { case CONSTRAINT_SPLINEIK_XZS_ORIGINAL: { /* original scales get used */ float scale; /* x-axis scale */ scale = len_v3(pchan->pose_mat[0]); mul_v3_fl(poseMat[0], scale); /* z-axis scale */ scale = len_v3(pchan->pose_mat[2]); mul_v3_fl(poseMat[2], scale); break; } case CONSTRAINT_SPLINEIK_XZS_INVERSE: { /* old 'volume preservation' method using the inverse scale */ float scale; /* calculate volume preservation factor which is * basically the inverse of the y-scaling factor */ if (fabsf(scaleFac) != 0.0f) { scale = 1.0f / fabsf(scaleFac); /* we need to clamp this within sensible values */ /* NOTE: these should be fine for now, but should get sanitised in future */ CLAMP(scale, 0.0001f, 100000.0f); } else scale = 1.0f; /* apply the scaling */ mul_v3_fl(poseMat[0], scale); mul_v3_fl(poseMat[2], scale); break; } case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: { /* improved volume preservation based on the Stretch To constraint */ float final_scale; /* as the basis for volume preservation, we use the inverse scale factor... */ if (fabsf(scaleFac) != 0.0f) { /* NOTE: The method here is taken wholesale from the Stretch To constraint */ float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge); if (bulge > 1.0f) { if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MAX) { float bulge_max = max_ff(ikData->bulge_max, 1.0f); float hard = min_ff(bulge, bulge_max); float range = bulge_max - 1.0f; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2; bulge = interpf(soft, hard, ikData->bulge_smooth); } } if (bulge < 1.0f) { if (ikData->flag & CONSTRAINT_SPLINEIK_USE_BULGE_MIN) { float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f); float hard = max_ff(bulge, bulge_min); float range = 1.0f - bulge_min; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2; bulge = interpf(soft, hard, ikData->bulge_smooth); } } /* compute scale factor for xz axes from this value */ final_scale = sqrtf(bulge); } else { /* no scaling, so scale factor is simple */ final_scale = 1.0f; } /* apply the scaling (assuming normalised scale) */ mul_v3_fl(poseMat[0], final_scale); mul_v3_fl(poseMat[2], final_scale); break; } } /* finally, multiply the x and z scaling by the radius of the curve too, * to allow automatic scales to get tweaked still */ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { mul_v3_fl(poseMat[0], radius); mul_v3_fl(poseMat[2], radius); } } /* step 5: set the location of the bone in the matrix */ if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) { /* when the 'no-root' option is affected, the chain can retain * the shape but be moved elsewhere */ copy_v3_v3(poseHead, pchan->pose_head); } else if (tree->con->enforce < 1.0f) { /* when the influence is too low * - blend the positions for the 'root' bone * - stick to the parent for any other */ if (pchan->parent) { copy_v3_v3(poseHead, pchan->pose_head); } else { /* FIXME: this introduces popping artifacts when we reach 0.0 */ interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce); } } copy_v3_v3(poseMat[3], poseHead); /* finally, store the new transform */ copy_m4_m4(pchan->pose_mat, poseMat); copy_v3_v3(pchan->pose_head, poseHead); /* recalculate tail, as it's now outdated after the head gets adjusted above! */ BKE_pose_where_is_bone_tail(pchan); /* done! */ pchan->flag |= POSE_DONE; }
/* simple deform modifier */ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { static const float lock_axis[2] = {0.0f, 0.0f}; int i; int limit_axis = 0; float smd_limit[2], smd_factor; SpaceTransform *transf = NULL, tmp_transf; void (*simpleDeform_callback)(const float factor, const float dcut[3], float co[3]) = NULL; /* Mode callback */ int vgroup; MDeformVert *dvert; /* Safe-check */ if (smd->origin == ob) smd->origin = NULL; /* No self references */ if (smd->limit[0] < 0.0f) smd->limit[0] = 0.0f; if (smd->limit[0] > 1.0f) smd->limit[0] = 1.0f; smd->limit[0] = min_ff(smd->limit[0], smd->limit[1]); /* Upper limit >= than lower limit */ /* Calculate matrixs do convert between coordinate spaces */ if (smd->origin) { transf = &tmp_transf; if (smd->originOpts & MOD_SIMPLEDEFORM_ORIGIN_LOCAL) { space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat); } else { copy_m4_m4(transf->local2target, smd->origin->obmat); invert_m4_m4(transf->target2local, transf->local2target); } } /* Setup vars, * Bend limits on X.. all other modes limit on Z */ limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; /* Update limits if needed */ { float lower = FLT_MAX; float upper = -FLT_MAX; for (i = 0; i < numVerts; i++) { float tmp[3]; copy_v3_v3(tmp, vertexCos[i]); if (transf) space_transform_apply(transf, tmp); lower = min_ff(lower, tmp[limit_axis]); upper = max_ff(upper, tmp[limit_axis]); } /* SMD values are normalized to the BV, calculate the absolut values */ smd_limit[1] = lower + (upper - lower) * smd->limit[1]; smd_limit[0] = lower + (upper - lower) * smd->limit[0]; smd_factor = smd->factor / max_ff(FLT_EPSILON, smd_limit[1] - smd_limit[0]); } modifier_get_vgroup(ob, dm, smd->vgroup_name, &dvert, &vgroup); switch (smd->mode) { case MOD_SIMPLEDEFORM_MODE_TWIST: simpleDeform_callback = simpleDeform_twist; break; case MOD_SIMPLEDEFORM_MODE_BEND: simpleDeform_callback = simpleDeform_bend; break; case MOD_SIMPLEDEFORM_MODE_TAPER: simpleDeform_callback = simpleDeform_taper; break; case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch; break; default: return; /* No simpledeform mode? */ } for (i = 0; i < numVerts; i++) { float weight = defvert_array_find_weight_safe(dvert, i, vgroup); if (weight != 0.0f) { float co[3], dcut[3] = {0.0f, 0.0f, 0.0f}; if (transf) { space_transform_apply(transf, vertexCos[i]); } copy_v3_v3(co, vertexCos[i]); /* Apply axis limits */ if (smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) { /* Bend mode shoulnt have any lock axis */ if (smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut); if (smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut); } axis_limit(limit_axis, smd_limit, co, dcut); simpleDeform_callback(smd_factor, dcut, co); /* apply deform */ interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); /* Use vertex weight has coef of linear interpolation */ if (transf) { space_transform_invert(transf, vertexCos[i]); } } } }