Changeset View
Standalone View
source/blender/bmesh/operators/bmo_primitive.c
| Context not available. | |||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_alloca.h" | |||||
| #include "BKE_editmesh.h" | |||||
| #include "DNA_meshdata_types.h" | |||||
| #include "bmesh.h" | #include "bmesh.h" | ||||
| #include "intern/bmesh_operators_private.h" | #include "intern/bmesh_operators_private.h" | ||||
| static void bm_mesh_calc_uvs_sphere_face(BMFace *f, float rot[4][4], int cd_loop_uv_offset); | |||||
| /* ************************ primitives ******************* */ | /* ************************ primitives ******************* */ | ||||
| Context not available. | |||||
| const unsigned int ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments")); | const unsigned int ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments")); | ||||
| const float xtot_inv2 = 2.0f / (xtot - 1); | const float xtot_inv2 = 2.0f / (xtot - 1); | ||||
| const float ytot_inv2 = 2.0f / (ytot - 1); | const float ytot_inv2 = 2.0f / (ytot - 1); | ||||
| const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); | |||||
| BMVert **varr; | BMVert **varr; | ||||
| BMVert *vquad[4]; | BMVert *vquad[4]; | ||||
| BMFace *f; | |||||
| float mat[4][4]; | float mat[4][4]; | ||||
| float vec[3], tvec[3]; | float vec[3], tvec[3]; | ||||
| Context not available. | |||||
| vquad[2] = varr[XY(x, y)]; | vquad[2] = varr[XY(x, y)]; | ||||
| vquad[3] = varr[XY(x - 1, y)]; | vquad[3] = varr[XY(x - 1, y)]; | ||||
| BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true); | f = BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW); | |||||
| } | } | ||||
| } | } | ||||
| #undef XY | #undef XY | ||||
| if (calc_uvs) | |||||
| BM_mesh_calc_uvs_grid(bm, xtot, ytot); | |||||
| } | |||||
campbellbarton: Whats the purpose of disabling these flags? | |||||
Not Done Inline ActionsIf they stay enabled, those faces get unwrapped again next time BM_mesh_calc_uvs_grid is called on this mesh (ie. adding a second primitive, with unwrapping, to the same mesh as the first). Those flags were just enabled in this function directly above. CommanderCorianderSalamander: If they stay enabled, those faces get unwrapped again next time BM_mesh_calc_uvs_grid is called… | |||||
Not Done Inline ActionsThese flags are reset for each bmesh-operator call, you shouldn't have to initialize them. If you do - then it must be some bug in the operator flag stack. campbellbarton: These flags are reset for each bmesh-operator call, you shouldn't have to initialize them.
If… | |||||
| void BM_mesh_calc_uvs_grid(BMesh *bm, unsigned int x_segments, unsigned int y_segments) | |||||
| { | |||||
| BMFace *f; | |||||
Not Done Inline ActionsBetter make caller responsible for ensuring BMesh has UV's, This goes for all other similar functions too. campbellbarton: Better make caller responsible for ensuring BMesh has UV's, This goes for all other similar… | |||||
| BMLoop *l; | |||||
| BMIter iter, liter; | |||||
| MLoopUV *luv; | |||||
| int cd_loop_uv_offset, loopindex; | |||||
| float x, y, dx, dy; | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
| BLI_assert(cd_loop_uv_offset != -1); | |||||
| dx = 1.0f / (x_segments - 1); | |||||
| dy = 1.0f / (y_segments - 1); | |||||
| x = 0.0f; | |||||
| y = 0.0f; | |||||
| BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | |||||
| if (!BMO_elem_flag_test(bm, f, FACE_NEW)) | |||||
| continue; | |||||
| BMO_elem_flag_disable(bm, f, FACE_NEW); | |||||
campbellbartonUnsubmitted Not Done Inline ActionsWhy disable? campbellbarton: Why disable? | |||||
| BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loopindex) { | |||||
| BMO_elem_flag_disable(bm, l->v, VERT_MARK); | |||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | |||||
| switch (loopindex) { | |||||
| case 0: | |||||
| x += dx; | |||||
| break; | |||||
| case 1: | |||||
| y += dy; | |||||
| break; | |||||
| case 2: | |||||
| x -= dx; | |||||
| break; | |||||
| case 3: | |||||
| y -= dy; | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| luv->uv[0] = x; | |||||
| luv->uv[1] = y; | |||||
| } | |||||
| x += dx; | |||||
| if (x >= 1.0f) { | |||||
| x = 0.0f; | |||||
| y += dy; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) | void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) | ||||
| Context not available. | |||||
| const float dia = BMO_slot_float_get(op->slots_in, "diameter"); | const float dia = BMO_slot_float_get(op->slots_in, "diameter"); | ||||
| const int seg = BMO_slot_int_get(op->slots_in, "u_segments"); | const int seg = BMO_slot_int_get(op->slots_in, "u_segments"); | ||||
| const int tot = BMO_slot_int_get(op->slots_in, "v_segments"); | const int tot = BMO_slot_int_get(op->slots_in, "v_segments"); | ||||
| const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); | |||||
| BMOperator bmop, prevop; | BMOperator bmop, prevop; | ||||
| BMVert *eve, *preveve; | BMVert *eve, *preveve; | ||||
| Context not available. | |||||
| BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f); | BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f); | ||||
| } | } | ||||
| if (calc_uvs) | |||||
| BM_mesh_calc_uvs_sphere(bm); | |||||
| /* and now do imat */ | /* and now do imat */ | ||||
| BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | ||||
| if (BMO_elem_flag_test(bm, eve, VERT_MARK)) { | if (BMO_elem_flag_test(bm, eve, VERT_MARK)) { | ||||
| Context not available. | |||||
| const float dia = BMO_slot_float_get(op->slots_in, "diameter"); | const float dia = BMO_slot_float_get(op->slots_in, "diameter"); | ||||
| const float dia_div = dia / 200.0f; | const float dia_div = dia / 200.0f; | ||||
| const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions"); | const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions"); | ||||
| const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); | |||||
| BMVert *eva[12]; | BMVert *eva[12]; | ||||
| BMVert *v; | BMVert *v; | ||||
| Context not available. | |||||
| BMO_op_finish(bm, &bmop); | BMO_op_finish(bm, &bmop); | ||||
| } | } | ||||
| if (calc_uvs) | |||||
| BM_mesh_calc_uvs_sphere(bm); | |||||
| /* must transform after because of sphere subdivision */ | /* must transform after because of sphere subdivision */ | ||||
| BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { | BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { | ||||
| if (BMO_elem_flag_test(bm, v, VERT_MARK)) { | if (BMO_elem_flag_test(bm, v, VERT_MARK)) { | ||||
| Context not available. | |||||
| BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | ||||
| } | } | ||||
| void bm_mesh_calc_uvs_sphere_face(BMFace *f, float rot[4][4], int cd_loop_uv_offset) { | |||||
| float *uvs[4]; | |||||
Not Done Inline Actionsalloca wont be freed until the function exits. you have to be very careful calling alloca in a loop, and in this case it can easily run out of stack memory and crash. In this case you could move the body of the for loop into a static function. campbellbarton: `alloca` wont be freed until the function exits. you have to be very careful calling alloca in… | |||||
Not Done Inline Actionsshouldn’t this func be static? If static, please also rename it to bm_mesh_calc_uvs_sphere_face mont29: shouldn’t this func be static?
If static, please also rename it to… | |||||
Not Done Inline ActionsIt's declared static at the top of the file ;) CommanderCorianderSalamander: It's declared static at the top of the file ;) | |||||
| BMLoop *l; | |||||
Not Done Inline ActionsWith UVSphere or IcoSphere, len will never be > 4, no need to use alloca in this case imho, just simply use a float (*)[4] table (with a BLI_assert on f->len)? Or do you want this func to be usable with any kind of sphere-like geometry? mont29: With UVSphere or IcoSphere, len will never be > 4, no need to use alloca in this case imho… | |||||
| BMIter iter; | |||||
| MLoopUV *luv; | |||||
| float v[3]; | |||||
| float dx; | |||||
Not Done Inline Actionsbetter to use zero_v3(v) later. But do this vec need to be initialized at all? mont29: better to use zero_v3(v) later. But do this vec need to be initialized at all? | |||||
| int mi, i; | |||||
| BLI_assert(f->len <= 4); | |||||
| BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) { | |||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | |||||
| copy_v3_v3(v, l->v->co); | |||||
| mul_m4_v3(rot, v); | |||||
| map_to_sphere(&luv->uv[0], &luv->uv[1], v[0], v[1], v[2]); | |||||
| uvs[i] = luv->uv; | |||||
| } | |||||
| mi = 0; /* fix awkwardly-wrapping UVs */ | |||||
Not Done Inline ActionsConventions are to use post-increment in our C code (same for other loops below). mont29: Conventions are to use post-increment in our C code (same for other loops below). | |||||
| for (i = 1; i < f->len; i++) | |||||
| if (uvs[i][0] > uvs[mi][0]) | |||||
| mi = i; | |||||
| for (i = 0; i < f->len; i++) { | |||||
| if (i != mi) { | |||||
| dx = uvs[mi][0] - uvs[i][0]; | |||||
Not Done Inline Actionseeeh, a one-line if() I missed! mont29: eeeh, a one-line if() I missed! | |||||
| if (dx > 0.5f) | |||||
| uvs[i][0] += 1.0f; | |||||
| } | |||||
| } | |||||
| } | |||||
Not Done Inline ActionsThis is around 4440 degrees, This could be 2.1 since the value is in radians. campbellbarton: This is around `4440` degrees, This could be `2.1` since the value is in radians. | |||||
| void BM_mesh_calc_uvs_sphere(BMesh *bm) | |||||
| { | |||||
| BMFace *f; | |||||
| BMIter iter; | |||||
| int cd_loop_uv_offset; | |||||
| float v[3]; | |||||
| float rot[4][4]; | |||||
| float axis[3] = {0.806f, 0.329f, 0.491f}; /* magic numbers - seem to be best for both ico and uv sphere projections */ | |||||
Not Done Inline Actionsanother one I missed, no spaces between brackets and numbers, and please use full float format (1.0f). mont29: another one I missed, no spaces between brackets and numbers, and please use full float format… | |||||
| float angle = 2.1f; /* more magic! */ | |||||
| float size[3] = { 1.0f, 1.0f, 1.0f }; | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
| BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */ | |||||
| loc_axisangle_size_to_mat4(rot, v, axis, angle, size); | |||||
| BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | |||||
| bm_mesh_calc_uvs_sphere_face(f, rot, cd_loop_uv_offset); | |||||
| } | |||||
| } | |||||
Not Done Inline ActionsThis is applying to all faces, which will overwrite existing UV's if you add a new sphere while in edit-mode. campbellbarton: This is applying to **all faces**, which will overwrite existing UV's if you add a new sphere… | |||||
Not Done Inline ActionsYes - this is actually the problem I was trying to solve in the other primitives by enabling/disabling FACE_NEW. Forgot to deal with it here =( CommanderCorianderSalamander: Yes - this is actually the problem I was trying to solve in the other primitives by… | |||||
| void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) | void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) | ||||
| { | { | ||||
| BMVert *eve; | BMVert *eve; | ||||
| Context not available. | |||||
| const int segs = BMO_slot_int_get(op->slots_in, "segments"); | const int segs = BMO_slot_int_get(op->slots_in, "segments"); | ||||
| const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); | const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); | ||||
| const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); | const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); | ||||
| const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); | |||||
| BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL; | BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL; | ||||
| float vec[3], mat[4][4], phi, phid; | float vec[3], mat[4][4], phi, phid; | ||||
| Context not available. | |||||
| f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false); | f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW); | BMO_elem_flag_enable(bm, f, FACE_NEW); | ||||
| if (calc_uvs) | |||||
Not Done Inline ActionsCode style: use 0.5f, not .5 kevindietrich: Code style: use 0.5f, not .5 | |||||
| BM_mesh_calc_uvs_circle(bm, mat, dia); | |||||
| } | } | ||||
| if (!cap_tris) { | if (!cap_tris) { | ||||
| Context not available. | |||||
| BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | ||||
| } | } | ||||
| void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], float radius) { | |||||
campbellbartonUnsubmitted Not Done Inline Actionscampbellbarton: style: http://wiki.blender.org/index.php/Dev:Doc/Code_Style#Braces | |||||
| BMFace *f; | |||||
| BMLoop *l; | |||||
| BMIter iter, liter; | |||||
| MLoopUV *luv; | |||||
| int cd_loop_uv_offset; | |||||
| int loopindex; | |||||
| float v_transform[3], inv_mat[4][4]; | |||||
| const float scale = 0.5f / radius; | |||||
| const float center = 0.5f; | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
| BLI_assert(cd_loop_uv_offset != -1); /* caller must ensure we have UVs already */ | |||||
| invert_m4_m4(inv_mat, mat); | |||||
| BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | |||||
| if (!BMO_elem_flag_test(bm, f, FACE_NEW)) | |||||
| continue; | |||||
| BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loopindex) { | |||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | |||||
| copy_v3_v3(v_transform, l->v->co); | |||||
| /* transform back into the unit circle flat on the Z-axis */ | |||||
| mul_m4_v3(inv_mat, v_transform); | |||||
| /* then just take those coords for UVs */ | |||||
| luv->uv[0] = center + scale * v_transform[0]; | |||||
| luv->uv[1] = center + scale * v_transform[1]; | |||||
| } | |||||
| } | |||||
| } | |||||
| void bmo_create_cone_exec(BMesh *bm, BMOperator *op) | void bmo_create_cone_exec(BMesh *bm, BMOperator *op) | ||||
| { | { | ||||
| BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2; | BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2; | ||||
| BMFace *f; | |||||
| float vec[3], mat[4][4], phi, phid; | float vec[3], mat[4][4], phi, phid; | ||||
| float dia1 = BMO_slot_float_get(op->slots_in, "diameter1"); | float dia1 = BMO_slot_float_get(op->slots_in, "diameter1"); | ||||
| float dia2 = BMO_slot_float_get(op->slots_in, "diameter2"); | float dia2 = BMO_slot_float_get(op->slots_in, "diameter2"); | ||||
| Context not available. | |||||
| int segs = BMO_slot_int_get(op->slots_in, "segments"); | int segs = BMO_slot_int_get(op->slots_in, "segments"); | ||||
| const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); | const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); | ||||
| const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); | const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); | ||||
| const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); | |||||
| int a; | int a; | ||||
| if (!segs) | if (!segs) | ||||
| Context not available. | |||||
| if (a) { | if (a) { | ||||
| if (cap_ends) { | if (cap_ends) { | ||||
| BMFace *f; | |||||
| f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false); | f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW); | if (calc_uvs) | ||||
| BM_face_normal_update(f); | |||||
| BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_MARK); | |||||
| f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, false); | f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, false); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW); | if (calc_uvs) | ||||
| BM_face_normal_update(f); | |||||
| BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_MARK); | |||||
Not Done Inline ActionsWith all this effort to calculate the normals, probably better just to call. BM_face_calc_normal campbellbarton: With all this effort to calculate the normals, probably better just to call. | |||||
| } | } | ||||
| BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, false); | |||||
| f = BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, false); | |||||
| if (calc_uvs) | |||||
| BM_face_normal_update(f); | |||||
| BMO_elem_flag_enable(bm, f, FACE_MARK); | |||||
| } | } | ||||
| else { | else { | ||||
| firstv1 = v1; | firstv1 = v1; | ||||
| Context not available. | |||||
| if (!a) | if (!a) | ||||
| return; | return; | ||||
| f = BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, false); | |||||
| if (calc_uvs) | |||||
| BM_face_normal_update(f); | |||||
| BMO_elem_flag_enable(bm, f, FACE_MARK); | |||||
| if (cap_ends) { | if (cap_ends) { | ||||
| BMFace *f; | |||||
| f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false); | f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW); | if (calc_uvs) | ||||
| BM_face_normal_update(f); | |||||
| BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_MARK); | |||||
| f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, false); | f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, false); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW); | if (calc_uvs) | ||||
| BM_face_normal_update(f); | |||||
| BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_MARK); | |||||
| } | } | ||||
| if (calc_uvs) | |||||
| BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends); | |||||
| if (!cap_tris) { | if (!cap_tris) { | ||||
| BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); | BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); | ||||
| } | } | ||||
| BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, false); | |||||
Not Done Inline ActionsWhy is this removed??? mont29: Why is this removed??? | |||||
Not Done Inline ActionsJust moved up a few lines so all the faces were made before the dissolve_faces call - it made calc_uvs simpler if it could assume it was capped with triangles (I think! it's been a while) CommanderCorianderSalamander: Just moved up a few lines so all the faces were made before the dissolve_faces call - it made… | |||||
| BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001); | BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001); | ||||
| BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | ||||
| } | } | ||||
| void BM_mesh_calc_uvs_cone(BMesh *bm, float mat[4][4], float radius_top, float radius_bottom, int segments, bool cap_ends) | |||||
| { | |||||
| BMFace *f; | |||||
| BMLoop *l; | |||||
| BMIter iter, liter; | |||||
| MLoopUV *luv; | |||||
| int cd_loop_uv_offset; | |||||
| float dx, dy, width; | |||||
| float v_transform[3], inv_mat[4][4]; | |||||
| float local_up[3] = {0.0f, 0.0f, 1.0f}; | |||||
| int i; | |||||
| float radius, scale_top, scale_bottom; | |||||
| float height, center, center2; | |||||
| if ((!radius_top || !radius_bottom) && !cap_ends) { | |||||
| center = 0.5f; | |||||
| center2 = 0.5f; | |||||
| radius = 0.5f; | |||||
| } | |||||
| else { | |||||
| center = 0.25f; | |||||
Not Done Inline ActionsThis can rather simply be zero_v3(inv_mat[3]) mont29: This can rather simply be `zero_v3(inv_mat[3])` | |||||
| center2 = 0.75f; | |||||
| radius = 0.24f; | |||||
| } | |||||
| scale_top = (radius_top) ? (radius / radius_top) : (radius / radius_bottom); /* if we don't have a top or bottom */ | |||||
| scale_bottom = (radius_bottom) ? (radius / radius_bottom) : (radius / radius_top); /* then use the other scale */ | |||||
| height = cap_ends ? 0.5f : 1.0f; | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
| copy_m4_m4(inv_mat, mat); | |||||
| zero_v3(inv_mat[3]); /* to transform the upvector, we want to ignore translation */ | |||||
| mul_m4_v3(inv_mat, local_up); /* transform the upvector like we did the cone itself */ | |||||
| invert_m4_m4(inv_mat, mat); /* and now save the inverse of the whole transform for operation on vertices */ | |||||
| BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for ensuring the mesh has UVs */ | |||||
| dx = 0.0f; | |||||
| dy = cap_ends? 0.5f : 0.0f; | |||||
| width = 1.0f / segments; | |||||
| BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | |||||
| if (!BMO_elem_flag_test(bm, f, FACE_MARK)) | |||||
| continue; | |||||
| BMO_elem_flag_disable(bm, f, FACE_MARK); | |||||
Not Done Inline Actionscould just pass this in. campbellbarton: could just pass this in. | |||||
campbellbartonUnsubmitted Not Done Inline ActionsWhy disable? campbellbarton: Why disable? | |||||
| if (f->len == 4 && radius_top && radius_bottom) { | |||||
Not Done Inline Actions0.24f could be made a const float and assigned a value. Same for other values re-used many times in this patch. campbellbarton: `0.24f` could be made a `const float` and assigned a value. Same for other values re-used many… | |||||
| /* side face - so unwrap it in a rectangle */ | |||||
| BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, i) { | |||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | |||||
| switch (i) { | |||||
| case 0: | |||||
| dx += width; | |||||
| break; | |||||
| case 1: | |||||
| dy += height; | |||||
| break; | |||||
| case 2: | |||||
| dx -= width; | |||||
| break; | |||||
| case 3: | |||||
| dy -= height; | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| luv->uv[0] = dx; | |||||
| luv->uv[1] = dy; | |||||
| } | |||||
| dx += width; | |||||
| } | |||||
| else { | |||||
| /* top or bottom face - so unwrap it by transforming back to a circle and using the X/Y coords */ | |||||
| BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { | |||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | |||||
| copy_v3_v3(v_transform, l->v->co); | |||||
| mul_m4_v3(inv_mat, v_transform); | |||||
| if (dot_v3v3(f->no, local_up) > 0) { /* if this is a top face of the cone */ | |||||
| luv->uv[0] = center + v_transform[0] * scale_top; | |||||
| luv->uv[1] = center + v_transform[1] * scale_top; | |||||
| } | |||||
| else { | |||||
| luv->uv[0] = center2 + v_transform[0] * scale_bottom; | |||||
| luv->uv[1] = center + v_transform[1] * scale_bottom; | |||||
Not Done Inline Actionscan use the dot product here. campbellbarton: can use the dot product here. | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| void bmo_create_cube_exec(BMesh *bm, BMOperator *op) | void bmo_create_cube_exec(BMesh *bm, BMOperator *op) | ||||
| { | { | ||||
| BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8; | BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8; | ||||
| float vec[3], mat[4][4], off = BMO_slot_float_get(op->slots_in, "size") / 2.0f; | float vec[3], mat[4][4], off = BMO_slot_float_get(op->slots_in, "size") / 2.0f; | ||||
| const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); | |||||
| BMO_slot_mat4_get(op->slots_in, "matrix", mat); | BMO_slot_mat4_get(op->slots_in, "matrix", mat); | ||||
| Context not available. | |||||
| BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, false); | BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, false); | ||||
| BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); | ||||
| if (calc_uvs) | |||||
| BM_mesh_calc_uvs_cube(bm); | |||||
| } | |||||
| void BM_mesh_calc_uvs_cube(BMesh *bm) | |||||
| { | |||||
| int cd_loop_uv_offset, faceindex, loopindex; | |||||
| float dx, dy; | |||||
| BMFace *f; | |||||
| BMLoop *l; | |||||
| BMIter iter, liter; | |||||
| MLoopUV *luv; | |||||
| bool flagged; | |||||
| const float width = 0.25f; | |||||
Not Done Inline ActionsThat flag is already disabled here. ;) mont29: That flag is already disabled here. ;) | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
| BLI_assert(cd_loop_uv_offset != -1); /* the caller can ensure that we have UVs */ | |||||
| dx = 0.375f; | |||||
| dy = 0.0f; | |||||
| BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, faceindex) { | |||||
| flagged = true; | |||||
| BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loopindex) { | |||||
| if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) { | |||||
| flagged = false; | |||||
| continue; | |||||
| } | |||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | |||||
| luv->uv[0] = dx; | |||||
| luv->uv[1] = dy; | |||||
| switch (loopindex) { | |||||
| case 0: | |||||
| dx += width; | |||||
Not Done Inline ActionsNo need to set dx/dy in the default case imho, this one will never be reached anyway. mont29: No need to set dx/dy in the default case imho, this one will never be reached anyway. | |||||
| break; | |||||
| case 1: | |||||
| dy += width; | |||||
| break; | |||||
| case 2: | |||||
| dx -= width; | |||||
| break; | |||||
| case 3: | |||||
| dy -= width; | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (flagged) { | |||||
| if (dy >= 0.75f && dx > 0.125f) { | |||||
| dx = 0.125f; | |||||
| dy = 0.5f; | |||||
| } | |||||
| else if (dx <= 0.125f) { | |||||
| dx = 0.625f; | |||||
| dy = 0.5f; | |||||
| } | |||||
| else { | |||||
| dy += 0.25f; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| Context not available. | |||||
Whats the purpose of disabling these flags?