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. | |||||
| 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 | ||||
| BM_mesh_calc_uvs_grid(bm, xtot, ytot); | |||||
| } | |||||
| void BM_mesh_calc_uvs_grid(BMesh *bm, unsigned int x_segments, unsigned int y_segments) | |||||
| { | |||||
| BMFace *f; | |||||
| BMLoop *l; | |||||
| BMIter iter, liter; | |||||
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… | |||||
| MLoopUV *luv; | |||||
| int cd_loop_uv_offset, loopindex; | |||||
| float x, y, dx, dy; | |||||
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… | |||||
| 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; | |||||
| y = 0; | |||||
| 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); | |||||
| 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) { | |||||
Not Done Inline ActionsWhy disable? campbellbarton: Why disable? | |||||
| 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; | |||||
| y += dy; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) | void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) | ||||
| 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); | ||||
| } | } | ||||
| 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. | |||||
| BMO_op_finish(bm, &bmop); | BMO_op_finish(bm, &bmop); | ||||
| } | } | ||||
| 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); | ||||
| } | } | ||||
| /* since we need to call alloca best to split this loop body into its own function */ | |||||
| void BM_mesh_calc_uvs_sphere_face(BMFace *f, float rot[4][4], int cd_loop_uv_offset) { | |||||
| float **uvs = BLI_array_alloca(uvs, f->len); | |||||
| BMLoop *l; | |||||
| BMIter iter; | |||||
| MLoopUV *luv; | |||||
| float v[3] = {0}; | |||||
| float dx; | |||||
| int mi, i; | |||||
| BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) { | |||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | |||||
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 ;) | |||||
| copy_v3_v3(v, l->v->co); | |||||
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… | |||||
| mul_m4_v3(rot, v); | |||||
| map_to_sphere(&luv->uv[0], &luv->uv[1], v[0], v[1], v[2]); | |||||
| uvs[i] = luv->uv; | |||||
| } | |||||
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? | |||||
| mi = 0; /* fix awkwardly-wrapping UVs */ | |||||
| 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]; | |||||
| if (dx > 0.5f) uvs[i][0] += 1.0f; | |||||
| } | |||||
| } | |||||
| } | |||||
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). | |||||
| void BM_mesh_calc_uvs_sphere(BMesh *bm) | |||||
| { | |||||
| BMFace *f; | |||||
| BMIter iter; | |||||
| int cd_loop_uv_offset; | |||||
| float v[3] = { 0 }; | |||||
Not Done Inline Actionseeeh, a one-line if() I missed! mont29: eeeh, a one-line if() I missed! | |||||
| float rot[4][4]; | |||||
| float axis[3] = { 0.806, 0.329, 0.491 }; /* magic numbers - seem to be best for both ico and uv sphere projections */ | |||||
| float angle = 77.5; /* more magic! */ | |||||
| float size[3] = { 1, 1, 1 }; | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
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. | |||||
| 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 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… | |||||
| void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) | void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) | ||||
| { | { | ||||
| BMVert *eve; | BMVert *eve; | ||||
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… | |||||
| 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); | ||||
| 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) { | |||||
| BMFace *f; | |||||
| BMLoop *l; | |||||
| BMIter iter, liter; | |||||
| MLoopUV *luv; | |||||
Not Done Inline ActionsCode style: use 0.5f, not .5 kevindietrich: Code style: use 0.5f, not .5 | |||||
| int cd_loop_uv_offset; | |||||
| int loopindex; | |||||
| float v_transform[3], inv_mat[4][4]; | |||||
| const float scale = .5f / radius; | |||||
| const float center = .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); | |||||
Not Done Inline Actionscampbellbarton: style: http://wiki.blender.org/index.php/Dev:Doc/Code_Style#Braces | |||||
| 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; | ||||
| float vec[3], mat[4][4], phi, phid; | BMFace *f; | ||||
| float vec[3], mat[4][4], normal_mat[4][4], phi, phid; | |||||
| float edge1[3], edge2[3]; | |||||
| 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"); | ||||
| float depth = BMO_slot_float_get(op->slots_in, "depth"); | float depth = BMO_slot_float_get(op->slots_in, "depth"); | ||||
| Context not available. | |||||
| return; | return; | ||||
| BMO_slot_mat4_get(op->slots_in, "matrix", mat); | BMO_slot_mat4_get(op->slots_in, "matrix", mat); | ||||
| copy_m4_m4(normal_mat, mat); | |||||
| for (a = 0; a < 3; ++a) { | |||||
| normal_mat[3][a] = 0; | |||||
| } | |||||
| phid = 2.0f * (float)M_PI / segs; | phid = 2.0f * (float)M_PI / segs; | ||||
| phi = 0; | phi = 0; | ||||
| Context not available. | |||||
| mul_m4_v3(mat, vec); | mul_m4_v3(mat, vec); | ||||
| cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); | cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); | ||||
| cent1->no[0] = cent1->no[1] = 0; | |||||
| cent1->no[2] = 1; | |||||
| mul_m4_v3(normal_mat, cent1->no); | |||||
| normalize_v3(cent1->no); | |||||
| vec[0] = vec[1] = 0.0f; | vec[0] = vec[1] = 0.0f; | ||||
| vec[2] = depth; | vec[2] = depth; | ||||
| mul_m4_v3(mat, vec); | mul_m4_v3(mat, vec); | ||||
| cent2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); | cent2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); | ||||
| cent2->no[0] = cent2->no[1] = 0; | |||||
| cent2->no[2] = -1; | |||||
| mul_m4_v3(normal_mat, cent2->no); | |||||
| normalize_v3(cent2->no); | |||||
| BMO_elem_flag_enable(bm, cent1, VERT_MARK); | BMO_elem_flag_enable(bm, cent1, VERT_MARK); | ||||
| BMO_elem_flag_enable(bm, cent2, VERT_MARK); | BMO_elem_flag_enable(bm, cent2, VERT_MARK); | ||||
| 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); | copy_v3_v3(f->no, cent1->no); | ||||
| 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); | copy_v3_v3(f->no, cent2->no); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_MARK); | |||||
| } | |||||
| copy_v3_v3(edge1, v2->co); | |||||
| sub_v3_v3(edge1, v1->co); | |||||
| if (dia1) { /* make sure we don't use a zero-length edge */ | |||||
| copy_v3_v3(edge2, lastv1->co); | |||||
| sub_v3_v3(edge2, v1->co); | |||||
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. | |||||
| } | |||||
| else { | |||||
| copy_v3_v3(edge2, lastv2->co); | |||||
| sub_v3_v3(edge2, v2->co); | |||||
| } | } | ||||
| 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); | |||||
| cross_v3_v3v3(f->no, edge1, edge2); /* cross edges to get a normal */ | |||||
| BMO_elem_flag_enable(bm, f, FACE_MARK); | |||||
| } | } | ||||
| else { | else { | ||||
| firstv1 = v1; | firstv1 = v1; | ||||
| Context not available. | |||||
| if (!a) | if (!a) | ||||
| return; | return; | ||||
| if (cap_ends) { | copy_v3_v3(edge1, firstv2->co); | ||||
| BMFace *f; | sub_v3_v3(edge1, firstv1->co); | ||||
| if (dia1) { /* make sure we don't use a zero-length edge */ | |||||
| copy_v3_v3(edge2, v1->co); | |||||
| sub_v3_v3(edge2, firstv1->co); | |||||
| } else { | |||||
| copy_v3_v3(edge2, v2->co); | |||||
| sub_v3_v3(edge2, v2->co); | |||||
| } | |||||
| f = BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, false); | |||||
| cross_v3_v3v3(f->no, edge1, edge2); /* cross edges to get a normal */ | |||||
| BMO_elem_flag_enable(bm, f, FACE_MARK); | |||||
| if (cap_ends) { | |||||
| 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); | copy_v3_v3(f->no, cent1->no); | ||||
| 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); | copy_v3_v3(f->no, cent2->no); | ||||
| BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_MARK); | |||||
| } | } | ||||
| BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1); | |||||
| 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) | |||||
| { | |||||
| 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, 0, 1}; | |||||
| int i, sidecount = 0; | |||||
Not Done Inline ActionsThis can rather simply be zero_v3(inv_mat[3]) mont29: This can rather simply be `zero_v3(inv_mat[3])` | |||||
| const float radius = .24f; | |||||
| const float scale_top = (radius_top) ? (radius / radius_top) : (radius / radius_bottom); /* if we don't have a top or bottom */ | |||||
| const float scale_bottom = (radius_bottom) ? (radius / radius_bottom) : (radius / radius_top); /* then use the other scale */ | |||||
| const float center = .25f; | |||||
| const float center2 = .75f; | |||||
| const float height = .5f; | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
| copy_m4_m4(inv_mat, mat); | |||||
| for (i = 0; i < 3; ++i) /* to transform the upvector, we want to ignore translation */ | |||||
| inv_mat[3][i] = 0; | |||||
| 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; | |||||
| dy = .5; | |||||
| BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | |||||
| if (BMO_elem_flag_test(bm, f, FACE_MARK)) ++sidecount; | |||||
| } | |||||
| sidecount /= 3; /* we only use this for truncated cones - so even if there aren't actually three faces / side this is ok! */ | |||||
| width = 1.0f / sidecount; | |||||
Not Done Inline Actionscould just pass this in. campbellbarton: could just pass this in. | |||||
Not Done Inline ActionsWhy disable? campbellbarton: Why disable? | |||||
| BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | |||||
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… | |||||
| if (!BMO_elem_flag_test(bm, f, FACE_MARK)) continue; | |||||
| BMO_elem_flag_disable(bm, f, FACE_MARK); | |||||
| if (f->len == 4 && radius_top && radius_bottom) { /* 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 (angle_v3v3(f->no, local_up) < M_PI_2) { /* if this is a top face of the cone (note: normals seem sort of backwards in create_cone_exec() above... so this actually detects bottom faces? hmm... */ | |||||
| luv->uv[0] = center + v_transform[0] * scale_bottom; | |||||
| luv->uv[1] = center + v_transform[1] * scale_bottom; | |||||
| } | |||||
| else { | |||||
| luv->uv[0] = center2 + v_transform[0] * scale_top; | |||||
Not Done Inline Actionscan use the dot product here. campbellbarton: can use the dot product here. | |||||
| luv->uv[1] = center + v_transform[1] * scale_top; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| 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; | ||||
| 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); | ||||
| 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 = .25f; | |||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | |||||
Not Done Inline ActionsThat flag is already disabled here. ;) mont29: That flag is already disabled here. ;) | |||||
| BLI_assert(cd_loop_uv_offset != -1); /* the caller can ensure that we have UVs */ | |||||
| dx = .375; | |||||
| dy = 0; | |||||
| 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; | |||||
| BMO_elem_flag_disable(bm, l->v, VERT_MARK); | |||||
| 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: | |||||
| dx = dy = 0; | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (flagged) { | |||||
| if (dy >= .75f && dx > .125) { | |||||
| dx = .125; | |||||
| dy = .5; | |||||
| } | |||||
| else if (dx <= .125) { | |||||
| dx = .625; | |||||
| dy = .5; | |||||
| } | |||||
| else { | |||||
| dy += .25; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| Context not available. | |||||
Whats the purpose of disabling these flags?