Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp')
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp522
1 files changed, 522 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
new file mode 100644
index 00000000000..51739cd4720
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -0,0 +1,522 @@
+/*
+ * ***** 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/BlenderStrokeRenderer.cpp
+ * \ingroup freestyle
+ */
+
+#include "BlenderStrokeRenderer.h"
+#include "BlenderTextureManager.h"
+
+#include "../application/AppConfig.h"
+#include "../stroke/Canvas.h"
+
+#include "BKE_global.h"
+
+// XXX Are those "ifdef __cplusplus" useful here?
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_library.h" /* free_libblock */
+#include "BKE_main.h" /* struct Main */
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+
+#include "RE_pipeline.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+BlenderStrokeRenderer::BlenderStrokeRenderer(Render* re, int render_count) : StrokeRenderer()
+{
+ // TEMPORARY - need a texture manager
+ _textureManager = new BlenderTextureManager;
+ _textureManager->load();
+
+ // for stroke mesh generation
+ _width = re->winx;
+ _height = re->winy;
+
+ //Scene.New("FreestyleStrokes")
+ old_scene = re->scene;
+
+ char name[22];
+ BLI_snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name + 2);
+ freestyle_scene = BKE_scene_add(G.main, name);
+ freestyle_scene->r.cfra = old_scene->r.cfra;
+ freestyle_scene->r.mode = old_scene->r.mode &
+ ~(R_EDGE_FRS | R_SHADOW | R_SSS | R_PANORAMA | R_ENVMAP | R_MBLUR | R_BORDER);
+ freestyle_scene->r.xsch = re->rectx; // old_scene->r.xsch
+ freestyle_scene->r.ysch = re->recty; // old_scene->r.ysch
+ freestyle_scene->r.xasp = 1.0f; // old_scene->r.xasp;
+ freestyle_scene->r.yasp = 1.0f; // old_scene->r.yasp;
+ freestyle_scene->r.tilex = old_scene->r.tilex;
+ freestyle_scene->r.tiley = old_scene->r.tiley;
+ freestyle_scene->r.size = 100; // old_scene->r.size
+ freestyle_scene->r.maximsize = old_scene->r.maximsize;
+ freestyle_scene->r.ocres = old_scene->r.ocres;
+ freestyle_scene->r.color_mgt_flag = 0; // old_scene->r.color_mgt_flag;
+ freestyle_scene->r.scemode = old_scene->r.scemode & ~(R_SINGLE_LAYER);
+ freestyle_scene->r.flag = old_scene->r.flag;
+ freestyle_scene->r.threads = old_scene->r.threads;
+ freestyle_scene->r.border.xmin = old_scene->r.border.xmin;
+ freestyle_scene->r.border.ymin = old_scene->r.border.ymin;
+ freestyle_scene->r.border.xmax = old_scene->r.border.xmax;
+ freestyle_scene->r.border.ymax = old_scene->r.border.ymax;
+ strcpy(freestyle_scene->r.pic, old_scene->r.pic);
+ freestyle_scene->r.safety.xmin = old_scene->r.safety.xmin;
+ freestyle_scene->r.safety.ymin = old_scene->r.safety.ymin;
+ freestyle_scene->r.safety.xmax = old_scene->r.safety.xmax;
+ freestyle_scene->r.safety.ymax = old_scene->r.safety.ymax;
+ freestyle_scene->r.osa = old_scene->r.osa;
+ freestyle_scene->r.filtertype = old_scene->r.filtertype;
+ freestyle_scene->r.gauss = old_scene->r.gauss;
+ freestyle_scene->r.dither_intensity = old_scene->r.dither_intensity;
+ BLI_strncpy(freestyle_scene->r.engine, old_scene->r.engine, sizeof(freestyle_scene->r.engine));
+ freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA;
+ freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG;
+ BKE_scene_disable_color_management(freestyle_scene);
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("%s: %d threads\n", __func__, freestyle_scene->r.threads);
+ }
+
+ // Render layer
+ SceneRenderLayer *srl = (SceneRenderLayer *)freestyle_scene->r.layers.first;
+ srl->layflag = SCE_LAY_SOLID | SCE_LAY_ZTRA;
+
+ BKE_scene_set_background(G.main, freestyle_scene);
+
+ // Camera
+ Object* object_camera = BKE_object_add(freestyle_scene, OB_CAMERA);
+
+ Camera* camera = (Camera *)object_camera->data;
+ camera->type = CAM_ORTHO;
+ camera->ortho_scale = max(re->rectx, re->recty);
+ camera->clipsta = 0.1f;
+ camera->clipend = 100.0f;
+
+ _z_delta = 0.00001f;
+ _z = camera->clipsta + _z_delta;
+
+ // test
+ //_z = 999.90f; _z_delta = 0.01f;
+
+ object_camera->loc[0] = re->disprect.xmin + 0.5f * re->rectx;
+ object_camera->loc[1] = re->disprect.ymin + 0.5f * re->recty;
+ object_camera->loc[2] = 1.0f;
+
+ freestyle_scene->camera = object_camera;
+
+ // Material
+ material = BKE_material_add(G.main, "stroke_material");
+ material->mode |= MA_VERTEXCOLP;
+ material->mode |= MA_TRANSP;
+ material->mode |= MA_SHLESS;
+ material->vcol_alpha = 1;
+
+ // Reset serial mesh ID (used for BlenderStrokeRenderer::NewMesh())
+ _mesh_id = 0xffffffff;
+}
+
+BlenderStrokeRenderer::~BlenderStrokeRenderer()
+{
+ if (0 != _textureManager) {
+ delete _textureManager;
+ _textureManager = NULL;
+ }
+
+ // The freestyle_scene object is not released here. Instead,
+ // the scene is released in free_all_freestyle_renders() in
+ // source/blender/render/intern/source/pipeline.c, after the
+ // compositor has finished.
+
+ // release objects and data blocks
+ for (Base *b = (Base*)freestyle_scene->base.first; b; b = b->next) {
+ Object *ob = b->object;
+ void *data = ob->data;
+ char name[24];
+ strcpy(name, ob->id.name);
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl;
+ }
+#endif
+ switch (ob->type) {
+ case OB_MESH:
+ BKE_libblock_free(&G.main->object, ob);
+ BKE_libblock_free(&G.main->mesh, data);
+ break;
+ case OB_CAMERA:
+ BKE_libblock_free(&G.main->object, ob);
+ BKE_libblock_free(&G.main->camera, data);
+ freestyle_scene->camera = NULL;
+ break;
+ default:
+ cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name+2) << endl;
+ }
+ }
+ BLI_freelistN(&freestyle_scene->base);
+
+ // release material
+ BKE_libblock_free(&G.main->mat, material);
+
+ BKE_scene_set_background(G.main, old_scene);
+}
+
+float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
+{
+ float z = _z;
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
+ if (!(_z < _z_delta * 100000.0f))
+ self->_z_delta *= 10.0f;
+ self->_z += _z_delta;
+ return -z;
+}
+
+unsigned int BlenderStrokeRenderer::get_stroke_mesh_id(void) const
+{
+ unsigned mesh_id = _mesh_id;
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
+ self->_mesh_id--;
+ return mesh_id;
+}
+
+void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
+{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
+ ////////////////////
+ // Build up scene
+ ////////////////////
+
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ /* Vec3r color[3]; */ /* UNUSED */
+ unsigned int vertex_index, edge_index, loop_index;
+ Vec2r p;
+
+ for (vector<Strip*>::iterator s = strips.begin(), send = strips.end();
+ s != send;
+ ++s){
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+ int strip_vertex_count = (*s)->sizeStrip();
+ int xl, xu, yl, yu, n, visible_faces, visible_segments;
+ bool visible;
+
+ // iterate over all vertices and count visible faces and strip segments
+ // (note: a strip segment is a series of visible faces, while two strip
+ // segments are separated by one or more invisible faces)
+ v[0] = strip_vertices.begin();
+ v[1] = v[0] + 1;
+ v[2] = v[0] + 2;
+ visible_faces = visible_segments = 0;
+ visible = false;
+ for (n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ xl = xu = yl = yu = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0)
+ xl++;
+ else if (p[0] > _width)
+ xu++;
+ if (p[1] < 0.0)
+ yl++;
+ else if (p[1] > _height)
+ yu++;
+ }
+ if (xl == 3 || xu == 3 || yl == 3 || yu == 3) {
+ visible = false;
+ }
+ else {
+ visible_faces++;
+ if (!visible)
+ visible_segments++;
+ visible = true;
+ }
+ }
+ if (visible_faces == 0)
+ continue;
+
+ //me = Mesh.New()
+#if 0
+ Object* object_mesh = BKE_object_add(freestyle_scene, OB_MESH);
+#else
+ Object* object_mesh = NewMesh();
+#endif
+ Mesh* mesh = (Mesh*)object_mesh->data;
+#if 0
+ MEM_freeN(mesh->bb);
+ mesh->bb = NULL;
+ mesh->id.us = 0;
+#endif
+#if 1
+ //me.materials = [mat]
+ mesh->mat = (Material**)MEM_mallocN(1 * sizeof(Material*), "MaterialList");
+ mesh->mat[0] = material;
+ mesh->totcol = 1;
+ test_object_materials((ID*)mesh);
+#else
+ assign_material(object_mesh, material, object_mesh->totcol + 1);
+ object_mesh->actcol = object_mesh->totcol;
+#endif
+
+ // vertices allocation
+ mesh->totvert = visible_faces + visible_segments * 2;
+ mesh->mvert = (MVert*)CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+
+ // edges allocation
+ mesh->totedge = visible_faces * 2 + visible_segments;
+ mesh->medge = (MEdge*)CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+
+ // faces allocation
+ mesh->totpoly = visible_faces;
+ mesh->mpoly = (MPoly*)CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+
+ // loops allocation
+ mesh->totloop = visible_faces * 3;
+ mesh->mloop = (MLoop*)CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
+
+ // colors allocation
+ mesh->mloopcol = (MLoopCol*)CustomData_add_layer(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop);
+
+ ////////////////////
+ // Data copy
+ ////////////////////
+
+ MVert *vertices = mesh->mvert;
+ MEdge *edges = mesh->medge;
+ MPoly *polys = mesh->mpoly;
+ MLoop *loops = mesh->mloop;
+ MLoopCol *colors = mesh->mloopcol;
+
+ v[0] = strip_vertices.begin();
+ v[1] = v[0] + 1;
+ v[2] = v[0] + 2;
+
+ vertex_index = edge_index = loop_index = 0;
+ visible = false;
+
+ // Note: Mesh generation in the following loop assumes stroke strips
+ // to be triangle strips.
+ for (n = 2; n < strip_vertex_count; n++, v[0]++, v[1]++, v[2]++) {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ xl = xu = yl = yu = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0)
+ xl++;
+ else if (p[0] > _width)
+ xu++;
+ if (p[1] < 0.0)
+ yl++;
+ else if (p[1] > _height)
+ yu++;
+ }
+ if (xl == 3 || xu == 3 || yl == 3 || yu == 3) {
+ visible = false;
+ }
+ else {
+ if (!visible) {
+ // first vertex
+ vertices->co[0] = svRep[0]->point2d()[0];
+ vertices->co[1] = svRep[0]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+ ++vertex_index;
+
+ // second vertex
+ vertices->co[0] = svRep[1]->point2d()[0];
+ vertices->co[1] = svRep[1]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+ ++vertex_index;
+
+ // first edge
+ edges->v1 = vertex_index - 2;
+ edges->v2 = vertex_index - 1;
+ ++edges;
+ ++edge_index;
+ }
+ visible = true;
+
+ // vertex
+ vertices->co[0] = svRep[2]->point2d()[0];
+ vertices->co[1] = svRep[2]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+ ++vertex_index;
+
+ // edges
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 3;
+ ++edges;
+ ++edge_index;
+
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 2;
+ ++edges;
+ ++edge_index;
+
+ // poly
+ polys->loopstart = loop_index;
+ polys->totloop = 3;
+ ++polys;
+
+ // loops
+ if (n % 2 == 0) {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 1;
+
+ loops[1].v = vertex_index - 2;
+ loops[1].e = edge_index - 3;
+
+ loops[2].v = vertex_index - 3;
+ loops[2].e = edge_index - 2;
+ }
+ else {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 2;
+
+ loops[1].v = vertex_index - 3;
+ loops[1].e = edge_index - 3;
+
+ loops[2].v = vertex_index - 2;
+ loops[2].e = edge_index - 1;
+ }
+ loops += 3;
+ loop_index += 3;
+
+ // colors
+ if (n % 2 == 0) {
+ colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
+ colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
+ colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f * svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
+ colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
+ colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
+ colors[1].a = (short)(255.0f * svRep[1]->alpha());
+
+ colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
+ colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
+ colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
+ colors[2].a = (short)(255.0f * svRep[0]->alpha());
+ }
+ else {
+ colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
+ colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
+ colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
+ colors[0].a = (short)(255.0f * svRep[2]->alpha());
+
+ colors[1].r = (short)(255.0f * svRep[0]->color()[0]);
+ colors[1].g = (short)(255.0f * svRep[0]->color()[1]);
+ colors[1].b = (short)(255.0f * svRep[0]->color()[2]);
+ colors[1].a = (short)(255.0f * svRep[0]->alpha());
+
+ colors[2].r = (short)(255.0f * svRep[1]->color()[0]);
+ colors[2].g = (short)(255.0f * svRep[1]->color()[1]);
+ colors[2].b = (short)(255.0f * svRep[1]->color()[2]);
+ colors[2].a = (short)(255.0f * svRep[1]->alpha());
+ }
+ colors += 3;
+ }
+ } // loop over strip vertices
+#if 0
+ BKE_mesh_validate(mesh, TRUE);
+#endif
+ } // loop over strips
+}
+
+// A replacement of BKE_object_add() for better performance.
+Object *BlenderStrokeRenderer::NewMesh() const
+{
+ Object *ob;
+ Base *base;
+ char name[MAX_ID_NAME];
+ unsigned int mesh_id = get_stroke_mesh_id();
+
+ BLI_snprintf(name, MAX_ID_NAME, "0%08xOB", mesh_id);
+ ob = BKE_object_add_only_object(G.main, OB_MESH, name);
+ BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id);
+ ob->data = BKE_mesh_add(G.main, name);
+ ob->lay = 1;
+
+ base = BKE_scene_base_add(freestyle_scene, ob);
+#if 0
+ BKE_scene_base_deselect_all(scene);
+ BKE_scene_base_select(scene, base);
+#else
+ (void)base;
+#endif
+ ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+
+ return ob;
+}
+
+Render* BlenderStrokeRenderer::RenderScene(Render *re)
+{
+ Camera *camera = (Camera*)freestyle_scene->camera->data;
+ if (camera->clipend < _z)
+ camera->clipend = _z + _z_delta * 100.0f;
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "clipsta " << camera->clipsta << ", clipend " << camera->clipend << endl;
+ }
+#endif
+
+ Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
+
+ RE_RenderFreestyleStrokes(freestyle_render, G.main, freestyle_scene);
+ return freestyle_render;
+}