no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,181 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "AABB.h"
#include "base/Macros.h"
#include "cocos/core/geometry/Enums.h"
#include "cocos/core/geometry/Sphere.h"
namespace cc {
namespace geometry {
Sphere *AABB::toBoundingSphere(Sphere *out, const AABB &a) {
out->setCenter(a.getCenter());
out->setRadius(a.getHalfExtents().length());
return out;
}
AABB *AABB::fromPoints(const Vec3 &minPos, const Vec3 &maxPos, AABB *dst) {
Vec3 center{(minPos + maxPos) * 0.5F};
Vec3 halfExtents{(maxPos - minPos) * 0.5F};
dst->setCenter(center);
dst->setHalfExtents(halfExtents);
return dst;
}
AABB *AABB::merge(AABB *out, const AABB &a, const AABB &b) {
Vec3 minCornor;
Vec3 maxCorner;
Vec3::max(a.getCenter() + a.getHalfExtents(), b.getCenter() + b.getHalfExtents(), &maxCorner);
Vec3::min(a.getCenter() - a.getHalfExtents(), b.getCenter() - b.getHalfExtents(), &minCornor);
return AABB::fromPoints(minCornor, maxCorner, out);
}
void AABB::merge(const cc::Vec3 &point) {
cc::Vec3 minPos = getCenter() - getHalfExtents();
cc::Vec3 maxPos = getCenter() + getHalfExtents();
if (point.x < minPos.x) {
minPos.x = point.x;
}
if (point.y < minPos.y) {
minPos.y = point.y;
}
if (point.z < minPos.z) {
minPos.z = point.z;
}
if (point.x > maxPos.x) {
maxPos.x = point.x;
}
if (point.y > maxPos.y) {
maxPos.y = point.y;
}
if (point.z > maxPos.z) {
maxPos.z = point.z;
}
const Vec3 center = (minPos + maxPos) * 0.5F;
setCenter(center);
setHalfExtents(maxPos.x - center.x, maxPos.y - center.y, maxPos.z - center.z);
}
void AABB::merge(const ccstd::vector<cc::Vec3> &points) {
for (const auto &p : points) {
merge(p);
}
}
void AABB::merge(const Frustum &frustum) {
const ccstd::array<Vec3, 8> &vertices = frustum.vertices;
for (size_t i = 0; i < vertices.max_size(); ++i) {
merge(vertices[i]);
}
}
bool AABB::aabbAabb(const AABB &aabb) const {
Vec3 aMin;
Vec3 aMax;
Vec3 bMin;
Vec3 bMax;
Vec3::subtract(getCenter(), getHalfExtents(), &aMin);
Vec3::add(getCenter(), getHalfExtents(), &aMax);
Vec3::subtract(aabb.getCenter(), aabb.getHalfExtents(), &bMin);
Vec3::add(aabb.getCenter(), aabb.getHalfExtents(), &bMax);
return (aMin.x <= bMax.x && aMax.x >= bMin.x) &&
(aMin.y <= bMax.y && aMax.y >= bMin.y) &&
(aMin.z <= bMax.z && aMax.z >= bMin.z);
}
int AABB::aabbPlane(const Plane &plane) const {
auto r = getHalfExtents().x * std::abs(plane.n.x) +
getHalfExtents().y * std::abs(plane.n.y) +
getHalfExtents().z * std::abs(plane.n.z);
auto dot = Vec3::dot(plane.n, getCenter());
if (dot + r < plane.d) {
return -1;
}
if (dot - r > plane.d) {
return 0;
}
return 1;
}
bool AABB::aabbFrustum(const Frustum &frustum) const {
const auto &planes = frustum.planes;
const auto *self = this;
return std::all_of(planes.begin(),
planes.end(),
// frustum plane normal points to the inside
[self](const Plane *plane) { return self->aabbPlane(*plane) != -1; });
}
void AABB::getBoundary(cc::Vec3 *minPos, cc::Vec3 *maxPos) const {
*maxPos = getCenter() + getHalfExtents();
*minPos = getCenter() - getHalfExtents();
}
void AABB::merge(const AABB &aabb) {
AABB::merge(this, aabb, *this);
}
void AABB::set(const cc::Vec3 &centerVal, const cc::Vec3 &halfExtentVal) {
setCenter(centerVal);
setHalfExtents(halfExtentVal);
}
void AABB::transform(const Mat4 &m, AABB *out) const {
Vec3::transformMat4(center, m, &out->center);
transformExtentM4(&out->halfExtents, getHalfExtents(), m);
}
bool AABB::contain(const cc::Vec3 &point) const {
cc::Vec3 minPos = getCenter() - getHalfExtents();
cc::Vec3 maxPos = getCenter() + getHalfExtents();
return !(point.x > maxPos.x || point.x < minPos.x ||
point.y > maxPos.y || point.y < minPos.y ||
point.z > maxPos.z || point.z < minPos.z);
}
// https://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
void AABB::transformExtentM4(Vec3 *out, const Vec3 &extent, const Mat4 &m4) {
Mat3 m3Tmp;
m3Tmp.m[0] = std::abs(m4.m[0]);
m3Tmp.m[1] = std::abs(m4.m[1]);
m3Tmp.m[2] = std::abs(m4.m[2]);
m3Tmp.m[3] = std::abs(m4.m[4]);
m3Tmp.m[4] = std::abs(m4.m[5]);
m3Tmp.m[5] = std::abs(m4.m[6]);
m3Tmp.m[6] = std::abs(m4.m[8]);
m3Tmp.m[7] = std::abs(m4.m[9]);
m3Tmp.m[8] = std::abs(m4.m[10]);
out->transformMat3(extent, m3Tmp);
}
AABB::AABB(float px, float py, float pz, float hw, float hh, float hl) : AABB() {
setCenter(px, py, pz);
setHalfExtents(hw, hh, hl);
}
} // namespace geometry
} // namespace cc

164
cocos/core/geometry/AABB.h Normal file
View File

