void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int rendering, int do_preview, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { #ifdef WITH_COMPOSITOR COM_execute(rd, scene, ntree, rendering, view_settings, display_settings); #else UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings); #endif UNUSED_VARS(do_preview); }
/* Init Textures, Framebuffers, Storage and Shaders. * It is called for every frames. * (Optional) */ static void EDIT_TEXT_engine_init(void *vedata) { EDIT_TEXT_TextureList *txl = ((EDIT_TEXT_Data *)vedata)->txl; EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; UNUSED_VARS(txl, fbl, stl); /* Init Framebuffers like this: order is attachment order (for color texs) */ /* * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; */ /* DRW_framebuffer_init takes care of checking if * the framebuffer is valid and has the right size*/ /* * float *viewport_size = DRW_viewport_size_get(); * DRW_framebuffer_init(&fbl->occlude_wire_fb, * (int)viewport_size[0], (int)viewport_size[1], * tex, 2); */ if (!e_data.wire_sh) { e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); } if (!e_data.overlay_select_sh) { e_data.overlay_select_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); } if (!e_data.overlay_cursor_sh) { e_data.overlay_cursor_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); } }
/* Add geometry to shadingGroups. Execute for each objects */ static void EDIT_TEXT_cache_populate(void *vedata, Object *ob) { EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); UNUSED_VARS(psl, stl); if (ob->type == OB_FONT) { if (ob == draw_ctx->object_edit) { const Curve *cu = ob->data; /* Get geometry cache */ struct GPUBatch *geom; bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; if ((cu->flag & CU_FAST) || !has_surface) { geom = DRW_cache_text_edge_wire_get(ob); if (geom) { DRW_shgroup_call(stl->g_data->wire_shgrp, geom, ob); } } else { /* object mode draws */ } edit_text_cache_populate_select(vedata, ob); edit_text_cache_populate_cursor(vedata, ob); edit_text_cache_populate_boxes(vedata, ob); } } }
bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base) { double frs_sec_base_double; if (anim->frs_sec) { if (anim->frs_sec > SHRT_MAX) { /* We cannot store original rational in our short/float format, * we need to approximate it as best as we can... */ *frs_sec = SHRT_MAX; frs_sec_base_double = anim->frs_sec_base * (double)SHRT_MAX / (double)anim->frs_sec; } else { *frs_sec = anim->frs_sec; frs_sec_base_double = anim->frs_sec_base; } #ifdef WITH_FFMPEG if (no_av_base) { *frs_sec_base = (float)(frs_sec_base_double / AV_TIME_BASE); } else { *frs_sec_base = (float)frs_sec_base_double; } #else UNUSED_VARS(no_av_base); *frs_sec_base = (float)frs_sec_base_double; #endif BLI_assert(*frs_sec > 0); BLI_assert(*frs_sec_base > 0.0f); return true; } return false; }
static void rna_SmokeModifier_velocity_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; int length[RNA_MAX_ARRAY_DIMENSION]; int size = rna_SmokeModifier_velocity_grid_get_length(ptr, length); float *vx, *vy, *vz; int i; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); vx = smoke_get_velocity_x(sds->fluid); vy = smoke_get_velocity_y(sds->fluid); vz = smoke_get_velocity_z(sds->fluid); for (i = 0; i < size; i += 3) { *(values++) = *(vx++); *(values++) = *(vy++); *(values++) = *(vz++); } BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RNA_boolean_set(op->ptr, "init_scene_frame_range", true); if (!RNA_struct_property_is_set(op->ptr, "filepath")) { Main *bmain = CTX_data_main(C); char filepath[FILE_MAX]; if (bmain->name[0] == '\0') { BLI_strncpy(filepath, "untitled", sizeof(filepath)); } else { BLI_strncpy(filepath, bmain->name, sizeof(filepath)); } BLI_replace_extension(filepath, sizeof(filepath), ".abc"); RNA_string_set(op->ptr, "filepath", filepath); } WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; UNUSED_VARS(event); }
static void rna_SmokeModifier_color_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); if (sds->flags & MOD_SMOKE_HIGHRES) { if (smoke_turbulence_has_colors(sds->wt)) smoke_turbulence_get_rgba(sds->wt, values, 0); else smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, values, 0); } else { if (smoke_has_colors(sds->fluid)) smoke_get_rgba(sds->fluid, values, 0); else smoke_get_rgba_from_density(sds->fluid, sds->active_color, values, 0); } BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
static void rna_SmokeModifier_flame_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; int length[RNA_MAX_ARRAY_DIMENSION]; int size = rna_SmokeModifier_grid_get_length(ptr, length); float *flame; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) flame = smoke_turbulence_get_flame(sds->wt); else flame = smoke_get_flame(sds->fluid); if (flame) memcpy(values, flame, size * sizeof(float)); else memset(values, 0, size * sizeof(float)); BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values) { #ifdef WITH_SMOKE SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data; int length[RNA_MAX_ARRAY_DIMENSION]; int size = rna_SmokeModifier_heat_grid_get_length(ptr, length); float *heat; BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ); heat = smoke_get_heat(sds->fluid); if (heat != NULL) { /* scale heat values from -2.0-2.0 to -1.0-1.0. */ for (int i = 0; i < size; i++) { values[i] = heat[i] * 0.5f; } } else { memset(values, 0, size * sizeof(float)); } BLI_rw_mutex_unlock(sds->fluid_mutex); #else UNUSED_VARS(ptr, values); #endif }
static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata) { WM_exit(C); UNUSED_VARS(event, userdata); return WM_UI_HANDLER_BREAK; }
static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata; const MLoopTri *lt = &data->sys->heat.mlooptri[index]; const MLoop *mloop = data->sys->heat.mloop; float (*verts)[3] = data->sys->heat.verts; const float *vtri_co[3]; float dist_test; vtri_co[0] = verts[mloop[lt->tri[0]].v]; vtri_co[1] = verts[mloop[lt->tri[1]].v]; vtri_co[2] = verts[mloop[lt->tri[2]].v]; #ifdef USE_KDOPBVH_WATERTIGHT if (isect_ray_tri_watertight_v3(data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL)) #else UNUSED_VARS(ray); if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL)) #endif { if (dist_test < hit->dist) { float n[3]; normal_tri_v3(n, UNPACK3(vtri_co)); if (dot_v3v3(n, data->vec) < -1e-5f) { hit->index = index; hit->dist = dist_test; } } } }
/* Draw time ! Control rendering pipeline from here */ static void EDIT_TEXT_draw_scene(void *vedata) { EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; /* Default framebuffer and texture */ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); UNUSED_VARS(fbl, dfbl, dtxl); /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ /* * DRW_framebuffer_texture_detach(dtxl->depth); * DRW_framebuffer_bind(fbl->custom_fb); * DRW_draw_pass(psl->pass); * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); * DRW_framebuffer_bind(dfbl->default_fb); */ DRW_draw_pass(psl->wire_pass); if (!DRW_pass_is_empty(psl->text_box_pass)) { DRW_draw_pass(psl->text_box_pass); } set_inverted_drawing(1); DRW_draw_pass(psl->overlay_select_pass); DRW_draw_pass(psl->overlay_cursor_pass); set_inverted_drawing(0); /* If you changed framebuffer, double check you rebind * the default one with its textures attached before finishing */ }
/* Optional: Post-cache_populate callback */ static void EDIT_TEXT_cache_finish(void *vedata) { EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; /* Do something here! dependent on the objects gathered */ UNUSED_VARS(psl, stl); }
static void rna_CacheFile_update(Main *bmain, Scene *scene, PointerRNA *ptr) { CacheFile *cache_file = (CacheFile *)ptr->data; DAG_id_tag_update(&cache_file->id, 0); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); UNUSED_VARS(bmain, scene); }
static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_opensubdiv, bool use_instancing, bool use_new_shading) { /* some useful defines to detect GPU type */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) { strcat(defines, "#define GPU_ATI\n"); if (GLEW_VERSION_3_0) { /* TODO(merwin): revisit this version check; GLEW_VERSION_3_0 means GL 3.0 or newer */ strcat(defines, "#define CLIP_WORKAROUND\n"); } } else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) strcat(defines, "#define GPU_NVIDIA\n"); else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) strcat(defines, "#define GPU_INTEL\n"); if (GPU_bicubic_bump_support()) strcat(defines, "#define BUMP_BICUBIC\n"); if (GLEW_VERSION_3_0) { strcat(defines, "#define BIT_OPERATIONS\n"); } #ifdef WITH_OPENSUBDIV /* TODO(sergey): Check whether we actually compiling shader for * the OpenSubdiv mesh. */ if (use_opensubdiv) { strcat(defines, "#define USE_OPENSUBDIV\n"); /* TODO(sergey): not strictly speaking a define, but this is * a global typedef which we don't have better place to define * in yet. */ strcat(defines, "struct VertexData {\n" " vec4 position;\n" " vec3 normal;\n" " vec2 uv;" "};\n"); } #else UNUSED_VARS(use_opensubdiv); #endif if (use_instancing) { strcat(defines, "#define USE_INSTANCING\n"); } if (use_new_shading) { strcat(defines, "#define USE_NEW_SHADING\n"); } return; }
/** * \note \a viewdist is only for ortho at the moment. */ void bglPolygonOffset(float viewdist, float dist) { static float winmat[16], offset = 0.0f; if (dist != 0.0f) { float offs; // glEnable(GL_POLYGON_OFFSET_FILL); // glPolygonOffset(-1.0, -1.0); /* hack below is to mimic polygon offset */ glMatrixMode(GL_PROJECTION); glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat); /* dist is from camera to center point */ if (winmat[15] > 0.5f) { #if 1 offs = 0.00001f * dist * viewdist; // ortho tweaking #else static float depth_fac = 0.0f; if (depth_fac == 0.0f) { int depthbits; glGetIntegerv(GL_DEPTH_BITS, &depthbits); depth_fac = 1.0f / (float)((1 << depthbits) - 1); } offs = (-1.0 / winmat[10]) * dist * depth_fac; UNUSED_VARS(viewdist); #endif } else { /* This adjustment effectively results in reducing the Z value by 0.25%. * * winmat[14] actually evaluates to `-2 * far * near / (far - near)`, * is very close to -0.2 with default clip range, and is used as the coefficient multiplied by `w / z`, * thus controlling the z dependent part of the depth value. */ offs = winmat[14] * -0.0025f * dist; } winmat[14] -= offs; offset += offs; glLoadMatrixf(winmat); glMatrixMode(GL_MODELVIEW); } else { glMatrixMode(GL_PROJECTION); winmat[14] += offset; offset = 0.0; glLoadMatrixf(winmat); glMatrixMode(GL_MODELVIEW); } }
static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *ptr) { # ifndef WITH_MOD_FLUID UNUSED_VARS(ptr); return 0; # else char value[32]; rna_DomainFluidSettings_memory_estimate_get(ptr, value); return strlen(value); # endif }
static bool dependsOnNormals(ModifierData *md) { #ifdef WITH_OPENSUBDIV SubsurfModifierData *smd = (SubsurfModifierData *) md; if (smd->use_opensubdiv && md->next == NULL) { return true; } #else UNUSED_VARS(md); #endif return false; }
CameraSettings::CameraSettings(CamTypes type, float x, float y, float z) { UNUSED_VARS(x, y, z); switch(type) { case FIXED_POS: setDefault(); break; default: break; } }
static void updateDepsgraph(ModifierData *md, struct Main *bmain, struct Scene *scene, Object *ob, struct DepsNodeHandle *node) { MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; if (mcmd->cache_file != NULL) { DEG_add_object_cache_relation(node, mcmd->cache_file, DEG_OB_COMP_CACHE, "Mesh Cache File"); } UNUSED_VARS(bmain, scene, ob); }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag flag) { #ifdef WITH_ALEMBIC MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; Scene *scene = md->scene; const float frame = BKE_scene_frame_get(scene); const float time = BKE_cachefile_time_offset(mcmd->cache_file, frame, FPS); const char *err_str = NULL; CacheFile *cache_file = mcmd->cache_file; BKE_cachefile_ensure_handle(G.main, cache_file); DerivedMesh *result = ABC_read_mesh(cache_file->handle, ob, dm, mcmd->object_path, time, &err_str, mcmd->read_flag); if (err_str) { modifier_setError(md, "%s", err_str); } return result ? result : dm; UNUSED_VARS(flag); #else return dm; UNUSED_VARS(md, ob, flag); #endif }
static void updateDepgraph(ModifierData *md, DagForest *forest, struct Main *bmain, struct Scene *scene, Object *ob, DagNode *obNode) { MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md; if (mcmd->cache_file != NULL) { DagNode *curNode = dag_get_node(forest, mcmd->cache_file); dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Cache File Modifier"); } UNUSED_VARS(bmain, scene, ob); }
bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base) { if (anim->frs_sec) { *frs_sec = anim->frs_sec; *frs_sec_base = anim->frs_sec_base; #ifdef WITH_FFMPEG if (no_av_base) { *frs_sec_base /= AV_TIME_BASE; } #else UNUSED_VARS(no_av_base); #endif return true; } return false; }
/** * Changes the object mode (if needed) to the one set in \a workspace_new. * Object mode is still stored on object level. In future it should all be workspace level instead. */ static void workspace_change_update(WorkSpace *workspace_new, const WorkSpace *workspace_old, bContext *C, wmWindowManager *wm) { /* needs to be done before changing mode! (to ensure right context) */ UNUSED_VARS(workspace_old, workspace_new, C, wm); #if 0 Object *ob_act = CTX_data_active_object(C) eObjectMode mode_old = workspace_old->object_mode; eObjectMode mode_new = workspace_new->object_mode; if (mode_old != mode_new) { ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports); ED_object_mode_toggle(C, mode_new); } #endif }
void IMB_anim_index_rebuild(struct IndexBuildContext *context, short *stop, short *do_update, float *progress) { switch (context->anim_type) { #ifdef WITH_FFMPEG case ANIM_FFMPEG: index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress); break; #endif #ifdef WITH_AVI default: index_rebuild_fallback((FallbackIndexBuilderContext *)context, stop, do_update, progress); break; #endif } UNUSED_VARS(stop, do_update, progress); }
void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop) { switch (context->anim_type) { #ifdef WITH_FFMPEG case ANIM_FFMPEG: index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop); break; #endif #ifdef WITH_AVI default: index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop); break; #endif } /* static defined at top of the file */ UNUSED_VARS(stop, proxy_sizes); }
static void face_edges_split( BMesh *bm, BMFace *f, struct LinkBase *e_ls_base, bool use_island_connect, MemArena *mem_arena_edgenet) { unsigned int i; unsigned int edge_arr_len = e_ls_base->list_len; BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len); LinkNode *node; BLI_assert(f->head.htype == BM_FACE); for (i = 0, node = e_ls_base->list; i < e_ls_base->list_len; i++, node = node->next) { edge_arr[i] = node->link; } BLI_assert(node == NULL); #ifdef USE_DUMP printf("# %s: %d %u\n", __func__, BM_elem_index_get(f), e_ls_base->list_len); #endif #ifdef USE_NET_ISLAND_CONNECT if (use_island_connect) { unsigned int edge_arr_holes_len; BMEdge **edge_arr_holes; if (BM_face_split_edgenet_connect_islands( bm, f, edge_arr, edge_arr_len, false, mem_arena_edgenet, &edge_arr_holes, &edge_arr_holes_len)) { edge_arr_len = edge_arr_holes_len; edge_arr = edge_arr_holes; /* owned by the arena */ } } #else UNUSED_VARS(use_island_connect, mem_arena_edgenet); #endif BM_face_split_edgenet(bm, f, edge_arr, (int)edge_arr_len, NULL, NULL); }
/** * Logic shared between #WM_file_read & #wm_homefile_read, * updates to make after reading a file. */ static void wm_file_read_post(bContext *C, bool is_startup_file) { bool addons_loaded = false; wmWindowManager *wm = CTX_wm_manager(C); if (!G.background) { /* remove windows which failed to be added via WM_check */ wm_window_ghostwindows_remove_invalid(C, wm); } CTX_wm_window_set(C, wm->windows.first); ED_editors_init(C); DAG_on_visible_update(CTX_data_main(C), true); #ifdef WITH_PYTHON if (is_startup_file) { /* possible python hasn't been initialized */ if (CTX_py_init_get(C)) { /* sync addons, these may have changed from the defaults */ BPY_execute_string(C, "__import__('addon_utils').reset_all()"); BPY_python_reset(C); addons_loaded = true; } } else { /* run any texts that were loaded in and flagged as modules */ BPY_python_reset(C); addons_loaded = true; } #else UNUSED_VARS(is_startup_file); #endif /* WITH_PYTHON */ WM_operatortype_last_properties_clear_all(); /* important to do before NULL'ing the context */ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); /* would otherwise be handled by event loop */ if (G.background) { Main *bmain = CTX_data_main(C); BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C)); } WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); /* report any errors. * currently disabled if addons aren't yet loaded */ if (addons_loaded) { wm_file_read_report(C); } if (!G.background) { /* in background mode this makes it hard to load * a blend file and do anything since the screen * won't be set to a valid value again */ CTX_wm_window_set(C, NULL); /* exits queues */ } if (!G.background) { // undo_editmode_clear(); BKE_undo_reset(); BKE_undo_write(C, "original"); /* save current state */ } }
GPUShader *GPU_shader_create_ex(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number, const int flags) { #ifdef WITH_OPENSUBDIV /* TODO(sergey): used to add #version 150 to the geometry shader. * Could safely be renamed to "use_geometry_code" since it's very * likely any of geometry code will want to use GLSL 1.5. */ bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0; #else UNUSED_VARS(flags); bool use_opensubdiv = false; #endif GLint status; GLchar log[5000]; GLsizei length = 0; GPUShader *shader; char standard_defines[MAX_DEFINE_LENGTH] = ""; char standard_extensions[MAX_EXT_DEFINE_LENGTH] = ""; if (geocode && !GPU_geometry_shader_support()) return NULL; shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE); if (vertexcode) shader->vertex = glCreateShader(GL_VERTEX_SHADER); if (fragcode) shader->fragment = glCreateShader(GL_FRAGMENT_SHADER); if (geocode) shader->geometry = glCreateShader(GL_GEOMETRY_SHADER_EXT); shader->program = glCreateProgram(); if (!shader->program || (vertexcode && !shader->vertex) || (fragcode && !shader->fragment) || (geocode && !shader->geometry)) { fprintf(stderr, "GPUShader, object creation failed.\n"); GPU_shader_free(shader); return NULL; } gpu_shader_standard_defines(standard_defines, use_opensubdiv, (flags & GPU_SHADER_FLAGS_NEW_SHADING) != 0); gpu_shader_standard_extensions(standard_extensions, geocode != NULL); if (vertexcode) { const char *source[5]; /* custom limit, may be too small, beware */ int num_source = 0; source[num_source++] = gpu_shader_version(); source[num_source++] = standard_extensions; source[num_source++] = standard_defines; if (defines) source[num_source++] = defines; source[num_source++] = vertexcode; gpu_dump_shaders(source, num_source, DEBUG_SHADER_VERTEX); glAttachShader(shader->program, shader->vertex); glShaderSource(shader->vertex, num_source, source, NULL); glCompileShader(shader->vertex); glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status); if (!status) { glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log); shader_print_errors("compile", log, source, num_source); GPU_shader_free(shader); return NULL; } } if (fragcode) { const char *source[7]; int num_source = 0; source[num_source++] = gpu_shader_version(); source[num_source++] = standard_extensions; source[num_source++] = standard_defines; #ifdef WITH_OPENSUBDIV /* TODO(sergey): Move to fragment shader source code generation. */ if (use_opensubdiv) { source[num_source++] = "#ifdef USE_OPENSUBDIV\n" "in block {\n" " VertexData v;\n" "} inpt;\n" "#endif\n"; } #endif if (defines) source[num_source++] = defines; if (libcode) source[num_source++] = libcode; source[num_source++] = fragcode; gpu_dump_shaders(source, num_source, DEBUG_SHADER_FRAGMENT); glAttachShader(shader->program, shader->fragment); glShaderSource(shader->fragment, num_source, source, NULL); glCompileShader(shader->fragment); glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status); if (!status) { glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log); shader_print_errors("compile", log, source, num_source); GPU_shader_free(shader); return NULL; } } if (geocode) { const char *source[6]; int num_source = 0; source[num_source++] = gpu_shader_version(); source[num_source++] = standard_extensions; source[num_source++] = standard_defines; if (defines) source[num_source++] = defines; source[num_source++] = geocode; gpu_dump_shaders(source, num_source, DEBUG_SHADER_GEOMETRY); glAttachShader(shader->program, shader->geometry); glShaderSource(shader->geometry, num_source, source, NULL); glCompileShader(shader->geometry); glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status); if (!status) { glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log); shader_print_errors("compile", log, source, num_source); GPU_shader_free(shader); return NULL; } if (!use_opensubdiv) { GPU_shader_geometry_stage_primitive_io(shader, input, output, number); } } #ifdef WITH_OPENSUBDIV if (use_opensubdiv) { glBindAttribLocation(shader->program, 0, "position"); glBindAttribLocation(shader->program, 1, "normal"); GPU_shader_geometry_stage_primitive_io(shader, GL_LINES_ADJACENCY_EXT, GL_TRIANGLE_STRIP, 4); } #endif glLinkProgram(shader->program); glGetProgramiv(shader->program, GL_LINK_STATUS, &status); if (!status) { glGetProgramInfoLog(shader->program, sizeof(log), &length, log); /* print attached shaders in pipeline order */ if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1); if (geocode) shader_print_errors("linking", log, &geocode, 1); if (libcode) shader_print_errors("linking", log, &libcode, 1); if (fragcode) shader_print_errors("linking", log, &fragcode, 1); GPU_shader_free(shader); return NULL; } #ifdef WITH_OPENSUBDIV /* TODO(sergey): Find a better place for this. */ if (use_opensubdiv && GLEW_VERSION_4_1) { glProgramUniform1i(shader->program, glGetUniformLocation(shader->program, "FVarDataOffsetBuffer"), 30); /* GL_TEXTURE30 */ glProgramUniform1i(shader->program, glGetUniformLocation(shader->program, "FVarDataBuffer"), 31); /* GL_TEXTURE31 */ } #endif return shader; }
/** * This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh. * The Linear system is LV = d * Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates * The Laplacian Matrix is computes as a * Lij = sum(Wij) (if i == j) * Lij = Wij (if i != j) * Wij is weight between vertex Vi and vertex Vj, we use cotangent weight * * The Differential Coordinate is computes as a * di = Vi * sum(Wij) - sum(Wij * Vj) * Where : * di is the Differential Coordinate i * sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj) * sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood. * * This Laplacian Matrix is described in the paper: * Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324, * New York, USA * * The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper: * Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes, * Conference on Graphics Patterns and Images, SIBGRAPI, 2013 * * The computation of Differential Coordinates is described in the paper: * Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing, * 2004. p. 179-188. */ static void initLaplacianMatrix(LaplacianSystem *sys) { float no[3]; float w2, w3; int i = 3, j, ti; int idv[3]; for (ti = 0; ti < sys->total_tris; ti++) { const unsigned int *vidt = sys->tris[ti]; const float *co[3]; co[0] = sys->co[vidt[0]]; co[1] = sys->co[vidt[1]]; co[2] = sys->co[vidt[2]]; normal_tri_v3(no, UNPACK3(co)); add_v3_v3(sys->no[vidt[0]], no); add_v3_v3(sys->no[vidt[1]], no); add_v3_v3(sys->no[vidt[2]], no); for (j = 0; j < 3; j++) { const float *v1, *v2, *v3; idv[0] = vidt[j]; idv[1] = vidt[(j + 1) % i]; idv[2] = vidt[(j + 2) % i]; v1 = sys->co[idv[0]]; v2 = sys->co[idv[1]]; v3 = sys->co[idv[2]]; w2 = cotangent_tri_weight_v3(v3, v1, v2); w3 = cotangent_tri_weight_v3(v2, v3, v1); sys->delta[idv[0]][0] += v1[0] * (w2 + w3); sys->delta[idv[0]][1] += v1[1] * (w2 + w3); sys->delta[idv[0]][2] += v1[2] * (w2 + w3); sys->delta[idv[0]][0] -= v2[0] * w2; sys->delta[idv[0]][1] -= v2[1] * w2; sys->delta[idv[0]][2] -= v2[2] * w2; sys->delta[idv[0]][0] -= v3[0] * w3; sys->delta[idv[0]][1] -= v3[1] * w3; sys->delta[idv[0]][2] -= v3[2] * w3; nlMatrixAdd(idv[0], idv[1], -w2); nlMatrixAdd(idv[0], idv[2], -w3); nlMatrixAdd(idv[0], idv[0], w2 + w3); } } } static void computeImplictRotations(LaplacianSystem *sys) { int vid, *vidn = NULL; float minj, mjt, qj[3], vj[3]; int i, j, ln; for (i = 0; i < sys->total_verts; i++) { normalize_v3(sys->no[i]); vidn = sys->ringv_map[i].indices; ln = sys->ringv_map[i].count; minj = 1000000.0f; for (j = 0; j < ln; j++) { vid = vidn[j]; copy_v3_v3(qj, sys->co[vid]); sub_v3_v3v3(vj, qj, sys->co[i]); normalize_v3(vj); mjt = fabsf(dot_v3v3(vj, sys->no[i])); if (mjt < minj) { minj = mjt; sys->unit_verts[i] = vidn[j]; } } } } static void rotateDifferentialCoordinates(LaplacianSystem *sys) { float alpha, beta, gamma; float pj[3], ni[3], di[3]; float uij[3], dun[3], e2[3], pi[3], fni[3], vn[3][3]; int i, j, num_fni, k, fi; int *fidn; for (i = 0; i < sys->total_verts; i++) { copy_v3_v3(pi, sys->co[i]); copy_v3_v3(ni, sys->no[i]); k = sys->unit_verts[i]; copy_v3_v3(pj, sys->co[k]); sub_v3_v3v3(uij, pj, pi); mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni)); sub_v3_v3(uij, dun); normalize_v3(uij); cross_v3_v3v3(e2, ni, uij); copy_v3_v3(di, sys->delta[i]); alpha = dot_v3v3(ni, di); beta = dot_v3v3(uij, di); gamma = dot_v3v3(e2, di); pi[0] = nlGetVariable(0, i); pi[1] = nlGetVariable(1, i); pi[2] = nlGetVariable(2, i); zero_v3(ni); num_fni = 0; num_fni = sys->ringf_map[i].count; for (fi = 0; fi < num_fni; fi++) { const unsigned int *vin; fidn = sys->ringf_map[i].indices; vin = sys->tris[fidn[fi]]; for (j = 0; j < 3; j++) { vn[j][0] = nlGetVariable(0, vin[j]); vn[j][1] = nlGetVariable(1, vin[j]); vn[j][2] = nlGetVariable(2, vin[j]); if (vin[j] == sys->unit_verts[i]) { copy_v3_v3(pj, vn[j]); } } normal_tri_v3(fni, UNPACK3(vn)); add_v3_v3(ni, fni); } normalize_v3(ni); sub_v3_v3v3(uij, pj, pi); mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni)); sub_v3_v3(uij, dun); normalize_v3(uij); cross_v3_v3v3(e2, ni, uij); fni[0] = alpha * ni[0] + beta * uij[0] + gamma * e2[0]; fni[1] = alpha * ni[1] + beta * uij[1] + gamma * e2[1]; fni[2] = alpha * ni[2] + beta * uij[2] + gamma * e2[2]; if (len_squared_v3(fni) > FLT_EPSILON) { nlRightHandSideSet(0, i, fni[0]); nlRightHandSideSet(1, i, fni[1]); nlRightHandSideSet(2, i, fni[2]); } else { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } } } static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3]) { int vid, i, j, n, na; n = sys->total_verts; na = sys->total_anchors; #ifdef OPENNL_THREADING_HACK modifier_opennl_lock(); #endif if (!sys->is_matrix_computed) { nlNewContext(); sys->context = nlGetCurrent(); nlSolverParameteri(NL_NB_VARIABLES, n); nlSolverParameteri(NL_SYMMETRIC, NL_FALSE); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlSolverParameteri(NL_NB_ROWS, n + na); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); nlBegin(NL_SYSTEM); for (i = 0; i < n; i++) { nlSetVariable(0, i, sys->co[i][0]); nlSetVariable(1, i, sys->co[i][1]); nlSetVariable(2, i, sys->co[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlSetVariable(0, vid, vertexCos[vid][0]); nlSetVariable(1, vid, vertexCos[vid][1]); nlSetVariable(2, vid, vertexCos[vid][2]); } nlBegin(NL_MATRIX); initLaplacianMatrix(sys); computeImplictRotations(sys); for (i = 0; i < n; i++) { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); nlMatrixAdd(n + i, vid, 1.0f); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (!nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = nlGetVariable(0, vid); vertexCos[vid][1] = nlGetVariable(1, vid); vertexCos[vid][2] = nlGetVariable(2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } sys->is_matrix_computed = true; } else if (sys->has_solution) { nlMakeCurrent(sys->context); nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); for (i = 0; i < n; i++) { nlRightHandSideSet(0, i, sys->delta[i][0]); nlRightHandSideSet(1, i, sys->delta[i][1]); nlRightHandSideSet(2, i, sys->delta[i][2]); } for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); nlMatrixAdd(n + i, vid, 1.0f); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = true; for (j = 1; j <= sys->repeat; j++) { nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); rotateDifferentialCoordinates(sys); for (i = 0; i < na; i++) { vid = sys->index_anchors[i]; nlRightHandSideSet(0, n + i, vertexCos[vid][0]); nlRightHandSideSet(1, n + i, vertexCos[vid][1]); nlRightHandSideSet(2, n + i, vertexCos[vid][2]); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (!nlSolveAdvanced(NULL, NL_FALSE)) { sys->has_solution = false; break; } } if (sys->has_solution) { for (vid = 0; vid < sys->total_verts; vid++) { vertexCos[vid][0] = nlGetVariable(0, vid); vertexCos[vid][1] = nlGetVariable(1, vid); vertexCos[vid][2] = nlGetVariable(2, vid); } } else { sys->has_solution = false; } } else { sys->has_solution = false; } } #ifdef OPENNL_THREADING_HACK modifier_opennl_unlock(); #endif } static bool isValidVertexGroup(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm) { int defgrp_index; MDeformVert *dvert = NULL; modifier_get_vgroup(ob, dm, lmd->anchor_grp_name, &dvert, &defgrp_index); return (dvert != NULL); } static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { int i; int defgrp_index; int total_anchors; float wpaint; MDeformVert *dvert = NULL; MDeformVert *dv = NULL; LaplacianSystem *sys; if (isValidVertexGroup(lmd, ob, dm)) { int *index_anchors = MEM_mallocN(sizeof(int) * numVerts, __func__); /* over-alloc */ const MLoopTri *mlooptri; const MLoop *mloop; STACK_DECLARE(index_anchors); STACK_INIT(index_anchors, numVerts); modifier_get_vgroup(ob, dm, lmd->anchor_grp_name, &dvert, &defgrp_index); BLI_assert(dvert != NULL); dv = dvert; for (i = 0; i < numVerts; i++) { wpaint = defvert_find_weight(dv, defgrp_index); dv++; if (wpaint > 0.0f) { STACK_PUSH(index_anchors, i); } } DM_ensure_looptri(dm); total_anchors = STACK_SIZE(index_anchors); lmd->cache_system = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumLoopTri(dm), total_anchors, lmd->anchor_grp_name, lmd->repeat); sys = (LaplacianSystem *)lmd->cache_system; memcpy(sys->index_anchors, index_anchors, sizeof(int) * total_anchors); memcpy(sys->co, vertexCos, sizeof(float[3]) * numVerts); MEM_freeN(index_anchors); lmd->vertexco = MEM_mallocN(sizeof(float[3]) * numVerts, "ModDeformCoordinates"); memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * numVerts); lmd->total_verts = numVerts; createFaceRingMap( dm->getNumVerts(dm), dm->getLoopTriArray(dm), dm->getNumLoopTri(dm), dm->getLoopArray(dm), &sys->ringf_map, &sys->ringf_indices); createVertRingMap( dm->getNumVerts(dm), dm->getEdgeArray(dm), dm->getNumEdges(dm), &sys->ringv_map, &sys->ringv_indices); mlooptri = dm->getLoopTriArray(dm); mloop = dm->getLoopArray(dm); for (i = 0; i < sys->total_tris; i++) { sys->tris[i][0] = mloop[mlooptri[i].tri[0]].v; sys->tris[i][1] = mloop[mlooptri[i].tri[1]].v; sys->tris[i][2] = mloop[mlooptri[i].tri[2]].v; } } } static int isSystemDifferent(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm, int numVerts) { int i; int defgrp_index; int total_anchors = 0; float wpaint; MDeformVert *dvert = NULL; MDeformVert *dv = NULL; LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system; if (sys->total_verts != numVerts) { return LAPDEFORM_SYSTEM_CHANGE_VERTEXES; } if (sys->total_edges != dm->getNumEdges(dm)) { return LAPDEFORM_SYSTEM_CHANGE_EDGES; } if (!STREQ(lmd->anchor_grp_name, sys->anchor_grp_name)) { return LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP; } modifier_get_vgroup(ob, dm, lmd->anchor_grp_name, &dvert, &defgrp_index); if (!dvert) { return LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP; } dv = dvert; for (i = 0; i < numVerts; i++) { wpaint = defvert_find_weight(dv, defgrp_index); dv++; if (wpaint > 0.0f) { total_anchors++; } } if (sys->total_anchors != total_anchors) { return LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS; } return LAPDEFORM_SYSTEM_NOT_CHANGE; } static void LaplacianDeformModifier_do( LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { float (*filevertexCos)[3]; int sysdif; LaplacianSystem *sys = NULL; filevertexCos = NULL; if (!(lmd->flag & MOD_LAPLACIANDEFORM_BIND)) { if (lmd->cache_system) { sys = lmd->cache_system; deleteLaplacianSystem(sys); lmd->cache_system = NULL; } lmd->total_verts = 0; MEM_SAFE_FREE(lmd->vertexco); return; } if (lmd->cache_system) { sysdif = isSystemDifferent(lmd, ob, dm, numVerts); sys = lmd->cache_system; if (sysdif) { if (sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS || sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP) { filevertexCos = MEM_mallocN(sizeof(float[3]) * numVerts, "TempModDeformCoordinates"); memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * numVerts); MEM_SAFE_FREE(lmd->vertexco); lmd->total_verts = 0; deleteLaplacianSystem(sys); lmd->cache_system = NULL; initSystem(lmd, ob, dm, filevertexCos, numVerts); sys = lmd->cache_system; /* may have been reallocated */ MEM_SAFE_FREE(filevertexCos); if (sys) { laplacianDeformPreview(sys, vertexCos); } } else { if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) { modifier_setError(&lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) { modifier_setError(&lmd->modifier, "Edges changed from %d to %d", sys->total_edges, dm->getNumEdges(dm)); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) { modifier_setError(&lmd->modifier, "Vertex group '%s' is not valid", sys->anchor_grp_name); } } } else { sys->repeat = lmd->repeat; laplacianDeformPreview(sys, vertexCos); } } else { if (!isValidVertexGroup(lmd, ob, dm)) { modifier_setError(&lmd->modifier, "Vertex group '%s' is not valid", lmd->anchor_grp_name); lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND; } else if (lmd->total_verts > 0 && lmd->total_verts == numVerts) { filevertexCos = MEM_mallocN(sizeof(float[3]) * numVerts, "TempDeformCoordinates"); memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * numVerts); MEM_SAFE_FREE(lmd->vertexco); lmd->total_verts = 0; initSystem(lmd, ob, dm, filevertexCos, numVerts); sys = lmd->cache_system; MEM_SAFE_FREE(filevertexCos); laplacianDeformPreview(sys, vertexCos); } else { initSystem(lmd, ob, dm, vertexCos, numVerts); sys = lmd->cache_system; laplacianDeformPreview(sys, vertexCos); } } if (sys && sys->is_matrix_computed && !sys->has_solution) { modifier_setError(&lmd->modifier, "The system did not find a solution"); } } #else /* WITH_OPENNL */ static void LaplacianDeformModifier_do( LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { UNUSED_VARS(lmd, ob, dm, vertexCos, numVerts); }