vrshoot
diff libs/assimp/IFCUtil.cpp @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/IFCUtil.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,577 @@ 1.4 +/* 1.5 +Open Asset Import Library (assimp) 1.6 +---------------------------------------------------------------------- 1.7 + 1.8 +Copyright (c) 2006-2012, assimp team 1.9 +All rights reserved. 1.10 + 1.11 +Redistribution and use of this software in source and binary forms, 1.12 +with or without modification, are permitted provided that the 1.13 +following conditions are met: 1.14 + 1.15 +* Redistributions of source code must retain the above 1.16 + copyright notice, this list of conditions and the 1.17 + following disclaimer. 1.18 + 1.19 +* Redistributions in binary form must reproduce the above 1.20 + copyright notice, this list of conditions and the 1.21 + following disclaimer in the documentation and/or other 1.22 + materials provided with the distribution. 1.23 + 1.24 +* Neither the name of the assimp team, nor the names of its 1.25 + contributors may be used to endorse or promote products 1.26 + derived from this software without specific prior 1.27 + written permission of the assimp team. 1.28 + 1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.40 + 1.41 +---------------------------------------------------------------------- 1.42 +*/ 1.43 + 1.44 +/** @file IFCUtil.cpp 1.45 + * @brief Implementation of conversion routines for some common Ifc helper entities. 1.46 + */ 1.47 + 1.48 +#include "AssimpPCH.h" 1.49 + 1.50 +#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER 1.51 + 1.52 +#include "IFCUtil.h" 1.53 +#include "PolyTools.h" 1.54 +#include "ProcessHelper.h" 1.55 + 1.56 +namespace Assimp { 1.57 + namespace IFC { 1.58 + 1.59 +// ------------------------------------------------------------------------------------------------ 1.60 +void TempOpening::Transform(const IfcMatrix4& mat) 1.61 +{ 1.62 + if(profileMesh) { 1.63 + profileMesh->Transform(mat); 1.64 + } 1.65 + if(profileMesh2D) { 1.66 + profileMesh2D->Transform(mat); 1.67 + } 1.68 + extrusionDir *= IfcMatrix3(mat); 1.69 +} 1.70 + 1.71 +// ------------------------------------------------------------------------------------------------ 1.72 +aiMesh* TempMesh::ToMesh() 1.73 +{ 1.74 + ai_assert(verts.size() == std::accumulate(vertcnt.begin(),vertcnt.end(),size_t(0))); 1.75 + 1.76 + if (verts.empty()) { 1.77 + return NULL; 1.78 + } 1.79 + 1.80 + std::auto_ptr<aiMesh> mesh(new aiMesh()); 1.81 + 1.82 + // copy vertices 1.83 + mesh->mNumVertices = static_cast<unsigned int>(verts.size()); 1.84 + mesh->mVertices = new aiVector3D[mesh->mNumVertices]; 1.85 + std::copy(verts.begin(),verts.end(),mesh->mVertices); 1.86 + 1.87 + // and build up faces 1.88 + mesh->mNumFaces = static_cast<unsigned int>(vertcnt.size()); 1.89 + mesh->mFaces = new aiFace[mesh->mNumFaces]; 1.90 + 1.91 + for(unsigned int i = 0,n=0, acc = 0; i < mesh->mNumFaces; ++n) { 1.92 + aiFace& f = mesh->mFaces[i]; 1.93 + if (!vertcnt[n]) { 1.94 + --mesh->mNumFaces; 1.95 + continue; 1.96 + } 1.97 + 1.98 + f.mNumIndices = vertcnt[n]; 1.99 + f.mIndices = new unsigned int[f.mNumIndices]; 1.100 + for(unsigned int a = 0; a < f.mNumIndices; ++a) { 1.101 + f.mIndices[a] = acc++; 1.102 + } 1.103 + 1.104 + ++i; 1.105 + } 1.106 + 1.107 + return mesh.release(); 1.108 +} 1.109 + 1.110 +// ------------------------------------------------------------------------------------------------ 1.111 +void TempMesh::Clear() 1.112 +{ 1.113 + verts.clear(); 1.114 + vertcnt.clear(); 1.115 +} 1.116 + 1.117 +// ------------------------------------------------------------------------------------------------ 1.118 +void TempMesh::Transform(const IfcMatrix4& mat) 1.119 +{ 1.120 + BOOST_FOREACH(IfcVector3& v, verts) { 1.121 + v *= mat; 1.122 + } 1.123 +} 1.124 + 1.125 +// ------------------------------------------------------------------------------ 1.126 +IfcVector3 TempMesh::Center() const 1.127 +{ 1.128 + return std::accumulate(verts.begin(),verts.end(),IfcVector3()) / static_cast<IfcFloat>(verts.size()); 1.129 +} 1.130 + 1.131 +// ------------------------------------------------------------------------------------------------ 1.132 +void TempMesh::Append(const TempMesh& other) 1.133 +{ 1.134 + verts.insert(verts.end(),other.verts.begin(),other.verts.end()); 1.135 + vertcnt.insert(vertcnt.end(),other.vertcnt.begin(),other.vertcnt.end()); 1.136 +} 1.137 + 1.138 +// ------------------------------------------------------------------------------------------------ 1.139 +void TempMesh::RemoveDegenerates() 1.140 +{ 1.141 + // The strategy is simple: walk the mesh and compute normals using 1.142 + // Newell's algorithm. The length of the normals gives the area 1.143 + // of the polygons, which is close to zero for lines. 1.144 + 1.145 + std::vector<IfcVector3> normals; 1.146 + ComputePolygonNormals(normals, false); 1.147 + 1.148 + bool drop = false; 1.149 + size_t inor = 0; 1.150 + 1.151 + std::vector<IfcVector3>::iterator vit = verts.begin(); 1.152 + for (std::vector<unsigned int>::iterator it = vertcnt.begin(); it != vertcnt.end(); ++inor) { 1.153 + const unsigned int pcount = *it; 1.154 + 1.155 + if (normals[inor].SquareLength() < 1e-5f) { 1.156 + it = vertcnt.erase(it); 1.157 + vit = verts.erase(vit, vit + pcount); 1.158 + 1.159 + drop = true; 1.160 + continue; 1.161 + } 1.162 + 1.163 + vit += pcount; 1.164 + ++it; 1.165 + } 1.166 + 1.167 + if(drop) { 1.168 + IFCImporter::LogDebug("removing degenerate faces"); 1.169 + } 1.170 +} 1.171 + 1.172 +// ------------------------------------------------------------------------------------------------ 1.173 +void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals, 1.174 + bool normalize, 1.175 + size_t ofs) const 1.176 +{ 1.177 + size_t max_vcount = 0; 1.178 + std::vector<unsigned int>::const_iterator begin = vertcnt.begin()+ofs, end = vertcnt.end(), iit; 1.179 + for(iit = begin; iit != end; ++iit) { 1.180 + max_vcount = std::max(max_vcount,static_cast<size_t>(*iit)); 1.181 + } 1.182 + 1.183 + std::vector<IfcFloat> temp((max_vcount+2)*4); 1.184 + normals.reserve( normals.size() + vertcnt.size()-ofs ); 1.185 + 1.186 + // `NewellNormal()` currently has a relatively strange interface and need to 1.187 + // re-structure things a bit to meet them. 1.188 + size_t vidx = std::accumulate(vertcnt.begin(),begin,0); 1.189 + for(iit = begin; iit != end; vidx += *iit++) { 1.190 + if (!*iit) { 1.191 + normals.push_back(IfcVector3()); 1.192 + continue; 1.193 + } 1.194 + for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) { 1.195 + const IfcVector3& v = verts[vidx+vofs]; 1.196 + temp[cnt++] = v.x; 1.197 + temp[cnt++] = v.y; 1.198 + temp[cnt++] = v.z; 1.199 +#ifdef _DEBUG 1.200 + temp[cnt] = std::numeric_limits<IfcFloat>::quiet_NaN(); 1.201 +#endif 1.202 + ++cnt; 1.203 + } 1.204 + 1.205 + normals.push_back(IfcVector3()); 1.206 + NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]); 1.207 + } 1.208 + 1.209 + if(normalize) { 1.210 + BOOST_FOREACH(IfcVector3& n, normals) { 1.211 + n.Normalize(); 1.212 + } 1.213 + } 1.214 +} 1.215 + 1.216 +// ------------------------------------------------------------------------------------------------ 1.217 +// Compute the normal of the last polygon in the given mesh 1.218 +IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const 1.219 +{ 1.220 + size_t total = vertcnt.back(), vidx = verts.size() - total; 1.221 + std::vector<IfcFloat> temp((total+2)*3); 1.222 + for(size_t vofs = 0, cnt = 0; vofs < total; ++vofs) { 1.223 + const IfcVector3& v = verts[vidx+vofs]; 1.224 + temp[cnt++] = v.x; 1.225 + temp[cnt++] = v.y; 1.226 + temp[cnt++] = v.z; 1.227 + } 1.228 + IfcVector3 nor; 1.229 + NewellNormal<3,3,3>(nor,total,&temp[0],&temp[1],&temp[2]); 1.230 + return normalize ? nor.Normalize() : nor; 1.231 +} 1.232 + 1.233 +// ------------------------------------------------------------------------------------------------ 1.234 +void TempMesh::FixupFaceOrientation() 1.235 +{ 1.236 + const IfcVector3 vavg = Center(); 1.237 + 1.238 + std::vector<IfcVector3> normals; 1.239 + ComputePolygonNormals(normals); 1.240 + 1.241 + size_t c = 0, ofs = 0; 1.242 + BOOST_FOREACH(unsigned int cnt, vertcnt) { 1.243 + if (cnt>2){ 1.244 + const IfcVector3& thisvert = verts[c]; 1.245 + if (normals[ofs]*(thisvert-vavg) < 0) { 1.246 + std::reverse(verts.begin()+c,verts.begin()+cnt+c); 1.247 + } 1.248 + } 1.249 + c += cnt; 1.250 + ++ofs; 1.251 + } 1.252 +} 1.253 + 1.254 +// ------------------------------------------------------------------------------------------------ 1.255 +void TempMesh::RemoveAdjacentDuplicates() 1.256 +{ 1.257 + 1.258 + bool drop = false; 1.259 + std::vector<IfcVector3>::iterator base = verts.begin(); 1.260 + BOOST_FOREACH(unsigned int& cnt, vertcnt) { 1.261 + if (cnt < 2){ 1.262 + base += cnt; 1.263 + continue; 1.264 + } 1.265 + 1.266 + IfcVector3 vmin,vmax; 1.267 + ArrayBounds(&*base, cnt ,vmin,vmax); 1.268 + 1.269 + 1.270 + const IfcFloat epsilon = (vmax-vmin).SquareLength() / static_cast<IfcFloat>(1e9); 1.271 + //const IfcFloat dotepsilon = 1e-9; 1.272 + 1.273 + //// look for vertices that lie directly on the line between their predecessor and their 1.274 + //// successor and replace them with either of them. 1.275 + 1.276 + //for(size_t i = 0; i < cnt; ++i) { 1.277 + // IfcVector3& v1 = *(base+i), &v0 = *(base+(i?i-1:cnt-1)), &v2 = *(base+(i+1)%cnt); 1.278 + // const IfcVector3& d0 = (v1-v0), &d1 = (v2-v1); 1.279 + // const IfcFloat l0 = d0.SquareLength(), l1 = d1.SquareLength(); 1.280 + // if (!l0 || !l1) { 1.281 + // continue; 1.282 + // } 1.283 + 1.284 + // const IfcFloat d = (d0/sqrt(l0))*(d1/sqrt(l1)); 1.285 + 1.286 + // if ( d >= 1.f-dotepsilon ) { 1.287 + // v1 = v0; 1.288 + // } 1.289 + // else if ( d < -1.f+dotepsilon ) { 1.290 + // v2 = v1; 1.291 + // continue; 1.292 + // } 1.293 + //} 1.294 + 1.295 + // drop any identical, adjacent vertices. this pass will collect the dropouts 1.296 + // of the previous pass as a side-effect. 1.297 + FuzzyVectorCompare fz(epsilon); 1.298 + std::vector<IfcVector3>::iterator end = base+cnt, e = std::unique( base, end, fz ); 1.299 + if (e != end) { 1.300 + cnt -= static_cast<unsigned int>(std::distance(e, end)); 1.301 + verts.erase(e,end); 1.302 + drop = true; 1.303 + } 1.304 + 1.305 + // check front and back vertices for this polygon 1.306 + if (cnt > 1 && fz(*base,*(base+cnt-1))) { 1.307 + verts.erase(base+ --cnt); 1.308 + drop = true; 1.309 + } 1.310 + 1.311 + // removing adjacent duplicates shouldn't erase everything :-) 1.312 + ai_assert(cnt>0); 1.313 + base += cnt; 1.314 + } 1.315 + if(drop) { 1.316 + IFCImporter::LogDebug("removing duplicate vertices"); 1.317 + } 1.318 +} 1.319 + 1.320 +// ------------------------------------------------------------------------------------------------ 1.321 +void TempMesh::Swap(TempMesh& other) 1.322 +{ 1.323 + vertcnt.swap(other.vertcnt); 1.324 + verts.swap(other.verts); 1.325 +} 1.326 + 1.327 +// ------------------------------------------------------------------------------------------------ 1.328 +bool IsTrue(const EXPRESS::BOOLEAN& in) 1.329 +{ 1.330 + return (std::string)in == "TRUE" || (std::string)in == "T"; 1.331 +} 1.332 + 1.333 +// ------------------------------------------------------------------------------------------------ 1.334 +IfcFloat ConvertSIPrefix(const std::string& prefix) 1.335 +{ 1.336 + if (prefix == "EXA") { 1.337 + return 1e18f; 1.338 + } 1.339 + else if (prefix == "PETA") { 1.340 + return 1e15f; 1.341 + } 1.342 + else if (prefix == "TERA") { 1.343 + return 1e12f; 1.344 + } 1.345 + else if (prefix == "GIGA") { 1.346 + return 1e9f; 1.347 + } 1.348 + else if (prefix == "MEGA") { 1.349 + return 1e6f; 1.350 + } 1.351 + else if (prefix == "KILO") { 1.352 + return 1e3f; 1.353 + } 1.354 + else if (prefix == "HECTO") { 1.355 + return 1e2f; 1.356 + } 1.357 + else if (prefix == "DECA") { 1.358 + return 1e-0f; 1.359 + } 1.360 + else if (prefix == "DECI") { 1.361 + return 1e-1f; 1.362 + } 1.363 + else if (prefix == "CENTI") { 1.364 + return 1e-2f; 1.365 + } 1.366 + else if (prefix == "MILLI") { 1.367 + return 1e-3f; 1.368 + } 1.369 + else if (prefix == "MICRO") { 1.370 + return 1e-6f; 1.371 + } 1.372 + else if (prefix == "NANO") { 1.373 + return 1e-9f; 1.374 + } 1.375 + else if (prefix == "PICO") { 1.376 + return 1e-12f; 1.377 + } 1.378 + else if (prefix == "FEMTO") { 1.379 + return 1e-15f; 1.380 + } 1.381 + else if (prefix == "ATTO") { 1.382 + return 1e-18f; 1.383 + } 1.384 + else { 1.385 + IFCImporter::LogError("Unrecognized SI prefix: " + prefix); 1.386 + return 1; 1.387 + } 1.388 +} 1.389 + 1.390 +// ------------------------------------------------------------------------------------------------ 1.391 +void ConvertColor(aiColor4D& out, const IfcColourRgb& in) 1.392 +{ 1.393 + out.r = static_cast<float>( in.Red ); 1.394 + out.g = static_cast<float>( in.Green ); 1.395 + out.b = static_cast<float>( in.Blue ); 1.396 + out.a = static_cast<float>( 1.f ); 1.397 +} 1.398 + 1.399 +// ------------------------------------------------------------------------------------------------ 1.400 +void ConvertColor(aiColor4D& out, const IfcColourOrFactor& in,ConversionData& conv,const aiColor4D* base) 1.401 +{ 1.402 + if (const EXPRESS::REAL* const r = in.ToPtr<EXPRESS::REAL>()) { 1.403 + out.r = out.g = out.b = static_cast<float>(*r); 1.404 + if(base) { 1.405 + out.r *= static_cast<float>( base->r ); 1.406 + out.g *= static_cast<float>( base->g ); 1.407 + out.b *= static_cast<float>( base->b ); 1.408 + out.a = static_cast<float>( base->a ); 1.409 + } 1.410 + else out.a = 1.0; 1.411 + } 1.412 + else if (const IfcColourRgb* const rgb = in.ResolveSelectPtr<IfcColourRgb>(conv.db)) { 1.413 + ConvertColor(out,*rgb); 1.414 + } 1.415 + else { 1.416 + IFCImporter::LogWarn("skipping unknown IfcColourOrFactor entity"); 1.417 + } 1.418 +} 1.419 + 1.420 +// ------------------------------------------------------------------------------------------------ 1.421 +void ConvertCartesianPoint(IfcVector3& out, const IfcCartesianPoint& in) 1.422 +{ 1.423 + out = IfcVector3(); 1.424 + for(size_t i = 0; i < in.Coordinates.size(); ++i) { 1.425 + out[i] = in.Coordinates[i]; 1.426 + } 1.427 +} 1.428 + 1.429 +// ------------------------------------------------------------------------------------------------ 1.430 +void ConvertVector(IfcVector3& out, const IfcVector& in) 1.431 +{ 1.432 + ConvertDirection(out,in.Orientation); 1.433 + out *= in.Magnitude; 1.434 +} 1.435 + 1.436 +// ------------------------------------------------------------------------------------------------ 1.437 +void ConvertDirection(IfcVector3& out, const IfcDirection& in) 1.438 +{ 1.439 + out = IfcVector3(); 1.440 + for(size_t i = 0; i < in.DirectionRatios.size(); ++i) { 1.441 + out[i] = in.DirectionRatios[i]; 1.442 + } 1.443 + const IfcFloat len = out.Length(); 1.444 + if (len<1e-6) { 1.445 + IFCImporter::LogWarn("direction vector magnitude too small, normalization would result in a division by zero"); 1.446 + return; 1.447 + } 1.448 + out /= len; 1.449 +} 1.450 + 1.451 +// ------------------------------------------------------------------------------------------------ 1.452 +void AssignMatrixAxes(IfcMatrix4& out, const IfcVector3& x, const IfcVector3& y, const IfcVector3& z) 1.453 +{ 1.454 + out.a1 = x.x; 1.455 + out.b1 = x.y; 1.456 + out.c1 = x.z; 1.457 + 1.458 + out.a2 = y.x; 1.459 + out.b2 = y.y; 1.460 + out.c2 = y.z; 1.461 + 1.462 + out.a3 = z.x; 1.463 + out.b3 = z.y; 1.464 + out.c3 = z.z; 1.465 +} 1.466 + 1.467 +// ------------------------------------------------------------------------------------------------ 1.468 +void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement3D& in) 1.469 +{ 1.470 + IfcVector3 loc; 1.471 + ConvertCartesianPoint(loc,in.Location); 1.472 + 1.473 + IfcVector3 z(0.f,0.f,1.f),r(1.f,0.f,0.f),x; 1.474 + 1.475 + if (in.Axis) { 1.476 + ConvertDirection(z,*in.Axis.Get()); 1.477 + } 1.478 + if (in.RefDirection) { 1.479 + ConvertDirection(r,*in.RefDirection.Get()); 1.480 + } 1.481 + 1.482 + IfcVector3 v = r.Normalize(); 1.483 + IfcVector3 tmpx = z * (v*z); 1.484 + 1.485 + x = (v-tmpx).Normalize(); 1.486 + IfcVector3 y = (z^x); 1.487 + 1.488 + IfcMatrix4::Translation(loc,out); 1.489 + AssignMatrixAxes(out,x,y,z); 1.490 +} 1.491 + 1.492 +// ------------------------------------------------------------------------------------------------ 1.493 +void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement2D& in) 1.494 +{ 1.495 + IfcVector3 loc; 1.496 + ConvertCartesianPoint(loc,in.Location); 1.497 + 1.498 + IfcVector3 x(1.f,0.f,0.f); 1.499 + if (in.RefDirection) { 1.500 + ConvertDirection(x,*in.RefDirection.Get()); 1.501 + } 1.502 + 1.503 + const IfcVector3 y = IfcVector3(x.y,-x.x,0.f); 1.504 + 1.505 + IfcMatrix4::Translation(loc,out); 1.506 + AssignMatrixAxes(out,x,y,IfcVector3(0.f,0.f,1.f)); 1.507 +} 1.508 + 1.509 +// ------------------------------------------------------------------------------------------------ 1.510 +void ConvertAxisPlacement(IfcVector3& axis, IfcVector3& pos, const IfcAxis1Placement& in) 1.511 +{ 1.512 + ConvertCartesianPoint(pos,in.Location); 1.513 + if (in.Axis) { 1.514 + ConvertDirection(axis,in.Axis.Get()); 1.515 + } 1.516 + else { 1.517 + axis = IfcVector3(0.f,0.f,1.f); 1.518 + } 1.519 +} 1.520 + 1.521 +// ------------------------------------------------------------------------------------------------ 1.522 +void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement& in, ConversionData& conv) 1.523 +{ 1.524 + if(const IfcAxis2Placement3D* pl3 = in.ResolveSelectPtr<IfcAxis2Placement3D>(conv.db)) { 1.525 + ConvertAxisPlacement(out,*pl3); 1.526 + } 1.527 + else if(const IfcAxis2Placement2D* pl2 = in.ResolveSelectPtr<IfcAxis2Placement2D>(conv.db)) { 1.528 + ConvertAxisPlacement(out,*pl2); 1.529 + } 1.530 + else { 1.531 + IFCImporter::LogWarn("skipping unknown IfcAxis2Placement entity"); 1.532 + } 1.533 +} 1.534 + 1.535 +// ------------------------------------------------------------------------------------------------ 1.536 +void ConvertTransformOperator(IfcMatrix4& out, const IfcCartesianTransformationOperator& op) 1.537 +{ 1.538 + IfcVector3 loc; 1.539 + ConvertCartesianPoint(loc,op.LocalOrigin); 1.540 + 1.541 + IfcVector3 x(1.f,0.f,0.f),y(0.f,1.f,0.f),z(0.f,0.f,1.f); 1.542 + if (op.Axis1) { 1.543 + ConvertDirection(x,*op.Axis1.Get()); 1.544 + } 1.545 + if (op.Axis2) { 1.546 + ConvertDirection(y,*op.Axis2.Get()); 1.547 + } 1.548 + if (const IfcCartesianTransformationOperator3D* op2 = op.ToPtr<IfcCartesianTransformationOperator3D>()) { 1.549 + if(op2->Axis3) { 1.550 + ConvertDirection(z,*op2->Axis3.Get()); 1.551 + } 1.552 + } 1.553 + 1.554 + IfcMatrix4 locm; 1.555 + IfcMatrix4::Translation(loc,locm); 1.556 + AssignMatrixAxes(out,x,y,z); 1.557 + 1.558 + 1.559 + IfcVector3 vscale; 1.560 + if (const IfcCartesianTransformationOperator3DnonUniform* nuni = op.ToPtr<IfcCartesianTransformationOperator3DnonUniform>()) { 1.561 + vscale.x = nuni->Scale?op.Scale.Get():1.f; 1.562 + vscale.y = nuni->Scale2?nuni->Scale2.Get():1.f; 1.563 + vscale.z = nuni->Scale3?nuni->Scale3.Get():1.f; 1.564 + } 1.565 + else { 1.566 + const IfcFloat sc = op.Scale?op.Scale.Get():1.f; 1.567 + vscale = IfcVector3(sc,sc,sc); 1.568 + } 1.569 + 1.570 + IfcMatrix4 s; 1.571 + IfcMatrix4::Scaling(vscale,s); 1.572 + 1.573 + out = locm * out * s; 1.574 +} 1.575 + 1.576 + 1.577 +} // ! IFC 1.578 +} // ! Assimp 1.579 + 1.580 +#endif