void RE_set_customdata_names(ObjectRen *obr, CustomData *data) { /* CustomData layer names are stored per object here, because the * DerivedMesh which stores the layers is freed */ CustomDataLayer *layer; int numtf = 0, numcol = 0, i, mtfn, mcn; if (CustomData_has_layer(data, CD_MTFACE)) { numtf= CustomData_number_of_layers(data, CD_MTFACE); obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames"); } if (CustomData_has_layer(data, CD_MCOL)) { numcol= CustomData_number_of_layers(data, CD_MCOL); obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames"); } for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { layer= &data->layers[i]; if (layer->type == CD_MTFACE) { BLI_strncpy(obr->mtface[mtfn++], layer->name, sizeof(layer->name)); obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf); obr->bakemtface= layer->active; } else if (layer->type == CD_MCOL) { BLI_strncpy(obr->mcol[mcn++], layer->name, sizeof(layer->name)); obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol); } } }
int console_char_pick(struct SpaceConsole *sc, ARegion *ar, const int mval[2]) { int pos_pick = 0; void *mouse_pick = NULL; int mval_clamp[2]; mval_clamp[0] = CLAMPIS(mval[0], CONSOLE_DRAW_MARGIN, ar->winx - CONSOLE_DRAW_MARGIN); mval_clamp[1] = CLAMPIS(mval[1], CONSOLE_DRAW_MARGIN, ar->winy - CONSOLE_DRAW_MARGIN); console_textview_main__internal(sc, ar, 0, mval_clamp, &mouse_pick, &pos_pick); return pos_pick; }
void TimeNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { SetValueOperation *operation = new SetValueOperation(); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); bNode *node = this->getbNode(); /* stack order output: fac */ float fac = 0.0f; const int framenumber = context->getFramenumber(); if (framenumber < node->custom1) { fac = 0.0f; } else if (framenumber > node->custom2) { fac = 1.0f; } else if (node->custom1 < node->custom2) { fac = (context->getFramenumber() - node->custom1) / (float)(node->custom2 - node->custom1); } curvemapping_initialize((CurveMapping *)node->storage); fac = curvemapping_evaluateF((CurveMapping *)node->storage, 0, fac); operation->setValue(CLAMPIS(fac, 0.0f, 1.0f)); graph->addOperation(operation); }
/* * This calls the new bevel code (added since 2.64) */ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; BMesh *bm; BMIter iter; BMEdge *e; BMVert *v; float weight, weight2; int vgroup = -1; MDeformVert *dvert = NULL; BevelModifierData *bmd = (BevelModifierData *)md; const float threshold = cosf(bmd->bevel_angle + 0.000000175f); const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0; const bool do_clamp = !(bmd->flags & MOD_BEVEL_OVERLAP_OK); const int offset_type = bmd->val_flags; const float value = bmd->value; const int mat = CLAMPIS(bmd->mat, -1, ctx->object->totcol - 1); const bool loop_slide = (bmd->flags & MOD_BEVEL_EVEN_WIDTHS) == 0; const bool mark_seam = (bmd->edge_flags & MOD_BEVEL_MARK_SEAM); const bool mark_sharp = (bmd->edge_flags & MOD_BEVEL_MARK_SHARP); bool harden_normals = (bmd->flags & MOD_BEVEL_HARDEN_NORMALS); const int face_strength_mode = bmd->face_str_mode; const int miter_outer = bmd->miter_outer; const int miter_inner = bmd->miter_inner; const float spread = bmd->spread; bm = BKE_mesh_to_bmesh_ex(mesh, &(struct BMeshCreateParams){0},
static float do_clump_level(float result[3], const float co[3], const float par_co[3], float time, float clumpfac, float clumppow, float pa_clump, CurveMapping *clumpcurve) { float clump = 0.0f; if (clumpcurve) { clump = pa_clump * (1.0f - CLAMPIS(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f)); interp_v3_v3v3(result, co, par_co, clump); } else if (clumpfac != 0.0f) { float cpow; if (clumppow < 0.0f) cpow = 1.0f + clumppow; else cpow = 1.0f + 9.0f * clumppow; if (clumpfac < 0.0f) /* clump roots instead of tips */ clump = -clumpfac * pa_clump * (float)pow(1.0 - (double)time, (double)cpow); else clump = clumpfac * pa_clump * (float)pow((double)time, (double)cpow); interp_v3_v3v3(result, co, par_co, clump); } return clump; }
/* this makes sure we can extend for non-cyclic. * * returns OK: 1/0 */ static bool where_on_path_deform( Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius) { BevList *bl; float ctime1; int cycl = 0; /* test for cyclic */ bl = ob->runtime.curve_cache->bev.first; if (!bl->nr) { return false; } if (bl->poly > -1) { cycl = 1; } if (cycl == 0) { ctime1 = CLAMPIS(ctime, 0.0f, 1.0f); } else { ctime1 = ctime; } /* vec needs 4 items */ if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) { if (cycl == 0) { Path *path = ob->runtime.curve_cache->path; float dvec[3]; if (ctime < 0.0f) { sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec); mul_v3_fl(dvec, ctime * (float)path->len); add_v3_v3(vec, dvec); if (quat) { copy_qt_qt(quat, path->data[0].quat); } if (radius) { *radius = path->data[0].radius; } } else if (ctime > 1.0f) { sub_v3_v3v3(dvec, path->data[path->len - 1].vec, path->data[path->len - 2].vec); mul_v3_fl(dvec, (ctime - 1.0f) * (float)path->len); add_v3_v3(vec, dvec); if (quat) { copy_qt_qt(quat, path->data[path->len - 1].quat); } if (radius) { *radius = path->data[path->len - 1].radius; } /* weight - not used but could be added */ } } return true; } return false; }
void PaletteColor_color_set(PointerRNA *ptr, const float values[3]) { PaletteColor *data = (PaletteColor *)(ptr->data); unsigned int i; for (i = 0; i < 3; i++) { ((float *)data->rgb)[i] = CLAMPIS(values[i], 0.0f, 1.0f); } }
void MovieClip_display_aspect_set(PointerRNA *ptr, const float values[2]) { MovieClip *data = (MovieClip *)(ptr->data); unsigned int i; for (i = 0; i < 2; i++) { (&data->aspx)[i] = CLAMPIS(values[i], 0.1000000015f, FLT_MAX); } }
static void rna_render_slots_active_set(PointerRNA *ptr, PointerRNA value) { Image *image = (Image *)ptr->id.data; if (value.id.data == image) { RenderSlot *render_slot = (RenderSlot *)value.data; int index = render_slot - image->render_slots; image->render_slot = CLAMPIS(index, 0, IMA_MAX_RENDER_SLOT - 1); } }
/* 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); }
// get visibility of a wind ray static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, EffectorData *efd, EffectedPoint *point) { const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT); ListBase *colls = colliders; ColliderCache *col; float norm[3], len = 0.0; float visibility = 1.0, absorption = 0.0; if (!(eff->pd->flag & PFIELD_VISIBILITY)) return visibility; if (!colls) colls = get_collider_cache(eff->scene, eff->ob, NULL); if (!colls) return visibility; negate_v3_v3(norm, efd->vec_to_point); len = normalize_v3(norm); /* check all collision objects */ for (col = colls->first; col; col = col->next) { CollisionModifierData *collmd = col->collmd; if (col->ob == eff->ob) continue; if (collmd->bvhtree) { BVHTreeRayHit hit; hit.index = -1; hit.dist = len + FLT_EPSILON; /* check if the way is blocked */ if (BLI_bvhtree_ray_cast_ex( collmd->bvhtree, point->loc, norm, 0.0f, &hit, eff_tri_ray_hit, NULL, raycast_flag) != -1) { absorption= col->ob->pd->absorption; /* visibility is only between 0 and 1, calculated from 1-absorption */ visibility *= CLAMPIS(1.0f-absorption, 0.0f, 1.0f); if (visibility <= 0.0f) break; } } } if (!colliders) free_collider_cache(&colls); return visibility; }
static void time_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(in), short UNUSED(thread)) { /* stack order output: fac */ float fac= 0.0f; if (node->custom1 < node->custom2) fac = (p->cfra - node->custom1)/(float)(node->custom2-node->custom1); fac = curvemapping_evaluateF(node->storage, 0, fac); out[0] = CLAMPIS(fac, 0.0f, 1.0f); }
static void node_composit_exec_curves_time(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { RenderData *rd= data; /* stack order output: fac */ float fac= 0.0f; if (node->custom1 < node->custom2) fac= (rd->cfra - node->custom1)/(float)(node->custom2-node->custom1); fac= curvemapping_evaluateF(node->storage, 0, fac); out[0]->vec[0]= CLAMPIS(fac, 0.0f, 1.0f); }
bool MOD_meshcache_read_mdd_times(const char *filepath, float (*vertexCos)[3], const int verts_tot, const char interp, const float time, const float fps, const char time_mode, const char **err_str) { float frame; FILE *fp = BLI_fopen(filepath, "rb"); bool ok; if (fp == NULL) { *err_str = errno ? strerror(errno) : "Unknown error opening file"; return false; } switch (time_mode) { case MOD_MESHCACHE_TIME_FRAME: { frame = time; break; } case MOD_MESHCACHE_TIME_SECONDS: { /* we need to find the closest time */ if (meshcache_read_mdd_range_from_time(fp, verts_tot, time, fps, &frame, err_str) == false) { fclose(fp); return false; } rewind(fp); break; } case MOD_MESHCACHE_TIME_FACTOR: default: { MDDHead mdd_head; if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) { fclose(fp); return false; } frame = CLAMPIS(time, 0.0f, 1.0f) * (float)mdd_head.frame_tot; rewind(fp); break; } } ok = MOD_meshcache_read_mdd_frame(fp, vertexCos, verts_tot, interp, frame, err_str); fclose(fp); return ok; }
static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, PyObject *value) { if (PyIndex_Check(key)) { int i; i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) { return -1; } if (value) { /* dvert[group_index] = 0.5 */ if (i < 0) { PyErr_SetString(PyExc_KeyError, "BMDeformVert[key] = x: " "weight keys can't be negative"); return -1; } else { MDeformWeight *dw = defvert_verify_index(self->data, i); const float f = PyFloat_AsDouble(value); if (f == -1 && PyErr_Occurred()) { // parsed key not a number PyErr_SetString(PyExc_TypeError, "BMDeformVert[key] = x: " "assigned value not a number"); return -1; } dw->weight = CLAMPIS(f, 0.0f, 1.0f); } } else { /* del dvert[group_index] */ MDeformWeight *dw = defvert_find_index(self->data, i); if (dw == NULL) { PyErr_SetString(PyExc_KeyError, "del BMDeformVert[key]: " "key not found"); } defvert_remove_group(self->data, dw); } return 0; } else { PyErr_Format(PyExc_TypeError, "BMDeformVert keys must be integers, not %.200s", Py_TYPE(key)->tp_name); return -1; } }
static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObject *args) { BPy_BMEdge *py_edge; BPy_BMVert *py_vert; float fac; int do_join_faces; BMesh *bm; BMEdge *e_new = NULL; if (!PyArg_ParseTuple(args, "O!O!fi:vert_collapse_faces", &BPy_BMVert_Type, &py_vert, &BPy_BMEdge_Type, &py_edge, &fac, &do_join_faces)) { return NULL; } BPY_BM_CHECK_OBJ(py_edge); BPY_BM_CHECK_OBJ(py_vert); /* this doubles for checking that the verts are in the same mesh */ if (!(py_edge->e->v1 == py_vert->v || py_edge->e->v2 == py_vert->v)) { PyErr_SetString(PyExc_ValueError, "vert_collapse_faces(vert, edge): the vertex is not found in the edge"); return NULL; } if (BM_vert_edge_count(py_vert->v) > 2) { PyErr_SetString(PyExc_ValueError, "vert_collapse_faces(vert, edge): vert has more then 2 connected edges"); return NULL; } bm = py_edge->bm; e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, TRUE); if (e_new) { return BPy_BMEdge_CreatePyObject(bm, e_new); } else { PyErr_SetString(PyExc_ValueError, "vert_collapse_edge(vert, edge): no new edge created, internal error"); return NULL; } }
static bool edbm_bevel_calc(wmOperator *op) { BevelData *opdata = op->customdata; BMEditMesh *em = opdata->em; BMOperator bmop; const float offset = RNA_float_get(op->ptr, "offset"); const int offset_type = RNA_enum_get(op->ptr, "offset_type"); const int segments = RNA_int_get(op->ptr, "segments"); const float profile = RNA_float_get(op->ptr, "profile"); const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only"); const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap"); int material = RNA_int_get(op->ptr, "material"); const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide"); /* revert to original mesh */ if (opdata->is_modal) { EDBM_redo_state_restore(opdata->mesh_backup, em, false); } if (em->ob) { material = CLAMPIS(material, -1, em->ob->totcol - 1); } EDBM_op_init(em, &bmop, op, "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b " "material=%i loop_slide=%b", BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, clamp_overlap, material, loop_slide); BMO_op_exec(em->bm, &bmop); if (offset != 0.0f) { /* not essential, but we may have some loose geometry that * won't get bevel'd and better not leave it selected */ EDBM_flag_disable_all(em, BM_ELEM_SELECT); BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true); } /* no need to de-select existing geometry */ if (!EDBM_op_finish(em, &bmop, op, true)) { return false; } EDBM_mesh_normals_update(opdata->em); EDBM_update_generic(opdata->em, true, true); return true; }
void GPU_simple_shader_colors(const float diffuse[3], const float specular[3], int shininess, float alpha) { float gl_diffuse[4], gl_specular[4]; copy_v3_v3(gl_diffuse, diffuse); gl_diffuse[3] = alpha; copy_v3_v3(gl_specular, specular); gl_specular[3] = 1.0f; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128)); }
static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata_t *AFD) { int xs, ys, clip = 0; float tc[4], xsd, ysd, cw = 0.f; const float ux = ibuf->x*AFD->dxt[0], uy = ibuf->y*AFD->dxt[1]; const float vx = ibuf->x*AFD->dyt[0], vy = ibuf->y*AFD->dyt[1]; int xsam = (int)(0.5f*sqrtf(ux*ux + uy*uy) + 0.5f); int ysam = (int)(0.5f*sqrtf(vx*vx + vy*vy) + 0.5f); const int minsam = AFD->intpol ? 2 : 4; xsam = CLAMPIS(xsam, minsam, ibuf->x*2); ysam = CLAMPIS(ysam, minsam, ibuf->y*2); xsd = 1.f / xsam; ysd = 1.f / ysam; texr->tr = texr->tg = texr->tb = texr->ta = 0.f; for (ys=0; ys<ysam; ++ys) { for (xs=0; xs<xsam; ++xs) { const float su = (xs + ((ys & 1) + 0.5f)*0.5f)*xsd - 0.5f; const float sv = (ys + ((xs & 1) + 0.5f)*0.5f)*ysd - 0.5f; const float pu = fx + su*AFD->dxt[0] + sv*AFD->dyt[0]; const float pv = fy + su*AFD->dxt[1] + sv*AFD->dyt[1]; const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu*ibuf->x, pv*ibuf->y, AFD->intpol, AFD->extflag); clip |= out; cw += out ? 0.f : 1.f; texr->tr += tc[0]; texr->tg += tc[1]; texr->tb += tc[2]; texr->ta += texr->talpha ? tc[3] : 0.f; } } xsd *= ysd; texr->tr *= xsd; texr->tg *= xsd; texr->tb *= xsd; /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */ texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f); }
static PyObject *bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args) { BPy_BMEdge *py_edge; BPy_BMVert *py_vert; float fac; BMesh *bm; BMVert *v_new = NULL; BMEdge *e_new = NULL; if (!PyArg_ParseTuple(args, "O!O!f:edge_split", &BPy_BMEdge_Type, &py_edge, &BPy_BMVert_Type, &py_vert, &fac)) { return NULL; } BPY_BM_CHECK_OBJ(py_edge); BPY_BM_CHECK_OBJ(py_vert); /* this doubles for checking that the verts are in the same mesh */ if (!(py_edge->e->v1 == py_vert->v || py_edge->e->v2 == py_vert->v)) { PyErr_SetString(PyExc_ValueError, "edge_split(edge, vert): the vertex is not found in the edge"); return NULL; } bm = py_edge->bm; v_new = BM_edge_split(bm, py_edge->e, py_vert->v, &e_new, CLAMPIS(fac, 0.0f, 1.0f)); if (v_new && e_new) { PyObject *ret = PyTuple_New(2); PyTuple_SET_ITEMS(ret, BPy_BMEdge_CreatePyObject(bm, e_new), BPy_BMVert_CreatePyObject(bm, v_new)); return ret; } else { PyErr_SetString(PyExc_ValueError, "edge_split(edge, vert): couldn't split the edge, internal error"); return NULL; } }
static int render_frame(int argc, const char **argv, void *data) { bContext *C = data; Scene *scene = CTX_data_scene(C); if (scene) { Main *bmain = CTX_data_main(C); if (argc > 1) { Render *re = RE_NewRender(scene->id.name); int frame; ReportList reports; switch (*argv[1]) { case '+': frame = scene->r.sfra + atoi(argv[1] + 1); break; case '-': frame = (scene->r.efra - atoi(argv[1] + 1)) + 1; break; default: frame = atoi(argv[1]); break; } BLI_begin_threaded_malloc(); BKE_reports_init(&reports, RPT_PRINT); frame = CLAMPIS(frame, MINAFRAME, MAXFRAME); RE_SetReports(re, &reports); RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step); RE_SetReports(re, NULL); BLI_end_threaded_malloc(); return 1; } else { printf("\nError: frame number must follow '-f / --render-frame'.\n"); return 0; } } else { printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n"); return 0; } }
static int set_end_frame(int argc, const char **argv, void *data) { bContext *C = data; if (CTX_data_scene(C)) { Scene *scene= CTX_data_scene(C); if (argc > 1) { int frame = atoi(argv[1]); (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME); return 1; } else { printf("\nError: frame number must follow '-e / --frame-end'.\n"); return 0; } } else { printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n"); return 0; } }
static int set_skip_frame(int argc, const char **argv, void *data) { bContext *C = data; if (CTX_data_scene(C)) { Scene *scene= CTX_data_scene(C); if (argc > 1) { int frame = atoi(argv[1]); (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME); return 1; } else { printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n"); return 0; } } else { printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n"); return 0; } }
/* this makes sure we can extend for non-cyclic. *vec needs 4 items! */ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius) /* returns OK */ { Curve *cu= ob->data; BevList *bl; float ctime1; int cycl=0; /* test for cyclic */ bl= cu->bev.first; if (!bl->nr) return 0; if(bl && bl->poly> -1) cycl= 1; if(cycl==0) { ctime1= CLAMPIS(ctime, 0.0f, 1.0f); } else ctime1= ctime; /* vec needs 4 items */ if(where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) { if(cycl==0) { Path *path= cu->path; float dvec[3]; if(ctime < 0.0f) { sub_v3_v3v3(dvec, path->data[1].vec, path->data[0].vec); mul_v3_fl(dvec, ctime*(float)path->len); add_v3_v3(vec, dvec); if(quat) copy_qt_qt(quat, path->data[0].quat); if(radius) *radius= path->data[0].radius; } else if(ctime > 1.0f) { sub_v3_v3v3(dvec, path->data[path->len-1].vec, path->data[path->len-2].vec); mul_v3_fl(dvec, (ctime-1.0f)*(float)path->len); add_v3_v3(vec, dvec); if(quat) copy_qt_qt(quat, path->data[path->len-1].quat); if(radius) *radius= path->data[path->len-1].radius; /* weight - not used but could be added */ } } return 1; } return 0; }
static void do_rough_curve(const float loc[3], float mat[4][4], float time, float fac, float size, CurveMapping *roughcurve, ParticleKey *state) { float rough[3]; float rco[3]; if (!roughcurve) return; fac *= CLAMPIS(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f); copy_v3_v3(rco, loc); mul_v3_fl(rco, time); rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2); rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2); rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2); madd_v3_v3fl(state->co, mat[0], fac * rough[0]); madd_v3_v3fl(state->co, mat[1], fac * rough[1]); madd_v3_v3fl(state->co, mat[2], fac * rough[2]); }
unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height) { const float max_segment = 0.005; unsigned int resol = BKE_mask_spline_resolution(spline, width, height); float max_jump = 0.0f; int i; /* avoid checking the featrher if we already hit the maximum value */ if (resol >= MASK_RESOL_MAX) { return MASK_RESOL_MAX; } for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; float prev_u, prev_w; int j; prev_u = 0.0f; prev_w = point->bezt.weight; for (j = 0; j < point->tot_uw; j++) { const float w_diff = (point->uw[j].w - prev_w); const float u_diff = (point->uw[j].u - prev_u); /* avoid divide by zero and very high values, * though these get clamped eventually */ if (u_diff > FLT_EPSILON) { float jump = fabsf(w_diff / u_diff); max_jump = max_ff(max_jump, jump); } prev_u = point->uw[j].u; prev_w = point->uw[j].w; } } resol += max_jump / max_segment; return CLAMPIS(resol, 1, MASK_RESOL_MAX); }
unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) { float max_segment = 0.01f; unsigned int i, resol = 1; if (width != 0 && height != 0) { max_segment = 1.0f / (float)max_ii(width, height); } for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; BezTriple *bezt_curr, *bezt_next; float a, b, c, len; unsigned int cur_resol; bezt_curr = &point->bezt; bezt_next = BKE_mask_spline_point_next_bezt(spline, spline->points, point); if (bezt_next == NULL) { break; } a = len_v3v3(bezt_curr->vec[1], bezt_curr->vec[2]); b = len_v3v3(bezt_curr->vec[2], bezt_next->vec[0]); c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]); len = a + b + c; cur_resol = len / max_segment; resol = MAX2(resol, cur_resol); if (resol >= MASK_RESOL_MAX) { break; } } return CLAMPIS(resol, 1, MASK_RESOL_MAX); }
static void rna_Lattice_points_w_set(PointerRNA *ptr, int value) { Lattice *lt= (Lattice*)ptr->data; lt->opntsw= CLAMPIS(value, 1, 64); }
/* 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; }
static void cloth_continuum_step(ClothModifierData *clmd, float dt) { ClothSimSettings *parms = clmd->sim_parms; Cloth *cloth = clmd->clothObject; Implicit_Data *data = cloth->implicit; int mvert_num = cloth->mvert_num; ClothVertex *vert; const float fluid_factor = 0.95f; /* blend between PIC and FLIP methods */ float smoothfac = parms->velocity_smooth; /* XXX FIXME arbitrary factor!!! this should be based on some intuitive value instead, * like number of hairs per cell and time decay instead of "strength" */ float density_target = parms->density_target; float density_strength = parms->density_strength; float gmin[3], gmax[3]; int i; /* clear grid info */ zero_v3_int(clmd->hair_grid_res); zero_v3(clmd->hair_grid_min); zero_v3(clmd->hair_grid_max); clmd->hair_grid_cellsize = 0.0f; hair_get_boundbox(clmd, gmin, gmax); /* gather velocities & density */ if (smoothfac > 0.0f || density_strength > 0.0f) { HairGrid *grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_cell_size, gmin, gmax); cloth_continuum_fill_grid(grid, cloth); /* main hair continuum solver */ BPH_hair_volume_solve_divergence(grid, dt, density_target, density_strength); for (i = 0, vert = cloth->verts; i < mvert_num; i++, vert++) { float x[3], v[3], nv[3]; /* calculate volumetric velocity influence */ BPH_mass_spring_get_position(data, i, x); BPH_mass_spring_get_new_velocity(data, i, v); BPH_hair_volume_grid_velocity(grid, x, v, fluid_factor, nv); interp_v3_v3v3(nv, v, nv, smoothfac); /* apply on hair data */ BPH_mass_spring_set_new_velocity(data, i, nv); } /* store basic grid info in the modifier data */ BPH_hair_volume_grid_geometry(grid, &clmd->hair_grid_cellsize, clmd->hair_grid_res, clmd->hair_grid_min, clmd->hair_grid_max); #if 0 /* DEBUG hair velocity vector field */ { const int size = 64; int i, j; float offset[3], a[3], b[3]; const int axis = 0; const float shift = 0.0f; copy_v3_v3(offset, clmd->hair_grid_min); zero_v3(a); zero_v3(b); offset[axis] = shift * clmd->hair_grid_cellsize; a[(axis+1) % 3] = clmd->hair_grid_max[(axis+1) % 3] - clmd->hair_grid_min[(axis+1) % 3]; b[(axis+2) % 3] = clmd->hair_grid_max[(axis+2) % 3] - clmd->hair_grid_min[(axis+2) % 3]; BKE_sim_debug_data_clear_category(clmd->debug_data, "grid velocity"); for (j = 0; j < size; ++j) { for (i = 0; i < size; ++i) { float x[3], v[3], gvel[3], gvel_smooth[3], gdensity; madd_v3_v3v3fl(x, offset, a, (float)i / (float)(size-1)); madd_v3_v3fl(x, b, (float)j / (float)(size-1)); zero_v3(v); BPH_hair_volume_grid_interpolate(grid, x, &gdensity, gvel, gvel_smooth, NULL, NULL); // BKE_sim_debug_data_add_circle(clmd->debug_data, x, gdensity, 0.7, 0.3, 1, "grid density", i, j, 3111); if (!is_zero_v3(gvel) || !is_zero_v3(gvel_smooth)) { float dvel[3]; sub_v3_v3v3(dvel, gvel_smooth, gvel); // BKE_sim_debug_data_add_vector(clmd->debug_data, x, gvel, 0.4, 0, 1, "grid velocity", i, j, 3112); // BKE_sim_debug_data_add_vector(clmd->debug_data, x, gvel_smooth, 0.6, 1, 1, "grid velocity", i, j, 3113); BKE_sim_debug_data_add_vector(clmd->debug_data, x, dvel, 0.4, 1, 0.7, "grid velocity", i, j, 3114); #if 0 if (gdensity > 0.0f) { float col0[3] = {0.0, 0.0, 0.0}; float col1[3] = {0.0, 1.0, 0.0}; float col[3]; interp_v3_v3v3(col, col0, col1, CLAMPIS(gdensity * clmd->sim_parms->density_strength, 0.0, 1.0)); // BKE_sim_debug_data_add_circle(clmd->debug_data, x, gdensity * clmd->sim_parms->density_strength, 0, 1, 0.4, "grid velocity", i, j, 3115); // BKE_sim_debug_data_add_dot(clmd->debug_data, x, col[0], col[1], col[2], "grid velocity", i, j, 3115); BKE_sim_debug_data_add_circle(clmd->debug_data, x, 0.01f, col[0], col[1], col[2], "grid velocity", i, j, 3115); } #endif } } } } #endif BPH_hair_volume_free_vertex_grid(grid); } }