diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/freestyle/intern/blender_interface | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/freestyle/intern/blender_interface')
6 files changed, 2158 insertions, 2078 deletions
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 1e2bfecff6a..6b14c9ec70f 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -30,151 +30,145 @@ namespace Freestyle { BlenderFileLoader::BlenderFileLoader(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph) { - _re = re; - _depsgraph = depsgraph; - _Scene = NULL; - _numFacesRead = 0; + _re = re; + _depsgraph = depsgraph; + _Scene = NULL; + _numFacesRead = 0; #if 0 - _minEdgeSize = DBL_MAX; + _minEdgeSize = DBL_MAX; #endif - _smooth = (view_layer->freestyle_config.flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) != 0; - _pRenderMonitor = NULL; + _smooth = (view_layer->freestyle_config.flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) != 0; + _pRenderMonitor = NULL; } BlenderFileLoader::~BlenderFileLoader() { - _Scene = NULL; + _Scene = NULL; } NodeGroup *BlenderFileLoader::Load() { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "\n=== Importing triangular meshes into Blender ===" << endl; - } - - // creation of the scene root node - _Scene = new NodeGroup; - - _viewplane_left = _re->viewplane.xmin; - _viewplane_right = _re->viewplane.xmax; - _viewplane_bottom = _re->viewplane.ymin; - _viewplane_top = _re->viewplane.ymax; - - if (_re->clip_start < 0.f) { - // Adjust clipping start/end and set up a Z offset when the viewport preview - // is used with the orthographic view. In this case, _re->clip_start is negative, - // while Freestyle assumes that imported mesh data are in the camera coordinate - // system with the view point located at origin [bug #36009]. - _z_near = -0.001f; - _z_offset = _re->clip_start + _z_near; - _z_far = -_re->clip_end + _z_offset; - } - else { - _z_near = -_re->clip_start; - _z_far = -_re->clip_end; - _z_offset = 0.f; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "\n=== Importing triangular meshes into Blender ===" << endl; + } + + // creation of the scene root node + _Scene = new NodeGroup; + + _viewplane_left = _re->viewplane.xmin; + _viewplane_right = _re->viewplane.xmax; + _viewplane_bottom = _re->viewplane.ymin; + _viewplane_top = _re->viewplane.ymax; + + if (_re->clip_start < 0.f) { + // Adjust clipping start/end and set up a Z offset when the viewport preview + // is used with the orthographic view. In this case, _re->clip_start is negative, + // while Freestyle assumes that imported mesh data are in the camera coordinate + // system with the view point located at origin [bug #36009]. + _z_near = -0.001f; + _z_offset = _re->clip_start + _z_near; + _z_far = -_re->clip_end + _z_offset; + } + else { + _z_near = -_re->clip_start; + _z_far = -_re->clip_end; + _z_offset = 0.f; + } #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Frustum: l " << _viewplane_left << " r " << _viewplane_right - << " b " << _viewplane_bottom << " t " << _viewplane_top - << " n " << _z_near << " f " << _z_far << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Frustum: l " << _viewplane_left << " r " << _viewplane_right + << " b " << _viewplane_bottom << " t " << _viewplane_top + << " n " << _z_near << " f " << _z_far << endl; + } #endif - int id = 0; - - DEG_OBJECT_ITER_BEGIN( - _depsgraph, ob, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | - DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI) - { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) { - break; - } - - if (ob->base_flag & (BASE_HOLDOUT | BASE_INDIRECT_ONLY)) { - continue; - } - - bool apply_modifiers = false; - bool calc_undeformed = false; - Mesh *mesh = BKE_mesh_new_from_object(_depsgraph, - _re->main, - _re->scene, - ob, - apply_modifiers, - calc_undeformed); - - if (mesh) { - insertShapeNode(ob, mesh, ++id); - BKE_id_free_ex(_re->main, &mesh->id, LIB_ID_FREE_NO_UI_USER, true); - } - } - DEG_OBJECT_ITER_END; - - // Return the built scene. - return _Scene; + int id = 0; + + DEG_OBJECT_ITER_BEGIN (_depsgraph, + ob, + DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) { + break; + } + + if (ob->base_flag & (BASE_HOLDOUT | BASE_INDIRECT_ONLY)) { + continue; + } + + bool apply_modifiers = false; + bool calc_undeformed = false; + Mesh *mesh = BKE_mesh_new_from_object( + _depsgraph, _re->main, _re->scene, ob, apply_modifiers, calc_undeformed); + + if (mesh) { + insertShapeNode(ob, mesh, ++id); + BKE_id_free_ex(_re->main, &mesh->id, LIB_ID_FREE_NO_UI_USER, true); + } + } + DEG_OBJECT_ITER_END; + + // Return the built scene. + return _Scene; } #define CLIPPED_BY_NEAR -1 -#define NOT_CLIPPED 0 -#define CLIPPED_BY_FAR 1 +#define NOT_CLIPPED 0 +#define CLIPPED_BY_FAR 1 // check if each vertex of a triangle (V1, V2, V3) is clipped by the near/far plane // and calculate the number of triangles to be generated by clipping int BlenderFileLoader::countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]) { - float *v[3]; - int numClipped, sum, numTris = 0; - - v[0] = v1; - v[1] = v2; - v[2] = v3; - numClipped = sum = 0; - for (int i = 0; i < 3; i++) { - if (v[i][2] > _z_near) { - clip[i] = CLIPPED_BY_NEAR; - numClipped++; - } - else if (v[i][2] < _z_far) { - clip[i] = CLIPPED_BY_FAR; - numClipped++; - } - else { - clip[i] = NOT_CLIPPED; - } + float *v[3]; + int numClipped, sum, numTris = 0; + + v[0] = v1; + v[1] = v2; + v[2] = v3; + numClipped = sum = 0; + for (int i = 0; i < 3; i++) { + if (v[i][2] > _z_near) { + clip[i] = CLIPPED_BY_NEAR; + numClipped++; + } + else if (v[i][2] < _z_far) { + clip[i] = CLIPPED_BY_FAR; + numClipped++; + } + else { + clip[i] = NOT_CLIPPED; + } #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - printf("%d %s\n", i, (clip[i] == NOT_CLIPPED) ? "not" : (clip[i] == CLIPPED_BY_NEAR) ? "near" : "far"); - } + if (G.debug & G_DEBUG_FREESTYLE) { + printf("%d %s\n", i, (clip[i] == NOT_CLIPPED) ? "not" : (clip[i] == CLIPPED_BY_NEAR) ? "near" : "far"); + } #endif - sum += clip[i]; - } - switch (numClipped) { - case 0: - numTris = 1; // triangle - break; - case 1: - numTris = 2; // tetragon - break; - case 2: - if (sum == 0) - numTris = 3; // pentagon - else - numTris = 1; // triangle - break; - case 3: - if (sum == 3 || sum == -3) - numTris = 0; - else - numTris = 2; // tetragon - break; - } - return numTris; + sum += clip[i]; + } + switch (numClipped) { + case 0: + numTris = 1; // triangle + break; + case 1: + numTris = 2; // tetragon + break; + case 2: + if (sum == 0) + numTris = 3; // pentagon + else + numTris = 1; // triangle + break; + case 3: + if (sum == 3 || sum == -3) + numTris = 0; + else + numTris = 2; // tetragon + break; + } + return numTris; } // find the intersection point C between the line segment from V1 to V2 and @@ -182,143 +176,168 @@ int BlenderFileLoader::countClippedFaces(float v1[3], float v2[3], float v3[3], // the X and Y components are unknown). void BlenderFileLoader::clipLine(float v1[3], float v2[3], float c[3], float z) { - // Order v1 and v2 by Z values to make sure that clipLine(P, Q, c, z) - // and clipLine(Q, P, c, z) gives exactly the same numerical result. - float *p, *q; - if (v1[2] < v2[2]) { - p = v1; - q = v2; - } - else { - p = v2; - q = v1; - } - double d[3]; - for (int i = 0; i < 3; i++) - d[i] = q[i] - p[i]; - double t = (z - p[2]) / d[2]; - c[0] = p[0] + t * d[0]; - c[1] = p[1] + t * d[1]; - c[2] = z; + // Order v1 and v2 by Z values to make sure that clipLine(P, Q, c, z) + // and clipLine(Q, P, c, z) gives exactly the same numerical result. + float *p, *q; + if (v1[2] < v2[2]) { + p = v1; + q = v2; + } + else { + p = v2; + q = v1; + } + double d[3]; + for (int i = 0; i < 3; i++) + d[i] = q[i] - p[i]; + double t = (z - p[2]) / d[2]; + c[0] = p[0] + t * d[0]; + c[1] = p[1] + t * d[1]; + c[2] = z; } // clip the triangle (V1, V2, V3) by the near and far clipping plane and // obtain a set of vertices after the clipping. The number of vertices // is at most 5. -void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], - float triNormals[][3], float n1[3], float n2[3], float n3[3], - bool edgeMarks[], bool em1, bool em2, bool em3, int clip[3]) +void BlenderFileLoader::clipTriangle(int numTris, + float triCoords[][3], + float v1[3], + float v2[3], + float v3[3], + float triNormals[][3], + float n1[3], + float n2[3], + float n3[3], + bool edgeMarks[], + bool em1, + bool em2, + bool em3, + int clip[3]) { - float *v[3], *n[3]; - bool em[3]; - int i, j, k; - - v[0] = v1; n[0] = n1; - v[1] = v2; n[1] = n2; - v[2] = v3; n[2] = n3; - em[0] = em1; /* edge mark of the edge between v1 and v2 */ - em[1] = em2; /* edge mark of the edge between v2 and v3 */ - em[2] = em3; /* edge mark of the edge between v3 and v1 */ - k = 0; - for (i = 0; i < 3; i++) { - j = (i + 1) % 3; - if (clip[i] == NOT_CLIPPED) { - copy_v3_v3(triCoords[k], v[i]); - copy_v3_v3(triNormals[k], n[i]); - edgeMarks[k] = em[i]; - k++; - if (clip[j] != NOT_CLIPPED) { - clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); - copy_v3_v3(triNormals[k], n[j]); - edgeMarks[k] = false; - k++; - } - } - else if (clip[i] != clip[j]) { - if (clip[j] == NOT_CLIPPED) { - clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); - copy_v3_v3(triNormals[k], n[i]); - edgeMarks[k] = em[i]; - k++; - } - else { - clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); - copy_v3_v3(triNormals[k], n[i]); - edgeMarks[k] = em[i]; - k++; - clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); - copy_v3_v3(triNormals[k], n[j]); - edgeMarks[k] = false; - k++; - } - } - } - BLI_assert(k == 2 + numTris); - (void)numTris; /* Ignored in release builds. */ + float *v[3], *n[3]; + bool em[3]; + int i, j, k; + + v[0] = v1; + n[0] = n1; + v[1] = v2; + n[1] = n2; + v[2] = v3; + n[2] = n3; + em[0] = em1; /* edge mark of the edge between v1 and v2 */ + em[1] = em2; /* edge mark of the edge between v2 and v3 */ + em[2] = em3; /* edge mark of the edge between v3 and v1 */ + k = 0; + for (i = 0; i < 3; i++) { + j = (i + 1) % 3; + if (clip[i] == NOT_CLIPPED) { + copy_v3_v3(triCoords[k], v[i]); + copy_v3_v3(triNormals[k], n[i]); + edgeMarks[k] = em[i]; + k++; + if (clip[j] != NOT_CLIPPED) { + clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + copy_v3_v3(triNormals[k], n[j]); + edgeMarks[k] = false; + k++; + } + } + else if (clip[i] != clip[j]) { + if (clip[j] == NOT_CLIPPED) { + clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + copy_v3_v3(triNormals[k], n[i]); + edgeMarks[k] = em[i]; + k++; + } + else { + clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + copy_v3_v3(triNormals[k], n[i]); + edgeMarks[k] = em[i]; + k++; + clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far); + copy_v3_v3(triNormals[k], n[j]); + edgeMarks[k] = false; + k++; + } + } + } + BLI_assert(k == 2 + numTris); + (void)numTris; /* Ignored in release builds. */ } -void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3], - float n1[3], float n2[3], float n3[3], - bool fm, bool em1, bool em2, bool em3) +void BlenderFileLoader::addTriangle(struct LoaderState *ls, + float v1[3], + float v2[3], + float v3[3], + float n1[3], + float n2[3], + float n3[3], + bool fm, + bool em1, + bool em2, + bool em3) { - float *fv[3], *fn[3]; + float *fv[3], *fn[3]; #if 0 - float len; + float len; #endif - unsigned int i, j; - IndexedFaceSet::FaceEdgeMark marks = 0; - - // initialize the bounding box by the first vertex - if (ls->currentIndex == 0) { - copy_v3_v3(ls->minBBox, v1); - copy_v3_v3(ls->maxBBox, v1); - } - - fv[0] = v1; fn[0] = n1; - fv[1] = v2; fn[1] = n2; - fv[2] = v3; fn[2] = n3; - for (i = 0; i < 3; i++) { - - copy_v3_v3(ls->pv, fv[i]); - copy_v3_v3(ls->pn, fn[i]); - - // update the bounding box - for (j = 0; j < 3; j++) { - if (ls->minBBox[j] > ls->pv[j]) - ls->minBBox[j] = ls->pv[j]; - - if (ls->maxBBox[j] < ls->pv[j]) - ls->maxBBox[j] = ls->pv[j]; - } + unsigned int i, j; + IndexedFaceSet::FaceEdgeMark marks = 0; + + // initialize the bounding box by the first vertex + if (ls->currentIndex == 0) { + copy_v3_v3(ls->minBBox, v1); + copy_v3_v3(ls->maxBBox, v1); + } + + fv[0] = v1; + fn[0] = n1; + fv[1] = v2; + fn[1] = n2; + fv[2] = v3; + fn[2] = n3; + for (i = 0; i < 3; i++) { + + copy_v3_v3(ls->pv, fv[i]); + copy_v3_v3(ls->pn, fn[i]); + + // update the bounding box + for (j = 0; j < 3; j++) { + if (ls->minBBox[j] > ls->pv[j]) + ls->minBBox[j] = ls->pv[j]; + + if (ls->maxBBox[j] < ls->pv[j]) + ls->maxBBox[j] = ls->pv[j]; + } #if 0 - len = len_v3v3(fv[i], fv[(i + 1) % 3]); - if (_minEdgeSize > len) - _minEdgeSize = len; + len = len_v3v3(fv[i], fv[(i + 1) % 3]); + if (_minEdgeSize > len) + _minEdgeSize = len; #endif - *ls->pvi = ls->currentIndex; - *ls->pni = ls->currentIndex; - *ls->pmi = ls->currentMIndex; - - ls->currentIndex += 3; - ls->pv += 3; - ls->pn += 3; - - ls->pvi++; - ls->pni++; - ls->pmi++; - } - - if (fm) - marks |= IndexedFaceSet::FACE_MARK; - if (em1) - marks |= IndexedFaceSet::EDGE_MARK_V1V2; - if (em2) - marks |= IndexedFaceSet::EDGE_MARK_V2V3; - if (em3) - marks |= IndexedFaceSet::EDGE_MARK_V3V1; - *(ls->pm++) = marks; + *ls->pvi = ls->currentIndex; + *ls->pni = ls->currentIndex; + *ls->pmi = ls->currentMIndex; + + ls->currentIndex += 3; + ls->pv += 3; + ls->pn += 3; + + ls->pvi++; + ls->pni++; + ls->pmi++; + } + + if (fm) + marks |= IndexedFaceSet::FACE_MARK; + if (em1) + marks |= IndexedFaceSet::EDGE_MARK_V1V2; + if (em2) + marks |= IndexedFaceSet::EDGE_MARK_V2V3; + if (em3) + marks |= IndexedFaceSet::EDGE_MARK_V3V1; + *(ls->pm++) = marks; } // With A, B and P indicating the three vertices of a given triangle, returns: @@ -327,420 +346,445 @@ void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v // zero otherwise. int BlenderFileLoader::testDegenerateTriangle(float v1[3], float v2[3], float v3[3]) { - const float eps = 1.0e-6; - const float eps_sq = eps * eps; + const float eps = 1.0e-6; + const float eps_sq = eps * eps; #if 0 - float area = area_tri_v3(v1, v2, v3); - bool verbose = (area < 1.0e-6); + float area = area_tri_v3(v1, v2, v3); + bool verbose = (area < 1.0e-6); #endif - if (equals_v3v3(v1, v2) || equals_v3v3(v2, v3) || equals_v3v3(v1, v3)) { + if (equals_v3v3(v1, v2) || equals_v3v3(v2, v3) || equals_v3v3(v1, v3)) { #if 0 - if (verbose && G.debug & G_DEBUG_FREESTYLE) { - printf("BlenderFileLoader::testDegenerateTriangle = 1\n"); - } + if (verbose && G.debug & G_DEBUG_FREESTYLE) { + printf("BlenderFileLoader::testDegenerateTriangle = 1\n"); + } #endif - return 1; - } - if (dist_squared_to_line_segment_v3(v1, v2, v3) < eps_sq || - dist_squared_to_line_segment_v3(v2, v1, v3) < eps_sq || - dist_squared_to_line_segment_v3(v3, v1, v2) < eps_sq) - { + return 1; + } + if (dist_squared_to_line_segment_v3(v1, v2, v3) < eps_sq || + dist_squared_to_line_segment_v3(v2, v1, v3) < eps_sq || + dist_squared_to_line_segment_v3(v3, v1, v2) < eps_sq) { #if 0 - if (verbose && G.debug & G_DEBUG_FREESTYLE) { - printf("BlenderFileLoader::testDegenerateTriangle = 2\n"); - } + if (verbose && G.debug & G_DEBUG_FREESTYLE) { + printf("BlenderFileLoader::testDegenerateTriangle = 2\n"); + } #endif - return 2; - } + return 2; + } #if 0 - if (verbose && G.debug & G_DEBUG_FREESTYLE) { - printf("BlenderFileLoader::testDegenerateTriangle = 0\n"); - } + if (verbose && G.debug & G_DEBUG_FREESTYLE) { + printf("BlenderFileLoader::testDegenerateTriangle = 0\n"); + } #endif - return 0; + return 0; } static bool testEdgeMark(Mesh *me, FreestyleEdge *fed, const MLoopTri *lt, int i) { - MLoop *mloop = &me->mloop[lt->tri[i]]; - MLoop *mloop_next = &me->mloop[lt->tri[(i+1)%3]]; - MEdge *medge = &me->medge[mloop->e]; + MLoop *mloop = &me->mloop[lt->tri[i]]; + MLoop *mloop_next = &me->mloop[lt->tri[(i + 1) % 3]]; + MEdge *medge = &me->medge[mloop->e]; - if (!ELEM(mloop_next->v, medge->v1, medge->v2)) { - /* Not an edge in the original mesh before triangulation. */ - return false; - } + if (!ELEM(mloop_next->v, medge->v1, medge->v2)) { + /* Not an edge in the original mesh before triangulation. */ + return false; + } - return (fed[mloop->e].flag & FREESTYLE_EDGE_MARK) != 0; + return (fed[mloop->e].flag & FREESTYLE_EDGE_MARK) != 0; } void BlenderFileLoader::insertShapeNode(Object *ob, Mesh *me, int id) { - char *name = ob->id.name + 2; - - // Compute loop triangles - int tottri = poly_to_tri_count(me->totpoly, me->totloop); - MLoopTri *mlooptri = (MLoopTri*)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__); - BKE_mesh_recalc_looptri( - me->mloop, me->mpoly, - me->mvert, - me->totloop, me->totpoly, - mlooptri); - - // Compute loop normals - BKE_mesh_calc_normals_split(me); - float (*lnors)[3] = NULL; - - if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { - lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); - } - - // Get other mesh data - MVert *mvert = me->mvert; - MLoop *mloop = me->mloop; - MPoly *mpoly = me->mpoly; - FreestyleEdge *fed = (FreestyleEdge*)CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE); - FreestyleFace *ffa = (FreestyleFace*)CustomData_get_layer(&me->pdata, CD_FREESTYLE_FACE); - - // Compute view matrix - Object *ob_camera_eval = DEG_get_evaluated_object(_depsgraph, RE_GetCamera(_re)); - float viewinv[4][4], viewmat[4][4]; - RE_GetCameraModelMatrix(_re, ob_camera_eval, viewinv); - invert_m4_m4(viewmat, viewinv); - - // Compute matrix including camera transform - float obmat[4][4], nmat[4][4]; - mul_m4_m4m4(obmat, viewmat, ob->obmat); - invert_m4_m4(nmat, obmat); - transpose_m4(nmat); - - // We count the number of triangles after the clipping by the near and far view - // planes is applied (Note: mesh vertices are in the camera coordinate system). - unsigned numFaces = 0; - float v1[3], v2[3], v3[3]; - float n1[3], n2[3], n3[3], facenormal[3]; - int clip[3]; - for (int a = 0; a < tottri; a++) { - const MLoopTri *lt = &mlooptri[a]; - - copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co); - copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co); - copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co); - - mul_m4_v3(obmat, v1); - mul_m4_v3(obmat, v2); - mul_m4_v3(obmat, v3); - - v1[2] += _z_offset; - v2[2] += _z_offset; - v3[2] += _z_offset; - - numFaces += countClippedFaces(v1, v2, v3, clip); - } + char *name = ob->id.name + 2; + + // Compute loop triangles + int tottri = poly_to_tri_count(me->totpoly, me->totloop); + MLoopTri *mlooptri = (MLoopTri *)MEM_malloc_arrayN(tottri, sizeof(*mlooptri), __func__); + BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri); + + // Compute loop normals + BKE_mesh_calc_normals_split(me); + float(*lnors)[3] = NULL; + + if (CustomData_has_layer(&me->ldata, CD_NORMAL)) { + lnors = (float(*)[3])CustomData_get_layer(&me->ldata, CD_NORMAL); + } + + // Get other mesh data + MVert *mvert = me->mvert; + MLoop *mloop = me->mloop; + MPoly *mpoly = me->mpoly; + FreestyleEdge *fed = (FreestyleEdge *)CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE); + FreestyleFace *ffa = (FreestyleFace *)CustomData_get_layer(&me->pdata, CD_FREESTYLE_FACE); + + // Compute view matrix + Object *ob_camera_eval = DEG_get_evaluated_object(_depsgraph, RE_GetCamera(_re)); + float viewinv[4][4], viewmat[4][4]; + RE_GetCameraModelMatrix(_re, ob_camera_eval, viewinv); + invert_m4_m4(viewmat, viewinv); + + // Compute matrix including camera transform + float obmat[4][4], nmat[4][4]; + mul_m4_m4m4(obmat, viewmat, ob->obmat); + invert_m4_m4(nmat, obmat); + transpose_m4(nmat); + + // We count the number of triangles after the clipping by the near and far view + // planes is applied (Note: mesh vertices are in the camera coordinate system). + unsigned numFaces = 0; + float v1[3], v2[3], v3[3]; + float n1[3], n2[3], n3[3], facenormal[3]; + int clip[3]; + for (int a = 0; a < tottri; a++) { + const MLoopTri *lt = &mlooptri[a]; + + copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co); + copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co); + copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co); + + mul_m4_v3(obmat, v1); + mul_m4_v3(obmat, v2); + mul_m4_v3(obmat, v3); + + v1[2] += _z_offset; + v2[2] += _z_offset; + v3[2] += _z_offset; + + numFaces += countClippedFaces(v1, v2, v3, clip); + } #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "numFaces " << numFaces << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "numFaces " << numFaces << endl; + } #endif - if (numFaces == 0) { - MEM_freeN(mlooptri); - return; - } - - // We allocate memory for the meshes to be imported - NodeGroup *currentMesh = new NodeGroup; - NodeShape *shape = new NodeShape; - - unsigned vSize = 3 * 3 * numFaces; - float *vertices = new float[vSize]; - unsigned nSize = vSize; - float *normals = new float[nSize]; - unsigned *numVertexPerFaces = new unsigned[numFaces]; - vector<Material *> meshMaterials; - vector<FrsMaterial> meshFrsMaterials; - - IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces]; - unsigned i; - for (i = 0; i <numFaces; i++) { - faceStyle[i] = IndexedFaceSet::TRIANGLES; - numVertexPerFaces[i] = 3; - } - - IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = new IndexedFaceSet::FaceEdgeMark[numFaces]; - - unsigned viSize = 3 * numFaces; - unsigned *VIndices = new unsigned[viSize]; - unsigned niSize = viSize; - unsigned *NIndices = new unsigned[niSize]; - unsigned *MIndices = new unsigned[viSize]; // Material Indices - - struct LoaderState ls; - ls.pv = vertices; - ls.pn = normals; - ls.pm = faceEdgeMarks; - ls.pvi = VIndices; - ls.pni = NIndices; - ls.pmi = MIndices; - ls.currentIndex = 0; - ls.currentMIndex = 0; - - FrsMaterial tmpMat; - - // We parse the vlak nodes again and import meshes while applying the clipping - // by the near and far view planes. - for (int a = 0; a < tottri; a++) { - const MLoopTri *lt = &mlooptri[a]; - const MPoly *mp = &mpoly[lt->poly]; - Material *mat = give_current_material(ob, mp->mat_nr + 1); - - copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co); - copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co); - copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co); - - mul_m4_v3(obmat, v1); - mul_m4_v3(obmat, v2); - mul_m4_v3(obmat, v3); - - v1[2] += _z_offset; - v2[2] += _z_offset; - v3[2] += _z_offset; - - if (_smooth && (mp->flag & ME_SMOOTH) && lnors) { - copy_v3_v3(n1, lnors[lt->tri[0]]); - copy_v3_v3(n2, lnors[lt->tri[1]]); - copy_v3_v3(n3, lnors[lt->tri[2]]); - - mul_mat3_m4_v3(nmat, n1); - mul_mat3_m4_v3(nmat, n2); - mul_mat3_m4_v3(nmat, n3); - - normalize_v3(n1); - normalize_v3(n2); - normalize_v3(n3); - } - else { - normal_tri_v3(facenormal, v3, v2, v1); - - copy_v3_v3(n1, facenormal); - copy_v3_v3(n2, facenormal); - copy_v3_v3(n3, facenormal); - } - - unsigned int numTris = countClippedFaces(v1, v2, v3, clip); - if (numTris == 0) - continue; - - bool fm = (ffa) ? (ffa[lt->poly].flag & FREESTYLE_FACE_MARK) != 0 : false; - bool em1 = false, em2 = false, em3 = false; - - if (fed) { - em1 = testEdgeMark(me, fed, lt, 0); - em2 = testEdgeMark(me, fed, lt, 1); - em3 = testEdgeMark(me, fed, lt, 2); - } - - if (mat) { - tmpMat.setLine(mat->line_col[0], mat->line_col[1], mat->line_col[2], mat->line_col[3]); - tmpMat.setDiffuse(mat->r, mat->g, mat->b, 1.0f); - tmpMat.setSpecular(mat->specr, mat->specg, mat->specb, 1.0f); - tmpMat.setShininess(128.f); - tmpMat.setPriority(mat->line_priority); - } - - if (meshMaterials.empty()) { - meshMaterials.push_back(mat); - meshFrsMaterials.push_back(tmpMat); - shape->setFrsMaterial(tmpMat); - } - else { - // find if the Blender material is already in the list - unsigned int i = 0; - bool found = false; - - for (vector<Material *>::iterator it = meshMaterials.begin(), itend = meshMaterials.end(); - it != itend; - it++, i++) - { - if (*it == mat) { - ls.currentMIndex = i; - found = true; - break; - } - } - - if (!found) { - meshMaterials.push_back(mat); - meshFrsMaterials.push_back(tmpMat); - ls.currentMIndex = meshFrsMaterials.size() - 1; - } - } - - float triCoords[5][3], triNormals[5][3]; - bool edgeMarks[5]; // edgeMarks[i] is for the edge between i-th and (i+1)-th vertices - - clipTriangle(numTris, triCoords, v1, v2, v3, triNormals, n1, n2, n3, - edgeMarks, em1, em2, em3, clip); - for (i = 0; i < numTris; i++) { - addTriangle(&ls, triCoords[0], triCoords[i + 1], triCoords[i + 2], - triNormals[0], triNormals[i + 1], triNormals[i + 2], - fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i + 1], - (i == numTris - 1) ? edgeMarks[i + 2] : false); - _numFacesRead++; - } - } - - MEM_freeN(mlooptri); - - // We might have several times the same vertex. We want a clean - // shape with no real-vertex. Here, we are making a cleaning pass. - float *cleanVertices = NULL; - unsigned int cvSize; - unsigned int *cleanVIndices = NULL; - - GeomCleaner::CleanIndexedVertexArray(vertices, vSize, VIndices, viSize, &cleanVertices, &cvSize, &cleanVIndices); - - float *cleanNormals = NULL; - unsigned int cnSize; - unsigned int *cleanNIndices = NULL; - - GeomCleaner::CleanIndexedVertexArray(normals, nSize, NIndices, niSize, &cleanNormals, &cnSize, &cleanNIndices); - - // format materials array - FrsMaterial **marray = new FrsMaterial *[meshFrsMaterials.size()]; - unsigned int mindex = 0; - for (vector<FrsMaterial>::iterator m = meshFrsMaterials.begin(), mend = meshFrsMaterials.end(); m != mend; ++m) { - marray[mindex] = new FrsMaterial(*m); - ++mindex; - } - - // deallocates memory: - delete [] vertices; - delete [] normals; - delete [] VIndices; - delete [] NIndices; - - // Fix for degenerated triangles - // A degenerate triangle is a triangle such that - // 1) A and B are in the same position in the 3D space; or - // 2) the distance between point P and line segment AB is zero. - // Only those degenerate triangles in the second form are resolved here - // by adding a small offset to P, whereas those in the first form are - // addressed later in WShape::MakeFace(). - vector<detri_t> detriList; - Vec3r zero(0.0, 0.0, 0.0); - unsigned vi0, vi1, vi2; - for (i = 0; i < viSize; i += 3) { - detri_t detri; - vi0 = cleanVIndices[i]; - vi1 = cleanVIndices[i + 1]; - vi2 = cleanVIndices[i + 2]; - Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]); - Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]); - Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]); - if (v0 == v1 || v0 == v2 || v1 == v2) { - continue; // do nothing for now - } - else if (GeomUtils::distPointSegment<Vec3r>(v0, v1, v2) < 1.0e-6) { - detri.viP = vi0; - detri.viA = vi1; - detri.viB = vi2; - } - else if (GeomUtils::distPointSegment<Vec3r>(v1, v0, v2) < 1.0e-6) { - detri.viP = vi1; - detri.viA = vi0; - detri.viB = vi2; - } - else if (GeomUtils::distPointSegment<Vec3r>(v2, v0, v1) < 1.0e-6) { - detri.viP = vi2; - detri.viA = vi0; - detri.viB = vi1; - } - else { - continue; - } - - detri.v = zero; - detri.n = 0; - for (unsigned int j = 0; j < viSize; j += 3) { - if (i == j) - continue; - vi0 = cleanVIndices[j]; - vi1 = cleanVIndices[j + 1]; - vi2 = cleanVIndices[j + 2]; - Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]); - Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]); - Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]); - if (detri.viP == vi0 && (detri.viA == vi1 || detri.viB == vi1)) { - detri.v += (v2 - v0); - detri.n++; - } - else if (detri.viP == vi0 && (detri.viA == vi2 || detri.viB == vi2)) { - detri.v += (v1 - v0); - detri.n++; - } - else if (detri.viP == vi1 && (detri.viA == vi0 || detri.viB == vi0)) { - detri.v += (v2 - v1); - detri.n++; - } - else if (detri.viP == vi1 && (detri.viA == vi2 || detri.viB == vi2)) { - detri.v += (v0 - v1); - detri.n++; - } - else if (detri.viP == vi2 && (detri.viA == vi0 || detri.viB == vi0)) { - detri.v += (v1 - v2); - detri.n++; - } - else if (detri.viP == vi2 && (detri.viA == vi1 || detri.viB == vi1)) { - detri.v += (v0 - v2); - detri.n++; - } - } - if (detri.n > 0) { - detri.v.normalizeSafe(); - } - detriList.push_back(detri); - } - - if (detriList.size() > 0) { - vector<detri_t>::iterator v; - for (v = detriList.begin(); v != detriList.end(); v++) { - detri_t detri = (*v); - if (detri.n == 0) { - cleanVertices[detri.viP] = cleanVertices[detri.viA]; - cleanVertices[detri.viP + 1] = cleanVertices[detri.viA + 1]; - cleanVertices[detri.viP + 2] = cleanVertices[detri.viA + 2]; - } - else if (detri.v.norm() > 0.0) { - cleanVertices[detri.viP] += 1.0e-5 * detri.v.x(); - cleanVertices[detri.viP + 1] += 1.0e-5 * detri.v.y(); - cleanVertices[detri.viP + 2] += 1.0e-5 * detri.v.z(); - } - } - if (G.debug & G_DEBUG_FREESTYLE) { - printf("Warning: Object %s contains %lu degenerated triangle%s (strokes may be incorrect)\n", - name, (long unsigned int)detriList.size(), (detriList.size() > 1) ? "s" : ""); - } - } - - // Create the IndexedFaceSet with the retrieved attributes - IndexedFaceSet *rep; - rep = new IndexedFaceSet(cleanVertices, cvSize, cleanNormals, cnSize, marray, meshFrsMaterials.size(), 0, 0, - numFaces, numVertexPerFaces, faceStyle, faceEdgeMarks, cleanVIndices, viSize, - cleanNIndices, niSize, MIndices, viSize, 0, 0, 0); - // sets the id of the rep - rep->setId(Id(id, 0)); - rep->setName(ob->id.name + 2); - rep->setLibraryPath(ob->id.lib ? ob->id.lib->name : ""); - - const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]), - Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2])); - rep->setBBox(bbox); - shape->AddRep(rep); - - currentMesh->AddChild(shape); - _Scene->AddChild(currentMesh); + if (numFaces == 0) { + MEM_freeN(mlooptri); + return; + } + + // We allocate memory for the meshes to be imported + NodeGroup *currentMesh = new NodeGroup; + NodeShape *shape = new NodeShape; + + unsigned vSize = 3 * 3 * numFaces; + float *vertices = new float[vSize]; + unsigned nSize = vSize; + float *normals = new float[nSize]; + unsigned *numVertexPerFaces = new unsigned[numFaces]; + vector<Material *> meshMaterials; + vector<FrsMaterial> meshFrsMaterials; + + IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces]; + unsigned i; + for (i = 0; i < numFaces; i++) { + faceStyle[i] = IndexedFaceSet::TRIANGLES; + numVertexPerFaces[i] = 3; + } + + IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = new IndexedFaceSet::FaceEdgeMark[numFaces]; + + unsigned viSize = 3 * numFaces; + unsigned *VIndices = new unsigned[viSize]; + unsigned niSize = viSize; + unsigned *NIndices = new unsigned[niSize]; + unsigned *MIndices = new unsigned[viSize]; // Material Indices + + struct LoaderState ls; + ls.pv = vertices; + ls.pn = normals; + ls.pm = faceEdgeMarks; + ls.pvi = VIndices; + ls.pni = NIndices; + ls.pmi = MIndices; + ls.currentIndex = 0; + ls.currentMIndex = 0; + + FrsMaterial tmpMat; + + // We parse the vlak nodes again and import meshes while applying the clipping + // by the near and far view planes. + for (int a = 0; a < tottri; a++) { + const MLoopTri *lt = &mlooptri[a]; + const MPoly *mp = &mpoly[lt->poly]; + Material *mat = give_current_material(ob, mp->mat_nr + 1); + + copy_v3_v3(v1, mvert[mloop[lt->tri[0]].v].co); + copy_v3_v3(v2, mvert[mloop[lt->tri[1]].v].co); + copy_v3_v3(v3, mvert[mloop[lt->tri[2]].v].co); + + mul_m4_v3(obmat, v1); + mul_m4_v3(obmat, v2); + mul_m4_v3(obmat, v3); + + v1[2] += _z_offset; + v2[2] += _z_offset; + v3[2] += _z_offset; + + if (_smooth && (mp->flag & ME_SMOOTH) && lnors) { + copy_v3_v3(n1, lnors[lt->tri[0]]); + copy_v3_v3(n2, lnors[lt->tri[1]]); + copy_v3_v3(n3, lnors[lt->tri[2]]); + + mul_mat3_m4_v3(nmat, n1); + mul_mat3_m4_v3(nmat, n2); + mul_mat3_m4_v3(nmat, n3); + + normalize_v3(n1); + normalize_v3(n2); + normalize_v3(n3); + } + else { + normal_tri_v3(facenormal, v3, v2, v1); + + copy_v3_v3(n1, facenormal); + copy_v3_v3(n2, facenormal); + copy_v3_v3(n3, facenormal); + } + + unsigned int numTris = countClippedFaces(v1, v2, v3, clip); + if (numTris == 0) + continue; + + bool fm = (ffa) ? (ffa[lt->poly].flag & FREESTYLE_FACE_MARK) != 0 : false; + bool em1 = false, em2 = false, em3 = false; + + if (fed) { + em1 = testEdgeMark(me, fed, lt, 0); + em2 = testEdgeMark(me, fed, lt, 1); + em3 = testEdgeMark(me, fed, lt, 2); + } + + if (mat) { + tmpMat.setLine(mat->line_col[0], mat->line_col[1], mat->line_col[2], mat->line_col[3]); + tmpMat.setDiffuse(mat->r, mat->g, mat->b, 1.0f); + tmpMat.setSpecular(mat->specr, mat->specg, mat->specb, 1.0f); + tmpMat.setShininess(128.f); + tmpMat.setPriority(mat->line_priority); + } + + if (meshMaterials.empty()) { + meshMaterials.push_back(mat); + meshFrsMaterials.push_back(tmpMat); + shape->setFrsMaterial(tmpMat); + } + else { + // find if the Blender material is already in the list + unsigned int i = 0; + bool found = false; + + for (vector<Material *>::iterator it = meshMaterials.begin(), itend = meshMaterials.end(); + it != itend; + it++, i++) { + if (*it == mat) { + ls.currentMIndex = i; + found = true; + break; + } + } + + if (!found) { + meshMaterials.push_back(mat); + meshFrsMaterials.push_back(tmpMat); + ls.currentMIndex = meshFrsMaterials.size() - 1; + } + } + + float triCoords[5][3], triNormals[5][3]; + bool edgeMarks[5]; // edgeMarks[i] is for the edge between i-th and (i+1)-th vertices + + clipTriangle( + numTris, triCoords, v1, v2, v3, triNormals, n1, n2, n3, edgeMarks, em1, em2, em3, clip); + for (i = 0; i < numTris; i++) { + addTriangle(&ls, + triCoords[0], + triCoords[i + 1], + triCoords[i + 2], + triNormals[0], + triNormals[i + 1], + triNormals[i + 2], + fm, + (i == 0) ? edgeMarks[0] : false, + edgeMarks[i + 1], + (i == numTris - 1) ? edgeMarks[i + 2] : false); + _numFacesRead++; + } + } + + MEM_freeN(mlooptri); + + // We might have several times the same vertex. We want a clean + // shape with no real-vertex. Here, we are making a cleaning pass. + float *cleanVertices = NULL; + unsigned int cvSize; + unsigned int *cleanVIndices = NULL; + + GeomCleaner::CleanIndexedVertexArray( + vertices, vSize, VIndices, viSize, &cleanVertices, &cvSize, &cleanVIndices); + + float *cleanNormals = NULL; + unsigned int cnSize; + unsigned int *cleanNIndices = NULL; + + GeomCleaner::CleanIndexedVertexArray( + normals, nSize, NIndices, niSize, &cleanNormals, &cnSize, &cleanNIndices); + + // format materials array + FrsMaterial **marray = new FrsMaterial *[meshFrsMaterials.size()]; + unsigned int mindex = 0; + for (vector<FrsMaterial>::iterator m = meshFrsMaterials.begin(), mend = meshFrsMaterials.end(); + m != mend; + ++m) { + marray[mindex] = new FrsMaterial(*m); + ++mindex; + } + + // deallocates memory: + delete[] vertices; + delete[] normals; + delete[] VIndices; + delete[] NIndices; + + // Fix for degenerated triangles + // A degenerate triangle is a triangle such that + // 1) A and B are in the same position in the 3D space; or + // 2) the distance between point P and line segment AB is zero. + // Only those degenerate triangles in the second form are resolved here + // by adding a small offset to P, whereas those in the first form are + // addressed later in WShape::MakeFace(). + vector<detri_t> detriList; + Vec3r zero(0.0, 0.0, 0.0); + unsigned vi0, vi1, vi2; + for (i = 0; i < viSize; i += 3) { + detri_t detri; + vi0 = cleanVIndices[i]; + vi1 = cleanVIndices[i + 1]; + vi2 = cleanVIndices[i + 2]; + Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]); + Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]); + Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]); + if (v0 == v1 || v0 == v2 || v1 == v2) { + continue; // do nothing for now + } + else if (GeomUtils::distPointSegment<Vec3r>(v0, v1, v2) < 1.0e-6) { + detri.viP = vi0; + detri.viA = vi1; + detri.viB = vi2; + } + else if (GeomUtils::distPointSegment<Vec3r>(v1, v0, v2) < 1.0e-6) { + detri.viP = vi1; + detri.viA = vi0; + detri.viB = vi2; + } + else if (GeomUtils::distPointSegment<Vec3r>(v2, v0, v1) < 1.0e-6) { + detri.viP = vi2; + detri.viA = vi0; + detri.viB = vi1; + } + else { + continue; + } + + detri.v = zero; + detri.n = 0; + for (unsigned int j = 0; j < viSize; j += 3) { + if (i == j) + continue; + vi0 = cleanVIndices[j]; + vi1 = cleanVIndices[j + 1]; + vi2 = cleanVIndices[j + 2]; + Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]); + Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]); + Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]); + if (detri.viP == vi0 && (detri.viA == vi1 || detri.viB == vi1)) { + detri.v += (v2 - v0); + detri.n++; + } + else if (detri.viP == vi0 && (detri.viA == vi2 || detri.viB == vi2)) { + detri.v += (v1 - v0); + detri.n++; + } + else if (detri.viP == vi1 && (detri.viA == vi0 || detri.viB == vi0)) { + detri.v += (v2 - v1); + detri.n++; + } + else if (detri.viP == vi1 && (detri.viA == vi2 || detri.viB == vi2)) { + detri.v += (v0 - v1); + detri.n++; + } + else if (detri.viP == vi2 && (detri.viA == vi0 || detri.viB == vi0)) { + detri.v += (v1 - v2); + detri.n++; + } + else if (detri.viP == vi2 && (detri.viA == vi1 || detri.viB == vi1)) { + detri.v += (v0 - v2); + detri.n++; + } + } + if (detri.n > 0) { + detri.v.normalizeSafe(); + } + detriList.push_back(detri); + } + + if (detriList.size() > 0) { + vector<detri_t>::iterator v; + for (v = detriList.begin(); v != detriList.end(); v++) { + detri_t detri = (*v); + if (detri.n == 0) { + cleanVertices[detri.viP] = cleanVertices[detri.viA]; + cleanVertices[detri.viP + 1] = cleanVertices[detri.viA + 1]; + cleanVertices[detri.viP + 2] = cleanVertices[detri.viA + 2]; + } + else if (detri.v.norm() > 0.0) { + cleanVertices[detri.viP] += 1.0e-5 * detri.v.x(); + cleanVertices[detri.viP + 1] += 1.0e-5 * detri.v.y(); + cleanVertices[detri.viP + 2] += 1.0e-5 * detri.v.z(); + } + } + if (G.debug & G_DEBUG_FREESTYLE) { + printf("Warning: Object %s contains %lu degenerated triangle%s (strokes may be incorrect)\n", + name, + (long unsigned int)detriList.size(), + (detriList.size() > 1) ? "s" : ""); + } + } + + // Create the IndexedFaceSet with the retrieved attributes + IndexedFaceSet *rep; + rep = new IndexedFaceSet(cleanVertices, + cvSize, + cleanNormals, + cnSize, + marray, + meshFrsMaterials.size(), + 0, + 0, + numFaces, + numVertexPerFaces, + faceStyle, + faceEdgeMarks, + cleanVIndices, + viSize, + cleanNIndices, + niSize, + MIndices, + viSize, + 0, + 0, + 0); + // sets the id of the rep + rep->setId(Id(id, 0)); + rep->setName(ob->id.name + 2); + rep->setLibraryPath(ob->id.lib ? ob->id.lib->name : ""); + + const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]), + Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2])); + rep->setBBox(bbox); + shape->AddRep(rep); + + currentMesh->AddChild(shape); + _Scene->AddChild(currentMesh); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h index 251e9329128..5fe98fba0d0 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h @@ -61,7 +61,7 @@ extern "C" { #include "DEG_depsgraph_query.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -69,78 +69,103 @@ namespace Freestyle { class NodeGroup; struct LoaderState { - float *pv; - float *pn; - IndexedFaceSet::FaceEdgeMark *pm; - unsigned *pvi; - unsigned *pni; - unsigned *pmi; - unsigned currentIndex; - unsigned currentMIndex; - float minBBox[3]; - float maxBBox[3]; + float *pv; + float *pn; + IndexedFaceSet::FaceEdgeMark *pm; + unsigned *pvi; + unsigned *pni; + unsigned *pmi; + unsigned currentIndex; + unsigned currentMIndex; + float minBBox[3]; + float maxBBox[3]; }; -class BlenderFileLoader -{ -public: - /*! Builds a MaxFileLoader */ - BlenderFileLoader(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph); - virtual ~BlenderFileLoader(); +class BlenderFileLoader { + public: + /*! Builds a MaxFileLoader */ + BlenderFileLoader(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph); + virtual ~BlenderFileLoader(); - /*! Loads the 3D scene and returns a pointer to the scene root node */ - NodeGroup *Load(); + /*! Loads the 3D scene and returns a pointer to the scene root node */ + NodeGroup *Load(); - /*! Gets the number of read faces */ - inline unsigned int numFacesRead() {return _numFacesRead;} + /*! Gets the number of read faces */ + inline unsigned int numFacesRead() + { + return _numFacesRead; + } #if 0 - /*! Gets the smallest edge size read */ - inline real minEdgeSize() {return _minEdgeSize;} + /*! Gets the smallest edge size read */ + inline real minEdgeSize() {return _minEdgeSize;} #endif - /*! Modifiers */ - inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {_pRenderMonitor = iRenderMonitor;} - -protected: - void insertShapeNode(Object *ob, Mesh *mesh, int id); - int testDegenerateTriangle(float v1[3], float v2[3], float v3[3]); - int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]); - void clipLine(float v1[3], float v2[3], float c[3], float z); - void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], - float triNormals[][3], float n1[3], float n2[3], float n3[3], - bool edgeMarks[5], bool em1, bool em2, bool em3, int clip[3]); - void addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3], - float n1[3], float n2[3], float n3[3], bool fm, bool em1, bool em2, bool em3); - -protected: - struct detri_t { - unsigned viA, viB, viP; // 0 <= viA, viB, viP < viSize - Vec3r v; - unsigned n; - }; - Render *_re; - Depsgraph *_depsgraph; - NodeGroup *_Scene; - unsigned _numFacesRead; + /*! Modifiers */ + inline void setRenderMonitor(RenderMonitor *iRenderMonitor) + { + _pRenderMonitor = iRenderMonitor; + } + + protected: + void insertShapeNode(Object *ob, Mesh *mesh, int id); + int testDegenerateTriangle(float v1[3], float v2[3], float v3[3]); + int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]); + void clipLine(float v1[3], float v2[3], float c[3], float z); + void clipTriangle(int numTris, + float triCoords[][3], + float v1[3], + float v2[3], + float v3[3], + float triNormals[][3], + float n1[3], + float n2[3], + float n3[3], + bool edgeMarks[5], + bool em1, + bool em2, + bool em3, + int clip[3]); + void addTriangle(struct LoaderState *ls, + float v1[3], + float v2[3], + float v3[3], + float n1[3], + float n2[3], + float n3[3], + bool fm, + bool em1, + bool em2, + bool em3); + + protected: + struct detri_t { + unsigned viA, viB, viP; // 0 <= viA, viB, viP < viSize + Vec3r v; + unsigned n; + }; + Render *_re; + Depsgraph *_depsgraph; + NodeGroup *_Scene; + unsigned _numFacesRead; #if 0 - real _minEdgeSize; + real _minEdgeSize; #endif - bool _smooth; /* if true, face smoothness is taken into account */ - float _viewplane_left; - float _viewplane_right; - float _viewplane_bottom; - float _viewplane_top; - float _z_near, _z_far; - float _z_offset; + bool _smooth; /* if true, face smoothness is taken into account */ + float _viewplane_left; + float _viewplane_right; + float _viewplane_bottom; + float _viewplane_top; + float _z_near, _z_far; + float _z_offset; - RenderMonitor *_pRenderMonitor; + RenderMonitor *_pRenderMonitor; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderFileLoader") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderFileLoader") #endif }; } /* namespace Freestyle */ -#endif // __BLENDER_FILE_LOADER_H__ +#endif // __BLENDER_FILE_LOADER_H__ diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index e7fc162ee1c..47e2fef33e3 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -74,821 +74,822 @@ const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_ti BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer() { - freestyle_bmain = re->freestyle_bmain; - - // for stroke mesh generation - _width = re->winx; - _height = re->winy; - - old_scene = re->scene; - - char name[MAX_ID_NAME - 2]; - BLI_snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name + 2); - freestyle_scene = BKE_scene_add(freestyle_bmain, name); - freestyle_scene->r.cfra = old_scene->r.cfra; - freestyle_scene->r.mode = old_scene->r.mode & - ~(R_EDGE_FRS | 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.color_mgt_flag = 0; // old_scene->r.color_mgt_flag; - freestyle_scene->r.scemode = (old_scene->r.scemode & ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE | R_MULTIVIEW)) & - (re->r.scemode | ~R_FULL_SAMPLE); - 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.dither_intensity = old_scene->r.dither_intensity; - STRNCPY(freestyle_scene->r.engine, old_scene->r.engine); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Stroke rendering engine : " << freestyle_scene->r.engine << endl; - } - freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA; - freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG; - - // Copy ID properties, including Cycles render properties - if (old_scene->id.properties) { - freestyle_scene->id.properties = IDP_CopyProperty_ex(old_scene->id.properties, 0); - } - - /* Render with transparent background. */ - freestyle_scene->r.alphamode = R_ALPHAPREMUL; - - if (STREQ(freestyle_scene->r.engine, RE_engine_id_CYCLES)) { - PointerRNA freestyle_scene_ptr; - RNA_id_pointer_create(&freestyle_scene->id, &freestyle_scene_ptr); - PointerRNA freestyle_cycles_ptr = RNA_pointer_get(&freestyle_scene_ptr, "cycles"); - RNA_boolean_set(&freestyle_cycles_ptr, "film_transparent", 1); - } - - if (G.debug & G_DEBUG_FREESTYLE) { - printf("%s: %d thread(s)\n", __func__, BKE_render_num_threads(&freestyle_scene->r)); - } - - BKE_scene_set_background(freestyle_bmain, freestyle_scene); - - // Scene layer. - ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first; - view_layer->layflag = SCE_LAY_SOLID | SCE_LAY_ZTRA; - - // Camera - Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, view_layer, OB_CAMERA, NULL); - - Camera *camera = (Camera *)object_camera->data; - camera->type = CAM_ORTHO; - camera->ortho_scale = max(re->rectx, re->recty); - camera->clip_start = 0.1f; - camera->clip_end = 100.0f; - - _z_delta = 0.00001f; - _z = camera->clip_start + _z_delta; - - 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; - - // Reset serial mesh ID (used for BlenderStrokeRenderer::NewMesh()) - _mesh_id = 0xffffffff; - - // Create a bNodeTree-to-Material hash table - _nodetree_hash = BLI_ghash_ptr_new("BlenderStrokeRenderer::_nodetree_hash"); - - // Depsgraph - freestyle_depsgraph = DEG_graph_new(freestyle_scene, view_layer, DAG_EVAL_RENDER); - DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &freestyle_scene->id, 0); - DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &object_camera->id, 0); - DEG_graph_tag_relations_update(freestyle_depsgraph); + freestyle_bmain = re->freestyle_bmain; + + // for stroke mesh generation + _width = re->winx; + _height = re->winy; + + old_scene = re->scene; + + char name[MAX_ID_NAME - 2]; + BLI_snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name + 2); + freestyle_scene = BKE_scene_add(freestyle_bmain, name); + freestyle_scene->r.cfra = old_scene->r.cfra; + freestyle_scene->r.mode = old_scene->r.mode & ~(R_EDGE_FRS | 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.color_mgt_flag = 0; // old_scene->r.color_mgt_flag; + freestyle_scene->r.scemode = (old_scene->r.scemode & + ~(R_SINGLE_LAYER | R_NO_FRAME_UPDATE | R_MULTIVIEW)) & + (re->r.scemode | ~R_FULL_SAMPLE); + 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.dither_intensity = old_scene->r.dither_intensity; + STRNCPY(freestyle_scene->r.engine, old_scene->r.engine); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Stroke rendering engine : " << freestyle_scene->r.engine << endl; + } + freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA; + freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG; + + // Copy ID properties, including Cycles render properties + if (old_scene->id.properties) { + freestyle_scene->id.properties = IDP_CopyProperty_ex(old_scene->id.properties, 0); + } + + /* Render with transparent background. */ + freestyle_scene->r.alphamode = R_ALPHAPREMUL; + + if (STREQ(freestyle_scene->r.engine, RE_engine_id_CYCLES)) { + PointerRNA freestyle_scene_ptr; + RNA_id_pointer_create(&freestyle_scene->id, &freestyle_scene_ptr); + PointerRNA freestyle_cycles_ptr = RNA_pointer_get(&freestyle_scene_ptr, "cycles"); + RNA_boolean_set(&freestyle_cycles_ptr, "film_transparent", 1); + } + + if (G.debug & G_DEBUG_FREESTYLE) { + printf("%s: %d thread(s)\n", __func__, BKE_render_num_threads(&freestyle_scene->r)); + } + + BKE_scene_set_background(freestyle_bmain, freestyle_scene); + + // Scene layer. + ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first; + view_layer->layflag = SCE_LAY_SOLID | SCE_LAY_ZTRA; + + // Camera + Object *object_camera = BKE_object_add( + freestyle_bmain, freestyle_scene, view_layer, OB_CAMERA, NULL); + + Camera *camera = (Camera *)object_camera->data; + camera->type = CAM_ORTHO; + camera->ortho_scale = max(re->rectx, re->recty); + camera->clip_start = 0.1f; + camera->clip_end = 100.0f; + + _z_delta = 0.00001f; + _z = camera->clip_start + _z_delta; + + 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; + + // Reset serial mesh ID (used for BlenderStrokeRenderer::NewMesh()) + _mesh_id = 0xffffffff; + + // Create a bNodeTree-to-Material hash table + _nodetree_hash = BLI_ghash_ptr_new("BlenderStrokeRenderer::_nodetree_hash"); + + // Depsgraph + freestyle_depsgraph = DEG_graph_new(freestyle_scene, view_layer, DAG_EVAL_RENDER); + DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &freestyle_scene->id, 0); + DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &object_camera->id, 0); + DEG_graph_tag_relations_update(freestyle_depsgraph); } BlenderStrokeRenderer::~BlenderStrokeRenderer() { - // 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 *base_next = NULL; - ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first; - for (Base *b = (Base *)view_layer->object_bases.first; b; b = base_next) { - base_next = b->next; - Object *ob = b->object; - char *name = ob->id.name; + // 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 *base_next = NULL; + ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first; + for (Base *b = (Base *)view_layer->object_bases.first; b; b = base_next) { + base_next = b->next; + Object *ob = b->object; + char *name = ob->id.name; #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl; + } #endif - switch (ob->type) { - case OB_CAMERA: - freestyle_scene->camera = NULL; - ATTR_FALLTHROUGH; - case OB_MESH: - BKE_scene_collections_object_remove(freestyle_bmain, - freestyle_scene, - ob, - true); - break; - default: - cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name + 2) << endl; - } - } - - // release materials - Link *lnk = (Link *)freestyle_bmain->materials.first; - - while (lnk) - { - Material *ma = (Material*)lnk; - lnk = lnk->next; - BKE_id_free(freestyle_bmain, ma); - } - - BLI_ghash_free(_nodetree_hash, NULL, NULL); - - DEG_graph_free(freestyle_depsgraph); - - FreeStrokeGroups(); + switch (ob->type) { + case OB_CAMERA: + freestyle_scene->camera = NULL; + ATTR_FALLTHROUGH; + case OB_MESH: + BKE_scene_collections_object_remove(freestyle_bmain, freestyle_scene, ob, true); + break; + default: + cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" + << (name + 2) << endl; + } + } + + // release materials + Link *lnk = (Link *)freestyle_bmain->materials.first; + + while (lnk) { + Material *ma = (Material *)lnk; + lnk = lnk->next; + BKE_id_free(freestyle_bmain, ma); + } + + BLI_ghash_free(_nodetree_hash, NULL, NULL); + + DEG_graph_free(freestyle_depsgraph); + + FreeStrokeGroups(); } 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; + 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; + unsigned mesh_id = _mesh_id; + BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this); + self->_mesh_id--; + return mesh_id; } -Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain, bNodeTree *iNodeTree, bool do_id_user) +Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain, + bNodeTree *iNodeTree, + bool do_id_user) { - Material *ma = BKE_material_add(bmain, "stroke_shader"); - bNodeTree *ntree; - bNode *output_linestyle = NULL; - bNodeSocket *fromsock, *tosock; - PointerRNA fromptr, toptr; - NodeShaderAttribute *storage; - - id_us_min(&ma->id); - - if (iNodeTree) { - // make a copy of linestyle->nodetree - ntree = ntreeCopyTree_ex(iNodeTree, bmain, do_id_user); - - // find the active Output Line Style node - for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) { - if (node->type == SH_NODE_OUTPUT_LINESTYLE && (node->flag & NODE_DO_OUTPUT)) { - output_linestyle = node; - break; - } - } - } - else { - ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree"); - } - ma->nodetree = ntree; - ma->use_nodes = 1; - - bNode *input_attr_color = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE); - input_attr_color->locx = 0.0f; - input_attr_color->locy = -200.0f; - storage = (NodeShaderAttribute *)input_attr_color->storage; - BLI_strncpy(storage->name, "Color", sizeof(storage->name)); - - bNode *mix_rgb_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB); - mix_rgb_color->custom1 = MA_RAMP_BLEND; // Mix - mix_rgb_color->locx = 200.0f; - mix_rgb_color->locy = -200.0f; - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); - RNA_float_set(&toptr, "default_value", 0.0f); - - bNode *input_attr_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE); - input_attr_alpha->locx = 400.0f; - input_attr_alpha->locy = 300.0f; - storage = (NodeShaderAttribute *)input_attr_alpha->storage; - BLI_strncpy(storage->name, "Alpha", sizeof(storage->name)); - - bNode *mix_rgb_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB); - mix_rgb_alpha->custom1 = MA_RAMP_BLEND; // Mix - mix_rgb_alpha->locx = 600.0f; - mix_rgb_alpha->locy = 300.0f; - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); - RNA_float_set(&toptr, "default_value", 0.0f); - - bNode *shader_emission = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION); - shader_emission->locx = 400.0f; - shader_emission->locy = -200.0f; - - bNode *input_light_path = nodeAddStaticNode(NULL, ntree, SH_NODE_LIGHT_PATH); - input_light_path->locx = 400.0f; - input_light_path->locy = 100.0f; - - bNode *mix_shader_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER); - mix_shader_color->locx = 600.0f; - mix_shader_color->locy = -100.0f; - - bNode *shader_transparent = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT); - shader_transparent->locx = 600.0f; - shader_transparent->locy = 100.0f; - - bNode *mix_shader_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER); - mix_shader_alpha->locx = 800.0f; - mix_shader_alpha->locy = 100.0f; - - bNode *output_material = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); - output_material->locx = 1000.0f; - output_material->locy = 100.0f; - - fromsock = (bNodeSocket *)BLI_findlink(&input_attr_color->outputs, 0); // Color - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 1); // Color1 - nodeAddLink(ntree, input_attr_color, fromsock, mix_rgb_color, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->outputs, 0); // Color - tosock = (bNodeSocket *)BLI_findlink(&shader_emission->inputs, 0); // Color - nodeAddLink(ntree, mix_rgb_color, fromsock, shader_emission, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&shader_emission->outputs, 0); // Emission - tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 2); // Shader (second) - nodeAddLink(ntree, shader_emission, fromsock, mix_shader_color, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&input_light_path->outputs, 0); // In Camera Ray - tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 0); // Fac - nodeAddLink(ntree, input_light_path, fromsock, mix_shader_color, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->outputs, 0); // Color - tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 0); // Fac - nodeAddLink(ntree, mix_rgb_alpha, fromsock, mix_shader_alpha, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&input_attr_alpha->outputs, 0); // Color - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 1); // Color1 - nodeAddLink(ntree, input_attr_alpha, fromsock, mix_rgb_alpha, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&shader_transparent->outputs, 0); // BSDF - tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 1); // Shader (first) - nodeAddLink(ntree, shader_transparent, fromsock, mix_shader_alpha, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_color->outputs, 0); // Shader - tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 2); // Shader (second) - nodeAddLink(ntree, mix_shader_color, fromsock, mix_shader_alpha, tosock); - - fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->outputs, 0); // Shader - tosock = (bNodeSocket *)BLI_findlink(&output_material->inputs, 0); // Surface - nodeAddLink(ntree, mix_shader_alpha, fromsock, output_material, tosock); - - if (output_linestyle) { - bNodeSocket *outsock; - bNodeLink *link; - - mix_rgb_color->custom1 = output_linestyle->custom1; // blend_type - mix_rgb_color->custom2 = output_linestyle->custom2; // use_clamp - - outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 0); // Color - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 2); // Color2 - link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); - if (link) { - nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock); - } - else { - float color[4]; - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); - RNA_float_get_array(&fromptr, "default_value", color); - RNA_float_set_array(&toptr, "default_value", color); - } - - outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 1); // Color Fac - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac - link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); - if (link) { - nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock); - } - else { - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); - RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value")); - } - - outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 2); // Alpha - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 2); // Color2 - link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); - if (link) { - nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock); - } - else { - float color[4]; - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); - color[0] = color[1] = color[2] = RNA_float_get(&fromptr, "default_value"); - color[3] = 1.0f; - RNA_float_set_array(&toptr, "default_value", color); - } - - outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 3); // Alpha Fac - tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac - link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); - if (link) { - nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock); - } - else { - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); - RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value")); - } - - for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) { - if (node->type == SH_NODE_UVALONGSTROKE) { - // UV output of the UV Along Stroke node - bNodeSocket *sock = (bNodeSocket *)BLI_findlink(&node->outputs, 0); - - // add new UV Map node - bNode *input_uvmap = nodeAddStaticNode(NULL, ntree, SH_NODE_UVMAP); - input_uvmap->locx = node->locx - 200.0f; - input_uvmap->locy = node->locy; - NodeShaderUVMap *storage = (NodeShaderUVMap *)input_uvmap->storage; - if (node->custom1 & 1) { // use_tips - BLI_strncpy(storage->uv_map, uvNames[1], sizeof(storage->uv_map)); - } - else { - BLI_strncpy(storage->uv_map, uvNames[0], sizeof(storage->uv_map)); - } - fromsock = (bNodeSocket *)BLI_findlink(&input_uvmap->outputs, 0); // UV - - // replace links from the UV Along Stroke node by links from the UV Map node - for (bNodeLink *link = (bNodeLink *)ntree->links.first; link; link = link->next) { - if (link->fromnode == node && link->fromsock == sock) { - nodeAddLink(ntree, input_uvmap, fromsock, link->tonode, link->tosock); - } - } - nodeRemSocketLinks(ntree, sock); - } - } - } - - nodeSetActive(ntree, output_material); - ntreeUpdateTree(bmain, ntree); - - return ma; + Material *ma = BKE_material_add(bmain, "stroke_shader"); + bNodeTree *ntree; + bNode *output_linestyle = NULL; + bNodeSocket *fromsock, *tosock; + PointerRNA fromptr, toptr; + NodeShaderAttribute *storage; + + id_us_min(&ma->id); + + if (iNodeTree) { + // make a copy of linestyle->nodetree + ntree = ntreeCopyTree_ex(iNodeTree, bmain, do_id_user); + + // find the active Output Line Style node + for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_OUTPUT_LINESTYLE && (node->flag & NODE_DO_OUTPUT)) { + output_linestyle = node; + break; + } + } + } + else { + ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree"); + } + ma->nodetree = ntree; + ma->use_nodes = 1; + + bNode *input_attr_color = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE); + input_attr_color->locx = 0.0f; + input_attr_color->locy = -200.0f; + storage = (NodeShaderAttribute *)input_attr_color->storage; + BLI_strncpy(storage->name, "Color", sizeof(storage->name)); + + bNode *mix_rgb_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB); + mix_rgb_color->custom1 = MA_RAMP_BLEND; // Mix + mix_rgb_color->locx = 200.0f; + mix_rgb_color->locy = -200.0f; + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); + RNA_float_set(&toptr, "default_value", 0.0f); + + bNode *input_attr_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE); + input_attr_alpha->locx = 400.0f; + input_attr_alpha->locy = 300.0f; + storage = (NodeShaderAttribute *)input_attr_alpha->storage; + BLI_strncpy(storage->name, "Alpha", sizeof(storage->name)); + + bNode *mix_rgb_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_RGB); + mix_rgb_alpha->custom1 = MA_RAMP_BLEND; // Mix + mix_rgb_alpha->locx = 600.0f; + mix_rgb_alpha->locy = 300.0f; + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); + RNA_float_set(&toptr, "default_value", 0.0f); + + bNode *shader_emission = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION); + shader_emission->locx = 400.0f; + shader_emission->locy = -200.0f; + + bNode *input_light_path = nodeAddStaticNode(NULL, ntree, SH_NODE_LIGHT_PATH); + input_light_path->locx = 400.0f; + input_light_path->locy = 100.0f; + + bNode *mix_shader_color = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER); + mix_shader_color->locx = 600.0f; + mix_shader_color->locy = -100.0f; + + bNode *shader_transparent = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_TRANSPARENT); + shader_transparent->locx = 600.0f; + shader_transparent->locy = 100.0f; + + bNode *mix_shader_alpha = nodeAddStaticNode(NULL, ntree, SH_NODE_MIX_SHADER); + mix_shader_alpha->locx = 800.0f; + mix_shader_alpha->locy = 100.0f; + + bNode *output_material = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); + output_material->locx = 1000.0f; + output_material->locy = 100.0f; + + fromsock = (bNodeSocket *)BLI_findlink(&input_attr_color->outputs, 0); // Color + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 1); // Color1 + nodeAddLink(ntree, input_attr_color, fromsock, mix_rgb_color, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->outputs, 0); // Color + tosock = (bNodeSocket *)BLI_findlink(&shader_emission->inputs, 0); // Color + nodeAddLink(ntree, mix_rgb_color, fromsock, shader_emission, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&shader_emission->outputs, 0); // Emission + tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 2); // Shader (second) + nodeAddLink(ntree, shader_emission, fromsock, mix_shader_color, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&input_light_path->outputs, 0); // In Camera Ray + tosock = (bNodeSocket *)BLI_findlink(&mix_shader_color->inputs, 0); // Fac + nodeAddLink(ntree, input_light_path, fromsock, mix_shader_color, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->outputs, 0); // Color + tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 0); // Fac + nodeAddLink(ntree, mix_rgb_alpha, fromsock, mix_shader_alpha, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&input_attr_alpha->outputs, 0); // Color + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 1); // Color1 + nodeAddLink(ntree, input_attr_alpha, fromsock, mix_rgb_alpha, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&shader_transparent->outputs, 0); // BSDF + tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 1); // Shader (first) + nodeAddLink(ntree, shader_transparent, fromsock, mix_shader_alpha, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_color->outputs, 0); // Shader + tosock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->inputs, 2); // Shader (second) + nodeAddLink(ntree, mix_shader_color, fromsock, mix_shader_alpha, tosock); + + fromsock = (bNodeSocket *)BLI_findlink(&mix_shader_alpha->outputs, 0); // Shader + tosock = (bNodeSocket *)BLI_findlink(&output_material->inputs, 0); // Surface + nodeAddLink(ntree, mix_shader_alpha, fromsock, output_material, tosock); + + if (output_linestyle) { + bNodeSocket *outsock; + bNodeLink *link; + + mix_rgb_color->custom1 = output_linestyle->custom1; // blend_type + mix_rgb_color->custom2 = output_linestyle->custom2; // use_clamp + + outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 0); // Color + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 2); // Color2 + link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); + if (link) { + nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock); + } + else { + float color[4]; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); + RNA_float_get_array(&fromptr, "default_value", color); + RNA_float_set_array(&toptr, "default_value", color); + } + + outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 1); // Color Fac + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_color->inputs, 0); // Fac + link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); + if (link) { + nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_color, tosock); + } + else { + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); + RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value")); + } + + outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 2); // Alpha + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 2); // Color2 + link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); + if (link) { + nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock); + } + else { + float color[4]; + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); + color[0] = color[1] = color[2] = RNA_float_get(&fromptr, "default_value"); + color[3] = 1.0f; + RNA_float_set_array(&toptr, "default_value", color); + } + + outsock = (bNodeSocket *)BLI_findlink(&output_linestyle->inputs, 3); // Alpha Fac + tosock = (bNodeSocket *)BLI_findlink(&mix_rgb_alpha->inputs, 0); // Fac + link = (bNodeLink *)BLI_findptr(&ntree->links, outsock, offsetof(bNodeLink, tosock)); + if (link) { + nodeAddLink(ntree, link->fromnode, link->fromsock, mix_rgb_alpha, tosock); + } + else { + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, outsock, &fromptr); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, tosock, &toptr); + RNA_float_set(&toptr, "default_value", RNA_float_get(&fromptr, "default_value")); + } + + for (bNode *node = (bNode *)ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_UVALONGSTROKE) { + // UV output of the UV Along Stroke node + bNodeSocket *sock = (bNodeSocket *)BLI_findlink(&node->outputs, 0); + + // add new UV Map node + bNode *input_uvmap = nodeAddStaticNode(NULL, ntree, SH_NODE_UVMAP); + input_uvmap->locx = node->locx - 200.0f; + input_uvmap->locy = node->locy; + NodeShaderUVMap *storage = (NodeShaderUVMap *)input_uvmap->storage; + if (node->custom1 & 1) { // use_tips + BLI_strncpy(storage->uv_map, uvNames[1], sizeof(storage->uv_map)); + } + else { + BLI_strncpy(storage->uv_map, uvNames[0], sizeof(storage->uv_map)); + } + fromsock = (bNodeSocket *)BLI_findlink(&input_uvmap->outputs, 0); // UV + + // replace links from the UV Along Stroke node by links from the UV Map node + for (bNodeLink *link = (bNodeLink *)ntree->links.first; link; link = link->next) { + if (link->fromnode == node && link->fromsock == sock) { + nodeAddLink(ntree, input_uvmap, fromsock, link->tonode, link->tosock); + } + } + nodeRemSocketLinks(ntree, sock); + } + } + } + + nodeSetActive(ntree, output_material); + ntreeUpdateTree(bmain, ntree); + + return ma; } void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const { - RenderStrokeRepBasic(iStrokeRep); + RenderStrokeRepBasic(iStrokeRep); } void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const { - bNodeTree *nt = iStrokeRep->getNodeTree(); - Material *ma = (Material *)BLI_ghash_lookup(_nodetree_hash, nt); - if (!ma) { - ma = BlenderStrokeRenderer::GetStrokeShader(freestyle_bmain, nt, false); - BLI_ghash_insert(_nodetree_hash, nt, ma); - } - iStrokeRep->setMaterial(ma); - - 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++; + bNodeTree *nt = iStrokeRep->getNodeTree(); + Material *ma = (Material *)BLI_ghash_lookup(_nodetree_hash, nt); + if (!ma) { + ma = BlenderStrokeRenderer::GetStrokeShader(freestyle_bmain, nt, false); + BLI_ghash_insert(_nodetree_hash, nt, ma); + } + iStrokeRep->setMaterial(ma); + + 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) bool BlenderStrokeRenderer::test_triangle_visibility(StrokeVertexRep *svRep[3]) const { - int xl, xu, yl, yu; - Vec2r p; - - xl = xu = yl = yu = 0; - for (int i = 0; i < 3; i++) { - p = svRep[i]->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++; - } - return !(xl == 3 || xu == 3 || yl == 3 || yu == 3); + int xl, xu, yl, yu; + Vec2r p; + + xl = xu = yl = yu = 0; + for (int i = 0; i < 3; i++) { + p = svRep[i]->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++; + } + return !(xl == 3 || xu == 3 || yl == 3 || yu == 3); } // Check the visibility of faces and strip segments. -void BlenderStrokeRenderer::test_strip_visibility(Strip::vertex_container& strip_vertices, - int *visible_faces, int *visible_segments) const +void BlenderStrokeRenderer::test_strip_visibility(Strip::vertex_container &strip_vertices, + int *visible_faces, + int *visible_segments) const { - const int strip_vertex_count = strip_vertices.size(); - Strip::vertex_container::iterator v[3]; - StrokeVertexRep *svRep[3]; - 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 (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_faces)++; - if (!visible) - (*visible_segments)++; - visible = true; - } - else { - visible = false; - } - } + const int strip_vertex_count = strip_vertices.size(); + Strip::vertex_container::iterator v[3]; + StrokeVertexRep *svRep[3]; + 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 (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_faces)++; + if (!visible) + (*visible_segments)++; + visible = true; + } + else { + visible = false; + } + } } // Release allocated memory for stroke groups void BlenderStrokeRenderer::FreeStrokeGroups() { - vector<StrokeGroup*>::const_iterator it, itend; - - for (it = strokeGroups.begin(), itend = strokeGroups.end(); - it != itend; ++it) - { - delete (*it); - } - for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end(); - it != itend; ++it) - { - delete (*it); - } + vector<StrokeGroup *>::const_iterator it, itend; + + for (it = strokeGroups.begin(), itend = strokeGroups.end(); it != itend; ++it) { + delete (*it); + } + for (it = texturedStrokeGroups.begin(), itend = texturedStrokeGroups.end(); it != itend; ++it) { + delete (*it); + } } // Build a scene populated by mesh objects representing stylized strokes int BlenderStrokeRenderer::GenerateScene() { - vector<StrokeGroup*>::const_iterator it, itend; - - 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 get_stroke_count(); + vector<StrokeGroup *>::const_iterator it, itend; + + 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 get_stroke_count(); } // Return the number of strokes int BlenderStrokeRenderer::get_stroke_count() const { - return strokeGroups.size() + texturedStrokeGroups.size(); + 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, (ViewLayer *)freestyle_scene->view_layers.first, OB_MESH); - DEG_relations_tag_update(freestyle_bmain); + Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, (ViewLayer *)freestyle_scene->view_layers.first, OB_MESH); + DEG_relations_tag_update(freestyle_bmain); #else - Object *object_mesh = NewMesh(); + Object *object_mesh = NewMesh(); #endif - Mesh *mesh = (Mesh *)object_mesh->data; - - mesh->totvert = group->totvert; - mesh->totedge = group->totedge; - mesh->totpoly = group->totpoly; - mesh->totloop = group->totloop; - mesh->totcol = group->totcol; - - 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); - - MVert *vertices = mesh->mvert; - MEdge *edges = mesh->medge; - MPoly *polys = mesh->mpoly; - MLoop *loops = mesh->mloop; - MLoopUV *loopsuv[2] = { NULL }; - - if (hasTex) { - // First UV layer - CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[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->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[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; - - mesh->mat = (Material **)MEM_mallocN(sizeof(Material *) * mesh->totcol, "MaterialList"); - - //////////////////// - // Data copy - //////////////////// - - 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; - - for (vector<StrokeRep*>::const_iterator it = group->strokes.begin(), itend = group->strokes.end(); - it != itend; ++it) - { - mesh->mat[material_index] = (*it)->getMaterial(); - id_us_plus(&mesh->mat[material_index]->id); - - 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; - - v[0] = strip_vertices.begin(); - v[1] = v[0] + 1; - v[2] = v[0] + 2; - - 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; - - // 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; - - // 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->mat_nr = material_index; - ++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; - - 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; - } - } - - // colors and alpha transparency. vertex colors are in sRGB - // space by convention, so convert from linear - float rgba[3][4]; - - for (int i = 0; i < 3; i++) { - copy_v3fl_v3db(rgba[i], &svRep[i]->color()[0]); - rgba[i][3] = svRep[i]->alpha(); - } - - if (is_odd) { - linearrgb_to_srgb_uchar4(&colors[0].r, rgba[2]); - linearrgb_to_srgb_uchar4(&colors[1].r, rgba[0]); - linearrgb_to_srgb_uchar4(&colors[2].r, rgba[1]); - } - else { - linearrgb_to_srgb_uchar4(&colors[0].r, rgba[2]); - linearrgb_to_srgb_uchar4(&colors[1].r, rgba[1]); - linearrgb_to_srgb_uchar4(&colors[2].r, rgba[0]); - } - 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 - material_index++; - } // loop over strokes - - test_object_materials(freestyle_bmain, object_mesh, (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, true); + Mesh *mesh = (Mesh *)object_mesh->data; + + mesh->totvert = group->totvert; + mesh->totedge = group->totedge; + mesh->totpoly = group->totpoly; + mesh->totloop = group->totloop; + mesh->totcol = group->totcol; + + 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); + + MVert *vertices = mesh->mvert; + MEdge *edges = mesh->medge; + MPoly *polys = mesh->mpoly; + MLoop *loops = mesh->mloop; + MLoopUV *loopsuv[2] = {NULL}; + + if (hasTex) { + // First UV layer + CustomData_add_layer_named( + &mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[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->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[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; + + mesh->mat = (Material **)MEM_mallocN(sizeof(Material *) * mesh->totcol, "MaterialList"); + + //////////////////// + // Data copy + //////////////////// + + 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; + + for (vector<StrokeRep *>::const_iterator it = group->strokes.begin(), + itend = group->strokes.end(); + it != itend; + ++it) { + mesh->mat[material_index] = (*it)->getMaterial(); + id_us_plus(&mesh->mat[material_index]->id); + + 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; + + v[0] = strip_vertices.begin(); + v[1] = v[0] + 1; + v[2] = v[0] + 2; + + 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; + + // 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; + + // 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->mat_nr = material_index; + ++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; + + 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; + } + } + + // colors and alpha transparency. vertex colors are in sRGB + // space by convention, so convert from linear + float rgba[3][4]; + + for (int i = 0; i < 3; i++) { + copy_v3fl_v3db(rgba[i], &svRep[i]->color()[0]); + rgba[i][3] = svRep[i]->alpha(); + } + + if (is_odd) { + linearrgb_to_srgb_uchar4(&colors[0].r, rgba[2]); + linearrgb_to_srgb_uchar4(&colors[1].r, rgba[0]); + linearrgb_to_srgb_uchar4(&colors[2].r, rgba[1]); + } + else { + linearrgb_to_srgb_uchar4(&colors[0].r, rgba[2]); + linearrgb_to_srgb_uchar4(&colors[1].r, rgba[1]); + linearrgb_to_srgb_uchar4(&colors[2].r, rgba[0]); + } + 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 + material_index++; + } // loop over strokes + + test_object_materials(freestyle_bmain, object_mesh, (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, true); #endif } // A replacement of BKE_object_add() for better performance. Object *BlenderStrokeRenderer::NewMesh() const { - Object *ob; - char name[MAX_ID_NAME]; - unsigned int mesh_id = get_stroke_mesh_id(); + Object *ob; + 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(freestyle_bmain, OB_MESH, name); - BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id); - ob->data = BKE_mesh_add(freestyle_bmain, name); + BLI_snprintf(name, MAX_ID_NAME, "0%08xOB", mesh_id); + ob = BKE_object_add_only_object(freestyle_bmain, OB_MESH, name); + BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id); + ob->data = BKE_mesh_add(freestyle_bmain, name); - Collection *collection_master = BKE_collection_master(freestyle_scene); - BKE_collection_object_add(freestyle_bmain, collection_master, ob); - DEG_graph_tag_relations_update(freestyle_depsgraph); + Collection *collection_master = BKE_collection_master(freestyle_scene); + BKE_collection_object_add(freestyle_bmain, collection_master, ob); + DEG_graph_tag_relations_update(freestyle_depsgraph); - DEG_graph_id_tag_update(freestyle_bmain, - freestyle_depsgraph, - &ob->id, - ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + DEG_graph_id_tag_update(freestyle_bmain, + freestyle_depsgraph, + &ob->id, + ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); - return ob; + return ob; } Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render) { - Camera *camera = (Camera *)freestyle_scene->camera->data; - if (camera->clip_end < _z) - camera->clip_end = _z + _z_delta * 100.0f; + Camera *camera = (Camera *)freestyle_scene->camera->data; + if (camera->clip_end < _z) + camera->clip_end = _z + _z_delta * 100.0f; #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "clip_start " << camera->clip_start << ", clip_end " << camera->clip_end << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "clip_start " << camera->clip_start << ", clip_end " << camera->clip_end << endl; + } #endif - Render *freestyle_render = RE_NewSceneRender(freestyle_scene); - ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first; - DEG_graph_relations_update(freestyle_depsgraph, freestyle_bmain, freestyle_scene, view_layer); + Render *freestyle_render = RE_NewSceneRender(freestyle_scene); + ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first; + DEG_graph_relations_update(freestyle_depsgraph, freestyle_bmain, freestyle_scene, view_layer); - RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene, - render && get_stroke_count() > 0); + RE_RenderFreestyleStrokes( + freestyle_render, freestyle_bmain, freestyle_scene, render && get_stroke_count() > 0); - return freestyle_render; + return freestyle_render; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h index 686e7272cc8..c333319ada1 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h @@ -38,66 +38,67 @@ struct bNodeTree; namespace Freestyle { -class BlenderStrokeRenderer : public StrokeRenderer -{ -public: - BlenderStrokeRenderer(Render *re, int render_count); - virtual ~BlenderStrokeRenderer(); - - /*! Renders a stroke rep */ - virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; - virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; - - 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); - -protected: - Main *freestyle_bmain; - Scene *old_scene; - Scene *freestyle_scene; - Depsgraph *freestyle_depsgraph; - bContext *_context; - float _width, _height; - float _z, _z_delta; - unsigned int _mesh_id; - bool _use_shading_nodes; - struct GHash *_nodetree_hash; - - static const char *uvNames[]; - - int get_stroke_count() const; - 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; +class BlenderStrokeRenderer : public StrokeRenderer { + public: + BlenderStrokeRenderer(Render *re, int render_count); + virtual ~BlenderStrokeRenderer(); + + /*! Renders a stroke rep */ + virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const; + virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const; + + 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); + + protected: + Main *freestyle_bmain; + Scene *old_scene; + Scene *freestyle_scene; + Depsgraph *freestyle_depsgraph; + bContext *_context; + float _width, _height; + float _z, _z_delta; + unsigned int _mesh_id; + bool _use_shading_nodes; + struct GHash *_nodetree_hash; + + static const char *uvNames[]; + + int get_stroke_count() const; + 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") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStrokeRenderer") #endif }; } /* namespace Freestyle */ -#endif // __BLENDER_STROKE_RENDERER_H__ +#endif // __BLENDER_STROKE_RENDERER_H__ diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h index 166f9243f63..a4beb1c119c 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h @@ -25,69 +25,69 @@ #include "../system/PythonInterpreter.h" extern "C" { -#include "BLI_utildefines.h" // BLI_assert() +#include "BLI_utildefines.h" // BLI_assert() struct Text; } namespace Freestyle { -class BufferedStyleModule : public StyleModule -{ -public: - BufferedStyleModule(const string& buffer, const string& file_name, Interpreter *inter) : StyleModule(file_name, inter) - { - _buffer = buffer; - } - - virtual ~BufferedStyleModule() - { - } - -protected: - virtual int interpret() - { - PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter); - BLI_assert(py_inter != 0); - return py_inter->interpretString(_buffer, getFileName()); - } - -private: - string _buffer; +class BufferedStyleModule : public StyleModule { + public: + BufferedStyleModule(const string &buffer, const string &file_name, Interpreter *inter) + : StyleModule(file_name, inter) + { + _buffer = buffer; + } + + virtual ~BufferedStyleModule() + { + } + + protected: + virtual int interpret() + { + PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter *>(_inter); + BLI_assert(py_inter != 0); + return py_inter->interpretString(_buffer, getFileName()); + } + + private: + string _buffer; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BufferedStyleModule") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BufferedStyleModule") #endif }; -class BlenderStyleModule : public StyleModule -{ -public: - BlenderStyleModule(struct Text *text, const string &name, Interpreter *inter) : StyleModule(name, inter) - { - _text = text; - } - - virtual ~BlenderStyleModule() - { - } - -protected: - virtual int interpret() - { - PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter); - BLI_assert(py_inter != 0); - return py_inter->interpretText(_text, getFileName()); - } - -private: - struct Text *_text; +class BlenderStyleModule : public StyleModule { + public: + BlenderStyleModule(struct Text *text, const string &name, Interpreter *inter) + : StyleModule(name, inter) + { + _text = text; + } + + virtual ~BlenderStyleModule() + { + } + + protected: + virtual int interpret() + { + PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter *>(_inter); + BLI_assert(py_inter != 0); + return py_inter->interpretText(_text, getFileName()); + } + + private: + struct Text *_text; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStyleModule") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStyleModule") #endif }; } /* namespace Freestyle */ -#endif // __BLENDERSTYLEMODULE_H__ +#endif // __BLENDERSTYLEMODULE_H__ diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 785f291d8c3..63ff4cc5457 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -66,7 +66,7 @@ extern "C" { #include "FRS_freestyle.h" #define DEFAULT_SPHERE_RADIUS 1.0f -#define DEFAULT_DKR_EPSILON 0.0f +#define DEFAULT_DKR_EPSILON 0.0f struct FreestyleGlobals g_freestyle; @@ -80,17 +80,17 @@ static AppView *view = NULL; static FreestyleLineSet lineset_buffer; static bool lineset_copied = false; - static void load_post_callback(struct Main * /*main*/, struct ID * /*id*/, void * /*arg*/) { - lineset_copied = false; + lineset_copied = false; } static bCallbackFuncStore load_post_callback_funcstore = { - NULL, NULL, /* next, prev */ - load_post_callback, /* func */ - NULL, /* arg */ - 0 /* alloc */ + NULL, + NULL, /* next, prev */ + load_post_callback, /* func */ + NULL, /* arg */ + 0 /* alloc */ }; //======================================================= @@ -99,35 +99,35 @@ static bCallbackFuncStore load_post_callback_funcstore = { void FRS_initialize() { - if (freestyle_is_initialized) - return; + if (freestyle_is_initialized) + return; - pathconfig = new Config::Path; - controller = new Controller(); - view = new AppView; - controller->setView(view); - controller->Clear(); - g_freestyle.scene = NULL; - lineset_copied = false; + pathconfig = new Config::Path; + controller = new Controller(); + view = new AppView; + controller->setView(view); + controller->Clear(); + g_freestyle.scene = NULL; + lineset_copied = false; - BLI_callback_add(&load_post_callback_funcstore, BLI_CB_EVT_LOAD_POST); + BLI_callback_add(&load_post_callback_funcstore, BLI_CB_EVT_LOAD_POST); - freestyle_is_initialized = 1; + 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); + 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_exit() { - delete pathconfig; - delete controller; - delete view; + delete pathconfig; + delete controller; + delete view; } //======================================================= @@ -136,536 +136,545 @@ void FRS_exit() 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; - } - - g_freestyle.viewport[0] = g_freestyle.viewport[1] = 0; - g_freestyle.viewport[2] = width; - g_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; - } + 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; + } + + g_freestyle.viewport[0] = g_freestyle.viewport[1] = 0; + g_freestyle.viewport[2] = width; + g_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 model-view matrix is simply the identity matrix. + // 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 model-view matrix is simply the identity matrix. - zero_v3(g_freestyle.viewpoint); + zero_v3(g_freestyle.viewpoint); - unit_m4(g_freestyle.mv); + unit_m4(g_freestyle.mv); - copy_m4_m4(g_freestyle.proj, re->winmat); + copy_m4_m4(g_freestyle.proj, re->winmat); #if 0 - print_m4("mv", g_freestyle.mv); - print_m4("proj", g_freestyle.proj); + print_m4("mv", g_freestyle.mv); + print_m4("proj", g_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; + 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 char * create_lineset_handler(char *layer_name, char *lineset_name) +static char *create_lineset_handler(char *layer_name, char *lineset_name) { - const char *fmt = "__import__('parameter_editor').process('%s', '%s')\n"; - char *s1 = escape_quotes(layer_name); - char *s2 = escape_quotes(lineset_name); - char *text = BLI_sprintfN(fmt, s1, s2); - MEM_freeN(s1); - MEM_freeN(s2); - return text; + const char *fmt = "__import__('parameter_editor').process('%s', '%s')\n"; + char *s1 = escape_quotes(layer_name); + char *s2 = escape_quotes(lineset_name); + char *text = BLI_sprintfN(fmt, s1, s2); + MEM_freeN(s1); + MEM_freeN(s2); + return text; } -struct edge_type_condition -{ - int edge_type, value; +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 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; + 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, ViewLayer *view_layer, Depsgraph *depsgraph) { - // load mesh - re->i.infostr = IFACE_("Freestyle: Mesh loading"); - re->stats_draw(re->sdh, &re->i); - re->i.infostr = NULL; - if (controller->LoadMesh(re, view_layer, depsgraph)) // returns if scene cannot be loaded or if empty - return; - if (re->test_break(re->tbh)) - return; - - // add style modules - FreestyleConfig *config = &view_layer->freestyle_config; - - 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->script && module_conf->is_displayed) { - const char *id_name = module_conf->script->id.name + 2; - if (G.debug & G_DEBUG_FREESTYLE) { - cout << " " << layer_count + 1 << ": " << id_name; - if (module_conf->script->name) - cout << " (" << module_conf->script->name << ")"; - cout << endl; - } - controller->InsertStyleModule(layer_count, id_name, module_conf->script); - 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 ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl; - } - char *buffer = create_lineset_handler(view_layer->name, lineset->name); - controller->InsertStyleModule(layer_count, lineset->name, buffer); - controller->toggleLayer(layer_count, true); - MEM_freeN(buffer); - 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 << "Ridges 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, view_layer->name); - bool diffuse = false, z = false; - for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) { - if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE_COLOR)) { - controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty); - diffuse = true; - } - if (STREQ(rpass->name, RE_PASSNAME_Z)) { - controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty); - z = true; - } - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Passes :" << endl; - cout << " Diffuse = " << (diffuse ? "enabled" : "disabled") << endl; - cout << " Z = " << (z ? "enabled" : "disabled") << endl; - } - - if (controller->hitViewMapCache()) - return; - - // compute view map - re->i.infostr = IFACE_("Freestyle: View map creation"); - re->stats_draw(re->sdh, &re->i); - re->i.infostr = NULL; - controller->ComputeViewMap(); + // load mesh + re->i.infostr = IFACE_("Freestyle: Mesh loading"); + re->stats_draw(re->sdh, &re->i); + re->i.infostr = NULL; + if (controller->LoadMesh( + re, view_layer, depsgraph)) // returns if scene cannot be loaded or if empty + return; + if (re->test_break(re->tbh)) + return; + + // add style modules + FreestyleConfig *config = &view_layer->freestyle_config; + + 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->script && module_conf->is_displayed) { + const char *id_name = module_conf->script->id.name + 2; + if (G.debug & G_DEBUG_FREESTYLE) { + cout << " " << layer_count + 1 << ": " << id_name; + if (module_conf->script->name) + cout << " (" << module_conf->script->name << ")"; + cout << endl; + } + controller->InsertStyleModule(layer_count, id_name, module_conf->script); + 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 ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl; + } + char *buffer = create_lineset_handler(view_layer->name, lineset->name); + controller->InsertStyleModule(layer_count, lineset->name, buffer); + controller->toggleLayer(layer_count, true); + MEM_freeN(buffer); + 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 << "Ridges 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, view_layer->name); + bool diffuse = false, z = false; + for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) { + if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE_COLOR)) { + controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty); + diffuse = true; + } + if (STREQ(rpass->name, RE_PASSNAME_Z)) { + controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty); + z = true; + } + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Passes :" << endl; + cout << " Diffuse = " << (diffuse ? "enabled" : "disabled") << endl; + cout << " Z = " << (z ? "enabled" : "disabled") << endl; + } + + if (controller->hitViewMapCache()) + return; + + // compute view map + re->i.infostr = IFACE_("Freestyle: View map creation"); + re->stats_draw(re->sdh, &re->i); + re->i.infostr = NULL; + controller->ComputeViewMap(); } void FRS_composite_result(Render *re, ViewLayer *view_layer, 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) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "No source render layer to composite" << endl; - } - return; - } - - src = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, freestyle_render->viewname); - if (!src) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "No source result image to composite" << endl; - } - return; - } + 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) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "No source render layer to composite" << endl; + } + return; + } + + src = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, freestyle_render->viewname); + if (!src) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "No source result image to composite" << endl; + } + return; + } #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "src: " << rl->rectx << " x " << rl->recty << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "src: " << rl->rectx << " x " << rl->recty << endl; + } #endif - rl = RE_GetRenderLayer(re->result, view_layer->name); - if (!rl) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "No destination render layer to composite to" << endl; - } - return; - } - dest = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname); - if (!dest) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "No destination result image to composite to" << endl; - } - return; - } + rl = RE_GetRenderLayer(re->result, view_layer->name); + if (!rl) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "No destination render layer to composite to" << endl; + } + return; + } + dest = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname); + if (!dest) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "No destination result image to composite to" << endl; + } + return; + } #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "dest: " << rl->rectx << " x " << rl->recty << endl; - } + 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); - blend_color_mix_float(pixDest, pixDest, pixSrc); - } - } - } + 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); + blend_color_mix_float(pixDest, pixDest, pixSrc); + } + } + } } static int displayed_layer_count(ViewLayer *view_layer) { - int count = 0; - - switch (view_layer->freestyle_config.mode) { - case FREESTYLE_CONTROL_SCRIPT_MODE: - for (FreestyleModuleConfig *module = (FreestyleModuleConfig *)view_layer->freestyle_config.modules.first; - module; - module = module->next) - { - if (module->script && module->is_displayed) - count++; - } - break; - case FREESTYLE_CONTROL_EDITOR_MODE: - for (FreestyleLineSet *lineset = (FreestyleLineSet *)view_layer->freestyle_config.linesets.first; - lineset; - lineset = lineset->next) - { - if (lineset->flags & FREESTYLE_LINESET_ENABLED) - count++; - } - break; - } - return count; + int count = 0; + + switch (view_layer->freestyle_config.mode) { + case FREESTYLE_CONTROL_SCRIPT_MODE: + for (FreestyleModuleConfig *module = + (FreestyleModuleConfig *)view_layer->freestyle_config.modules.first; + module; + module = module->next) { + if (module->script && module->is_displayed) + count++; + } + break; + case FREESTYLE_CONTROL_EDITOR_MODE: + for (FreestyleLineSet *lineset = + (FreestyleLineSet *)view_layer->freestyle_config.linesets.first; + lineset; + lineset = lineset->next) { + if (lineset->flags & FREESTYLE_LINESET_ENABLED) + count++; + } + break; + } + return count; } int FRS_is_freestyle_enabled(ViewLayer *view_layer) { - return ((view_layer->flag & VIEW_LAYER_RENDER) && - (view_layer->flag & VIEW_LAYER_FREESTYLE) && - displayed_layer_count(view_layer) > 0); + return ((view_layer->flag & VIEW_LAYER_RENDER) && (view_layer->flag & VIEW_LAYER_FREESTYLE) && + displayed_layer_count(view_layer) > 0); } void FRS_init_stroke_renderer(Render *re) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << endl; - cout << "#===============================================================" << endl; - cout << "# Freestyle" << endl; - cout << "#===============================================================" << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << endl; + cout << "#===============================================================" << endl; + cout << "# Freestyle" << endl; + cout << "#===============================================================" << endl; + } - init_view(re); + init_view(re); - controller->ResetRenderCount(); + controller->ResetRenderCount(); } void FRS_begin_stroke_rendering(Render *re) { - init_camera(re); + init_camera(re); } Render *FRS_do_stroke_rendering(Render *re, ViewLayer *view_layer, int render) { - Render *freestyle_render = NULL; - - if (!render) - return controller->RenderStrokes(re, false); - - RenderMonitor monitor(re); - controller->setRenderMonitor(&monitor); - controller->setViewMapCache((view_layer->freestyle_config.flags & FREESTYLE_VIEW_MAP_CACHE) ? true : false); - - if (G.debug & G_DEBUG_FREESTYLE) { - cout << endl; - cout << "----------------------------------------------------------" << endl; - cout << "| " << (re->scene->id.name + 2) << "|" << view_layer->name << endl; - cout << "----------------------------------------------------------" << endl; - } - - /* Create depsgraph and evaluate scene. */ - ViewLayer *scene_view_layer = (ViewLayer*)BLI_findstring(&re->scene->view_layers, view_layer->name, offsetof(ViewLayer, name)); - Depsgraph *depsgraph = DEG_graph_new(re->scene, scene_view_layer, DAG_EVAL_RENDER); - BKE_scene_graph_update_for_newframe(depsgraph, re->main); - - // prepare Freestyle: - // - load mesh - // - add style modules - // - set parameters - // - compute view map - prepare(re, view_layer, depsgraph); - - if (re->test_break(re->tbh)) { - controller->CloseFile(); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Break" << endl; - } - } - else { - // render and composite Freestyle result - if (controller->_ViewMap) { - // render strokes - re->i.infostr = IFACE_("Freestyle: Stroke rendering"); - re->stats_draw(re->sdh, &re->i); - re->i.infostr = NULL; - g_freestyle.scene = DEG_get_evaluated_scene(depsgraph); - int strokeCount = controller->DrawStrokes(); - if (strokeCount > 0) { - freestyle_render = controller->RenderStrokes(re, true); - } - controller->CloseFile(); - g_freestyle.scene = NULL; - - // composite result - if (freestyle_render) { - FRS_composite_result(re, view_layer, freestyle_render); - RE_FreeRenderResult(freestyle_render->result); - freestyle_render->result = NULL; - } - } - } - - DEG_graph_free(depsgraph); - - return freestyle_render; + Render *freestyle_render = NULL; + + if (!render) + return controller->RenderStrokes(re, false); + + RenderMonitor monitor(re); + controller->setRenderMonitor(&monitor); + controller->setViewMapCache( + (view_layer->freestyle_config.flags & FREESTYLE_VIEW_MAP_CACHE) ? true : false); + + if (G.debug & G_DEBUG_FREESTYLE) { + cout << endl; + cout << "----------------------------------------------------------" << endl; + cout << "| " << (re->scene->id.name + 2) << "|" << view_layer->name << endl; + cout << "----------------------------------------------------------" << endl; + } + + /* Create depsgraph and evaluate scene. */ + ViewLayer *scene_view_layer = (ViewLayer *)BLI_findstring( + &re->scene->view_layers, view_layer->name, offsetof(ViewLayer, name)); + Depsgraph *depsgraph = DEG_graph_new(re->scene, scene_view_layer, DAG_EVAL_RENDER); + BKE_scene_graph_update_for_newframe(depsgraph, re->main); + + // prepare Freestyle: + // - load mesh + // - add style modules + // - set parameters + // - compute view map + prepare(re, view_layer, depsgraph); + + if (re->test_break(re->tbh)) { + controller->CloseFile(); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Break" << endl; + } + } + else { + // render and composite Freestyle result + if (controller->_ViewMap) { + // render strokes + re->i.infostr = IFACE_("Freestyle: Stroke rendering"); + re->stats_draw(re->sdh, &re->i); + re->i.infostr = NULL; + g_freestyle.scene = DEG_get_evaluated_scene(depsgraph); + int strokeCount = controller->DrawStrokes(); + if (strokeCount > 0) { + freestyle_render = controller->RenderStrokes(re, true); + } + controller->CloseFile(); + g_freestyle.scene = NULL; + + // composite result + if (freestyle_render) { + FRS_composite_result(re, view_layer, freestyle_render); + RE_FreeRenderResult(freestyle_render->result); + freestyle_render->result = NULL; + } + } + } + + DEG_graph_free(depsgraph); + + return freestyle_render; } void FRS_end_stroke_rendering(Render * /*re*/) { - // clear canvas - controller->Clear(); + // clear canvas + controller->Clear(); } void FRS_free_view_map_cache(void) { - // free cache - controller->DeleteViewMap(true); + // free cache + controller->DeleteViewMap(true); #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - printf("View map cache freed\n"); - } + if (G.debug & G_DEBUG_FREESTYLE) { + printf("View map cache freed\n"); + } #endif } @@ -675,64 +684,64 @@ void FRS_free_view_map_cache(void) void FRS_copy_active_lineset(FreestyleConfig *config) { - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(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; - } + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(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 = BKE_freestyle_lineset_get_active(config); - - if (lineset) { - if (lineset->linestyle) - id_us_min(&lineset->linestyle->id); - lineset->linestyle = lineset_buffer.linestyle; - if (lineset->linestyle) - id_us_plus(&lineset->linestyle->id); - 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) { - id_us_min(&lineset->group->id); - lineset->group = NULL; - } - if (lineset_buffer.group) { - lineset->group = lineset_buffer.group; - id_us_plus(&lineset->group->id); - } - strcpy(lineset->name, lineset_buffer.name); - BKE_freestyle_lineset_unique_name(config, lineset); - lineset->flags |= FREESTYLE_LINESET_CURRENT; - } + if (!lineset_copied) + return; + + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); + + if (lineset) { + if (lineset->linestyle) + id_us_min(&lineset->linestyle->id); + lineset->linestyle = lineset_buffer.linestyle; + if (lineset->linestyle) + id_us_plus(&lineset->linestyle->id); + 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) { + id_us_min(&lineset->group->id); + lineset->group = NULL; + } + if (lineset_buffer.group) { + lineset->group = lineset_buffer.group; + id_us_plus(&lineset->group->id); + } + strcpy(lineset->name, lineset_buffer.name); + BKE_freestyle_lineset_unique_name(config, lineset); + lineset->flags |= FREESTYLE_LINESET_CURRENT; + } } void FRS_delete_active_lineset(FreestyleConfig *config) { - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); - if (lineset) { - BKE_freestyle_lineset_delete(config, lineset); - } + if (lineset) { + BKE_freestyle_lineset_delete(config, lineset); + } } /** @@ -741,18 +750,18 @@ void FRS_delete_active_lineset(FreestyleConfig *config) */ bool FRS_move_active_lineset(FreestyleConfig *config, int direction) { - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); - return (lineset != NULL) && BLI_listbase_link_move(&config->linesets, lineset, direction); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); + return (lineset != NULL) && BLI_listbase_link_move(&config->linesets, lineset, direction); } // Testing Material *FRS_create_stroke_material(Main *bmain, struct FreestyleLineStyle *linestyle) { - bNodeTree *nt = (linestyle->use_nodes) ? linestyle->nodetree : NULL; - Material *ma = BlenderStrokeRenderer::GetStrokeShader(bmain, nt, true); - ma->id.us = 0; - return ma; + bNodeTree *nt = (linestyle->use_nodes) ? linestyle->nodetree : NULL; + Material *ma = BlenderStrokeRenderer::GetStrokeShader(bmain, nt, true); + ma->id.us = 0; + return ma; } -} // extern "C" +} // extern "C" |