1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "[OBB.h]"19 #ifdef MATH_ENABLE_STL_SUPPORT20 #include <iostream>21 #include <utility>22 #endif23 #include "../Math/MathFunc.h"24 #include "[AABB.h]"25 #include "[Frustum.h]"26 #include "../Algorithm/Random/LCG.h"27 #include "[LineSegment.h]"28 #include "[Line.h]"29 #include "[Plane.h]"30 #include "[Polygon.h]"31 #include "[Polyhedron.h]"32 #include "[Sphere.h]"33 #include "[Capsule.h]"34 #include "../Math/float3x3.h"35 #include "../Math/float3x4.h"36 #include "../Math/float4.h"37 #include "../Math/float4x4.h"38 #include "../Math/Quat.h"39 #include "[PBVolume.h]"40 #include "[Ray.h]"41 #include "[Triangle.h]"42 #include <stdlib.h>43 44 #ifdef MATH_CONTAINERLIB_SUPPORT45 #include "Algorithm/Sort/Sort.h"46 #endif47 48 #ifdef MATH_GRAPHICSENGINE_INTEROP49 #include "VertexBuffer.h"50 #endif51 52 #if defined(MATH_SSE) && defined(MATH_AUTOMATIC_SSE)53 #include "../Math/float4_sse.h"54 #include "../Math/float4x4_sse.h"55 #endif56 57 [MATH_BEGIN_NAMESPACE]58 59 [OBB::OBB](const vec &pos, const vec &r, const vec &axis0, const vec &axis1, const vec &axis2)60 :pos(pos), r(r)61 {62 axis[0] = axis0;63 axis[1] = axis1;64 axis[2] = axis2;65 }66 67 [OBB::OBB](const [AABB] &aabb)68 {69 [SetFrom](aabb);70 }71 72 void [OBB::SetNegativeInfinity]()73 {74 [pos] = [POINT_VEC_SCALAR](0.f);75 [r].[SetFromScalar](-[FLOAT_INF]);76 [axis][0] = [DIR_VEC](1,0,0);77 [axis][1] = [DIR_VEC](0, 1, 0);78 [axis][2] = [DIR_VEC](0, 0, 1);79 }80 81 void [OBB::SetFrom](const [AABB] &aabb)82 {83 [pos] = aabb.[CenterPoint]();84 [r] = aabb.[HalfSize]();85 [axis][0] = [DIR_VEC](1, 0, 0);86 [axis][1] = [DIR_VEC](0, 1, 0);87 [axis][2] = [DIR_VEC](0, 0, 1);88 }89 90 template<typename Matrix>91 void [OBBSetFrom]([OBB] &obb, const [AABB] &aabb, const Matrix &m)92 {93 [assume](m.IsColOrthogonal()); 94 [assume](m.HasUniformScale()); 95 obb.[pos] = m.MulPos(aabb.[CenterPoint]());96 obb.[r] = aabb.[HalfSize]();97 obb.[axis][0] = [DIR_VEC](m.Col(0));98 obb.[axis][1] = [DIR_VEC](m.Col(1));99 obb.[axis][2] = [DIR_VEC](m.Col(2));100 101 102 float matrixScale = obb.[axis][0].[LengthSq]();103 matrixScale = [Sqrt](matrixScale);104 obb.[r] *= matrixScale;105 matrixScale = 1.f / matrixScale;106 obb.[axis][0] *= matrixScale;107 obb.[axis][1] *= matrixScale;108 obb.[axis][2] *= matrixScale;109 110 111 112 113 vec::Orthonormalize(obb.[axis][0], obb.[axis][1], obb.[axis][2]);114 }115 116 void [OBB::SetFrom](const [AABB] &aabb, const [float3x3] &transform)117 {118 [assume](transform.[IsColOrthogonal]());119 [OBBSetFrom](*this, aabb, transform);120 }121 122 void [OBB::SetFrom](const [AABB] &aabb, const [float3x4] &transform)123 {124 [OBBSetFrom](*this, aabb, transform);125 }126 127 void [OBB::SetFrom](const [AABB] &aabb, const [float4x4] &transform)128 {129 [assume](transform.[Row](3).[Equals](0,0,0,1));130 [OBBSetFrom](*this, aabb, transform.[Float3x4Part]());131 }132 133 void [OBB::SetFrom](const [AABB] &aabb, const [Quat] &transform)134 {135 [OBBSetFrom](*this, aabb, [float3x3](transform));136 }137 138 void [OBB::SetFrom](const [Sphere] &sphere)139 {140 [pos] = sphere.[pos];141 [r].[SetFromScalar](sphere.[r]);142 [axis][0] = [DIR_VEC](1,0,0);143 [axis][1] = [DIR_VEC](0,1,0);144 [axis][2] = [DIR_VEC](0,0,1);145 }146 147 #ifdef MATH_CONTAINERLIB_SUPPORT148 bool [OBB::SetFrom](const [Polyhedron] &polyhedron)149 {150 if (!polyhedron.[v].empty())151 {152 *this = [OBB::OptimalEnclosingOBB]((vec*)&polyhedron.[v][0], (int)polyhedron.[v].size());153 return true;154 }155 else156 {157 [SetNegativeInfinity]();158 return false;159 }160 }161 #endif162 163 #if 0164 void OBB::SetFromApproximate(const vec *pointArray, int numPoints)165 {166 *this = PCAEnclosingOBB(pointArray, numPoints);167 }168 #endif169 170 [Polyhedron] [OBB::ToPolyhedron]() const171 {172 173 174 [Polyhedron] p;175 176 177 for(int i = 0; i < 8; ++i)178 p.[v].push_back([CornerPoint](i));179 180 181 const int faces[6][4] =182 {183 { 0, 1, 3, 2 }, 184 { 4, 6, 7, 5 }, 185 { 0, 4, 5, 1 }, 186 { 7, 6, 2, 3 }, 187 { 0, 2, 6, 4 }, 188 { 1, 5, 7, 3 }, 189 };190 191 for(int f = 0; f < 6; ++f)192 {193 [Polyhedron::Face] face;194 for(int v = 0; v < 4; ++v)195 face.[v].push_back(faces[f][v]);196 p.[f].push_back(face);197 }198 199 return p;200 }201 202 [PBVolume<6>] [OBB::ToPBVolume]() const203 {204 [PBVolume<6>] pbVolume;205 for(int i = 0; i < 6; ++i)206 pbVolume.[p][i] = [FacePlane](i);207 208 return pbVolume;209 }210 211 [AABB] [OBB::MinimalEnclosingAABB]() const212 {213 [AABB] aabb;214 aabb.[SetFrom](*this);215 return aabb;216 }217 218 #if 0219 220 [AABB] OBB::MaximalContainedAABB() const221 {222 #ifdef _MSC_VER223 #pragma warning(OBB::MaximalContainedAABB not implemented!)224 #else225 #warning OBB::MaximalContainedAABB not implemented!226 #endif227 [assume](false && "OBB::MaximalContainedAABB not implemented!"); 228 return [AABB]();229 }230 #endif231 232 [Sphere] [OBB::MinimalEnclosingSphere]() const233 {234 [Sphere] s;235 s.[pos] = [pos];236 s.[r] = [HalfDiagonal]().[Length]();237 return s;238 }239 240 [Sphere] [OBB::MaximalContainedSphere]() const241 {242 [Sphere] s;243 s.[pos] = [pos];244 s.[r] = [r].[MinElement]();245 return s;246 }247 248 bool [OBB::IsFinite]() const249 {250 return [pos].[IsFinite]() && [r].[IsFinite]() && [axis][0].[IsFinite]() && [axis][1].[IsFinite]() && [axis][2].[IsFinite]();251 }252 253 bool [OBB::IsDegenerate]() const254 {255 return !([r].[x] > 0.f && [r].[y] > 0.f && [r].[z] > 0.f);256 }257 258 vec [OBB::CenterPoint]() const259 {260 return [pos];261 }262 263 vec [OBB::PointInside](float x, float y, float z) const264 {265 [assume](0.f <= x && x <= 1.f);266 [assume](0.f <= y && y <= 1.f);267 [assume](0.f <= z && z <= 1.f);268 269 return [pos] + [axis][0] * (2.f * [r].[x] * x - [r].[x])270 + [axis][1] * (2.f * [r].[y] * y - [r].[y])271 + [axis][2] * (2.f * [r].[z] * z - [r].[z]);272 }273 274 [LineSegment] [OBB::Edge](int edgeIndex) const275 {276 [assume](0 <= edgeIndex && edgeIndex <= 11);277 switch(edgeIndex)278 {279 default: 280 case 0: return [LineSegment]([CornerPoint](0), [CornerPoint](1));281 case 1: return [LineSegment]([CornerPoint](0), [CornerPoint](2));282 case 2: return [LineSegment]([CornerPoint](0), [CornerPoint](4));283 case 3: return [LineSegment]([CornerPoint](1), [CornerPoint](3));284 case 4: return [LineSegment]([CornerPoint](1), [CornerPoint](5));285 case 5: return [LineSegment]([CornerPoint](2), [CornerPoint](3));286 case 6: return [LineSegment]([CornerPoint](2), [CornerPoint](6));287 case 7: return [LineSegment]([CornerPoint](3), [CornerPoint](7));288 case 8: return [LineSegment]([CornerPoint](4), [CornerPoint](5));289 case 9: return [LineSegment]([CornerPoint](4), [CornerPoint](6));290 case 10: return [LineSegment]([CornerPoint](5), [CornerPoint](7));291 case 11: return [LineSegment]([CornerPoint](6), [CornerPoint](7));292 }293 }294 295 vec [OBB::CornerPoint](int cornerIndex) const296 { 297 [assume](0 <= cornerIndex && cornerIndex <= 7);298 switch(cornerIndex)299 {300 default: 301 case 0: return [pos] - [r].[x] * [axis][0] - [r].[y] * [axis][1] - [r].[z] * [axis][2];302 case 1: return [pos] - [r].[x] * [axis][0] - [r].[y] * [axis][1] + [r].[z] * [axis][2];303 case 2: return [pos] - [r].[x] * [axis][0] + [r].[y] * [axis][1] - [r].[z] * [axis][2];304 case 3: return [pos] - [r].[x] * [axis][0] + [r].[y] * [axis][1] + [r].[z] * [axis][2];305 case 4: return [pos] + [r].[x] * [axis][0] - [r].[y] * [axis][1] - [r].[z] * [axis][2];306 case 5: return [pos] + [r].[x] * [axis][0] - [r].[y] * [axis][1] + [r].[z] * [axis][2];307 case 6: return [pos] + [r].[x] * [axis][0] + [r].[y] * [axis][1] - [r].[z] * [axis][2];308 case 7: return [pos] + [r].[x] * [axis][0] + [r].[y] * [axis][1] + [r].[z] * [axis][2];309 }310 }311 312 vec [OBB::ExtremePoint](const vec &direction) const313 {314 vec pt = [pos];315 pt += [axis][0] * ([Dot](direction, [axis][0]) >= 0.f ? [r].[x] : -[r].[x]);316 pt += [axis][1] * ([Dot](direction, [axis][1]) >= 0.f ? [r].[y] : -[r].[y]);317 pt += [axis][2] * ([Dot](direction, [axis][2]) >= 0.f ? [r].[z] : -[r].[z]);318 return pt;319 }320 321 vec [OBB::ExtremePoint](const vec &direction, float &projectionDistance) const322 {323 vec extremePoint = [ExtremePoint](direction);324 projectionDistance = extremePoint.Dot(direction);325 return extremePoint;326 }327 328 void [OBB::ProjectToAxis](const vec &direction, float &outMin, float &outMax) const329 {330 float x = [Abs]([Dot](direction, [axis][0]) * [r].[x]);331 float y = [Abs]([Dot](direction, [axis][1]) * [r].[y]);332 float z = [Abs]([Dot](direction, [axis][2]) * [r].[z]);333 float pt = [Dot](direction, [pos]);334 outMin = pt - x - y - z;335 outMax = pt + x + y + z;336 }337 338 int [OBB::UniqueFaceNormals](vec *out) const339 {340 out[0] = [axis][0];341 out[1] = [axis][1];342 out[2] = [axis][2];343 return 3;344 }345 346 int [OBB::UniqueEdgeDirections](vec *out) const347 {348 out[0] = [axis][0];349 out[1] = [axis][1];350 out[2] = [axis][2];351 return 3;352 }353 354 vec [OBB::PointOnEdge](int edgeIndex, float u) const355 {356 [assume](0 <= edgeIndex && edgeIndex <= 11);357 [assume](0 <= u && u <= 1.f);358 359 edgeIndex = [Clamp](edgeIndex, 0, 11);360 vec [d] = [axis][edgeIndex/4] * (2.f * u - 1.f) * [r][edgeIndex/4];361 switch(edgeIndex)362 {363 default: 364 case 0: return [pos] - [r].[y] * [axis][1] - [r].[z] * [axis][2] + [d];365 case 1: return [pos] - [r].[y] * [axis][1] + [r].[z] * [axis][2] + [d];366 case 2: return [pos] + [r].[y] * [axis][1] - [r].[z] * [axis][2] + [d];367 case 3: return [pos] + [r].[y] * [axis][1] + [r].[z] * [axis][2] + [d];368 369 case 4: return [pos] - [r].[x] * [axis][0] - [r].[z] * [axis][2] + [d];370 case 5: return [pos] - [r].[x] * [axis][0] + [r].[z] * [axis][2] + [d];371 case 6: return [pos] + [r].[x] * [axis][0] - [r].[z] * [axis][2] + [d];372 case 7: return [pos] + [r].[x] * [axis][0] + [r].[z] * [axis][2] + [d];373 374 case 8: return [pos] - [r].[x] * [axis][0] - [r].[y] * [axis][1] + [d];375 case 9: return [pos] - [r].[x] * [axis][0] + [r].[y] * [axis][1] + [d];376 case 10: return [pos] + [r].[x] * [axis][0] - [r].[y] * [axis][1] + [d];377 case 11: return [pos] + [r].[x] * [axis][0] + [r].[y] * [axis][1] + [d];378 }379 }380 381 vec [OBB::FaceCenterPoint](int faceIndex) const382 {383 [assume](0 <= faceIndex && faceIndex <= 5);384 385 switch(faceIndex)386 {387 default: 388 case 0: return [pos] - [r].[x] * [axis][0];389 case 1: return [pos] + [r].[x] * [axis][0];390 case 2: return [pos] - [r].[y] * [axis][1];391 case 3: return [pos] + [r].[y] * [axis][1];392 case 4: return [pos] - [r].[z] * [axis][2];393 case 5: return [pos] + [r].[z] * [axis][2];394 }395 }396 397 vec [OBB::FacePoint](int faceIndex, float u, float v) const398 {399 [assume](0 <= faceIndex && faceIndex <= 5);400 [assume](0 <= u && u <= 1.f);401 [assume](0 <= v && v <= 1.f);402 403 int uIdx = faceIndex/2;404 int vIdx = (faceIndex/2 + 1) % 3;405 vec U = [axis][uIdx] * (2.f * u - 1.f) * [r][uIdx];406 vec V = [axis][vIdx] * (2.f * v - 1.f) * [r][vIdx];407 switch(faceIndex)408 {409 default: 410 case 0: return [pos] - [r].[z] * [axis][2] + U + V;411 case 1: return [pos] + [r].[z] * [axis][2] + U + V;412 case 2: return [pos] - [r].[x] * [axis][0] + U + V;413 case 3: return [pos] + [r].[x] * [axis][0] + U + V;414 case 4: return [pos] - [r].[y] * [axis][1] + U + V;415 case 5: return [pos] + [r].[y] * [axis][1] + U + V;416 }417 }418 419 [Plane] [OBB::FacePlane](int faceIndex) const420 {421 [assume](0 <= faceIndex && faceIndex <= 5);422 switch(faceIndex)423 {424 default: 425 case 0: return [Plane]([FaceCenterPoint](0), -[axis][0]);426 case 1: return [Plane]([FaceCenterPoint](1), [axis][0]);427 case 2: return [Plane]([FaceCenterPoint](2), -[axis][1]);428 case 3: return [Plane]([FaceCenterPoint](3), [axis][1]);429 case 4: return [Plane]([FaceCenterPoint](4), -[axis][2]);430 case 5: return [Plane]([FaceCenterPoint](5), [axis][2]);431 }432 }433 434 void [OBB::GetCornerPoints](vec *outPointArray) const435 {436 [assume](outPointArray);437 #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS438 if (!outPointArray)439 return;440 #endif441 for(int i = 0; i < 8; ++i)442 outPointArray[i] = [CornerPoint](i);443 }444 445 void [OBB::GetFacePlanes]([Plane] *outPlaneArray) const446 {447 [assume](outPlaneArray);448 #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS449 if (!outPlaneArray)450 return;451 #endif452 for(int i = 0; i < 6; ++i)453 outPlaneArray[i] = [FacePlane](i);454 }455 456 457 void [OBB::ExtremePointsAlongDirection](const vec &dir, const vec *pointArray, int numPoints, int &idxSmallest, int &idxLargest)458 {459 [assume](pointArray || numPoints == 0);460 461 idxSmallest = idxLargest = 0;462 463 #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS464 if (!pointArray)465 return;466 #endif467 468 float smallestD = [FLOAT_INF];469 float largestD = -[FLOAT_INF];470 for(int i = 0; i < numPoints; ++i)471 {472 float d = [Dot](pointArray[i], dir);473 if (d < smallestD)474 {475 smallestD = [d];476 idxSmallest = i;477 }478 if (d > largestD)479 {480 largestD = [d];481 idxLargest = i;482 }483 }484 }485 486 #if 0487 [OBB] OBB::PCAEnclosingOBB(const vec * , int )488 {489 #ifdef _MSC_VER490 #pragma warning(OBB::PCAEnclosingOBB not implemented!)491 #else492 #warning OBB::PCAEnclosingOBB not implemented!493 #endif494 [assume](false && "OBB::PCAEnclosingOBB not implemented!"); 495 return [OBB]();496 }497 #endif498 499 #define LEX_ORDER(x, y) if ((x) < (y)) return -1; else if ((x) > (y)) return 1;500 int [LexFloat3Cmp](const vec &a, const vec &b)501 {502 [LEX_ORDER](a.x, b.x);503 return 0;504 }505 int [LexFloat3CmpV](const void *a, const void *b) { return [LexFloat3Cmp](*(const vec*)a, *(const vec*)b); }506 507 [OBB] [OBB::OptimalEnclosingOBB](const vec *pointArray, int numPoints)508 {509 [OBB] minOBB;510 #ifdef MATH_VEC_IS_FLOAT4511 minOBB.[r].[w] = 0.f;512 #endif513 float minVolume = [FLOAT_INF];514 515 std::vector<float2> pts;516 pts.resize(numPoints);517 518 519 [VecArray] dirs;520 dirs.reserve((numPoints * numPoints-1) / 2);521 for(int i = 0; i < numPoints; ++i)522 for(int j = i+1; j < numPoints; ++j)523 {524 vec edge = pointArray[i]-pointArray[j];525 float oldLength = edge.Normalize();526 if (edge.z < 0.f)527 edge = -edge;528 if (oldLength > 0.f)529 dirs.push_back(edge);530 }531 532 533 #ifdef MATH_CONTAINERLIB_SUPPORT534 sort::QuickSort(&dirs[0], (int)dirs.size(), [LexFloat3Cmp]);535 #else536 qsort(&dirs[0], dirs.size(), sizeof(VecArray::value_type), [LexFloat3CmpV]);537 #endif538 size_t nDistinct = 1;539 for(size_t i = 1; i < dirs.size(); ++i)540 {541 vec d = dirs[i];542 bool removed = false;543 for(size_t j = 0; j < nDistinct; ++j)544 {545 float distX = d.x - dirs[j].x;546 if (distX > 1[e]-3f)547 break;548 if (d.DistanceSq(dirs[j]) < 1[e]-3f)549 {550 removed = true;551 break;552 }553 }554 if (!removed)555 dirs[nDistinct++] = dirs[i];556 }557 if (nDistinct != dirs.size())558 {559 dirs.erase(dirs.begin() + nDistinct, dirs.end());560 561 }562 563 for(size_t i = 0; i < dirs.size(); ++i)564 {565 vec edge = dirs[i];566 567 int e1, [e2];568 [ExtremePointsAlongDirection](edge, pointArray, numPoints, e1, e2);569 float edgeLength = [Abs]([Dot](pointArray[e1] - pointArray[e2], edge));570 571 vec u, v;572 edge.PerpendicularBasis(u, v);573 for(int k = 0; k < numPoints; ++k)574 pts[k] = [float2](pointArray[k].[Dot](u), pointArray[k].[Dot](v));575 576 [float2] rectCenter;577 [float2] uDir;578 [float2] vDir;579 float minU, maxU, minV, maxV;580 float rectArea = [float2::MinAreaRectInPlace](&pts[0], (int)pts.size(), rectCenter, uDir, vDir, minU, maxU, minV, maxV);581 float volume = rectArea * edgeLength;582 583 if (volume < minVolume)584 {585 [float2] c10 = (maxV - minV) * vDir;586 [float2] c20 = (maxU - minU) * uDir;587 [float2] center = 0.5f * (uDir * (minU+maxU) + vDir * (minV+maxV));588 vec C1 = c10.[x]*u + c10.[y]*v;589 vec C2 = c20.[x]*u + c20.[y]*v;590 minOBB.[axis][0] = edge;591 vec rectCenterPos = vec([POINT_VEC_SCALAR](0.f)) + center.[x]*u + center.[y]*v;592 minOBB.[pos] = [Dot](pointArray[e1]+pointArray[e2], edge) * 0.5f * edge + rectCenterPos;593 minOBB.[r][0] = edgeLength * 0.5f;594 minOBB.[r][1] = C1.[Normalize]()*0.5f;595 minOBB.[r][2] = C2.[Normalize]()*0.5f;596 minOBB.[axis][1] = C1;597 minOBB.[axis][2] = C2;598 minVolume = volume;599 }600 }601 602 return minOBB;603 }604 605 vec [OBB::Size]() const606 {607 return [r] * 2.f;608 }609 610 vec [OBB::HalfSize]() const611 {612 return [r];613 }614 615 vec [OBB::Diagonal]() const616 {617 return 2.f * [HalfDiagonal]();618 }619 620 vec [OBB::HalfDiagonal]() const621 {622 return [axis][0] * [r][0] + [axis][1] * [r][1] + [axis][2] * [r][2];623 }624 625 [float3x4] [OBB::WorldToLocal]() const626 {627 [float3x4] m = [LocalToWorld]();628 m.[InverseOrthonormal]();629 return m;630 }631 632 [float3x4] [OBB::LocalToWorld]() const633 {634 635 636 637 638 639 640 641 642 643 644 645 646 647 [assume2]([axis][0].IsNormalized(), [axis][0], [axis][0].LengthSq());648 [assume2]([axis][1].IsNormalized(), [axis][1], [axis][1].LengthSq());649 [assume2]([axis][2].IsNormalized(), [axis][2], [axis][2].LengthSq());650 [float3x4] m; 651 m.[SetCol](0, [axis][0].ptr());652 m.[SetCol](1, [axis][1].ptr());653 m.[SetCol](2, [axis][2].ptr());654 vec p = [pos] - [axis][0] * [r].[x] - [axis][1] * [r].[y] - [axis][2] * [r].[z];655 m.[SetCol](3, p.ptr());656 [assume](m.[IsOrthonormal]());657 return m;658 }659 660 661 vec [OBB::ClosestPoint](const vec &targetPoint) const662 {663 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)664 665 simd4f d = sub_ps(targetPoint.v, [pos].v);666 simd4f x = xxxx_ps([r].v);667 simd4f closestPoint = [pos].v;668 closestPoint = add_ps(closestPoint, mul_ps(max_ps(min_ps(dot4_ps(d, [axis][0].v), x), negate_ps(x)), [axis][0].v));669 simd4f y = yyyy_ps([r].v);670 closestPoint = add_ps(closestPoint, mul_ps(max_ps(min_ps(dot4_ps(d, [axis][1].v), y), negate_ps(y)), [axis][1].v));671 simd4f z = zzzz_ps([r].v);672 closestPoint = add_ps(closestPoint, mul_ps(max_ps(min_ps(dot4_ps(d, [axis][2].v), z), negate_ps(z)), [axis][2].v));673 return closestPoint;674 #else675 676 vec d = targetPoint - [pos];677 vec closestPoint = [pos]; 678 for(int i = 0; i < 3; ++i) 679 closestPoint += [Clamp]([Dot](d, [axis][i]), -[r][i], [r][i]) * [axis][i];680 681 return closestPoint;682 #endif683 }684 685 float [OBB::Volume]() const686 {687 return [Size]().[ProductOfElements]();688 }689 690 float [OBB::SurfaceArea]() const691 {692 const vec size = [Size]();693 return 2.f * (size.x*size.y + size.x*size.z + size.y*size.z);694 }695 696 vec [OBB::RandomPointInside]([LCG] &rng) const697 {698 float f1 = rng.[Float]();699 float f2 = rng.[Float]();700 float f3 = rng.[Float]();701 return [PointInside](f1, f2, f3);702 }703 704 vec [OBB::RandomPointOnSurface]([LCG] &rng) const705 {706 int i = rng.[Int](0, 5);707 float f1 = rng.[Float]();708 float f2 = rng.[Float]();709 return [FacePoint](i, f1, f2);710 }711 712 vec [OBB::RandomPointOnEdge]([LCG] &rng) const713 {714 int i = rng.[Int](0, 11);715 float f = rng.[Float]();716 return [PointOnEdge](i, f);717 }718 719 vec [OBB::RandomCornerPoint]([LCG] &rng) const720 {721 return [CornerPoint](rng.[Int](0, 7));722 }723 724 void [OBB::Translate](const vec &offset)725 {726 pos += offset;727 }728 729 void [OBB::Scale](const vec ¢erPoint, float scaleFactor)730 {731 return [Scale](centerPoint, [DIR_VEC_SCALAR](scaleFactor));732 }733 734 void [OBB::Scale](const vec ¢erPoint, const vec &scaleFactor)735 {736 737 [float3x4] transform = [float3x4::Scale](scaleFactor, centerPoint);738 [Transform](transform);739 }740 741 template<typename Matrix>742 void [OBBTransform]([OBB] &o, const Matrix &transform)743 {744 o.[pos] = transform.MulPos(o.[pos]);745 o.[axis][0] = transform.MulDir(o.[r].[x] * o.[axis][0]);746 o.[axis][1] = transform.MulDir(o.[r].[y] * o.[axis][1]);747 o.[axis][2] = transform.MulDir(o.[r].[z] * o.[axis][2]);748 o.[r].[x] = o.[axis][0].[Normalize]();749 o.[r].[y] = o.[axis][1].[Normalize]();750 o.[r].[z] = o.[axis][2].[Normalize]();751 }752 753 void [OBB::Transform](const [float3x3] &transform)754 {755 [assume](transform.[IsColOrthogonal]());756 [OBBTransform](*this, transform);757 }758 759 void [OBB::Transform](const [float3x4] &transform)760 {761 [assume](transform.[IsColOrthogonal]());762 [OBBTransform](*this, transform);763 }764 765 void [OBB::Transform](const [float4x4] &transform)766 {767 [assume](transform.[IsColOrthogonal3]());768 [OBBTransform](*this, transform);769 }770 771 void [OBB::Transform](const [Quat] &transform)772 {773 [OBBTransform](*this, transform.[ToFloat3x3]());774 }775 776 float [OBB::Distance](const vec &point) const777 {778 779 780 vec closestPoint = [ClosestPoint](point);781 return point.Distance(closestPoint);782 }783 784 float [OBB::Distance](const [Sphere] &sphere) const785 {786 return [Max](0.f, [Distance](sphere.[pos]) - sphere.[r]);787 }788 789 bool [OBB::Contains](const vec &point) const790 {791 #if defined(MATH_SSE) && defined(MATH_AUTOMATIC_SSE)792 793 simd4f pt = sub_ps(point.v, pos.v);794 simd4f s1 = mul_ps(pt, [axis][0].v);795 simd4f s2 = mul_ps(pt, [axis][1].v);796 simd4f s3 = mul_ps(pt, [axis][2].v);797 s1 = abs_ps(sum_xyzw_ps(s1));798 s2 = abs_ps(sum_xyzw_ps(s2));799 s3 = abs_ps(sum_xyzw_ps(s3));800 801 s1 = _mm_sub_ss(s1, [r].v);802 s2 = _mm_sub_ss(s2, yyyy_ps([r].v));803 simd4f s12 = _mm_max_ss(s1, s2);804 s3 = _mm_sub_ss(s3, zzzz_ps([r].v));805 s3 = _mm_max_ss(s12, s3);806 return _mm_cvtss_f32(s3) <= 0.f; 807 #else808 809 vec pt = point - [pos];810 return [Abs]([Dot](pt, [axis][0])) <= [r][0] &&811 [Abs]([Dot](pt, [axis][1])) <= [r][1] &&812 [Abs]([Dot](pt, [axis][2])) <= [r][2];813 #endif814 }815 816 bool [OBB::Contains](const [LineSegment] &lineSegment) const817 {818 return [Contains](lineSegment.[a]) && [Contains](lineSegment.[b]);819 }820 821 bool [OBB::Contains](const [AABB] &aabb) const822 {823 824 825 for(int i = 0; i < 8; ++i)826 if (![Contains](aabb.[CornerPoint](i)))827 return false;828 829 return true;830 }831 832 bool [OBB::Contains](const [OBB] &obb) const833 {834 for(int i = 0; i < 8; ++i)835 if (![Contains](obb.[CornerPoint](i)))836 return false;837 838 return true;839 }840 841 bool [OBB::Contains](const [Triangle] &triangle) const842 {843 return [Contains](triangle.[a]) && [Contains](triangle.[b]) && [Contains](triangle.[c]);844 }845 846 bool [OBB::Contains](const [Polygon] &polygon) const847 {848 for(int i = 0; i < polygon.[NumVertices](); ++i)849 if (![Contains](polygon.[Vertex](i)))850 return false;851 return true;852 }853 854 bool [OBB::Contains](const [Frustum] &frustum) const855 {856 for(int i = 0; i < 8; ++i)857 if (![Contains](frustum.[CornerPoint](i)))858 return false;859 860 return true;861 }862 863 bool [OBB::Contains](const [Polyhedron] &polyhedron) const864 {865 [assume](polyhedron.[IsClosed]());866 for(int i = 0; i < polyhedron.[NumVertices](); ++i)867 if (![Contains](polyhedron.[Vertex](i)))868 return false;869 870 return true;871 }872 873 bool [OBB::Intersects](const [AABB] &aabb) const874 {875 return [Intersects]([OBB](aabb));876 }877 878 void [OBB::Enclose](const vec &point)879 {880 vec p = point - [pos];881 for(int i = 0; i < 3; ++i)882 {883 [assume2]([EqualAbs]([axis][i].[Length](), 1.f), [axis][i], [axis][i].[Length]());884 float dist = p.Dot([axis][i]);885 float distanceFromOBB = [Abs](dist) - [r][i];886 if (distanceFromOBB > 0.f)887 {888 [r][i] += distanceFromOBB * 0.5f;889 if (dist > 0.f) 890 pos += [axis][i] * distanceFromOBB * 0.5f;891 else892 pos -= [axis][i] * distanceFromOBB * 0.5f;893 894 p = point-[pos]; 895 896 [mathassert]([EqualAbs]([Abs](p.Dot([axis][i])), [r][i], 1[e]-1f));897 }898 }899 900 [assume2]([Distance](point) <= 1[e]-3f, point, [Distance](point));901 }902 903 void [OBB::Triangulate](int x, int y, int z, vec *outPos, vec *outNormal, [float2] *outUV, bool ccwIsFrontFacing) const904 {905 [AABB] aabb([POINT_VEC_SCALAR](0), [r]*2.f);906 aabb.[Triangulate](x, y, z, outPos, outNormal, outUV, ccwIsFrontFacing);907 [float3x4] localToWorld = [LocalToWorld]();908 [assume](localToWorld.[HasUnitaryScale]()); 909 localToWorld.[BatchTransformPos](outPos, [NumVerticesInTriangulation](x,y,z), sizeof(vec));910 localToWorld.[BatchTransformDir](outNormal, [NumVerticesInTriangulation](x,y,z), sizeof(vec));911 }912 913 void [OBB::ToEdgeList](vec *outPos) const914 {915 [assume](outPos);916 if (!outPos)917 return;918 for(int i = 0; i < 12; ++i)919 {920 [LineSegment] edge = [Edge](i);921 outPos[i*2] = edge.[a];922 outPos[i*2+1] = edge.[b];923 }924 }925 926 bool [OBB::Intersects](const [OBB] &b, float [epsilon]) const927 {928 [assume](pos.IsFinite());929 [assume](b.[pos].[IsFinite]());930 [assume](vec::AreOrthogonal([axis][0], [axis][1], [axis][2]));931 [assume](vec::AreOrthogonal(b.[axis][0], b.[axis][1], b.[axis][2]));932 933 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)934 935 936 937 938 939 940 simd4f bLocalToWorld[3];941 mat3x4_transpose((const simd4f*)b.[axis], bLocalToWorld);942 943 944 simd4f R[3];945 mat3x4_mul_sse(R, (const simd4f*)[axis], bLocalToWorld);946 947 948 simd4f t = mat3x4_mul_sse((const simd4f*)[axis], sub_ps(b.[pos], pos));949 950 951 952 const vec epsilonxyz = set1_ps(epsilon);953 simd4f AbsR[3];954 AbsR[0] = add_ps(abs_ps(R[0]), epsilonxyz);955 AbsR[1] = add_ps(abs_ps(R[1]), epsilonxyz);956 AbsR[2] = add_ps(abs_ps(R[2]), epsilonxyz);957 958 959 simd4f res = cmpgt_ps(abs_ps(t), add_ps([r], mat3x4_mul_sse(AbsR, b.[r])));960 if (!allzero_ps(res)) return false;961 962 963 simd4f transpR[3];964 mat3x4_transpose(R, transpR);965 vec l = abs_ps(mat3x4_mul_sse(transpR, [r]));966 simd4f transpAbsR[3];967 mat3x4_transpose(AbsR, transpAbsR);968 vec s = mat3x4_mul_sse(transpAbsR, [r]);969 res = cmpgt_ps(l, add_ps(s, b.[r]));970 if (!allzero_ps(res)) return false;971 972 973 974 975 976 977 simd4f ra = mul_ps(shuffle1_ps([r], _MM_SHUFFLE(3,1,1,1)), AbsR[2]);978 ra = add_ps(ra, mul_ps(shuffle1_ps([r], _MM_SHUFFLE(3,2,2,2)), AbsR[1]));979 simd4f rb = mul_ps(shuffle1_ps(b.[r], _MM_SHUFFLE(3,0,0,1)), shuffle1_ps(AbsR[0], _MM_SHUFFLE(3,1,2,2)));980 rb = add_ps(rb, mul_ps(shuffle1_ps(b.[r], _MM_SHUFFLE(3,1,2,2)), shuffle1_ps(AbsR[0], _MM_SHUFFLE(3,0,0,1))));981 simd4f lhs = mul_ps(shuffle1_ps(t, _MM_SHUFFLE(3,2,2,2)), R[1]);982 lhs = sub_ps(lhs, mul_ps(shuffle1_ps(t, _MM_SHUFFLE(3,1,1,1)), R[2]));983 res = cmpgt_ps(abs_ps(lhs), add_ps(ra, rb));984 if (!allzero_ps(res)) return false;985 986 987 988 989 ra = mul_ps(shuffle1_ps([r], _MM_SHUFFLE(3,0,0,0)), AbsR[2]);990 ra = add_ps(ra, mul_ps(shuffle1_ps([r], _MM_SHUFFLE(3,2,2,2)), AbsR[0]));991 rb = mul_ps(shuffle1_ps(b.[r], _MM_SHUFFLE(3,0,0,1)), shuffle1_ps(AbsR[1], _MM_SHUFFLE(3,1,2,2)));992 rb = add_ps(rb, mul_ps(shuffle1_ps(b.[r], _MM_SHUFFLE(3,1,2,2)), shuffle1_ps(AbsR[1], _MM_SHUFFLE(3,0,0,1))));993 lhs = mul_ps(shuffle1_ps(t, _MM_SHUFFLE(3,0,0,0)), R[2]);994 lhs = sub_ps(lhs, mul_ps(shuffle1_ps(t, _MM_SHUFFLE(3,2,2,2)), R[0]));995 res = cmpgt_ps(abs_ps(lhs), add_ps(ra, rb));996 if (!allzero_ps(res)) return false;997 998 999 1000 1001 ra = mul_ps(shuffle1_ps([r], _MM_SHUFFLE(3,0,0,0)), AbsR[1]);1002 ra = add_ps(ra, mul_ps(shuffle1_ps([r], _MM_SHUFFLE(3,1,1,1)), AbsR[0]));1003 rb = mul_ps(shuffle1_ps(b.[r], _MM_SHUFFLE(3,0,0,1)), shuffle1_ps(AbsR[2], _MM_SHUFFLE(3,1,2,2)));1004 rb = add_ps(rb, mul_ps(shuffle1_ps(b.[r], _MM_SHUFFLE(3,1,2,2)), shuffle1_ps(AbsR[2], _MM_SHUFFLE(3,0,0,1))));1005 lhs = mul_ps(shuffle1_ps(t, _MM_SHUFFLE(3,1,1,1)), R[0]);1006 lhs = sub_ps(lhs, mul_ps(shuffle1_ps(t, _MM_SHUFFLE(3,0,0,0)), R[1]));1007 res = cmpgt_ps(abs_ps(lhs), add_ps(ra, rb));1008 return allzero_ps(res) != 0;1009 1010 #else1011 1012 1013 1014 1015 1016 1017 [float3x3] R;1018 for(int i = 0; i < 3; ++i)1019 for(int j = 0; j < 3; ++j)1020 R[i][j] = [Dot]([axis][i], b.[axis][j]);1021 1022 vec t = b.[pos] - [pos];1023 1024 t = [DIR_VEC]([Dot](t, [axis][0]), [Dot](t, [axis][1]), [Dot](t, [axis][2]));1025 1026 [float3x3] AbsR;1027 for(int i = 0; i < 3; ++i)1028 for(int j = 0; j < 3; ++j)1029 AbsR[i][j] = [Abs](R[i][j]) + [epsilon];1030 1031 1032 for(int i = 0; i < 3; ++i)1033 {1034 float ra = [r][i];1035 float rb = [DOT3](b.[r], AbsR[i]);1036 if ([Abs](t[i]) > ra + rb)1037 return false;1038 }1039 1040 1041 for(int i = 0; i < 3; ++i)1042 {1043 float ra = [r][0] * AbsR[0][i] + [r][1] * AbsR[1][i] + [r][2] * AbsR[2][i];1044 float rb = b.[r][i];1045 if ([Abs](t.x * R[0][i] + t.y * R[1][i] + t.z * R[2][i]) > ra + rb)1046 return false;1047 }1048 1049 1050 1051 1052 float ra = [r].[y] * AbsR[2][0] + [r].[z] * AbsR[1][0];1053 float rb = b.[r].[y] * AbsR[0][2] + b.[r].[z] * AbsR[0][1];1054 if ([Abs](t.z * R[1][0] - t.y * R[2][0]) > ra + rb)1055 return false;1056 1057 1058 ra = [r].[y] * AbsR[2][1] + [r].[z] * AbsR[1][1];1059 rb = b.[r].[x] * AbsR[0][2] + b.[r].[z] * AbsR[0][0];1060 if ([Abs](t.z * R[1][1] - t.y * R[2][1]) > ra + rb)1061 return false;1062 1063 1064 ra = [r].[y] * AbsR[2][2] + [r].[z] * AbsR[1][2];1065 rb = b.[r].[x] * AbsR[0][1] + b.[r].[y] * AbsR[0][0];1066 if ([Abs](t.z * R[1][2] - t.y * R[2][2]) > ra + rb)1067 return false;1068 1069 1070 ra = [r].[x] * AbsR[2][0] + [r].[z] * AbsR[0][0];1071 rb = b.[r].[y] * AbsR[1][2] + b.[r].[z] * AbsR[1][1];1072 if ([Abs](t.x * R[2][0] - t.z * R[0][0]) > ra + rb)1073 return false;1074 1075 1076 ra = [r].[x] * AbsR[2][1] + [r].[z] * AbsR[0][1];1077 rb = b.[r].[x] * AbsR[1][2] + b.[r].[z] * AbsR[1][0];1078 if ([Abs](t.x * R[2][1] - t.z * R[0][1]) > ra + rb)1079 return false;1080 1081 1082 ra = [r].[x] * AbsR[2][2] + [r].[z] * AbsR[0][2];1083 rb = b.[r].[x] * AbsR[1][1] + b.[r].[y] * AbsR[1][0];1084 if ([Abs](t.x * R[2][2] - t.z * R[0][2]) > ra + rb)1085 return false;1086 1087 1088 ra = [r].[x] * AbsR[1][0] + [r].[y] * AbsR[0][0];1089 rb = b.[r].[y] * AbsR[2][2] + b.[r].[z] * AbsR[2][1];1090 if ([Abs](t.y * R[0][0] - t.x * R[1][0]) > ra + rb)1091 return false;1092 1093 1094 ra = [r].[x] * AbsR[1][1] + [r].[y] * AbsR[0][1];1095 rb = b.[r].[x] * AbsR[2][2] + b.[r].[z] * AbsR[2][0];1096 if ([Abs](t.y * R[0][1] - t.x * R[1][1]) > ra + rb)1097 return false;1098 1099 1100 ra = [r].[x] * AbsR[1][2] + [r].[y] * AbsR[0][2];1101 rb = b.[r].[x] * AbsR[2][1] + b.[r].[y] * AbsR[2][0];1102 if ([Abs](t.y * R[0][2] - t.x * R[1][2]) > ra + rb)1103 return false;1104 1105 1106 return true;1107 #endif1108 }1109 1110 1111 bool [OBB::Intersects](const [Plane] &p) const1112 {1113 1114 float t = [r][0] * [Abs]([Dot](p.[normal], [axis][0])) +1115 [r][1] * [Abs]([Dot](p.[normal], [axis][1])) +1116 [r][2] * [Abs]([Dot](p.[normal], [axis][2]));1117 1118 float s = [Dot](p.[normal], pos) - p.[d];1119 return [Abs](s) <= t;1120 }1121 1122 bool [OBB::Intersects](const [Ray] &ray) const1123 {1124 [AABB] aabb([POINT_VEC_SCALAR](0.f), [Size]());1125 [Ray] [r] = [WorldToLocal]() * ray;1126 return aabb.[Intersects](r);1127 }1128 1129 bool [OBB::Intersects](const [Ray] &ray, float &dNear, float &dFar) const1130 {1131 [AABB] aabb([POINT_VEC_SCALAR](0.f), [Size]());1132 [Ray] r = [WorldToLocal]() * ray;1133 return aabb.[Intersects](r, dNear, dFar);1134 }1135 1136 bool [OBB::Intersects](const [Line] &line) const1137 {1138 [AABB] aabb([POINT_VEC_SCALAR](0.f), [Size]());1139 [Line] l = [WorldToLocal]() * line;1140 return aabb.[Intersects](l);1141 }1142 1143 bool [OBB::Intersects](const [Line] &line, float &dNear, float &dFar) const1144 {1145 [AABB] aabb([POINT_VEC_SCALAR](0.f), [Size]());1146 [Line] l = [WorldToLocal]() * line;1147 return aabb.[Intersects](l, dNear, dFar);1148 }1149 1150 bool [OBB::Intersects](const [LineSegment] &lineSegment) const1151 {1152 [AABB] aabb([POINT_VEC_SCALAR](0.f), [Size]());1153 [LineSegment] l = [WorldToLocal]() * lineSegment;1154 return aabb.[Intersects](l);1155 }1156 1157 bool [OBB::Intersects](const [LineSegment] &lineSegment, float &dNear, float &dFar) const1158 {1159 [AABB] aabb([POINT_VEC_SCALAR](0.f), [Size]());1160 [LineSegment] l = [WorldToLocal]() * lineSegment;1161 return aabb.[Intersects](l, dNear, dFar);1162 }1163 1164 1165 bool [OBB::Intersects](const [Sphere] &sphere, vec *closestPointOnOBB) const1166 {1167 1168 vec pt = [ClosestPoint](sphere.[pos]);1169 1170 1171 if (closestPointOnOBB)1172 *closestPointOnOBB = pt;1173 1174 return pt.DistanceSq(sphere.[pos]) <= sphere.[r] * sphere.[r];1175 }1176 1177 bool [OBB::Intersects](const [Capsule] &capsule) const1178 {1179 return capsule.[Intersects](*this);1180 }1181 1182 bool [OBB::Intersects](const [Triangle] &triangle) const1183 {1184 [AABB] aabb([POINT_VEC_SCALAR](0.f), [Size]());1185 [Triangle] t = [WorldToLocal]() * triangle;1186 return t.[Intersects](aabb);1187 }1188 1189 bool [OBB::Intersects](const [Polygon] &polygon) const1190 {1191 return polygon.[Intersects](*this);1192 }1193 1194 bool [OBB::Intersects](const [Frustum] &frustum) const1195 {1196 return frustum.[Intersects](*this);1197 }1198 1199 bool [OBB::Intersects](const [Polyhedron] &polyhedron) const1200 {1201 return polyhedron.[Intersects](*this);1202 }1203 1204 #ifdef MATH_ENABLE_STL_SUPPORT1205 std::string [OBB::ToString]() const1206 {1207 char str[256];1208 sprintf(str, "OBB(Pos:(%.2f, %.2f, %.2f) Halfsize:(%.2f, %.2f, %.2f) X:(%.2f, %.2f, %.2f) Y:(%.2f, %.2f, %.2f) Z:(%.2f, %.2f, %.2f))",1209 pos.x, pos.y, pos.z, r.x, r.y, r.z, [axis][0].[x], [axis][0].[y], [axis][0].[z], [axis][1].[x], [axis][1].[y], [axis][1].[z], [axis][2].[x], [axis][2].[y], [axis][2].[z]);1210 return str;1211 }1212 1213 std::string [OBB::SerializeToString]() const1214 {1215 std::string s = pos.xyz().SerializeToString() + " "1216 + r.xyz().[SerializeToString]() + " "1217 + [axis][0].[xyz]().[SerializeToString]() + " "1218 + [axis][1].[xyz]().[SerializeToString]() + " "1219 + [axis][2].[xyz]().[SerializeToString]();1220 return s;1221 }1222 1223 std::string [OBB::SerializeToCodeString]() const1224 {1225 return "OBB(" + pos.SerializeToCodeString() + ","1226 + r.[SerializeToCodeString]() + ","1227 + [axis][0].[SerializeToCodeString]() + ","1228 + [axis][1].[SerializeToCodeString]() + ","1229 + [axis][2].[SerializeToCodeString]() + ")";1230 }1231 1232 std::ostream &[operator <<](std::ostream &o, const [OBB] &obb)1233 {1234 o << obb.[ToString]();1235 return o;1236 }1237 1238 #endif1239 1240 [OBB] [OBB::FromString](const char *str, const char **outEndStr)1241 {1242 [assume](str);1243 if (!str)1244 return [OBB]([vec::nan], [vec::nan], [vec::nan], [vec::nan], [vec::nan]);1245 [OBB] o;1246 [MATH_SKIP_WORD](str, "OBB(");1247 [MATH_SKIP_WORD](str, "Pos:(");1248 o.[pos] = [PointVecFromString](str, &str);1249 [MATH_SKIP_WORD](str, " Halfsize:(");1250 o.[r] = [DirVecFromString](str, &str);1251 [MATH_SKIP_WORD](str, " X:(");1252 o.[axis][0] = [DirVecFromString](str, &str);1253 [MATH_SKIP_WORD](str, " Y:(");1254 o.[axis][1] = [DirVecFromString](str, &str);1255 [MATH_SKIP_WORD](str, " Z:(");1256 o.[axis][2] = [DirVecFromString](str, &str);1257 if (outEndStr)1258 *outEndStr = str;1259 return o;1260 }1261 1262 #ifdef MATH_GRAPHICSENGINE_INTEROP1263 void [OBB::Triangulate](VertexBuffer &vb, int x, int y, int z, bool ccwIsFrontFacing) const1264 {1265 Array<vec> [pos];1266 Array<vec> normal;1267 Array<float2> uv;1268 int numVertices = (x*y+y*z+x*z)*2*6;1269 pos.Resize_pod(numVertices);1270 normal.Resize_pod(numVertices);1271 uv.Resize_pod(numVertices);1272 [Triangulate](x,y,z, &pos[0], &normal[0], &uv[0], ccwIsFrontFacing);1273 int startIndex = vb.AppendVertices(numVertices);1274 for(int i = 0; i < (int)pos.size(); ++i)1275 {1276 vb.Set(startIndex+i, VDPosition, [POINT_TO_FLOAT4](pos[i]));1277 if (vb.Declaration()->TypeOffset(VDNormal) >= 0)1278 vb.Set(startIndex+i, VDNormal, [DIR_TO_FLOAT4](normal[i]));1279 if (vb.Declaration()->TypeOffset(VDUV) >= 0)1280 vb.SetFloat2(startIndex+i, VDUV, 0, uv[i]);1281 }1282 }1283 1284 void OBB::ToLineList(VertexBuffer &vb) const1285 {1286 Array<vec> [pos];1287 pos.Resize_pod([NumVerticesInEdgeList]());1288 [ToEdgeList](&pos[0]);1289 int startIndex = vb.AppendVertices((int)pos.size());1290 for(int i = 0; i < (int)pos.size(); ++i)1291 vb.Set(startIndex+i, VDPosition, [POINT_TO_FLOAT4](pos[i]));1292 }1293 1294 #endif1295 1296 [OBB] [operator *](const [float3x3] &transform, const [OBB] &obb)1297 {1298 [OBB] o(obb);1299 o.[Transform](transform);1300 return o;1301 }1302 1303 [OBB] [operator *](const [float3x4] &transform, const [OBB] &obb)1304 {1305 [OBB] o(obb);1306 o.[Transform](transform);1307 return o;1308 }1309 1310 [OBB] [operator *](const [float4x4] &transform, const [OBB] &obb)1311 {1312 [OBB] o(obb);1313 o.[Transform](transform);1314 return o;1315 }1316 1317 [OBB] [operator *](const [Quat] &transform, const [OBB] &obb)1318 {1319 [OBB] o(obb);1320 o.[Transform](transform);1321 return o;1322 }1323 1324 [MATH_END_NAMESPACE] Go back to previous page