Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-03-13 08:19:06

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 /// Framework include files
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/Detector.h>
0017 #include <DD4hep/ShapeTags.h>
0018 #include <DDCAD/ASSIMPReader.h>
0019 #include <DDCAD/Utilities.h>
0020 
0021 /// Open Asset Importer Library
0022 #include "assimp/scene.h"
0023 #include "assimp/postprocess.h"
0024 #include "assimp/Importer.hpp"
0025 
0026 /// C/C++ include files
0027 #include <sstream>
0028 
0029 using namespace dd4hep;
0030 using namespace dd4hep::cad;
0031 
0032 /// Read input file
0033 std::vector<std::unique_ptr<TGeoTessellated> >
0034 ASSIMPReader::readShapes(const std::string& source, double unit_length)  const
0035 {
0036   using Vertex = TessellatedSolid::Vertex;
0037   std::vector<std::unique_ptr<TGeoTessellated> > result;
0038   std::unique_ptr<Assimp::Importer> importer = std::make_unique<Assimp::Importer>();
0039   int aiflags = aiProcess_Triangulate|aiProcess_JoinIdenticalVertices|aiProcess_CalcTangentSpace;
0040   auto scene = importer->ReadFile( source.c_str(), aiflags);
0041   if ( !scene )  {
0042     except("ASSIMPReader","+++ FileNotFound: %s",source.c_str());
0043   }
0044   double unit = unit_length;
0045   bool   dump_facets = ((flags>>8)&0x1) == 1;
0046   for (unsigned int index = 0; index < scene->mNumMeshes; index++)   {
0047     aiMesh* mesh = scene->mMeshes[index];
0048     if ( mesh->mNumFaces > 0 )   {
0049       auto name = mesh->mName.C_Str();
0050       const aiVector3D* v = mesh->mVertices;
0051       std::vector<Vertex> vertices;
0052       vertices.reserve(mesh->mNumVertices);
0053       for(unsigned int i=0; i < mesh->mNumVertices; i++)  {
0054         vertices.emplace_back(Vertex(v[i].x*unit, v[i].y*unit, v[i].z*unit));
0055       }
0056       TessellatedSolid shape(name, vertices);
0057       for(unsigned int i=0; i < mesh->mNumFaces; i++)  {
0058         const unsigned int* idx  = mesh->mFaces[i].mIndices;
0059         shape->AddFacet(idx[0], idx[1], idx[2]);
0060       }
0061       if ( shape->GetNfacets() > 2 )   {
0062         shape->CloseShape(true,true,true);
0063         if ( dump_facets )   {
0064           for( size_t i=0, n=shape->GetNfacets(); i < n; ++i )   {
0065             const auto& facet = shape->GetFacet(i);
0066             std::string str = dd4hep::cad::streamFacet(facet, shape);
0067             printout(ALWAYS,"ASSIMPReader","++ Facet %4ld : %s",
0068                      i, str.c_str());
0069           }
0070         }
0071         shape->SetTitle(TESSELLATEDSOLID_TAG);
0072         result.emplace_back(std::unique_ptr<TGeoTessellated>(shape.ptr()));
0073         continue;
0074       }
0075       delete shape.ptr();
0076     }
0077   }
0078   printout(ALWAYS,"ASSIMPReader","+++ Read %ld meshes from %s",
0079            result.size(), source.c_str());
0080   return result;
0081 }
0082 
0083 /// Read input file and create a volume-set
0084 std::vector<std::unique_ptr<TGeoVolume> >
0085 ASSIMPReader::readVolumes(const std::string& source, double unit_length)  const
0086 {
0087   using Vertex = TessellatedSolid::Vertex;
0088   std::vector<std::unique_ptr<TGeoVolume> > result;
0089   std::unique_ptr<Assimp::Importer> importer = std::make_unique<Assimp::Importer>();
0090   bool dump_facets = ((flags>>8)&0x1) == 1;
0091   int aiflags = aiProcess_Triangulate|aiProcess_JoinIdenticalVertices|aiProcess_CalcTangentSpace;
0092   auto scene = importer->ReadFile( source.c_str(), aiflags);
0093   
0094   if ( !scene )  {
0095     except("ASSIMPReader","+++ FileNotFound: %s",source.c_str());
0096   }
0097   double unit = unit_length;
0098   for (unsigned int index = 0; index < scene->mNumMeshes; index++)   {
0099     aiMesh* mesh = scene->mMeshes[index];
0100     if ( mesh->mNumFaces > 0 )   {
0101       std::string name = mesh->mName.C_Str();
0102       const aiVector3D* v = mesh->mVertices;
0103       std::vector<Vertex> vertices;
0104 
0105       vertices.reserve(mesh->mNumVertices);
0106       for(unsigned int i=0; i < mesh->mNumVertices; i++)  {
0107         vertices.emplace_back(Vertex(v[i].x*unit, v[i].y*unit, v[i].z*unit));
0108       }
0109       TessellatedSolid shape(name,vertices);
0110       if ( name.empty() )  {
0111         name = _toString(result.size(), "tessellated_%ld");
0112       }
0113 
0114       /// NOTE: IMPORTANT!
0115       ///       ALWAYS add facets using the physical vertices!
0116       ///       TGeoTessellated takes care that the vertex map is unique and
0117       ///       assigns the proper indices to the facet.
0118       for(unsigned int i=0; i < mesh->mNumFaces; i++)  {
0119         const unsigned int* idx  = mesh->mFaces[i].mIndices;
0120         bool degenerated = false;
0121         if ( mesh->mFaces[i].mNumIndices == 3 )
0122           degenerated = dd4hep::cad::facetIsDegenerated({vertices[idx[0]], vertices[idx[1]], vertices[idx[2]]});
0123         else if ( mesh->mFaces[i].mNumIndices == 4 )
0124           degenerated = dd4hep::cad::facetIsDegenerated({vertices[idx[0]], vertices[idx[1]], vertices[idx[2]], vertices[idx[3]]});
0125         
0126         if ( degenerated )   {
0127           printout(DEBUG, "ASSIMPReader", "+++ %s: Drop degenerated facet: %d %d %d",
0128                    name.c_str(), idx[0], idx[1], idx[2]);
0129         }
0130 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
0131         else if ( mesh->mFaces[i].mNumIndices == 3 )   {
0132           shape->AddFacet(vertices[idx[0]], vertices[idx[1]], vertices[idx[2]]);
0133         }
0134         else if ( mesh->mFaces[i].mNumIndices == 4 )   {
0135           shape->AddFacet(vertices[idx[0]], vertices[idx[1]], vertices[idx[2]], vertices[idx[3]]);
0136         }
0137 #else
0138         else if ( mesh->mFaces[i].mNumIndices == 3 )   {
0139           shape->AddFacet(idx[0], idx[1], idx[2]);
0140         }
0141         else if ( mesh->mFaces[i].mNumIndices == 4 )   {
0142           shape->AddFacet(idx[0], idx[1], idx[2], idx[3]);
0143         }
0144 #endif
0145         else  {
0146           printout(INFO, "ASSIMPReader", "+++ %s: Fancy facet with %d indices.",
0147                    name.c_str(), mesh->mFaces[i].mNumIndices);
0148         }
0149       }
0150       if ( shape->GetNfacets() > 2 )   {
0151         std::string mat_name;
0152         Material mat;
0153         VisAttr  vis;
0154         if ( scene->HasMaterials() )   {
0155           aiMaterial* ai_mat = scene->mMaterials[mesh->mMaterialIndex];
0156           mat_name = ai_mat->GetName().C_Str();
0157           mat = detector.material(mat_name);
0158         }
0159         if ( !mat.isValid() )   {
0160           printout(ERROR, "ASSIMPReader",
0161                    "+++ %s: No material named '%s' FOUND. Will use Air. [Missing material]",
0162                    name.c_str(), mat_name.c_str());
0163           mat = detector.air();
0164         }
0165         Volume vol(name, Solid(shape.ptr()), mat);
0166         if ( mesh->HasVertexColors(0) )   {
0167           const aiColor4D* col = mesh->mColors[0];
0168           if ( col )   {
0169             for( const auto& _v : detector.visAttributes() )   {
0170               float ca, cr, cg, cb, eps = 0.05;
0171               VisAttr(_v.second).argb(ca, cr, cg, cb);
0172               if( std::abs(col->a-ca) < eps && std::abs(col->r-cr) < eps &&
0173                   std::abs(col->g-cg) < eps && std::abs(col->b-cb) < eps )   {
0174                 vis = _v.second;
0175                 break;
0176               }
0177             }
0178             if ( !vis.isValid() )   {
0179               char text[1024];
0180               ::snprintf(text,sizeof(text),"vis_%s_%p", name.c_str(), (void*)vol.ptr());
0181               text[sizeof(text)-1] = 0;
0182               vis = VisAttr(text);
0183               vis.setColor(col->a,col->r,col->g,col->b);
0184               detector.add(vis);
0185             }
0186             vol.setVisAttributes(vis);
0187           }
0188         }
0189         printout(INFO,"ASSIMPReader",
0190                  "+++ %-17s Material: %-16s  Viualization: %s",
0191                  vol.name(), mat.name(), vis.isValid() ? vis.name() : "NONE");
0192         shape->CloseShape(true,true,true);
0193         if ( dump_facets )   {
0194           for( size_t i=0, n=shape->GetNfacets(); i < n; ++i )   {
0195             const auto& facet = shape->GetFacet(i);
0196             std::string str = dd4hep::cad::streamFacet(facet, shape);
0197             printout(ALWAYS,"ASSIMPReader","++ Facet %4ld : %s",
0198                      i, str.c_str());
0199           }
0200         }
0201         result.emplace_back(std::unique_ptr<TGeoVolume>(vol.ptr()));
0202         continue;
0203       }
0204       delete shape.ptr();
0205     }
0206   }
0207   printout(ALWAYS,"ASSIMPReader","+++ Read %ld meshes from %s",
0208            result.size(), source.c_str());
0209   return result;
0210 }