/*************************************************************************** * Copyright (c) 2008 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ #include #ifdef FC_OS_WIN32 #include #endif #ifdef FC_OS_MACOSX #include #else #include #endif #include #include #include #include #include #include #include #endif #include "SoPolygon.h" using namespace MeshGui; SO_NODE_SOURCE(SoPolygon) void SoPolygon::initClass() { SO_NODE_INIT_CLASS(SoPolygon, SoShape, "Shape"); } SoPolygon::SoPolygon() { SO_NODE_CONSTRUCTOR(SoPolygon); SO_NODE_ADD_FIELD(startIndex, (0)); SO_NODE_ADD_FIELD(numVertices, (0)); SO_NODE_ADD_FIELD(highlight, (false)); SO_NODE_ADD_FIELD(render, (true)); } /** * Renders the polygon. */ void SoPolygon::GLRender(SoGLRenderAction* action) { if (shouldGLRender(action) && render.getValue()) { SoState* state = action->getState(); const SoCoordinateElement* coords = SoCoordinateElement::getInstance(state); if (!coords) { return; } const SbVec3f* points = coords->getArrayPtr3(); if (!points) { return; } SoMaterialBundle mb(action); SoTextureCoordinateBundle tb(action, true, false); SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); mb.sendFirst(); // make sure we have the correct material int32_t len = coords->getNum(); drawPolygon(points, len); } } /** * Renders the polygon. */ void SoPolygon::drawPolygon(const SbVec3f* points, int32_t len) const { glLineWidth(3.0F); int32_t beg = startIndex.getValue(); int32_t cnt = numVertices.getValue(); int32_t end = beg + cnt; if (end > len) { return; // wrong setup, too few points } // draw control mesh glBegin(GL_LINES); for (int32_t i = beg; i < end; ++i) { int32_t j = (i - beg + 1) % cnt + beg; glVertex3fv(points[i].getValue()); glVertex3fv(points[j].getValue()); } glEnd(); } /** * Calculates picked point based on primitives generated by subclasses. */ void SoPolygon::rayPick(SoRayPickAction* action) { // if (this->shouldRayPick(action)) { // this->computeObjectSpaceRay(action); // const SoBoundingBoxCache* bboxcache = getBoundingBoxCache(); // if (!bboxcache || !bboxcache->isValid(action->getState()) || // SoFCMeshObjectShape_ray_intersect(action, bboxcache->getProjectedBox())) { // this->generatePrimitives(action); // } //} inherited::rayPick(action); } void SoPolygon::generatePrimitives(SoAction* /*action*/) {} /** * Sets the bounding box of the mesh to \a box and its center to \a center. */ void SoPolygon::computeBBox(SoAction* action, SbBox3f& box, SbVec3f& center) { SoState* state = action->getState(); const SoCoordinateElement* coords = SoCoordinateElement::getInstance(state); if (!coords) { return; } const SbVec3f* points = coords->getArrayPtr3(); if (!points) { return; } constexpr float floatMax = std::numeric_limits::max(); float maxX = -floatMax, minX = floatMax, maxY = -floatMax, minY = floatMax, maxZ = -floatMax, minZ = floatMax; int32_t len = coords->getNum(); int32_t beg = startIndex.getValue(); int32_t cnt = numVertices.getValue(); int32_t end = beg + cnt; if (end <= len) { for (int32_t i = beg; i < end; i++) { maxX = std::max(maxX, points[i][0]); minX = std::min(minX, points[i][0]); maxY = std::max(maxY, points[i][1]); minY = std::min(minY, points[i][1]); maxZ = std::max(maxZ, points[i][2]); minZ = std::min(minZ, points[i][2]); } box.setBounds(minX, minY, minZ, maxX, maxY, maxZ); center.setValue(0.5F * (minX + maxX), 0.5F * (minY + maxY), 0.5F * (minZ + maxZ)); } else { box.setBounds(SbVec3f(0, 0, 0), SbVec3f(0, 0, 0)); center.setValue(0.0F, 0.0F, 0.0F); } }