@@ -0,0 +1,164 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <algorithm>
#include "base/memory/Memory.h"
#include "base/std/container/vector.h"
#include "core/geometry/Enums.h"
#include "math/Mat3.h"
#include "math/Quaternion.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
class Sphere;
class Frustum;
class Plane;
class AABB final : public ShapeBase {
public:
/**
* @en
* create a new AABB
* @zh
* 创建一个新的 AABB 实例。
* @param px - AABB 的原点的 X 坐标。
* @param py - AABB 的原点的 Y 坐标。
* @param pz - AABB 的原点的 Z 坐标。
* @param hw - AABB 宽度的一半。
* @param hh - AABB 高度的一半。
* @param hl - AABB 长度的一半。
* @returns 返回新创建的 AABB 实例。
*/
static AABB *create(float px, float py, float pz, float hw, float hh, float hl) {
return ccnew AABB(px, py, pz, hw, hh, hl);
}
/**
* @en
* Set the components of a AABB to the given values
* @zh
* 将 AABB 的属性设置为给定的值。
* @param {AABB} out 接受操作的 AABB。
* @param px - AABB 的原点的 X 坐标。
* @param py - AABB 的原点的 Y 坐标。
* @param pz - AABB 的原点的 Z 坐标。
* @param hw - AABB 宽度的一半。
* @param hh - AABB 高度的一半。
* @param hl - AABB 长度度的一半。
* @return {AABB} out 接受操作的 AABB。
*/
static AABB *set(AABB *out, float px, float py,
float pz,
float hw,
float hh,
float hl) {
out->setCenter(px, py, pz);
out->setHalfExtents(hw, hh, hl);
return out;
}
/**
* @en
* Merge tow AABB.
* @zh
* 合并两个 AABB 到 out。
* @param out 接受操作的 AABB。
* @param a 输入的 AABB。
* @param b 输入的 AABB。
* @returns {AABB} out 接受操作的 AABB。
*/
static AABB *merge(AABB *out, const AABB &a, const AABB &b);
/**
* @en
* AABB to sphere
* @zh
* 包围盒转包围球
* @param out 接受操作的 sphere。
* @param a 输入的 AABB。
*/
static Sphere *toBoundingSphere(Sphere *out, const AABB &a);
static AABB *fromPoints(const Vec3 &minPos, const Vec3 &maxPos, AABB *dst);
static void transformExtentM4(Vec3 *out, const Vec3 &extent, const Mat4 &m4);
AABB(float px, float py, float pz, float hw, float hh, float hl);
AABB() : ShapeBase(ShapeEnum::SHAPE_AABB) {}
~AABB() override = default;
/**
* @en
* aabb-plane intersect detect.
* @zh
* 轴对齐包围盒和平面的相交性检测。
* @param {AABB} aabb 轴对齐包围盒
* @param {Plane} plane 平面
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
*/
bool aabbAabb(const AABB &aabb) const;
/**
* @en
* aabb-frustum intersect detect, faster but has false positive corner cases.
* @zh
* 轴对齐包围盒和锥台相交性检测,速度快,但有错误情况。
* @param {AABB} aabb 轴对齐包围盒
* @param {Frustum} frustum 锥台
* @return {number} 0 或 非0
*/
bool aabbFrustum(const Frustum &) const;
int aabbPlane(const Plane &) const;
void getBoundary(cc::Vec3 *minPos, cc::Vec3 *maxPos) const;
void merge(const AABB &aabb);
void merge(const cc::Vec3 &point);
void merge(const ccstd::vector<cc::Vec3> &points);
void merge(const Frustum &frustum);
void set(const cc::Vec3 &centerVal, const cc::Vec3 &halfExtentVal);
void transform(const Mat4 &m, AABB *out) const;
bool contain(const cc::Vec3 &point) const;
inline void setCenter(float x, float y, float z) { center.set(x, y, z); }
inline void setCenter(const Vec3 &center) { this->center.set(center); }
inline void setValid(bool isValid) { _isValid = isValid; }
inline const Vec3 &getCenter() const { return center; }
inline bool isValid() const { return _isValid; }
inline void setHalfExtents(float x, float y, float z) { halfExtents.set(x, y, z); }
inline void setHalfExtents(const Vec3 &halfExtents) { this->halfExtents.set(halfExtents); }
inline const Vec3 &getHalfExtents() const { return halfExtents; }
cc::Vec3 center;
cc::Vec3 halfExtents{1, 1, 1};
private:
bool _isValid{true};
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,71 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "cocos/core/geometry/Capsule.h"
#include "cocos/math/Vec3.h"
namespace cc {
namespace geometry {
void Capsule::transform(const Mat4 &m, const Vec3 & /*pos*/, const Quaternion &rot, const Vec3 &scale, Capsule *out) const {
const auto maxComponent = mathutils::absMaxComponent(scale);
out->radius = this->radius * std::abs(maxComponent);
const auto halfTotalWorldHeight = (this->halfHeight + this->radius) * std::abs(scale.y);
auto halfWorldHeight = halfTotalWorldHeight - out->radius;
if (halfWorldHeight < 0) halfWorldHeight = 0;
out->halfHeight = halfWorldHeight;
out->center.transformMat4(this->center, m);
Quaternion::multiply(this->rotation, rot, &out->rotation);
out->updateCache();
}
void Capsule::updateCache() {
updateLocalCenter();
ellipseCenter0.transformQuat(rotation);
ellipseCenter1.transformQuat(rotation);
ellipseCenter0 += center;
ellipseCenter1 += center;
}
void Capsule::updateLocalCenter() {
switch (axis) {
case CenterEnum::X:
ellipseCenter0 = {halfHeight, 0, 0};
ellipseCenter1 = {-halfHeight, 0, 0};
break;
case CenterEnum::Y:
ellipseCenter0 = {0, halfHeight, 0};
ellipseCenter1 = {0, -halfHeight, 0};
break;
case CenterEnum::Z:
ellipseCenter0 = {0, 0, halfHeight};
ellipseCenter1 = {0, 0, -halfHeight};
break;
default:
CC_ABORT();
}
}
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,130 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "core/geometry/Enums.h"
#include "math/Mat4.h"
#include "math/Quaternion.h"
#include "math/Utils.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
/**
* @en
* Basic Geometry: capsule.
* @zh
* 基础几何,胶囊体。
*/
class Capsule final : public ShapeBase {
/**
* @en
* Gets the type of the shape.
* @zh
* 获取形状的类型。
*/
public:
enum class CenterEnum {
X = 0,
Y = 1,
Z = 2
};
/**
* @en
* Capsule sphere radius.
* @zh
* 胶囊体球部半径。
*/
float radius{0.0F};
/**
* @en
* The distance between the center point of the capsule and the center of the sphere.
* @zh
* 胶囊体中心点和球部圆心的距离。
*/
float halfHeight{0.0F};
/**
* @en
* Local orientation of capsule [0,1,2] => [x,y,z].
* @zh
* 胶囊体的本地朝向,映射关系 [0,1,2] => [x,y,z]。
*/
CenterEnum axis;
/**
* @en
* The origin of the capsule.
* @zh
* 胶囊体的原点。
*/
Vec3 center;
/**
* @en
* The rotation of the capsule.
* @zh
* 胶囊体的旋转。
*/
Quaternion rotation;
/** cache, local center of ellipse */
Vec3 ellipseCenter0;
Vec3 ellipseCenter1;
explicit Capsule(float radius = 0.5, float halfHeight = 0.5, CenterEnum axis = CenterEnum::Y) : ShapeBase(ShapeEnum::SHAPE_CAPSULE) {
this->radius = radius;
this->halfHeight = halfHeight;
this->axis = axis;
this->center = {};
this->rotation = {};
ellipseCenter0 = {0, halfHeight, 0};
ellipseCenter1 = {0, -halfHeight, 0};
updateCache();
}
Capsule(const Capsule &other) = default;
Capsule(Capsule &&other) = default;
Capsule &operator=(const Capsule &other) = default;
Capsule &operator=(Capsule &&other) = default;
~Capsule() override = default;
/**
* @en
* Transform this capsule.
* @zh
* 变换此胶囊体。
*/
void transform(const Mat4 &m, const Vec3 &pos, const Quaternion &rot, const Vec3 &scale, Capsule *out) const;
private:
void updateCache();
void updateLocalCenter();
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,38 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "cocos/core/geometry/Curve.h"
namespace cc {
namespace geometry {
float OptimizedKey::evaluate(float tt) {
const t = tt - time;
return evalOptCurve(t, coefficient);
}
float evalOptCurve(float t, const ccstd::vector<float> &coefs) {
return (t * (t * (t * coefs[0] + coefs[1]) + coefs[2])) + coefs[3];
}
} // namespace geometry
} // namespace cc

386
cocos/core/geometry/Curve.h Normal file
View File

@@ -0,0 +1,386 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
namespace cc {
namespace geometry {
constexpr auto LOOK_FORWARD = 3;
/**
* @en
* A key frame in the curve.
* @zh
* 曲线中的一个关键帧。
*/
struct Keyframe {
/**
* @en Current frame time.
* @zh 当前帧时间。
*/
float time = 0;
/**
* @en Current frame value.
* @zh 当前帧的值。
*/
float value = 0;
/**
* @en In tangent value.
* @zh 左切线。
*/
float inTangent = 0;
/**
* @en Out tangent value.
* @zh 右切线。
*/
float outTangent = 0;
};
float evalOptCurve(float t, const ccstd::vector<float> &coefs);
struct OptimizedKey {
float index;
float time;
float endTime;
ccstd::vector<float> coefficient;
OptimizedKey() {
index = -1;
time = 0;
endTime = 0;
coefficient.resize(4);
}
static float evaluate(float t);
};
/**
* @en
* Describe a curve in which three times Hermite interpolation is used for each adjacent key frame.
* @zh
* 描述一条曲线其中每个相邻关键帧采用三次hermite插值计算。
*/
class AnimationCurve {
// @serializable
private:
// _curve ! : RealCurve;
public:
static ccstd::vector<KeyFrame> defaultKF = [ {
time : 0,
value : 1,
inTangent : 0,
outTangent : 0,
},
{
time : 1,
value : 1,
inTangent : 0,
outTangent : 0,
} ];
/**
* For internal usage only.
* @internal
*/
get _internalCurve() {
return this._curve;
}
/**
* @en
* The key frame of the curve.
* @zh
* 曲线的关键帧。
*/
auto getKeyFrames() {
return Array.from(this._curve.keyframes()).map(([ time, value ]) = > {
const legacyKeyframe = ccnew Keyframe();
legacyKeyframe.time = time;
legacyKeyframe.value = value.value;
legacyKeyframe.inTangent = value.leftTangent;
legacyKeyframe.outTangent = value.rightTangent;
return legacyKeyframe;
});
}
void setKeyFrames(value) {
this._curve.assignSorted(value.map((legacyCurve) = > [
legacyCurve.time,
{
interpolationMode : RealInterpolationMode.CUBIC,
value : legacyCurve.value,
leftTangent : legacyCurve.inTangent,
rightTangent : legacyCurve.outTangent,
},
]));
}
/**
* @en
* Loop mode [[WrapMode]] when the sampling time exceeds the left end.
* @zh
* 当采样时间超出左端时采用的循环模式[[WrapMode]]。
*/
auto getPreWrapMode() {
return toLegacyWrapMode(this._curve.preExtrapolation);
}
void sPreWrapMode(value) {
this._curve.preExtrapolation = fromLegacyWrapMode(value);
}
/**
* @en
* Cycle mode [[WrapMode]] when the sampling time exceeds the right end.
* @zh
* 当采样时间超出右端时采用的循环模式[[WrapMode]]。
*/
get postWrapMode() {
return toLegacyWrapMode(this._curve.postExtrapolation);
}
set postWrapMode(value) {
this._curve.postExtrapolation = fromLegacyWrapMode(value);
}
private
cachedKey : OptimizedKey;
/**
* 构造函数。
* @param keyFrames 关键帧。
*/
constructor(keyFrames
: Keyframe[] | null | RealCurve = null) {
if (keyFrames instanceof RealCurve) {
this._curve = keyFrames;
} else {
const curve = ccnew RealCurve();
this._curve = curve;
curve.preExtrapolation = ExtrapolationMode.LOOP;
curve.postExtrapolation = ExtrapolationMode.CLAMP;
if (!keyFrames) {
curve.assignSorted([
[ 0.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
[ 1.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
]);
} else {
curve.assignSorted(keyFrames.map((legacyKeyframe) = > [ legacyKeyframe.time, {
interpolationMode : RealInterpolationMode.CUBIC,
value : legacyKeyframe.value,
leftTangent : legacyKeyframe.inTangent,
rightTangent : legacyKeyframe.outTangent,
} ]));
}
}
this.cachedKey = ccnew OptimizedKey();
}
/**
* @en
* Add a keyframe.
* @zh
* 添加一个关键帧。
* @param keyFrame 关键帧。
*/
public
addKey(keyFrame
: Keyframe | null) {
if (!keyFrame) {
this._curve.clear();
} else {
this._curve.addKeyFrame(keyFrame.time, {
interpolationMode : RealInterpolationMode.CUBIC,
value : keyFrame.value,
leftTangent : keyFrame.inTangent,
rightTangent : keyFrame.outTangent,
});
}
}
/**
* @ignore
* @param time
*/
public
evaluate_slow(time
: number) {
return this._curve.evaluate(time);
}
/**
* @en
* Calculate the curve interpolation at a given point in time.
* @zh
* 计算给定时间点的曲线插值。
* @param time 时间。
*/
public
evaluate(time
: number) {
const {cachedKey, _curve : curve} = this;
const nKeyframes = curve.keyFramesCount;
const lastKeyframeIndex = nKeyframes - 1;
let wrappedTime = time;
const extrapolationMode = time < 0 ? curve.preExtrapolation : curve.postExtrapolation;
const startTime = curve.getKeyframeTime(0);
const endTime = curve.getKeyframeTime(lastKeyframeIndex);
switch (extrapolationMode) {
case ExtrapolationMode.LOOP:
wrappedTime = repeat(time - startTime, endTime - startTime) + startTime;
break;
case ExtrapolationMode.PING_PONG:
wrappedTime = pingPong(time - startTime, endTime - startTime) + startTime;
break;
case ExtrapolationMode.CLAMP:
default:
wrappedTime = clamp(time, startTime, endTime);
break;
}
if (wrappedTime >= cachedKey.time && wrappedTime < cachedKey.endTime) {
return cachedKey.evaluate(wrappedTime);
}
const leftIndex = this.findIndex(cachedKey, wrappedTime);
const rightIndex = Math.min(leftIndex + 1, lastKeyframeIndex);
this.calcOptimizedKey(cachedKey, leftIndex, rightIndex);
return cachedKey.evaluate(wrappedTime);
}
/**
* @ignore
* @param optKey
* @param leftIndex
* @param rightIndex
*/
public
calcOptimizedKey(optKey
: OptimizedKey, leftIndex
: number, rightIndex
: number) {
const lhsTime = this._curve.getKeyframeTime(leftIndex);
const rhsTime = this._curve.getKeyframeTime(rightIndex);
const {value : lhsValue, leftTangent : lhsOutTangent} = this._curve.getKeyframeValue(leftIndex);
const {value : rhsValue, rightTangent : rhsInTangent} = this._curve.getKeyframeValue(rightIndex);
optKey.index = leftIndex;
optKey.time = lhsTime;
optKey.endTime = rhsTime;
const dx = rhsTime - lhsTime;
const dy = rhsValue - lhsValue;
const length = 1 / (dx * dx);
const d1 = lhsOutTangent * dx;
const d2 = rhsInTangent * dx;
optKey.coefficient[0] = (d1 + d2 - dy - dy) * length / dx;
optKey.coefficient[1] = (dy + dy + dy - d1 - d1 - d2) * length;
optKey.coefficient[2] = lhsOutTangent;
optKey.coefficient[3] = lhsValue;
}
/**
* @ignore
* @param optKey
* @param t
*/
private
findIndex(optKey
: OptimizedKey, t
: number) {
const {_curve : curve} = this;
const nKeyframes = curve.keyFramesCount;
const cachedIndex = optKey.index;
if (cachedIndex != = -1) {
const cachedTime = curve.getKeyframeTime(cachedIndex);
if (t > cachedTime) {
for (let i = 0; i < LOOK_FORWARD; i++) {
const currIndex = cachedIndex + i;
if (currIndex + 1 < nKeyframes && curve.getKeyframeTime(currIndex + 1) > t) {
return currIndex;
}
}
} else {
for (let i = 0; i < LOOK_FORWARD; i++) {
const currIndex = cachedIndex - i;
if (currIndex >= 0 && curve.getKeyframeTime(currIndex - 1) <= t) {
return currIndex - 1;
}
}
}
}
let left = 0;
let right = nKeyframes;
let mid;
while (right - left > 1) {
mid = Math.floor((left + right) / 2);
if (curve.getKeyframeTime(mid) >= t) {
right = mid;
} else {
left = mid;
}
}
return left;
}
}
function
fromLegacyWrapMode(legacyWrapMode
: WrapModeMask) : ExtrapolationMode {
switch (legacyWrapMode) {
default:
case WrapModeMask.Default:
case WrapModeMask.Normal:
case WrapModeMask.Clamp: return ExtrapolationMode.CLAMP;
case WrapModeMask.PingPong: return ExtrapolationMode.PING_PONG;
case WrapModeMask.Loop: return ExtrapolationMode.LOOP;
}
}
function toLegacyWrapMode(extrapolationMode
: ExtrapolationMode) : WrapModeMask {
switch (extrapolationMode) {
default:
case ExtrapolationMode.LINEAR:
case ExtrapolationMode.CLAMP: return WrapModeMask.Clamp;
case ExtrapolationMode.PING_PONG: return WrapModeMask.PingPong;
case ExtrapolationMode.LOOP: return WrapModeMask.Loop;
}
}
/**
* Same as but more effective than `new LegacyCurve()._internalCurve`.
*/
export function constructLegacyCurveAndConvert() {
const curve = ccnew RealCurve();
curve.assignSorted([
[ 0.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
[ 1.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
]);
return curve;
}
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,104 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "cocos/core/geometry/Distance.h"
#include "cocos/core/geometry/AABB.h"
#include "cocos/core/geometry/Obb.h"
#include "cocos/core/geometry/Plane.h"
#include "cocos/math/Mat4.h"
#include <algorithm>
#include "base/std/container/array.h"
#include "cocos/math/Utils.h"
#include "cocos/math/Vec3.h"
namespace cc {
namespace geometry {
float pointPlane(const Vec3 &point, const Plane &plane) {
return Vec3::dot(plane.n, point) - plane.d;
}
Vec3 *ptPointPlane(Vec3 *out, const Vec3 &point, const Plane &plane) {
auto t = pointPlane(point, plane);
*out = point - t * plane.n;
return out;
}
Vec3 *ptPointAabb(Vec3 *out, const Vec3 &point, const AABB &aabb) {
auto min = aabb.getCenter() - aabb.getHalfExtents();
auto max = aabb.getCenter() + aabb.getHalfExtents();
*out = {cc::mathutils::clamp(point.x, min.x, max.x),
cc::mathutils::clamp(point.y, min.y, max.y),
cc::mathutils::clamp(point.z, min.z, max.z)};
return out;
}
Vec3 *ptPointObb(Vec3 *out, const Vec3 &point, const OBB &obb) {
ccstd::array<Vec3, 3> u = {
Vec3{obb.orientation.m[0], obb.orientation.m[1], obb.orientation.m[2]},
Vec3{obb.orientation.m[3], obb.orientation.m[4], obb.orientation.m[5]},
Vec3{obb.orientation.m[6], obb.orientation.m[7], obb.orientation.m[8]},
};
ccstd::array<float, 3> e = {obb.halfExtents.x, obb.halfExtents.y, obb.halfExtents.z};
auto d = point - obb.center;
float dist = 0.0F;
// Start result at center of obb; make steps from there
*out = obb.center;
// For each OBB axis...
for (int i = 0; i < 3; i++) {
// ...project d onto that axis to get the distance
// along the axis of d from the obb center
dist = Vec3::dot(d, u[i]);
// if distance farther than the obb extents, clamp to the obb
dist = cc::mathutils::clamp(dist, -e[i], e[i]);
// Step that distance along the axis to get world coordinate
*out += (dist * u[i]);
}
return out;
}
Vec3 *ptPointLine(Vec3 *out, const Vec3 &point, const Vec3 &linePointA, const Vec3 &linePointB) {
auto dir = linePointA - linePointB;
auto dirSquared = dir.lengthSquared();
if (dirSquared == 0.0F) {
// The point is at the segment start.
*out = linePointA;
} else {
// Calculate the projection of the point onto the line extending through the segment.
auto ap = point - linePointA;
auto t = Vec3::dot(ap, dir) / dirSquared;
*out = linePointA + cc::mathutils::clamp(t, 0.0F, 1.0F) * dir;
}
return out;
}
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,96 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
namespace cc {
class Mat4;
class Vec3;
namespace geometry {
class Plane;
class OBB;
class AABB;
/**
* @en
* the distance between a point and a plane
* @zh
* 计算点和平面之间的距离。
* @param {Vec3} point 点。
* @param {Plane} plane 平面。
* @return 距离。
*/
float pointPlane(const Vec3 &point, const Plane &plane);
/**
* @en
* the closest point on plane to a given point
* @zh
* 计算平面上最接近给定点的点。
* @param out 最近点。
* @param point 给定点。
* @param plane 平面。
* @return 最近点。
*/
Vec3 *ptPointPlane(Vec3 *out, const Vec3 &point, const Plane &plane);
/**
* @en
* the closest point on aabb to a given point
* @zh
* 计算 aabb 上最接近给定点的点。
* @param {Vec3} out 最近点。
* @param {Vec3} point 给定点。
* @param {AABB} aabb 轴对齐包围盒。
* @return {Vec3} 最近点。
*/
Vec3 *ptPointAabb(Vec3 *out, const Vec3 &point, const AABB &aabb);
/**
* @en
* the closest point on obb to a given point
* @zh
* 计算 obb 上最接近给定点的点。
* @param {Vec3} out 最近点。
* @param {Vec3} point 给定点。
* @param {OBB} obb 方向包围盒。
* @return {Vec3} 最近点。
*/
Vec3 *ptPointObb(Vec3 *out, const Vec3 &point, const OBB &obb);
/**
* @en
* Calculate the nearest point on the line to the given point.
* @zh
* 计算给定点距离直线上最近的一点。
* @param out 最近点
* @param point 给定点
* @param linePointA 线上的某点 A
* @param linePointB 线上的某点 B
*/
Vec3 *ptPointLine(Vec3 *out, const Vec3 &point, const Vec3 &linePointA, const Vec3 &linePointB);
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,69 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "base/RefCounted.h"
namespace cc {
namespace geometry {
enum class ShapeEnum {
SHAPE_RAY = (1 << 0),
SHAPE_LINE = (1 << 1),
SHAPE_SPHERE = (1 << 2),
SHAPE_AABB = (1 << 3),
SHAPE_OBB = (1 << 4),
SHAPE_PLANE = (1 << 5),
SHAPE_TRIANGLE = (1 << 6),
SHAPE_FRUSTUM = (1 << 7),
SHAPE_FRUSTUM_ACCURATE = (1 << 8),
SHAPE_CAPSULE = (1 << 9),
SHAPE_SPLINE = (1 << 10),
SHAPE_BAD = (1 << 11),
};
class ShapeBase : public RefCounted {
public:
ShapeBase(ShapeEnum type) : _type(type) {}
/**
* @en
* Gets the type of the shape.
* @zh
* 获取形状的类型。
*/
inline ShapeEnum getType() const {
CC_ASSERT_NE(_type, ShapeEnum::SHAPE_BAD); // shape is not initialized
return _type;
}
inline void setType(ShapeEnum type) { _type = type; }
private:
ShapeEnum _type = ShapeEnum::SHAPE_BAD;
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,215 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "core/geometry/Frustum.h"
#include <cmath>
#include "core/geometry/Enums.h"
#include "scene/Define.h"
namespace cc {
namespace geometry {
namespace {
const ccstd::vector<cc::Vec3> VEC_VALS{
{1, 1, 1},
{-1, 1, 1},
{-1, -1, 1},
{1, -1, 1},
{1, 1, -1},
{-1, 1, -1},
{-1, -1, -1},
{1, -1, -1}};
} // namespace
void Frustum::createOrtho(Frustum *out, float width,
float height,
float near,
float far,
const Mat4 &transform) {
createOrthographic(out, width, height, near, far, transform);
}
void Frustum::createOrthographic(Frustum *out, float width,
float height,
float near,
float far,
const Mat4 &transform) {
auto halfWidth = width / 2.0F;
auto halfHeight = height / 2.0F;
Vec3::transformMat4({halfWidth, halfHeight, -near}, transform, &out->vertices[0]);
Vec3::transformMat4({-halfWidth, halfHeight, -near}, transform, &out->vertices[1]);
Vec3::transformMat4({-halfWidth, -halfHeight, -near}, transform, &out->vertices[2]);
Vec3::transformMat4({halfWidth, -halfHeight, -near}, transform, &out->vertices[3]);
Vec3::transformMat4({halfWidth, halfHeight, -far}, transform, &out->vertices[4]);
Vec3::transformMat4({-halfWidth, halfHeight, -far}, transform, &out->vertices[5]);
Vec3::transformMat4({-halfWidth, -halfHeight, -far}, transform, &out->vertices[6]);
Vec3::transformMat4({halfWidth, -halfHeight, -far}, transform, &out->vertices[7]);
out->updatePlanes();
}
Frustum *Frustum::createFromAABB(Frustum *out, const AABB &aabb) {
Vec3 minPos;
Vec3 maxPos;
aabb.getBoundary(&minPos, &maxPos);
out->vertices[0].set(maxPos.x, maxPos.y, -minPos.z);
out->vertices[1].set(minPos.x, maxPos.y, -minPos.z);
out->vertices[2].set(minPos.x, minPos.y, -minPos.z);
out->vertices[3].set(maxPos.x, minPos.y, -minPos.z);
out->vertices[4].set(maxPos.x, maxPos.y, -maxPos.z);
out->vertices[5].set(minPos.x, maxPos.y, -maxPos.z);
out->vertices[6].set(minPos.x, minPos.y, -maxPos.z);
out->vertices[7].set(maxPos.x, minPos.y, -maxPos.z);
out->updatePlanes();
return out;
}
void Frustum::createPerspective(Frustum *out, float fov,
float aspect,
float near,
float far,
const Mat4 &transform) {
const float h = tanf(fov * 0.5F);
const float w = h * aspect;
const Vec3 nearTemp(near * w, near * h, near);
const Vec3 farTemp(far * w, far * h, far);
out->vertices[0].transformMat4(Vec3(nearTemp.x, nearTemp.y, -nearTemp.z), transform);
out->vertices[1].transformMat4(Vec3(-nearTemp.x, nearTemp.y, -nearTemp.z), transform);
out->vertices[2].transformMat4(Vec3(-nearTemp.x, -nearTemp.y, -nearTemp.z), transform);
out->vertices[3].transformMat4(Vec3(nearTemp.x, -nearTemp.y, -nearTemp.z), transform);
out->vertices[4].transformMat4(Vec3(farTemp.x, farTemp.y, -farTemp.z), transform);
out->vertices[5].transformMat4(Vec3(-farTemp.x, farTemp.y, -farTemp.z), transform);
out->vertices[6].transformMat4(Vec3(-farTemp.x, -farTemp.y, -farTemp.z), transform);
out->vertices[7].transformMat4(Vec3(farTemp.x, -farTemp.y, -farTemp.z), transform);
out->updatePlanes();
}
void Frustum::update(const Mat4 &m, const Mat4 &inv) {
// left plane
planes[0]->n.set(m.m[3] + m.m[0], m.m[7] + m.m[4], m.m[11] + m.m[8]);
planes[0]->d = -(m.m[15] + m.m[12]);
// right plane
planes[1]->n.set(m.m[3] - m.m[0], m.m[7] - m.m[4], m.m[11] - m.m[8]);
planes[1]->d = -(m.m[15] - m.m[12]);
// bottom plane
planes[2]->n.set(m.m[3] + m.m[1], m.m[7] + m.m[5], m.m[11] + m.m[9]);
planes[2]->d = -(m.m[15] + m.m[13]);
// top plane
planes[3]->n.set(m.m[3] - m.m[1], m.m[7] - m.m[5], m.m[11] - m.m[9]);
planes[3]->d = -(m.m[15] - m.m[13]);
// near plane
planes[4]->n.set(m.m[3] + m.m[2], m.m[7] + m.m[6], m.m[11] + m.m[10]);
planes[4]->d = -(m.m[15] + m.m[14]);
// far plane
planes[5]->n.set(m.m[3] - m.m[2], m.m[7] - m.m[6], m.m[11] - m.m[10]);
planes[5]->d = -(m.m[15] - m.m[14]);
for (Plane *plane : planes) {
float invDist = 1 / plane->n.length();
plane->n *= invDist;
plane->d *= invDist;
}
uint32_t i = 0;
for (const Vec3 &vec : VEC_VALS) {
vertices[i].transformMat4(vec, inv);
i++;
}
}
void Frustum::transform(const Mat4 &mat) {
for (auto i = 0; i < 8; i++) {
vertices[i].transformMat4(vertices[i], mat);
}
updatePlanes();
}
void Frustum::createOrthographic(float width, float height, float near, float far, const Mat4 &transform) {
createOrthographic(this, width, height, near, far, transform);
}
void Frustum::createOrtho(const float width, const float height, const float near, const float far, const Mat4 &transform) {
createOrthographic(width, height, near, far, transform);
}
void Frustum::split(float near, float far, float aspect, float fov, const Mat4 &transform) {
createPerspective(this, fov, aspect, near, far, transform);
}
void Frustum::updatePlanes() {
// left plane
planes[0]->define(vertices[1], vertices[6], vertices[5]);
// right plane
planes[1]->define(vertices[3], vertices[4], vertices[7]);
// bottom plane
planes[2]->define(vertices[6], vertices[3], vertices[7]);
// top plane
planes[3]->define(vertices[0], vertices[5], vertices[4]);
// near plane
planes[4]->define(vertices[2], vertices[0], vertices[3]);
// far plane
planes[5]->define(vertices[7], vertices[5], vertices[6]);
}
Frustum::Frustum() : ShapeBase(ShapeEnum::SHAPE_FRUSTUM) {
init();
}
Frustum::Frustum(const Frustum &rhs) : ShapeBase(rhs) {
init();
*this = rhs;
}
Frustum::~Frustum() {
for (auto *plane : planes) {
plane->release();
}
}
Frustum &Frustum::operator=(const Frustum &rhs) {
if (this == &rhs) {
return *this;
}
vertices = rhs.vertices;
for (size_t i = 0; i < planes.size(); ++i) { // NOLINT(modernize-loop-convert)
Plane::copy(planes[i], *rhs.planes[i]);
}
return *this;
}
void Frustum::init() {
for (size_t i = 0; i < planes.size(); ++i) { // NOLINT(modernize-loop-convert)
planes[i] = ccnew Plane();
planes[i]->addRef();
}
}
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,207 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/memory/Memory.h"
#include "base/std/container/array.h"
#include "core/geometry/AABB.h"
#include "core/geometry/Enums.h"
#include "core/geometry/Plane.h"
#include "math/Mat4.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
class Frustum final : public ShapeBase {
public:
/**
* @en
* Create a ortho frustum.
* @zh
* 创建一个正交视锥体。
* @param out @en The result orthographic frustum. @zh 输出的正交视锥体。
* @param width @en The width of the frustum. @zh 正交视锥体的宽度。
* @param height @en The height of the frustum. @zh 正交视锥体的高度。
* @param near @en The near plane of the frustum. @zh 正交视锥体的近平面值。
* @param far @en The far plane of the frustum. @zh 正交视锥体的远平面值。
* @param transform @en The transform matrix of the frustum. @zh 正交视锥体的变换矩阵。
*
* @deprecated since 3.8.0, please use [createOrthographic] instead of it.
*/
static void createOrtho(Frustum *out, float width,
float height,
float near,
float far,
const Mat4 &transform);
/**
* @en
* Create a ortho frustum.
* @zh
* 创建一个正交视锥体。
* @param out @en The result orthographic frustum. @zh 输出的正交视锥体。
* @param width @en The width of the frustum. @zh 正交视锥体的宽度。
* @param height @en The height of the frustum. @zh 正交视锥体的高度。
* @param near @en The near plane of the frustum. @zh 正交视锥体的近平面值。
* @param far @en The far plane of the frustum. @zh 正交视锥体的远平面值。
* @param transform @en The transform matrix of the frustum. @zh 正交视锥体的变换矩阵。
*/
static void createOrthographic(Frustum *out, float width,
float height,
float near,
float far,
const Mat4 &transform);
/**
* @en
* Create a perspective frustum.
* @zh
* 创建一个透视视锥体。
* @param out @en The result perspective frustum. @zh 输出的透视视锥体。
* @param fov @en The field of view of the frustum. @zh 视锥体的视野。
* @param aspect @en The aspect ratio of the frustum. @zh 视锥体的宽高比。
* @param near @en The near plane of the frustum. @zh 视锥体的近平面值。
* @param far @en The far plane of the frustum. @zh 视锥体的远平面值。
* @param transform @en The transform matrix of the frustum. @zh 视锥体的变换矩阵。
*/
static void createPerspective(Frustum *out, float fov,
float aspect,
float near,
float far,
const Mat4 &transform);
/**
* @en Create a frustum from an AABB box.
* @zh 从 AABB 包围盒中创建一个视锥体。
* @param out @en The result frustum @zh 输出的视锥体对象。
* @param aabb @en The AABB bounding box of the frustum @zh AABB 包围盒。
* @return @en The out object @zh 返回视锥体.
*
* @deprecated since 3.8.0, please use [createOrthographic] instead of it.
*/
static Frustum *createFromAABB(Frustum *out, const AABB &aabb);
/**
* @en
* Create a ccnew frustum.
* @zh
* 创建一个新的截锥体。
* @return @en An empty frustum. @zh 一个空截椎体
*/
static Frustum *create() {
return ccnew Frustum();
}
/**
* @en
* Clone a frustum.
* @zh
* 克隆一个截锥体。
* @param f @en The frustum to clone from @zh 用于克隆的截锥体
* @return @en The cloned frustum @zh 克隆出的新截锥体
*/
static Frustum *clone(const Frustum &f) {
return Frustum::copy(ccnew Frustum(), f);
}
/**
* @en
* Copy the values from one frustum to another.
* @zh
* 从一个视锥体拷贝到另一个视锥体。
* @param out @en The result frustum @zh 用于存储拷贝数据的截锥体
* @param f @en The frustum to copy from @zh 用于克隆的截锥体
* @return @en The out object @zh 传入的 out 对象
*/
static Frustum *copy(Frustum *out, const Frustum &f) {
out->setType(f.getType());
for (size_t i = 0; i < 6; ++i) { // NOLINT(modernize-loop-convert)
Plane::copy(out->planes[i], *(f.planes[i]));
}
out->vertices = f.vertices;
return out;
}
Frustum();
Frustum(const Frustum &rhs);
Frustum(Frustum &&rhs) = delete;
~Frustum() override;
// Can remove these operator override functions if not using Plane* in planes array.
Frustum &operator=(const Frustum &rhs);
Frustum &operator=(Frustum &&rhs) = delete;
/**
* @en
* Transform this frustum.
* @zh
* 变换此截锥体。
* @param mat 变换矩阵。
*/
void transform(const Mat4 &);
void createOrtho(float width, float height, float near, float far, const Mat4 &transform);
void createOrthographic(float width, float height, float near, float far, const Mat4 &transform);
/**
* @en
* Set as a perspective frustum.
* @zh
* 设置为一个透视视锥体。
* @param near @en The near plane of the frustum. @zh 视锥体的近平面值。
* @param far @en The far plane of the frustum. @zh 视锥体的远平面值。
* @param fov @en The field of view of the frustum. @zh 视锥体的视野。
* @param aspect @en The aspect ratio of the frustum. @zh 视锥体的宽高比。
* @param transform @en The transform matrix of the frustum. @zh 视锥体的变换矩阵。
*
* @deprecated since 3.8.0, please use [createPerspective] instead of it.
*/
void split(float near, float far, float aspect, float fov, const Mat4 &transform);
void updatePlanes();
void update(const Mat4 &m, const Mat4 &inv);
/**
* @en
* Set whether to use accurate intersection testing function on this frustum.
* @zh
* 设置是否在此截锥体上使用精确的相交测试函数。
*
* @deprecated since v3.8.0 no need to set accurate flag since it doesn't affect the calculation at all.
*/
inline void setAccurate(bool accurate) {
setType(accurate ? ShapeEnum::SHAPE_FRUSTUM_ACCURATE : ShapeEnum::SHAPE_FRUSTUM);
}
ccstd::array<Vec3, 8> vertices;
ccstd::array<Plane *, 6> planes;
private:
void init();
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,41 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "AABB.h"
#include "Capsule.h"
// #include "Curve.h"
#include "Distance.h"
#include "Enums.h"
#include "Frustum.h"
#include "Intersect.h"
#include "Line.h"
#include "Obb.h"
#include "Plane.h"
#include "Ray.h"
#include "Spec.h"
#include "Sphere.h"
#include "Spline.h"
#include "Triangle.h"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,498 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/Macros.h"
#include "core/assets/RenderingSubMesh.h"
#include "core/geometry/Distance.h"
#include "core/geometry/Enums.h"
#include "core/geometry/Frustum.h"
#include "core/geometry/Spec.h"
#include <cmath>
namespace cc {
class Vec3;
class Mat3;
namespace scene {
class Model;
}
namespace geometry {
class Ray;
class Plane;
class OBB;
class AABB;
class Line;
class Frustum;
class Sphere;
class Triangle;
class Capsule;
/**
* @en
* ray-plane intersect detect.
* @zh
* 射线与平面的相交性检测。
* @param {Ray} ray 射线
* @param {Plane} plane 平面
* @return {number} 0 或 非0
*/
float rayPlane(const Ray &ray, const Plane &plane);
// based on http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/
/**
* @en
* ray-triangle intersect detect.
* @zh
* 射线与三角形的相交性检测。
* @param {Ray} ray 射线
* @param {Triangle} triangle 三角形
* @param {boolean} doubleSided 三角形是否为双面
* @return {number} 0 或 非0
*/
float rayTriangle(const Ray &ray, const Triangle &triangle, bool doubleSided = false);
/**
* @en
* ray-sphere intersect detect.
* @zh
* 射线和球的相交性检测。
* @param {Ray} ray 射线
* @param {Sphere} sphere 球
* @return {number} 0 或 非0
*/
float raySphere(const Ray &ray, const Sphere &sphere);
float rayAABB2(const Ray &ray, const Vec3 &min, const Vec3 &max);
/**
* @en
* ray-aabb intersect detect.
* @zh
* 射线和轴对齐包围盒的相交性检测。
* @param {Ray} ray 射线
* @param {AABB} aabb 轴对齐包围盒
* @return {number} 0 或 非0
*/
float rayAABB(const Ray &ray, const AABB &aabb);
/**
* @en
* ray-obb intersect detect.
* @zh
* 射线和方向包围盒的相交性检测。
* @param {Ray} ray 射线
* @param {OBB} obb 方向包围盒
* @return {number} 0 或 非0
*/
float rayOBB(const Ray &ray, const OBB &obb);
/**
* @en
* ray-capsule intersect detect.
* @zh
* 射线和胶囊体的相交性检测。
* @param {Ray} ray 射线
* @param {Capsule} capsule 胶囊体
* @return {number} 0 或 非0
*/
float rayCapsule(const Ray &ray, const Capsule &capsule);
/**
* @en
* ray-subMesh intersect detect, in model space.
* @zh
* 在模型空间中,射线和子三角网格的相交性检测。
* @param {Ray} ray
* @param {RenderingSubMesh} subMesh
* @param {IRaySubMeshOptions} options
* @return {number} 0 or !0
*/
float raySubMesh(const Ray &ray, const RenderingSubMesh &submesh, IRaySubMeshOptions *options = nullptr);
/**
* @en
* ray-mesh intersect detect, in model space.
* @zh
* 在模型空间中,射线和三角网格资源的相交性检测。
* @param {Ray} ray
* @param {Mesh} mesh
* @param {IRayMeshOptions} options
* @return {number} 0 or !0
*/
float rayMesh(const Ray &ray, const Mesh &mesh, IRayMeshOptions *option);
/**
* @en
* ray-model intersect detect, in world space.
* @zh
* 在世界空间中,射线和渲染模型的相交性检测。
* @param ray
* @param model
* @param options
* @return 0 or !0
*/
float rayModel(const Ray &ray, const scene::Model &model, IRayModelOptions *option);
/**
* @en
* line-plane intersect detect.
* @zh
* 线段与平面的相交性检测。
* @param {line} line 线段
* @param {Plane} plane 平面
* @return {number} 0 或 非0
*/
float linePlane(const Line &line, const Plane &plane);
/**
* @en
* line-triangle intersect detect.
* @zh
* 线段与三角形的相交性检测。
* @param {line} line 线段
* @param {Triangle} triangle 三角形
* @param {Vec3} outPt 可选,相交点
* @return {number} 0 或 非0
*/
int lineTriangle(const Line &line, const Triangle &triangle, Vec3 *outPt = nullptr);
/**
* @en
* line-aabb intersect detect.
* @zh
* 线段与轴对齐包围盒的相交性检测
* @param line 线段
* @param aabb 轴对齐包围盒
* @return {number} 0 或 非0
*/
float lineAABB(const Line &line, const AABB &aabb);
/**
* @en
* line-obb intersect detect.
* @zh
* 线段与方向包围盒的相交性检测
* @param line 线段
* @param obb 方向包围盒
* @return {number} 0 或 非0
*/
float lineOBB(const Line &line, const OBB &obb);
/**
* @en
* line-sphere intersect detect.
* @zh
* 线段与球的相交性检测
* @param line 线段
* @param sphere 球
* @return {number} 0 或 非0
*/
float lineSphere(const Line &line, const Sphere &sphere);
/**
* @en
* aabb-aabb intersect detect.
* @zh
* 轴对齐包围盒和轴对齐包围盒的相交性检测。
* @param {AABB} aabb1 轴对齐包围盒1
* @param {AABB} aabb2 轴对齐包围盒2
* @return {number} 0 或 非0
*/
bool aabbWithAABB(const AABB &aabb1, const AABB &aabb2);
/**
* @en
* aabb-obb intersect detect.
* @zh
* 轴对齐包围盒和方向包围盒的相交性检测。
* @param {AABB} aabb 轴对齐包围盒
* @param {OBB} obb 方向包围盒
* @return {number} 0 或 非0
*/
int aabbWithOBB(const AABB &aabb, const OBB &obb);
/**
* @en
* aabb-plane intersect detect.
* @zh
* 轴对齐包围盒和平面的相交性检测。
* @param {AABB} aabb 轴对齐包围盒
* @param {Plane} plane 平面
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
*/
int aabbPlane(const AABB &aabb, const Plane &plane);
/**
* @en
* aabb-frustum intersect detect, faster but has false positive corner cases.
* @zh
* 轴对齐包围盒和锥台相交性检测,速度快,但有错误情况。
* @param {AABB} aabb 轴对齐包围盒
* @param {Frustum} frustum 锥台
* @return {number} 0 或 非0
*/
int aabbFrustum(const AABB &aabb, const Frustum &frustum);
/**
* @en
* aabb-frustum intersect detect, faster but false while frustum is completely inside the aabb.
* @zh
* 轴对齐包围盒和锥台的相交性检测。速度快但是当锥台完全在aabb中时就会判断出错。
* @param {AABB} aabb 轴对齐包围盒
* @param {Frustum} frustum 锥台
* @return {number} aabb completely inside the frustum = 1, otherwise = 0
*/
int aabbFrustumCompletelyInside(const AABB &aabb, const Frustum &frustum);
// https://cesium.com/blog/2017/02/02/tighter-frustum-culling-and-why-you-may-want-to-disregard-it/
/**
* @en
* aabb-frustum intersect, handles most of the false positives correctly.
* @zh
* 轴对齐包围盒和锥台相交性检测,正确处理大多数错误情况。
* @param {AABB} aabb 轴对齐包围盒
* @param {Frustum} frustum 锥台
* @return {number}
*/
int aabbFrustumAccurate(const AABB &aabb, const Frustum &frustum);
/**
* @en
* obb contains the point.
* @zh
* 方向包围盒和点的相交性检测。
* @param {OBB} obb 方向包围盒
* @param {Vec3} point 点
* @return {boolean} true or false
*/
bool obbPoint(const OBB &obb, const Vec3 &point);
/**
* @en
* obb-plane intersect detect.
* @zh
* 方向包围盒和平面的相交性检测。
* @param {OBB} obb 方向包围盒
* @param {Plane} plane 平面
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
*/
int obbPlane(const OBB &obb, const Plane &plane);
/**
* @en
* obb-frustum intersect, faster but has false positive corner cases.
* @zh
* 方向包围盒和锥台相交性检测,速度快,但有错误情况。
* @param {OBB} obb 方向包围盒
* @param {Frustum} frustum 锥台
* @return {number} 0 或 非0
*/
int obbFrustum(const OBB &obb, const Frustum &frustum);
// https://cesium.com/blog/2017/02/02/tighter-frustum-culling-and-why-you-may-want-to-disregard-it/
/**
* @en
* obb-frustum intersect, handles most of the false positives correctly.
* @zh
* 方向包围盒和锥台相交性检测,正确处理大多数错误情况。
* @param {OBB} obb 方向包围盒
* @param {Frustum} frustum 锥台
* @return {number} 0 或 非0
*/
int obbFrustumAccurate(const OBB &obb, const Frustum &frustum);
/**
* @en
* obb-obb intersect detect.
* @zh
* 方向包围盒和方向包围盒的相交性检测。
* @param {OBB} obb1 方向包围盒1
* @param {OBB} obb2 方向包围盒2
* @return {number} 0 或 非0
*/
int obbWithOBB(const OBB &obb1, const OBB &obb2);
// https://github.com/diku-dk/bvh-tvcg18/blob/1fd3348c17bc8cf3da0b4ae60fdb8f2aa90a6ff0/FOUNDATION/GEOMETRY/GEOMETRY/include/overlap/geometry_overlap_obb_capsule.h
/**
* @en
* obb-capsule intersect detect.
* @zh
* 方向包围盒和胶囊体的相交性检测。
* @param obb 方向包围盒
* @param capsule 胶囊体
*/
int obbCapsule(const OBB &obb, const Capsule &capsule);
/**
* @en
* sphere-plane intersect, not necessarily faster than obb-plane,due to the length calculation of the
* plane normal to factor out the unnomalized plane distance.
* @zh
* 球与平面的相交性检测。
* @param {Sphere} sphere 球
* @param {Plane} plane 平面
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
*/
int spherePlane(const Sphere &sphere, const Plane &plane);
/**
* @en
* sphere-frustum intersect, faster but has false positive corner cases.
* @zh
* 球和锥台的相交性检测,速度快,但有错误情况。
* @param {Sphere} sphere 球
* @param {Frustum} frustum 锥台
* @return {number} 0 或 非0
*/
int sphereFrustum(const Sphere &sphere, const Frustum &frustum);
// https://stackoverflow.com/questions/20912692/view-frustum-culling-corner-cases
/**
* @en
* sphere-frustum intersect, handles the false positives correctly.
* @zh
* 球和锥台的相交性检测,正确处理大多数错误情况。
* @param {Sphere} sphere 球
* @param {Frustum} frustum 锥台
* @return {number} 0 或 非0
*/
int sphereFrustumAccurate(const Sphere &sphere, const Frustum &frustum);
/**
* @en
* sphere-sphere intersect detect.
* @zh
* 球和球的相交性检测。
* @param {Sphere} sphere0 球0
* @param {Sphere} sphere1 球1
* @return {boolean} true or false
*/
bool sphereWithSphere(const Sphere &sphere0, const Sphere &sphere1);
/**
* @en
* sphere-aabb intersect detect.
* @zh
* 球和轴对齐包围盒的相交性检测。
* @param {Sphere} sphere 球
* @param {AABB} aabb 轴对齐包围盒
* @return {boolean} true or false
*/
bool sphereAABB(const Sphere &sphere, const AABB &aabb);
/**
* @en
* sphere-obb intersect detect.
* @zh
* 球和方向包围盒的相交性检测。
* @param {Sphere} sphere 球
* @param {OBB} obb 方向包围盒
* @return {boolean} true or false
*/
bool sphereOBB(const Sphere &sphere, const OBB &obb);
/**
* @en
* sphere-capsule intersect detect.
* @zh
* 球和胶囊体的相交性检测。
*/
bool sphereCapsule(const Sphere &sphere, const Capsule &capsule);
// http://www.geomalgorithms.com/a07-_distance.html
/**
* @en
* capsule-capsule intersect detect.
* @zh
* 胶囊体和胶囊体的相交性检测。
*/
bool capsuleWithCapsule(const Capsule &capsuleA, const Capsule &capsuleB);
template <typename T1, typename T2>
auto intersects(const T1 & /*a*/, const T2 & /*b*/) {
static_assert(std::is_base_of<T1, ShapeBase>::value, "type is not base of ShapeBase");
static_assert(std::is_base_of<T2, ShapeBase>::value, "type is not base of ShapeBase");
CC_ABORT(); // mismatch
}
#define DECLARE_EXCHANGABLE_INTERSECT(TYPE1, TYPE2, FN) \
template <> \
inline auto intersects(const TYPE1 &arg1, const TYPE2 &arg2) { \
return FN(arg1, arg2); \
} \
template <> \
inline auto intersects(const TYPE2 &arg2, const TYPE1 &arg1) { \
return FN(arg1, arg2); \
}
#define DECLARE_SELF_INTERSECT(TYPE, FN) \
template <> \
inline auto intersects(const TYPE &arg1, const TYPE &arg2) { \
return FN(arg1, arg2); \
}
int dynObbFrustum(const OBB &obb, const Frustum &frustum);
int dynSphereFrustum(const Sphere &sphere, const Frustum &frustum);
int dynAabbFrustum(const AABB &aabb, const Frustum &frustum);
DECLARE_EXCHANGABLE_INTERSECT(Ray, Sphere, raySphere)
DECLARE_EXCHANGABLE_INTERSECT(Ray, AABB, rayAABB)
DECLARE_EXCHANGABLE_INTERSECT(Ray, OBB, rayOBB)
DECLARE_EXCHANGABLE_INTERSECT(Ray, Plane, rayPlane)
DECLARE_EXCHANGABLE_INTERSECT(Ray, Triangle, rayTriangle)
DECLARE_EXCHANGABLE_INTERSECT(Ray, Capsule, rayCapsule)
DECLARE_EXCHANGABLE_INTERSECT(Line, Sphere, lineSphere)
DECLARE_EXCHANGABLE_INTERSECT(Line, AABB, lineAABB)
DECLARE_EXCHANGABLE_INTERSECT(Line, OBB, lineOBB)
DECLARE_EXCHANGABLE_INTERSECT(Line, Plane, linePlane)
DECLARE_EXCHANGABLE_INTERSECT(Line, Triangle, lineTriangle)
DECLARE_SELF_INTERSECT(Sphere, sphereWithSphere)
DECLARE_EXCHANGABLE_INTERSECT(Sphere, AABB, sphereAABB)
DECLARE_EXCHANGABLE_INTERSECT(Sphere, OBB, sphereOBB)
DECLARE_EXCHANGABLE_INTERSECT(Sphere, Plane, spherePlane)
DECLARE_EXCHANGABLE_INTERSECT(Sphere, Frustum, dynSphereFrustum)
DECLARE_EXCHANGABLE_INTERSECT(Sphere, Capsule, sphereCapsule)
DECLARE_SELF_INTERSECT(AABB, aabbWithAABB)
DECLARE_EXCHANGABLE_INTERSECT(AABB, OBB, aabbWithOBB)
DECLARE_EXCHANGABLE_INTERSECT(AABB, Plane, aabbPlane)
DECLARE_EXCHANGABLE_INTERSECT(AABB, Frustum, dynAabbFrustum)
DECLARE_SELF_INTERSECT(OBB, obbWithOBB)
DECLARE_EXCHANGABLE_INTERSECT(OBB, Plane, obbPlane)
DECLARE_EXCHANGABLE_INTERSECT(OBB, Frustum, dynObbFrustum)
DECLARE_EXCHANGABLE_INTERSECT(OBB, Capsule, obbCapsule)
DECLARE_SELF_INTERSECT(Capsule, capsuleWithCapsule)
#undef DECLARE_SELF_INTERSECT
#undef DECLARE_EXCHANGABLE_INTERSECT
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,81 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "core/geometry/Line.h"
#include "base/memory/Memory.h"
namespace cc {
namespace geometry {
Line *Line::create(float sx,
float sy,
float sz,
float ex,
float ey,
float ez) {
return ccnew Line(sx, sy, sz, ex, ey, ez);
}
Line *Line::clone(const Line &a) {
return ccnew Line(
a.s.x, a.s.y, a.s.z,
a.e.x, a.e.y, a.e.z);
}
Line *Line::copy(Line *out, const Line &a) {
out->s = a.s;
out->e = a.e;
return out;
}
Line *Line::fromPoints(Line *out, const Vec3 &start, const Vec3 &end) {
out->s = start;
out->e = end;
return out;
}
Line *Line::set(Line *out,
float sx,
float sy,
float sz,
float ex,
float ey,
float ez) {
out->s.x = sx;
out->s.y = sy;
out->s.z = sz;
out->e.x = ex;
out->e.y = ey;
out->e.z = ez;
return out;
}
Line::Line(float sx, float sy, float sz, float ex, float ey, float ez) : ShapeBase(ShapeEnum::SHAPE_LINE) {
s = {sx, sy, sz};
e = {ex, ey, ez};
}
} // namespace geometry
} // namespace cc

171
cocos/core/geometry/Line.h Normal file
View File

@@ -0,0 +1,171 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "core/geometry/Enums.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
/**
* @en
* Basic Geometry: Line.
* @zh
* 基础几何 line。
*/
class Line final : public ShapeBase {
public:
/**
* @en
* create a new line
* @zh
* 创建一个新的 line。
* @param sx 起点的 x 部分。
* @param sy 起点的 y 部分。
* @param sz 起点的 z 部分。
* @param ex 终点的 x 部分。
* @param ey 终点的 y 部分。
* @param ez 终点的 z 部分。
* @return
*/
static Line *create(float sx,
float sy,
float sz,
float ex,
float ey,
float ez);
/**
* @en
* Creates a new Line initialized with values from an existing Line
* @zh
* 克隆一个新的 line。
* @param a 克隆的来源。
* @return 克隆出的对象。
*/
static Line *clone(const Line &a);
/**
* @en
* Copy the values from one Line to another
* @zh
* 复制一个线的值到另一个。
* @param out 接受操作的对象。
* @param a 复制的来源。
* @return 接受操作的对象。
*/
static Line *copy(Line *out, const Line &a);
/**
* @en
* create a line from two points
* @zh
* 用两个点创建一个线。
* @param out 接受操作的对象。
* @param start 起点。
* @param end 终点。
* @return out 接受操作的对象。
*/
static Line *fromPoints(Line *out, const Vec3 &start, const Vec3 &end);
/**
* @en
* Set the components of a Vec3 to the given values
* @zh
* 将给定线的属性设置为给定值。
* @param out 接受操作的对象。
* @param sx 起点的 x 部分。
* @param sy 起点的 y 部分。
* @param sz 起点的 z 部分。
* @param ex 终点的 x 部分。
* @param ey 终点的 y 部分。
* @param ez 终点的 z 部分。
* @return out 接受操作的对象。
*/
static Line *set(Line *out,
float sx,
float sy,
float sz,
float ex,
float ey,
float ez);
/**
* @zh
* 计算线的长度。
* @param a 要计算的线。
* @return 长度。
*/
static inline float len(const Line &a) {
return a.s.distance(a.e);
}
/**
* @zh
* 起点。
*/
Vec3 s;
/**
* @zh
* 终点。
*/
Vec3 e;
/**
* 构造一条线。
* @param sx 起点的 x 部分。
* @param sy 起点的 y 部分。
* @param sz 起点的 z 部分。
* @param ex 终点的 x 部分。
* @param ey 终点的 y 部分。
* @param ez 终点的 z 部分。
*/
explicit Line(float sx = 0, float sy = 0, float sz = 0, float ex = 0, float ey = 0, float ez = -1);
Line(const Line &) = default;
Line &operator=(const Line &) = default;
Line &operator=(Line &&) = default;
Line(Line &&) = default;
~Line() override = default;
/**
* @zh
* 计算线的长度。
* @param a 要计算的线。
* @return 长度。
*/
inline float length() const {
return s.distance(e);
}
};
} // namespace geometry
} // namespace cc

128
cocos/core/geometry/Obb.cpp Normal file
View File

@@ -0,0 +1,128 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "cocos/core/geometry/Obb.h"
#include "base/memory/Memory.h"
namespace {
void transformExtentM3(cc::Vec3 *out, const cc::Vec3 &extent, const cc::Mat3 &m3) {
cc::Mat3 m3Tmp;
m3Tmp.m[0] = std::abs(m3.m[0]);
m3Tmp.m[1] = std::abs(m3.m[1]);
m3Tmp.m[2] = std::abs(m3.m[2]);
m3Tmp.m[3] = std::abs(m3.m[3]);
m3Tmp.m[4] = std::abs(m3.m[4]);
m3Tmp.m[5] = std::abs(m3.m[5]);
m3Tmp.m[6] = std::abs(m3.m[6]);
m3Tmp.m[7] = std::abs(m3.m[7]);
m3Tmp.m[8] = std::abs(m3.m[8]);
out->transformMat3(extent, m3Tmp);
};
} // namespace
namespace cc {
namespace geometry {
OBB *OBB::create(
float cx, float cy, float cz,
float hw, float hh, float hl,
float ox1, float ox2, float ox3,
float oy1, float oy2, float oy3,
float oz1, float oz2, float oz3) {
return ccnew OBB(cx, cy, cz, hw, hh, hl,
ox1, ox2, ox3,
oy1, oy2, oy3,
oz1, oz2, oz3);
}
OBB *OBB::clone(const OBB &a) {
return ccnew OBB(a.center.x, a.center.y, a.center.z,
a.halfExtents.x, a.halfExtents.y, a.halfExtents.z,
a.orientation.m[0], a.orientation.m[1], a.orientation.m[2],
a.orientation.m[3], a.orientation.m[4], a.orientation.m[5],
a.orientation.m[6], a.orientation.m[7], a.orientation.m[8]);
}
OBB *OBB::copy(OBB *out, const OBB &a) {
out->center = a.center;
out->halfExtents = a.halfExtents;
out->orientation = a.orientation;
return out;
}
OBB *OBB::fromPoints(OBB *out, const Vec3 &minPos, const Vec3 &maxPos) {
out->center = 0.5F * (minPos + maxPos);
out->halfExtents = 0.5F * (maxPos - minPos);
Mat3::identity(out->orientation);
return out;
}
OBB *OBB::set(OBB *out,
float cx, float cy, float cz,
float hw, float hh, float hl,
float ox1, float ox2, float ox3,
float oy1, float oy2, float oy3,
float oz1, float oz2, float oz3) {
out->center = {cx, cy, cz};
out->halfExtents = {hw, hh, hl};
out->orientation = {ox1, ox2, ox3, oy1, oy2, oy3, oz1, oz2, oz3};
return out;
}
OBB::OBB(float cx, float cy, float cz,
float hw, float hh, float hl,
float ox1, float ox2, float ox3,
float oy1, float oy2, float oy3,
float oz1, float oz2, float oz3) : ShapeBase(ShapeEnum::SHAPE_OBB) {
center = {cx, cy, cz};
halfExtents = {hw, hh, hl};
orientation = {ox1, ox2, ox3, oy1, oy2, oy3, oz1, oz2, oz3};
}
void OBB::getBoundary(Vec3 *minPos, Vec3 *maxPos) const {
Vec3 v3Tmp;
transformExtentM3(&v3Tmp, halfExtents, orientation);
*minPos = center - v3Tmp;
*maxPos = center + v3Tmp;
}
void OBB::transform(const Mat4 &m, const Vec3 & /*pos*/, const Quaternion &rot, const Vec3 &scale, OBB *out) const {
Vec3::transformMat4(center, m, &out->center);
// parent shape doesn't contain rotations for now
Mat3::fromQuat(rot, &out->orientation);
Vec3::multiply(halfExtents, scale, &out->halfExtents);
}
void OBB::translateAndRotate(const Mat4 &m, const Quaternion &rot, OBB *out) const {
Vec3::transformMat4(center, m, &out->center);
// parent shape doesn't contain rotations for now
Mat3::fromQuat(rot, &out->orientation);
}
void OBB::setScale(const Vec3 &scale, OBB *out) const {
Vec3::multiply(halfExtents, scale, &out->halfExtents);
}
} // namespace geometry
} // namespace cc

192
cocos/core/geometry/Obb.h Normal file
View File

@@ -0,0 +1,192 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "cocos/core/geometry/Enums.h"
#include "cocos/math/Mat3.h"
#include "cocos/math/Quaternion.h"
#include "cocos/math/Vec3.h"
namespace cc {
namespace geometry {
class OBB final : public ShapeBase {
public:
/**
* @en
* create a new obb
* @zh
* 创建一个新的 obb 实例。
* @param cx 形状的相对于原点的 X 坐标。
* @param cy 形状的相对于原点的 Y 坐标。
* @param cz 形状的相对于原点的 Z 坐标。
* @param hw - obb 宽度的一半。
* @param hh - obb 高度的一半。
* @param hl - obb 长度的一半。
* @param ox1 方向矩阵参数。
* @param ox2 方向矩阵参数。
* @param ox3 方向矩阵参数。
* @param oy1 方向矩阵参数。
* @param oy2 方向矩阵参数。
* @param oy3 方向矩阵参数。
* @param oz1 方向矩阵参数。
* @param oz2 方向矩阵参数。
* @param oz3 方向矩阵参数。
* @return 返回一个 obb。
*/
static OBB *create(
float cx, float cy, float cz,
float hw, float hh, float hl,
float ox1, float ox2, float ox3,
float oy1, float oy2, float oy3,
float oz1, float oz2, float oz3);
/**
* @en
* clone a new obb
* @zh
* 克隆一个 obb。
* @param a 克隆的目标。
* @returns 克隆出的新对象。
*/
static OBB *clone(const OBB &a);
/**
* @en
* copy the values from one obb to another
* @zh
* 将从一个 obb 的值复制到另一个 obb。
* @param {OBB} out 接受操作的 obb。
* @param {OBB} a 被复制的 obb。
* @return {OBB} out 接受操作的 obb。
*/
static OBB *copy(OBB *out, const OBB &a);
/**
* @en
* create a new obb from two corner points
* @zh
* 用两个点创建一个新的 obb。
* @param out - 接受操作的 obb。
* @param minPos - obb 的最小点。
* @param maxPos - obb 的最大点。
* @returns {OBB} out 接受操作的 obb。
*/
static OBB *fromPoints(OBB *out, const Vec3 &minPos, const Vec3 &maxPos);
/**
* @en
* Set the components of a obb to the given values
* @zh
* 将给定 obb 的属性设置为给定的值。
* @param cx - obb 的原点的 X 坐标。
* @param cy - obb 的原点的 Y 坐标。
* @param cz - obb 的原点的 Z 坐标。
* @param hw - obb 宽度的一半。
* @param hh - obb 高度的一半。
* @param hl - obb 长度的一半。
* @param ox1 方向矩阵参数。
* @param ox2 方向矩阵参数。
* @param ox3 方向矩阵参数。
* @param oy1 方向矩阵参数。
* @param oy2 方向矩阵参数。
* @param oy3 方向矩阵参数。
* @param oz1 方向矩阵参数。
* @param oz2 方向矩阵参数。
* @param oz3 方向矩阵参数。
* @return {OBB} out
*/
static OBB *set(OBB *out,
float cx, float cy, float cz,
float hw, float hh, float hl,
float ox1, float ox2, float ox3,
float oy1, float oy2, float oy3,
float oz1, float oz2, float oz3);
/**
* @zh
* 本地坐标的中心点。
*/
Vec3 center;
/**
* @zh
* 长宽高的一半。
*/
Vec3 halfExtents;
/**
* @zh
* 方向矩阵。
*/
Mat3 orientation;
explicit OBB(float cx = 0, float cy = 0, float cz = 0,
float hw = 1, float hh = 1, float hl = 1,
float ox1 = 1, float ox2 = 0, float ox3 = 0,
float oy1 = 0, float oy2 = 1, float oy3 = 0,
float oz1 = 0, float oz2 = 0, float oz3 = 1);
/**
* @en
* Get the bounding points of this shape
* @zh
* 获取 obb 的最小点和最大点。
* @param {Vec3} minPos 最小点。
* @param {Vec3} maxPos 最大点。
*/
void getBoundary(Vec3 *minPos, Vec3 *maxPos) const;
/**
* Transform this shape
* @zh
* 将 out 根据这个 obb 的数据进行变换。
* @param m 变换的矩阵。
* @param pos 变换的位置部分。
* @param rot 变换的旋转部分。
* @param scale 变换的缩放部分。
* @param out 变换的目标。
*/
void transform(const Mat4 &m, const Vec3 &pos, const Quaternion &rot, const Vec3 &scale, OBB *out) const;
/**
* @zh
* 将 out 根据这个 obb 的数据进行变换。
* @param m 变换的矩阵。
* @param rot 变换的旋转部分。
* @param out 变换的目标。
*/
void translateAndRotate(const Mat4 &m, const Quaternion &rot, OBB *out) const;
/**
* @zh
* 将 out 根据这个 obb 的数据进行缩放。
* @param scale 缩放值。
* @param out 缩放的目标。
*/
void setScale(const Vec3 &scale, OBB *out) const;
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,118 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "cocos/core/geometry/Plane.h"
#include "base/memory/Memory.h"
namespace cc {
namespace geometry {
Plane *Plane::create(float nx, float ny, float nz, float d) {
return ccnew Plane{nx, ny, nz, d};
}
Plane *Plane::clone(const Plane &p) {
return ccnew Plane{p.n.x, p.n.y, p.n.z, p.d};
}
Plane *Plane::copy(Plane *out, const Plane &p) {
out->n = p.n;
out->d = p.d;
return out;
}
Plane *Plane::fromPoints(Plane *out,
const Vec3 &a,
const Vec3 &b,
const Vec3 &c) {
Vec3::cross(b - a, c - a, &out->n);
out->n.normalize();
out->d = Vec3::dot(out->n, a);
return out;
}
Plane *Plane::fromNormalAndPoint(Plane *out, const Vec3 &normal, const Vec3 &point) {
out->n = normal;
out->d = Vec3::dot(normal, point);
return out;
}
Plane *Plane::normalize(Plane *out, const Plane &a) {
const auto len = a.n.length();
out->n = a.n.getNormalized();
if (len > 0) {
out->d = a.d / len;
}
return out;
}
Plane *Plane::set(Plane *out, float nx, float ny, float nz, float d) {
out->n = {nx, ny, nz};
out->d = d;
return out;
}
Plane::Plane(float nx, float ny, float nz, float d) : Plane() {
n = {nx, ny, nz};
this->d = d;
}
void Plane::transform(const Mat4 &mat) {
Mat4 tempMat = mat.getInversed();
tempMat.transpose();
Vec4 tempVec4 = {n.x, n.y, n.z, -d};
tempMat.transformVector(&tempVec4);
n.set(tempVec4.x, tempVec4.y, tempVec4.z);
d = -tempVec4.w;
}
// Define from 3 vertices.
void Plane::define(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2) {
const Vec3 dist1 = v1 - v0;
const Vec3 dist2 = v2 - v0;
Vec3 dist;
Vec3::cross(dist1, dist2, &dist);
define(dist, v0);
}
// Define from a normal vector and a point on the plane.
void Plane::define(const Vec3 &normal, const Vec3 &point) {
n = normal.getNormalized();
d = n.dot(point);
}
// Return signed distance to a point.
float Plane::distance(const Vec3 &point) const {
return n.dot(point) - d;
}
Plane Plane::clone() const {
Plane plane;
plane.n.set(n);
plane.d = d;
return plane;
}
} // namespace geometry
} // namespace cc

191
cocos/core/geometry/Plane.h Normal file
View File

@@ -0,0 +1,191 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "cocos/core/geometry/Enums.h"
#include "cocos/math/Mat4.h"
#include "cocos/math/Vec3.h"
#include "cocos/math/Vec4.h"
namespace cc {
namespace geometry {
/**
* @en
* Basic Geometry: Plane.
* @zh
* 基础几何 Plane。
*/
class Plane final : public ShapeBase {
/**
* @en
* create a new plane
* @zh
* 创建一个新的 plane。
* @param nx 法向分量的 x 部分。
* @param ny 法向分量的 y 部分。
* @param nz 法向分量的 z 部分。
* @param d 与原点的距离。
* @return
*/
public:
static Plane *create(float nx, float ny, float nz, float d);
/**
* @en
* clone a new plane
* @zh
* 克隆一个新的 plane。
* @param p 克隆的来源。
* @return 克隆出的对象。
*/
static Plane *clone(const Plane &p);
/**
* @en
* copy the values from one plane to another
* @zh
* 复制一个平面的值到另一个。
* @param out 接受操作的对象。
* @param p 复制的来源。
* @return 接受操作的对象。
*/
static Plane *copy(Plane *out, const Plane &p);
/**
* @en
* create a plane from three points
* @zh
* 用三个点创建一个平面。
* @param out 接受操作的对象。
* @param a 点 a。
* @param b 点 b。
* @param c 点 c。
* @return out 接受操作的对象。
*/
static Plane *fromPoints(Plane *out,
const Vec3 &a,
const Vec3 &b,
const Vec3 &c);
/**
* @en
* Set the components of a plane to the given values
* @zh
* 将给定平面的属性设置为给定值。
* @param out 接受操作的对象。
* @param nx 法向分量的 x 部分。
* @param ny 法向分量的 y 部分。
* @param nz 法向分量的 z 部分。
* @param d 与原点的距离。
* @return out 接受操作的对象。
*/
static Plane *set(Plane *out, float nx, float ny, float nz, float d);
/**
* @en
* create plane from normal and point
* @zh
* 用一条法线和一个点创建平面。
* @param out 接受操作的对象。
* @param normal 平面的法线。
* @param point 平面上的一点。
* @return out 接受操作的对象。
*/
static Plane *fromNormalAndPoint(Plane *out, const Vec3 &normal, const Vec3 &point);
/**
* @en
* normalize a plane
* @zh
* 归一化一个平面。
* @param out 接受操作的对象。
* @param a 操作的源数据。
* @return out 接受操作的对象。
*/
static Plane *normalize(Plane *out, const Plane &a);
// compatibility with vector interfaces
inline void setX(float val) { n.x = val; }
inline float getX() const { return n.x; }
inline void setY(float val) { n.y = val; }
inline float getY() const { return n.y; }
inline void setZ(float val) { n.z = val; }
inline float getZ() const { return n.z; }
inline void setW(float val) { d = val; }
inline float getW() const { return d; }
/**
* @en
* Construct a plane.
* @zh
* 构造一个平面。
* @param nx 法向分量的 x 部分。
* @param ny 法向分量的 y 部分。
* @param nz 法向分量的 z 部分。
* @param d 与原点的距离。
*/
explicit Plane(float nx, float ny, float nz, float d);
Plane() : ShapeBase(ShapeEnum::SHAPE_PLANE) {}
// Plane(const Plane& other) = default;
// Plane(Plane&& other) = default;
// Plane& operator=(const Plane& other) = default;
// Plane& operator=(Plane&& other) = default;
// ~Plane() = default;
/**
* @en
* transform this plane.
* @zh
* 变换一个平面。
* @param mat
*/
void transform(const Mat4 &mat);
/**
* @en
* The normal of the plane.
* @zh
* 法线向量。
*/
Vec3 n{0.0F, 1.0F, 0.0F};
/**
* @en
* The distance from the origin to the plane.
* @zh
* 原点到平面的距离。
*/
float d{0.0F};
void define(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2);
void define(const Vec3 &normal, const Vec3 &point);
float distance(const Vec3 &point) const;
Plane clone() const;
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,76 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "core/geometry/Ray.h"
#include "base/memory/Memory.h"
namespace cc {
namespace geometry {
Ray *Ray::create(float ox, float oy, float oz, float dx, float dy, float dz) {
return ccnew Ray{ox, oy, oz, dx, dy, dz};
}
Ray *Ray::clone(const Ray &a) {
return ccnew Ray{
a.o.x, a.o.y, a.o.z,
a.d.x, a.d.y, a.d.z};
}
Ray *Ray::copy(Ray *out, const Ray &a) {
out->o = a.o;
out->d = a.d;
return out;
}
Ray *Ray::fromPoints(Ray *out, const Vec3 &origin, const Vec3 &target) {
out->o = origin;
out->d = (target - origin).getNormalized();
return out;
}
Ray *Ray::set(Ray *out, float ox, float oy,
float oz,
float dx,
float dy,
float dz) {
out->o.x = ox;
out->o.y = oy;
out->o.z = oz;
out->d.x = dx;
out->d.y = dy;
out->d.z = dz;
return out;
}
Ray::Ray(float ox, float oy, float oz,
float dx, float dy, float dz) : ShapeBase(ShapeEnum::SHAPE_RAY) {
o = {ox, oy, oz};
d = {dx, dy, dz};
}
void Ray::computeHit(Vec3 *out, float distance) const {
*out = o + d.getNormalized() * distance;
}
} // namespace geometry
} // namespace cc

160
cocos/core/geometry/Ray.h Normal file
View File

@@ -0,0 +1,160 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "core/geometry/Enums.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
/**
* @en
* Basic Geometry: ray.
* @zh
* 基础几何 射线。
*/
class Ray final : public ShapeBase {
public:
/**
* @en
* create a new ray
* @zh
* 创建一条射线。
* @param {number} ox 起点的 x 部分。
* @param {number} oy 起点的 y 部分。
* @param {number} oz 起点的 z 部分。
* @param {number} dx 方向的 x 部分。
* @param {number} dy 方向的 y 部分。
* @param {number} dz 方向的 z 部分。
* @return {Ray} 射线。
*/
static Ray *create(float ox = 0, float oy = 0, float oz = 0, float dx = 0, float dy = 0, float dz = 1);
/**
* @en
* Creates a new ray initialized with values from an existing ray
* @zh
* 从一条射线克隆出一条新的射线。
* @param {Ray} a 克隆的目标。
* @return {Ray} 克隆出的新对象。
*/
static Ray *clone(const Ray &a);
/**
* @en
* Copy the values from one ray to another
* @zh
* 将从一个 ray 的值复制到另一个 ray。
* @param {Ray} out 接受操作的 ray。
* @param {Ray} a 被复制的 ray。
* @return {Ray} out 接受操作的 ray。
*/
static Ray *copy(Ray *out, const Ray &a);
/**
* @en
* create a ray from two points
* @zh
* 用两个点创建一条射线。
* @param {Ray} out 接受操作的射线。
* @param {Vec3} origin 射线的起点。
* @param {Vec3} target 射线上的一点。
* @return {Ray} out 接受操作的射线。
*/
static Ray *fromPoints(Ray *out, const Vec3 &origin, const Vec3 &target);
/**
* @en
* Set the components of a ray to the given values
* @zh
* 将给定射线的属性设置为给定的值。
* @param {Ray} out 接受操作的射线。
* @param {number} ox 起点的 x 部分。
* @param {number} oy 起点的 y 部分。
* @param {number} oz 起点的 z 部分。
* @param {number} dx 方向的 x 部分。
* @param {number} dy 方向的 y 部分。
* @param {number} dz 方向的 z 部分。
* @return {Ray} out 接受操作的射线。
*/
static Ray *set(Ray *out, float ox, float oy,
float oz,
float dx,
float dy,
float dz);
/**
* @en
* The origin of the ray.
* @zh
* 起点。
*/
Vec3 o;
/**
* @en
* The direction of the ray.
* @zh
* 方向。
*/
Vec3 d;
/**
* @en
* Construct a ray;
* @zh
* 构造一条射线。
* @param {number} ox 起点的 x 部分。
* @param {number} oy 起点的 y 部分。
* @param {number} oz 起点的 z 部分。
* @param {number} dx 方向的 x 部分。
* @param {number} dy 方向的 y 部分。
* @param {number} dz 方向的 z 部分。
*/
explicit Ray(float ox = 0, float oy = 0, float oz = 0,
float dx = 0, float dy = 0, float dz = -1);
Ray(const Ray &) = default;
Ray &operator=(const Ray &) = default;
Ray &operator=(Ray &&) = default;
Ray(Ray &&) = default;
~Ray() override = default;
/**
* @en
* Compute a point with the distance between the origin.
* @zh
* 根据给定距离计算出射线上的一点。
* @param out 射线上的另一点。
* @param distance 给定距离。
*/
void computeHit(Vec3 *out, float distance) const;
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,23 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

174
cocos/core/geometry/Spec.h Normal file
View File

@@ -0,0 +1,174 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cfloat>
#include <cstdint>
#include "base/std/container/vector.h"
#include "base/std/optional.h"
namespace cc {
namespace geometry {
/**
* @en
* The raycast mode.
* @zh
* 射线检测模式。
*/
enum class ERaycastMode {
/**
* @en
* Detect and record all data.
* @zh
* 检测并记录所有的数据。
*/
ALL,
/**
* @en
* Detect all, but record only the most recent data.
* @zh
* 检测所有,但只记录最近的数据。
*/
CLOSEST,
/**
* @en
* Once the test is successful, the test is stopped and the data is recorded only once.
* @zh
* 一旦检测成功就停止检测,只会记录一次数据。
*/
ANY,
};
/**
* @en
* The storage structure of the raycast results.
* @zh
* 射线检测结果的存储结构。
*/
struct IRaySubMeshResult {
/**
* @en
* The distance between the hit point and the ray.
* @zh
* 击中点和射线的距离。
*/
float distance{0.0F};
/**
* @en
* The index of the triangle vertex 0。
* @zh
* 三角形顶点0的索引。
*/
uint32_t vertexIndex0{0};
/**
* @en
* The index of the triangle vertex 1。
* @zh
* 三角形顶点1的索引
*/
uint32_t vertexIndex1{0};
/**
* @en
* The index of the triangle vertex 2。
* @zh
* 三角形顶点2的索引
*/
uint32_t vertexIndex2{0};
};
/**
* @en
* The optional param structure of the `raySubMesh`.
* @zh
* `raySubMesh`的可选参数结构。
*/
struct IRaySubMeshOptions {
/**
* @en
* The raycast mode`ANY` by default.
* @zh
* 射线检测模式:[0, 1, 2]=>[`ALL`, `CLOSEST`, `ANY`]
*/
ERaycastMode mode;
/**
* @en
* The maximum distance of the raycast, `Infinity` by default.
* @zh
* 射线检测的最大距离,默认为`Infinity`。
*/
float distance = FLT_MAX;
/**
* @en
* An array used to store the results of a ray detection.
* @zh
* 用于存储射线检测结果的数组。
*/
ccstd::optional<ccstd::vector<IRaySubMeshResult>> result{};
/**
* @en
* Whether to detect the double-sided or not`false` by default.
* @zh
* 是否检测双面,默认为`false`。
*/
bool doubleSided{false};
};
/**
* @en
* The optional param structure of the `rayMesh`.
* @zh
* `rayMesh`的可选参数结构。
*/
struct IRayMeshOptions : public IRaySubMeshOptions {
/**
* @en
* The index of the sub mesh.
* @zh
* 子网格的索引。
*/
ccstd::optional<ccstd::vector<uint32_t>> subIndices{};
};
/**
* @en
* The optional param structure of the `rayModel`.
* @zh
* `rayModel`的可选参数结构。
*/
using IRayModelOptions = IRayMeshOptions;
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,202 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "core/geometry/Sphere.h"
#include <algorithm>
#include "core/geometry/AABB.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
Sphere *Sphere::create(float cx, float cy, float cz, float radius) {
return ccnew Sphere(cx, cy, cz, radius);
}
Sphere *Sphere::clone(const Sphere &p) {
return ccnew Sphere(p._center.x, p._center.y, p._center.z, p._radius);
}
Sphere *Sphere::copy(Sphere *out, const Sphere &p) {
out->_center = p._center;
out->_radius = p._radius;
return out;
}
Sphere *Sphere::fromPoints(Sphere *out, const Vec3 &minPos, const Vec3 &maxPos) {
out->_center = 0.5F * (minPos + maxPos);
out->_radius = 0.5F * (maxPos - minPos).length();
return out;
}
Sphere *Sphere::set(Sphere *out, float cx, float cy, float cz, float r) {
out->_center = {cx, cy, cz};
out->_radius = r;
return out;
}
Sphere *Sphere::mergePoint(Sphere *out, const Sphere &s, const Vec3 &point) {
// if sphere.radius Less than 0,
// Set this point as anchor,
// And set radius to 0.
if (s._radius < 0.0) {
out->_center = point;
out->_radius = 0.0F;
return out;
}
auto offset = point - s._center;
auto dist = offset.length();
if (dist > s._radius) {
auto half = (dist - s._radius) * 0.5F;
out->_radius += half;
offset.scale(half / dist);
out->_center = out->_center + offset;
}
return out;
}
void Sphere::merge(const ccstd::vector<cc::Vec3> &points) {
if (points.empty()) return;
_radius = -1.0F;
for (const auto &p : points) {
merge(p);
}
}
Sphere *Sphere::mergeAABB(Sphere *out, const Sphere &s, const AABB &a) {
Vec3 aabbMin;
Vec3 aabbMax;
a.getBoundary(&aabbMin, &aabbMax);
Sphere::mergePoint(out, s, aabbMin);
Sphere::mergePoint(out, s, aabbMax);
return out;
}
Sphere::Sphere(float cx, float cy, float cz, float radius) : ShapeBase(ShapeEnum::SHAPE_SPHERE) {
_center = {cx, cy, cz};
_radius = radius;
}
void Sphere::getBoundary(Vec3 *minPos, Vec3 *maxPos) const {
Vec3 half = {_radius, _radius, _radius};
*minPos = _center - half;
*maxPos = _center + half;
}
void Sphere::transform(const Mat4 &m,
const Vec3 & /*pos*/,
const Quaternion & /*rot*/,
const Vec3 &scale,
Sphere *out) const {
Vec3::transformMat4(_center, m, &out->_center);
out->_radius = _radius * mathutils::maxComponent(scale);
}
int Sphere::intersect(const Plane &plane) const {
const float dot = plane.n.dot(_center);
const float r = _radius * plane.n.length();
if (dot + r < plane.d) {
return -1; // Sphere is on the back of the plane
}
if (dot - r > plane.d) {
return 0; // Sphere is on the front of the plane
}
return 1; // intersect
}
bool Sphere::intersect(const Frustum &frustum) const {
const auto &planes = frustum.planes;
const auto *self = this;
return std::all_of(planes.begin(),
planes.end(),
// frustum plane normal points to the inside
[self](const Plane *plane) { return self->intersect(*plane) != -1; });
}
void Sphere::mergePoint(const Vec3 &point) {
if (_radius < 0.0F) {
_center = point;
_radius = 0.0F;
return;
}
auto offset = point - _center;
auto distance = offset.length();
if (distance > _radius) {
auto half = (distance - _radius) * 0.5F;
_radius += half;
offset.scale(half / distance);
_center += offset;
}
}
void Sphere::define(const AABB &aabb) {
cc::Vec3 minPos;
cc::Vec3 maxPos;
aabb.getBoundary(&minPos, &maxPos);
// Initialize sphere
_center.set(minPos);
_radius = 0.0F;
// Calculate sphere
const cc::Vec3 offset = maxPos - _center;
const float dist = offset.length();
const float half = dist * 0.5F;
_radius += dist * 0.5F;
_center += (half / dist) * offset;
}
void Sphere::mergeAABB(const AABB *aabb) {
cc::Vec3 minPos;
cc::Vec3 maxPos;
aabb->getBoundary(&minPos, &maxPos);
mergePoint(minPos);
mergePoint(maxPos);
}
int Sphere::spherePlane(const Plane &plane) const {
return intersect(plane);
}
bool Sphere::sphereFrustum(const Frustum &frustum) const {
return intersect(frustum);
}
void Sphere::mergeFrustum(const Frustum &frustum) {
const ccstd::array<Vec3, 8> &vertices = frustum.vertices;
for (size_t i = 0; i < vertices.max_size(); ++i) {
merge(vertices[i]);
}
}
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,201 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "core/geometry/Enums.h"
#include "core/geometry/Frustum.h"
#include "math/Utils.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
class AABB;
class Sphere final : public ShapeBase {
public:
/**
* @en
* create a new sphere
* @zh
* 创建一个新的 sphere 实例。
* @param cx 形状的相对于原点的 X 坐标。
* @param cy 形状的相对于原点的 Y 坐标。
* @param cz 形状的相对于原点的 Z 坐标。
* @param r 球体的半径
* @return {Sphere} 返回一个 sphere。
*/
static Sphere *create(float cx, float cy, float cz, float radius);
/**
* @en
* clone a new sphere
* @zh
* 克隆一个新的 sphere 实例。
* @param {Sphere} p 克隆的目标。
* @return {Sphere} 克隆出的示例。
*/
static Sphere *clone(const Sphere &p);
/**
* @en
* copy the values from one sphere to another
* @zh
* 将从一个 sphere 的值复制到另一个 sphere。
* @param {Sphere} out 接受操作的 sphere。
* @param {Sphere} a 被复制的 sphere。
* @return {Sphere} out 接受操作的 sphere。
*/
static Sphere *copy(Sphere *out, const Sphere &p);
/**
* @en
* create a new bounding sphere from two corner points
* @zh
* 从两个点创建一个新的 sphere。
* @param out - 接受操作的 sphere。
* @param minPos - sphere 的最小点。
* @param maxPos - sphere 的最大点。
* @returns {Sphere} out 接受操作的 sphere。
*/
static Sphere *fromPoints(Sphere *out, const Vec3 &minPos, const Vec3 &maxPos);
/**
* @en
* Set the components of a sphere to the given values
* @zh
* 将球体的属性设置为给定的值。
* @param {Sphere} out 接受操作的 sphere。
* @param cx 形状的相对于原点的 X 坐标。
* @param cy 形状的相对于原点的 Y 坐标。
* @param cz 形状的相对于原点的 Z 坐标。
* @param {number} r 半径。
* @return {Sphere} out 接受操作的 sphere。
* @function
*/
static Sphere *set(Sphere *out, float cx, float cy, float cz, float r);
/**
* @zh
* 球跟点合并
*/
static Sphere *mergePoint(Sphere *out, const Sphere &s, const Vec3 &point);
/**
* @zh
* 球跟立方体合并
*/
static Sphere *mergeAABB(Sphere *out, const Sphere &s, const AABB &a);
explicit Sphere(float cx = 0, float cy = 0, float cz = 0, float radius = 1.0F);
Sphere(const Sphere &) = default;
Sphere(Sphere &&) = delete;
~Sphere() override = default;
Sphere &operator=(const Sphere &) = default;
Sphere &operator=(Sphere &&) = delete;
inline float getRadius() const { return _radius; }
inline const Vec3 &getCenter() const { return _center; }
inline void setCenter(const Vec3 &val) { _center = val; }
inline void setRadius(float val) { _radius = val; }
inline Sphere *clone() const {
return Sphere::clone(*this);
}
inline Sphere *copy(Sphere *out) const {
return Sphere::copy(out, *this);
}
void define(const AABB &aabb);
void mergeAABB(const AABB *aabb);
void mergePoint(const Vec3 &point);
void mergeFrustum(const Frustum &frustum);
inline void merge(const AABB *aabb) { mergeAABB(aabb); }
inline void merge(const Vec3 &point) { mergePoint(point); }
void merge(const ccstd::vector<Vec3> &points);
inline void merge(const Frustum &frustum) { mergeFrustum(frustum); }
bool intersect(const Frustum &frustum) const;
int intersect(const Plane &plane) const;
int spherePlane(const Plane &plane) const;
bool sphereFrustum(const Frustum &frustum) const;
/**
* @en
* Get the bounding points of this shape
* @zh
* 获取此形状的边界点。
* @param {Vec3} minPos 最小点。
* @param {Vec3} maxPos 最大点。
*/
void getBoundary(Vec3 *minPos, Vec3 *maxPos) const;
/**
* @en
* Transform this shape
* @zh
* 将 out 根据这个 sphere 的数据进行变换。
* @param m 变换的矩阵。
* @param pos 变换的位置部分。
* @param rot 变换的旋转部分。
* @param scale 变换的缩放部分。
* @param out 变换的目标。
*/
void transform(const Mat4 &m,
const Vec3 & /*pos*/,
const Quaternion & /*rot*/,
const Vec3 &scale,
Sphere *out) const;
/**
* @en
* Translate and rotate this sphere.
* @zh
* 将 out 根据这个 sphere 的数据进行变换。
* @param m 变换的矩阵。
* @param rot 变换的旋转部分。
* @param out 变换的目标。
*/
inline void translateAndRotate(const Mat4 &m, const Quaternion & /*rot*/, Sphere *out) const {
Vec3::transformMat4(_center, m, &out->_center);
}
/**
* @en
* Scaling this sphere.
* @zh
* 将 out 根据这个 sphere 的数据进行缩放。
* @param scale 缩放值。
* @param out 缩放的目标。
*/
inline void setScale(const Vec3 &scale, Sphere *out) const {
out->_radius = _radius * mathutils::maxComponent(scale);
}
// private: // make public for js bindings
float _radius{-1.0};
Vec3 _center;
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,200 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "core/geometry/Spline.h"
#include <cmath>
#include "base/Log.h"
#include "base/Macros.h"
#include "base/memory/Memory.h"
#include "math/Utils.h"
namespace cc {
namespace geometry {
Spline::Spline(SplineMode mode /*= SplineMode::CATMULL_ROM*/, ccstd::vector<Vec3> knots /*= {}*/)
: ShapeBase(ShapeEnum::SHAPE_SPLINE), _mode(mode), _knots(std::move(knots)) {
}
Spline *Spline::create(SplineMode mode, const ccstd::vector<Vec3> &knots /*= {}*/) {
return ccnew Spline(mode, knots);
}
Spline *Spline::clone(const Spline &s) {
return ccnew Spline(s._mode, s._knots);
}
Spline *Spline::copy(Spline *out, const Spline &s) {
out->_mode = s._mode;
out->_knots = s._knots;
return out;
}
void Spline::setModeAndKnots(SplineMode mode, const ccstd::vector<Vec3> &knots) {
_mode = mode;
_knots = knots;
}
void Spline::insertKnot(uint32_t index, const Vec3 &knot) {
if (index >= static_cast<uint32_t>(_knots.size())) {
_knots.push_back(knot);
return;
}
_knots.insert(_knots.begin() + index, knot);
}
void Spline::removeKnot(uint32_t index) {
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
_knots.erase(_knots.begin() + index);
}
void Spline::setKnot(uint32_t index, const Vec3 &knot) {
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
_knots[index] = knot;
}
const Vec3 &Spline::getKnot(uint32_t index) const {
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
return _knots[index];
}
Vec3 &Spline::getKnot(uint32_t index) {
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
return _knots[index];
}
Vec3 Spline::getPoint(float t, uint32_t index /*= SPLINE_WHOLE_INDEX*/) const {
t = mathutils::clamp(t, 0.0F, 1.0F);
const auto segments = getSegments();
if (segments == 0) {
return Vec3(0.0F, 0.0F, 0.0F);
}
if (index == SPLINE_WHOLE_INDEX) {
const auto deltaT = 1.0F / static_cast<float>(segments);
index = static_cast<uint32_t>(t / deltaT);
t = std::fmod(t, deltaT) / deltaT;
}
if (index >= segments) {
return _knots.back();
}
switch (_mode) {
case SplineMode::LINEAR:
return calcLinear(_knots[index], _knots[index + 1], t);
case SplineMode::BEZIER:
return calcBezier(_knots[index * 4], _knots[index * 4 + 1], _knots[index * 4 + 2], _knots[index * 4 + 3], t);
case SplineMode::CATMULL_ROM: {
const auto v0 = index > 0 ? _knots[index - 1] : _knots[index];
const auto v3 = index + 2 < static_cast<uint32_t>(_knots.size()) ? _knots[index + 2] : _knots[index + 1];
return calcCatmullRom(v0, _knots[index], _knots[index + 1], v3, t);
}
default:
return Vec3(0.0F, 0.0F, 0.0F);
}
}
ccstd::vector<Vec3> Spline::getPoints(uint32_t num, uint32_t index /*= SPLINE_WHOLE_INDEX*/) const {
if (num == 0U) {
return {};
}
if (num == 1U) {
auto point = getPoint(0.0F, index);
return {point};
}
ccstd::vector<Vec3> points;
const float deltaT = 1.0F / (static_cast<float>(num) - 1.0F);
for (auto i = 0; i < num; i++) {
const auto t = static_cast<float>(i) * deltaT;
const auto point = getPoint(t, index);
points.push_back(point);
}
return points;
}
uint32_t Spline::getSegments() const {
const auto count = static_cast<uint32_t>(_knots.size());
switch (_mode) {
case SplineMode::LINEAR:
case SplineMode::CATMULL_ROM:
if (count < 2) {
CC_LOG_WARNING("Spline error: less than 2 knots.");
return 0;
}
return count - 1;
case SplineMode::BEZIER:
if (count < 4 || count % 4 != 0) {
CC_LOG_WARNING("Spline error: less than 4 knots or not a multiple of 4.");
return 0;
}
return count / 4;
default:
CC_ABORT();
return 0;
}
}
Vec3 Spline::calcLinear(const Vec3 &v0, const Vec3 &v1, float t) {
const auto result = v0 * (1.0F - t) + v1 * t;
return result;
}
Vec3 Spline::calcBezier(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t) {
const auto s = 1.0F - t;
const auto result = v0 * s * s * s +
v1 * 3.0F * t * s * s +
v2 * 3.0F * t * t * s +
v3 * t * t * t;
return result;
}
Vec3 Spline::calcCatmullRom(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t) {
const auto t2 = t * t;
const auto t3 = t2 * t;
const auto result = v0 * (-0.5F * t3 + t2 - 0.5F * t) +
v1 * (1.5F * t3 - 2.5F * t2 + 1.0F) +
v2 * (-1.5F * t3 + 2.0F * t2 + 0.5F * t) +
v3 * (0.5F * t3 - 0.5F * t2);
return result;
}
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,115 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/std/container/vector.h"
#include "core/geometry/Enums.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
enum class SplineMode {
/**
* Broken line:
* Each knot is connected with a straight line from the beginning to the end to form a curve. At least two knots.
*/
LINEAR = 0,
/**
* Piecewise Bezier curve:
* Every four knots form a curve. Total knots number must be a multiple of 4.
* Each curve passes only the first and fourth knots, and does not pass through the middle two control knots.
*
* If you need a whole continuous curve:
* (1) Suppose the four knots of the previous curve are A, B, C, D
* (2) The four knots of the next curve must be D, E, F, G
* (3) C and E need to be symmetrical about D
*/
BEZIER = 1,
/**
* Catmull Rom curve:
* All knots(including start & end knots) form a whole continuous curve. At least two knots.
* The whole curve passes through all knots.
*/
CATMULL_ROM = 2
};
constexpr uint32_t SPLINE_WHOLE_INDEX = 0xffffffff;
/**
* @en
* Basic Geometry: Spline.
* @zh
* 基础几何 Spline。
*/
class Spline final : public ShapeBase {
public:
explicit Spline(SplineMode mode = SplineMode::CATMULL_ROM, ccstd::vector<Vec3> knots = {});
Spline(const Spline &) = default;
Spline(Spline &&) = default;
~Spline() override = default;
Spline &operator=(const Spline &) = default;
Spline &operator=(Spline &&) = default;
static Spline *create(SplineMode mode, const ccstd::vector<Vec3> &knots = {});
static Spline *clone(const Spline &s);
static Spline *copy(Spline *out, const Spline &s);
inline void setMode(SplineMode mode) { _mode = mode; }
inline SplineMode getMode() const { return _mode; }
inline void setKnots(const ccstd::vector<Vec3> &knots) { _knots = knots; }
inline const ccstd::vector<Vec3> &getKnots() const { return _knots; }
inline void clearKnots() { _knots.clear(); }
inline uint32_t getKnotCount() const { return static_cast<uint32_t>(_knots.size()); }
inline void addKnot(const Vec3 &knot) { _knots.push_back(knot); }
void setModeAndKnots(SplineMode mode, const ccstd::vector<Vec3> &knots);
void insertKnot(uint32_t index, const Vec3 &knot);
void removeKnot(uint32_t index);
void setKnot(uint32_t index, const Vec3 &knot);
const Vec3 &getKnot(uint32_t index) const;
Vec3 &getKnot(uint32_t index);
// get a point at t with repect to the `index` segment of curve or the whole curve.
Vec3 getPoint(float t, uint32_t index = SPLINE_WHOLE_INDEX) const;
// get num points from 0 to 1 uniformly with repect to the `index` segment of curve or the whole curve
ccstd::vector<Vec3> getPoints(uint32_t num, uint32_t index = SPLINE_WHOLE_INDEX) const;
private:
uint32_t getSegments() const;
static Vec3 calcLinear(const Vec3 &v0, const Vec3 &v1, float t);
static Vec3 calcBezier(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t);
static Vec3 calcCatmullRom(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t);
SplineMode _mode{SplineMode::CATMULL_ROM};
ccstd::vector<Vec3> _knots; // control points of the curve.
};
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,87 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "core/geometry/Triangle.h"
#include "base/memory/Memory.h"
namespace cc {
namespace geometry {
Triangle *Triangle::create(float ax, float ay, float az,
float bx, float by, float bz,
float cx, float cy, float cz) {
return ccnew Triangle(ax, ay, az, bx, by, bz, cx, cy, cz);
}
Triangle *Triangle::clone(const Triangle &t) {
return ccnew Triangle(
t.a.x, t.a.y, t.a.z,
t.b.x, t.b.y, t.b.z,
t.c.x, t.c.y, t.c.z);
}
Triangle *Triangle::copy(Triangle *out, const Triangle &t) {
out->a = t.a;
out->b = t.b;
out->c = t.c;
return out;
}
Triangle *Triangle::fromPoints(Triangle *out, const Vec3 &a,
const Vec3 &b,
const Vec3 &c) {
out->a = a;
out->b = b;
out->c = c;
return out;
}
Triangle *Triangle::set(Triangle *out,
float ax, float ay, float az,
float bx, float by, float bz,
float cx, float cy, float cz) {
out->a.x = ax;
out->a.y = ay;
out->a.z = az;
out->b.x = bx;
out->b.y = by;
out->b.z = bz;
out->c.x = cx;
out->c.y = cy;
out->c.z = cz;
return out;
}
Triangle::Triangle(float ax, float ay, float az,
float bx, float by, float bz,
float cx, float cy, float cz) : ShapeBase(ShapeEnum::SHAPE_TRIANGLE) {
a = {ax, ay, az};
b = {bx, by, bz};
c = {cx, cy, cz};
}
} // namespace geometry
} // namespace cc

View File

@@ -0,0 +1,175 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
https://www.cocos.com/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "core/geometry/Enums.h"
#include "math/Vec3.h"
namespace cc {
namespace geometry {
/**
* @en
* Basic Geometry: Triangle.
* @zh
* 基础几何 三角形。
*/
class Triangle final : public ShapeBase {
public:
/**
* @en
* create a new triangle
* @zh
* 创建一个新的 triangle。
* @param {number} ax a 点的 x 部分。
* @param {number} ay a 点的 y 部分。
* @param {number} az a 点的 z 部分。
* @param {number} bx b 点的 x 部分。
* @param {number} by b 点的 y 部分。
* @param {number} bz b 点的 z 部分。
* @param {number} cx c 点的 x 部分。
* @param {number} cy c 点的 y 部分。
* @param {number} cz c 点的 z 部分。
* @return {Triangle} 一个新的 triangle。
*/
static Triangle *create(float ax = 1, float ay = 0, float az = 0,
float bx = 0, float by = 0, float bz = 0,
float cx = 0, float cy = 0, float cz = 1);
/**
* @en
* clone a new triangle
* @zh
* 克隆一个新的 triangle。
* @param {Triangle} t 克隆的目标。
* @return {Triangle} 克隆出的新对象。
*/
static Triangle *clone(const Triangle &t);
/**
* @en
* copy the values from one triangle to another
* @zh
* 将一个 triangle 的值复制到另一个 triangle。
* @param {Triangle} out 接受操作的 triangle。
* @param {Triangle} t 被复制的 triangle。
* @return {Triangle} out 接受操作的 triangle。
*/
static Triangle *copy(Triangle *out, const Triangle &t);
/**
* @en
* Create a triangle from three points
* @zh
* 用三个点创建一个 triangle。
* @param {Triangle} out 接受操作的 triangle。
* @param {Vec3} a a 点。
* @param {Vec3} b b 点。
* @param {Vec3} c c 点。
* @return {Triangle} out 接受操作的 triangle。
*/
static Triangle *fromPoints(Triangle *out, const Vec3 &a,
const Vec3 &b,
const Vec3 &c);
/**
* @en
* Set the components of a triangle to the given values
* @zh
* 将给定三角形的属性设置为给定值。
* @param {Triangle} out 给定的三角形。
* @param {number} ax a 点的 x 部分。
* @param {number} ay a 点的 y 部分。
* @param {number} az a 点的 z 部分。
* @param {number} bx b 点的 x 部分。
* @param {number} by b 点的 y 部分。
* @param {number} bz b 点的 z 部分。
* @param {number} cx c 点的 x 部分。
* @param {number} cy c 点的 y 部分。
* @param {number} cz c 点的 z 部分。
* @return {Triangle}
* @function
*/
static Triangle *set(Triangle *out,
float ax, float ay, float az,
float bx, float by, float bz,
float cx, float cy, float cz);
/**
* @en
* Point a.
* @zh
* 点 a。
*/
Vec3 a;
/**
* @en
* Point b.
* @zh
* 点 b。
*/
Vec3 b;
/**
* @en
* Point c.
* @zh
* 点 c。
*/
Vec3 c;
/**
* @en
* Construct a triangle.
* @zh
* 构造一个三角形。
* @param {number} ax a 点的 x 部分。
* @param {number} ay a 点的 y 部分。
* @param {number} az a 点的 z 部分。
* @param {number} bx b 点的 x 部分。
* @param {number} by b 点的 y 部分。
* @param {number} bz b 点的 z 部分。
* @param {number} cx c 点的 x 部分。
* @param {number} cy c 点的 y 部分。
* @param {number} cz c 点的 z 部分。
*/
explicit Triangle(float ax = 0, float ay = 0, float az = 0,
float bx = 1, float by = 0, float bz = 0,
float cx = 0, float cy = 1, float cz = 0);
Triangle(const Triangle &) = default;
Triangle(Triangle &&) = default;
~Triangle() override = default;
Triangle &operator=(const Triangle &) = default;
Triangle &operator=(Triangle &&) = default;
}; // namespace geometry
} // namespace geometry
} // namespace cc