| |
| |
|
|
| #include "tgl.h" |
| |
| |
| #include "ext/ttexturesstorage.h" |
| #include "ext/plasticdeformerstorage.h" |
| |
| |
| #include "tcg/tcg_iterator_ops.h" |
| |
| #include "ext/meshutils.h" |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| struct NoColorFunction { |
| void faceColor(int f, int m) {} |
| void edgeColor(int e, int m) {} |
| void vertexColor(int v, int m) {} |
| }; |
| |
| |
| |
| template <typename VerticesContainer, typename PointType, typename ColorFunction> |
| inline void tglDrawEdges(const TTextureMesh &mesh, const VerticesContainer &vertices, |
| ColorFunction colorFunction) |
| { |
| |
| glBegin(GL_LINES); |
| |
| TTextureMesh::edges_container::const_iterator et, eEnd = mesh.edges().end(); |
| |
| for (et = mesh.edges().begin(); et != eEnd; ++et) { |
| const TTextureMesh::edge_type &ed = *et; |
| |
| int v0 = ed.vertex(0), v1 = ed.vertex(1); |
| |
| const PointType &p0 = vertices[v0]; |
| const PointType &p1 = vertices[v1]; |
| |
| colorFunction.edgeColor(et.index(), -1); |
| |
| colorFunction.vertexColor(v0, -1); |
| glVertex2d(tcg::point_traits<PointType>::x(p0), tcg::point_traits<PointType>::y(p0)); |
| |
| colorFunction.vertexColor(v1, -1); |
| glVertex2d(tcg::point_traits<PointType>::x(p1), tcg::point_traits<PointType>::y(p1)); |
| } |
| |
| glEnd(); |
| } |
| |
| |
| |
| template <typename ColorFunction> |
| inline void tglDrawFaces(const TMeshImage &meshImage, ColorFunction colorFunction) |
| { |
| glBegin(GL_TRIANGLES); |
| |
| int m, mCount = meshImage.meshes().size(); |
| for (m = 0; m != mCount; ++m) { |
| const TTextureMesh &mesh = *meshImage.meshes()[m]; |
| const tcg::list<TTextureVertex> &vertices = mesh.vertices(); |
| |
| |
| TTextureMesh::faces_container::const_iterator ft, fEnd = mesh.faces().end(); |
| |
| for (ft = mesh.faces().begin(); ft != fEnd; ++ft) { |
| int v0, v1, v2; |
| mesh.faceVertices(ft.index(), v0, v1, v2); |
| |
| const TTextureVertex &p0 = vertices[v0]; |
| const TTextureVertex &p1 = vertices[v1]; |
| const TTextureVertex &p2 = vertices[v2]; |
| |
| colorFunction.faceColor(ft.index(), m); |
| |
| colorFunction.vertexColor(v0, m), glVertex2d(p0.P().x, p0.P().y); |
| colorFunction.vertexColor(v1, m), glVertex2d(p1.P().x, p1.P().y); |
| colorFunction.vertexColor(v2, m), glVertex2d(p2.P().x, p2.P().y); |
| } |
| } |
| |
| glEnd(); |
| } |
| |
| |
| |
| template <typename ColorFunction> |
| inline void tglDrawFaces(const TMeshImage &meshImage, const PlasticDeformerDataGroup *group, |
| ColorFunction colorFunction) |
| { |
| glBegin(GL_TRIANGLES); |
| |
| |
| typedef std::vector<std::pair<int, int>> SortedFacesVector; |
| |
| const SortedFacesVector &sortedFaces = group->m_sortedFaces; |
| const std::vector<TTextureMeshP> &meshes = meshImage.meshes(); |
| |
| int m = -1; |
| const TTextureMesh *mesh; |
| const double *dstCoords; |
| |
| int v0, v1, v2; |
| |
| |
| SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end()); |
| for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) { |
| int f = sft->first, m_ = sft->second; |
| |
| if (m != m_) { |
| m = m_; |
| |
| mesh = meshes[m].getPointer(); |
| dstCoords = group->m_datas[m].m_output.get(); |
| } |
| |
| mesh->faceVertices(f, v0, v1, v2); |
| |
| const double *d0 = dstCoords + (v0 << 1), *d1 = dstCoords + (v1 << 1), *d2 = dstCoords + (v2 << 1); |
| |
| colorFunction.faceColor(f, m); |
| |
| colorFunction.vertexColor(v0, m), glVertex2d(*d0, *(d0 + 1)); |
| colorFunction.vertexColor(v1, m), glVertex2d(*d1, *(d1 + 1)); |
| colorFunction.vertexColor(v2, m), glVertex2d(*d2, *(d2 + 1)); |
| } |
| |
| glEnd(); |
| } |
| |
| } |
| |
| |
| |
| |
| |
| void transform(const TMeshImageP &meshImage, const TAffine &aff) |
| { |
| const std::vector<TTextureMeshP> &meshes = meshImage->meshes(); |
| |
| int m, mCount = meshes.size(); |
| for (m = 0; m != mCount; ++m) { |
| TTextureMesh &mesh = *meshes[m]; |
| |
| tcg::list<TTextureMesh::vertex_type> &vertices = mesh.vertices(); |
| |
| tcg::list<TTextureMesh::vertex_type>::iterator vt, vEnd(vertices.end()); |
| for (vt = vertices.begin(); vt != vEnd; ++vt) |
| vt->P() = aff * vt->P(); |
| } |
| } |
| |
| |
| |
| void tglDrawEdges(const TMeshImage &mi, const PlasticDeformerDataGroup *group) |
| { |
| const std::vector<TTextureMeshP> &meshes = mi.meshes(); |
| |
| int m, mCount = meshes.size(); |
| if (group) { |
| for (m = 0; m != mCount; ++m) |
| tglDrawEdges<const TPointD *, TPointD, NoColorFunction>( |
| *meshes[m], (const TPointD *)group->m_datas[m].m_output.get(), NoColorFunction()); |
| } else { |
| for (m = 0; m != mCount; ++m) { |
| const TTextureMesh &mesh = *meshes[m]; |
| |
| tglDrawEdges<tcg::list<TTextureMesh::vertex_type>, TTextureVertex, NoColorFunction>( |
| mesh, mesh.vertices(), NoColorFunction()); |
| } |
| } |
| } |
| |
| |
| |
| void tglDrawFaces(const TMeshImage &image, const PlasticDeformerDataGroup *group) |
| { |
| if (group) |
| tglDrawFaces(image, group, NoColorFunction()); |
| else |
| tglDrawFaces(image, NoColorFunction()); |
| } |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| struct LinearColorFunction { |
| typedef double (*ValueFunc)(const LinearColorFunction *cf, int m, int primitive); |
| |
| public: |
| const TMeshImage &m_meshImg; |
| const PlasticDeformerDataGroup *m_group; |
| |
| double m_min, m_max; |
| double *m_cMin, *m_cMax; |
| |
| double m_dt; |
| bool m_degenerate; |
| |
| ValueFunc m_func; |
| |
| public: |
| LinearColorFunction(const TMeshImage &meshImg, |
| const PlasticDeformerDataGroup *group, |
| double min, double max, |
| double *cMin, double *cMax, |
| ValueFunc func) |
| : m_meshImg(meshImg), m_group(group), m_min(min), m_max(max), m_cMin(cMin), m_cMax(cMax), m_dt(max - min), m_degenerate(m_dt < 1e-4), m_func(func) |
| { |
| } |
| |
| void operator()(int primitive, int m) |
| { |
| if (m_degenerate) { |
| glColor4d(0.5 * (m_cMin[0] + m_cMax[0]), |
| 0.5 * (m_cMin[1] + m_cMax[1]), |
| 0.5 * (m_cMin[2] + m_cMax[2]), |
| 0.5 * (m_cMin[3] + m_cMax[3])); |
| return; |
| } |
| |
| double val = m_func(this, m, primitive); |
| double t = (val - m_min) / m_dt, one_t = (m_max - val) / m_dt; |
| |
| glColor4d(one_t * m_cMin[0] + t * m_cMax[0], |
| one_t * m_cMin[1] + t * m_cMax[1], |
| one_t * m_cMin[2] + t * m_cMax[2], |
| one_t * m_cMin[3] + t * m_cMax[3]); |
| } |
| }; |
| |
| |
| |
| struct LinearVertexColorFunction : public LinearColorFunction, public NoColorFunction { |
| LinearVertexColorFunction(const TMeshImage &meshImg, |
| const PlasticDeformerDataGroup *group, |
| double min, double max, |
| double *cMin, double *cMax, |
| ValueFunc func) |
| : LinearColorFunction(meshImg, group, min, max, cMin, cMax, func) {} |
| |
| void vertexColor(int v, int m) { operator()(v, m); } |
| }; |
| |
| |
| |
| struct LinearFaceColorFunction : public LinearColorFunction, public NoColorFunction { |
| LinearFaceColorFunction(const TMeshImage &meshImg, |
| const PlasticDeformerDataGroup *group, |
| double min, double max, |
| double *cMin, double *cMax, |
| ValueFunc func) |
| : LinearColorFunction(meshImg, group, min, max, cMin, cMax, func) {} |
| |
| void faceColor(int v, int m) { operator()(v, m); } |
| }; |
| |
| } |
| |
| |
| |
| void tglDrawSO(const TMeshImage &image, double minColor[4], double maxColor[4], |
| const PlasticDeformerDataGroup *group, bool deformedDomain) |
| { |
| struct locals { |
| static double returnSO(const LinearColorFunction *cf, int m, int f) |
| { |
| return cf->m_group->m_datas[m].m_so[f]; |
| } |
| }; |
| |
| double min = 0.0, max = 0.0; |
| if (group) |
| min = group->m_soMin, max = group->m_soMax; |
| |
| LinearFaceColorFunction colorFunction(image, group, min, max, minColor, maxColor, locals::returnSO); |
| |
| if (group && deformedDomain) |
| tglDrawFaces(image, group, colorFunction); |
| else |
| tglDrawFaces(image, colorFunction); |
| } |
| |
| |
| |
| void tglDrawRigidity(const TMeshImage &image, double minColor[4], double maxColor[4], |
| const PlasticDeformerDataGroup *group, bool deformedDomain) |
| { |
| struct locals { |
| static double returnRigidity(const LinearColorFunction *cf, int m, int v) |
| { |
| return cf->m_meshImg.meshes()[m]->vertex(v).P().rigidity; |
| } |
| }; |
| |
| LinearVertexColorFunction colorFunction(image, group, |
| 1.0, 1e4, minColor, maxColor, locals::returnRigidity); |
| |
| if (group && deformedDomain) |
| tglDrawFaces(image, group, colorFunction); |
| else |
| tglDrawFaces(image, colorFunction); |
| } |
| |
| |
| |
| |
| |
| void tglDraw(const TMeshImage &meshImage, |
| const DrawableTextureData &texData, const TAffine &meshToTexAff, |
| const PlasticDeformerDataGroup &group) |
| { |
| typedef MeshTexturizer::TextureData::TileData TileData; |
| |
| |
| glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_HINT_BIT); |
| |
| glEnable(GL_BLEND); |
| |
| glEnable(GL_LINE_SMOOTH); |
| glLineWidth(1.0f); |
| |
| glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
| |
| |
| const std::vector<TTextureMeshP> &meshes = meshImage.meshes(); |
| const TTextureMesh *mesh; |
| |
| typedef std::vector<std::pair<int, int>> SortedFacesVector; |
| const SortedFacesVector &sortedFaces = group.m_sortedFaces; |
| |
| const MeshTexturizer::TextureData *td = texData.m_textureData; |
| int t, tCount = td->m_tileDatas.size(); |
| |
| GLuint texId = -1; |
| int m = -1; |
| const double *dstCoords; |
| |
| int v0, v1, v2; |
| int e1ovi, e2ovi; |
| |
| |
| std::vector<TAffine> tileAff(tCount); |
| for (t = 0; t != tCount; ++t) { |
| const TileData &tileData = td->m_tileDatas[t]; |
| const TRectD &tileRect = tileData.m_tileGeometry; |
| |
| tileAff[t] = TScale(1.0 / (tileRect.x1 - tileRect.x0), 1.0 / (tileRect.y1 - tileRect.y0)) * |
| TTranslation(-tileRect.x0, -tileRect.y0) * |
| meshToTexAff; |
| } |
| |
| |
| |
| |
| SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end()); |
| for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) { |
| int f = sft->first, m_ = sft->second; |
| |
| if (m != m_) { |
| |
| m = m_; |
| |
| mesh = meshes[m].getPointer(); |
| dstCoords = group.m_datas[m].m_output.get(); |
| } |
| |
| |
| const TTextureMesh::face_type &fc = mesh->face(f); |
| |
| const TTextureMesh::edge_type &ed0 = mesh->edge(fc.edge(0)), |
| &ed1 = mesh->edge(fc.edge(1)), |
| &ed2 = mesh->edge(fc.edge(2)); |
| |
| { |
| v0 = ed0.vertex(0); |
| v1 = ed0.vertex(1); |
| v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1)); |
| |
| e1ovi = (ed1.vertex(0) == v1) | (ed1.vertex(1) == v1); |
| e2ovi = 1 - e1ovi; |
| } |
| |
| const TPointD &p0 = mesh->vertex(v0).P(), &p1 = mesh->vertex(v1).P(), &p2 = mesh->vertex(v2).P(); |
| |
| for (t = 0; t != tCount; ++t) { |
| |
| const TileData &tileData = td->m_tileDatas[t]; |
| |
| |
| TPointD s[3] = {tileAff[t] * p0, tileAff[t] * p1, tileAff[t] * p2}; |
| |
| |
| if ( |
| std::min({s[0].x, s[1].x, s[2].x}) > 1.0 || |
| std::min({s[0].y, s[1].y, s[2].y}) > 1.0 || |
| std::max({s[0].x, s[1].x, s[2].x}) < 0.0 || |
| std::max({s[0].y, s[1].y, s[2].y}) < 0.0) |
| continue; |
| |
| |
| |
| if (tileData.m_textureId != texId) { |
| texId = tileData.m_textureId; |
| |
| glBindTexture(GL_TEXTURE_2D, tileData.m_textureId); |
| } |
| |
| const double *d[3] = {dstCoords + (v0 << 1), |
| dstCoords + (v1 << 1), |
| dstCoords + (v2 << 1)}; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| bool drawEd0 = (ed0.facesCount() < 2), |
| drawEd1 = (ed1.facesCount() < 2), |
| drawEd2 = (ed2.facesCount() < 2); |
| |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); |
| |
| glBegin(GL_LINES); |
| { |
| if (drawEd0) { |
| glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); |
| glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); |
| } |
| |
| if (drawEd1) { |
| glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1)); |
| glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); |
| } |
| |
| if (drawEd2) { |
| glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1)); |
| glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); |
| } |
| } |
| glEnd(); |
| |
| glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
| glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); |
| |
| glBegin(GL_LINES); |
| { |
| if (drawEd0) { |
| glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); |
| glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); |
| } |
| |
| if (drawEd1) { |
| glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1)); |
| glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); |
| } |
| |
| if (drawEd2) { |
| glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1)); |
| glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); |
| } |
| } |
| glEnd(); |
| |
| |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); |
| |
| glBegin(GL_TRIANGLES); |
| { |
| glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); |
| glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); |
| glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); |
| } |
| glEnd(); |
| |
| glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
| glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); |
| |
| glBegin(GL_TRIANGLES); |
| { |
| glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); |
| glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); |
| glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); |
| } |
| glEnd(); |
| } |
| } |
| |
| glBindTexture(GL_TEXTURE_2D, 0); |
| |
| glPopAttrib(); |
| } |
| |