1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "[TriangleMesh.h]"19 #include <stdlib.h>20 #include <string.h>21 #include "../Math/float3.h"22 #include "[Triangle.h]"23 #include "[Ray.h]"24 #include "[Polyhedron.h]"25 #include "../MathGeoLibFwd.h"26 #include "../Math/MathConstants.h"27 #include "../Math/myassert.h"28 #include "../../tests/SystemInfo.h"29 30 #include <vector>31 32 #include "../Math/SSEMath.h"33 34 35 36 #define SOA_HAS_EDGES37 38 [MATH_BEGIN_NAMESPACE]39 40 enum [SIMDCapability]41 {42 [SIMD_NONE],43 [SIMD_SSE],44 [SIMD_SSE2],45 46 47 48 [SIMD_SSE41],49 50 [SIMD_AVX]51 };52 53 [SIMDCapability] [DetectSIMDCapability]()54 {55 #ifdef WIN32 56 57 #ifdef MATH_SSE58 int CPUInfo[4] = {-1};59 60 unsigned nIds;61 int nFeatureInfo = 0;62 63 64 65 #ifdef MATH_SSE4166 bool bSSE41Extensions = false;67 #endif68 69 70 71 72 73 74 75 76 77 78 79 80 81 #ifdef MATH_AVX82 bool hasAVX = false;83 #endif84 85 86 CpuId(CPUInfo, 0);87 nIds = CPUInfo[0];88 89 90 91 if (nIds >= 1)92 {93 94 95 CpuId(CPUInfo, 1);96 97 98 {99 100 101 102 103 104 105 #ifdef MATH_AVX106 hasAVX = (CPUInfo[2] & 0x10000000) || false;107 #endif108 nFeatureInfo = CPUInfo[3];109 }110 }111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 #ifdef MATH_AVX145 if (hasAVX)146 return [SIMD_AVX];147 #endif148 #ifdef MATH_SSE41149 if (bSSE41Extensions)150 return [SIMD_SSE41];151 #endif152 #ifdef MATH_SSE2153 const bool hasSSE2 = (nFeatureInfo & (1 << 26)) != 0;154 if (hasSSE2)155 return [SIMD_SSE2];156 #endif157 #ifdef MATH_SSE158 const bool hasSSE = (nFeatureInfo & (1 << 25)) != 0;159 if (hasSSE)160 return [SIMD_SSE];161 #endif162 163 #endif // ~ MATH_SSE not defined.164 #endif165 return [SIMD_NONE];166 }167 168 const int [simdCapability] = [DetectSIMDCapability]();169 170 [TriangleMesh::TriangleMesh]()171 :data(0), numTriangles(0), vertexSizeBytes(0)172 #ifdef _DEBUG173 , vertexDataLayout(0)174 #endif175 {176 177 }178 179 [TriangleMesh::~TriangleMesh]()180 {181 [AlignedFree](data);182 }183 184 [TriangleMesh::TriangleMesh](const [TriangleMesh] &rhs)185 :data(0), numTriangles(0), vertexSizeBytes(0)186 #ifdef _DEBUG187 , vertexDataLayout(0)188 #endif189 {190 *this = rhs;191 }192 193 [TriangleMesh] &[TriangleMesh::operator =](const [TriangleMesh] &rhs)194 {195 if (this == &rhs)196 return *this;197 198 #ifdef _DEBUG199 vertexDataLayout = rhs.vertexDataLayout;200 #endif201 ReallocVertexBuffer(rhs.numTriangles, rhs.vertexSizeBytes);202 memcpy(data, rhs.data, numTriangles*3*vertexSizeBytes);203 204 return *this;205 }206 207 void [TriangleMesh::Set](const [Polyhedron] &polyhedron)208 {209 [TriangleArray] [tris] = polyhedron.[Triangulate]();210 if (!tris.empty())211 {212 int alignment = (simdCapability == [SIMD_AVX]) ? 8 : ((simdCapability == [SIMD_SSE41] || simdCapability == [SIMD_SSE2]) ? 4 : 1);213 vec degen = [POINT_VEC_SCALAR](-[FLOAT_INF]);214 [Triangle] degent(degen, degen, degen);215 while(tris.size() % alignment != 0)216 tris.push_back(degent);217 [Set](([Triangle]*)&tris[0], (int)tris.size());218 }219 }220 221 void [TriangleMesh::Set](const float *triangleMesh, int numTriangles, int vertexSizeBytes)222 {223 #ifndef MATH_AUTOMATIC_SSE // TODO: Restore support for this when MATH_AUTOMATIC_SSE is defined!224 if (simdCapability == [SIMD_AVX])225 [SetSoA8](triangleMesh, numTriangles, vertexSizeBytes);226 else if (simdCapability == [SIMD_SSE41] || simdCapability == [SIMD_SSE2])227 [SetSoA4](triangleMesh, numTriangles, vertexSizeBytes);228 else229 #endif230 [SetAoS](triangleMesh, numTriangles, vertexSizeBytes);231 }232 233 float [TriangleMesh::IntersectRay](const [Ray] &ray) const234 {235 #ifndef MATH_AUTOMATIC_SSE // TODO: Restore support for this when MATH_AUTOMATIC_SSE is defined!236 #ifdef MATH_AVX237 if (simdCapability == [SIMD_AVX])238 return IntersectRay_AVX(ray);239 #endif240 #ifdef MATH_SSE41241 if (simdCapability == [SIMD_SSE41])242 return IntersectRay_SSE41(ray);243 #endif244 #ifdef MATH_SSE2245 if (simdCapability == [SIMD_SSE2])246 return IntersectRay_SSE2(ray);247 #endif248 #endif249 int triangleIndex;250 float u, v;251 return [IntersectRay_TriangleIndex_UV_CPP](ray, triangleIndex, u, v);252 }253 254 float [TriangleMesh::IntersectRay_TriangleIndex](const [Ray] &ray, int &outTriangleIndex) const255 {256 #ifndef MATH_AUTOMATIC_SSE // TODO: Restore support for this when MATH_AUTOMATIC_SSE is defined!257 #ifdef MATH_AVX258 if (simdCapability == [SIMD_AVX])259 return IntersectRay_TriangleIndex_AVX(ray, outTriangleIndex);260 #endif261 #ifdef MATH_SSE41262 if (simdCapability == [SIMD_SSE41])263 return IntersectRay_TriangleIndex_SSE41(ray, outTriangleIndex);264 #endif265 #ifdef MATH_SSE2266 if (simdCapability == [SIMD_SSE2])267 return IntersectRay_TriangleIndex_SSE2(ray, outTriangleIndex);268 #endif269 #endif270 float u, v;271 return [IntersectRay_TriangleIndex_UV_CPP](ray, outTriangleIndex, u, v);272 }273 274 float [TriangleMesh::IntersectRay_TriangleIndex_UV](const [Ray] &ray, int &outTriangleIndex, float &outU, float &outV) const275 {276 #ifndef MATH_AUTOMATIC_SSE // TODO: Restore support for this when MATH_AUTOMATIC_SSE is defined!277 #ifdef MATH_AVX278 if (simdCapability == [SIMD_AVX])279 return IntersectRay_TriangleIndex_UV_AVX(ray, outTriangleIndex, outU, outV);280 #endif281 #ifdef MATH_SSE41282 if (simdCapability == [SIMD_SSE41])283 return IntersectRay_TriangleIndex_UV_SSE41(ray, outTriangleIndex, outU, outV);284 #endif285 #ifdef MATH_SSE2286 if (simdCapability == [SIMD_SSE2])287 return IntersectRay_TriangleIndex_UV_SSE2(ray, outTriangleIndex, outU, outV);288 #endif289 #endif290 291 return [IntersectRay_TriangleIndex_UV_CPP](ray, outTriangleIndex, outU, outV);292 }293 294 void TriangleMesh::ReallocVertexBuffer(int numTris, int vertexSizeBytes_)295 {296 [AlignedFree](data);297 vertexSizeBytes = vertexSizeBytes_;298 data = (float*)[AlignedMalloc](numTris * 3 * vertexSizeBytes, 32);299 numTriangles = numTris;300 }301 302 void [TriangleMesh::SetAoS](const float *vertexData, int numTriangles, int vertexSizeBytes)303 {304 ReallocVertexBuffer(numTriangles, vertexSizeBytes);305 #ifdef _DEBUG306 vertexDataLayout = 0; 307 #endif308 309 memcpy(data, vertexData, numTriangles * 3 * vertexSizeBytes);310 }311 312 void [TriangleMesh::SetSoA4](const float *vertexData, int numTriangles, int vertexSizeBytes)313 {314 ReallocVertexBuffer(numTriangles, 3*sizeof(float));315 #ifdef _DEBUG316 vertexDataLayout = 1; 317 #endif318 319 [assert](vertexSizeBytes % 4 == 0);320 int vertexSizeFloats = vertexSizeBytes / 4;321 int triangleSizeFloats = vertexSizeFloats * 3;322 [assert](numTriangles % 4 == 0); 323 324 325 326 327 float *o = data;328 for(int i = 0; i + 4 <= numTriangles; i += 4) 329 {330 for (int j = 0; j < 3; ++j) 331 {332 const float *src = vertexData;333 for (int k = 0; k < 3; ++k) 334 {335 *o++ = src[0];336 *o++ = src[triangleSizeFloats];337 *o++ = src[2 * triangleSizeFloats];338 *o++ = src[3 * triangleSizeFloats];339 ++src;340 }341 vertexData += vertexSizeFloats;342 }343 vertexData += 3 * triangleSizeFloats;344 }345 346 #ifdef SOA_HAS_EDGES347 o = data;348 for(int i = 0; i + 4 <= numTriangles; i += 4)349 {350 for(int j = 12; j < 24; ++j)351 o[j] -= o[j-12];352 for(int j = 24; j < 36; ++j)353 o[j] -= o[j-24];354 o += 36;355 }356 #endif357 }358 359 void [TriangleMesh::SetSoA8](const float *vertexData, int numTriangles, int vertexSizeBytes)360 {361 ReallocVertexBuffer(numTriangles, 3*sizeof(float));362 #ifdef _DEBUG363 vertexDataLayout = 2; 364 #endif365 366 [assert](vertexSizeBytes % 4 == 0);367 int vertexSizeFloats = vertexSizeBytes / 4;368 int triangleSizeFloats = vertexSizeFloats * 3;369 [assert](numTriangles % 8 == 0); 370 371 372 373 374 float *o = data;375 for(int i = 0; i + 8 <= numTriangles; i += 8) 376 {377 for (int j = 0; j < 3; ++j) 378 {379 const float *src = vertexData;380 for (int k = 0; k < 3; ++k) 381 {382 *o++ = src[0];383 *o++ = src[triangleSizeFloats];384 *o++ = src[2 * triangleSizeFloats];385 *o++ = src[3 * triangleSizeFloats];386 *o++ = src[4 * triangleSizeFloats];387 *o++ = src[5 * triangleSizeFloats];388 *o++ = src[6 * triangleSizeFloats];389 *o++ = src[7 * triangleSizeFloats];390 ++src;391 }392 vertexData += vertexSizeFloats;393 }394 vertexData += 7 * triangleSizeFloats;395 }396 397 #ifdef SOA_HAS_EDGES398 o = data;399 for(int i = 0; i + 8 <= numTriangles; i += 8)400 {401 for(int j = 24; j < 48; ++j)402 o[j] -= o[j-24];403 for(int j = 48; j < 72; ++j)404 o[j] -= o[j-48];405 o += 72;406 }407 #endif408 }409 410 float [TriangleMesh::IntersectRay_TriangleIndex_UV_CPP](const [Ray] &ray, int &outTriangleIndex, float &outU, float &outV) const411 {412 [assert](sizeof([float3]) == 3*sizeof(float));413 [assert](sizeof([Triangle]) == 3*sizeof(vec));414 #ifdef _DEBUG415 [assert](vertexDataLayout == 0); 416 #endif417 418 float [nearestD] = [FLOAT_INF];419 420 const [Triangle] *tris = reinterpret_cast<const [Triangle]*>(data);421 for(int i = 0; i < numTriangles; ++i)422 {423 float u, v;424 float [d] = [Triangle::IntersectLineTri](ray.[pos], ray.[dir], tris->[a], tris->[b], tris->[c], u, v);425 if (d >= 0.f && d < nearestD)426 {427 nearestD = [d];428 outU = u;429 outV = v;430 outTriangleIndex = i;431 }432 ++[tris];433 }434 435 return [nearestD];436 }437 438 [MATH_END_NAMESPACE]439 440 #ifdef MATH_SSE2441 #define MATH_GEN_SSE2442 #include "[TriangleMesh_IntersectRay_SSE.inl]"443 444 #define MATH_GEN_SSE2445 #define MATH_GEN_TRIANGLEINDEX446 #include "[TriangleMesh_IntersectRay_SSE.inl]"447 448 #define MATH_GEN_SSE2449 #define MATH_GEN_TRIANGLEINDEX450 #define MATH_GEN_UV451 #include "[TriangleMesh_IntersectRay_SSE.inl]"452 #endif453 454 #ifdef MATH_SSE41455 #define MATH_GEN_SSE41456 #include "[TriangleMesh_IntersectRay_SSE.inl]"457 458 #define MATH_GEN_SSE41459 #define MATH_GEN_TRIANGLEINDEX460 #include "[TriangleMesh_IntersectRay_SSE.inl]"461 462 #define MATH_GEN_SSE41463 #define MATH_GEN_TRIANGLEINDEX464 #define MATH_GEN_UV465 #include "[TriangleMesh_IntersectRay_SSE.inl]"466 #endif467 468 #ifdef MATH_AVX469 #define MATH_GEN_AVX470 #include "[TriangleMesh_IntersectRay_AVX.inl]"471 472 #define MATH_GEN_AVX473 #define MATH_GEN_TRIANGLEINDEX474 #include "[TriangleMesh_IntersectRay_AVX.inl]"475 476 #define MATH_GEN_AVX477 #define MATH_GEN_TRIANGLEINDEX478 #define MATH_GEN_UV479 #include "[TriangleMesh_IntersectRay_AVX.inl]"480 #endif Go back to previous page