File indexing completed on 2025-03-13 08:19:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0022 #include "assimp/scene.h"
0023 #include "assimp/postprocess.h"
0024 #include "assimp/Importer.hpp"
0025
0026
0027 #include <sstream>
0028
0029 using namespace dd4hep;
0030 using namespace dd4hep::cad;
0031
0032
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
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
0115
0116
0117
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 }