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:
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp9
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp502
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h19
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.cpp25
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h1
5 files changed, 334 insertions, 222 deletions
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
index 7c8a0c9d079..f8931d32f56 100644
--- a/source/blender/freestyle/intern/application/Controller.cpp
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -882,10 +882,13 @@ void Controller::ResetRenderCount()
Render *Controller::RenderStrokes(Render *re, bool render)
{
+ int totmesh = 0;
_Chrono.start();
BlenderStrokeRenderer *blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
- if (render)
+ if (render) {
_Canvas->Render(blenderRenderer);
+ totmesh = blenderRenderer->GenerateScene();
+ }
real d = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Temporary scene generation: " << d << endl;
@@ -904,8 +907,8 @@ Render *Controller::RenderStrokes(Render *re, bool render)
float mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
float megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
- printf("%d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n",
- freestyle_render->i.totvert, freestyle_render->i.totface,
+ printf("%d objs, %d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n",
+ totmesh, freestyle_render->i.totvert, freestyle_render->i.totface,
megs_used_memory, mmap_used_memory, megs_peak_memory);
}
delete blenderRenderer;
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 09701ab6acd..29f3bfe0d94 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -66,6 +66,8 @@ extern "C" {
namespace Freestyle {
+const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_tips"};
+
BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer()
{
freestyle_bmain = re->freestyle_bmain;
@@ -208,6 +210,8 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
if (_use_shading_nodes)
BLI_ghash_free(_nodetree_hash, NULL, NULL);
+
+ FreeStrokeGroups();
}
float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
@@ -414,10 +418,10 @@ Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTr
input_uvmap->locy = node->locy;
NodeShaderUVMap *storage = (NodeShaderUVMap *)input_uvmap->storage;
if (node->custom1 & 1) { // use_tips
- BLI_strncpy(storage->uv_map, "along_stroke_tips", sizeof(storage->uv_map));
+ BLI_strncpy(storage->uv_map, uvNames[1], sizeof(storage->uv_map));
}
else {
- BLI_strncpy(storage->uv_map, "along_stroke", sizeof(storage->uv_map));
+ BLI_strncpy(storage->uv_map, uvNames[0], sizeof(storage->uv_map));
}
fromsock = (bNodeSocket *)BLI_findlink(&input_uvmap->outputs, 0); // UV
@@ -440,6 +444,11 @@ Material* BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTr
void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
if (_use_shading_nodes) {
bNodeTree *nt = iStrokeRep->getNodeTree();
Material *ma = (Material *)BLI_ghash_lookup(_nodetree_hash, nt);
@@ -509,10 +518,10 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
// We'll generate both with tips and without tips
// coordinates, on two different UV layers.
if (ma->mtex[a]->texflag & MTEX_TIPS) {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke_tips", sizeof(ma->mtex[a]->uvname));
+ BLI_strncpy(ma->mtex[a]->uvname, uvNames[1], sizeof(ma->mtex[a]->uvname));
}
else {
- BLI_strncpy(ma->mtex[a]->uvname, "along_stroke", sizeof(ma->mtex[a]->uvname));
+ BLI_strncpy(ma->mtex[a]->uvname, uvNames[0], sizeof(ma->mtex[a]->uvname));
}
a++;
}
@@ -521,7 +530,42 @@ void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
}
}
- RenderStrokeRepBasic(iStrokeRep);
+ const vector<Strip*>& strips = iStrokeRep->getStrips();
+ const bool hasTex = iStrokeRep->hasTex();
+ int totvert = 0, totedge = 0, totpoly = 0, totloop = 0;
+ int visible_faces, visible_segments;
+ for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+
+ // count visible faces and strip segments
+ test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
+ if (visible_faces == 0)
+ continue;
+
+ totvert += visible_faces + visible_segments * 2;
+ totedge += visible_faces * 2 + visible_segments;
+ totpoly += visible_faces;
+ totloop += visible_faces * 3;
+ }
+
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this); // FIXME
+ vector<StrokeGroup*> *groups = hasTex ? &self->texturedStrokeGroups : &self->strokeGroups;
+ StrokeGroup *group;
+ if (groups->empty() || !(groups->back()->totvert + totvert < MESH_MAX_VERTS &&
+ groups->back()->totcol + 1 < MAXMAT))
+ {
+ group = new StrokeGroup;
+ groups->push_back(group);
+ }
+ else {
+ group = groups->back();
+ }
+ group->strokes.push_back(iStrokeRep);
+ group->totvert += totvert;
+ group->totedge += totedge;
+ group->totpoly += totpoly;
+ group->totloop += totloop;
+ group->totcol++;
}
// Check if the triangle is visible (i.e., within the render image boundary)
@@ -578,127 +622,168 @@ void BlenderStrokeRenderer::test_strip_visibility(Strip::vertex_container& strip
}
}
-// Build a mesh object representing a stroke
-void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+// Release allocated memory for stroke groups
+void BlenderStrokeRenderer::FreeStrokeGroups()
{
- vector<Strip*>& strips = iStrokeRep->getStrips();
- const bool hasTex = iStrokeRep->hasTex();
- Strip::vertex_container::iterator v[3];
- StrokeVertexRep *svRep[3];
- unsigned int vertex_index, edge_index, loop_index;
- Vec2r p;
+ vector<StrokeGroup*>::const_iterator it, itend;
- int totvert = 0, totedge = 0, totpoly = 0, totloop = 0;
- int visible_faces, visible_segments;
-
- bool visible;
- for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
- Strip::vertex_container& strip_vertices = (*s)->vertices();
+ for (it = strokeGroups.begin(), itend = strokeGroups.end();
+ it != itend; ++it)
+ {
+ delete (*it);
+ }
+ for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
+ it != itend; ++it)
+ {
+ delete (*it);
+ }
+}
- // count visible faces and strip segments
- test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
- if (visible_faces == 0)
- continue;
+// Build a scene populated by mesh objects representing stylized strokes
+int BlenderStrokeRenderer::GenerateScene()
+{
+ vector<StrokeGroup*>::const_iterator it, itend;
- totvert += visible_faces + visible_segments * 2;
- totedge += visible_faces * 2 + visible_segments;
- totpoly += visible_faces;
- totloop += visible_faces * 3;
+ for (it = strokeGroups.begin(), itend = strokeGroups.end();
+ it != itend; ++it)
+ {
+ GenerateStrokeMesh(*it, false);
+ }
+ for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end();
+ it != itend; ++it)
+ {
+ GenerateStrokeMesh(*it, true);
}
+ return strokeGroups.size() + texturedStrokeGroups.size();
+}
+// Build a mesh object representing a group of stylized strokes
+void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
+{
#if 0
Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, OB_MESH);
#else
Object *object_mesh = NewMesh();
#endif
Mesh *mesh = (Mesh *)object_mesh->data;
- mesh->mat = (Material **)MEM_mallocN(1 * sizeof(Material *), "MaterialList");
- mesh->mat[0] = iStrokeRep->getMaterial();
- mesh->totcol = 1;
- test_object_materials(freestyle_bmain, (ID *)mesh);
- // vertices allocation
- mesh->totvert = totvert; // visible_faces + visible_segments * 2;
- CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+ mesh->totvert = group->totvert;
+ mesh->totedge = group->totedge;
+ mesh->totpoly = group->totpoly;
+ mesh->totloop = group->totloop;
+ mesh->totcol = group->totcol;
- // edges allocation
- mesh->totedge = totedge; // visible_faces * 2 + visible_segments;
- CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+ mesh->mvert = (MVert *)CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+ mesh->medge = (MEdge *)CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+ mesh->mpoly = (MPoly *)CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+ mesh->mloop = (MLoop *)CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
- // faces allocation
- mesh->totpoly = totpoly; // visible_faces;
- CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
-
- // loops allocation
- mesh->totloop = totloop; // visible_faces * 3;
- CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
-
- // uv maps
+ MVert *vertices = mesh->mvert;
+ MEdge *edges = mesh->medge;
+ MPoly *polys = mesh->mpoly;
+ MLoop *loops = mesh->mloop;
MLoopUV *loopsuv[2] = { NULL };
- if (hasTex) {
- loopsuv[0] = (MLoopUV *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke");
- loopsuv[1] = (MLoopUV *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, "along_stroke_tips");
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke");
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, "along_stroke_tips");
+ if (hasTex) {
+ // First UV layer
+ CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[0]);
+ CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[0]);
+ CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 0);
+ CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 0);
+ BKE_mesh_update_customdata_pointers(mesh, true);
+ loopsuv[0] = mesh->mloopuv;
+
+ // Second UV layer
+ CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[1]);
+ CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[1]);
+ CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 1);
+ CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 1);
+ BKE_mesh_update_customdata_pointers(mesh, true);
+ loopsuv[1] = mesh->mloopuv;
}
// colors and transparency (the latter represented by grayscale colors)
MLoopCol *colors = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Color");
MLoopCol *transp = (MLoopCol *)CustomData_add_layer_named(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop, "Alpha");
+ mesh->mloopcol = colors;
- BKE_mesh_update_customdata_pointers(mesh, true);
+ mesh->mat = (Material **)MEM_mallocN(sizeof(Material *) * mesh->totcol, "MaterialList");
////////////////////
// Data copy
////////////////////
- MVert *vertices = mesh->mvert;
- MEdge *edges = mesh->medge;
- MPoly *polys = mesh->mpoly;
- MLoop *loops = mesh->mloop;
+ int vertex_index = 0, edge_index = 0, loop_index = 0, material_index = 0;
+ int visible_faces, visible_segments;
+ bool visible;
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec2r p;
- vertex_index = edge_index = loop_index = 0;
+ for (vector<StrokeRep*>::const_iterator it = group->strokes.begin(), itend = group->strokes.end();
+ it != itend; ++it)
+ {
+ mesh->mat[material_index] = (*it)->getMaterial();
+ material_index++;
- for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
- Strip::vertex_container& strip_vertices = (*s)->vertices();
- int strip_vertex_count = strip_vertices.size();
+ vector<Strip*>& strips = (*it)->getStrips();
+ for (vector<Strip*>::const_iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+ int strip_vertex_count = strip_vertices.size();
- // count visible faces and strip segments
- test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
- if (visible_faces == 0)
- continue;
+ // count visible faces and strip segments
+ test_strip_visibility(strip_vertices, &visible_faces, &visible_segments);
+ if (visible_faces == 0)
+ continue;
- v[0] = strip_vertices.begin();
- v[1] = v[0] + 1;
- v[2] = v[0] + 2;
+ v[0] = strip_vertices.begin();
+ v[1] = v[0] + 1;
+ v[2] = v[0] + 2;
- visible = false;
+ visible = false;
- // Note: Mesh generation in the following loop assumes stroke strips
- // to be triangle strips.
- for (int 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]);
- if (!test_triangle_visibility(svRep)) {
- 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->no[0] = 0;
- vertices->no[1] = 0;
- vertices->no[2] = SHRT_MAX;
- ++vertices;
- ++vertex_index;
+ // Note: Mesh generation in the following loop assumes stroke strips
+ // to be triangle strips.
+ for (int 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]);
+ if (!test_triangle_visibility(svRep)) {
+ 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->no[0] = 0;
+ vertices->no[1] = 0;
+ vertices->no[2] = SHRT_MAX;
+ ++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->no[0] = 0;
+ vertices->no[1] = 0;
+ vertices->no[2] = SHRT_MAX;
+ ++vertices;
+ ++vertex_index;
+
+ // first edge
+ edges->v1 = vertex_index - 2;
+ edges->v2 = vertex_index - 1;
+ ++edges;
+ ++edge_index;
+ }
+ visible = true;
- // second vertex
- vertices->co[0] = svRep[1]->point2d()[0];
- vertices->co[1] = svRep[1]->point2d()[1];
+ // vertex
+ vertices->co[0] = svRep[2]->point2d()[0];
+ vertices->co[1] = svRep[2]->point2d()[1];
vertices->co[2] = get_stroke_vertex_z();
vertices->no[0] = 0;
vertices->no[1] = 0;
@@ -706,140 +791,127 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
++vertices;
++vertex_index;
- // first edge
- edges->v1 = vertex_index - 2;
- edges->v2 = vertex_index - 1;
+ // edges
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 3;
++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->no[0] = 0;
- vertices->no[1] = 0;
- vertices->no[2] = SHRT_MAX;
- ++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;
-
- // Even and odd loops connect triangles vertices differently
- bool is_odd = n % 2;
- // loops
- if (is_odd) {
- 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;
- }
- else {
- loops[0].v = vertex_index - 1;
- loops[0].e = edge_index - 1;
- loops[1].v = vertex_index - 2;
- loops[1].e = edge_index - 3;
+ edges->v1 = vertex_index - 1;
+ edges->v2 = vertex_index - 2;
+ ++edges;
+ ++edge_index;
- loops[2].v = vertex_index - 3;
- loops[2].e = edge_index - 2;
- }
- loops += 3;
- loop_index += 3;
-
- // UV
- if (hasTex) {
- // First UV layer (loopsuv[0]) has no tips (texCoord(0)).
- // Second UV layer (loopsuv[1]) has tips: (texCoord(1)).
- for (int L = 0; L < 2; L++) {
- if (is_odd) {
- loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
- loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
-
- loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
- loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
-
- loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
- loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
- }
- else {
- loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
- loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+ // poly
+ polys->loopstart = loop_index;
+ polys->totloop = 3;
+ ++polys;
+
+ // Even and odd loops connect triangles vertices differently
+ bool is_odd = n % 2;
+ // loops
+ if (is_odd) {
+ loops[0].v = vertex_index - 1;
+ loops[0].e = edge_index - 2;
- loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
- loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
+ loops[1].v = vertex_index - 3;
+ loops[1].e = edge_index - 3;
- loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
- loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
+ loops[2].v = vertex_index - 2;
+ loops[2].e = edge_index - 1;
+ }
+ else {
+ 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;
+ }
+ loops += 3;
+ loop_index += 3;
+
+ // UV
+ if (hasTex) {
+ // First UV layer (loopsuv[0]) has no tips (texCoord(0)).
+ // Second UV layer (loopsuv[1]) has tips: (texCoord(1)).
+ for (int L = 0; L < 2; L++) {
+ if (is_odd) {
+ loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
+ loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+
+ loopsuv[L][1].uv[0] = svRep[0]->texCoord(L).x();
+ loopsuv[L][1].uv[1] = svRep[0]->texCoord(L).y();
+
+ loopsuv[L][2].uv[0] = svRep[1]->texCoord(L).x();
+ loopsuv[L][2].uv[1] = svRep[1]->texCoord(L).y();
+ }
+ else {
+ loopsuv[L][0].uv[0] = svRep[2]->texCoord(L).x();
+ loopsuv[L][0].uv[1] = svRep[2]->texCoord(L).y();
+
+ loopsuv[L][1].uv[0] = svRep[1]->texCoord(L).x();
+ loopsuv[L][1].uv[1] = svRep[1]->texCoord(L).y();
+
+ loopsuv[L][2].uv[0] = svRep[0]->texCoord(L).x();
+ loopsuv[L][2].uv[1] = svRep[0]->texCoord(L).y();
+ }
+ loopsuv[L] += 3;
}
- loopsuv[L] += 3;
}
- }
- // colors and alpha transparency
- if (is_odd) {
- 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());
- }
- 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[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());
+ // colors and alpha transparency
+ if (is_odd) {
+ 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());
+ }
+ 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[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());
+ }
+ transp[0].r = transp[0].g = transp[0].b = colors[0].a;
+ transp[1].r = transp[1].g = transp[1].b = colors[1].a;
+ transp[2].r = transp[2].g = transp[2].b = colors[2].a;
+ colors += 3;
+ transp += 3;
}
- transp[0].r = transp[0].g = transp[0].b = colors[0].a;
- transp[1].r = transp[1].g = transp[1].b = colors[1].a;
- transp[2].r = transp[2].g = transp[2].b = colors[2].a;
- colors += 3;
- transp += 3;
- }
- } // loop over strip vertices
- } // loop over strips
-#if 0
- BLI_assert(totvert == vertex_index);
- BLI_assert(totedge == edge_index);
- BLI_assert(totloop == loop_index);
+ } // loop over strip vertices
+ } // loop over strips
+ } // loop over strokes
+
+ test_object_materials(freestyle_bmain, (ID *)mesh);
+
+#if 0 // XXX
+ BLI_assert(mesh->totvert == vertex_index);
+ BLI_assert(mesh->totedge == edge_index);
+ BLI_assert(mesh->totloop == loop_index);
+ BLI_assert(mesh->totcol == material_index);
BKE_mesh_validate(mesh, true);
#endif
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
index 74e5d321df2..a381932e9e7 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -53,6 +53,21 @@ public:
Object *NewMesh() const;
+ struct StrokeGroup {
+ explicit StrokeGroup() : totvert(0), totedge(0), totpoly(0), totloop(0), totcol(0) {}
+ vector<StrokeRep*> strokes;
+ int totvert;
+ int totedge;
+ int totpoly;
+ int totloop;
+ int totcol;
+ };
+ vector<StrokeGroup*> strokeGroups, texturedStrokeGroups;
+
+ int GenerateScene();
+ void GenerateStrokeMesh(StrokeGroup *group, bool hasTex);
+ void FreeStrokeGroups();
+
Render *RenderScene(Render *re, bool render);
static Material* GetStrokeShader(Main *bmain, bNodeTree *iNodeTree, bool do_id_user);
@@ -68,12 +83,16 @@ protected:
bool _use_shading_nodes;
struct GHash *_nodetree_hash;
+ static const char *uvNames[];
+
float get_stroke_vertex_z(void) const;
unsigned int get_stroke_mesh_id(void) const;
bool test_triangle_visibility(StrokeVertexRep *svRep[3]) const;
void test_strip_visibility(Strip::vertex_container& strip_vertices,
int *visible_faces, int *visible_segments) const;
+ vector<StrokeRep *> _strokeReps;
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStrokeRenderer")
#endif
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
index 863da069259..244b20f6b89 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.cpp
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -400,6 +400,7 @@ Stroke::Stroke()
}
_nodeTree = NULL;
_tips = false;
+ _rep = NULL;
}
Stroke::Stroke(const Stroke& iBrother)
@@ -427,6 +428,10 @@ Stroke::Stroke(const Stroke& iBrother)
}
_nodeTree = iBrother._nodeTree;
_tips = iBrother._tips;
+ if (iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = NULL;
}
Stroke::~Stroke()
@@ -439,6 +444,10 @@ Stroke::~Stroke()
}
_ViewEdges.clear();
+ if (_rep) {
+ delete _rep;
+ _rep = NULL;
+ }
}
Stroke& Stroke::operator=(const Stroke& iBrother)
@@ -456,6 +465,12 @@ Stroke& Stroke::operator=(const Stroke& iBrother)
_id = iBrother._id;
_ViewEdges = iBrother._ViewEdges;
_sampling = iBrother._sampling;
+ if (_rep)
+ delete _rep;
+ if (iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = NULL;
return *this;
}
@@ -757,14 +772,16 @@ void Stroke::ScaleThickness(float iFactor)
void Stroke::Render(const StrokeRenderer *iRenderer)
{
- StrokeRep rep(this);
- iRenderer->RenderStrokeRep(&rep);
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
}
void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
{
- StrokeRep rep(this);
- iRenderer->RenderStrokeRepBasic(&rep);
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
}
Stroke::vertex_iterator Stroke::vertices_begin(float sampling)
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
index 8ff801ed144..5f0b4eab309 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.h
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -549,6 +549,7 @@ private:
MTex *_mtex[MAX_MTEX];
bNodeTree *_nodeTree;
bool _tips;
+ StrokeRep *_rep;
Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
public: