/*************************************************************************** * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * * * * 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 # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include "ViewProviderFemMesh.h" #include #include #include #include #include #include #include #include #include #include using namespace FemGui; PROPERTY_SOURCE(FemGui::ViewProviderFemMesh, Gui::ViewProviderGeometryObject) App::PropertyFloatConstraint::Constraints ViewProviderFemMesh::floatRange = {1.0f,64.0f,1.0f}; ViewProviderFemMesh::ViewProviderFemMesh() { App::Material mat; mat.ambientColor.set(0.2f,0.2f,0.2f); mat.diffuseColor.set(0.1f,0.1f,0.1f); mat.specularColor.set(0.0f,0.0f,0.0f); mat.emissiveColor.set(0.0f,0.0f,0.0f); mat.shininess = 0.0f; mat.transparency = 0.0f; ADD_PROPERTY(PointMaterial,(mat)); ADD_PROPERTY(PointColor,(mat.diffuseColor)); ADD_PROPERTY(PointSize,(2.0f)); PointSize.setConstraints(&floatRange); ADD_PROPERTY(LineWidth,(1.0f)); LineWidth.setConstraints(&floatRange); pcDrawStyle = new SoDrawStyle(); pcDrawStyle->ref(); pcDrawStyle->style = SoDrawStyle::LINES; pcDrawStyle->lineWidth = LineWidth.getValue(); pShapeHints = new SoShapeHints; pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; pShapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING; pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; pShapeHints->ref(); pcMatBinding = new SoMaterialBinding; pcMatBinding->value = SoMaterialBinding::OVERALL; pcMatBinding->ref(); pcCoords = new SoCoordinate3(); pcCoords->ref(); pcFaces = new SoIndexedFaceSet; pcFaces->ref(); pcPointStyle = new SoDrawStyle(); pcPointStyle->ref(); pcPointStyle->style = SoDrawStyle::POINTS; pcPointStyle->pointSize = PointSize.getValue(); pcPointMaterial = new SoMaterial; pcPointMaterial->ref(); PointMaterial.touch(); } ViewProviderFemMesh::~ViewProviderFemMesh() { pcCoords->unref(); pcDrawStyle->unref(); pcFaces->unref(); pShapeHints->unref(); pcMatBinding->unref(); pcPointMaterial->unref(); pcPointStyle->unref(); } void ViewProviderFemMesh::attach(App::DocumentObject *pcObj) { ViewProviderGeometryObject::attach(pcObj); // flat SoGroup* pcFlatRoot = new SoGroup(); pcFlatRoot->addChild(pShapeHints); pcFlatRoot->addChild(pcShapeMaterial); pcFlatRoot->addChild(pcMatBinding); pcFlatRoot->addChild(pcHighlight); addDisplayMaskMode(pcFlatRoot, "Flat"); // line SoLightModel* pcLightModel = new SoLightModel(); pcLightModel->model = SoLightModel::BASE_COLOR; SoGroup* pcWireRoot = new SoGroup(); pcWireRoot->addChild(pcDrawStyle); pcWireRoot->addChild(pcLightModel); SoBaseColor* color = new SoBaseColor(); color->rgb.setValue(0.0f,0.0f,0.0f); pcWireRoot->addChild(color); pcWireRoot->addChild(pcHighlight); addDisplayMaskMode(pcWireRoot, "Wireframe"); // flat+line SoPolygonOffset* offset = new SoPolygonOffset(); offset->styles = SoPolygonOffset::LINES; offset->factor = -2.0f; offset->units = 1.0f; SoGroup* pcFlatWireRoot = new SoSeparator(); pcFlatWireRoot->addChild(pcFlatRoot); pcFlatWireRoot->addChild(offset); pcFlatWireRoot->addChild(pcWireRoot); addDisplayMaskMode(pcFlatWireRoot, "Flat Lines"); // Points SoGroup* pcPointsRoot = new SoSeparator(); pcPointsRoot->addChild(pcPointMaterial); pcPointsRoot->addChild(pcPointStyle); pcPointsRoot->addChild(pcCoords); SoPointSet * pointset = new SoPointSet; pcPointsRoot->addChild(pointset); addDisplayMaskMode(pcPointsRoot, "Points"); pcHighlight->addChild(pcCoords); pcHighlight->addChild(pcFaces); } void ViewProviderFemMesh::setDisplayMode(const char* ModeName) { if (strcmp("Flat Lines",ModeName)==0) setDisplayMaskMode("Flat Lines"); else if (strcmp("Shaded",ModeName)==0) setDisplayMaskMode("Flat"); else if (strcmp("Wireframe",ModeName)==0) setDisplayMaskMode("Wireframe"); else if (strcmp("Points",ModeName)==0) setDisplayMaskMode("Points"); ViewProviderGeometryObject::setDisplayMode( ModeName ); } std::vector ViewProviderFemMesh::getDisplayModes(void) const { std::vector StrList; StrList.push_back("Flat Lines"); StrList.push_back("Shaded"); StrList.push_back("Wireframe"); StrList.push_back("Points"); return StrList; } void ViewProviderFemMesh::updateData(const App::Property* prop) { if (prop->isDerivedFrom(Fem::PropertyFemMesh::getClassTypeId())) { ViewProviderFEMMeshBuilder builder; builder.createMesh(prop, pcCoords, pcFaces); } Gui::ViewProviderGeometryObject::updateData(prop); } void ViewProviderFemMesh::onChanged(const App::Property* prop) { if (prop == &PointSize) { pcPointStyle->pointSize = PointSize.getValue(); } else if (prop == &PointColor) { const App::Color& c = PointColor.getValue(); pcPointMaterial->diffuseColor.setValue(c.r,c.g,c.b); if (c != PointMaterial.getValue().diffuseColor) PointMaterial.setDiffuseColor(c); } else if (prop == &PointMaterial) { const App::Material& Mat = PointMaterial.getValue(); if (PointColor.getValue() != Mat.diffuseColor) PointColor.setValue(Mat.diffuseColor); pcPointMaterial->ambientColor.setValue(Mat.ambientColor.r,Mat.ambientColor.g,Mat.ambientColor.b); pcPointMaterial->diffuseColor.setValue(Mat.diffuseColor.r,Mat.diffuseColor.g,Mat.diffuseColor.b); pcPointMaterial->specularColor.setValue(Mat.specularColor.r,Mat.specularColor.g,Mat.specularColor.b); pcPointMaterial->emissiveColor.setValue(Mat.emissiveColor.r,Mat.emissiveColor.g,Mat.emissiveColor.b); pcPointMaterial->shininess.setValue(Mat.shininess); pcPointMaterial->transparency.setValue(Mat.transparency); } else if (prop == &LineWidth) { pcDrawStyle->lineWidth = LineWidth.getValue(); } else { ViewProviderGeometryObject::onChanged(prop); } } // ---------------------------------------------------------------------------- void ViewProviderFEMMeshBuilder::buildNodes(const App::Property* prop, std::vector& nodes) const { SoCoordinate3 *pcPointsCoord=0; SoIndexedFaceSet *pcFaces=0; if (nodes.empty()) { pcPointsCoord = new SoCoordinate3(); nodes.push_back(pcPointsCoord); pcFaces = new SoIndexedFaceSet(); nodes.push_back(pcFaces); } else if (nodes.size() == 2) { if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId()) pcPointsCoord = static_cast(nodes[0]); if (nodes[1]->getTypeId() == SoIndexedFaceSet::getClassTypeId()) pcFaces = static_cast(nodes[1]); } if (pcPointsCoord && pcFaces) createMesh(prop, pcPointsCoord, pcFaces); } void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces) const { const Fem::PropertyFemMesh* mesh = static_cast(prop); SMESHDS_Mesh* data = const_cast(mesh->getValue().getSMesh())->GetMeshDS(); const SMDS_MeshInfo& info = data->GetMeshInfo(); int numNode = info.NbNodes(); int numTria = info.NbTriangles(); int numQuad = info.NbQuadrangles(); //int numPoly = info.NbPolygons(); //int numVolu = info.NbVolumes(); int numTetr = info.NbTetras(); //int numHexa = info.NbHexas(); //int numPyrd = info.NbPyramids(); //int numPris = info.NbPrisms(); //int numHedr = info.NbPolyhedrons(); int index=0; std::map mapNodeIndex; // set the point coordinates coords->point.setNum(numNode); SMDS_NodeIteratorPtr aNodeIter = data->nodesIterator(); unsigned int i=0; SbVec3f* verts = coords->point.startEditing(); for (;aNodeIter->more();) { const SMDS_MeshNode* aNode = aNodeIter->next(); verts[i++].setValue((float)aNode->X(),(float)aNode->Y(),(float)aNode->Z()); mapNodeIndex[aNode] = index++; } coords->point.finishEditing(); // set the face indices index=0; faces->coordIndex.setNum(4*numTria + 5*numQuad + 16*numTetr); int32_t* indices = faces->coordIndex.startEditing(); SMDS_FaceIteratorPtr aFaceIter = data->facesIterator(); for (;aFaceIter->more();) { const SMDS_MeshFace* aFace = aFaceIter->next(); int num = aFace->NbNodes(); if (num != 3 && num != 4) continue; for (int j=0; jGetNode(j); indices[index++] = mapNodeIndex[node]; } indices[index++] = SO_END_FACE_INDEX; } SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator(); for (;aVolIter->more();) { const SMDS_MeshVolume* aVol = aVolIter->next(); int num = aVol->NbNodes(); if (num != 4) continue; int i1 = mapNodeIndex[aVol->GetNode(0)]; int i2 = mapNodeIndex[aVol->GetNode(1)]; int i3 = mapNodeIndex[aVol->GetNode(2)]; int i4 = mapNodeIndex[aVol->GetNode(3)]; indices[index++] = i1; indices[index++] = i3; indices[index++] = i2; indices[index++] = SO_END_FACE_INDEX; indices[index++] = i1; indices[index++] = i2; indices[index++] = i4; indices[index++] = SO_END_FACE_INDEX; indices[index++] = i1; indices[index++] = i4; indices[index++] = i3; indices[index++] = SO_END_FACE_INDEX; indices[index++] = i2; indices[index++] = i3; indices[index++] = i4; indices[index++] = SO_END_FACE_INDEX; } faces->coordIndex.finishEditing(); }