/*************************************************************************** * 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_ # ifdef FC_OS_WIN32 # include # endif # ifdef FC_OS_MACOSX # include # else # include # endif # include # include # include # include # include # include # include # include # include #endif #include "SoFCShapeObject.h" using namespace PartGui; SO_NODE_SOURCE(SoFCShape); SoFCShape::SoFCShape() : coords(new SoCoordinate3) , norm(new SoNormal) , faceset(new SoBrepFaceSet) , lineset(new SoBrepEdgeSet) , nodeset(new SoBrepPointSet) { SO_NODE_CONSTRUCTOR(SoFCShape); } void SoFCShape::initClass() { SO_NODE_INIT_CLASS(SoFCShape, SoSeparator, "Separator"); } SO_NODE_SOURCE(SoFCControlPoints) void SoFCControlPoints::initClass() { SO_NODE_INIT_CLASS(SoFCControlPoints, SoShape, "Shape"); } SoFCControlPoints::SoFCControlPoints() { SO_NODE_CONSTRUCTOR(SoFCControlPoints); SbVec3f c(1.0f, 0.447059f, 0.337255f); SO_NODE_ADD_FIELD(numPolesU, (0)); SO_NODE_ADD_FIELD(numPolesV, (0)); SO_NODE_ADD_FIELD(numKnotsU, (0)); SO_NODE_ADD_FIELD(numKnotsV, (0)); SO_NODE_ADD_FIELD(lineColor, (c)); } /** * Renders the control points. */ void SoFCControlPoints::GLRender(SoGLRenderAction *action) { if (shouldGLRender(action)) { 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(); drawControlPoints(points, len); } } /** * Renders the control points and knots. */ void SoFCControlPoints::drawControlPoints(const SbVec3f * points,int32_t len) const { glLineWidth(1.0f); glColor3fv(lineColor.getValue().getValue()); uint32_t nCtU=numPolesU.getValue(); uint32_t nCtV=numPolesV.getValue(); uint32_t poles = nCtU * nCtV; if (poles > (uint32_t)len) return; // wrong setup, too few points // draw control mesh glBegin(GL_LINES); for (uint32_t u = 0; u < nCtU-1; ++u) { for (uint32_t v = 0; v < nCtV -1; ++v) { glVertex3fv(points[u*nCtV+v].getValue()); glVertex3fv(points[u*nCtV+v+1].getValue()); glVertex3fv(points[u*nCtV+v].getValue()); glVertex3fv(points[(u+1)*nCtV+v].getValue()); } glVertex3fv(points[(u+1)*nCtV-1].getValue()); glVertex3fv(points[(u+2)*nCtV-1].getValue()); } for (uint32_t v = 0; v < nCtV -1; ++v) { glVertex3fv(points[(nCtU-1)*nCtV+v].getValue()); glVertex3fv(points[(nCtU-1)*nCtV+v+1].getValue()); } glEnd(); // draw poles glPointSize(5.0f); glBegin(GL_POINTS); for (uint32_t p=0; p (uint32_t)len) return; // wrong setup, too few points glColor3f(1.0f, 1.0f, 0.0f); glPointSize(6.0f); glBegin(GL_POINTS); for (uint32_t p=poles; pgetState(); 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(); if (len > 0) { for (int32_t i=0; i(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); } }