static void sculpt_undo_restore_deformed(const SculptSession *ss, SculptUndoNode *unode, int uindex, int oindex, float coord[3]) { if (unode->orig_co) { swap_v3_v3(coord, unode->orig_co[uindex]); copy_v3_v3(unode->co[uindex], ss->deform_cos[oindex]); } else { swap_v3_v3(coord, unode->co[uindex]); } }
static void occ_build_split(OcclusionTree *tree, int begin, int end, int *split) { float min[3], max[3], mid; int axis, a, enda; /* split in middle of boundbox. this seems faster than median split * on complex scenes, possibly since it avoids two distant faces to * be in the same node better? */ axis = occ_find_bbox_axis(tree, begin, end, min, max); mid = 0.5f * (min[axis] + max[axis]); a = begin; enda = end; while (a < enda) { if (tree->co[a][axis] > mid) { enda--; SWAP(OccFace, tree->face[a], tree->face[enda]); swap_v3_v3(tree->co[a], tree->co[enda]); } else a++; } *split = enda; }
static bool test_swap_v3_v3(float a[3], float b[3]) { /* no need for float comparison here (memory is exactly equal or not) */ if (memcmp(a, b, sizeof(float[3])) != 0) { swap_v3_v3(a, b); return true; } else { return false; } }
/* Swap pairs of lattice points along a specified axis * - Helper for lattice_flip_exec() */ static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis) { BPoint *bpA, *bpB; int numU = lt->pntsu; int numV = lt->pntsv; int numW = lt->pntsw; int u0 = u, u1 = u; int v0 = v, v1 = v; int w0 = w, w1 = w; /* get pair index by just overriding the relevant pair-value * - "-1" else buffer overflow */ switch (axis) { case LATTICE_FLIP_U: u1 = numU - u - 1; break; case LATTICE_FLIP_V: v1 = numV - v - 1; break; case LATTICE_FLIP_W: w1 = numW - w - 1; break; } /* get points to operate on */ bpA = <->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)]; bpB = <->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)]; /* Swap all coordinates, so that flipped coordinates belong to * the indices on the correct side of the lattice. * * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4) * Indices: (0,L) (1,R) --> (0,L) (1,R) */ swap_v3_v3(bpA->vec, bpB->vec); /* However, we need to mirror the coordinate values on the axis we're dealing with, * otherwise we'd have effectively only rotated the points around. If we don't do this, * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms * such as flipped normals, etc. * * Coords: (3 4) |0| (-2 4) --\ * \-> (-3 4) |0| (2 4) * Indices: (0,L) (1,R) --> (0,L) (1,R) */ lattice_flip_point_value(lt, u0, v0, w0, mid, axis); lattice_flip_point_value(lt, u1, v1, w1, mid, axis); }
static void mirror_bezier_xaxis_ex(BezTriple *bezt, const float center) { float diff; int i; for (i = 0; i < 3; i++) { diff = (center - bezt->vec[i][0]); bezt->vec[i][0] = (center + diff); } swap_v3_v3(bezt->vec[0], bezt->vec[2]); SWAP(char, bezt->h1, bezt->h2); SWAP(char, bezt->f1, bezt->f3); }
static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNode *unode) { Scene *scene = CTX_data_scene(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; MVert *mvert; int *index, i, j; if (unode->maxvert) { /* regular mesh restore */ if (ss->kb && strcmp(ss->kb->name, unode->shapeName)) { /* shape key has been changed before calling undo operator */ Key *key = BKE_key_from_object(ob); KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL; if (kb) { ob->shapenr = BLI_findindex(&key->block, kb) + 1; sculpt_update_mesh_elements(scene, sd, ob, 0, FALSE); WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); } else { /* key has been removed -- skip this undo node */ return 0; } } index = unode->index; mvert = ss->mvert; if (ss->kb) { float (*vertCos)[3]; vertCos = BKE_key_convert_to_vertcos(ob, ss->kb); for (i = 0; i < unode->totvert; i++) { if (ss->modifiers_active) { sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); } else { if (unode->orig_co) swap_v3_v3(vertCos[index[i]], unode->orig_co[i]); else swap_v3_v3(vertCos[index[i]], unode->co[i]); } } /* propagate new coords to keyblock */ sculpt_vertcos_to_key(ob, ss->kb, vertCos); /* pbvh uses it's own mvert array, so coords should be */ /* propagated to pbvh here */ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos); MEM_freeN(vertCos); } else { for (i = 0; i < unode->totvert; i++) { if (ss->modifiers_active) { sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co); } else { if (unode->orig_co) swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]); else swap_v3_v3(mvert[index[i]].co, unode->co[i]); } mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } else if (unode->maxgrid && dm->getGridData) { /* multires restore */ CCGElem **grids, *grid; CCGKey key; float (*co)[3]; int gridsize; grids = dm->getGridData(dm); gridsize = dm->getGridSize(dm); dm->getGridKey(dm, &key); co = unode->co; for (j = 0; j < unode->totgrid; j++) { grid = grids[unode->grids[j]]; for (i = 0; i < gridsize * gridsize; i++, co++) swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[0]); } } return 1; }
static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = CTX_data_edit_object(C); bArmature *arm = (bArmature *)ob->data; ListBase chains = {NULL, NULL}; LinkData *chain; /* get chains of bones (ends on chains) */ chains_find_tips(arm->edbo, &chains); if (BLI_listbase_is_empty(&chains)) return OPERATOR_CANCELLED; /* ensure that mirror bones will also be operated on */ armature_tag_select_mirrored(arm); /* clear BONE_TRANSFORM flags * - used to prevent duplicate/canceling operations from occurring [#34123] * - BONE_DONE cannot be used here as that's already used for mirroring */ armature_clear_swap_done_flags(arm); /* loop over chains, only considering selected and visible bones */ for (chain = chains.first; chain; chain = chain->next) { EditBone *ebo, *child = NULL, *parent = NULL; /* loop over bones in chain */ for (ebo = chain->data; ebo; ebo = parent) { /* parent is this bone's original parent * - we store this, as the next bone that is checked is this one * but the value of ebo->parent may change here... */ parent = ebo->parent; /* skip bone if already handled... [#34123] */ if ((ebo->flag & BONE_TRANSFORM) == 0) { /* only if selected and editable */ if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) { /* swap head and tail coordinates */ swap_v3_v3(ebo->head, ebo->tail); /* do parent swapping: * - use 'child' as new parent * - connected flag is only set if points are coincidental */ ebo->parent = child; if ((child) && equals_v3v3(ebo->head, child->tail)) ebo->flag |= BONE_CONNECTED; else ebo->flag &= ~BONE_CONNECTED; /* get next bones * - child will become the new parent of next bone */ child = ebo; } else { /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it * as it will be facing in opposite direction */ if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) { ebo->parent = NULL; ebo->flag &= ~BONE_CONNECTED; } /* get next bones * - child will become new parent of next bone (not swapping occurred, * so set to NULL to prevent infinite-loop) */ child = NULL; } /* tag as done (to prevent double-swaps) */ ebo->flag |= BONE_TRANSFORM; } } } /* free chains */ BLI_freelistN(&chains); /* clear temp flags */ armature_clear_swap_done_flags(arm); armature_tag_unselect(arm); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); return OPERATOR_FINISHED; }
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, GPUTexture *tex, const float min[3], const float max[3], const int res[3], float dx, float UNUSED(base_scale), const float viewnormal[3], GPUTexture *tex_shadow, GPUTexture *tex_flame) { const float ob_sizei[3] = { 1.0f / fabsf(ob->size[0]), 1.0f / fabsf(ob->size[1]), 1.0f / fabsf(ob->size[2])}; int i, j, k, n, good_index; float d /*, d0 */ /* UNUSED */, dd, ds; float (*points)[3] = NULL; int numpoints = 0; float cor[3] = {1.0f, 1.0f, 1.0f}; int gl_depth = 0, gl_blend = 0; int use_fire = (sds->active_fields & SM_ACTIVE_FIRE); /* draw slices of smoke is adapted from c++ code authored * by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */ float cv[][3] = { {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} }; /* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */ float edges[12][2][3] = { {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, {{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}} }; unsigned char *spec_data; float *spec_pixels; GPUTexture *tex_spec; GPUProgram *smoke_program; int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE; float size[3]; if (!tex) { printf("Could not allocate 3D texture for 3D View smoke drawing.\n"); return; } #ifdef DEBUG_DRAW_TIME TIMEIT_START(draw); #endif /* generate flame spectrum texture */ #define SPEC_WIDTH 256 #define FIRE_THRESH 7 #define MAX_FIRE_ALPHA 0.06f #define FULL_ON_FIRE 100 spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char)); flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000); spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float)); for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { for (k = 0; k < SPEC_WIDTH; k++) { int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4; if (k >= FIRE_THRESH) { spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f; spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f; spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f; spec_pixels[index + 3] = MAX_FIRE_ALPHA * ( (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH)); } else { spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f; } } } } tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL); #undef SPEC_WIDTH #undef FIRE_THRESH #undef MAX_FIRE_ALPHA #undef FULL_ON_FIRE sub_v3_v3v3(size, max, min); /* maxx, maxy, maxz */ cv[0][0] = max[0]; cv[0][1] = max[1]; cv[0][2] = max[2]; /* minx, maxy, maxz */ cv[1][0] = min[0]; cv[1][1] = max[1]; cv[1][2] = max[2]; /* minx, miny, maxz */ cv[2][0] = min[0]; cv[2][1] = min[1]; cv[2][2] = max[2]; /* maxx, miny, maxz */ cv[3][0] = max[0]; cv[3][1] = min[1]; cv[3][2] = max[2]; /* maxx, maxy, minz */ cv[4][0] = max[0]; cv[4][1] = max[1]; cv[4][2] = min[2]; /* minx, maxy, minz */ cv[5][0] = min[0]; cv[5][1] = max[1]; cv[5][2] = min[2]; /* minx, miny, minz */ cv[6][0] = min[0]; cv[6][1] = min[1]; cv[6][2] = min[2]; /* maxx, miny, minz */ cv[7][0] = max[0]; cv[7][1] = min[1]; cv[7][2] = min[2]; copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */ copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */ copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */ copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */ copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */ copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */ copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */ copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */ copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */ copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */ copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */ copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */ // printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]); // printf("min[2]: %f, max[2]: %f\n", min[2], max[2]); edges[0][1][2] = size[2]; edges[1][1][2] = size[2]; edges[2][1][2] = size[2]; edges[3][1][2] = size[2]; edges[4][1][1] = size[1]; edges[5][1][1] = size[1]; edges[6][1][1] = size[1]; edges[7][1][1] = size[1]; edges[8][1][0] = size[0]; edges[9][1][0] = size[0]; edges[10][1][0] = size[0]; edges[11][1][0] = size[0]; glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); /* find cube vertex that is closest to the viewer */ for (i = 0; i < 8; i++) { float x, y, z; x = cv[i][0] - viewnormal[0] * size[0] * 0.5f; y = cv[i][1] - viewnormal[1] * size[1] * 0.5f; z = cv[i][2] - viewnormal[2] * size[2] * 0.5f; if ((x >= min[0]) && (x <= max[0]) && (y >= min[1]) && (y <= max[1]) && (z >= min[2]) && (z <= max[2])) { break; } } if (i >= 8) { /* fallback, avoid using buffer over-run */ i = 0; } // printf("i: %d\n", i); // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]); smoke_program = GPU_shader_get_builtin_program(progtype); if (smoke_program) { GPU_program_bind(smoke_program); /* cell spacing */ GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0); /* custom parameter for smoke style (higher = thicker) */ if (sds->active_fields & SM_ACTIVE_COLORS) GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0); else GPU_program_parameter_4f(smoke_program, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0); } else printf("Your gfx card does not support 3D View smoke drawing.\n"); GPU_texture_bind(tex, 0); if (tex_shadow) GPU_texture_bind(tex_shadow, 1); else printf("No volume shadow\n"); if (tex_flame) { GPU_texture_bind(tex_flame, 2); GPU_texture_bind(tex_spec, 3); } if (!GPU_non_power_of_two_support()) { cor[0] = (float)res[0] / (float)power_of_2_max_u(res[0]); cor[1] = (float)res[1] / (float)power_of_2_max_u(res[1]); cor[2] = (float)res[2] / (float)power_of_2_max_u(res[2]); } cor[0] /= size[0]; cor[1] /= size[1]; cor[2] /= size[2]; /* our slices are defined by the plane equation a*x + b*y +c*z + d = 0 * (a,b,c), the plane normal, are given by viewdir * d is the parameter along the view direction. the first d is given by * inserting previously found vertex into the plane equation */ /* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */ ds = (fabsf(viewnormal[0]) * size[0] + fabsf(viewnormal[1]) * size[1] + fabsf(viewnormal[2]) * size[2]); dd = max_fff(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f; n = 0; good_index = i; // printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds); points = MEM_callocN(sizeof(*points) * 12, "smoke_points_preview"); while (1) { float p0[3]; float tmp_point[3], tmp_point2[3]; if (dd * (float)n > ds) break; copy_v3_v3(tmp_point, viewnormal); mul_v3_fl(tmp_point, -dd * ((ds / dd) - (float)n)); add_v3_v3v3(tmp_point2, cv[good_index], tmp_point); d = dot_v3v3(tmp_point2, viewnormal); // printf("my d: %f\n", d); /* intersect_edges returns the intersection points of all cube edges with * the given plane that lie within the cube */ numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges); // printf("points: %d\n", numpoints); if (numpoints > 2) { copy_v3_v3(p0, points[0]); /* sort points to get a convex polygon */ for (i = 1; i < numpoints - 1; i++) { for (j = i + 1; j < numpoints; j++) { if (!convex(p0, viewnormal, points[j], points[i])) { swap_v3_v3(points[i], points[j]); } } } /* render fire slice */ if (use_fire) { if (GLEW_VERSION_1_4) glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE); else glBlendFunc(GL_SRC_ALPHA, GL_ONE); GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { glTexCoord3d((points[i][0] - min[0]) * cor[0], (points[i][1] - min[1]) * cor[1], (points[i][2] - min[2]) * cor[2]); glVertex3f(points[i][0] * ob_sizei[0], points[i][1] * ob_sizei[1], points[i][2] * ob_sizei[2]); } glEnd(); } /* render smoke slice */ if (GLEW_VERSION_1_4) glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { glTexCoord3d((points[i][0] - min[0]) * cor[0], (points[i][1] - min[1]) * cor[1], (points[i][2] - min[2]) * cor[2]); glVertex3f(points[i][0] * ob_sizei[0], points[i][1] * ob_sizei[1], points[i][2] * ob_sizei[2]); } glEnd(); } n++; } #ifdef DEBUG_DRAW_TIME printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw)); TIMEIT_END(draw); #endif if (tex_shadow) GPU_texture_unbind(tex_shadow); GPU_texture_unbind(tex); if (tex_flame) { GPU_texture_unbind(tex_flame); GPU_texture_unbind(tex_spec); } GPU_texture_free(tex_spec); free(spec_data); free(spec_pixels); if (smoke_program) GPU_program_unbind(smoke_program); MEM_freeN(points); if (!gl_blend) { glDisable(GL_BLEND); } if (gl_depth) { glEnable(GL_DEPTH_TEST); } }