diff options
Diffstat (limited to '3rdparty/bx/src')
-rw-r--r-- | 3rdparty/bx/src/allocator.cpp | 11 | ||||
-rw-r--r-- | 3rdparty/bx/src/amalgamated.cpp | 5 | ||||
-rw-r--r-- | 3rdparty/bx/src/bounds.cpp | 2039 | ||||
-rw-r--r-- | 3rdparty/bx/src/bx.cpp | 94 | ||||
-rw-r--r-- | 3rdparty/bx/src/bx_p.h | 45 | ||||
-rw-r--r-- | 3rdparty/bx/src/commandline.cpp | 9 | ||||
-rw-r--r-- | 3rdparty/bx/src/crtnone.cpp | 26 | ||||
-rw-r--r-- | 3rdparty/bx/src/debug.cpp | 24 | ||||
-rw-r--r-- | 3rdparty/bx/src/dtoa.cpp | 13 | ||||
-rw-r--r-- | 3rdparty/bx/src/easing.cpp | 5 | ||||
-rw-r--r-- | 3rdparty/bx/src/file.cpp | 462 | ||||
-rw-r--r-- | 3rdparty/bx/src/filepath.cpp | 206 | ||||
-rw-r--r-- | 3rdparty/bx/src/hash.cpp | 125 | ||||
-rw-r--r-- | 3rdparty/bx/src/math.cpp | 392 | ||||
-rw-r--r-- | 3rdparty/bx/src/mutex.cpp | 43 | ||||
-rw-r--r-- | 3rdparty/bx/src/os.cpp | 76 | ||||
-rw-r--r-- | 3rdparty/bx/src/process.cpp | 39 | ||||
-rw-r--r-- | 3rdparty/bx/src/semaphore.cpp | 30 | ||||
-rw-r--r-- | 3rdparty/bx/src/settings.cpp | 5 | ||||
-rw-r--r-- | 3rdparty/bx/src/sort.cpp | 124 | ||||
-rw-r--r-- | 3rdparty/bx/src/string.cpp | 302 | ||||
-rw-r--r-- | 3rdparty/bx/src/thread.cpp | 156 | ||||
-rw-r--r-- | 3rdparty/bx/src/timer.cpp | 10 | ||||
-rw-r--r-- | 3rdparty/bx/src/url.cpp | 3 |
24 files changed, 3403 insertions, 841 deletions
diff --git a/3rdparty/bx/src/allocator.cpp b/3rdparty/bx/src/allocator.cpp index c26677edb25..203631f6009 100644 --- a/3rdparty/bx/src/allocator.cpp +++ b/3rdparty/bx/src/allocator.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/allocator.h> #include <malloc.h> @@ -38,7 +37,7 @@ namespace bx BX_UNUSED(_file, _line); _aligned_free(_ptr); # else - bx::alignedFree(this, _ptr, _align, _file, _line); + alignedFree(this, _ptr, _align, _file, _line); # endif // BX_ } @@ -55,7 +54,7 @@ namespace bx BX_UNUSED(_file, _line); return _aligned_malloc(_size, _align); # else - return bx::alignedAlloc(this, _size, _align, _file, _line); + return alignedAlloc(this, _size, _align, _file, _line); # endif // BX_ } @@ -68,7 +67,7 @@ namespace bx BX_UNUSED(_file, _line); return _aligned_realloc(_ptr, _size, _align); # else - return bx::alignedRealloc(this, _ptr, _size, _align, _file, _line); + return alignedRealloc(this, _ptr, _size, _align, _file, _line); # endif // BX_ } diff --git a/3rdparty/bx/src/amalgamated.cpp b/3rdparty/bx/src/amalgamated.cpp index d3f896b1416..037418a5717 100644 --- a/3rdparty/bx/src/amalgamated.cpp +++ b/3rdparty/bx/src/amalgamated.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ #include "allocator.cpp" +#include "bounds.cpp" #include "bx.cpp" #include "commandline.cpp" #include "crtnone.cpp" diff --git a/3rdparty/bx/src/bounds.cpp b/3rdparty/bx/src/bounds.cpp new file mode 100644 index 00000000000..d7068fe42b0 --- /dev/null +++ b/3rdparty/bx/src/bounds.cpp @@ -0,0 +1,2039 @@ +/* + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include <bx/rng.h> +#include <bx/math.h> +#include <bx/bounds.h> + +namespace bx +{ + Vec3 getCenter(const Aabb& _aabb) + { + return mul(add(_aabb.min, _aabb.max), 0.5f); + } + + Vec3 getExtents(const Aabb& _aabb) + { + return mul(sub(_aabb.max, _aabb.min), 0.5f); + } + + Vec3 getCenter(const Triangle& _triangle) + { + return mul(add(add(_triangle.v0, _triangle.v1), _triangle.v2), 1.0f/3.0f); + } + + void toAabb(Aabb& _outAabb, const Vec3& _extents) + { + _outAabb.min = neg(_extents); + _outAabb.max = _extents; + } + + void toAabb(Aabb& _outAabb, const Vec3& _center, const Vec3& _extents) + { + _outAabb.min = sub(_center, _extents); + _outAabb.max = add(_center, _extents); + } + + void toAabb(Aabb& _outAabb, const Cylinder& _cylinder) + { + // Reference(s): + // - https://web.archive.org/web/20181113055756/http://iquilezles.org/www/articles/diskbbox/diskbbox.htm + // + const Vec3 axis = sub(_cylinder.end, _cylinder.pos); + const Vec3 asq = mul(axis, axis); + const Vec3 nsq = mul(asq, 1.0f/dot(axis, axis) ); + const Vec3 tmp = sub(Vec3(1.0f), nsq); + + const float inv = 1.0f/(tmp.x*tmp.y*tmp.z); + + const Vec3 extent = + { + _cylinder.radius * tmp.x * sqrt( (nsq.x + nsq.y * nsq.z) * inv), + _cylinder.radius * tmp.y * sqrt( (nsq.y + nsq.z * nsq.x) * inv), + _cylinder.radius * tmp.z * sqrt( (nsq.z + nsq.x * nsq.y) * inv), + }; + + const Vec3 minP = sub(_cylinder.pos, extent); + const Vec3 minE = sub(_cylinder.end, extent); + const Vec3 maxP = add(_cylinder.pos, extent); + const Vec3 maxE = add(_cylinder.end, extent); + + _outAabb.min = min(minP, minE); + _outAabb.max = max(maxP, maxE); + } + + void toAabb(Aabb& _outAabb, const Disk& _disk) + { + // Reference(s): + // - https://web.archive.org/web/20181113055756/http://iquilezles.org/www/articles/diskbbox/diskbbox.htm + // + const Vec3 nsq = mul(_disk.normal, _disk.normal); + const Vec3 one = { 1.0f, 1.0f, 1.0f }; + const Vec3 tmp = sub(one, nsq); + const float inv = 1.0f / (tmp.x*tmp.y*tmp.z); + + const Vec3 extent = + { + _disk.radius * tmp.x * sqrt( (nsq.x + nsq.y * nsq.z) * inv), + _disk.radius * tmp.y * sqrt( (nsq.y + nsq.z * nsq.x) * inv), + _disk.radius * tmp.z * sqrt( (nsq.z + nsq.x * nsq.y) * inv), + }; + + _outAabb.min = sub(_disk.center, extent); + _outAabb.max = add(_disk.center, extent); + } + + void toAabb(Aabb& _outAabb, const Obb& _obb) + { + Vec3 xyz = { 1.0f, 1.0f, 1.0f }; + Vec3 tmp = mul(xyz, _obb.mtx); + + _outAabb.min = tmp; + _outAabb.max = tmp; + + for (uint32_t ii = 1; ii < 8; ++ii) + { + xyz.x = ii & 1 ? -1.0f : 1.0f; + xyz.y = ii & 2 ? -1.0f : 1.0f; + xyz.z = ii & 4 ? -1.0f : 1.0f; + tmp = mul(xyz, _obb.mtx); + + _outAabb.min = min(_outAabb.min, tmp); + _outAabb.max = max(_outAabb.max, tmp); + } + } + + void toAabb(Aabb& _outAabb, const Sphere& _sphere) + { + const float radius = _sphere.radius; + _outAabb.min = sub(_sphere.center, radius); + _outAabb.max = add(_sphere.center, radius); + } + + void toAabb(Aabb& _outAabb, const Triangle& _triangle) + { + _outAabb.min = min(_triangle.v0, _triangle.v1, _triangle.v2); + _outAabb.max = max(_triangle.v0, _triangle.v1, _triangle.v2); + } + + void aabbTransformToObb(Obb& _obb, const Aabb& _aabb, const float* _mtx) + { + toObb(_obb, _aabb); + float result[16]; + mtxMul(result, _obb.mtx, _mtx); + memCopy(_obb.mtx, result, sizeof(result) ); + } + + void toAabb(Aabb& _outAabb, const void* _vertices, uint32_t _numVertices, uint32_t _stride) + { + Vec3 mn(init::None); + Vec3 mx(init::None); + uint8_t* vertex = (uint8_t*)_vertices; + + mn = mx = load<Vec3>(vertex); + vertex += _stride; + + for (uint32_t ii = 1; ii < _numVertices; ++ii) + { + const Vec3 pos = load<Vec3>(vertex); + vertex += _stride; + + mn = min(pos, mn); + mx = max(pos, mx); + } + + _outAabb.min = mn; + _outAabb.max = mx; + } + + void toAabb(Aabb& _outAabb, const float* _mtx, const void* _vertices, uint32_t _numVertices, uint32_t _stride) + { + Vec3 mn(init::None); + Vec3 mx(init::None); + uint8_t* vertex = (uint8_t*)_vertices; + mn = mx = mul(load<Vec3>(vertex), _mtx); + + vertex += _stride; + + for (uint32_t ii = 1; ii < _numVertices; ++ii) + { + Vec3 pos = mul(load<Vec3>(vertex), _mtx); + vertex += _stride; + + mn = min(pos, mn); + mx = max(pos, mx); + } + + _outAabb.min = mn; + _outAabb.max = mx; + } + + float calcAreaAabb(const Aabb& _aabb) + { + const float ww = _aabb.max.x - _aabb.min.x; + const float hh = _aabb.max.y - _aabb.min.y; + const float dd = _aabb.max.z - _aabb.min.z; + return 2.0f * (ww*hh + ww*dd + hh*dd); + } + + void aabbExpand(Aabb& _outAabb, float _factor) + { + _outAabb.min.x -= _factor; + _outAabb.min.y -= _factor; + _outAabb.min.z -= _factor; + _outAabb.max.x += _factor; + _outAabb.max.y += _factor; + _outAabb.max.z += _factor; + } + + void aabbExpand(Aabb& _outAabb, const Vec3& _pos) + { + _outAabb.min = min(_outAabb.min, _pos); + _outAabb.max = max(_outAabb.max, _pos); + } + + void toObb(Obb& _outObb, const Aabb& _aabb) + { + memSet(_outObb.mtx, 0, sizeof(_outObb.mtx) ); + _outObb.mtx[ 0] = (_aabb.max.x - _aabb.min.x) * 0.5f; + _outObb.mtx[ 5] = (_aabb.max.y - _aabb.min.y) * 0.5f; + _outObb.mtx[10] = (_aabb.max.z - _aabb.min.z) * 0.5f; + _outObb.mtx[12] = (_aabb.min.x + _aabb.max.x) * 0.5f; + _outObb.mtx[13] = (_aabb.min.y + _aabb.max.y) * 0.5f; + _outObb.mtx[14] = (_aabb.min.z + _aabb.max.z) * 0.5f; + _outObb.mtx[15] = 1.0f; + } + + void calcObb(Obb& _outObb, const void* _vertices, uint32_t _numVertices, uint32_t _stride, uint32_t _steps) + { + Aabb aabb; + toAabb(aabb, _vertices, _numVertices, _stride); + float minArea = calcAreaAabb(aabb); + + Obb best; + toObb(best, aabb); + + float angleStep = float(kPiHalf/_steps); + float ax = 0.0f; + float mtx[16]; + + for (uint32_t ii = 0; ii < _steps; ++ii) + { + float ay = 0.0f; + + for (uint32_t jj = 0; jj < _steps; ++jj) + { + float az = 0.0f; + + for (uint32_t kk = 0; kk < _steps; ++kk) + { + mtxRotateXYZ(mtx, ax, ay, az); + + float mtxT[16]; + mtxTranspose(mtxT, mtx); + toAabb(aabb, mtxT, _vertices, _numVertices, _stride); + + float area = calcAreaAabb(aabb); + if (area < minArea) + { + minArea = area; + aabbTransformToObb(best, aabb, mtx); + } + + az += angleStep; + } + + ay += angleStep; + } + + ax += angleStep; + } + + memCopy(&_outObb, &best, sizeof(Obb) ); + } + + void calcMaxBoundingSphere(Sphere& _sphere, const void* _vertices, uint32_t _numVertices, uint32_t _stride) + { + Aabb aabb; + toAabb(aabb, _vertices, _numVertices, _stride); + + Vec3 center = getCenter(aabb); + + float maxDistSq = 0.0f; + uint8_t* vertex = (uint8_t*)_vertices; + + for (uint32_t ii = 0; ii < _numVertices; ++ii) + { + const Vec3& pos = load<Vec3>(vertex); + vertex += _stride; + + const Vec3 tmp = sub(pos, center); + const float distSq = dot(tmp, tmp); + maxDistSq = max(distSq, maxDistSq); + } + + _sphere.center = center; + _sphere.radius = sqrt(maxDistSq); + } + + void calcMinBoundingSphere(Sphere& _sphere, const void* _vertices, uint32_t _numVertices, uint32_t _stride, float _step) + { + RngMwc rng; + + uint8_t* vertex = (uint8_t*)_vertices; + + Vec3 center(init::None); + float* position = (float*)&vertex[0]; + center.x = position[0]; + center.y = position[1]; + center.z = position[2]; + + position = (float*)&vertex[1*_stride]; + center.x += position[0]; + center.y += position[1]; + center.z += position[2]; + + center.x *= 0.5f; + center.y *= 0.5f; + center.z *= 0.5f; + + float xx = position[0] - center.x; + float yy = position[1] - center.y; + float zz = position[2] - center.z; + float maxDistSq = xx*xx + yy*yy + zz*zz; + + float radiusStep = _step * 0.37f; + + bool done; + do + { + done = true; + for (uint32_t ii = 0, index = rng.gen()%_numVertices; ii < _numVertices; ++ii, index = (index + 1)%_numVertices) + { + position = (float*)&vertex[index*_stride]; + + xx = position[0] - center.x; + yy = position[1] - center.y; + zz = position[2] - center.z; + float distSq = xx*xx + yy*yy + zz*zz; + + if (distSq > maxDistSq) + { + done = false; + + center.x += xx * radiusStep; + center.y += yy * radiusStep; + center.z += zz * radiusStep; + maxDistSq = lerp(maxDistSq, distSq, _step); + + break; + } + } + + } while (!done); + + _sphere.center = center; + _sphere.radius = sqrt(maxDistSq); + } + + void buildFrustumPlanes(Plane* _result, const float* _viewProj) + { + const float xw = _viewProj[ 3]; + const float yw = _viewProj[ 7]; + const float zw = _viewProj[11]; + const float ww = _viewProj[15]; + + const float xz = _viewProj[ 2]; + const float yz = _viewProj[ 6]; + const float zz = _viewProj[10]; + const float wz = _viewProj[14]; + + Plane& near = _result[0]; + Plane& far = _result[1]; + Plane& left = _result[2]; + Plane& right = _result[3]; + Plane& top = _result[4]; + Plane& bottom = _result[5]; + + near.normal.x = xw - xz; + near.normal.y = yw - yz; + near.normal.z = zw - zz; + near.dist = ww - wz; + + far.normal.x = xw + xz; + far.normal.y = yw + yz; + far.normal.z = zw + zz; + far.dist = ww + wz; + + const float xx = _viewProj[ 0]; + const float yx = _viewProj[ 4]; + const float zx = _viewProj[ 8]; + const float wx = _viewProj[12]; + + left.normal.x = xw - xx; + left.normal.y = yw - yx; + left.normal.z = zw - zx; + left.dist = ww - wx; + + right.normal.x = xw + xx; + right.normal.y = yw + yx; + right.normal.z = zw + zx; + right.dist = ww + wx; + + const float xy = _viewProj[ 1]; + const float yy = _viewProj[ 5]; + const float zy = _viewProj[ 9]; + const float wy = _viewProj[13]; + + top.normal.x = xw + xy; + top.normal.y = yw + yy; + top.normal.z = zw + zy; + top.dist = ww + wy; + + bottom.normal.x = xw - xy; + bottom.normal.y = yw - yy; + bottom.normal.z = zw - zy; + bottom.dist = ww - wy; + + Plane* plane = _result; + for (uint32_t ii = 0; ii < 6; ++ii) + { + const float invLen = 1.0f/length(plane->normal); + plane->normal = normalize(plane->normal); + plane->dist *= invLen; + ++plane; + } + } + + Ray makeRay(float _x, float _y, const float* _invVp) + { + Ray ray; + + const Vec3 near = { _x, _y, 0.0f }; + ray.pos = mulH(near, _invVp); + + const Vec3 far = { _x, _y, 1.0f }; + Vec3 tmp = mulH(far, _invVp); + + const Vec3 dir = sub(tmp, ray.pos); + ray.dir = normalize(dir); + + return ray; + } + + bool intersect(const Ray& _ray, const Aabb& _aabb, Hit* _hit) + { + const Vec3 invDir = rcp(_ray.dir); + const Vec3 tmp0 = sub(_aabb.min, _ray.pos); + const Vec3 t0 = mul(tmp0, invDir); + const Vec3 tmp1 = sub(_aabb.max, _ray.pos); + const Vec3 t1 = mul(tmp1, invDir); + + const Vec3 mn = min(t0, t1); + const Vec3 mx = max(t0, t1); + + const float tmin = max(mn.x, mn.y, mn.z); + const float tmax = min(mx.x, mx.y, mx.z); + + if (0.0f > tmax + || tmin > tmax) + { + return false; + } + + if (NULL != _hit) + { + _hit->plane.normal.x = float( (t1.x == tmin) - (t0.x == tmin) ); + _hit->plane.normal.y = float( (t1.y == tmin) - (t0.y == tmin) ); + _hit->plane.normal.z = float( (t1.z == tmin) - (t0.z == tmin) ); + + _hit->plane.dist = tmin; + _hit->pos = getPointAt(_ray, tmin); + } + + return true; + } + + static constexpr Aabb kUnitAabb = + { + { -1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + }; + + bool intersect(const Ray& _ray, const Obb& _obb, Hit* _hit) + { + Aabb aabb; + toAabb(aabb, _obb); + + if (!intersect(_ray, aabb) ) + { + return false; + } + + float mtxInv[16]; + mtxInverse(mtxInv, _obb.mtx); + + Ray obbRay; + obbRay.pos = mul(_ray.pos, mtxInv); + obbRay.dir = mulXyz0(_ray.dir, mtxInv); + + if (intersect(obbRay, kUnitAabb, _hit) ) + { + if (NULL != _hit) + { + _hit->pos = mul(_hit->pos, _obb.mtx); + + const Vec3 tmp = mulXyz0(_hit->plane.normal, _obb.mtx); + _hit->plane.normal = normalize(tmp); + } + + return true; + } + + return false; + } + + bool intersect(const Ray& _ray, const Disk& _disk, Hit* _hit) + { + Plane plane(_disk.normal, -dot(_disk.center, _disk.normal) ); + + Hit tmpHit; + _hit = NULL != _hit ? _hit : &tmpHit; + + if (intersect(_ray, plane, _hit) ) + { + const Vec3 tmp = sub(_disk.center, _hit->pos); + return dot(tmp, tmp) <= square(_disk.radius); + } + + return false; + } + + static bool intersect(const Ray& _ray, const Cylinder& _cylinder, bool _capsule, Hit* _hit) + { + Vec3 axis = sub(_cylinder.end, _cylinder.pos); + const Vec3 rc = sub(_ray.pos, _cylinder.pos); + const Vec3 dxa = cross(_ray.dir, axis); + + const float len = length(dxa); + const Vec3 normal = normalize(dxa); + const float dist = abs(dot(rc, normal) ); + + if (dist > _cylinder.radius) + { + return false; + } + + Vec3 vo = cross(rc, axis); + const float t0 = -dot(vo, normal) / len; + + vo = normalize(cross(normal, axis) ); + + const float rsq = square(_cylinder.radius); + const float ddoto = dot(_ray.dir, vo); + const float ss = t0 - abs(sqrt(rsq - square(dist) ) / ddoto); + + if (0.0f > ss) + { + return false; + } + + const Vec3 point = getPointAt(_ray, ss); + + const float axisLen = length(axis); + axis = normalize(axis); + const float pdota = dot(_cylinder.pos, axis); + const float height = dot(point, axis) - pdota; + + if (0.0f < height + && axisLen > height) + { + if (NULL != _hit) + { + const float t1 = height / axisLen; + const Vec3 pointOnAxis = lerp(_cylinder.pos, _cylinder.end, t1); + + _hit->pos = point; + + const Vec3 tmp = sub(point, pointOnAxis); + _hit->plane.normal = normalize(tmp); + + _hit->plane.dist = ss; + } + + return true; + } + + if (_capsule) + { + const float rdota = dot(_ray.pos, axis); + const float pp = rdota - pdota; + const float t1 = pp / axisLen; + + const Vec3 pointOnAxis = lerp(_cylinder.pos, _cylinder.end, t1); + const Vec3 axisToRay = sub(_ray.pos, pointOnAxis); + + if (_cylinder.radius < length(axisToRay) + && 0.0f > ss) + { + return false; + } + + Sphere sphere; + sphere.radius = _cylinder.radius; + + sphere.center = 0.0f >= height + ? _cylinder.pos + : _cylinder.end + ; + + return intersect(_ray, sphere, _hit); + } + + Plane plane(init::None); + Vec3 pos(init::None); + + if (0.0f >= height) + { + plane.normal = neg(axis); + pos = _cylinder.pos; + } + else + { + plane.normal = axis; + pos = _cylinder.end; + } + + plane.dist = -dot(pos, plane.normal); + + Hit tmpHit; + _hit = NULL != _hit ? _hit : &tmpHit; + + if (intersect(_ray, plane, _hit) ) + { + const Vec3 tmp = sub(pos, _hit->pos); + return dot(tmp, tmp) <= rsq; + } + + return false; + } + + bool intersect(const Ray& _ray, const Cylinder& _cylinder, Hit* _hit) + { + return intersect(_ray, _cylinder, false, _hit); + } + + bool intersect(const Ray& _ray, const Capsule& _capsule, Hit* _hit) + { + BX_STATIC_ASSERT(sizeof(Capsule) == sizeof(Cylinder) ); + return intersect(_ray, *( (const Cylinder*)&_capsule), true, _hit); + } + + bool intersect(const Ray& _ray, const Cone& _cone, Hit* _hit) + { + const Vec3 axis = sub(_cone.pos, _cone.end); + + const float len = length(axis); + const Vec3 normal = normalize(axis); + + Disk disk; + disk.center = _cone.pos; + disk.normal = normal; + disk.radius = _cone.radius; + + Hit tmpInt; + Hit* out = NULL != _hit ? _hit : &tmpInt; + bool hit = intersect(_ray, disk, out); + + const Vec3 ro = sub(_ray.pos, _cone.end); + + const float hyp = sqrt(square(_cone.radius) + square(len) ); + const float cosaSq = square(len/hyp); + const float ndoto = dot(normal, ro); + const float ndotd = dot(normal, _ray.dir); + + const float aa = square(ndotd) - cosaSq; + const float bb = 2.0f * (ndotd*ndoto - dot(_ray.dir, ro)*cosaSq); + const float cc = square(ndoto) - dot(ro, ro)*cosaSq; + + float det = bb*bb - 4.0f*aa*cc; + + if (0.0f > det) + { + return hit; + } + + det = sqrt(det); + const float invA2 = 1.0f / (2.0f*aa); + const float t1 = (-bb - det) * invA2; + const float t2 = (-bb + det) * invA2; + + float tt = t1; + if (0.0f > t1 + || (0.0f < t2 && t2 < t1) ) + { + tt = t2; + } + + if (0.0f > tt) + { + return hit; + } + + const Vec3 hitPos = getPointAt(_ray, tt); + const Vec3 point = sub(hitPos, _cone.end); + + const float hh = dot(normal, point); + + if (0.0f > hh + || len < hh) + { + return hit; + } + + if (NULL != _hit) + { + if (!hit + || tt < _hit->plane.dist) + { + _hit->plane.dist = tt; + _hit->pos = hitPos; + + const float scale = hh / dot(point, point); + const Vec3 pointScaled = mul(point, scale); + + const Vec3 tmp = sub(pointScaled, normal); + _hit->plane.normal = normalize(tmp); + } + } + + return true; + } + + bool intersect(const Ray& _ray, const Plane& _plane, bool _doublesided, Hit* _hit) + { + const float dist = distance(_plane, _ray.pos); + const float ndotd = dot(_ray.dir, _plane.normal); + + if (!_doublesided + && (0.0f > dist || 0.0f < ndotd) ) + { + return false; + } + + if (NULL != _hit) + { + _hit->plane.normal = _plane.normal; + + float tt = -dist/ndotd; + _hit->plane.dist = tt; + _hit->pos = getPointAt(_ray, tt); + } + + return true; + } + + bool intersect(const Ray& _ray, const Sphere& _sphere, Hit* _hit) + { + const Vec3 rs = sub(_ray.pos, _sphere.center); + + const float bb = dot(rs, _ray.dir); + if (0.0f < bb) + { + return false; + } + + const float aa = dot(_ray.dir, _ray.dir); + const float cc = dot(rs, rs) - square(_sphere.radius); + + const float discriminant = bb*bb - aa*cc; + + if (0.0f >= discriminant) + { + return false; + } + + const float sqrtDiscriminant = sqrt(discriminant); + const float invA = 1.0f / aa; + const float tt = -(bb + sqrtDiscriminant)*invA; + + if (0.0f >= tt) + { + return false; + } + + if (NULL != _hit) + { + _hit->plane.dist = tt; + + const Vec3 point = getPointAt(_ray, tt); + _hit->pos = point; + + const Vec3 tmp = sub(point, _sphere.center); + _hit->plane.normal = normalize(tmp); + } + + return true; + } + + bool intersect(const Ray& _ray, const Triangle& _triangle, Hit* _hit) + { + const Vec3 edge10 = sub(_triangle.v1, _triangle.v0); + const Vec3 edge02 = sub(_triangle.v0, _triangle.v2); + const Vec3 normal = cross(edge02, edge10); + const Vec3 vo = sub(_triangle.v0, _ray.pos); + const Vec3 dxo = cross(_ray.dir, vo); + const float det = dot(normal, _ray.dir); + + if (0.0f < det) + { + return false; + } + + const float invDet = 1.0f/det; + const float bz = dot(dxo, edge02) * invDet; + const float by = dot(dxo, edge10) * invDet; + const float bx = 1.0f - by - bz; + + if (0.0f > bx + || 0.0f > by + || 0.0f > bz) + { + return false; + } + + if (NULL != _hit) + { + _hit->plane.normal = normalize(normal); + + const float tt = dot(normal, vo) * invDet; + _hit->plane.dist = tt; + _hit->pos = getPointAt(_ray, tt); + } + + return true; + } + + Vec3 barycentric(const Triangle& _triangle, const Vec3& _pos) + { + const Vec3 v0 = sub(_triangle.v1, _triangle.v0); + const Vec3 v1 = sub(_triangle.v2, _triangle.v0); + const Vec3 v2 = sub(_pos, _triangle.v0); + + const float dot00 = dot(v0, v0); + const float dot01 = dot(v0, v1); + const float dot02 = dot(v0, v2); + const float dot11 = dot(v1, v1); + const float dot12 = dot(v1, v2); + + const float invDenom = 1.0f/(dot00*dot11 - square(dot01) ); + + const float vv = (dot11*dot02 - dot01*dot12)*invDenom; + const float ww = (dot00*dot12 - dot01*dot02)*invDenom; + const float uu = 1.0f - vv - ww; + + return { uu, vv, ww }; + } + + Vec3 cartesian(const Triangle& _triangle, const Vec3& _uvw) + { + const Vec3 b0 = mul(_triangle.v0, _uvw.x); + const Vec3 b1 = mul(_triangle.v1, _uvw.y); + const Vec3 b2 = mul(_triangle.v2, _uvw.z); + + return add(add(b0, b1), b2); + } + + void calcPlane(Plane& _outPlane, const Disk& _disk) + { + calcPlane(_outPlane, _disk.normal, _disk.center); + } + + void calcPlane(Plane& _outPlane, const Triangle& _triangle) + { + calcPlane(_outPlane, _triangle.v0, _triangle.v1, _triangle.v2); + } + + float projectToAxis(const Vec3& _axis, const Vec3& _point) + { + return dot(_axis, _point); + } + + Interval projectToAxis(const Vec3& _axis, const Vec3* _points, uint32_t _num) + { + Interval interval(projectToAxis(_axis, _points[0]) ); + + for (uint32_t ii = 1; ii < _num; ++ii) + { + interval.expand(projectToAxis(_axis, _points[ii]) ); + } + + return interval; + } + + Interval projectToAxis(const Vec3& _axis, const Aabb& _aabb) + { + const float extent = abs(projectToAxis(abs(_axis), getExtents(_aabb) ) ); + const float center = projectToAxis( _axis , getCenter (_aabb) ); + return + { + center - extent, + center + extent, + }; + } + + Interval projectToAxis(const Vec3& _axis, const Triangle& _triangle) + { + const float a0 = projectToAxis(_axis, _triangle.v0); + const float a1 = projectToAxis(_axis, _triangle.v1); + const float a2 = projectToAxis(_axis, _triangle.v2); + return + { + min(a0, a1, a2), + max(a0, a1, a2), + }; + } + + struct Srt + { + Quaternion rotation = init::Identity; + Vec3 translation = init::Zero; + Vec3 scale = init::Zero; + }; + + Srt toSrt(const Aabb& _aabb) + { + return { init::Identity, getCenter(_aabb), getExtents(_aabb) }; + } + + Srt toSrt(const void* _mtx) + { + Srt result; + + const float* mtx = (const float*)_mtx; + + result.translation = { mtx[12], mtx[13], mtx[14] }; + + float xx = mtx[ 0]; + float xy = mtx[ 1]; + float xz = mtx[ 2]; + float yx = mtx[ 4]; + float yy = mtx[ 5]; + float yz = mtx[ 6]; + float zx = mtx[ 8]; + float zy = mtx[ 9]; + float zz = mtx[10]; + + result.scale = + { + sqrt(xx*xx + xy*xy + xz*xz), + sqrt(yx*yx + yy*yy + yz*yz), + sqrt(zx*zx + zy*zy + zz*zz), + }; + + const Vec3 invScale = rcp(result.scale); + + xx *= invScale.x; + xy *= invScale.x; + xz *= invScale.x; + yx *= invScale.y; + yy *= invScale.y; + yz *= invScale.y; + zx *= invScale.z; + zy *= invScale.z; + zz *= invScale.z; + + const float trace = xx + yy + zz; + + if (0.0f < trace) + { + const float invS = 0.5f * rsqrt(trace + 1.0f); + result.rotation = + { + (yz - zy) * invS, + (zx - xz) * invS, + (xy - yx) * invS, + 0.25f / invS, + }; + } + else + { + if (xx > yy + && xx > zz) + { + const float invS = 0.5f * sqrt(max(1.0f + xx - yy - zz, 1e-8f) ); + result.rotation = + { + 0.25f / invS, + (xy + yx) * invS, + (xz + zx) * invS, + (yz - zy) * invS, + }; + } + else if (yy > zz) + { + const float invS = 0.5f * sqrt(max(1.0f + yy - xx - zz, 1e-8f) ); + result.rotation = + { + (xy + yx) * invS, + 0.25f / invS, + (yz + zy) * invS, + (zx - xz) * invS, + }; + } + else + { + const float invS = 0.5f * sqrt(max(1.0f + zz - xx - yy, 1e-8f) ); + result.rotation = + { + (xz + zx) * invS, + (yz + zy) * invS, + 0.25f / invS, + (xy - yx) * invS, + }; + } + } + + return result; + } + + void mtxFromSrt(float* _outMtx, const Srt& _srt) + { + mtxFromQuaternion(_outMtx, _srt.rotation); + + store<Vec3>(&_outMtx[0], mul(load<Vec3>(&_outMtx[0]), _srt.scale.x) ); + store<Vec3>(&_outMtx[4], mul(load<Vec3>(&_outMtx[4]), _srt.scale.y) ); + store<Vec3>(&_outMtx[8], mul(load<Vec3>(&_outMtx[8]), _srt.scale.z) ); + + store<Vec3>(&_outMtx[12], _srt.translation); + } + + bool isNearZero(float _v) + { + return isEqual(_v, 0.0f, 0.00001f); + } + + bool isNearZero(const Vec3& _v) + { + return isNearZero(dot(_v, _v) ); + } + + bool intersect(Line& _outLine, const Plane& _planeA, const Plane& _planeB) + { + const Vec3 axb = cross(_planeA.normal, _planeB.normal); + const float denom = dot(axb, axb); + + if (isNearZero(denom) ) + { + return false; + } + + const Vec3 bxaxb = cross(_planeB.normal, axb); + const Vec3 axbxa = cross(axb, _planeA.normal); + const Vec3 tmp0 = mul(bxaxb, _planeA.dist); + const Vec3 tmp1 = mul(axbxa, _planeB.dist); + const Vec3 tmp2 = add(tmp0, tmp1); + + _outLine.pos = mul(tmp2, -1.0f/denom); + _outLine.dir = normalize(axb); + + return true; + } + + Vec3 intersectPlanes(const Plane& _pa, const Plane& _pb, const Plane& _pc) + { + const Vec3 axb = cross(_pa.normal, _pb.normal); + const Vec3 bxc = cross(_pb.normal, _pc.normal); + const Vec3 cxa = cross(_pc.normal, _pa.normal); + const Vec3 tmp0 = mul(bxc, _pa.dist); + const Vec3 tmp1 = mul(cxa, _pb.dist); + const Vec3 tmp2 = mul(axb, _pc.dist); + const Vec3 tmp3 = add(tmp0, tmp1); + const Vec3 tmp4 = add(tmp3, tmp2); + + const float denom = dot(_pa.normal, bxc); + const Vec3 result = mul(tmp4, -1.0f/denom); + + return result; + } + + bool intersect(float& _outTa, float& _outTb, const LineSegment& _a, const LineSegment& _b) + { + // Reference(s): + // + // - The shortest line between two lines in 3D + // https://web.archive.org/web/20120309093234/http://paulbourke.net/geometry/lineline3d/ + + const Vec3 bd = sub(_b.end, _b.pos); + if (isNearZero(bd) ) + { + return false; + } + + const Vec3 ad = sub(_a.end, _a.pos); + if (isNearZero(ad) ) + { + return false; + } + + const Vec3 ab = sub(_a.pos, _b.pos); + + const float d0 = projectToAxis(ab, bd); + const float d1 = projectToAxis(ad, bd); + const float d2 = projectToAxis(ab, ad); + const float d3 = projectToAxis(bd, bd); + const float d4 = projectToAxis(ad, ad); + + const float denom = d4*d3 - square(d1); + + float ta = 0.0f; + + if (!isNearZero(denom) ) + { + ta = (d0*d1 - d2*d3)/denom; + } + + _outTa = ta; + _outTb = (d0+d1*ta)/d3; + + return true; + } + + bool intersect(const LineSegment& _a, const LineSegment& _b) + { + float ta, tb; + if (!intersect(ta, tb, _a, _b) ) + { + return false; + } + + return 0.0f >= ta + && 1.0f <= ta + && 0.0f >= tb + && 1.0f <= tb + ; + } + + bool intersect(const LineSegment& _line, const Plane& _plane, Hit* _hit) + { + const float dist = distance(_plane, _line.pos); + const float flip = sign(dist); + const Vec3 dir = normalize(sub(_line.end, _line.pos) ); + const float ndotd = dot(dir, _plane.normal); + const float tt = -dist/ndotd; + const float len = length(sub(_line.end, _line.pos) ); + + if (tt < 0.0f || tt > len) + { + return false; + } + + if (NULL != _hit) + { + _hit->pos = mad(dir, tt, _line.pos); + + _hit->plane.normal = mul(_plane.normal, flip); + _hit->plane.dist = -dot(_hit->plane.normal, _hit->pos); + } + + return true; + } + + float distance(const Plane& _plane, const LineSegment& _line) + { + const float pd = distance(_plane, _line.pos); + const float ed = distance(_plane, _line.end); + return min(max(pd*ed, 0.0f), abs(pd), abs(ed) ); + } + + Vec3 closestPoint(const Line& _line, const Vec3& _point) + { + const float tt = projectToAxis(_line.dir, sub(_point, _line.pos) ); + return getPointAt(_line, tt); + } + + Vec3 closestPoint(const LineSegment& _line, const Vec3& _point, float& _outT) + { + const Vec3 axis = sub(_line.end, _line.pos); + const float lengthSq = dot(axis, axis); + const float tt = clamp(projectToAxis(axis, sub(_point, _line.pos) ) / lengthSq, 0.0f, 1.0f); + _outT = tt; + return mad(axis, tt, _line.pos); + } + + Vec3 closestPoint(const LineSegment& _line, const Vec3& _point) + { + float ignored; + return closestPoint(_line, _point, ignored); + } + + Vec3 closestPoint(const Plane& _plane, const Vec3& _point) + { + const float dist = distance(_plane, _point); + return sub(_point, mul(_plane.normal, dist) ); + } + + Vec3 closestPoint(const Aabb& _aabb, const Vec3& _point) + { + return clamp(_point, _aabb.min, _aabb.max); + } + + Vec3 closestPoint(const Obb& _obb, const Vec3& _point) + { + const Srt srt = toSrt(_obb.mtx); + + Aabb aabb; + toAabb(aabb, srt.scale); + + const Quaternion invRotation = invert(srt.rotation); + const Vec3 obbSpacePos = mul(sub(_point, srt.translation), srt.rotation); + const Vec3 pos = closestPoint(aabb, obbSpacePos); + + return add(mul(pos, invRotation), srt.translation); + } + + Vec3 closestPoint(const Triangle& _triangle, const Vec3& _point) + { + Plane plane(init::None); + calcPlane(plane, _triangle); + + const Vec3 pos = closestPoint(plane, _point); + const Vec3 uvw = barycentric(_triangle, pos); + + return cartesian(_triangle, clamp<Vec3>(uvw, Vec3(0.0f), Vec3(1.0f) ) ); + } + + bool overlap(const Aabb& _aabb, const Vec3& _pos) + { + const Vec3 ac = getCenter(_aabb); + const Vec3 ae = getExtents(_aabb); + const Vec3 abc = abs(sub(ac, _pos) ); + + return abc.x <= ae.x + && abc.y <= ae.y + && abc.z <= ae.z + ; + } + + bool overlap(const Aabb& _aabbA, const Aabb& _aabbB) + { + return true + && overlap(Interval{_aabbA.min.x, _aabbA.max.x}, Interval{_aabbB.min.x, _aabbB.max.x}) + && overlap(Interval{_aabbA.min.y, _aabbA.max.y}, Interval{_aabbB.min.y, _aabbB.max.y}) + && overlap(Interval{_aabbA.min.z, _aabbA.max.z}, Interval{_aabbB.min.z, _aabbB.max.z}) + ; + } + + bool overlap(const Aabb& _aabb, const Plane& _plane) + { + const Vec3 center = getCenter(_aabb); + const float dist = distance(_plane, center); + + const Vec3 extents = getExtents(_aabb); + const Vec3 normal = abs(_plane.normal); + const float radius = dot(extents, normal); + + return abs(dist) <= radius; + } + + static constexpr Vec3 kAxis[] = + { + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + }; + + bool overlap(const Aabb& _aabb, const Triangle& _triangle) + { + Aabb triAabb; + toAabb(triAabb, _triangle); + + if (!overlap(_aabb, triAabb) ) + { + return false; + } + + Plane plane(init::None); + calcPlane(plane, _triangle); + + if (!overlap(_aabb, plane) ) + { + return false; + } + + const Vec3 center = getCenter(_aabb); + const Vec3 v0 = sub(_triangle.v0, center); + const Vec3 v1 = sub(_triangle.v1, center); + const Vec3 v2 = sub(_triangle.v2, center); + + const Vec3 edge[] = + { + sub(v1, v0), + sub(v2, v1), + sub(v0, v2), + }; + + for (uint32_t ii = 0; ii < 3; ++ii) + { + for (uint32_t jj = 0; jj < 3; ++jj) + { + const Vec3 axis = cross(kAxis[ii], edge[jj]); + + const Interval aabbR = projectToAxis(axis, _aabb); + const Interval triR = projectToAxis(axis, _triangle); + + if (!overlap(aabbR, triR) ) + { + return false; + } + } + } + + return true; + } + + bool overlap(const Aabb& _aabb, const Capsule& _capsule) + { + const Vec3 pos = closestPoint(LineSegment{_capsule.pos, _capsule.end}, getCenter(_aabb) ); + return overlap(_aabb, Sphere{pos, _capsule.radius}); + } + + bool overlap(const Aabb& _aabb, const Cone& _cone) + { + float tt; + const Vec3 pos = closestPoint(LineSegment{_cone.pos, _cone.end}, getCenter(_aabb), tt); + return overlap(_aabb, Sphere{pos, lerp(_cone.radius, 0.0f, tt)}); + } + + bool overlap(const Aabb& _aabb, const Disk& _disk) + { + if (!overlap(_aabb, Sphere{_disk.center, _disk.radius}) ) + { + return false; + } + + Plane plane(init::None); + calcPlane(plane, _disk.normal, _disk.center); + + return overlap(_aabb, plane); + } + + static void calcObbVertices( + Vec3* _outVertices + , const Vec3& _axisX + , const Vec3& _axisY + , const Vec3& _axisZ + , const Vec3& _pos + , const Vec3& _scale + ) + { + const Vec3 ax = mul(_axisX, _scale.x); + const Vec3 ay = mul(_axisY, _scale.y); + const Vec3 az = mul(_axisZ, _scale.z); + + const Vec3 ppx = add(_pos, ax); + const Vec3 pmx = sub(_pos, ax); + const Vec3 ypz = add(ay, az); + const Vec3 ymz = sub(ay, az); + + _outVertices[0] = sub(pmx, ymz); + _outVertices[1] = sub(ppx, ymz); + _outVertices[2] = add(ppx, ymz); + _outVertices[3] = add(pmx, ymz); + _outVertices[4] = sub(pmx, ypz); + _outVertices[5] = sub(ppx, ypz); + _outVertices[6] = add(ppx, ypz); + _outVertices[7] = add(pmx, ypz); + } + + static bool overlaps(const Vec3& _axis, const Vec3* _vertsA, const Vec3* _vertsB) + { + Interval ia = projectToAxis(_axis, _vertsA, 8); + Interval ib = projectToAxis(_axis, _vertsB, 8); + + return overlap(ia, ib); + } + + static bool overlap(const Srt& _srtA, const Srt& _srtB) + { + const Vec3 ax = toXAxis(_srtA.rotation); + const Vec3 ay = toYAxis(_srtA.rotation); + const Vec3 az = toZAxis(_srtA.rotation); + + const Vec3 bx = toXAxis(_srtB.rotation); + const Vec3 by = toYAxis(_srtB.rotation); + const Vec3 bz = toZAxis(_srtB.rotation); + + Vec3 vertsA[8] = { init::None, init::None, init::None, init::None, init::None, init::None, init::None, init::None }; + calcObbVertices(vertsA, ax, ay, az, init::Zero, _srtA.scale); + + Vec3 vertsB[8] = { init::None, init::None, init::None, init::None, init::None, init::None, init::None, init::None }; + calcObbVertices(vertsB, bx, by, bz, sub(_srtB.translation, _srtA.translation), _srtB.scale); + + return overlaps(ax, vertsA, vertsB) + && overlaps(ay, vertsA, vertsB) + && overlaps(az, vertsA, vertsB) + && overlaps(bx, vertsA, vertsB) + && overlaps(by, vertsA, vertsB) + && overlaps(bz, vertsA, vertsB) + && overlaps(cross(ax, bx), vertsA, vertsB) + && overlaps(cross(ax, by), vertsA, vertsB) + && overlaps(cross(ax, bz), vertsA, vertsB) + && overlaps(cross(ay, bx), vertsA, vertsB) + && overlaps(cross(ay, by), vertsA, vertsB) + && overlaps(cross(ay, bz), vertsA, vertsB) + && overlaps(cross(az, bx), vertsA, vertsB) + && overlaps(cross(az, by), vertsA, vertsB) + && overlaps(cross(az, bz), vertsA, vertsB) + ; + } + + bool overlap(const Aabb& _aabb, const Obb& _obb) + { + const Srt srtA = toSrt(_aabb); + const Srt srtB = toSrt(_obb.mtx); + + return overlap(srtA, srtB); + } + + bool overlap(const Capsule& _capsule, const Vec3& _pos) + { + const Vec3 pos = closestPoint(LineSegment{_capsule.pos, _capsule.end}, _pos); + return overlap(Sphere{pos, _capsule.radius}, _pos); + } + + bool overlap(const Capsule& _capsule, const Plane& _plane) + { + return distance(_plane, LineSegment{_capsule.pos, _capsule.end}) <= _capsule.radius; + } + + bool overlap(const Capsule& _capsuleA, const Capsule& _capsuleB) + { + float ta, tb; + if (!intersect(ta, tb, {_capsuleA.pos, _capsuleA.end}, {_capsuleB.pos, _capsuleB.end}) ) + { + return false; + } + + if (0.0f <= ta + && 1.0f >= ta + && 0.0f <= tb + && 1.0f >= tb) + { + const Vec3 ad = sub(_capsuleA.end, _capsuleA.pos); + const Vec3 bd = sub(_capsuleB.end, _capsuleB.pos); + + return overlap( + Sphere{mad(ad, ta, _capsuleA.pos), _capsuleA.radius} + , Sphere{mad(bd, tb, _capsuleB.pos), _capsuleB.radius} + ); + } + + if (0.0f <= ta + && 1.0f >= ta) + { + return overlap(_capsuleA, Sphere{0.0f >= tb ? _capsuleB.pos : _capsuleB.end, _capsuleB.radius}); + } + + if (0.0f <= tb + && 1.0f >= tb) + { + return overlap(_capsuleB, Sphere{0.0f >= ta ? _capsuleA.pos : _capsuleA.end, _capsuleA.radius}); + } + + const Vec3 pa = 0.0f > ta ? _capsuleA.pos : _capsuleA.end; + const Vec3 pb = 0.0f > tb ? _capsuleB.pos : _capsuleB.end; + const Vec3 closestA = closestPoint(LineSegment{_capsuleA.pos, _capsuleA.end}, pb); + const Vec3 closestB = closestPoint(LineSegment{_capsuleB.pos, _capsuleB.end}, pa); + + if (dot(closestA, pb) <= dot(closestB, pa) ) + { + return overlap(_capsuleA, Sphere{closestB, _capsuleB.radius}); + } + + return overlap(_capsuleB, Sphere{closestA, _capsuleA.radius}); + } + + bool overlap(const Cone& _cone, const Vec3& _pos) + { + float tt; + const Vec3 pos = closestPoint(LineSegment{_cone.pos, _cone.end}, _pos, tt); + return overlap(Disk{pos, normalize(sub(_cone.end, _cone.pos) ), lerp(_cone.radius, 0.0f, tt)}, _pos); + } + + bool overlap(const Cone& _cone, const Cylinder& _cylinder) + { + BX_UNUSED(_cone, _cylinder); + return false; + } + + bool overlap(const Cone& _cone, const Capsule& _capsule) + { + BX_UNUSED(_cone, _capsule); + return false; + } + + bool overlap(const Cone& _coneA, const Cone& _coneB) + { + BX_UNUSED(_coneA, _coneB); + return false; + } + + bool overlap(const Cone& _cone, const Disk& _disk) + { + BX_UNUSED(_cone, _disk); + return false; + } + + bool overlap(const Cone& _cone, const Obb& _obb) + { + BX_UNUSED(_cone, _obb); + return false; + } + + bool overlap(const Cylinder& _cylinder, const Vec3& _pos) + { + const Vec3 pos = closestPoint(LineSegment{_cylinder.pos, _cylinder.end}, _pos); + return overlap(Disk{pos, normalize(sub(_cylinder.end, _cylinder.pos) ), _cylinder.radius}, _pos); + } + + bool overlap(const Cylinder& _cylinder, const Sphere& _sphere) + { + const Vec3 pos = closestPoint(LineSegment{_cylinder.pos, _cylinder.end}, _sphere.center); + return overlap(Disk{pos, normalize(sub(_cylinder.end, _cylinder.pos) ), _cylinder.radius}, _sphere); + } + + bool overlap(const Cylinder& _cylinder, const Aabb& _aabb) + { + const Vec3 pos = closestPoint(LineSegment{_cylinder.pos, _cylinder.end}, getCenter(_aabb) ); + return overlap(Disk{pos, normalize(sub(_cylinder.end, _cylinder.pos) ), _cylinder.radius}, _aabb); + } + + bool overlap(const Cylinder& _cylinder, const Plane& _plane) + { + BX_UNUSED(_cylinder, _plane); + return false; + } + + bool overlap(const Cylinder& _cylinderA, const Cylinder& _cylinderB) + { + BX_UNUSED(_cylinderA, _cylinderB); + return false; + } + + bool overlap(const Cylinder& _cylinder, const Capsule& _capsule) + { + BX_UNUSED(_cylinder, _capsule); + return false; + } + + bool overlap(const Cylinder& _cylinder, const Disk& _disk) + { + BX_UNUSED(_cylinder, _disk); + return false; + } + + bool overlap(const Cylinder& _cylinder, const Obb& _obb) + { + BX_UNUSED(_cylinder, _obb); + return false; + } + + bool overlap(const Disk& _disk, const Vec3& _pos) + { + Plane plane(init::None); + calcPlane(plane, _disk.normal, _disk.center); + + if (!isNearZero(distance(plane, _pos) ) ) + { + return false; + } + + return distanceSq(_disk.center, _pos) <= square(_disk.radius); + } + + bool overlap(const Disk& _disk, const Plane& _plane) + { + Plane plane(init::None); + calcPlane(plane, _disk.normal, _disk.center); + + if (!overlap(plane, _plane) ) + { + return false; + } + + return overlap(_plane, Sphere{_disk.center, _disk.radius}); + } + + bool overlap(const Disk& _disk, const Capsule& _capsule) + { + if (!overlap(_capsule, Sphere{_disk.center, _disk.radius}) ) + { + return false; + } + + Plane plane(init::None); + calcPlane(plane, _disk.normal, _disk.center); + + return overlap(_capsule, plane); + } + + bool overlap(const Disk& _diskA, const Disk& _diskB) + { + Plane planeA(init::None); + calcPlane(planeA, _diskA.normal, _diskA.center); + + Plane planeB(init::None); + calcPlane(planeB, _diskB); + + Line line; + + if (!intersect(line, planeA, planeB) ) + { + return false; + } + + const Vec3 pa = closestPoint(line, _diskA.center); + const Vec3 pb = closestPoint(line, _diskB.center); + + const float lenA = distance(pa, _diskA.center); + const float lenB = distance(pb, _diskB.center); + + return sqrt(square(_diskA.radius) - square(lenA) ) + + sqrt(square(_diskB.radius) - square(lenB) ) + >= distance(pa, pb) + ; + } + + bool overlap(const Disk& _disk, const Obb& _obb) + { + if (!overlap(_obb, Sphere{_disk.center, _disk.radius}) ) + { + return false; + } + + Plane plane(init::None); + calcPlane(plane, _disk.normal, _disk.center); + + return overlap(_obb, plane); + } + + bool overlap(const Obb& _obb, const Vec3& _pos) + { + const Srt srt = toSrt(_obb.mtx); + + Aabb aabb; + toAabb(aabb, srt.scale); + + const Quaternion invRotation = invert(srt.rotation); + const Vec3 pos = mul(sub(_pos, srt.translation), invRotation); + + return overlap(aabb, pos); + } + + bool overlap(const Obb& _obb, const Plane& _plane) + { + const Srt srt = toSrt(_obb.mtx); + + const Quaternion invRotation = invert(srt.rotation); + const Vec3 axis = + { + projectToAxis(_plane.normal, mul(Vec3{1.0f, 0.0f, 0.0f}, invRotation) ), + projectToAxis(_plane.normal, mul(Vec3{0.0f, 1.0f, 0.0f}, invRotation) ), + projectToAxis(_plane.normal, mul(Vec3{0.0f, 0.0f, 1.0f}, invRotation) ), + }; + + const float dist = abs(distance(_plane, srt.translation) ); + const float radius = dot(srt.scale, abs(axis) ); + + return dist <= radius; + } + + bool overlap(const Obb& _obb, const Capsule& _capsule) + { + const Srt srt = toSrt(_obb.mtx); + + Aabb aabb; + toAabb(aabb, srt.scale); + + const Quaternion invRotation = invert(srt.rotation); + + const Capsule capsule = + { + mul(sub(_capsule.pos, srt.translation), invRotation), + mul(sub(_capsule.end, srt.translation), invRotation), + _capsule.radius, + }; + + return overlap(aabb, capsule); + } + + bool overlap(const Obb& _obbA, const Obb& _obbB) + { + const Srt srtA = toSrt(_obbA.mtx); + const Srt srtB = toSrt(_obbB.mtx); + + return overlap(srtA, srtB); + } + + bool overlap(const Plane& _plane, const LineSegment& _line) + { + return isNearZero(distance(_plane, _line) ); + } + + bool overlap(const Plane& _plane, const Vec3& _pos) + { + return isNearZero(distance(_plane, _pos) ); + } + + bool overlap(const Plane& _planeA, const Plane& _planeB) + { + const Vec3 dir = cross(_planeA.normal, _planeB.normal); + const float len = length(dir); + + return !isNearZero(len); + } + + bool overlap(const Plane& _plane, const Cone& _cone) + { + const Vec3 axis = sub(_cone.pos, _cone.end); + const float len = length(axis); + const Vec3 dir = normalize(axis); + + const Vec3 v1 = cross(_plane.normal, dir); + const Vec3 v2 = cross(v1, dir); + + const float bb = len; + const float aa = _cone.radius; + const float cc = sqrt(square(aa) + square(bb) ); + + const Vec3 pos = add(add(_cone.end + , mul(dir, len * bb/cc) ) + , mul(v2, len * aa/cc) + ); + + return overlap(_plane, LineSegment{pos, _cone.end}); + } + + bool overlap(const Sphere& _sphere, const Vec3& _pos) + { + const float distSq = distanceSq(_sphere.center, _pos); + const float radiusSq = square(_sphere.radius); + return distSq <= radiusSq; + } + + bool overlap(const Sphere& _sphereA, const Sphere& _sphereB) + { + const float distSq = distanceSq(_sphereA.center, _sphereB.center); + const float radiusSq = square(_sphereA.radius + _sphereB.radius); + return distSq <= radiusSq; + } + + bool overlap(const Sphere& _sphere, const Aabb& _aabb) + { + const Vec3 pos = closestPoint(_aabb, _sphere.center); + return overlap(_sphere, pos); + } + + bool overlap(const Sphere& _sphere, const Plane& _plane) + { + return abs(distance(_plane, _sphere.center) ) <= _sphere.radius; + } + + bool overlap(const Sphere& _sphere, const Triangle& _triangle) + { + Plane plane(init::None); + calcPlane(plane, _triangle); + + if (!overlap(_sphere, plane) ) + { + return false; + } + + const Vec3 pos = closestPoint(plane, _sphere.center); + const Vec3 uvw = barycentric(_triangle, pos); + const float nr = -_sphere.radius; + + return uvw.x >= nr + && uvw.y >= nr + && uvw.z >= nr + ; + } + + bool overlap(const Sphere& _sphere, const Capsule& _capsule) + { + const Vec3 pos = closestPoint(LineSegment{_capsule.pos, _capsule.end}, _sphere.center); + return overlap(_sphere, Sphere{pos, _capsule.radius}); + } + + bool overlap(const Sphere& _sphere, const Cone& _cone) + { + float tt; + const Vec3 pos = closestPoint(LineSegment{_cone.pos, _cone.end}, _sphere.center, tt); + return overlap(_sphere, Sphere{pos, lerp(_cone.radius, 0.0f, tt)}); + } + + bool overlap(const Sphere& _sphere, const Disk& _disk) + { + if (!overlap(_sphere, Sphere{_disk.center, _disk.radius}) ) + { + return false; + } + + Plane plane(init::None); + calcPlane(plane, _disk.normal, _disk.center); + + return overlap(_sphere, plane); + } + + bool overlap(const Sphere& _sphere, const Obb& _obb) + { + const Vec3 pos = closestPoint(_obb, _sphere.center); + return overlap(_sphere, pos); + } + + bool overlap(const Triangle& _triangle, const Vec3& _pos) + { + const Vec3 uvw = barycentric(_triangle, _pos); + + return uvw.x >= 0.0f + && uvw.y >= 0.0f + && uvw.z >= 0.0f + ; + } + + bool overlap(const Triangle& _triangle, const Plane& _plane) + { + const float dist0 = distance(_plane, _triangle.v0); + const float dist1 = distance(_plane, _triangle.v1); + const float dist2 = distance(_plane, _triangle.v2); + + const float minDist = min(dist0, dist1, dist2); + const float maxDist = max(dist0, dist1, dist2); + + return 0.0f > minDist + && 0.0f < maxDist + ; + } + + inline bool overlap(const Triangle& _triangleA, const Triangle& _triangleB, const Vec3& _axis) + { + const Interval ia = projectToAxis(_axis, _triangleA); + const Interval ib = projectToAxis(_axis, _triangleB); + return overlap(ia, ib); + } + + bool overlap(const Triangle& _triangleA, const Triangle& _triangleB) + { + const Vec3 baA = sub(_triangleA.v1, _triangleA.v0); + const Vec3 cbA = sub(_triangleA.v2, _triangleA.v1); + const Vec3 acA = sub(_triangleA.v0, _triangleA.v2); + + const Vec3 baB = sub(_triangleB.v1, _triangleB.v0); + const Vec3 cbB = sub(_triangleB.v2, _triangleB.v1); + const Vec3 acB = sub(_triangleB.v0, _triangleB.v2); + + return overlap(_triangleA, _triangleB, cross(baA, cbA) ) + && overlap(_triangleA, _triangleB, cross(baB, cbB) ) + && overlap(_triangleA, _triangleB, cross(baB, baA) ) + && overlap(_triangleA, _triangleB, cross(baB, cbA) ) + && overlap(_triangleA, _triangleB, cross(baB, acA) ) + && overlap(_triangleA, _triangleB, cross(cbB, baA) ) + && overlap(_triangleA, _triangleB, cross(cbB, cbA) ) + && overlap(_triangleA, _triangleB, cross(cbB, acA) ) + && overlap(_triangleA, _triangleB, cross(acB, baA) ) + && overlap(_triangleA, _triangleB, cross(acB, cbA) ) + && overlap(_triangleA, _triangleB, cross(acB, acA) ) + ; + } + + template<typename Ty> + bool overlap(const Triangle& _triangle, const Ty& _ty) + { + Plane plane(init::None); + calcPlane(plane, _triangle); + + plane.normal = neg(plane.normal); + plane.dist = -plane.dist; + + const LineSegment line = + { + _ty.pos, + _ty.end, + }; + + Hit hit; + if (intersect(line, plane, &hit) ) + { + return true; + } + + const Vec3 pos = closestPoint(plane, hit.pos); + const Vec3 uvw = barycentric(_triangle, pos); + + const float nr = -_ty.radius; + + if (uvw.x >= nr + && uvw.y >= nr + && uvw.z >= nr) + { + return true; + } + + const LineSegment ab = LineSegment{_triangle.v0, _triangle.v1}; + const LineSegment bc = LineSegment{_triangle.v1, _triangle.v2}; + const LineSegment ca = LineSegment{_triangle.v2, _triangle.v0}; + + float ta0 = 0.0f, tb0 = 0.0f; + const bool i0 = intersect(ta0, tb0, ab, line); + + float ta1, tb1; + const bool i1 = intersect(ta1, tb1, bc, line); + + float ta2, tb2; + const bool i2 = intersect(ta2, tb2, ca, line); + + if (!i0 + || !i1 + || !i2) + { + return false; + } + + ta0 = clamp(ta0, 0.0f, 1.0f); + ta1 = clamp(ta1, 0.0f, 1.0f); + ta2 = clamp(ta2, 0.0f, 1.0f); + tb0 = clamp(tb0, 0.0f, 1.0f); + tb1 = clamp(tb1, 0.0f, 1.0f); + tb2 = clamp(tb2, 0.0f, 1.0f); + + const Vec3 pa0 = getPointAt(ab, ta0); + const Vec3 pa1 = getPointAt(bc, ta1); + const Vec3 pa2 = getPointAt(ca, ta2); + + const Vec3 pb0 = getPointAt(line, tb0); + const Vec3 pb1 = getPointAt(line, tb1); + const Vec3 pb2 = getPointAt(line, tb2); + + const float d0 = distanceSq(pa0, pb0); + const float d1 = distanceSq(pa1, pb1); + const float d2 = distanceSq(pa2, pb2); + + if (d0 <= d1 + && d0 <= d2) + { + return overlap(_ty, pa0); + } + else if (d1 <= d2) + { + return overlap(_ty, pa1); + } + + return overlap(_ty, pa2); + } + + bool overlap(const Triangle& _triangle, const Cylinder& _cylinder) + { + return overlap<Cylinder>(_triangle, _cylinder); + } + + bool overlap(const Triangle& _triangle, const Capsule& _capsule) + { + return overlap<Capsule>(_triangle, _capsule); + } + + bool overlap(const Triangle& _triangle, const Cone& _cone) + { + const LineSegment ab = LineSegment{_triangle.v0, _triangle.v1}; + const LineSegment bc = LineSegment{_triangle.v1, _triangle.v2}; + const LineSegment ca = LineSegment{_triangle.v2, _triangle.v0}; + + const LineSegment line = + { + _cone.pos, + _cone.end, + }; + + float ta0 = 0.0f, tb0 = 0.0f; + const bool i0 = intersect(ta0, tb0, ab, line); + + float ta1, tb1; + const bool i1 = intersect(ta1, tb1, bc, line); + + float ta2, tb2; + const bool i2 = intersect(ta2, tb2, ca, line); + + if (!i0 + || !i1 + || !i2) + { + return false; + } + + ta0 = clamp(ta0, 0.0f, 1.0f); + ta1 = clamp(ta1, 0.0f, 1.0f); + ta2 = clamp(ta2, 0.0f, 1.0f); + tb0 = clamp(tb0, 0.0f, 1.0f); + tb1 = clamp(tb1, 0.0f, 1.0f); + tb2 = clamp(tb2, 0.0f, 1.0f); + + const Vec3 pa0 = getPointAt(ab, ta0); + const Vec3 pa1 = getPointAt(bc, ta1); + const Vec3 pa2 = getPointAt(ca, ta2); + + const Vec3 pb0 = getPointAt(line, tb0); + const Vec3 pb1 = getPointAt(line, tb1); + const Vec3 pb2 = getPointAt(line, tb2); + + const float d0 = distanceSq(pa0, pb0); + const float d1 = distanceSq(pa1, pb1); + const float d2 = distanceSq(pa2, pb2); + + if (d0 <= d1 + && d0 <= d2) + { + return overlap(_cone, pa0); + } + else if (d1 <= d2) + { + return overlap(_cone, pa1); + } + + return overlap(_cone, pa2); + } + + bool overlap(const Triangle& _triangle, const Disk& _disk) + { + if (!overlap(_triangle, Sphere{_disk.center, _disk.radius}) ) + { + return false; + } + + Plane plane(init::None); + calcPlane(plane, _disk.normal, _disk.center); + + return overlap(_triangle, plane); + } + + bool overlap(const Triangle& _triangle, const Obb& _obb) + { + const Srt srt = toSrt(_obb.mtx); + + Aabb aabb; + toAabb(aabb, srt.scale); + + const Quaternion invRotation = invert(srt.rotation); + + const Triangle triangle = + { + mul(sub(_triangle.v0, srt.translation), invRotation), + mul(sub(_triangle.v1, srt.translation), invRotation), + mul(sub(_triangle.v2, srt.translation), invRotation), + }; + + return overlap(triangle, aabb); + } + +} // namespace bx diff --git a/3rdparty/bx/src/bx.cpp b/3rdparty/bx/src/bx.cpp index 659cb5917cf..45b4d7528a7 100644 --- a/3rdparty/bx/src/bx.cpp +++ b/3rdparty/bx/src/bx.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/debug.h> #include <bx/readerwriter.h> @@ -44,29 +43,29 @@ namespace bx #endif // BX_CRT_NONE } - void memCopy(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch, uint32_t _dstPitch) + void memCopy( + void* _dst + , uint32_t _dstStride + , const void* _src + , uint32_t _srcStride + , uint32_t _stride + , uint32_t _numStrides + ) { - const uint8_t* src = (const uint8_t*)_src; - uint8_t* dst = (uint8_t*)_dst; - - for (uint32_t ii = 0; ii < _num; ++ii) + if (_stride == _srcStride + && _stride == _dstStride) { - memCopy(dst, src, _size); - src += _srcPitch; - dst += _dstPitch; + memCopy(_dst, _src, _stride*_numStrides); + return; } - } - /// - void gather(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch) - { - memCopy(_dst, _src, _size, _num, _srcPitch, _size); - } + const uint8_t* src = (const uint8_t*)_src; + uint8_t* dst = (uint8_t*)_dst; - /// - void scatter(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _dstPitch) - { - memCopy(_dst, _src, _size, _num, _size, _dstPitch); + for (uint32_t ii = 0; ii < _numStrides; ++ii, src += _srcStride, dst += _dstStride) + { + memCopy(dst, src, _stride); + } } void memMoveRef(void* _dst, const void* _src, size_t _numBytes) @@ -102,6 +101,31 @@ namespace bx #endif // BX_CRT_NONE } + void memMove( + void* _dst + , uint32_t _dstStride + , const void* _src + , uint32_t _srcStride + , uint32_t _stride + , uint32_t _numStrides + ) + { + if (_stride == _srcStride + && _stride == _dstStride) + { + memMove(_dst, _src, _stride*_numStrides); + return; + } + + const uint8_t* src = (const uint8_t*)_src; + uint8_t* dst = (uint8_t*)_dst; + + for (uint32_t ii = 0; ii < _numStrides; ++ii, src += _srcStride, dst += _dstStride) + { + memMove(dst, src, _stride); + } + } + void memSetRef(void* _dst, uint8_t _ch, size_t _numBytes) { uint8_t* dst = (uint8_t*)_dst; @@ -121,6 +145,22 @@ namespace bx #endif // BX_CRT_NONE } + void memSet(void* _dst, uint32_t _dstStride, uint8_t _ch, uint32_t _stride, uint32_t _num) + { + if (_stride == _dstStride) + { + memSet(_dst, _ch, _stride*_num); + return; + } + + uint8_t* dst = (uint8_t*)_dst; + + for (uint32_t ii = 0; ii < _num; ++ii, dst += _dstStride) + { + memSet(dst, _ch, _stride); + } + } + int32_t memCmpRef(const void* _lhs, const void* _rhs, size_t _numBytes) { const char* lhs = (const char*)_lhs; @@ -144,4 +184,16 @@ namespace bx #endif // BX_CRT_NONE } + /// + void gather(void* _dst, const void* _src, uint32_t _srcStride, uint32_t _stride, uint32_t _numStrides) + { + memMove(_dst, _stride, _src, _srcStride, _stride, _numStrides); + } + + /// + void scatter(void* _dst, uint32_t _dstStride, const void* _src, uint32_t _stride, uint32_t _numStrides) + { + memMove(_dst, _dstStride, _src, _stride, _stride, _numStrides); + } + } // namespace bx diff --git a/3rdparty/bx/src/bx_p.h b/3rdparty/bx/src/bx_p.h deleted file mode 100644 index d4b00084de3..00000000000 --- a/3rdparty/bx/src/bx_p.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause - */ - -#ifndef BX_P_H_HEADER_GUARD -#define BX_P_H_HEADER_GUARD - -#ifndef BX_CONFIG_DEBUG -# define BX_CONFIG_DEBUG 0 -#endif // BX_CONFIG_DEBUG - -#if BX_CONFIG_DEBUG -# define BX_TRACE _BX_TRACE -# define BX_WARN _BX_WARN -# define BX_CHECK _BX_CHECK -# define BX_CONFIG_ALLOCATOR_DEBUG 1 -#endif // BX_CONFIG_DEBUG - -#define _BX_TRACE(_format, ...) \ - BX_MACRO_BLOCK_BEGIN \ - bx::debugPrintf(__FILE__ "(" BX_STRINGIZE(__LINE__) "): BX " _format "\n", ##__VA_ARGS__); \ - BX_MACRO_BLOCK_END - -#define _BX_WARN(_condition, _format, ...) \ - BX_MACRO_BLOCK_BEGIN \ - if (!BX_IGNORE_C4127(_condition) ) \ - { \ - BX_TRACE("WARN " _format, ##__VA_ARGS__); \ - } \ - BX_MACRO_BLOCK_END - -#define _BX_CHECK(_condition, _format, ...) \ - BX_MACRO_BLOCK_BEGIN \ - if (!BX_IGNORE_C4127(_condition) ) \ - { \ - BX_TRACE("CHECK " _format, ##__VA_ARGS__); \ - bx::debugBreak(); \ - } \ - BX_MACRO_BLOCK_END - -#include <bx/bx.h> -#include <bx/debug.h> - -#endif // BX_P_H_HEADER_GUARD diff --git a/3rdparty/bx/src/commandline.cpp b/3rdparty/bx/src/commandline.cpp index df322560b56..ca31636ca76 100644 --- a/3rdparty/bx/src/commandline.cpp +++ b/3rdparty/bx/src/commandline.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/commandline.h> #include <bx/string.h> @@ -39,7 +38,7 @@ namespace bx switch (state) { case SkipWhitespace: - for (; isSpace(*curr); ++curr) {}; // skip whitespace + for (; isSpace(*curr) && *curr!=_term; ++curr) {}; // skip whitespace state = SetTerm; break; @@ -47,7 +46,7 @@ namespace bx if ('"' == *curr) { term = '"'; - ++curr; // skip begining quote + ++curr; // skip beginning quote } else { diff --git a/3rdparty/bx/src/crtnone.cpp b/3rdparty/bx/src/crtnone.cpp index 93579515c7f..6abdeeeb67f 100644 --- a/3rdparty/bx/src/crtnone.cpp +++ b/3rdparty/bx/src/crtnone.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/debug.h> #include <bx/file.h> #include <bx/math.h> @@ -75,7 +74,7 @@ extern "C" char* strcat(char* _dst, const char* _src) extern "C" const char* strchr(const char* _str, int _ch) { - return bx::strFind(_str, _ch); + return bx::strFind(_str, _ch).getPtr(); } extern "C" int32_t strcmp(const char* _lhs, const char* _rhs) @@ -95,12 +94,12 @@ extern "C" int32_t strcasecmp(const char* _lhs, const char* _rhs) extern "C" const char* strstr(const char* _str, const char* _find) { - return bx::strFind(_str, _find); + return bx::strFind(_str, _find).getPtr(); } extern "C" void qsort(void* _base, size_t _num, size_t _size, bx::ComparisonFn _fn) { - BX_CHECK(_num <= UINT32_MAX && _size <= UINT32_MAX, ""); + BX_ASSERT(_num <= UINT32_MAX && _size <= UINT32_MAX, ""); return bx::quickSort(_base, _num, _size, _fn); } @@ -338,6 +337,12 @@ extern "C" int fscanf(FILE* _stream, const char* _format, ...) return -1; } +extern "C" int __isoc99_fscanf(FILE* _stream, const char* _format, ...) +{ + BX_UNUSED(_stream, _format); + return -1; +} + FILE * stdout; extern "C" FILE* fopen(const char* _filename, const char* _mode) @@ -601,6 +606,11 @@ extern "C" void free(void* _ptr) crt0::realloc(_ptr, 0); } +extern "C" void exit(int _exitCode) +{ + crt0::exit(_exitCode); +} + #endif // BX_PLATFORM_* extern "C" void abort(void) @@ -621,6 +631,10 @@ void operator delete(void*) { } +void operator delete(void*, size_t) +{ +} + extern "C" void __cxa_pure_virtual(void) { } diff --git a/3rdparty/bx/src/debug.cpp b/3rdparty/bx/src/debug.cpp index 8e8bae122a6..062df287d7a 100644 --- a/3rdparty/bx/src/debug.cpp +++ b/3rdparty/bx/src/debug.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/debug.h> #include <bx/string.h> // isPrint #include <bx/readerwriter.h> // WriterI @@ -24,8 +23,8 @@ extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _ # include <CoreFoundation/CFString.h> extern "C" void NSLog(CFStringRef _format, ...); # endif // defined(__OBJC__) -#elif 0 // BX_PLATFORM_EMSCRIPTEN -# include <emscripten.h> +#elif BX_PLATFORM_EMSCRIPTEN +# include <emscripten/emscripten.h> #else # include <stdio.h> // fputs, fflush #endif // BX_PLATFORM_WINDOWS @@ -43,6 +42,17 @@ namespace bx // NaCl doesn't like int 3: // NativeClient: NaCl module load failed: Validation failure. File violates Native Client safety rules. __asm__ ("int $3"); +#elif BX_PLATFORM_EMSCRIPTEN + emscripten_log(0 + | EM_LOG_CONSOLE + | EM_LOG_ERROR + | EM_LOG_C_STACK + | EM_LOG_JS_STACK + , "debugBreak!" + ); + // Doing emscripten_debugger() disables asm.js validation due to an emscripten bug + //emscripten_debugger(); + EM_ASM({ debugger; }); #else // cross platform implementation int* int3 = (int*)3L; *int3 = 3; @@ -69,7 +79,7 @@ namespace bx # else NSLog(__CFStringMakeConstantString("%s"), _out); # endif // defined(__OBJC__) -#elif 0 // BX_PLATFORM_EMSCRIPTEN +#elif BX_PLATFORM_EMSCRIPTEN emscripten_log(EM_LOG_CONSOLE, "%s", _out); #else fputs(_out, stdout); @@ -137,7 +147,7 @@ namespace bx if (NULL != _data) { - const uint8_t* data = reinterpret_cast<const uint8_t*>(_data); + const uint8_t* data = (const uint8_t*)_data; char hex[HEX_DUMP_WIDTH*3+1]; char ascii[HEX_DUMP_WIDTH+1]; uint32_t hexPos = 0; diff --git a/3rdparty/bx/src/dtoa.cpp b/3rdparty/bx/src/dtoa.cpp index 3c23ea516e1..a36314ed98d 100644 --- a/3rdparty/bx/src/dtoa.cpp +++ b/3rdparty/bx/src/dtoa.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/cpu.h> #include <bx/math.h> #include <bx/string.h> @@ -74,8 +73,8 @@ namespace bx DiyFp operator-(const DiyFp& rhs) const { - BX_CHECK(e == rhs.e, ""); - BX_CHECK(f >= rhs.f, ""); + BX_ASSERT(e == rhs.e, ""); + BX_ASSERT(f >= rhs.f, ""); return DiyFp(f - rhs.f, e); } @@ -224,7 +223,7 @@ namespace bx uint32_t index = static_cast<uint32_t>( (k >> 3) + 1); *K = -(-348 + static_cast<int32_t>(index << 3) ); // decimal exponent no need lookup table - BX_CHECK(index < sizeof(s_kCachedPowers_F) / sizeof(s_kCachedPowers_F[0]), ""); + BX_ASSERT(index < sizeof(s_kCachedPowers_F) / sizeof(s_kCachedPowers_F[0]), ""); return DiyFp(s_kCachedPowers_F[index], s_kCachedPowers_E[index]); } @@ -1120,7 +1119,7 @@ namespace bx bool fromString(int32_t* _out, const StringView& _str) { - StringView str = bx::strLTrimSpace(_str); + StringView str = strLTrimSpace(_str); const char* ptr = str.getPtr(); const char* term = str.getTerm(); diff --git a/3rdparty/bx/src/easing.cpp b/3rdparty/bx/src/easing.cpp index e9f82b280de..38f35ec2cad 100644 --- a/3rdparty/bx/src/easing.cpp +++ b/3rdparty/bx/src/easing.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/easing.h> namespace bx diff --git a/3rdparty/bx/src/file.cpp b/3rdparty/bx/src/file.cpp index 8a282cab91f..dab862006ae 100644 --- a/3rdparty/bx/src/file.cpp +++ b/3rdparty/bx/src/file.cpp @@ -1,24 +1,33 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/file.h> +#ifndef BX_CONFIG_CRT_FILE_READER_WRITER +# define BX_CONFIG_CRT_FILE_READER_WRITER !BX_CRT_NONE +#endif // BX_CONFIG_CRT_FILE_READER_WRITER + +#ifndef BX_CONFIG_CRT_DIRECTORY_READER +# define BX_CONFIG_CRT_DIRECTORY_READER (BX_PLATFORM_OS_DESKTOP && !BX_CRT_NONE) +#endif // BX_CONFIG_CRT_DIRECTORY_READER + #if BX_CRT_NONE # include "crt0.h" #else -# include <stdio.h> -# include <sys/stat.h> +# if BX_CONFIG_CRT_DIRECTORY_READER +# include <dirent.h> +# endif // BX_CONFIG_CRT_DIRECTORY_READER +# include <stdio.h> // remove +# include <sys/stat.h> // stat, mkdir +# if BX_CRT_MSVC +# include <direct.h> // _getcwd +# else +# include <unistd.h> // getcwd +# endif // BX_CRT_MSVC #endif // !BX_CRT_NONE -#ifndef BX_CONFIG_CRT_FILE_READER_WRITER -# define BX_CONFIG_CRT_FILE_READER_WRITER !(0 \ - || BX_CRT_NONE \ - ) -#endif // BX_CONFIG_CRT_FILE_READER_WRITER - namespace bx { class NoopWriterImpl : public FileWriterI @@ -64,6 +73,7 @@ namespace bx # elif 0 \ || BX_PLATFORM_ANDROID \ || BX_PLATFORM_BSD \ + || BX_PLATFORM_HAIKU \ || BX_PLATFORM_IOS \ || BX_PLATFORM_OSX # define fseeko64 fseeko @@ -89,18 +99,18 @@ namespace bx virtual bool open(const FilePath& _filePath, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } - m_file = fopen(_filePath.get(), "rb"); + m_file = fopen(_filePath.getCPtr(), "rb"); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileReader: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileReader: Failed to open file."); return false; } @@ -120,26 +130,26 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); fseeko64(m_file, _offset, _whence); return ftello64(m_file); } virtual int32_t read(void* _data, int32_t _size, Error* _err) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = (int32_t)fread(_data, 1, _size, m_file); if (size != _size) { if (0 != feof(m_file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "FileReader: EOF."); + BX_ERROR_SET(_err, kErrorReaderWriterEof, "FileReader: EOF."); } else if (0 != ferror(m_file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "FileReader: read error."); + BX_ERROR_SET(_err, kErrorReaderWriterRead, "FileReader: read error."); } return size >= 0 ? size : 0; @@ -169,19 +179,19 @@ namespace bx virtual bool open(const FilePath& _filePath, bool _append, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } - m_file = fopen(_filePath.get(), _append ? "ab" : "wb"); + m_file = fopen(_filePath.getCPtr(), _append ? "ab" : "wb"); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileWriter: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileWriter: Failed to open file."); return false; } @@ -201,20 +211,20 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); fseeko64(m_file, _offset, _whence); return ftello64(m_file); } virtual int32_t write(const void* _data, int32_t _size, Error* _err) override { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != m_file, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = (int32_t)fwrite(_data, 1, _size, m_file); if (size != _size) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "FileWriter: write failed."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "FileWriter: write failed."); return size >= 0 ? size : 0; } @@ -261,19 +271,19 @@ namespace bx virtual bool open(const FilePath& _filePath, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (0 != m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } - m_fd = crt0::open(_filePath.get(), crt0::Open::Read, 0); + m_fd = crt0::open(_filePath.getCPtr(), crt0::Open::Read, 0); if (0 >= m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileReader: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileReader: Failed to open file."); return false; } @@ -293,14 +303,14 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); return crt0::seek(m_fd, _offset, crt0::Whence::Enum(_whence) ); } virtual int32_t read(void* _data, int32_t _size, Error* _err) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = crt0::read(m_fd, _data, _size); if (size != _size) @@ -308,11 +318,11 @@ namespace bx BX_UNUSED(_err); // if (0 != feof(m_file) ) // { -// BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "FileReader: EOF."); +// BX_ERROR_SET(_err, kErrorReaderWriterEof, "FileReader: EOF."); // } // else if (0 != ferror(m_file) ) // { -// BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "FileReader: read error."); +// BX_ERROR_SET(_err, kErrorReaderWriterRead, "FileReader: read error."); // } return size >= 0 ? size : 0; @@ -342,19 +352,19 @@ namespace bx virtual bool open(const FilePath& _filePath, bool _append, Error* _err) override { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (0 != m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "FileReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "FileReader: File is already open."); return false; } - m_fd = crt0::open(_filePath.get(), _append ? crt0::Open::Append : crt0::Open::Write, 0600); + m_fd = crt0::open(_filePath.getCPtr(), _append ? crt0::Open::Append : crt0::Open::Write, 0600); if (0 >= m_fd) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "FileWriter: Failed to open file."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "FileWriter: Failed to open file."); return false; } @@ -374,19 +384,19 @@ namespace bx virtual int64_t seek(int64_t _offset, Whence::Enum _whence) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); return crt0::seek(m_fd, _offset, crt0::Whence::Enum(_whence) ); } virtual int32_t write(const void* _data, int32_t _size, Error* _err) override { - BX_CHECK(0 != m_fd, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(0 != m_fd, "Reader/Writer file is not open."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); int32_t size = crt0::write(m_fd, _data, _size); if (size != _size) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "FileWriter: write failed."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "FileWriter: write failed."); return size >= 0 ? size : 0; } @@ -553,18 +563,193 @@ namespace bx return impl->write(_data, _size, _err); } - bool stat(const FilePath& _filePath, FileInfo& _outFileInfo) +#if BX_CONFIG_CRT_DIRECTORY_READER + + class DirectoryReaderImpl : public ReaderOpenI, public CloserI, public ReaderI + { + public: + DirectoryReaderImpl() + : m_dir(NULL) + , m_pos(0) + { + } + + virtual ~DirectoryReaderImpl() + { + close(); + } + + virtual bool open(const FilePath& _filePath, Error* _err) override + { + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + m_dir = opendir(_filePath.getCPtr() ); + + if (NULL == m_dir) + { + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "DirectoryReader: Failed to open directory."); + return false; + } + + m_pos = 0; + + return true; + } + + virtual void close() override + { + if (NULL != m_dir) + { + closedir(m_dir); + m_dir = NULL; + } + } + + virtual int32_t read(void* _data, int32_t _size, Error* _err) override + { + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + int32_t total = 0; + + uint8_t* out = (uint8_t*)_data; + + while (0 < _size) + { + if (0 == m_pos) + { + if (!fetch(m_cache, m_dir) ) + { + BX_ERROR_SET(_err, kErrorReaderWriterEof, "DirectoryReader: EOF."); + return total; + } + } + + const uint8_t* src = (const uint8_t*)&m_cache; + int32_t size = min<int32_t>(_size, sizeof(m_cache)-m_pos); + memCopy(&out[total], &src[m_pos], size); + total += size; + _size -= size; + + m_pos += size; + m_pos %= sizeof(m_cache); + } + + return total; + } + + static bool fetch(FileInfo& _out, DIR* _dir) + { + for (;;) + { + const dirent* item = readdir(_dir); + + if (NULL == item) + { + break; + } + + if (0 != (item->d_type & DT_DIR) ) + { + _out.type = FileType::Dir; + _out.size = UINT64_MAX; + _out.filePath.set(item->d_name); + return true; + } + + if (0 != (item->d_type & DT_REG) ) + { + _out.type = FileType::File; + _out.size = UINT64_MAX; + _out.filePath.set(item->d_name); + return true; + } + } + + return false; + } + + FileInfo m_cache; + DIR* m_dir; + int32_t m_pos; + }; + +#else + + class DirectoryReaderImpl : public ReaderOpenI, public CloserI, public ReaderI + { + public: + DirectoryReaderImpl() + { + } + + virtual ~DirectoryReaderImpl() + { + } + + virtual bool open(const FilePath& _filePath, Error* _err) override + { + BX_UNUSED(_filePath); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "DirectoryReader: Failed to open directory."); + return false; + } + + virtual void close() override + { + } + + virtual int32_t read(void* _data, int32_t _size, Error* _err) override + { + BX_UNUSED(_data, _size); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ERROR_SET(_err, kErrorReaderWriterEof, "DirectoryReader: EOF."); + return 0; + } + }; + +#endif // BX_CONFIG_CRT_DIRECTORY_READER + + DirectoryReader::DirectoryReader() + { + BX_STATIC_ASSERT(sizeof(DirectoryReaderImpl) <= sizeof(m_internal) ); + BX_PLACEMENT_NEW(m_internal, DirectoryReaderImpl); + } + + DirectoryReader::~DirectoryReader() + { + DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal); + impl->~DirectoryReaderImpl(); + } + + bool DirectoryReader::open(const FilePath& _filePath, Error* _err) + { + DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal); + return impl->open(_filePath, _err); + } + + void DirectoryReader::close() + { + DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal); + impl->close(); + } + + int32_t DirectoryReader::read(void* _data, int32_t _size, Error* _err) + { + DirectoryReaderImpl* impl = reinterpret_cast<DirectoryReaderImpl*>(m_internal); + return impl->read(_data, _size, _err); + } + + bool stat(FileInfo& _outFileInfo, const FilePath& _filePath) { #if BX_CRT_NONE BX_UNUSED(_filePath, _outFileInfo); return false; #else - _outFileInfo.m_size = 0; - _outFileInfo.m_type = FileInfo::Count; + _outFileInfo.size = 0; + _outFileInfo.type = FileType::Count; # if BX_COMPILER_MSVC struct ::_stat64 st; - int32_t result = ::_stat64(_filePath.get(), &st); + int32_t result = ::_stat64(_filePath.getCPtr(), &st); if (0 != result) { @@ -573,15 +758,15 @@ namespace bx if (0 != (st.st_mode & _S_IFREG) ) { - _outFileInfo.m_type = FileInfo::Regular; + _outFileInfo.type = FileType::File; } else if (0 != (st.st_mode & _S_IFDIR) ) { - _outFileInfo.m_type = FileInfo::Directory; + _outFileInfo.type = FileType::Dir; } # else struct ::stat st; - int32_t result = ::stat(_filePath.get(), &st); + int32_t result = ::stat(_filePath.getCPtr(), &st); if (0 != result) { return false; @@ -589,18 +774,185 @@ namespace bx if (0 != (st.st_mode & S_IFREG) ) { - _outFileInfo.m_type = FileInfo::Regular; + _outFileInfo.type = FileType::File; } else if (0 != (st.st_mode & S_IFDIR) ) { - _outFileInfo.m_type = FileInfo::Directory; + _outFileInfo.type = FileType::Dir; } # endif // BX_COMPILER_MSVC - _outFileInfo.m_size = st.st_size; + _outFileInfo.size = st.st_size; return true; #endif // BX_CRT_NONE } + bool make(const FilePath& _filePath, Error* _err) + { + BX_ERROR_SCOPE(_err); + + if (!_err->isOk() ) + { + return false; + } + +#if BX_CRT_MSVC + int32_t result = ::_mkdir(_filePath.getCPtr() ); +#elif BX_CRT_MINGW + int32_t result = ::mkdir(_filePath.getCPtr()); +#elif BX_CRT_NONE + BX_UNUSED(_filePath); + int32_t result = -1; +#else + int32_t result = ::mkdir(_filePath.getCPtr(), 0700); +#endif // BX_CRT_MSVC + + if (0 != result) + { + BX_ERROR_SET(_err, kErrorAccess, "The parent directory does not allow write permission to the process."); + return false; + } + + return true; + } + + bool makeAll(const FilePath& _filePath, Error* _err) + { + BX_ERROR_SCOPE(_err); + + if (!_err->isOk() ) + { + return false; + } + + FileInfo fi; + + if (stat(fi, _filePath) ) + { + if (FileType::Dir == fi.type) + { + return true; + } + + BX_ERROR_SET(_err, kErrorNotDirectory, "File already exist, and is not directory."); + return false; + } + + const StringView dir = strRTrim(_filePath, "/"); + const StringView slash = strRFind(dir, '/'); + + if (!slash.isEmpty() + && slash.getPtr() - dir.getPtr() > 1) + { + if (!makeAll(StringView(dir.getPtr(), slash.getPtr() ), _err) ) + { + return false; + } + } + + FilePath path(dir); + return make(path, _err); + } + + bool remove(const FilePath& _filePath, Error* _err) + { + BX_ERROR_SCOPE(_err); + + if (!_err->isOk() ) + { + return false; + } + +#if BX_CRT_MSVC + int32_t result = -1; + FileInfo fi; + if (stat(fi, _filePath) ) + { + if (FileType::Dir == fi.type) + { + result = ::_rmdir(_filePath.getCPtr() ); + } + else + { + result = ::remove(_filePath.getCPtr() ); + } + } +#elif BX_CRT_NONE + BX_UNUSED(_filePath); + int32_t result = -1; +#else + int32_t result = ::remove(_filePath.getCPtr() ); +#endif // BX_CRT_MSVC + + if (0 != result) + { + BX_ERROR_SET(_err, kErrorAccess, "The parent directory does not allow write permission to the process."); + return false; + } + + return true; + } + + bool removeAll(const FilePath& _filePath, Error* _err) + { + BX_ERROR_SCOPE(_err); + + if (remove(_filePath, _err) ) + { + return true; + } + + _err->reset(); + + FileInfo fi; + + if (!stat(fi, _filePath) ) + { + BX_ERROR_SET(_err, kErrorAccess, "The parent directory does not allow write permission to the process."); + return false; + } + + if (FileType::Dir != fi.type) + { + BX_ERROR_SET(_err, kErrorNotDirectory, "File already exist, and is not directory."); + return false; + } + + Error err; + DirectoryReader dr; + + if (!open(&dr, _filePath, &err) ) + { + BX_ERROR_SET(_err, kErrorNotDirectory, "File already exist, and is not directory."); + return false; + } + + while (err.isOk() ) + { + read(&dr, fi, &err); + + if (err.isOk() ) + { + if (0 == strCmp(fi.filePath, ".") + || 0 == strCmp(fi.filePath, "..") ) + { + continue; + } + + FilePath path(_filePath); + path.join(fi.filePath); + if (!removeAll(path, _err) ) + { + _err->reset(); + break; + } + } + } + + close(&dr); + + return remove(_filePath, _err); + } + } // namespace bx diff --git a/3rdparty/bx/src/filepath.cpp b/3rdparty/bx/src/filepath.cpp index 0ee2fc171ad..892bf80e48c 100644 --- a/3rdparty/bx/src/filepath.cpp +++ b/3rdparty/bx/src/filepath.cpp @@ -1,24 +1,19 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/file.h> #include <bx/os.h> #include <bx/readerwriter.h> #if !BX_CRT_NONE -# include <stdio.h> // remove -# include <dirent.h> // opendir - # if BX_CRT_MSVC # include <direct.h> // _getcwd # else -# include <sys/stat.h> // mkdir # include <unistd.h> // getcwd # endif // BX_CRT_MSVC -#endif // 0 +#endif // !BX_CRT_NONE #if BX_PLATFORM_WINDOWS extern "C" __declspec(dllimport) unsigned long __stdcall GetTempPathA(unsigned long _max, char* _ptr); @@ -154,7 +149,7 @@ namespace bx return size; } - static bool getEnv(char* _out, uint32_t* _inOutSize, const StringView& _name, FileInfo::Enum _type) + static bool getEnv(char* _out, uint32_t* _inOutSize, const StringView& _name, FileType::Enum _type) { uint32_t len = *_inOutSize; *_out = '\0'; @@ -162,8 +157,8 @@ namespace bx if (getEnv(_out, &len, _name) ) { FileInfo fi; - if (stat(_out, fi) - && _type == fi.m_type) + if (stat(fi, _out) + && _type == fi.type) { *_inOutSize = len; return true; @@ -204,9 +199,9 @@ namespace bx { return false #if BX_PLATFORM_WINDOWS - || getEnv(_out, _inOutSize, "USERPROFILE", FileInfo::Directory) + || getEnv(_out, _inOutSize, "USERPROFILE", FileType::Dir) #endif // BX_PLATFORM_WINDOWS - || getEnv(_out, _inOutSize, "HOME", FileInfo::Directory) + || getEnv(_out, _inOutSize, "HOME", FileType::Dir) ; } @@ -232,7 +227,7 @@ namespace bx { uint32_t len = *_inOutSize; *_out = '\0'; - bool ok = getEnv(_out, &len, *tmp, FileInfo::Directory); + bool ok = getEnv(_out, &len, *tmp, FileType::Dir); if (ok && len != 0 @@ -244,8 +239,8 @@ namespace bx } FileInfo fi; - if (stat("/tmp", fi) - && FileInfo::Directory == fi.m_type) + if (stat(fi, "/tmp") + && FileType::Dir == fi.type) { strCopy(_out, *_inOutSize, "/tmp"); *_inOutSize = 4; @@ -336,7 +331,12 @@ namespace bx set(tmp); } - const char* FilePath::get() const + FilePath::operator StringView() const + { + return StringView(m_filePath, strLen(m_filePath) ); + } + + const char* FilePath::getCPtr() const { return m_filePath; } @@ -360,7 +360,7 @@ namespace bx return StringView(fileName.getPtr()+1); } - return get(); + return getCPtr(); } StringView FilePath::getBaseName() const @@ -385,7 +385,8 @@ namespace bx const StringView fileName = getFileName(); if (!fileName.isEmpty() ) { - return strFind(fileName, '.'); + const StringView dot = strFind(fileName, '.'); + return StringView(dot.getPtr(), fileName.getTerm() ); } return StringView(); @@ -403,171 +404,4 @@ namespace bx return 0 == strCmp(m_filePath, "."); } - bool make(const FilePath& _filePath, Error* _err) - { - BX_ERROR_SCOPE(_err); - - if (!_err->isOk() ) - { - return false; - } - -#if BX_CRT_MSVC - int32_t result = ::_mkdir(_filePath.get() ); -#elif BX_CRT_MINGW - int32_t result = ::mkdir(_filePath.get()); -#elif BX_CRT_NONE - BX_UNUSED(_filePath); - int32_t result = -1; -#else - int32_t result = ::mkdir(_filePath.get(), 0700); -#endif // BX_CRT_MSVC - - if (0 != result) - { - BX_ERROR_SET(_err, BX_ERROR_ACCESS, "The parent directory does not allow write permission to the process."); - return false; - } - - return true; - } - - bool makeAll(const FilePath& _filePath, Error* _err) - { - BX_ERROR_SCOPE(_err); - - if (!_err->isOk() ) - { - return false; - } - - FileInfo fi; - - if (stat(_filePath, fi) ) - { - if (FileInfo::Directory == fi.m_type) - { - return true; - } - - BX_ERROR_SET(_err, BX_ERROR_NOT_DIRECTORY, "File already exist, and is not directory."); - return false; - } - - const StringView dir = strRTrim(_filePath.get(), "/"); - const StringView slash = strRFind(dir, '/'); - - if (!slash.isEmpty() - && slash.getPtr() - dir.getPtr() > 1) - { - if (!makeAll(StringView(dir.getPtr(), slash.getPtr() ), _err) ) - { - return false; - } - } - - FilePath path(dir); - return make(path, _err); - } - - bool remove(const FilePath& _filePath, Error* _err) - { - BX_ERROR_SCOPE(_err); - - if (!_err->isOk() ) - { - return false; - } - -#if BX_CRT_MSVC - int32_t result = -1; - FileInfo fi; - if (stat(_filePath, fi) ) - { - if (FileInfo::Directory == fi.m_type) - { - result = ::_rmdir(_filePath.get() ); - } - else - { - result = ::remove(_filePath.get() ); - } - } -#elif BX_CRT_NONE - BX_UNUSED(_filePath); - int32_t result = -1; -#else - int32_t result = ::remove(_filePath.get() ); -#endif // BX_CRT_MSVC - - if (0 != result) - { - BX_ERROR_SET(_err, BX_ERROR_ACCESS, "The parent directory does not allow write permission to the process."); - return false; - } - - return true; - } - - bool removeAll(const FilePath& _filePath, Error* _err) - { - BX_ERROR_SCOPE(_err); - - if (remove(_filePath, _err) ) - { - return true; - } - - _err->reset(); - - FileInfo fi; - - if (!stat(_filePath, fi) ) - { - BX_ERROR_SET(_err, BX_ERROR_ACCESS, "The parent directory does not allow write permission to the process."); - return false; - } - - if (FileInfo::Directory != fi.m_type) - { - BX_ERROR_SET(_err, BX_ERROR_NOT_DIRECTORY, "File already exist, and is not directory."); - return false; - } - -#if BX_CRT_NONE - BX_UNUSED(_filePath); - return false; -#elif BX_PLATFORM_WINDOWS \ - || BX_PLATFORM_LINUX \ - || BX_PLATFORM_OSX - DIR* dir = opendir(_filePath.get() ); - if (NULL == dir) - { - BX_ERROR_SET(_err, BX_ERROR_NOT_DIRECTORY, "File already exist, and is not directory."); - return false; - } - - for (dirent* item = readdir(dir); NULL != item; item = readdir(dir) ) - { - if (0 == strCmp(item->d_name, ".") - || 0 == strCmp(item->d_name, "..") ) - { - continue; - } - - FilePath path(_filePath); - path.join(item->d_name); - if (!removeAll(path, _err) ) - { - _err->reset(); - break; - } - } - - closedir(dir); -#endif // !BX_CRT_NONE - - return remove(_filePath, _err); - } - } // namespace bx diff --git a/3rdparty/bx/src/hash.cpp b/3rdparty/bx/src/hash.cpp index 7ae5e39cc80..0fcfaaca6c9 100644 --- a/3rdparty/bx/src/hash.cpp +++ b/3rdparty/bx/src/hash.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/hash.h> namespace bx @@ -134,7 +133,7 @@ void HashCrc32::begin(Enum _type) m_table = s_crcTable[_type]; } -void HashCrc32::add(const void* _data, int _len) +void HashCrc32::add(const void* _data, int32_t _len) { const uint8_t* data = (const uint8_t*)_data; @@ -148,4 +147,122 @@ void HashCrc32::add(const void* _data, int _len) m_hash = hash; } +struct HashMurmur2APod +{ + uint32_t m_hash; + uint32_t m_tail; + uint32_t m_count; + uint32_t m_size; +}; +BX_STATIC_ASSERT(sizeof(HashMurmur2A) == sizeof(HashMurmur2APod) ); + +BX_FORCE_INLINE void mmix(uint32_t& _h, uint32_t& _k) +{ + constexpr uint32_t kMurmurMul = 0x5bd1e995; + constexpr uint32_t kMurmurRightShift = 24; + + _k *= kMurmurMul; + _k ^= _k >> kMurmurRightShift; + _k *= kMurmurMul; + _h *= kMurmurMul; + _h ^= _k; +} + +static void mixTail(HashMurmur2APod& _self, const uint8_t*& _data, int32_t& _len) +{ + while (_len + && ( (_len<4) || _self.m_count) + ) + { + _self.m_tail |= (*_data++) << (_self.m_count * 8); + + _self.m_count++; + _len--; + + if (_self.m_count == 4) + { + mmix(_self.m_hash, _self.m_tail); + _self.m_tail = 0; + _self.m_count = 0; + } + } +} + +BX_FORCE_INLINE uint32_t readAligned(const uint8_t* _data) +{ + return *(uint32_t*)_data; +} + +BX_FORCE_INLINE uint32_t readUnaligned(const uint8_t* _data) +{ + if (BX_ENABLED(BX_CPU_ENDIAN_BIG) ) + { + return 0 + | _data[0]<<24 + | _data[1]<<16 + | _data[2]<<8 + | _data[3] + ; + } + else + { + return 0 + | _data[0] + | _data[1]<<8 + | _data[2]<<16 + | _data[3]<<24 + ; + } +} + +typedef uint32_t (*ReadDataFn)(const uint8_t* _data); + +template<ReadDataFn FnT> +static void addData(HashMurmur2APod& _self, const uint8_t* _data, int32_t _len) +{ + while (_len >= 4) + { + uint32_t kk = FnT(_data); + + mmix(_self.m_hash, kk); + + _data += 4; + _len -= 4; + } + + mixTail(_self, _data, _len); +} + +void HashMurmur2A::add(const void* _data, int32_t _len) +{ + HashMurmur2APod& self = *(HashMurmur2APod*)this; + + const uint8_t* data = (const uint8_t*)_data; + + m_size += _len; + mixTail(self, data, _len); + + if (BX_UNLIKELY(!isAligned(data, 4) ) ) + { + addData<readUnaligned>(self, data, _len); + return; + } + + addData<readAligned>(self, data, _len); +} + +uint32_t HashMurmur2A::end() +{ + constexpr uint32_t kMurmurMul = 0x5bd1e995; + + mmix(m_hash, m_tail); + mmix(m_hash, m_size); + + m_hash ^= m_hash >> 13; + m_hash *= kMurmurMul; + m_hash ^= m_hash >> 15; + + return m_hash; +} + } // namespace bx diff --git a/3rdparty/bx/src/math.cpp b/3rdparty/bx/src/math.cpp index ba0676e96bf..8975d5bed25 100644 --- a/3rdparty/bx/src/math.cpp +++ b/3rdparty/bx/src/math.cpp @@ -1,12 +1,13 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/math.h> #include <bx/uint32_t.h> +#include <bx/string.h> + namespace bx { const float kInfinity = bitsToFloat(UINT32_C(0x7f800000) ); @@ -113,7 +114,7 @@ namespace bx if (maxaxy == 0.0f) { - return 0.0f*sign(_y); + return _y < 0.0f ? -0.0f : 0.0f; } const float mxy = minaxy / maxaxy; @@ -126,7 +127,7 @@ namespace bx const float tmp5 = tmp4 * mxy; const float tmp6 = ay > ax ? kPiHalf - tmp5 : tmp5; const float tmp7 = _x < 0.0f ? kPi - tmp6 : tmp6; - const float result = sign(_y)*tmp7; + const float result = _y < 0.0f ? -tmp7 : tmp7; return result; } @@ -239,87 +240,53 @@ namespace bx return result; } - BX_CONST_FUNC float floor(float _a) + void mtxLookAt(float* _result, const Vec3& _eye, const Vec3& _at, const Vec3& _up, Handedness::Enum _handedness) { - if (_a < 0.0f) - { - const float fr = fract(-_a); - const float result = -_a - fr; - - return -(0.0f != fr - ? result + 1.0f - : result) - ; - } - - return _a - fract(_a); - } - - static void mtxLookAtImpl(float* _result, const Vec3& _eye, const Vec3& _view, const Vec3& _up) - { - const Vec3 uxv = cross(_up, _view); + const Vec3 view = normalize( + Handedness::Right == _handedness + ? sub(_eye, _at) + : sub(_at, _eye) + ); + const Vec3 uxv = cross(_up, view); const Vec3 right = normalize(uxv); - const Vec3 up = cross(_view, right); + const Vec3 up = cross(view, right); memSet(_result, 0, sizeof(float)*16); _result[ 0] = right.x; _result[ 1] = up.x; - _result[ 2] = _view.x; + _result[ 2] = view.x; _result[ 4] = right.y; _result[ 5] = up.y; - _result[ 6] = _view.y; + _result[ 6] = view.y; _result[ 8] = right.z; _result[ 9] = up.z; - _result[10] = _view.z; + _result[10] = view.z; _result[12] = -dot(right, _eye); - _result[13] = -dot(up, _eye); - _result[14] = -dot(_view, _eye); + _result[13] = -dot(up, _eye); + _result[14] = -dot(view, _eye); _result[15] = 1.0f; } - void mtxLookAtLh(float* _result, const Vec3& _eye, const Vec3& _at, const Vec3& _up) - { - const Vec3 tmp = sub(_at, _eye); - const Vec3 view = normalize(tmp); - - mtxLookAtImpl(_result, _eye, view, _up); - } - - void mtxLookAtRh(float* _result, const Vec3& _eye, const Vec3& _at, const Vec3& _up) - { - const Vec3 tmp = sub(_eye, _at); - const Vec3 view = normalize(tmp); - - mtxLookAtImpl(_result, _eye, view, _up); - } - - void mtxLookAt(float* _result, const Vec3& _eye, const Vec3& _at, const Vec3& _up) - { - mtxLookAtLh(_result, _eye, _at, _up); - } - - template<Handness::Enum HandnessT> - void mtxProjXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, float _far, bool _oglNdc) + static void mtxProjXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, float _far, bool _homogeneousNdc, Handedness::Enum _handedness) { const float diff = _far-_near; - const float aa = _oglNdc ? ( _far+_near)/diff : _far/diff; - const float bb = _oglNdc ? (2.0f*_far*_near)/diff : _near*aa; + const float aa = _homogeneousNdc ? ( _far+_near)/diff : _far/diff; + const float bb = _homogeneousNdc ? (2.0f*_far*_near)/diff : _near*aa; memSet(_result, 0, sizeof(float)*16); _result[ 0] = _width; _result[ 5] = _height; - _result[ 8] = (Handness::Right == HandnessT) ? _x : -_x; - _result[ 9] = (Handness::Right == HandnessT) ? _y : -_y; - _result[10] = (Handness::Right == HandnessT) ? -aa : aa; - _result[11] = (Handness::Right == HandnessT) ? -1.0f : 1.0f; + _result[ 8] = (Handedness::Right == _handedness) ? _x : -_x; + _result[ 9] = (Handedness::Right == _handedness) ? _y : -_y; + _result[10] = (Handedness::Right == _handedness) ? -aa : aa; + _result[11] = (Handedness::Right == _handedness) ? -1.0f : 1.0f; _result[14] = -bb; } - template<Handness::Enum HandnessT> - void mtxProjImpl(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) + void mtxProj(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _homogeneousNdc, Handedness::Enum _handedness) { const float invDiffRl = 1.0f/(_rt - _lt); const float invDiffUd = 1.0f/(_ut - _dt); @@ -327,96 +294,47 @@ namespace bx const float height = 2.0f*_near * invDiffUd; const float xx = (_rt + _lt) * invDiffRl; const float yy = (_ut + _dt) * invDiffUd; - mtxProjXYWH<HandnessT>(_result, xx, yy, width, height, _near, _far, _oglNdc); + mtxProjXYWH(_result, xx, yy, width, height, _near, _far, _homogeneousNdc, _handedness); } - template<Handness::Enum HandnessT> - void mtxProjImpl(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) + void mtxProj(float* _result, const float _fov[4], float _near, float _far, bool _homogeneousNdc, Handedness::Enum _handedness) { - mtxProjImpl<HandnessT>(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _far, _oglNdc); + mtxProj(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _far, _homogeneousNdc, _handedness); } - template<Handness::Enum HandnessT> - void mtxProjImpl(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) + void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far, bool _homogeneousNdc, Handedness::Enum _handedness) { const float height = 1.0f/tan(toRad(_fovy)*0.5f); const float width = height * 1.0f/_aspect; - mtxProjXYWH<HandnessT>(_result, 0.0f, 0.0f, width, height, _near, _far, _oglNdc); + mtxProjXYWH(_result, 0.0f, 0.0f, width, height, _near, _far, _homogeneousNdc, _handedness); } - void mtxProj(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); - } - - void mtxProj(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Left>(_result, _fov, _near, _far, _oglNdc); - } - - void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Left>(_result, _fovy, _aspect, _near, _far, _oglNdc); - } - - void mtxProjLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); - } - - void mtxProjLh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Left>(_result, _fov, _near, _far, _oglNdc); - } - - void mtxProjLh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Left>(_result, _fovy, _aspect, _near, _far, _oglNdc); - } - - void mtxProjRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); - } - - void mtxProjRh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Right>(_result, _fov, _near, _far, _oglNdc); - } - - void mtxProjRh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) - { - mtxProjImpl<Handness::Right>(_result, _fovy, _aspect, _near, _far, _oglNdc); - } - - template<NearFar::Enum NearFarT, Handness::Enum HandnessT> - void mtxProjInfXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, bool _oglNdc) + static void mtxProjInfXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, bool _homogeneousNdc, Handedness::Enum _handedness, NearFar::Enum _nearFar) { float aa; float bb; - if (BX_ENABLED(NearFar::Reverse == NearFarT) ) + if (NearFar::Reverse == _nearFar) { - aa = _oglNdc ? -1.0f : 0.0f; - bb = _oglNdc ? -2.0f*_near : -_near; + aa = _homogeneousNdc ? -1.0f : 0.0f; + bb = _homogeneousNdc ? -2.0f*_near : -_near; } else { aa = 1.0f; - bb = _oglNdc ? 2.0f*_near : _near; + bb = _homogeneousNdc ? 2.0f*_near : _near; } memSet(_result, 0, sizeof(float)*16); _result[ 0] = _width; _result[ 5] = _height; - _result[ 8] = (Handness::Right == HandnessT) ? _x : -_x; - _result[ 9] = (Handness::Right == HandnessT) ? _y : -_y; - _result[10] = (Handness::Right == HandnessT) ? -aa : aa; - _result[11] = (Handness::Right == HandnessT) ? -1.0f : 1.0f; + _result[ 8] = (Handedness::Right == _handedness) ? _x : -_x; + _result[ 9] = (Handedness::Right == _handedness) ? _y : -_y; + _result[10] = (Handedness::Right == _handedness) ? -aa : aa; + _result[11] = (Handedness::Right == _handedness) ? -1.0f : 1.0f; _result[14] = -bb; } - template<NearFar::Enum NearFarT, Handness::Enum HandnessT> - void mtxProjInfImpl(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) + void mtxProjInf(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _homogeneousNdc, Handedness::Enum _handedness, NearFar::Enum _nearFar) { const float invDiffRl = 1.0f/(_rt - _lt); const float invDiffUd = 1.0f/(_ut - _dt); @@ -424,107 +342,29 @@ namespace bx const float height = 2.0f*_near * invDiffUd; const float xx = (_rt + _lt) * invDiffRl; const float yy = (_ut + _dt) * invDiffUd; - mtxProjInfXYWH<NearFarT,HandnessT>(_result, xx, yy, width, height, _near, _oglNdc); + mtxProjInfXYWH(_result, xx, yy, width, height, _near, _homogeneousNdc, _handedness, _nearFar); } - template<NearFar::Enum NearFarT, Handness::Enum HandnessT> - void mtxProjInfImpl(float* _result, const float _fov[4], float _near, bool _oglNdc) + void mtxProjInf(float* _result, const float _fov[4], float _near, bool _homogeneousNdc, Handedness::Enum _handedness, NearFar::Enum _nearFar) { - mtxProjInfImpl<NearFarT,HandnessT>(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _oglNdc); + mtxProjInf(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _homogeneousNdc, _handedness, _nearFar); } - template<NearFar::Enum NearFarT, Handness::Enum HandnessT> - void mtxProjInfImpl(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) + void mtxProjInf(float* _result, float _fovy, float _aspect, float _near, bool _homogeneousNdc, Handedness::Enum _handedness, NearFar::Enum _nearFar) { const float height = 1.0f/tan(toRad(_fovy)*0.5f); const float width = height * 1.0f/_aspect; - mtxProjInfXYWH<NearFarT,HandnessT>(_result, 0.0f, 0.0f, width, height, _near, _oglNdc); - } - - void mtxProjInf(float* _result, const float _fov[4], float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Left>(_result, _fov, _near, _oglNdc); - } - - void mtxProjInf(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } - - void mtxProjInf(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); - } - - void mtxProjInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } - - void mtxProjInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Left>(_result, _fov, _near, _oglNdc); - } - - void mtxProjInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); + mtxProjInfXYWH(_result, 0.0f, 0.0f, width, height, _near, _homogeneousNdc, _handedness, _nearFar); } - void mtxProjInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } - - void mtxProjInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Right>(_result, _fov, _near, _oglNdc); - } - - void mtxProjInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Default,Handness::Right>(_result, _fovy, _aspect, _near, _oglNdc); - } - - void mtxProjRevInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Reverse,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } - - void mtxProjRevInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Reverse,Handness::Left>(_result, _fov, _near, _oglNdc); - } - - void mtxProjRevInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Reverse,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); - } - - void mtxProjRevInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Reverse,Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } - - void mtxProjRevInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Reverse,Handness::Right>(_result, _fov, _near, _oglNdc); - } - - void mtxProjRevInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) - { - mtxProjInfImpl<NearFar::Reverse,Handness::Right>(_result, _fovy, _aspect, _near, _oglNdc); - } - - template<Handness::Enum HandnessT> - void mtxOrthoImpl(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) + void mtxOrtho(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _homogeneousNdc, Handedness::Enum _handedness) { const float aa = 2.0f/(_right - _left); const float bb = 2.0f/(_top - _bottom); - const float cc = (_oglNdc ? 2.0f : 1.0f) / (_far - _near); + const float cc = (_homogeneousNdc ? 2.0f : 1.0f) / (_far - _near); const float dd = (_left + _right )/(_left - _right); const float ee = (_top + _bottom)/(_bottom - _top ); - const float ff = _oglNdc + const float ff = _homogeneousNdc ? (_near + _far)/(_near - _far) : _near /(_near - _far) ; @@ -532,28 +372,13 @@ namespace bx memSet(_result, 0, sizeof(float)*16); _result[ 0] = aa; _result[ 5] = bb; - _result[10] = (Handness::Right == HandnessT) ? -cc : cc; + _result[10] = Handedness::Right == _handedness ? -cc : cc; _result[12] = dd + _offset; _result[13] = ee; _result[14] = ff; _result[15] = 1.0f; } - void mtxOrtho(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) - { - mtxOrthoImpl<Handness::Left>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); - } - - void mtxOrthoLh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) - { - mtxOrthoImpl<Handness::Left>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); - } - - void mtxOrthoRh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) - { - mtxOrthoImpl<Handness::Right>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); - } - void mtxRotateX(float* _result, float _ax) { const float sx = sin(_ax); @@ -694,15 +519,15 @@ namespace bx void mtx3Inverse(float* _result, const float* _a) { - float xx = _a[0]; - float xy = _a[1]; - float xz = _a[2]; - float yx = _a[3]; - float yy = _a[4]; - float yz = _a[5]; - float zx = _a[6]; - float zy = _a[7]; - float zz = _a[8]; + const float xx = _a[0]; + const float xy = _a[1]; + const float xz = _a[2]; + const float yx = _a[3]; + const float yy = _a[4]; + const float yz = _a[5]; + const float zx = _a[6]; + const float zy = _a[7]; + const float zz = _a[8]; float det = 0.0f; det += xx * (yy*zz - yz*zy); @@ -726,22 +551,22 @@ namespace bx void mtxInverse(float* _result, const float* _a) { - float xx = _a[ 0]; - float xy = _a[ 1]; - float xz = _a[ 2]; - float xw = _a[ 3]; - float yx = _a[ 4]; - float yy = _a[ 5]; - float yz = _a[ 6]; - float yw = _a[ 7]; - float zx = _a[ 8]; - float zy = _a[ 9]; - float zz = _a[10]; - float zw = _a[11]; - float wx = _a[12]; - float wy = _a[13]; - float wz = _a[14]; - float ww = _a[15]; + const float xx = _a[ 0]; + const float xy = _a[ 1]; + const float xz = _a[ 2]; + const float xw = _a[ 3]; + const float yx = _a[ 4]; + const float yy = _a[ 5]; + const float yz = _a[ 6]; + const float yw = _a[ 7]; + const float zx = _a[ 8]; + const float zy = _a[ 9]; + const float zz = _a[10]; + const float zw = _a[11]; + const float wx = _a[12]; + const float wy = _a[13]; + const float wz = _a[14]; + const float ww = _a[15]; float det = 0.0f; det += xx * (yy*(zz*ww - zw*wz) - yz*(zy*ww - zw*wy) + yw*(zy*wz - zz*wy) ); @@ -772,6 +597,71 @@ namespace bx _result[15] = +(xx*(yy*zz - zy*yz) - xy*(yx*zz - zx*yz) + xz*(yx*zy - zx*yy) ) * invDet; } + void mtx3Cofactor(float* _result, const float* _a) + { + const float xx = _a[0]; + const float xy = _a[1]; + const float xz = _a[2]; + const float yx = _a[3]; + const float yy = _a[4]; + const float yz = _a[5]; + const float zx = _a[6]; + const float zy = _a[7]; + const float zz = _a[8]; + + _result[0] = +(yy*zz - yz * zy); + _result[1] = -(yx*zz - yz * zx); + _result[2] = +(yx*zy - yy * zx); + + _result[3] = -(xy*zz - xz * zy); + _result[4] = +(xx*zz - xz * zx); + _result[5] = -(xx*zy - xy * zx); + + _result[6] = +(xy*yz - xz * yy); + _result[7] = -(xx*yz - xz * yx); + _result[8] = +(xx*yy - xy * yx); + } + + void mtxCofactor(float* _result, const float* _a) + { + const float xx = _a[0]; + const float xy = _a[1]; + const float xz = _a[2]; + const float xw = _a[3]; + const float yx = _a[4]; + const float yy = _a[5]; + const float yz = _a[6]; + const float yw = _a[7]; + const float zx = _a[8]; + const float zy = _a[9]; + const float zz = _a[10]; + const float zw = _a[11]; + const float wx = _a[12]; + const float wy = _a[13]; + const float wz = _a[14]; + const float ww = _a[15]; + + _result[ 0] = +(yy*(zz*ww - wz * zw) - yz * (zy*ww - wy * zw) + yw * (zy*wz - wy * zz) ); + _result[ 1] = -(yx*(zz*ww - wz * zw) - yz * (zx*ww - wx * zw) + yw * (zx*wz - wx * zz) ); + _result[ 2] = +(yx*(zy*ww - wy * zw) - yy * (zx*ww - wx * zw) + yw * (zx*wy - wx * zy) ); + _result[ 3] = -(yx*(zy*wz - wy * zz) - yy * (zx*wz - wx * zz) + yz * (zx*wy - wx * zy) ); + + _result[ 4] = -(xy*(zz*ww - wz * zw) - xz * (zy*ww - wy * zw) + xw * (zy*wz - wy * zz) ); + _result[ 5] = +(xx*(zz*ww - wz * zw) - xz * (zx*ww - wx * zw) + xw * (zx*wz - wx * zz) ); + _result[ 6] = -(xx*(zy*ww - wy * zw) - xy * (zx*ww - wx * zw) + xw * (zx*wy - wx * zy) ); + _result[ 7] = +(xx*(zy*wz - wy * zz) - xy * (zx*wz - wx * zz) + xz * (zx*wy - wx * zy) ); + + _result[ 8] = +(xy*(yz*ww - wz * yw) - xz * (yy*ww - wy * yw) + xw * (yy*wz - wy * yz) ); + _result[ 9] = -(xx*(yz*ww - wz * yw) - xz * (yx*ww - wx * yw) + xw * (yx*wz - wx * yz) ); + _result[10] = +(xx*(yy*ww - wy * yw) - xy * (yx*ww - wx * yw) + xw * (yx*wy - wx * yy) ); + _result[11] = -(xx*(yy*wz - wy * yz) - xy * (yx*wz - wx * yz) + xz * (yx*wy - wx * yy) ); + + _result[12] = -(xy*(yz*zw - zz * yw) - xz * (yy*zw - zy * yw) + xw * (yy*zz - zy * yz) ); + _result[13] = +(xx*(yz*zw - zz * yw) - xz * (yx*zw - zx * yw) + xw * (yx*zz - zx * yz) ); + _result[14] = -(xx*(yy*zw - zy * yw) - xy * (yx*zw - zx * yw) + xw * (yx*zy - zx * yy) ); + _result[15] = +(xx*(yy*zz - zy * yz) - xy * (yx*zz - zx * yz) + xz * (yx*zy - zx * yy) ); + } + void calcLinearFit2D(float _result[2], const void* _points, uint32_t _stride, uint32_t _numPoints) { float sumX = 0.0f; diff --git a/3rdparty/bx/src/mutex.cpp b/3rdparty/bx/src/mutex.cpp index 27c6b63b709..0ef8597a8aa 100644 --- a/3rdparty/bx/src/mutex.cpp +++ b/3rdparty/bx/src/mutex.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/mutex.h> #if BX_CONFIG_SUPPORTS_THREADING @@ -12,15 +11,21 @@ # include <bx/cpu.h> # include "crt0.h" #elif BX_PLATFORM_ANDROID \ + || BX_PLATFORM_BSD \ + || BX_PLATFORM_HAIKU \ || BX_PLATFORM_LINUX \ || BX_PLATFORM_IOS \ || BX_PLATFORM_OSX \ || BX_PLATFORM_PS4 \ - || BX_PLATFORM_RPI + || BX_PLATFORM_RPI \ + || BX_PLATFORM_NX # include <pthread.h> #elif BX_PLATFORM_WINDOWS \ || BX_PLATFORM_WINRT \ || BX_PLATFORM_XBOXONE +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif // WIN32_LEAN_AND_MEAN # include <windows.h> # include <errno.h> #endif // BX_PLATFORM_ @@ -54,12 +59,12 @@ namespace bx { uint32_t* futex = (uint32_t*)m_internal; - if (State::Unlocked == bx::atomicCompareAndSwap<uint32_t>(futex, State::Unlocked, State::Locked) ) + if (State::Unlocked == atomicCompareAndSwap<uint32_t>(futex, State::Unlocked, State::Locked) ) { return; } - while (State::Unlocked != bx::atomicCompareAndSwap<uint32_t>(futex, State::Locked, State::Contested) ) + while (State::Unlocked != atomicCompareAndSwap<uint32_t>(futex, State::Locked, State::Contested) ) { crt0::futexWait(futex, State::Contested); } @@ -69,7 +74,7 @@ namespace bx { uint32_t* futex = (uint32_t*)m_internal; - if (State::Contested == bx::atomicCompareAndSwap<uint32_t>(futex, State::Locked, State::Unlocked) ) + if (State::Contested == atomicCompareAndSwap<uint32_t>(futex, State::Locked, State::Unlocked) ) { crt0::futexWake(futex, State::Locked); } @@ -156,4 +161,26 @@ namespace bx } // namespace bx -#endif // BX_MUTEX_H_HEADER_GUARD +#else + +namespace bx +{ + Mutex::Mutex() + { + } + + Mutex::~Mutex() + { + } + + void Mutex::lock() + { + } + + void Mutex::unlock() + { + } + +} // namespace bx + +#endif // BX_CONFIG_SUPPORTS_THREADING diff --git a/3rdparty/bx/src/os.cpp b/3rdparty/bx/src/os.cpp index 0e925bb2f90..99394579b72 100644 --- a/3rdparty/bx/src/os.cpp +++ b/3rdparty/bx/src/os.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/string.h> #include <bx/os.h> #include <bx/uint32_t.h> @@ -15,25 +14,28 @@ #endif // BX_CRT_MSVC #if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif // WIN32_LEAN_AND_MEAN # include <windows.h> # include <psapi.h> #elif BX_PLATFORM_ANDROID \ - || BX_PLATFORM_EMSCRIPTEN \ || BX_PLATFORM_BSD \ + || BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_HAIKU \ || BX_PLATFORM_HURD \ || BX_PLATFORM_IOS \ || BX_PLATFORM_LINUX \ + || BX_PLATFORM_NX \ || BX_PLATFORM_OSX \ || BX_PLATFORM_PS4 \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK \ - || BX_PLATFORM_NX + || BX_PLATFORM_RPI # include <sched.h> // sched_yield -# if BX_PLATFORM_BSD \ - || BX_PLATFORM_IOS \ - || BX_PLATFORM_OSX \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_STEAMLINK +# if BX_PLATFORM_BSD \ + || BX_PLATFORM_HAIKU \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_OSX \ + || BX_PLATFORM_PS4 # include <pthread.h> // mach_port_t # endif // BX_PLATFORM_* @@ -45,11 +47,13 @@ # if BX_PLATFORM_ANDROID # include <malloc.h> // mallinfo # elif BX_PLATFORM_LINUX \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK + || BX_PLATFORM_RPI # include <stdio.h> // fopen # include <unistd.h> // syscall # include <sys/syscall.h> +# elif BX_PLATFORM_HAIKU +# include <stdio.h> // fopen +# include <unistd.h> // syscall # elif BX_PLATFORM_OSX # include <mach/mach.h> // mach_task_basic_info # elif BX_PLATFORM_HURD @@ -62,7 +66,6 @@ namespace bx { - void sleep(uint32_t _ms) { #if BX_PLATFORM_WINDOWS @@ -97,8 +100,7 @@ namespace bx #if BX_PLATFORM_WINDOWS return ::GetCurrentThreadId(); #elif BX_PLATFORM_LINUX \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK + || BX_PLATFORM_RPI return (pid_t)::syscall(SYS_gettid); #elif BX_PLATFORM_IOS \ || BX_PLATFORM_OSX @@ -174,7 +176,7 @@ namespace bx void* dlopen(const FilePath& _filePath) { #if BX_PLATFORM_WINDOWS - return (void*)::LoadLibraryA(_filePath.get() ); + return (void*)::LoadLibraryA(_filePath.getCPtr() ); #elif BX_PLATFORM_EMSCRIPTEN \ || BX_PLATFORM_PS4 \ || BX_PLATFORM_XBOXONE \ @@ -183,12 +185,19 @@ namespace bx BX_UNUSED(_filePath); return NULL; #else - return ::dlopen(_filePath.get(), RTLD_LOCAL|RTLD_LAZY); + void* so = ::dlopen(_filePath.getCPtr(), RTLD_LOCAL|RTLD_LAZY); + BX_WARN(NULL != so, "dlopen failed: \"%s\".", ::dlerror() ); + return so; #endif // BX_PLATFORM_ } void dlclose(void* _handle) { + if (NULL == _handle) + { + return; + } + #if BX_PLATFORM_WINDOWS ::FreeLibrary( (HMODULE)_handle); #elif BX_PLATFORM_EMSCRIPTEN \ @@ -206,7 +215,7 @@ namespace bx { const int32_t symbolMax = _symbol.getLength()+1; char* symbol = (char*)alloca(symbolMax); - bx::strCopy(symbol, symbolMax, _symbol); + strCopy(symbol, symbolMax, _symbol); #if BX_PLATFORM_WINDOWS return (void*)::GetProcAddress( (HMODULE)_handle, symbol); @@ -226,16 +235,17 @@ namespace bx { const int32_t nameMax = _name.getLength()+1; char* name = (char*)alloca(nameMax); - bx::strCopy(name, nameMax, _name); + strCopy(name, nameMax, _name); #if BX_PLATFORM_WINDOWS DWORD len = ::GetEnvironmentVariableA(name, _out, *_inOutSize); bool result = len != 0 && len < *_inOutSize; *_inOutSize = len; return result; -#elif BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT \ +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT \ || BX_CRT_NONE BX_UNUSED(name, _out, _inOutSize); return false; @@ -263,21 +273,22 @@ namespace bx { const int32_t nameMax = _name.getLength()+1; char* name = (char*)alloca(nameMax); - bx::strCopy(name, nameMax, _name); + strCopy(name, nameMax, _name); char* value = NULL; if (!_value.isEmpty() ) { int32_t valueMax = _value.getLength()+1; value = (char*)alloca(valueMax); - bx::strCopy(value, valueMax, _value); + strCopy(value, valueMax, _value); } #if BX_PLATFORM_WINDOWS ::SetEnvironmentVariableA(name, value); -#elif BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT \ +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT \ || BX_CRT_NONE BX_UNUSED(name, value); #else @@ -339,7 +350,7 @@ namespace bx int32_t len = 0; for(uint32_t ii = 0; NULL != _argv[ii]; ++ii) { - len += snprintf(&temp[len], bx::uint32_imax(0, total-len) + len += snprintf(&temp[len], uint32_imax(0, total-len) , "%s " , _argv[ii] ); @@ -368,4 +379,9 @@ namespace bx #endif // BX_PLATFORM_LINUX || BX_PLATFORM_HURD } + void exit(int32_t _exitCode) + { + ::exit(_exitCode); + } + } // namespace bx diff --git a/3rdparty/bx/src/process.cpp b/3rdparty/bx/src/process.cpp index 90d663b3f5a..8afa1feb230 100644 --- a/3rdparty/bx/src/process.cpp +++ b/3rdparty/bx/src/process.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/process.h> #include <stdio.h> @@ -34,28 +33,28 @@ namespace bx ProcessReader::~ProcessReader() { - BX_CHECK(NULL == m_file, "Process not closed!"); + BX_ASSERT(NULL == m_file, "Process not closed!"); } bool ProcessReader::open(const FilePath& _filePath, const StringView& _args, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessReader: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "ProcessReader: File is already open."); return false; } char tmp[kMaxFilePath*2] = "\""; - strCat(tmp, BX_COUNTOF(tmp), _filePath.get() ); + strCat(tmp, BX_COUNTOF(tmp), _filePath); strCat(tmp, BX_COUNTOF(tmp), "\" "); strCat(tmp, BX_COUNTOF(tmp), _args); m_file = popen(tmp, "r"); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessReader: Failed to open process."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "ProcessReader: Failed to open process."); return false; } @@ -64,7 +63,7 @@ namespace bx void ProcessReader::close() { - BX_CHECK(NULL != m_file, "Process not open!"); + BX_ASSERT(NULL != m_file, "Process not open!"); FILE* file = (FILE*)m_file; m_exitCode = pclose(file); m_file = NULL; @@ -72,7 +71,7 @@ namespace bx int32_t ProcessReader::read(void* _data, int32_t _size, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); FILE* file = (FILE*)m_file; int32_t size = (int32_t)fread(_data, 1, _size, file); @@ -80,11 +79,11 @@ namespace bx { if (0 != feof(file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "ProcessReader: EOF."); + BX_ERROR_SET(_err, kErrorReaderWriterEof, "ProcessReader: EOF."); } else if (0 != ferror(file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "ProcessReader: read error."); + BX_ERROR_SET(_err, kErrorReaderWriterRead, "ProcessReader: read error."); } return size >= 0 ? size : 0; @@ -105,28 +104,28 @@ namespace bx ProcessWriter::~ProcessWriter() { - BX_CHECK(NULL == m_file, "Process not closed!"); + BX_ASSERT(NULL == m_file, "Process not closed!"); } bool ProcessWriter::open(const FilePath& _filePath, const StringView& _args, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); if (NULL != m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessWriter: File is already open."); + BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "ProcessWriter: File is already open."); return false; } char tmp[kMaxFilePath*2] = "\""; - strCat(tmp, BX_COUNTOF(tmp), _filePath.get() ); + strCat(tmp, BX_COUNTOF(tmp), _filePath); strCat(tmp, BX_COUNTOF(tmp), "\" "); strCat(tmp, BX_COUNTOF(tmp), _args); m_file = popen(tmp, "w"); if (NULL == m_file) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessWriter: Failed to open process."); + BX_ERROR_SET(_err, kErrorReaderWriterOpen, "ProcessWriter: Failed to open process."); return false; } @@ -135,7 +134,7 @@ namespace bx void ProcessWriter::close() { - BX_CHECK(NULL != m_file, "Process not open!"); + BX_ASSERT(NULL != m_file, "Process not open!"); FILE* file = (FILE*)m_file; m_exitCode = pclose(file); m_file = NULL; @@ -143,7 +142,7 @@ namespace bx int32_t ProcessWriter::write(const void* _data, int32_t _size, Error* _err) { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); + BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); FILE* file = (FILE*)m_file; int32_t size = (int32_t)fwrite(_data, 1, _size, file); @@ -151,7 +150,7 @@ namespace bx { if (0 != ferror(file) ) { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "ProcessWriter: write error."); + BX_ERROR_SET(_err, kErrorReaderWriterWrite, "ProcessWriter: write error."); } return size >= 0 ? size : 0; diff --git a/3rdparty/bx/src/semaphore.cpp b/3rdparty/bx/src/semaphore.cpp index 3663fe767b5..787b913a8d8 100644 --- a/3rdparty/bx/src/semaphore.cpp +++ b/3rdparty/bx/src/semaphore.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/semaphore.h> #if BX_CONFIG_SUPPORTS_THREADING @@ -20,6 +19,9 @@ #elif BX_PLATFORM_WINDOWS \ || BX_PLATFORM_WINRT \ || BX_PLATFORM_XBOXONE +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif // WIN32_LEAN_AND_MEAN # include <windows.h> # include <limits.h> # if BX_PLATFORM_XBOXONE @@ -76,7 +78,7 @@ namespace bx SemaphoreInternal* si = (SemaphoreInternal*)m_internal; si->m_handle = dispatch_semaphore_create(0); - BX_CHECK(NULL != si->m_handle, "dispatch_semaphore_create failed."); + BX_ASSERT(NULL != si->m_handle, "dispatch_semaphore_create failed."); } Semaphore::~Semaphore() @@ -140,10 +142,10 @@ namespace bx int result; result = pthread_mutex_init(&si->m_mutex, NULL); - BX_CHECK(0 == result, "pthread_mutex_init %d", result); + BX_ASSERT(0 == result, "pthread_mutex_init %d", result); result = pthread_cond_init(&si->m_cond, NULL); - BX_CHECK(0 == result, "pthread_cond_init %d", result); + BX_ASSERT(0 == result, "pthread_cond_init %d", result); BX_UNUSED(result); } @@ -154,10 +156,10 @@ namespace bx int result; result = pthread_cond_destroy(&si->m_cond); - BX_CHECK(0 == result, "pthread_cond_destroy %d", result); + BX_ASSERT(0 == result, "pthread_cond_destroy %d", result); result = pthread_mutex_destroy(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_destroy %d", result); + BX_ASSERT(0 == result, "pthread_mutex_destroy %d", result); BX_UNUSED(result); } @@ -167,18 +169,18 @@ namespace bx SemaphoreInternal* si = (SemaphoreInternal*)m_internal; int result = pthread_mutex_lock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_lock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_lock %d", result); for (uint32_t ii = 0; ii < _count; ++ii) { result = pthread_cond_signal(&si->m_cond); - BX_CHECK(0 == result, "pthread_cond_signal %d", result); + BX_ASSERT(0 == result, "pthread_cond_signal %d", result); } si->m_count += _count; result = pthread_mutex_unlock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_unlock %d", result); BX_UNUSED(result); } @@ -188,7 +190,7 @@ namespace bx SemaphoreInternal* si = (SemaphoreInternal*)m_internal; int result = pthread_mutex_lock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_lock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_lock %d", result); if (-1 == _msecs) { @@ -219,7 +221,7 @@ namespace bx } result = pthread_mutex_unlock(&si->m_mutex); - BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); + BX_ASSERT(0 == result, "pthread_mutex_unlock %d", result); BX_UNUSED(result); @@ -240,7 +242,7 @@ namespace bx #else si->m_handle = CreateSemaphoreA(NULL, 0, LONG_MAX, NULL); #endif - BX_CHECK(NULL != si->m_handle, "Failed to create Semaphore!"); + BX_ASSERT(NULL != si->m_handle, "Failed to create Semaphore!"); } Semaphore::~Semaphore() diff --git a/3rdparty/bx/src/settings.cpp b/3rdparty/bx/src/settings.cpp index e09e11f687f..7f16eeee10f 100644 --- a/3rdparty/bx/src/settings.cpp +++ b/3rdparty/bx/src/settings.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/settings.h> namespace diff --git a/3rdparty/bx/src/sort.cpp b/3rdparty/bx/src/sort.cpp index 515b33f24f1..31ad8c795f4 100644 --- a/3rdparty/bx/src/sort.cpp +++ b/3rdparty/bx/src/sort.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/sort.h> namespace bx @@ -52,5 +51,124 @@ namespace bx quickSortR(pivot, _data, _num, _stride, _fn); } + bool isSorted(const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn) + { + const uint8_t* data = (uint8_t*)_data; + + for (uint32_t ii = 1; ii < _num; ++ii) + { + int32_t result = _fn(&data[(ii-1)*_stride], &data[ii*_stride]); + + if (0 < result) + { + return false; + } + } + + return true; + } + + uint32_t unique(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn) + { + if (0 == _num) + { + return 0; + } + + uint8_t* data = (uint8_t*)_data; + + uint32_t last = 0; + + for (uint32_t ii = 1; ii < _num; ++ii) + { + int32_t result = _fn(&data[last*_stride], &data[ii*_stride]); + BX_ASSERT(0 >= result, "Performing unique on non-sorted array (ii %d, last %d)!", ii, last); + + if (0 > result) + { + last++; + swap(&data[last*_stride], &data[ii*_stride], _stride); + } + } + + return last+1; + } + + uint32_t lowerBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn) + { + uint32_t offset = 0; + const uint8_t* data = (uint8_t*)_data; + + for (uint32_t ll = _num; offset < ll;) + { + const uint32_t idx = (offset + ll) / 2; + + int32_t result = _fn(_key, &data[idx * _stride]); + + if (result <= 0) + { + ll = idx; + } + else + { + offset = idx + 1; + } + } + + return offset; + } + + uint32_t upperBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn) + { + uint32_t offset = 0; + const uint8_t* data = (uint8_t*)_data; + + for (uint32_t ll = _num; offset < ll;) + { + const uint32_t idx = (offset + ll) / 2; + + int32_t result = _fn(_key, &data[idx * _stride]); + + if (result < 0) + { + ll = idx; + } + else + { + offset = idx + 1; + } + } + + return offset; + } + + int32_t binarySearch(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn) + { + uint32_t offset = 0; + const uint8_t* data = (uint8_t*)_data; + + for (uint32_t ll = _num; offset < ll;) + { + const uint32_t idx = (offset + ll) / 2; + + int32_t result = _fn(_key, &data[idx * _stride]); + + if (result < 0) + { + ll = idx; + } + else if (result > 0) + { + offset = idx + 1; + } + else + { + return idx; + } + } + + return ~offset; + } + } // namespace bx diff --git a/3rdparty/bx/src/string.cpp b/3rdparty/bx/src/string.cpp index 7710028ae6d..94429ebd21d 100644 --- a/3rdparty/bx/src/string.cpp +++ b/3rdparty/bx/src/string.cpp @@ -1,12 +1,11 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/allocator.h> +#include <bx/file.h> #include <bx/hash.h> -#include <bx/readerwriter.h> #include <bx/string.h> namespace bx @@ -135,7 +134,7 @@ namespace bx { for (int32_t ii = 0; ii < _len; ++ii) { - *_inOutStr = toLower(*_inOutStr); + _inOutStr[ii] = toLower(_inOutStr[ii]); } } @@ -154,7 +153,7 @@ namespace bx { for (int32_t ii = 0; ii < _len; ++ii) { - *_inOutStr = toUpper(*_inOutStr); + _inOutStr[ii] = toUpper(_inOutStr[ii]); } } @@ -188,7 +187,12 @@ namespace bx } } - return 0 == max && _lhsMax == _rhsMax ? 0 : fn(*_lhs) - fn(*_rhs); + if (0 == max) + { + return _lhsMax == _rhsMax ? 0 : _lhsMax > _rhsMax ? 1 : -1; + } + + return fn(*_lhs) - fn(*_rhs); } int32_t strCmp(const StringView& _lhs, const StringView& _rhs, int32_t _max) @@ -305,9 +309,9 @@ namespace bx inline int32_t strCopy(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) { - BX_CHECK(NULL != _dst, "_dst can't be NULL!"); - BX_CHECK(NULL != _src, "_src can't be NULL!"); - BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); + BX_ASSERT(NULL != _dst, "_dst can't be NULL!"); + BX_ASSERT(NULL != _src, "_src can't be NULL!"); + BX_ASSERT(0 < _dstSize, "_dstSize can't be 0!"); const int32_t len = strLen(_src, _num); const int32_t max = _dstSize-1; @@ -325,9 +329,9 @@ namespace bx inline int32_t strCat(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) { - BX_CHECK(NULL != _dst, "_dst can't be NULL!"); - BX_CHECK(NULL != _src, "_src can't be NULL!"); - BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); + BX_ASSERT(NULL != _dst, "_dst can't be NULL!"); + BX_ASSERT(NULL != _src, "_src can't be NULL!"); + BX_ASSERT(0 < _dstSize, "_dstSize can't be 0!"); const int32_t max = _dstSize; const int32_t len = strLen(_dst, max); @@ -370,7 +374,7 @@ namespace bx inline const char* strRFindUnsafe(const char* _str, int32_t _len, char _ch) { - for (int32_t ii = _len; 0 <= ii; --ii) + for (int32_t ii = _len-1; 0 <= ii; --ii) { if (_str[ii] == _ch) { @@ -408,25 +412,16 @@ namespace bx ++ptr; --stringLen; - // Search pattern lenght can't be longer than the string. + // Search pattern length can't be longer than the string. if (findLen > stringLen) { return NULL; } } - // Set pointers. - const char* string = ptr; - const char* search = _find; - - // Start comparing. - while (fn(*string++) == fn(*search++) ) + if (0 == strCmp<fn>(ptr, _findMax, _find, _findMax) ) { - // If end of the 'search' string is reached, all characters match. - if ('\0' == *search) - { - return ptr; - } + return ptr; } } @@ -485,7 +480,7 @@ namespace bx } } - return _str; + return StringView(_str.getTerm(), _str.getTerm() ); } StringView strLTrimSpace(const StringView& _str) @@ -528,7 +523,29 @@ namespace bx { return StringView(ptr, ii + 1); } + } + + return StringView(_str.getPtr(), _str.getPtr()); + } + + return _str; + } + + StringView strRTrimSpace(const StringView& _str) + { + if (!_str.isEmpty() ) + { + const char* ptr = _str.getPtr(); + + for (int32_t len = _str.getLength(), ii = len - 1; 0 <= ii; --ii) + { + if (!isSpace(ptr[ii]) ) + { + return StringView(ptr, ii + 1); + } } + + return StringView(_str.getPtr(), _str.getPtr()); } return _str; @@ -539,29 +556,24 @@ namespace bx return strLTrim(strRTrim(_str, _chars), _chars); } + StringView strTrimSpace(const StringView& _str) + { + return strLTrimSpace(strRTrimSpace(_str) ); + } + constexpr uint32_t kFindStep = 1024; StringView strFindNl(const StringView& _str) { StringView str(_str); - for (; str.getPtr() != _str.getTerm() - ; str = StringView(min(str.getPtr() + kFindStep, _str.getTerm() ), min(str.getPtr() + kFindStep*2, _str.getTerm() ) ) - ) + // This method returns the character past the \n, so + // there is no need to look for he \r which preceedes it. + StringView eol = strFind(str, "\n"); + if (!eol.isEmpty() ) { - StringView eol = strFind(str, "\r\n"); - if (!eol.isEmpty() ) - { - return StringView(eol.getTerm(), _str.getTerm() ); - } - - eol = strFind(str, '\n'); - if (!eol.isEmpty() ) - { - return StringView(eol.getTerm(), _str.getTerm() ); - } + return StringView(eol.getTerm(), str.getTerm() ); } - return StringView(_str.getTerm(), _str.getTerm() ); } @@ -669,7 +681,7 @@ namespace bx StringView ptr = strFind(_str, _word); for (; !ptr.isEmpty(); ptr = strFind(StringView(ptr.getPtr() + len, _str.getTerm() ), _word) ) { - char ch = *(ptr.getPtr() - 1); + char ch = ptr.getPtr() != _str.getPtr() ? *(ptr.getPtr() - 1) : ' '; if (isAlphaNum(ch) || '_' == ch) { continue; @@ -687,9 +699,10 @@ namespace bx return StringView(_str.getTerm(), _str.getTerm() ); } - StringView findIdentifierMatch(const StringView& _str, const char** _words) + StringView findIdentifierMatch(const StringView& _str, const char** _words, int32_t _num) { - for (StringView word = *_words; !word.isEmpty(); ++_words, word = *_words) + int32_t ii = 0; + for (StringView word = *_words; ii < _num && !word.isEmpty(); ++ii, ++_words, word = *_words) { StringView match = findIdentifierMatch(_str, word); if (!match.isEmpty() ) @@ -733,13 +746,40 @@ namespace bx { int32_t size = 0; int32_t len = (int32_t)strLen(_str, _len); - int32_t padding = _param.width > len ? _param.width - len : 0; - bool sign = _param.sign && len > 1 && _str[0] != '-'; - padding = padding > 0 ? padding - sign : 0; + + if (_param.width > 0) + { + len = min(_param.width, len); + } + + const bool hasMinus = (NULL != _str && '-' == _str[0]); + const bool hasSign = _param.sign || hasMinus; + char sign = hasSign ? hasMinus ? '-' : '+' : '\0'; + + const char* str = _str; + if (hasMinus) + { + str++; + len--; + } + + int32_t padding = _param.width > len ? _param.width - len - hasSign: 0; if (!_param.left) { - size += writeRep(_writer, _param.fill, padding, _err); + if (' ' != _param.fill + && '\0' != sign) + { + size += write(_writer, sign, _err); + sign = '\0'; + } + + size += writeRep(_writer, _param.fill, max(0, padding), _err); + } + + if ('\0' != sign) + { + size += write(_writer, sign, _err); } if (NULL == _str) @@ -750,17 +790,12 @@ namespace bx { for (int32_t ii = 0; ii < len; ++ii) { - size += write(_writer, toUpper(_str[ii]), _err); + size += write(_writer, toUpper(str[ii]), _err); } } - else if (sign) - { - size += write(_writer, '+', _err); - size += write(_writer, _str, len, _err); - } else { - size += write(_writer, _str, len, _err); + size += write(_writer, str, len, _err); } if (_param.left) @@ -781,6 +816,11 @@ namespace bx return write(_writer, _str, _param.prec, _param, _err); } + static int32_t write(WriterI* _writer, const StringView& _str, const Param& _param, Error* _err) + { + return write(_writer, _str.getPtr(), min(_param.prec, _str.getLength() ), _param, _err); + } + static int32_t write(WriterI* _writer, int32_t _i, const Param& _param, Error* _err) { char str[33]; @@ -843,30 +883,39 @@ namespace bx return 0; } - if (_param.upper) - { - toUpperUnsafe(str, len); - } - const char* dot = strFind(str, INT32_MAX, '.'); if (NULL != dot) { - const int32_t prec = INT32_MAX == _param.prec ? 6 : _param.prec; - const int32_t precLen = int32_t( - dot - + uint32_min(prec + _param.spec, 1) - + prec - - str - ); - if (precLen > len) + const int32_t prec = INT32_MAX == _param.prec ? 6 : _param.prec; + const char* strEnd = str + len; + const char* exponent = strFind(str, INT32_MAX, 'e'); + const char* fracEnd = NULL != exponent ? exponent : strEnd; + + char* fracBegin = &str[dot - str + min(prec + _param.spec, 1)]; + const int32_t curPrec = int32_t(fracEnd - fracBegin); + + // Move exponent to its final location after trimming or adding extra 0s. + if (fracEnd != strEnd) + { + const int32_t exponentLen = int32_t(strEnd - fracEnd); + char* finalExponentPtr = &fracBegin[prec]; + memMove(finalExponentPtr, fracEnd, exponentLen); + + finalExponentPtr[exponentLen] = '\0'; + len = int32_t(&finalExponentPtr[exponentLen] - str); + } + else { - for (int32_t ii = len; ii < precLen; ++ii) + len = (int32_t)(fracBegin + prec - str); + } + + if (curPrec < prec) + { + for (int32_t ii = curPrec; ii < prec; ++ii) { - str[ii] = '0'; + fracBegin[ii] = '0'; } - str[precLen] = '\0'; } - len = precLen; } return write(_writer, str, len, _param, _err); @@ -907,17 +956,22 @@ namespace bx } else if ('%' == ch) { - // %[flags][width][.precision][length sub-specifier]specifier - read(&reader, ch); + // %[Flags][Width][.Precision][Leegth]Type + read(&reader, ch, &err); Param param; - // flags - while (' ' == ch + // Reference(s): + // - Flags field + // https://en.wikipedia.org/wiki/Printf_format_string#Flags_field + // + while (err.isOk() + && ( ' ' == ch || '-' == ch || '+' == ch || '0' == ch || '#' == ch) + ) { switch (ch) { @@ -929,7 +983,7 @@ namespace bx case '#': param.spec = true; break; } - read(&reader, ch); + read(&reader, ch, &err); } if (param.left) @@ -937,10 +991,13 @@ namespace bx param.fill = ' '; } - // width + // Reference(s): + // - Width field + // https://en.wikipedia.org/wiki/Printf_format_string#Width_field + // if ('*' == ch) { - read(&reader, ch); + read(&reader, ch, &err); param.width = va_arg(_argList, int32_t); if (0 > param.width) @@ -952,49 +1009,57 @@ namespace bx } else { - while (isNumeric(ch) ) + while (err.isOk() + && isNumeric(ch) ) { param.width = param.width * 10 + ch - '0'; - read(&reader, ch); + read(&reader, ch, &err); } } - // .precision + // Reference(s): + // - Precision field + // https://en.wikipedia.org/wiki/Printf_format_string#Precision_field if ('.' == ch) { - read(&reader, ch); + read(&reader, ch, &err); if ('*' == ch) { - read(&reader, ch); + read(&reader, ch, &err); param.prec = va_arg(_argList, int32_t); } else { param.prec = 0; - while (isNumeric(ch) ) + while (err.isOk() + && isNumeric(ch) ) { param.prec = param.prec * 10 + ch - '0'; - read(&reader, ch); + read(&reader, ch, &err); } } } - // length sub-specifier - while ('h' == ch + // Reference(s): + // - Length field + // https://en.wikipedia.org/wiki/Printf_format_string#Length_field + while (err.isOk() + && ( 'h' == ch || 'I' == ch || 'l' == ch || 'j' == ch || 't' == ch || 'z' == ch) + ) { switch (ch) { default: break; case 'j': param.bits = sizeof(intmax_t )*8; break; - case 't': param.bits = sizeof(size_t )*8; break; - case 'z': param.bits = sizeof(ptrdiff_t)*8; break; + case 't': param.bits = sizeof(ptrdiff_t)*8; break; + case 'z': param.bits = sizeof(size_t )*8; break; case 'h': case 'I': case 'l': switch (ch) @@ -1004,14 +1069,14 @@ namespace bx default: break; } - read(&reader, ch); + read(&reader, ch, &err); switch (ch) { case 'h': param.bits = sizeof(signed char )*8; break; case 'l': param.bits = sizeof(long long int)*8; break; case '3': case '6': - read(&reader, ch); + read(&reader, ch, &err); switch (ch) { case '2': param.bits = sizeof(int32_t)*8; break; @@ -1025,11 +1090,18 @@ namespace bx break; } - read(&reader, ch); + read(&reader, ch, &err); + } + + if (!err.isOk() ) + { + break; } - // specifier - switch (toLower(ch) ) + // Reference(s): + // - Type field + // https://en.wikipedia.org/wiki/Printf_format_string#Type_field + switch (ch) { case 'c': size += write(_writer, char(va_arg(_argList, int32_t) ), param, _err); @@ -1039,6 +1111,10 @@ namespace bx size += write(_writer, va_arg(_argList, const char*), param, _err); break; + case 'S': + size += write(_writer, *va_arg(_argList, const StringView*), param, _err); + break; + case 'o': param.base = 8; switch (param.bits) @@ -1059,8 +1135,11 @@ namespace bx break; case 'e': + case 'E': case 'f': + case 'F': case 'g': + case 'G': param.upper = isUpper(ch); size += write(_writer, va_arg(_argList, double), param, _err); break; @@ -1070,6 +1149,7 @@ namespace bx break; case 'x': + case 'X': param.base = 16; param.upper = isUpper(ch); switch (param.bits) @@ -1088,6 +1168,10 @@ namespace bx } break; + case 'n': + *va_arg(_argList, int32_t*) = size; + break; + default: size += write(_writer, ch, _err); break; @@ -1147,10 +1231,10 @@ namespace bx SizerWriter sizer; va_list argListCopy; va_copy(argListCopy, _argList); - int32_t size = write(&sizer, _format, argListCopy, &err); + int32_t total = write(&sizer, _format, argListCopy, &err); va_end(argListCopy); - return size; + return total; } int32_t snprintf(char* _out, int32_t _max, const char* _format, ...) @@ -1159,6 +1243,28 @@ namespace bx va_start(argList, _format); int32_t total = vsnprintf(_out, _max, _format, argList); va_end(argList); + + return total; + } + + int32_t vprintf(const char* _format, va_list _argList) + { + Error err; + va_list argListCopy; + va_copy(argListCopy, _argList); + int32_t total = write(getStdOut(), _format, argListCopy, &err); + va_end(argListCopy); + + return total; + } + + int32_t printf(const char* _format, ...) + { + va_list argList; + va_start(argList, _format); + int32_t total = vprintf(_format, argList); + va_end(argList); + return total; } diff --git a/3rdparty/bx/src/thread.cpp b/3rdparty/bx/src/thread.cpp index f52e0bdcbf4..f5e5f81bc21 100644 --- a/3rdparty/bx/src/thread.cpp +++ b/3rdparty/bx/src/thread.cpp @@ -1,39 +1,45 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" +#include <bx/os.h> #include <bx/thread.h> #if BX_CONFIG_SUPPORTS_THREADING +#if BX_PLATFORM_WINDOWS && !BX_CRT_NONE +# include <bx/string.h> +#endif + #if BX_CRT_NONE # include "crt0.h" #elif BX_PLATFORM_ANDROID \ + || BX_PLATFORM_BSD \ + || BX_PLATFORM_HAIKU \ || BX_PLATFORM_LINUX \ || BX_PLATFORM_IOS \ || BX_PLATFORM_OSX \ || BX_PLATFORM_PS4 \ - || BX_PLATFORM_RPI + || BX_PLATFORM_RPI \ + || BX_PLATFORM_NX # include <pthread.h> -# if defined(__FreeBSD__) +# if BX_PLATFORM_BSD # include <pthread_np.h> -# endif +# endif // BX_PLATFORM_BSD # if BX_PLATFORM_LINUX && (BX_CRT_GLIBC < 21200) # include <sys/prctl.h> # endif // BX_PLATFORM_ #elif BX_PLATFORM_WINDOWS \ || BX_PLATFORM_WINRT \ - || BX_PLATFORM_XBOXONE + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif // WIN32_LEAN_AND_MEAN # include <windows.h> # include <limits.h> # include <errno.h> -# if BX_PLATFORM_WINRT -using namespace Platform; -using namespace Windows::Foundation; -using namespace Windows::System::Threading; -# endif // BX_PLATFORM_WINRT #endif // BX_PLATFORM_ namespace bx @@ -122,20 +128,25 @@ namespace bx } } - void Thread::init(ThreadFn _fn, void* _userData, uint32_t _stackSize, const char* _name) + bool Thread::init(ThreadFn _fn, void* _userData, uint32_t _stackSize, const char* _name) { - BX_CHECK(!m_running, "Already running!"); + BX_ASSERT(!m_running, "Already running!"); m_fn = _fn; m_userData = _userData; m_stackSize = _stackSize; - m_running = true; ThreadInternal* ti = (ThreadInternal*)m_internal; #if BX_CRT_NONE ti->m_handle = crt0::threadCreate(&ti->threadFunc, _userData, m_stackSize, _name); + + if (NULL == ti->m_handle) + { + return false; + } #elif BX_PLATFORM_WINDOWS \ - || BX_PLATFORM_XBOXONE + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT ti->m_handle = ::CreateThread(NULL , m_stackSize , (LPTHREAD_START_ROUTINE)ti->threadFunc @@ -143,48 +154,57 @@ namespace bx , 0 , NULL ); -#elif BX_PLATFORM_WINRT - ti->m_handle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); - auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^) - { - m_exitCode = ti->threadFunc(this); - SetEvent(ti->m_handle); - } - , CallbackContext::Any - ); - - ThreadPool::RunAsync(workItemHandler, WorkItemPriority::Normal, WorkItemOptions::TimeSliced); + if (NULL == ti->m_handle) + { + return false; + } #elif BX_PLATFORM_POSIX int result; BX_UNUSED(result); pthread_attr_t attr; result = pthread_attr_init(&attr); - BX_CHECK(0 == result, "pthread_attr_init failed! %d", result); + BX_WARN(0 == result, "pthread_attr_init failed! %d", result); + if (0 != result) + { + return false; + } if (0 != m_stackSize) { result = pthread_attr_setstacksize(&attr, m_stackSize); - BX_CHECK(0 == result, "pthread_attr_setstacksize failed! %d", result); + BX_WARN(0 == result, "pthread_attr_setstacksize failed! %d", result); + + if (0 != result) + { + return false; + } } result = pthread_create(&ti->m_handle, &attr, &ti->threadFunc, this); - BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result); + BX_WARN(0 == result, "pthread_attr_setschedparam failed! %d", result); + if (0 != result) + { + return false; + } #else # error "Not implemented!" #endif // BX_PLATFORM_ + m_running = true; m_sem.wait(); if (NULL != _name) { setThreadName(_name); } + + return true; } void Thread::shutdown() { - BX_CHECK(m_running, "Not running!"); + BX_ASSERT(m_running, "Not running!"); ThreadInternal* ti = (ThreadInternal*)m_internal; #if BX_CRT_NONE crt0::threadJoin(ti->m_handle, NULL); @@ -240,33 +260,47 @@ namespace bx # else pthread_set_name_np(ti->m_handle, _name); # endif // defined(__NetBSD__) -#elif BX_PLATFORM_WINDOWS && BX_COMPILER_MSVC -# pragma pack(push, 8) - struct ThreadName - { - DWORD type; - LPCSTR name; - DWORD id; - DWORD flags; - }; -# pragma pack(pop) - ThreadName tn; - tn.type = 0x1000; - tn.name = _name; - tn.id = ti->m_threadId; - tn.flags = 0; - - __try - { - RaiseException(0x406d1388 - , 0 - , sizeof(tn)/4 - , reinterpret_cast<ULONG_PTR*>(&tn) - ); - } - __except(EXCEPTION_EXECUTE_HANDLER) +#elif BX_PLATFORM_WINDOWS + // Try to use the new thread naming API from Win10 Creators update onwards if we have it + typedef HRESULT (WINAPI *SetThreadDescriptionProc)(HANDLE, PCWSTR); + SetThreadDescriptionProc SetThreadDescription = dlsym<SetThreadDescriptionProc>((void*)GetModuleHandleA("Kernel32.dll"), "SetThreadDescription"); + + if (NULL != SetThreadDescription) { + uint32_t length = (uint32_t)strLen(_name)+1; + uint32_t size = length*sizeof(wchar_t); + wchar_t* name = (wchar_t*)alloca(size); + mbstowcs(name, _name, size-2); + SetThreadDescription(ti->m_handle, name); } +# if BX_COMPILER_MSVC +# pragma pack(push, 8) + struct ThreadName + { + DWORD type; + LPCSTR name; + DWORD id; + DWORD flags; + }; +# pragma pack(pop) + ThreadName tn; + tn.type = 0x1000; + tn.name = _name; + tn.id = ti->m_threadId; + tn.flags = 0; + + __try + { + RaiseException(0x406d1388 + , 0 + , sizeof(tn)/4 + , reinterpret_cast<ULONG_PTR*>(&tn) + ); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } +# endif // BX_COMPILER_MSVC #else BX_UNUSED(_name); #endif // BX_PLATFORM_ @@ -339,14 +373,14 @@ namespace bx TlsDataInternal* ti = (TlsDataInternal*)m_internal; ti->m_id = TlsAlloc(); - BX_CHECK(TLS_OUT_OF_INDEXES != ti->m_id, "Failed to allocated TLS index (err: 0x%08x).", GetLastError() ); + BX_ASSERT(TLS_OUT_OF_INDEXES != ti->m_id, "Failed to allocated TLS index (err: 0x%08x).", GetLastError() ); } TlsData::~TlsData() { TlsDataInternal* ti = (TlsDataInternal*)m_internal; BOOL result = TlsFree(ti->m_id); - BX_CHECK(0 != result, "Failed to free TLS index (err: 0x%08x).", GetLastError() ); BX_UNUSED(result); + BX_ASSERT(0 != result, "Failed to free TLS index (err: 0x%08x).", GetLastError() ); BX_UNUSED(result); } void* TlsData::get() const @@ -369,14 +403,14 @@ namespace bx TlsDataInternal* ti = (TlsDataInternal*)m_internal; int result = pthread_key_create(&ti->m_id, NULL); - BX_CHECK(0 == result, "pthread_key_create failed %d.", result); BX_UNUSED(result); + BX_ASSERT(0 == result, "pthread_key_create failed %d.", result); BX_UNUSED(result); } TlsData::~TlsData() { TlsDataInternal* ti = (TlsDataInternal*)m_internal; int result = pthread_key_delete(ti->m_id); - BX_CHECK(0 == result, "pthread_key_delete failed %d.", result); BX_UNUSED(result); + BX_ASSERT(0 == result, "pthread_key_delete failed %d.", result); BX_UNUSED(result); } void* TlsData::get() const @@ -389,7 +423,7 @@ namespace bx { TlsDataInternal* ti = (TlsDataInternal*)m_internal; int result = pthread_setspecific(ti->m_id, _ptr); - BX_CHECK(0 == result, "pthread_setspecific failed %d.", result); BX_UNUSED(result); + BX_ASSERT(0 == result, "pthread_setspecific failed %d.", result); BX_UNUSED(result); } #endif // BX_PLATFORM_* diff --git a/3rdparty/bx/src/timer.cpp b/3rdparty/bx/src/timer.cpp index 8cfebdda7f5..faecf822e10 100644 --- a/3rdparty/bx/src/timer.cpp +++ b/3rdparty/bx/src/timer.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2010-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + * Copyright 2010-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx/blob/master/LICENSE */ -#include "bx_p.h" #include <bx/timer.h> #if BX_CRT_NONE @@ -13,6 +12,9 @@ #elif BX_PLATFORM_EMSCRIPTEN # include <emscripten.h> #elif BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif // WIN32_LEAN_AND_MEAN # include <windows.h> #else # include <sys/time.h> // gettimeofday @@ -41,7 +43,7 @@ namespace bx gettimeofday(&now, 0); int64_t i64 = now.tv_sec*INT64_C(1000000) + now.tv_usec; #else - BX_CHECK(false, "Not implemented!"); + BX_ASSERT(false, "Not implemented!"); int64_t i64 = UINT64_MAX; #endif // BX_PLATFORM_ return i64; diff --git a/3rdparty/bx/src/url.cpp b/3rdparty/bx/src/url.cpp index f58ecf5a9c3..5421fd01a47 100644 --- a/3rdparty/bx/src/url.cpp +++ b/3rdparty/bx/src/url.cpp @@ -1,9 +1,8 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bnet#license-bsd-2-clause */ -#include "bx_p.h" #include <bx/url.h> namespace bx |