/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2019, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2019 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef __FMMDL_DRAW_BODY_H__ #define __FMMDL_DRAW_BODY_H__ #include #include #include #include #include "Modeler/FMMdlSurface.h" #include #include namespace FacetModeler { /** \details Draws the specified body to OdGiCommonDraw with the view direction specified. \param pDraw [in/out] Object to draw on. \param rBody [in] Body to draw. \param pViewDir [in] View direction vector for calculating silhouettes as OdGeVector3d. */ inline void DrawBody( OdGiCommonDraw *pDraw, const Body &rBody, const OdGeVector3d *pViewDir = NULL); /** \details Draws the specified surface on the body to OdGiCommonDraw with the view direction specified. \param pDraw [in/out] Object to draw on. \param rBody [in] Body to draw. \param pSurface [in] Surface to draw. \param pViewDir [in] View direction vector for calculating silhouettes as OdGeVector3d. \remarks If the value of the pointer is equal to zero, then all the faces whose surface is not specified will be drawn. */ inline void DrawBodySurface( OdGiCommonDraw* pDraw, const Body& rBody, const Surface* pSurface, const OdGeVector3d* pViewDir); inline void DrawBody( OdGiCommonDraw *pDraw, const Body &rBody, const OdGeVector3d *pViewDir) { if (!rBody.isNull()) { OdArray > vertexTagsSaved(rBody.vertexCount()); VertexIterator vi(&rBody); while (!vi.done()) { vertexTagsSaved.append(vi.get()->tag()); vi.get()->setTag(0); vi.next(); } DrawBodySurface(pDraw, rBody, 0, pViewDir); Surface *pSurf = rBody.surfaceList(); OdUInt32 i; for (i = 0; i < rBody.surfaceCount(); ++i) { ODA_ASSERT(pSurf != 0); DrawBodySurface(pDraw, rBody, pSurf, pViewDir); pSurf = pSurf->next(); } i = 0; vi = VertexIterator(&rBody); while (!vi.done()) { vi.get()->setTag(vertexTagsSaved[i++]); vi.next(); } } } inline void DrawBodySurface(OdGiCommonDraw *pDraw, const Body &rBody, const Surface *pSurface, const OdGeVector3d *pViewDir) { OdUInt32 iVCount = rBody.vertexCount(); OdUInt32 iECount = rBody.countEdges(); OdUInt32 iFCount = rBody.faceCount(); OdGeVector3dArray normals; OdGePoint3dArray aVertices; aVertices.reserve(iVCount); OdGiEdgeData cEdgeData; OdGiFaceData cFaceData; OdGiVertexData cVertexData; OdUInt8Array vEdgeVisibilities; OdUInt8Array vFaceVisibilities; normals.reserve(aVertices.size()); vEdgeVisibilities.reserve(iECount); vFaceVisibilities.reserve(iFCount); OdInt32Array vFD; vFD.reserve(iECount + iFCount * 2); OdGeVector3dArray vNormals; vNormals.reserve(iFCount); bool bFaceVis = false; bool bEdgeVis = false; FaceIterator itF(&rBody); while (!itF.done()) { if (itF.get()->surface() != pSurface) { itF.next(); continue; } vNormals.push_back(itF.get()->normal()); OdGiVisibility eFVis = kOdGiVisible; if (itF.get()->isFlagOn(VFF)) eFVis = kOdGiInvisible; if (itF.get()->orientation() == efoDiscard) eFVis = kOdGiInvisible; vFaceVisibilities.push_back((OdUInt8) eFVis); if (eFVis != kOdGiVisible) { bFaceVis = true; } OdUInt32 i, iSize = itF.get()->loopCount(); for (i = 0; i < iSize; i++) { vFD.push_back(0); // reserve space for size OdInt32 nFaceStart = vFD.size(); Edge *pE = itF.get()->edge(i); Edge *pS = pE; do { Vertex *pVertex = pE->vertex(); OdInt32 vertexId = (OdInt32) pVertex->tag(); // use 1-based indecies to have zero as "unused" flag if (vertexId > 0) { --vertexId; } else { vertexId = aVertices.size(); aVertices.push_back(pVertex->point()); pVertex->setTag(vertexId + 1); if (pSurface) { pVertex->normal(*itF.get(), *normals.append()); // draw vertex normals for debugging //OdGePoint3d pts[] = { pVertex->point(), pVertex->point() + normals.last() * 1.5 }; //pDraw->geometry().polyline( 2, pts ); } } vFD.push_back(vertexId); OdGiVisibility eVis = kOdGiVisible; if (pE->isFlagOn(VEF)) { eVis = kOdGiInvisible; } else if (pE->isFlagOn(AEF)) { if (pViewDir) { Edge *pPair = pE->pair(); if (pPair) { OdGeVector3d vNrm1 = pE->face()->normal(); OdGeVector3d vNrm2 = pPair->face()->normal(); if (((pViewDir->dotProduct(vNrm1) > 0) == (pViewDir->dotProduct(vNrm2) > 0))) { eVis = kOdGiInvisible; } else { eVis = kOdGiVisible; } } } else { eVis = kOdGiSilhouette; } } vEdgeVisibilities.push_back((OdUInt8) eVis); if (eVis != kOdGiVisible) { bEdgeVis = true; } pE = pE->next(); } while (pE != pS); // set face size or hole -size vFD[nFaceStart - 1] = (i == 0 ? vFD.size() - nFaceStart : nFaceStart - vFD.size()); } itF.next(); } if (vFD.size()) { if (bEdgeVis) cEdgeData.setVisibility(vEdgeVisibilities.getPtr()); if (bFaceVis) cFaceData.setVisibility(vFaceVisibilities.getPtr()); cVertexData.setNormals(normals.getPtr()); cFaceData.setNormals(vNormals.getPtr()); pDraw->rawGeometry().shell( aVertices.size(), aVertices.getPtr(), vFD.size(), vFD.getPtr(), bEdgeVis ? &cEdgeData : 0, &cFaceData, normals.size() ? &cVertexData : 0 ); } } } #endif //#ifndef __FMMDL_DRAW_BODY_H__