Index: source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp |
=================================================================== |
--- source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp (revision 0) |
+++ source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp (working copy) |
@@ -0,0 +1,932 @@ |
+/* |
+ * ***** BEGIN GPL LICENSE BLOCK ***** |
+ * |
+ * This program is free software; you can redistribute it and/or |
+ * modify it under the terms of the GNU General Public License |
+ * as published by the Free Software Foundation; either version 2 |
+ * of the License, or (at your option) any later version. |
+ * |
+ * This program is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ * GNU General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU General Public License |
+ * along with this program; if not, write to the Free Software Foundation, |
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
+ * |
+ * The Original Code is Copyright (C) 2010 Blender Foundation. |
+ * All rights reserved. |
+ * |
+ * The Original Code is: all of this file. |
+ * |
+ * Contributor(s): none yet. |
+ * |
+ * ***** END GPL LICENSE BLOCK ***** |
+ */ |
+ |
+/** \file blender/freestyle/intern/blender_interface/FRS_freestyle.cpp |
+ * \ingroup freestyle |
+ */ |
+ |
+#include <iostream> |
+#include <map> |
+#include <set> |
+ |
+#include "../application/AppCanvas.h" |
+#include "../application/AppConfig.h" |
+#include "../application/AppView.h" |
+#include "../application/Controller.h" |
+ |
+#include "BKE_global.h" |
+ |
+using namespace std; |
+ |
+// XXX Are those "ifdef __cplusplus" useful here? |
+#ifdef __cplusplus |
+extern "C" { |
+#endif |
+ |
+#include "MEM_guardedalloc.h" |
+ |
+#include "DNA_camera_types.h" |
+#include "DNA_freestyle_types.h" |
+#include "DNA_group_types.h" |
+#include "DNA_text_types.h" |
+ |
+#include "BKE_global.h" |
+#include "BKE_library.h" |
+#include "BKE_linestyle.h" |
+#include "BKE_main.h" |
+#include "BKE_text.h" |
+ |
+#include "BLI_blenlib.h" |
+#include "BLI_math.h" |
+ |
+#include "BPY_extern.h" |
+ |
+#include "renderpipeline.h" |
+#include "pixelblending.h" |
+ |
+#include "FRS_freestyle.h" |
+#include "FRS_freestyle_config.h" |
+ |
+#define DEFAULT_SPHERE_RADIUS 1.0f |
+#define DEFAULT_DKR_EPSILON 0.0f |
+ |
+// Freestyle configuration |
+static short freestyle_is_initialized = 0; |
+static Config::Path *pathconfig = NULL; |
+static Controller *controller = NULL; |
+static AppView *view = NULL; |
+ |
+// line set buffer for copy & paste |
+static FreestyleLineSet lineset_buffer; |
+static bool lineset_copied = false; |
+ |
+// camera information |
+float freestyle_viewpoint[3]; |
+float freestyle_mv[4][4]; |
+float freestyle_proj[4][4]; |
+int freestyle_viewport[4]; |
+ |
+// current scene |
+Scene *freestyle_scene; |
+ |
+string default_module_path; |
+ |
+// function declarations |
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset); |
+static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module); |
+ |
+//======================================================= |
+// Initialization |
+//======================================================= |
+ |
+void FRS_initialize() |
+{ |
+ if (freestyle_is_initialized) |
+ return; |
+ |
+ pathconfig = new Config::Path; |
+ controller = new Controller(); |
+ view = new AppView; |
+ controller->setView(view); |
+ controller->Clear(); |
+ freestyle_scene = NULL; |
+ lineset_copied = false; |
+ |
+ default_module_path = pathconfig->getProjectDir() + Config::DIR_SEP + "style_modules" + |
+ Config::DIR_SEP + "contour.py"; |
+ |
+ freestyle_is_initialized = 1; |
+} |
+ |
+void FRS_set_context(bContext *C) |
+{ |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "FRS_set_context: context 0x" << C << " scene 0x" << CTX_data_scene(C) << endl; |
+ } |
+ controller->setContext(C); |
+} |
+ |
+void FRS_read_file(bContext *C) |
+{ |
+ lineset_copied = false; |
+} |
+ |
+void FRS_exit() |
+{ |
+ delete pathconfig; |
+ delete controller; |
+ delete view; |
+} |
+ |
+//======================================================= |
+// Rendering |
+//======================================================= |
+ |
+static void init_view(Render *re) |
+{ |
+ int width = re->winx; |
+ int height = re->winy; |
+ int xmin = re->disprect.xmin; |
+ int ymin = re->disprect.ymin; |
+ int xmax = re->disprect.xmax; |
+ int ymax = re->disprect.ymax; |
+ |
+ float thickness = 1.0f; |
+ switch (re->r.line_thickness_mode) { |
+ case R_LINE_THICKNESS_ABSOLUTE: |
+ thickness = re->r.unit_line_thickness * (re->r.size / 100.f); |
+ break; |
+ case R_LINE_THICKNESS_RELATIVE: |
+ thickness = height / 480.f; |
+ break; |
+ } |
+ |
+ freestyle_viewport[0] = freestyle_viewport[1] = 0; |
+ freestyle_viewport[2] = width; |
+ freestyle_viewport[3] = height; |
+ |
+ view->setWidth(width); |
+ view->setHeight(height); |
+ view->setBorder(xmin, ymin, xmax, ymax); |
+ view->setThickness(thickness); |
+ |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "\n=== Dimensions of the 2D image coordinate system ===" << endl; |
+ cout << "Width : " << width << endl; |
+ cout << "Height : " << height << endl; |
+ if (re->r.mode & R_BORDER) |
+ cout << "Border : (" << xmin << ", " << ymin << ") - (" << xmax << ", " << ymax << ")" << endl; |
+ cout << "Unit line thickness : " << thickness << " pixel(s)" << endl; |
+ } |
+} |
+ |
+static void init_camera(Render *re) |
+{ |
+ // It is assumed that imported meshes are in the camera coordinate system. |
+ // Therefore, the view point (i.e., camera position) is at the origin, and |
+ // the the model-view matrix is simply the identity matrix. |
+ |
+ freestyle_viewpoint[0] = 0.0; |
+ freestyle_viewpoint[1] = 0.0; |
+ freestyle_viewpoint[2] = 0.0; |
+ |
+ for (int i = 0; i < 4; i++) { |
ideasman42
2013/03/02 10:56:47
copy_m4m4 would do here.
kjym3
2013/03/03 01:58:03
Done. Also used unit_m4() for setting freestyle_m
|
+ for (int j = 0; j < 4; j++) |
+ freestyle_mv[i][j] = (i == j) ? 1.0 : 0.0; |
+ } |
+ |
+ for (int i = 0; i < 4; i++) { |
+ for (int j = 0; j < 4; j++) |
+ freestyle_proj[i][j] = re->winmat[i][j]; |
+ } |
+ |
+#if 0 |
+ print_m4("mv", freestyle_mv); |
+ print_m4("proj", freestyle_proj); |
+#endif |
+} |
+ |
+static char *escape_quotes(char *name) |
+{ |
+ char *s = (char*)MEM_mallocN(strlen(name) * 2 + 1, "escape_quotes"); |
+ char *p = s; |
+ while (*name) { |
+ if (*name == '\'') |
+ *(p++) = '\\'; |
+ *(p++) = *(name++); |
+ } |
+ *p = '\0'; |
+ return s; |
+} |
+ |
+static Text *create_lineset_handler(char *layer_name, char *lineset_name) |
+{ |
+ char *s1 = escape_quotes(layer_name); |
+ char *s2 = escape_quotes(lineset_name); |
+ Text *text = BKE_text_add(G.main, lineset_name); |
+ BKE_text_write(text, "import parameter_editor; parameter_editor.process('"); |
+ BKE_text_write(text, s1); |
+ BKE_text_write(text, "', '"); |
+ BKE_text_write(text, s2); |
+ BKE_text_write(text, "')\n"); |
+ MEM_freeN(s1); |
+ MEM_freeN(s2); |
+ return text; |
+} |
+ |
+struct edge_type_condition |
+{ |
+ int edge_type, value; |
+}; |
+ |
+// examines the conditions and returns true if the target edge type needs to be computed |
+static bool test_edge_type_conditions(struct edge_type_condition *conditions, |
+ int num_edge_types, bool logical_and, int target, bool distinct) |
+{ |
+ int target_condition = 0; |
+ int num_non_target_positive_conditions = 0; |
+ int num_non_target_negative_conditions = 0; |
+ |
+ for (int i = 0; i < num_edge_types; i++) { |
+ if (conditions[i].edge_type == target) |
+ target_condition = conditions[i].value; |
+ else if (conditions[i].value > 0) |
+ ++num_non_target_positive_conditions; |
+ else if (conditions[i].value < 0) |
+ ++num_non_target_negative_conditions; |
+ } |
+ if (distinct) { |
+ // In this case, the 'target' edge type is assumed to appear on distinct edge |
+ // of its own and never together with other edge types. |
+ if (logical_and) { |
+ if (num_non_target_positive_conditions > 0) |
+ return false; |
+ if (target_condition > 0) |
+ return true; |
+ if (target_condition < 0) |
+ return false; |
+ if (num_non_target_negative_conditions > 0) |
+ return true; |
+ } |
+ else { |
+ if (target_condition > 0) |
+ return true; |
+ if (num_non_target_negative_conditions > 0) |
+ return true; |
+ if (target_condition < 0) |
+ return false; |
+ if (num_non_target_positive_conditions > 0) |
+ return false; |
+ } |
+ } |
+ else { |
+ // In this case, the 'target' edge type may appear together with other edge types. |
+ if (target_condition > 0) |
+ return true; |
+ if (target_condition < 0) |
+ return true; |
+ if (logical_and) { |
+ if (num_non_target_positive_conditions > 0) |
+ return false; |
+ if (num_non_target_negative_conditions > 0) |
+ return true; |
+ } |
+ else { |
+ if (num_non_target_negative_conditions > 0) |
+ return true; |
+ if (num_non_target_positive_conditions > 0) |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+static void prepare(Render *re, SceneRenderLayer *srl) |
+{ |
+ // load mesh |
+ re->i.infostr = "Freestyle: Mesh loading"; |
+ re->stats_draw(re->sdh, &re->i); |
+ re->i.infostr = NULL; |
+ if (controller->LoadMesh(re, srl)) // returns if scene cannot be loaded or if empty |
+ return; |
+ if (re->test_break(re->tbh)) |
+ return; |
+ |
+ // add style modules |
+ FreestyleConfig *config = &srl->freestyleConfig; |
+ |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "\n=== Rendering options ===" << endl; |
+ } |
+ int layer_count = 0; |
+ |
+ switch (config->mode) { |
+ case FREESTYLE_CONTROL_SCRIPT_MODE: |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "Modules :" << endl; |
+ } |
+ for (FreestyleModuleConfig *module_conf = (FreestyleModuleConfig*)config->modules.first; |
+ module_conf; |
+ module_conf = module_conf->next) |
+ { |
+ if(module_conf->is_displayed) { |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << " " << layer_count+1 << ": " << module_conf->module_path << endl; |
+ } |
+ controller->InsertStyleModule(layer_count, module_conf->module_path); |
+ controller->toggleLayer(layer_count, true); |
+ layer_count++; |
+ } |
+ } |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << endl; |
+ } |
+ controller->setComputeRidgesAndValleysFlag((config->flags & FREESTYLE_RIDGES_AND_VALLEYS_FLAG) ? true : false); |
+ controller->setComputeSuggestiveContoursFlag((config->flags & FREESTYLE_SUGGESTIVE_CONTOURS_FLAG) ? true : false); |
+ controller->setComputeMaterialBoundariesFlag((config->flags & FREESTYLE_MATERIAL_BOUNDARIES_FLAG) ? true : false); |
+ break; |
+ case FREESTYLE_CONTROL_EDITOR_MODE: |
+ int use_ridges_and_valleys = 0; |
+ int use_suggestive_contours = 0; |
+ int use_material_boundaries = 0; |
+ struct edge_type_condition conditions[] = { |
+ {FREESTYLE_FE_SILHOUETTE, 0}, |
+ {FREESTYLE_FE_BORDER, 0}, |
+ {FREESTYLE_FE_CREASE, 0}, |
+ {FREESTYLE_FE_RIDGE_VALLEY, 0}, |
+ {FREESTYLE_FE_SUGGESTIVE_CONTOUR, 0}, |
+ {FREESTYLE_FE_MATERIAL_BOUNDARY, 0}, |
+ {FREESTYLE_FE_CONTOUR, 0}, |
+ {FREESTYLE_FE_EXTERNAL_CONTOUR, 0}, |
+ {FREESTYLE_FE_EDGE_MARK, 0} |
+ }; |
+ int num_edge_types = sizeof(conditions) / sizeof(struct edge_type_condition); |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "Linesets:" << endl; |
+ } |
+ for (FreestyleLineSet *lineset = (FreestyleLineSet*)config->linesets.first; |
+ lineset; |
+ lineset = lineset->next) |
+ { |
+ if (lineset->flags & FREESTYLE_LINESET_ENABLED) { |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << " " << layer_count+1 << ": " << lineset->name << " - " |
+ << lineset->linestyle->id.name+2 << endl; |
+ } |
+ Text *text = create_lineset_handler(srl->name, lineset->name); |
+ controller->InsertStyleModule(layer_count, lineset->name, text); |
+ controller->toggleLayer(layer_count, true); |
+ if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) { |
+ ++use_ridges_and_valleys; |
+ ++use_suggestive_contours; |
+ ++use_material_boundaries; |
+ } |
+ else { |
+ // conditions for feature edge selection by edge types |
+ for (int i = 0; i < num_edge_types; i++) { |
+ if (!(lineset->edge_types & conditions[i].edge_type)) |
+ conditions[i].value = 0; // no condition specified |
+ else if (!(lineset->exclude_edge_types & conditions[i].edge_type)) |
+ conditions[i].value = 1; // condition: X |
+ else |
+ conditions[i].value = -1; // condition: NOT X |
+ } |
+ // logical operator for the selection conditions |
+ bool logical_and = ((lineset->flags & FREESTYLE_LINESET_FE_AND) != 0); |
+ // negation operator |
+ if (lineset->flags & FREESTYLE_LINESET_FE_NOT) { |
+ // convert an Exclusive condition into an Inclusive equivalent using De Morgan's laws: |
+ // NOT (X OR Y) --> (NOT X) AND (NOT Y) |
+ // NOT (X AND Y) --> (NOT X) OR (NOT Y) |
+ for (int i = 0; i < num_edge_types; i++) |
+ conditions[i].value *= -1; |
+ logical_and = !logical_and; |
+ } |
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and, |
+ FREESTYLE_FE_RIDGE_VALLEY, true)) |
+ { |
+ ++use_ridges_and_valleys; |
+ } |
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and, |
+ FREESTYLE_FE_SUGGESTIVE_CONTOUR, true)) |
+ { |
+ ++use_suggestive_contours; |
+ } |
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and, |
+ FREESTYLE_FE_MATERIAL_BOUNDARY, true)) |
+ { |
+ ++use_material_boundaries; |
+ } |
+ } |
+ layer_count++; |
+ } |
+ } |
+ controller->setComputeRidgesAndValleysFlag(use_ridges_and_valleys > 0); |
+ controller->setComputeSuggestiveContoursFlag(use_suggestive_contours > 0); |
+ controller->setComputeMaterialBoundariesFlag(use_material_boundaries > 0); |
+ break; |
+ } |
+ |
+ // set parameters |
+ if (config->flags & FREESTYLE_ADVANCED_OPTIONS_FLAG) { |
+ controller->setSphereRadius(config->sphere_radius); |
+ controller->setSuggestiveContourKrDerivativeEpsilon(config->dkr_epsilon); |
+ } |
+ else { |
+ controller->setSphereRadius(DEFAULT_SPHERE_RADIUS); |
+ controller->setSuggestiveContourKrDerivativeEpsilon(DEFAULT_DKR_EPSILON); |
+ } |
+ controller->setFaceSmoothness((config->flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) ? true : false); |
+ controller->setCreaseAngle(RAD2DEGF(config->crease_angle)); |
+ controller->setVisibilityAlgo((config->flags & FREESTYLE_CULLING) ? |
+ FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE : |
+ FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE); |
+ |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "Crease angle : " << controller->getCreaseAngle() << endl; |
+ cout << "Sphere radius : " << controller->getSphereRadius() << endl; |
+ cout << "Face smoothness : " << (controller->getFaceSmoothness() ? "enabled" : "disabled") << endl; |
+ cout << "Redges and valleys : " << (controller->getComputeRidgesAndValleysFlag() ? "enabled" : "disabled") |
+ << endl; |
+ cout << "Suggestive contours : " << (controller->getComputeSuggestiveContoursFlag() ? "enabled" : "disabled") |
+ << endl; |
+ cout << "Suggestive contour Kr derivative epsilon : " << controller->getSuggestiveContourKrDerivativeEpsilon() |
+ << endl; |
+ cout << "Material boundaries : " << (controller->getComputeMaterialBoundariesFlag() ? "enabled" : "disabled") |
+ << endl; |
+ cout << endl; |
+ } |
+ |
+ // set diffuse and z depth passes |
+ RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name); |
+ bool diffuse = false, z = false; |
+ for (RenderPass *rpass = (RenderPass*)rl->passes.first; rpass; rpass = rpass->next) { |
+ switch (rpass->passtype) { |
+ case SCE_PASS_DIFFUSE: |
+ controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty); |
+ diffuse = true; |
+ break; |
+ case SCE_PASS_Z: |
+ controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty); |
+ z = true; |
+ break; |
+ } |
+ } |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "Passes :" << endl; |
+ cout << " Diffuse = " << (diffuse ? "enabled" : "disabled") << endl; |
+ cout << " Z = " << (z ? "enabled" : "disabled") << endl; |
+ } |
+ |
+ // compute view map |
+ re->i.infostr = "Freestyle: View map creation"; |
+ re->stats_draw(re->sdh, &re->i); |
+ re->i.infostr = NULL; |
+ controller->ComputeViewMap(); |
+} |
+ |
+void FRS_composite_result(Render* re, SceneRenderLayer* srl, Render* freestyle_render) |
+{ |
+ RenderLayer *rl; |
+ float *src, *dest, *pixSrc, *pixDest; |
+ int x, y, rectx, recty; |
+ |
+ if (freestyle_render == NULL || freestyle_render->result == NULL) |
+ return; |
+ |
+ rl = render_get_active_layer( freestyle_render, freestyle_render->result ); |
+ if (!rl || rl->rectf == NULL) { |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "Cannot find Freestyle result image" << endl; |
+ } |
+ return; |
+ } |
+ src = rl->rectf; |
+#if 0 |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "src: " << rl->rectx << " x " << rl->recty << endl; |
+ } |
+#endif |
+ |
+ rl = RE_GetRenderLayer(re->result, srl->name); |
+ if (!rl || rl->rectf == NULL) { |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "No layer to composite to" << endl; |
+ } |
+ return; |
+ } |
+ dest = rl->rectf; |
+#if 0 |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "dest: " << rl->rectx << " x " << rl->recty << endl; |
+ } |
+#endif |
+ |
+ rectx = re->rectx; |
+ recty = re->recty; |
+ for (y = 0; y < recty; y++) { |
+ for (x = 0; x < rectx; x++) { |
+ pixSrc = src + 4 * (rectx * y + x); |
+ if (pixSrc[3] > 0.0) { |
+ pixDest = dest + 4 * (rectx * y + x); |
+ addAlphaOverFloat(pixDest, pixSrc); |
+ } |
+ } |
+ } |
+} |
+ |
+static int displayed_layer_count(SceneRenderLayer *srl) |
+{ |
+ int count = 0; |
+ |
+ switch (srl->freestyleConfig.mode) { |
+ case FREESTYLE_CONTROL_SCRIPT_MODE: |
+ for (FreestyleModuleConfig *module = (FreestyleModuleConfig*)srl->freestyleConfig.modules.first; |
+ module; |
+ module = module->next) |
+ { |
+ if (module->is_displayed) |
+ count++; |
+ } |
+ break; |
+ case FREESTYLE_CONTROL_EDITOR_MODE: |
+ for (FreestyleLineSet *lineset = (FreestyleLineSet*)srl->freestyleConfig.linesets.first; |
+ lineset; |
+ lineset = lineset->next) |
+ { |
+ if (lineset->flags & FREESTYLE_LINESET_ENABLED) |
+ count++; |
+ } |
+ break; |
+ } |
+ return count; |
+} |
+ |
+int FRS_is_freestyle_enabled(SceneRenderLayer *srl) |
+{ |
+ return (!(srl->layflag & SCE_LAY_DISABLE) && srl->layflag & SCE_LAY_FRS && displayed_layer_count(srl) > 0); |
+} |
+ |
+void FRS_init_stroke_rendering(Render *re) |
+{ |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << endl; |
+ cout << "#===============================================================" << endl; |
+ cout << "# Freestyle" << endl; |
+ cout << "#===============================================================" << endl; |
+ } |
+ |
+ init_view(re); |
+ init_camera(re); |
+ |
+ controller->ResetRenderCount(); |
+} |
+ |
+Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl) |
+{ |
+ Render *freestyle_render = NULL; |
+ |
+ RenderMonitor monitor(re); |
+ controller->setRenderMonitor(&monitor); |
+ |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << endl; |
+ cout << "----------------------------------------------------------" << endl; |
+ cout << "| " << (re->scene->id.name + 2) << "|" << srl->name << endl; |
+ cout << "----------------------------------------------------------" << endl; |
+ } |
+ |
+ // prepare Freestyle: |
+ // - load mesh |
+ // - add style modules |
+ // - set parameters |
+ // - compute view map |
+ prepare(re, srl); |
+ |
+ if (re->test_break(re->tbh)) { |
+ controller->CloseFile(); |
+ if (G.debug & G_DEBUG_FREESTYLE) { |
+ cout << "Break" << endl; |
+ } |
+ return NULL; |
+ } |
+ |
+ // render and composite Freestyle result |
+ if (controller->_ViewMap) { |
+ // render strokes |
+ re->i.infostr = "Freestyle: Stroke rendering"; |
+ re->stats_draw(re->sdh, &re->i); |
+ re->i.infostr = NULL; |
+ freestyle_scene = re->scene; |
+ controller->DrawStrokes(); |
+ freestyle_render = controller->RenderStrokes(re); |
+ controller->CloseFile(); |
+ freestyle_scene = NULL; |
+ |
+ // composite result |
+ FRS_composite_result(re, srl, freestyle_render); |
+ RE_FreeRenderResult(freestyle_render->result); |
+ freestyle_render->result = NULL; |
+ } |
+ |
+ return freestyle_render; |
+} |
+ |
+void FRS_finish_stroke_rendering(Render *re) { |
+ // clear canvas |
+ controller->Clear(); |
+} |
+ |
+//======================================================= |
+// Freestyle Panel Configuration |
+//======================================================= |
+ |
+void FRS_init_freestyle_config(FreestyleConfig *config) |
+{ |
irieshinsuke
2013/03/21 12:39:58
Why these default values are different from the fa
kjym3
2013/03/23 22:46:08
Fixed in revision 55484. Also fixed the default v
irieshinsuke
2013/03/30 09:55:14
I think the default line color should remain black
kjym3
2013/04/03 00:25:10
Fixed in revision 55677.
|
+ config->mode = FREESTYLE_CONTROL_SCRIPT_MODE; |
+ |
+ config->modules.first = config->modules.last = NULL; |
+ config->flags = 0; |
+ config->sphere_radius = DEFAULT_SPHERE_RADIUS; |
+ config->dkr_epsilon = DEFAULT_DKR_EPSILON; |
+ config->crease_angle = DEG2RADF(120.0f); |
+ |
+ config->linesets.first = config->linesets.last = NULL; |
+} |
+ |
+void FRS_free_freestyle_config(FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset; |
+ |
+ for (lineset = (FreestyleLineSet*)config->linesets.first; lineset; lineset = lineset->next) { |
+ if (lineset->group) { |
+ lineset->group->id.us--; |
+ lineset->group = NULL; |
+ } |
+ lineset->linestyle->id.us--; |
+ lineset->linestyle = NULL; |
+ } |
+ BLI_freelistN(&config->linesets); |
+ BLI_freelistN(&config->modules); |
+} |
+ |
+void FRS_copy_freestyle_config(FreestyleConfig *new_config, FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset, *new_lineset; |
+ FreestyleModuleConfig *module, *new_module; |
+ |
+ new_config->mode = config->mode; |
+ new_config->raycasting_algorithm = config->raycasting_algorithm; /* deprecated */ |
+ new_config->flags = config->flags; |
+ new_config->sphere_radius = config->sphere_radius; |
+ new_config->dkr_epsilon = config->dkr_epsilon; |
+ new_config->crease_angle = config->crease_angle; |
+ |
+ new_config->linesets.first = new_config->linesets.last = NULL; |
+ for (lineset = (FreestyleLineSet*)config->linesets.first; lineset; lineset = lineset->next) { |
+ new_lineset = FRS_alloc_lineset(); |
+ copy_lineset(new_lineset, lineset); |
+ BLI_addtail(&new_config->linesets, (void*)new_lineset); |
+ } |
+ |
+ new_config->modules.first = new_config->modules.last = NULL; |
+ for (module = (FreestyleModuleConfig*)config->modules.first; module; module = module->next) { |
+ new_module = FRS_alloc_module(); |
+ copy_module(new_module, module); |
+ BLI_addtail(&new_config->modules, (void*)new_module); |
+ } |
+} |
+ |
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset) |
+{ |
+ new_lineset->linestyle = lineset->linestyle; |
+ new_lineset->linestyle->id.us++; |
+ new_lineset->flags = lineset->flags; |
+ new_lineset->selection = lineset->selection; |
+ new_lineset->qi = lineset->qi; |
+ new_lineset->qi_start = lineset->qi_start; |
+ new_lineset->qi_end = lineset->qi_end; |
+ new_lineset->edge_types = lineset->edge_types; |
+ new_lineset->exclude_edge_types = lineset->exclude_edge_types; |
+ new_lineset->group = lineset->group; |
+ if (new_lineset->group) { |
+ new_lineset->group->id.us++; |
+ } |
+ strcpy(new_lineset->name, lineset->name); |
+} |
+ |
+FreestyleModuleConfig *FRS_alloc_module() |
+{ |
+ return (FreestyleModuleConfig*)MEM_callocN(sizeof(FreestyleModuleConfig), "style module configuration"); |
+} |
+ |
+void FRS_add_module(FreestyleConfig *config) |
+{ |
+ FreestyleModuleConfig *module_conf = (FreestyleModuleConfig*)MEM_callocN(sizeof(FreestyleModuleConfig), |
+ "style module configuration"); |
+ BLI_addtail(&config->modules, (void*)module_conf); |
+ |
+ strcpy(module_conf->module_path, default_module_path.c_str()); |
+ module_conf->is_displayed = 1; |
+} |
+ |
+static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module) |
+{ |
+ strcpy(new_module->module_path, module->module_path); |
+ new_module->is_displayed = module->is_displayed; |
+} |
+ |
+void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf) |
+{ |
+ BLI_freelinkN(&config->modules, module_conf); |
+} |
+ |
+void FRS_move_module_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf) |
+{ |
+ BLI_remlink(&config->modules, module_conf); |
+ BLI_insertlinkbefore(&config->modules, module_conf->prev, module_conf); |
+} |
+ |
+void FRS_move_module_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf) |
+{ |
+ BLI_remlink(&config->modules, module_conf); |
+ BLI_insertlinkafter(&config->modules, module_conf->next, module_conf); |
+} |
+ |
+static void unique_lineset_name(FreestyleConfig *config, FreestyleLineSet *lineset) |
+{ |
+ BLI_uniquename(&config->linesets, lineset, "FreestyleLineSet", '.', offsetof(FreestyleLineSet, name), |
+ sizeof(lineset->name)); |
+} |
+ |
+FreestyleLineSet *FRS_alloc_lineset() |
+{ |
+ return (FreestyleLineSet*)MEM_callocN(sizeof(FreestyleLineSet), "Freestyle line set"); |
+} |
+ |
+FreestyleLineSet *FRS_add_lineset(FreestyleConfig *config) |
+{ |
+ int lineset_index = BLI_countlist(&config->linesets); |
+ |
+ FreestyleLineSet *lineset = FRS_alloc_lineset(); |
+ BLI_addtail(&config->linesets, (void*)lineset); |
+ FRS_set_active_lineset_index(config, lineset_index); |
+ |
+ lineset->linestyle = FRS_new_linestyle("LineStyle", NULL); |
+ lineset->flags |= FREESTYLE_LINESET_ENABLED; |
+ lineset->selection = FREESTYLE_SEL_IMAGE_BORDER; |
+ lineset->qi = FREESTYLE_QI_VISIBLE; |
+ lineset->qi_start = 0; |
+ lineset->qi_end = 100; |
+ lineset->edge_types = FREESTYLE_FE_SILHOUETTE | FREESTYLE_FE_BORDER | FREESTYLE_FE_CREASE; |
+ lineset->exclude_edge_types = 0; |
+ lineset->group = NULL; |
+ if (lineset_index > 0) |
+ sprintf(lineset->name, "LineSet %i", lineset_index + 1); |
+ else |
+ strcpy(lineset->name, "LineSet"); |
+ unique_lineset_name(config, lineset); |
+ |
+ return lineset; |
+} |
+ |
+void FRS_copy_active_lineset(FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config); |
+ |
+ if (lineset) { |
+ lineset_buffer.linestyle = lineset->linestyle; |
+ lineset_buffer.flags = lineset->flags; |
+ lineset_buffer.selection = lineset->selection; |
+ lineset_buffer.qi = lineset->qi; |
+ lineset_buffer.qi_start = lineset->qi_start; |
+ lineset_buffer.qi_end = lineset->qi_end; |
+ lineset_buffer.edge_types = lineset->edge_types; |
+ lineset_buffer.exclude_edge_types = lineset->exclude_edge_types; |
+ lineset_buffer.group = lineset->group; |
+ strcpy(lineset_buffer.name, lineset->name); |
+ lineset_copied = true; |
+ } |
+} |
+ |
+void FRS_paste_active_lineset(FreestyleConfig *config) |
+{ |
+ if (!lineset_copied) |
+ return; |
+ |
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config); |
+ |
+ if (lineset) { |
+ lineset->linestyle->id.us--; |
+ lineset->linestyle = lineset_buffer.linestyle; |
+ lineset->linestyle->id.us++; |
+ lineset->flags = lineset_buffer.flags; |
+ lineset->selection = lineset_buffer.selection; |
+ lineset->qi = lineset_buffer.qi; |
+ lineset->qi_start = lineset_buffer.qi_start; |
+ lineset->qi_end = lineset_buffer.qi_end; |
+ lineset->edge_types = lineset_buffer.edge_types; |
+ lineset->exclude_edge_types = lineset_buffer.exclude_edge_types; |
+ if (lineset->group) { |
+ lineset->group->id.us--; |
+ lineset->group = NULL; |
+ } |
+ if (lineset_buffer.group) { |
+ lineset->group = lineset_buffer.group; |
+ lineset->group->id.us++; |
+ } |
+ strcpy(lineset->name, lineset_buffer.name); |
+ unique_lineset_name(config, lineset); |
+ lineset->flags |= FREESTYLE_LINESET_CURRENT; |
+ } |
+} |
+ |
+void FRS_delete_active_lineset(FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config); |
+ |
+ if (lineset) { |
+ if (lineset->group) { |
+ lineset->group->id.us--; |
+ lineset->group = NULL; |
+ } |
+ lineset->linestyle->id.us--; |
+ lineset->linestyle = NULL; |
+ BLI_remlink(&config->linesets, lineset); |
+ MEM_freeN(lineset); |
+ FRS_set_active_lineset_index(config, 0); |
+ } |
+} |
+ |
+void FRS_move_active_lineset_up(FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config); |
+ |
+ if (lineset) { |
+ BLI_remlink(&config->linesets, lineset); |
+ BLI_insertlinkbefore(&config->linesets, lineset->prev, lineset); |
+ } |
+} |
+ |
+void FRS_move_active_lineset_down(FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset = FRS_get_active_lineset(config); |
+ |
+ if (lineset) { |
+ BLI_remlink(&config->linesets, lineset); |
+ BLI_insertlinkafter(&config->linesets, lineset->next, lineset); |
+ } |
+} |
+ |
+FreestyleLineSet *FRS_get_active_lineset(FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset; |
+ |
+ for (lineset = (FreestyleLineSet*)config->linesets.first; lineset; lineset = lineset->next) { |
+ if (lineset->flags & FREESTYLE_LINESET_CURRENT) |
+ return lineset; |
+ } |
+ return NULL; |
+} |
+ |
+short FRS_get_active_lineset_index(FreestyleConfig *config) |
+{ |
+ FreestyleLineSet *lineset; |
+ short i; |
+ |
+ for (lineset = (FreestyleLineSet*)config->linesets.first, i = 0; lineset; lineset = lineset->next, i++) { |
+ if (lineset->flags & FREESTYLE_LINESET_CURRENT) |
+ return i; |
+ } |
+ return 0; |
+} |
+ |
+void FRS_set_active_lineset_index(FreestyleConfig *config, short index) |
+{ |
+ FreestyleLineSet *lineset; |
+ short i; |
+ |
+ for (lineset = (FreestyleLineSet*)config->linesets.first, i = 0; lineset; lineset = lineset->next, i++) { |
+ if (i == index) |
+ lineset->flags |= FREESTYLE_LINESET_CURRENT; |
+ else |
+ lineset->flags &= ~FREESTYLE_LINESET_CURRENT; |
+ } |
+} |
+ |
+void FRS_unlink_target_object(FreestyleConfig *config, Object *ob) |
+{ |
+ FreestyleLineSet *lineset; |
+ |
+ for (lineset = (FreestyleLineSet*)config->linesets.first; lineset; lineset = lineset->next) { |
+ FRS_unlink_linestyle_target_object(lineset->linestyle, ob); |
+ } |
+} |
+ |
+#ifdef __cplusplus |
+} // extern "C" |
+#endif |