diff options
Diffstat (limited to 'source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp')
-rw-r--r-- | source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp | 356 |
1 files changed, 356 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..f8c87fd0029 --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -0,0 +1,356 @@ +# include "BlenderStrokeRenderer.h" +# include "../stroke/Canvas.h" +# include "../application/AppConfig.h" + +# include "BlenderTextureManager.h" + +#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_mesh_types.h" +#include "DNA_meshdata_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_material.h" +#include "BKE_main.h" /* struct Main */ +#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(); + + _width = re->winx; _height = re->winy; // for stroke mesh generation + + // Scene.New("FreestyleStrokes") + old_scene = re->scene; + + char name[22]; + snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name+2); + freestyle_scene = BKE_scene_add(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.f; // old_scene->r.xasp; + freestyle_scene->r.yasp= 1.f; // old_scene->r.yasp; + freestyle_scene->r.xparts= old_scene->r.xparts; + freestyle_scene->r.yparts= old_scene->r.yparts; + 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_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.f; + + freestyle_scene->camera = object_camera; + + // Material + material = BKE_material_add("stroke_material"); + material->mode |= MA_VERTEXCOLP; + material->mode |= MA_TRANSP; + material->mode |= MA_SHLESS; + material->vcol_alpha = 1; +} + +BlenderStrokeRenderer::~BlenderStrokeRenderer(){ + + if(0 != _textureManager) + { + delete _textureManager; + _textureManager = 0; + } + + // 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 + Base *b = (Base *)freestyle_scene->base.first; + while(b) { + Object *ob = b->object; + void *data = ob->data; + char name[24]; + strcpy(name, ob->id.name); + //cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl; + 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; + } + b = b->next; + } + 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; +} + +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]; + unsigned int vertex_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 m, 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]; ++(v[1]); + v[2] = v[1]; ++(v[2]); + visible_faces = visible_segments = 0; + visible = false; + for (n = 2; n < strip_vertex_count; n++) + { + svRep[0] = *(v[0]); + svRep[1] = *(v[1]); + svRep[2] = *(v[2]); + m = 0; + for (int j = 0; j < 3; j++) { + p = svRep[j]->point2d(); + if (p[0] < 0.0 || p[0] > _width || p[1] < 0.0 || p[1] > _height) + m++; + } + if (m == 3) { + visible = false; + } else { + visible_faces++; + if (!visible) + visible_segments++; + visible = true; + } + ++v[0]; ++v[1]; ++v[2]; + } + if (visible_faces == 0) + continue; + + // me = Mesh.New() + Object* object_mesh = BKE_object_add(freestyle_scene, OB_MESH); + Mesh* mesh = (Mesh *) object_mesh->data; + // MEM_freeN(mesh->bb); + // mesh->bb= NULL; + // mesh->id.us = 0; + +#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); + + // faces allocation + mesh->totface = visible_faces; + mesh->mface = (MFace*) CustomData_add_layer( &mesh->fdata, CD_MFACE, CD_CALLOC, NULL, mesh->totface); + + // colors allocation - me.vertexColors = True + mesh->mcol = (MCol *) CustomData_add_layer( &mesh->fdata, CD_MCOL, CD_CALLOC, NULL, mesh->totface ); + + //////////////////// + // Data copy + //////////////////// + + MVert* vertices = mesh->mvert; + MFace* faces = mesh->mface; + MCol* colors = mesh->mcol; + + v[0] = strip_vertices.begin(); + v[1] = v[0]; ++(v[1]); + v[2] = v[1]; ++(v[2]); + + vertex_index = 0; + visible = false; + + for (n = 2; n < strip_vertex_count; n++) + { + svRep[0] = *(v[0]); + svRep[1] = *(v[1]); + svRep[2] = *(v[2]); + m = 0; + for (int j = 0; j < 3; j++) { + p = svRep[j]->point2d(); + if (p[0] < 0.0 || p[0] > _width || p[1] < 0.0 || p[1] > _height) + m++; + } + if (m == 3) { + visible = false; + } else { + if (!visible) { + vertex_index += 2; + + // first vertex + vertices->co[0] = svRep[0]->point2d()[0]; + vertices->co[1] = svRep[0]->point2d()[1]; + vertices->co[2] = get_stroke_vertex_z(); + ++vertices; + + // second vertex + vertices->co[0] = svRep[1]->point2d()[0]; + vertices->co[1] = svRep[1]->point2d()[1]; + vertices->co[2] = get_stroke_vertex_z(); + ++vertices; + } + visible = true; + + // vertex + vertices->co[0] = svRep[2]->point2d()[0]; + vertices->co[1] = svRep[2]->point2d()[1]; + vertices->co[2] = get_stroke_vertex_z(); + + // faces + faces->v1 = vertex_index - 2; + faces->v2 = vertex_index - 1; + faces->v3 = vertex_index; + faces->v4 = 0; + + // colors + // red and blue are swapped - cf DNA_meshdata_types.h : MCol + color[0] = svRep[0]->color(); + color[1] = svRep[1]->color(); + color[2] = svRep[2]->color(); + + colors->r = (short)(255.0f*(color[0])[2]); + colors->g = (short)(255.0f*(color[0])[1]); + colors->b = (short)(255.0f*(color[0])[0]); + colors->a = (short)(255.0f*svRep[0]->alpha()); + ++colors; + + colors->r = (short)(255.0f*(color[1])[2]); + colors->g = (short)(255.0f*(color[1])[1]); + colors->b = (short)(255.0f*(color[1])[0]); + colors->a = (short)(255.0f*svRep[1]->alpha()); + ++colors; + + colors->r = (short)(255.0f*(color[2])[2]); + colors->g = (short)(255.0f*(color[2])[1]); + colors->b = (short)(255.0f*(color[2])[0]); + colors->a = (short)(255.0f*svRep[2]->alpha()); + ++colors; + + ++faces; ++vertices; ++colors; + ++vertex_index; + } + ++v[0]; ++v[1]; ++v[2]; + + } // loop over strip vertices + + } // loop over strips + +} + +Render* BlenderStrokeRenderer::RenderScene( Render *re ) { + Camera *camera = (Camera *)freestyle_scene->camera->data; + if (camera->clipend < _z) + camera->clipend = _z + _z_delta * 100.0f; + //cout << "clipsta " << camera->clipsta << ", clipend " << camera->clipend << endl; + + Render *freestyle_render = RE_NewRender(freestyle_scene->id.name); + + RE_RenderFreestyleStrokes(freestyle_render, G.main, freestyle_scene); + return freestyle_render; +} |