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

100
cocos/math/Color.cpp Normal file
View File

@@ -0,0 +1,100 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-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 "Color.h"
namespace cc {
Color::Color()
: r(0),
g(0),
b(0),
a(0) {
}
Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
: r(r),
g(g),
b(b),
a(a) {
}
Color::Color(const uint8_t *src) {
set(src);
}
Color::Color(uint32_t val) {
set(val);
}
Color::Color(const Color &p1, const Color &p2) {
set(p1, p2);
}
Color::Color(const Color &copy) {
set(copy);
}
void Color::set(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
this->r = r;
this->g = g;
this->b = b;
this->a = a;
}
void Color::set(const uint8_t *array) {
r = array[0];
g = array[1];
b = array[2];
a = array[3];
}
void Color::set(uint32_t val) {
r = val & 0x000000FF;
g = (val & 0x0000FF00) >> 8;
b = (val & 0x00FF0000) >> 16;
a = (val & 0xFF000000) >> 24;
}
void Color::set(const Color &c) {
this->r = c.r;
this->g = c.g;
this->b = c.b;
this->a = c.a;
}
void Color::set(const Color &p1, const Color &p2) {
r = p2.r - p1.r;
g = p2.g - p1.g;
b = p2.b - p1.b;
a = p2.a - p1.a;
}
Vec4 Color::toVec4() const {
return {static_cast<float>(r) / 255.F, static_cast<float>(g) / 255.F, static_cast<float>(b) / 255.F, static_cast<float>(a) / 255.F};
}
} // namespace cc

118
cocos/math/Color.h Normal file
View File

@@ -0,0 +1,118 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-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 <cstdint>
#include "math/Vec4.h"
namespace cc {
class Color {
public:
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
/**
* Constructs a new color initialized to all zeros.
*/
Color();
/**
* Constructs a new color initialized to the specified values.
*
* @param xx The x coordinate.
* @param yy The y coordinate.
* @param zz The z coordinate.
* @param ww The w coordinate.
*/
explicit Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
/**
* Constructs a new color from the values in the specified array.
*
* @param array An array containing the elements of the color in the order r, g, b, a.
*/
explicit Color(const uint8_t *src);
explicit Color(uint32_t val);
/**
* Constructs a color that describes the direction between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
Color(const Color &p1, const Color &p2);
/**
* Constructor.
*
* Creates a new color that is a copy of the specified color.
*
* @param copy The color to copy.
*/
Color(const Color &copy);
/**
* Sets the elements of this color to the specified values.
*
* @param xx The new x coordinate.
* @param yy The new y coordinate.
* @param zz The new z coordinate.
* @param ww The new w coordinate.
*/
void set(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
/**
* Sets the elements of this color from the values in the specified array.
*
* @param array An array containing the elements of the color in the order r, g, b, a.
*/
void set(const uint8_t *array);
void set(uint32_t val);
/**
* Sets the elements of this color to those in the specified color.
*
* @param v The color to copy.
*/
void set(const Color &c);
/**
* Sets this color to the directional color between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
void set(const Color &p1, const Color &p2);
Vec4 toVec4() const;
};
} // namespace cc

241
cocos/math/Geometry.cpp Normal file
View File

@@ -0,0 +1,241 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
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 "math/Geometry.h"
#include <algorithm>
#include <cmath>
#include "base/Macros.h"
// implementation of Vec2
namespace cc {
// implementation of Size
Size::Size() = default;
Size::Size(float w, float h) : width(w),
height(h) {
}
Size::Size(const Size &other) = default;
Size::Size(const Vec2 &point) : width(point.x),
height(point.y) {
}
Size &Size::operator=(const Size &other) {
setSize(other.width, other.height);
return *this;
}
Size &Size::operator=(const Vec2 &point) {
setSize(point.x, point.y);
return *this;
}
Size Size::operator+(const Size &right) const {
return Size(this->width + right.width, this->height + right.height);
}
Size Size::operator-(const Size &right) const {
return Size(this->width - right.width, this->height - right.height);
}
Size Size::operator*(float a) const {
return Size(this->width * a, this->height * a);
}
Size Size::operator/(float a) const {
CC_ASSERT_NE(a, 0);
float inv = 1.0F / a;
return Size(this->width * inv, this->height * inv);
}
void Size::setSize(float w, float h) {
this->width = w;
this->height = h;
}
bool Size::equals(const Size &target) const {
return (std::abs(this->width - target.width) < FLT_EPSILON) && (std::abs(this->height - target.height) < FLT_EPSILON);
}
const Size Size::ZERO = Size(0, 0);
// implementation of Rect
Rect::Rect() {
setRect(0.0F, 0.0F, 0.0F, 0.0F);
}
Rect::Rect(float x, float y, float width, float height) {
setRect(x, y, width, height);
}
Rect::Rect(const Vec2 &pos, const Size &dimension) {
setRect(pos.x, pos.y, dimension.width, dimension.height);
}
Rect::Rect(const Rect &other) {
setRect(other.x, other.y, other.width, other.height);
}
Rect &Rect::operator=(const Rect &other) {
setRect(other.x, other.y, other.width, other.height);
return *this;
}
void Rect::setRect(float x, float y, float width, float height) {
// CGRect can support width<0 or height<0
// CC_ASSERT(width >= 0.0f && height >= 0.0f);
this->x = x;
this->y = y;
this->width = width;
this->height = height;
}
bool Rect::equals(const Rect &rect) const {
return (std::abs(this->x - rect.x) < FLT_EPSILON) && (std::abs(this->y - rect.y) < FLT_EPSILON) && (std::abs(this->width - rect.width) < FLT_EPSILON) && (std::abs(this->height - rect.height) < FLT_EPSILON);
}
float Rect::getMaxX() const {
return this->x + this->width;
}
float Rect::getMidX() const {
return this->x + this->width / 2.0F;
}
float Rect::getMinX() const {
return this->x;
}
float Rect::getMaxY() const {
return this->y + this->height;
}
float Rect::getMidY() const {
return this->y + this->height / 2.0F;
}
float Rect::getMinY() const {
return this->y;
}
bool Rect::containsPoint(const Vec2 &point) const {
bool bRet = false;
if (point.x >= getMinX() && point.x <= getMaxX() && point.y >= getMinY() && point.y <= getMaxY()) {
bRet = true;
}
return bRet;
}
bool Rect::intersectsRect(const Rect &rect) const {
return !(getMaxX() < rect.getMinX() ||
rect.getMaxX() < getMinX() ||
getMaxY() < rect.getMinY() ||
rect.getMaxY() < getMinY());
}
bool Rect::intersectsCircle(const Vec2 &center, float radius) const {
Vec2 rectangleCenter((this->x + this->width / 2),
(this->y + this->height / 2));
float w = this->width / 2;
float h = this->height / 2;
float dx = std::abs(center.x - rectangleCenter.x);
float dy = std::abs(center.y - rectangleCenter.y);
if (dx > (radius + w) || dy > (radius + h)) {
return false;
}
Vec2 circleDistance(std::abs(center.x - this->x - w),
std::abs(center.y - this->y - h));
if (circleDistance.x <= (w)) {
return true;
}
if (circleDistance.y <= (h)) {
return true;
}
float cornerDistanceSq = powf(circleDistance.x - w, 2) + powf(circleDistance.y - h, 2);
return (cornerDistanceSq <= (powf(radius, 2)));
}
void Rect::merge(const Rect &rect) {
float minX = std::min(getMinX(), rect.getMinX());
float minY = std::min(getMinY(), rect.getMinY());
float maxX = std::max(getMaxX(), rect.getMaxX());
float maxY = std::max(getMaxY(), rect.getMaxY());
setRect(minX, minY, maxX - minX, maxY - minY);
}
Rect Rect::unionWithRect(const Rect &rect) const {
float thisLeftX = this->x;
float thisRightX = this->x + this->width;
float thisTopY = this->y + this->height;
float thisBottomY = this->y;
if (thisRightX < thisLeftX) {
std::swap(thisRightX, thisLeftX); // This rect has negative width
}
if (thisTopY < thisBottomY) {
std::swap(thisTopY, thisBottomY); // This rect has negative height
}
float otherLeftX = rect.x;
float otherRightX = rect.x + rect.width;
float otherTopY = rect.y + rect.height;
float otherBottomY = rect.y;
if (otherRightX < otherLeftX) {
std::swap(otherRightX, otherLeftX); // Other rect has negative width
}
if (otherTopY < otherBottomY) {
std::swap(otherTopY, otherBottomY); // Other rect has negative height
}
float combinedLeftX = std::min(thisLeftX, otherLeftX);
float combinedRightX = std::max(thisRightX, otherRightX);
float combinedTopY = std::max(thisTopY, otherTopY);
float combinedBottomY = std::min(thisBottomY, otherBottomY);
return Rect(combinedLeftX, combinedBottomY, combinedRightX - combinedLeftX, combinedTopY - combinedBottomY);
}
const Rect Rect::ZERO = Rect(0, 0, 0, 0);
} // namespace cc

140
cocos/math/Geometry.h Normal file
View File

@@ -0,0 +1,140 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
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 "math/Vec2.h"
namespace cc {
class CC_DLL Size {
public:
/**Width of the Size.*/
float width{0.F};
/**Height of the Size.*/
float height{0.F};
/**Conversion from Vec2 to Size.*/
operator Vec2() const { // NOLINT
return Vec2(width, height);
}
/**
@{
Constructor.
@param width Width of the size.
@param height Height of the size.
@param other Copy constructor.
@param point Conversion from a point.
*/
Size();
Size(float width, float height);
Size(const Size &other);
explicit Size(const Vec2 &point);
/**@}*/
Size &operator=(const Size &other);
Size &operator=(const Vec2 &point);
Size operator+(const Size &right) const;
Size operator-(const Size &right) const;
Size operator*(float a) const;
Size operator/(float a) const;
/**
Set the width and height of Size.
*/
void setSize(float width, float height);
/**
Check if two size is the same.
*/
bool equals(const Size &target) const;
/**Size(0,0).*/
static const Size ZERO;
};
/**Rectangle area.*/
class CC_DLL Rect {
public:
float x{0.F};
float y{0.F};
float width{0.F};
float height{0.F};
Rect();
Rect(float x, float y, float width, float height);
Rect(const Vec2 &pos, const Size &dimension);
Rect(const Rect &other);
Rect &operator=(const Rect &other);
void setRect(float x, float y, float width, float height);
/**
Get the left of the rect.
*/
float getMinX() const; /// return the leftmost x-value of current rect
/**
Get the X coordinate of center point.
*/
float getMidX() const; /// return the midpoint x-value of current rect
/**
Get the right of rect.
*/
float getMaxX() const; /// return the rightmost x-value of current rect
/**
Get the bottom of rect.
*/
float getMinY() const; /// return the bottommost y-value of current rect
/**
Get the Y coordinate of center point.
*/
float getMidY() const; /// return the midpoint y-value of current rect
/**
Get top of rect.
*/
float getMaxY() const; /// return the topmost y-value of current rect
bool equals(const Rect &rect) const;
/**
Check if the points is contained in the rect.
*/
bool containsPoint(const Vec2 &point) const;
/**
Check the intersect status of two rects.
*/
bool intersectsRect(const Rect &rect) const;
/**
Check the intersect status of the rect and a circle.
*/
bool intersectsCircle(const Vec2 &center, float radius) const;
/**
Get the min rect which can contain this and rect.
*/
Rect unionWithRect(const Rect &rect) const;
/**Compute the min rect which can contain this and rect, assign it to this.*/
void merge(const Rect &rect);
/**An empty Rect.*/
static const Rect ZERO;
};
} // namespace cc

448
cocos/math/Mat3.cpp Normal file
View File

@@ -0,0 +1,448 @@
/****************************************************************************
Copyright (c) 2018-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 "math/Mat3.h"
#include <cmath>
#include <cstring>
#include "base/Macros.h"
#include "math/Math.h"
#include "math/MathUtil.h"
#include "math/Quaternion.h"
NS_CC_MATH_BEGIN
Mat3::Mat3() {
*this = IDENTITY;
}
Mat3::Mat3(float m00, float m01, float m02,
float m03, float m04, float m05,
float m06, float m07, float m08) {
set(m00, m01, m02, m03, m04, m05, m06, m07, m08);
}
Mat3::Mat3(const float *mat) {
set(mat);
}
Mat3::Mat3(const Mat3 &copy) {
memcpy(m, copy.m, MATRIX3_SIZE);
}
void Mat3::set(float m00, float m01, float m02,
float m03, float m04, float m05,
float m06, float m07, float m08) {
m[0] = m00;
m[1] = m01;
m[2] = m02;
m[3] = m03;
m[4] = m04;
m[5] = m05;
m[6] = m06;
m[7] = m07;
m[8] = m08;
}
void Mat3::set(const float *mat) {
CC_ASSERT(mat);
memcpy(this->m, mat, MATRIX3_SIZE);
}
void Mat3::set(const Mat3 &mat) {
memcpy(this->m, mat.m, MATRIX3_SIZE);
}
void Mat3::identity(Mat3 &mat) {
mat.m[0] = 1;
mat.m[1] = 0;
mat.m[2] = 0;
mat.m[3] = 0;
mat.m[4] = 1;
mat.m[5] = 0;
mat.m[6] = 0;
mat.m[7] = 0;
mat.m[8] = 1;
}
void Mat3::fromViewUp(const Vec3 &view, Mat3 *out) {
CC_ASSERT(out);
fromViewUp(view, Vec3(0, 1, 0), out);
}
void Mat3::fromViewUp(const Vec3 &view, const Vec3 &up, Mat3 *out) {
CC_ASSERT(out);
if (view.lengthSquared() < math::EPSILON * math::EPSILON) {
Mat3::identity(*out);
return;
}
Vec3 vTempA{Vec3::ZERO};
Vec3 vTempB{Vec3::ZERO};
Vec3::cross(up, view, &vTempA);
vTempA.normalize();
if (vTempA.lengthSquared() < math::EPSILON * math::EPSILON) {
Mat3::identity(*out);
return;
}
Vec3::cross(view, vTempA, &vTempB);
out->set(vTempA.x, vTempA.y, vTempA.z,
vTempB.x, vTempB.y, vTempB.z,
view.x, view.y, view.z);
}
void Mat3::transpose() {
float a01 = m[1];
float a02 = m[2];
float a12 = m[5];
m[1] = m[3];
m[2] = m[6];
m[3] = a01;
m[5] = m[7];
m[6] = a02;
m[7] = a12;
}
void Mat3::transpose(const Mat3 &mat, Mat3 *out) {
CC_ASSERT(out);
out->m[0] = mat.m[0];
out->m[1] = mat.m[3];
out->m[2] = mat.m[6];
out->m[3] = mat.m[1];
out->m[4] = mat.m[4];
out->m[5] = mat.m[7];
out->m[6] = mat.m[2];
out->m[7] = mat.m[5];
out->m[8] = mat.m[8];
}
void Mat3::inverse() {
float a00 = m[0];
float a01 = m[1];
float a02 = m[2];
float a10 = m[3];
float a11 = m[4];
float a12 = m[5];
float a20 = m[6];
float a21 = m[7];
float a22 = m[8];
float b01 = a22 * a11 - a12 * a21;
float b11 = -a22 * a10 + a12 * a20;
float b21 = a21 * a10 - a11 * a20;
// Calculate the determinant
float det = a00 * b01 + a01 * b11 + a02 * b21;
if (det == 0.F) {
set(0.F, 0.F, 0.F, 0.F, 0.F, 0.F, 0.F, 0.F, 0.F);
return;
}
det = 1.0F / det;
m[0] = b01 * det;
m[1] = (-a22 * a01 + a02 * a21) * det;
m[2] = (a12 * a01 - a02 * a11) * det;
m[3] = b11 * det;
m[4] = (a22 * a00 - a02 * a20) * det;
m[5] = (-a12 * a00 + a02 * a10) * det;
m[6] = b21 * det;
m[7] = (-a21 * a00 + a01 * a20) * det;
m[8] = (a11 * a00 - a01 * a10) * det;
}
void Mat3::adjoint(const Mat3 &mat, Mat3 *out) {
CC_ASSERT(out);
float a00 = mat.m[0];
float a01 = mat.m[1];
float a02 = mat.m[2];
float a10 = mat.m[3];
float a11 = mat.m[4];
float a12 = mat.m[5];
float a20 = mat.m[6];
float a21 = mat.m[7];
float a22 = mat.m[8];
out->m[0] = (a11 * a22 - a12 * a21);
out->m[1] = (a02 * a21 - a01 * a22);
out->m[2] = (a01 * a12 - a02 * a11);
out->m[3] = (a12 * a20 - a10 * a22);
out->m[4] = (a00 * a22 - a02 * a20);
out->m[5] = (a02 * a10 - a00 * a12);
out->m[6] = (a10 * a21 - a11 * a20);
out->m[7] = (a01 * a20 - a00 * a21);
out->m[8] = (a00 * a11 - a01 * a10);
}
float Mat3::determinant() {
return m[0] * (m[8] * m[4] - m[5] * m[7]) + m[1] * (-m[8] * m[3] + m[5] * m[6]) + m[2] * (m[7] * m[3] - m[4] * m[6]);
}
void Mat3::multiply(const Mat3 &a, const Mat3 &b, Mat3 *out) {
CC_ASSERT(out);
float a00 = a.m[0];
float a01 = a.m[1];
float a02 = a.m[2];
float a10 = a.m[3];
float a11 = a.m[4];
float a12 = a.m[5];
float a20 = a.m[6];
float a21 = a.m[7];
float a22 = a.m[8];
float b00 = b.m[0];
float b01 = b.m[1];
float b02 = b.m[2];
float b10 = b.m[3];
float b11 = b.m[4];
float b12 = b.m[5];
float b20 = b.m[6];
float b21 = b.m[7];
float b22 = b.m[8];
out->m[0] = b00 * a00 + b01 * a10 + b02 * a20;
out->m[1] = b00 * a01 + b01 * a11 + b02 * a21;
out->m[2] = b00 * a02 + b01 * a12 + b02 * a22;
out->m[3] = b10 * a00 + b11 * a10 + b12 * a20;
out->m[4] = b10 * a01 + b11 * a11 + b12 * a21;
out->m[5] = b10 * a02 + b11 * a12 + b12 * a22;
out->m[6] = b20 * a00 + b21 * a10 + b22 * a20;
out->m[7] = b20 * a01 + b21 * a11 + b22 * a21;
out->m[8] = b20 * a02 + b21 * a12 + b22 * a22;
}
void Mat3::translate(const Mat3 &mat, const Vec2 &vec, Mat3 *out) {
CC_ASSERT(out);
float a00 = mat.m[0];
float a01 = mat.m[1];
float a02 = mat.m[2];
float a10 = mat.m[3];
float a11 = mat.m[4];
float a12 = mat.m[5];
float a20 = mat.m[6];
float a21 = mat.m[7];
float a22 = mat.m[8];
float x = vec.x;
float y = vec.y;
out->m[0] = a00;
out->m[1] = a01;
out->m[2] = a02;
out->m[3] = a10;
out->m[4] = a11;
out->m[5] = a12;
out->m[6] = x * a00 + y * a10 + a20;
out->m[7] = x * a01 + y * a11 + a21;
out->m[8] = x * a02 + y * a12 + a22;
}
void Mat3::rotate(const Mat3 &mat, float rad, Mat3 *out) {
CC_ASSERT(out);
float a00 = mat.m[0];
float a01 = mat.m[1];
float a02 = mat.m[2];
float a10 = mat.m[3];
float a11 = mat.m[4];
float a12 = mat.m[5];
float a20 = mat.m[6];
float a21 = mat.m[7];
float a22 = mat.m[8];
float s = sin(rad);
float c = cos(rad);
out->m[0] = c * a00 + s * a10;
out->m[1] = c * a01 + s * a11;
out->m[2] = c * a02 + s * a12;
out->m[3] = c * a10 - s * a00;
out->m[4] = c * a11 - s * a01;
out->m[5] = c * a12 - s * a02;
out->m[6] = a20;
out->m[7] = a21;
out->m[8] = a22;
}
void Mat3::scale(const Mat3 &mat, const Vec2 &vec, Mat3 *out) {
CC_ASSERT(out);
float x = vec.x;
float y = vec.y;
out->m[0] = x * mat.m[0];
out->m[1] = x * mat.m[1];
out->m[2] = x * mat.m[2];
out->m[3] = y * mat.m[3];
out->m[4] = y * mat.m[4];
out->m[5] = y * mat.m[5];
out->m[6] = mat.m[6];
out->m[7] = mat.m[7];
out->m[8] = mat.m[8];
}
void Mat3::fromMat4(const Mat4 &mat, Mat3 *out) {
CC_ASSERT(out);
out->m[0] = mat.m[0];
out->m[1] = mat.m[1];
out->m[2] = mat.m[2];
out->m[3] = mat.m[4];
out->m[4] = mat.m[5];
out->m[5] = mat.m[6];
out->m[6] = mat.m[8];
out->m[7] = mat.m[9];
out->m[8] = mat.m[10];
}
void Mat3::fromTranslation(const Vec2 &vec, Mat3 *out) {
CC_ASSERT(out);
out->m[0] = 1;
out->m[1] = 0;
out->m[2] = 0;
out->m[3] = 0;
out->m[4] = 1;
out->m[5] = 0;
out->m[6] = vec.x;
out->m[7] = vec.y;
out->m[8] = 1;
}
void Mat3::fromRotation(float rad, Mat3 *out) {
CC_ASSERT(out);
float s = sin(rad);
float c = cos(rad);
out->m[0] = c;
out->m[1] = s;
out->m[2] = 0;
out->m[3] = -s;
out->m[4] = c;
out->m[5] = 0;
out->m[6] = 0;
out->m[7] = 0;
out->m[8] = 1;
}
void Mat3::fromScaling(const Vec2 &vec, Mat3 *out) {
CC_ASSERT(out);
out->m[0] = vec.x;
out->m[1] = 0;
out->m[2] = 0;
out->m[3] = 0;
out->m[4] = vec.y;
out->m[5] = 0;
out->m[6] = 0;
out->m[7] = 0;
out->m[8] = 1;
}
void Mat3::fromQuat(const Quaternion &quat, Mat3 *out) {
CC_ASSERT(out);
float x = quat.x;
float y = quat.y;
float z = quat.z;
float w = quat.w;
float x2 = x + x;
float y2 = y + y;
float z2 = z + z;
float xx = x * x2;
float yx = y * x2;
float yy = y * y2;
float zx = z * x2;
float zy = z * y2;
float zz = z * z2;
float wx = w * x2;
float wy = w * y2;
float wz = w * z2;
out->m[0] = 1 - yy - zz;
out->m[3] = yx - wz;
out->m[6] = zx + wy;
out->m[1] = yx + wz;
out->m[4] = 1 - xx - zz;
out->m[7] = zy - wx;
out->m[2] = zx - wy;
out->m[5] = zy + wx;
out->m[8] = 1 - xx - yy;
}
void Mat3::add(const Mat3 &a, const Mat3 &b, Mat3 *out) {
CC_ASSERT(out);
out->m[0] = a.m[0] + b.m[0];
out->m[1] = a.m[1] + b.m[1];
out->m[2] = a.m[2] + b.m[2];
out->m[3] = a.m[3] + b.m[3];
out->m[4] = a.m[4] + b.m[4];
out->m[5] = a.m[5] + b.m[5];
out->m[6] = a.m[6] + b.m[6];
out->m[7] = a.m[7] + b.m[7];
out->m[8] = a.m[8] + b.m[8];
}
void Mat3::subtract(const Mat3 &a, const Mat3 &b, Mat3 *out) {
CC_ASSERT(out);
out->m[0] = a.m[0] - b.m[0];
out->m[1] = a.m[1] - b.m[1];
out->m[2] = a.m[2] - b.m[2];
out->m[3] = a.m[3] - b.m[3];
out->m[4] = a.m[4] - b.m[4];
out->m[5] = a.m[5] - b.m[5];
out->m[6] = a.m[6] - b.m[6];
out->m[7] = a.m[7] - b.m[7];
out->m[8] = a.m[8] - b.m[8];
}
bool Mat3::approxEquals(const Mat3 &v, float precision /* = CC_FLOAT_CMP_PRECISION */) const {
return math::isEqualF(m[0], v.m[0], precision) &&
math::isEqualF(m[1], v.m[1], precision) &&
math::isEqualF(m[2], v.m[2], precision) &&
math::isEqualF(m[3], v.m[3], precision) &&
math::isEqualF(m[4], v.m[4], precision) &&
math::isEqualF(m[5], v.m[5], precision) &&
math::isEqualF(m[6], v.m[6], precision) &&
math::isEqualF(m[7], v.m[7], precision) &&
math::isEqualF(m[8], v.m[8], precision);
}
const Mat3 Mat3::IDENTITY = Mat3(
1.F, 0.F, 0.F,
0.F, 1.F, 0.F,
0.F, 0.F, 1.F);
const Mat3 Mat3::ZERO = Mat3(
0, 0, 0,
0, 0, 0,
0, 0, 0);
NS_CC_MATH_END

244
cocos/math/Mat3.h Normal file
View File

@@ -0,0 +1,244 @@
/****************************************************************************
Copyright (c) 2018-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
#define MATRIX3_SIZE (sizeof(float) * 9)
#include "base/Macros.h"
#include "math/Mat4.h"
#include "math/Vec2.h"
#include "math/Vec3.h"
#include "math/Vec4.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
class CC_DLL Mat3 {
public:
/**
* Stores the columns of this 3x3 matrix.
* matrix layout
* |m[0] m[3] m[6]|
* |m[1] m[4] m[7]|
* |m[2] m[5] m[8]|
*/
float m[9];
/**
* Default constructor.
* Constructs a matrix initialized to the identity matrix:
*
* 1 0 0
* 0 1 0
* 0 0 1
*/
Mat3();
/**
* Constructs a matrix initialized to the specified values which are column-major order.
*/
Mat3(float m00, float m01, float m02,
float m03, float m04, float m05,
float m06, float m07, float m08);
/**
* Creates a matrix initialized to the specified column-major array.
*
* The passed-in array is in column-major order, so the memory layout of the array is as follows:
*
* 0 3 6
* 1 4 7
* 2 5 8
*
* @param mat An array containing 16 elements in column-major order.
*/
explicit Mat3(const float *mat);
/**
* Constructs a new matrix by copying the values from the specified matrix.
*
* @param copy The matrix to copy.
*/
Mat3(const Mat3 &copy);
/**
*
* @brief Construct a new Mat 3 object with a Mat4.
* Copies the upper-left 3x3 values of a 4x4 matrix into a 3x3 matrix.
* @param m4
*/
explicit Mat3(const Mat4 &m4) {
fromMat4(m4, this);
}
/**
* @brief Construct a new Mat 3 object with a Quaternion
* Calculates a 3x3 matrix from the given quaternion.
* @param quat
*/
explicit Mat3(const Quaternion &quat) {
fromQuat(quat, this);
}
/**
* Destructor.
*/
~Mat3() = default;
/**
* Sets the values of this matrix which are column-major order.
*/
void set(float m00, float m01, float m02,
float m03, float m04, float m05,
float m06, float m07, float m08);
/**
* Sets the values of this matrix to those in the specified column-major array.
*
* @param mat An array containing 9 elements in column-major format.
*/
void set(const float *mat);
/**
* Sets the values of this matrix to those of the specified matrix.
*
* @param mat The source matrix.
*/
void set(const Mat3 &mat);
/**
* return an identity matrix.
*/
static void identity(Mat3 &mat);
/**
* Transposes matrix.
*/
void transpose();
/**
* Transposes a matrix.
*/
static void transpose(const Mat3 &mat, Mat3 *out);
/**
* Inverts a matrix.
*/
void inverse();
/**
* Calculates the adjoint matrix.
*/
static void adjoint(const Mat3 &mat, Mat3 *out);
/**
* Calculates the determinant of a matrix.
*/
float determinant();
/**
* Multiply two matrices explicitly.
*/
static void multiply(const Mat3 &a, const Mat3 &b, Mat3 *out);
/**
* Multiply a matrix with a translation matrix given by a translation offset.
*/
static void translate(const Mat3 &mat, const Vec2 &vec, Mat3 *out);
/**
* Rotates a matrix by the given angle.
*/
static void rotate(const Mat3 &mat, float rad, Mat3 *out);
/**
* Multiply a matrix with a scale matrix given by a scale vector.
*/
static void scale(const Mat3 &mat, const Vec2 &vec, Mat3 *out);
/**
* Copies the upper-left 3x3 values of a 4x4 matrix into a 3x3 matrix.
*/
static void fromMat4(const Mat4 &mat, Mat3 *out);
/**
* Creates a matrix from a translation offset.
*/
static void fromTranslation(const Vec2 &vec, Mat3 *out);
/**
* Creates a matrix from a given angle.
*/
static void fromRotation(float rad, Mat3 *out);
/**
* Creates a matrix from a scale vector.
*/
static void fromScaling(const Vec2 &vec, Mat3 *out);
/**
* Sets a third order matrix with view direction and up direction. Then save the results to out matrix
*/
static void fromViewUp(const Vec3 &view, Mat3 *out);
static void fromViewUp(const Vec3 &view, const Vec3 &up, Mat3 *out);
/**
* Calculates a 3x3 matrix from the given quaternion.
*/
static void fromQuat(const Quaternion &quat, Mat3 *out);
/**
* Adds two matrices.
*/
static void add(const Mat3 &a, const Mat3 &b, Mat3 *out);
/**
* Subtracts matrix b from matrix a.
*/
static void subtract(const Mat3 &a, const Mat3 &b, Mat3 *out);
/**
* Determines if this matrix is approximately equal to the given matrix.
*/
bool approxEquals(const Mat3 &v, float precision = CC_FLOAT_CMP_PRECISION) const;
/** equals to a matrix full of zeros */
static const Mat3 ZERO;
/** equals to the identity matrix */
static const Mat3 IDENTITY;
};
NS_CC_MATH_END
/**
end of base group
@}
*/

1061
cocos/math/Mat4.cpp Normal file

File diff suppressed because it is too large Load Diff

964
cocos/math/Mat4.h Normal file
View File

@@ -0,0 +1,964 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#pragma once
#include "base/Macros.h"
#include "math/Vec3.h"
#include "math/Vec4.h"
#undef __SSE__
#ifdef __SSE__
#include <xmmintrin.h>
#endif
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
//class Plane;
/**
* Defines a 4 x 4 floating point matrix representing a 3D transformation.
*
* Vectors are treated as columns, resulting in a matrix that is represented as follows,
* where x, y and z are the translation components of the matrix:
*
* 1 0 0 x
* 0 1 0 y
* 0 0 1 z
* 0 0 0 1
*
* This matrix class is directly compatible with OpenGL since its elements are
* laid out in memory exactly as they are expected by OpenGL.
* The matrix uses column-major format such that array indices increase down column first.
* Since matrix multiplication is not commutative, multiplication must be done in the
* correct order when combining transformations. Suppose we have a translation
* matrix T and a rotation matrix R. To first rotate an object around the origin
* and then translate it, you would multiply the two matrices as TR.
*
* Likewise, to first translate the object and then rotate it, you would do RT.
* So generally, matrices must be multiplied in the reverse order in which you
* want the transformations to take place (this also applies to
* the scale, rotate, and translate methods below; these methods are convenience
* methods for post-multiplying by a matrix representing a scale, rotation, or translation).
*
* In the case of repeated local transformations (i.e. rotate around the Z-axis by 0.76 radians,
* then translate by 2.1 along the X-axis, then ...), it is better to use the Transform class
* (which is optimized for that kind of usage).
*
* @see Transform
*/
class CC_DLL Mat4 {
public:
// //temp add conversion
// operator kmMat4() const
// {
// kmMat4 result;
// kmMat4Fill(&result, m);
// return result;
// }
// Mat4(const kmMat4& mat)
// {
// set(mat.mat);
// }
/**
* Stores the columns of this 4x4 matrix.
* matrix layout
* |m[0] m[4] m[8] m[12]|
* |m[1] m[5] m[9] m[13]|
* |m[2] m[6] m[10] m[14]|
* |m[3] m[7] m[11] m[15]|
*/
#ifdef __SSE__
union {
__m128 col[4];
float m[16];
};
#else
float m[16];
#endif
/**
* Default constructor.
* Constructs a matrix initialized to the identity matrix:
*
* 1 0 0 0
* 0 1 0 0
* 0 0 1 0
* 0 0 0 1
*/
Mat4();
/**
* Constructs a matrix initialized to the specified value.
*
* @param m00 Component in column 0, row 0 position (index 0)
* @param m01 Component in column 0, row 1 position (index 1)
* @param m02 Component in column 0, row 2 position (index 2)
* @param m03 Component in column 0, row 3 position (index 3)
* @param m10 Component in column 1, row 0 position (index 4)
* @param m11 Component in column 1, row 1 position (index 5)
* @param m12 Component in column 1, row 2 position (index 6)
* @param m13 Component in column 1, row 3 position (index 7)
* @param m20 Component in column 2, row 0 position (index 8)
* @param m21 Component in column 2, row 1 position (index 9)
* @param m22 Component in column 2, row 2 position (index 10)
* @param m23 Component in column 2, row 3 position (index 11)
* @param m30 Component in column 3, row 0 position (index 12)
* @param m31 Component in column 3, row 1 position (index 13)
* @param m32 Component in column 3, row 2 position (index 14)
* @param m33 Component in column 3, row 3 position (index 15)
*/
Mat4(float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33);
/**
* Creates a matrix initialized to the specified column-major array.
*
* The passed-in array is in column-major order, so the memory layout of the array is as follows:
*
* 0 4 8 12
* 1 5 9 13
* 2 6 10 14
* 3 7 11 15
*
* @param mat An array containing 16 elements in column-major order.
*/
explicit Mat4(const float *mat);
/**
* Constructs a new matrix by copying the values from the specified matrix.
*
* @param copy The matrix to copy.
*/
Mat4(const Mat4 &copy);
/**
* Destructor.
*/
~Mat4() = default;
/**
* Creates a view matrix based on the specified input parameters.
*
* @param eyePosition The eye position.
* @param targetPosition The target's center position.
* @param up The up vector.
* @param dst A matrix to store the result in.
*/
static void createLookAt(const Vec3 &eyePosition, const Vec3 &targetPosition, const Vec3 &up, Mat4 *dst);
/**
* Creates a view matrix based on the specified input parameters.
*
* @param eyePositionX The eye x-coordinate position.
* @param eyePositionY The eye y-coordinate position.
* @param eyePositionZ The eye z-coordinate position.
* @param targetCenterX The target's center x-coordinate position.
* @param targetCenterY The target's center y-coordinate position.
* @param targetCenterZ The target's center z-coordinate position.
* @param upX The up vector x-coordinate value.
* @param upY The up vector y-coordinate value.
* @param upZ The up vector z-coordinate value.
* @param dst A matrix to store the result in.
*/
static void createLookAt(float eyePositionX, float eyePositionY, float eyePositionZ,
float targetPositionX, float targetPositionY, float targetPositionZ,
float upX, float upY, float upZ, Mat4 *dst);
/**
* Builds a perspective projection matrix based on a field of view and returns by value.
*
* Projection space refers to the space after applying projection transformation from view space.
* After the projection transformation, visible content has x- and y-coordinates ranging from -1 to 1,
* and a z-coordinate ranging from 0 to 1. To obtain the viewable area (in world space) of a scene,
* create a BoundingFrustum and pass the combined view and projection matrix to the constructor.
*
* @param fieldOfView The field of view in the y direction (in degrees).
* @param aspectRatio The aspect ratio, defined as view space width divided by height.
* @param zNearPlane The distance to the near view plane.
* @param zFarPlane The distance to the far view plane.
* @param dst A matrix to store the result in.
*/
static void createPerspective(float fieldOfView, float aspectRatio, float zNearPlane, float zFarPlane, Mat4 *dst = nullptr) {
Mat4::createPerspective(fieldOfView, aspectRatio, zNearPlane, zFarPlane, true, -1.0F, 1.0F, 0, dst);
}
static void createPerspective(float fieldOfView, float aspectRatio, float zNearPlane, float zFarPlane,
bool isFieldOfViewY = false, float minClipZ = -1, float projectionSignY = 1,
int orientation = 0, Mat4 *dst = nullptr);
/**
* Creates an orthographic projection matrix.
*
* Projection space refers to the space after applying
* projection transformation from view space. After the
* projection transformation, visible content has
* x and y coordinates ranging from -1 to 1, and z coordinates
* ranging from 0 to 1.
*
* Unlike perspective projection, in orthographic projection
* there is no perspective foreshortening.
*
* The viewable area of this orthographic projection extends
* from left to right on the x-axis, bottom to top on the y-axis,
* and zNearPlane to zFarPlane on the z-axis. These values are
* relative to the position and x, y, and z-axes of the view.
* To obtain the viewable area (in world space) of a scene,
* create a BoundingFrustum and pass the combined view and
* projection matrix to the constructor.
*
* @param left The minimum x-value of the view volume.
* @param right The maximum x-value of the view volume.
* @param bottom The minimum y-value of the view volume.
* @param top The maximum y-value of the view volume.
* @param zNearPlane The minimum z-value of the view volume.
* @param zFarPlane The maximum z-value of the view volume.
* @param dst A matrix to store the result in.
*/
static void createOrthographic(float left, float right, float bottom, float top, float zNearPlane, float zFarPlane, Mat4 *dst);
static void createOrthographicOffCenter(float left, float right, float bottom, float top,
float zNearPlane, float zFarPlane, Mat4 *dst);
static void createOrthographicOffCenter(float left, float right, float bottom, float top,
float zNearPlane, float zFarPlane, float minClipZ,
float projectionSignY, int orientation, Mat4 *dst);
/**
* Creates a spherical billboard that rotates around a specified object position.
*
* This method computes the facing direction of the billboard from the object position
* and camera position. When the object and camera positions are too close, the matrix
* will not be accurate. To avoid this problem, this method defaults to the identity
* rotation if the positions are too close. (See the other overload of createBillboard
* for an alternative approach).
*
* @param objectPosition The position of the object the billboard will rotate around.
* @param cameraPosition The position of the camera.
* @param cameraUpVector The up vector of the camera.
* @param dst A matrix to store the result in.
*/
static void createBillboard(const Vec3 &objectPosition, const Vec3 &cameraPosition,
const Vec3 &cameraUpVector, Mat4 *dst);
/**
* Creates a spherical billboard that rotates around a specified object position with
* provision for a safe default orientation.
*
* This method computes the facing direction of the billboard from the object position
* and camera position. When the object and camera positions are too close, the matrix
* will not be accurate. To avoid this problem, this method uses the specified camera
* forward vector if the positions are too close. (See the other overload of createBillboard
* for an alternative approach).
*
* @param objectPosition The position of the object the billboard will rotate around.
* @param cameraPosition The position of the camera.
* @param cameraUpVector The up vector of the camera.
* @param cameraForwardVector The forward vector of the camera, used if the positions are too close.
* @param dst A matrix to store the result in.
*/
static void createBillboard(const Vec3 &objectPosition, const Vec3 &cameraPosition,
const Vec3 &cameraUpVector, const Vec3 &cameraForwardVector,
Mat4 *dst);
//Fills in an existing Mat4 so that it reflects the coordinate system about a specified Plane.
//plane The Plane about which to create a reflection.
//dst A matrix to store the result in.
//static void createReflection(const Plane& plane, Mat4* dst);
/**
* Creates a scale matrix.
*
* @param scale The amount to scale.
* @param dst A matrix to store the result in.
*/
static void createScale(const Vec3 &scale, Mat4 *dst);
/**
* Creates a scale matrix.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
* @param dst A matrix to store the result in.
*/
static void createScale(float xScale, float yScale, float zScale, Mat4 *dst);
/**
* Creates a rotation matrix from the specified quaternion.
*
* @param quat A quaternion describing a 3D orientation.
* @param dst A matrix to store the result in.
*/
static void createRotation(const Quaternion &quat, Mat4 *dst);
/**
* Creates a rotation matrix from the specified axis and angle.
*
* @param axis A vector describing the axis to rotate about.
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
static void createRotation(const Vec3 &axis, float angle, Mat4 *dst);
/**
* Creates a matrix describing a rotation around the x-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
static void createRotationX(float angle, Mat4 *dst);
/**
* Creates a matrix describing a rotation around the y-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
static void createRotationY(float angle, Mat4 *dst);
/**
* Creates a matrix describing a rotation around the z-axis.
*
* @param angle The angle of rotation (in radians).
* @param dst A matrix to store the result in.
*/
static void createRotationZ(float angle, Mat4 *dst);
/**
* Creates a translation matrix.
*
* @param translation The translation.
* @param dst A matrix to store the result in.
*/
static void createTranslation(const Vec3 &translation, Mat4 *dst);
/**
* Creates a translation matrix.
*
* @param xTranslation The translation on the x-axis.
* @param yTranslation The translation on the y-axis.
* @param zTranslation The translation on the z-axis.
* @param dst A matrix to store the result in.
*/
static void createTranslation(float xTranslation, float yTranslation, float zTranslation, Mat4 *dst);
/**
* Adds a scalar value to each component of this matrix.
*
* @param scalar The scalar to add.
*/
void add(float scalar);
/**
* Adds a scalar value to each component of this matrix and stores the result in dst.
*
* @param scalar The scalar value to add.
* @param dst A matrix to store the result in.
*/
void add(float scalar, Mat4 *dst);
/**
* Adds the specified matrix to this matrix.
*
* @param mat The matrix to add.
*/
void add(const Mat4 &mat);
/**
* Adds the specified matrices and stores the result in dst.
*
* @param m1 The first matrix.
* @param m2 The second matrix.
* @param dst The destination matrix to add to.
*/
static void add(const Mat4 &m1, const Mat4 &m2, Mat4 *dst);
/**
* Calculate the matrix according to the ratation and translation
*/
static void fromRT(const Quaternion &rotation, const Vec3 &translation, Mat4 *dst);
/**
* Compose a matrix from scale, rotation and translation, applied in order.
*/
static void fromRTS(const Quaternion &rotation, const Vec3 &translation, const Vec3 &scale, Mat4 *dst);
/**
* Decomposes the scale, rotation and translation components of this matrix.
*/
static void toRTS(const Mat4 &src, Quaternion *rotation, Vec3 *translation, Vec3 *scale);
/**
* Decomposes the scale, rotation and translation components of this matrix.
*
* @param scale The scale.
* @param rotation The rotation.
* @param translation The translation.
*/
bool decompose(Vec3 *scale, Quaternion *rotation, Vec3 *translation) const;
/**
* Computes the determinant of this matrix.
*
* @return The determinant.
*/
float determinant() const;
/**
* Gets the scalar component of this matrix in the specified vector.
*
* If the scalar component of this matrix has negative parts,
* it is not possible to always extract the exact scalar component;
* instead, a scale vector that is mathematically equivalent to the
* original scale vector is extracted and returned.
*
* @param scale A vector to receive the scale.
*/
void getScale(Vec3 *scale) const;
/**
* Gets the rotational component of this matrix in the specified quaternion.
*
* @param rotation A quaternion to receive the rotation.
*
* @return true if the rotation is successfully extracted, false otherwise.
*/
bool getRotation(Quaternion *rotation) const;
/**
* Gets the translational component of this matrix in the specified vector.
*
* @param translation A vector to receive the translation.
*/
void getTranslation(Vec3 *translation) const;
/**
* Gets the up vector of this matrix.
*
* @param dst The destination vector.
*/
void getUpVector(Vec3 *dst) const;
/**
* Gets the down vector of this matrix.
*
* @param dst The destination vector.
*/
void getDownVector(Vec3 *dst) const;
/**
* Gets the left vector of this matrix.
*
* @param dst The destination vector.
*/
void getLeftVector(Vec3 *dst) const;
/**
* Gets the right vector of this matrix.
*
* @param dst The destination vector.
*/
void getRightVector(Vec3 *dst) const;
/**
* Gets the forward vector of this matrix.
*
* @param dst The destination vector.
*/
void getForwardVector(Vec3 *dst) const;
/**
* Gets the backward vector of this matrix.
*
* @param dst The destination vector.
*/
void getBackVector(Vec3 *dst) const;
/**
* Inverts this matrix.
*
* @return true if the matrix can be inverted, false otherwise.
*/
bool inverse();
/**
* Clone this matrix.
*
* @return a new clone matrix.
*/
Mat4 clone() const;
/**
* Get the inversed matrix.
*/
Mat4 getInversed() const;
/**
* Determines if this matrix is equal to the identity matrix.
*
* @return true if the matrix is an identity matrix, false otherwise.
*/
bool isIdentity() const;
/**
* Multiplies the components of this matrix by the specified scalar.
*
* @param scalar The scalar value.
*/
void multiply(float scalar);
/**
* Multiplies the components of this matrix by a scalar and stores the result in dst.
*
* @param scalar The scalar value.
* @param dst A matrix to store the result in.
*/
void multiply(float scalar, Mat4 *dst) const;
/**
* Multiplies the components of the specified matrix by a scalar and stores the result in dst.
*
* @param mat The matrix.
* @param scalar The scalar value.
* @param dst A matrix to store the result in.
*/
static void multiply(const Mat4 &mat, float scalar, Mat4 *dst);
/**
* Multiplies this matrix by the specified one.
*
* @param mat The matrix to multiply.
*/
void multiply(const Mat4 &mat);
/**
* Multiplies m1 by m2 and stores the result in dst.
*
* @param m1 The first matrix to multiply.
* @param m2 The second matrix to multiply.
* @param dst A matrix to store the result in.
*/
static void multiply(const Mat4 &m1, const Mat4 &m2, Mat4 *dst);
/**
* Negates this matrix.
*/
void negate();
/**
Get the Negated matrix.
*/
Mat4 getNegated() const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified quaternion rotation.
*
* @param q The quaternion to rotate by.
*/
void rotate(const Quaternion &q);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified quaternion rotation and stores the result in dst.
*
* @param q The quaternion to rotate by.
* @param dst A matrix to store the result in.
*/
void rotate(const Quaternion &q, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation about the specified axis.
*
* @param axis The axis to rotate about.
* @param angle The angle (in radians).
*/
void rotate(const Vec3 &axis, float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the specified
* rotation about the specified axis and stores the result in dst.
*
* @param axis The axis to rotate about.
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotate(const Vec3 &axis, float angle, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the x-axis.
*
* @param angle The angle (in radians).
*/
void rotateX(float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the x-axis and stores the result in dst.
*
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotateX(float angle, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the y-axis.
*
* @param angle The angle (in radians).
*/
void rotateY(float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the y-axis and stores the result in dst.
*
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotateY(float angle, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the z-axis.
*
* @param angle The angle (in radians).
*/
void rotateZ(float angle);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified rotation around the z-axis and stores the result in dst.
*
* @param angle The angle (in radians).
* @param dst A matrix to store the result in.
*/
void rotateZ(float angle, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation.
*
* @param value The amount to scale along all axes.
*/
void scale(float value);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation and stores the result in dst.
*
* @param value The amount to scale along all axes.
* @param dst A matrix to store the result in.
*/
void scale(float value, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
*/
void scale(float xScale, float yScale, float zScale);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation and stores the result in dst.
*
* @param xScale The amount to scale along the x-axis.
* @param yScale The amount to scale along the y-axis.
* @param zScale The amount to scale along the z-axis.
* @param dst A matrix to store the result in.
*/
void scale(float xScale, float yScale, float zScale, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation.
*
* @param s The scale values along the x, y and z axes.
*/
void scale(const Vec3 &s);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified scale transformation and stores the result in dst.
*
* @param s The scale values along the x, y and z axes.
* @param dst A matrix to store the result in.
*/
void scale(const Vec3 &s, Mat4 *dst) const;
/**
* Sets the values of this matrix.
*
* @param m00 Component in column 0, row 0 position (index 0)
* @param m01 Component in column 0, row 1 position (index 1)
* @param m02 Component in column 0, row 2 position (index 2)
* @param m03 Component in column 0, row 3 position (index 3)
* @param m10 Component in column 1, row 0 position (index 4)
* @param m11 Component in column 1, row 1 position (index 5)
* @param m12 Component in column 1, row 2 position (index 6)
* @param m13 Component in column 1, row 3 position (index 7)
* @param m20 Component in column 2, row 0 position (index 8)
* @param m21 Component in column 2, row 1 position (index 9)
* @param m22 Component in column 2, row 2 position (index 10)
* @param m23 Component in column 2, row 3 position (index 11)
* @param m30 Component in column 3, row 0 position (index 12)
* @param m31 Component in column 3, row 1 position (index 13)
* @param m32 Component in column 3, row 2 position (index 14)
* @param m33 Component in column 3, row 3 position (index 15)
*/
void set(float m00, float m01, float m02, float m03,
float m10, float m11, float m12, float m13,
float m20, float m21, float m22, float m23,
float m30, float m31, float m32, float m33);
/**
* Sets the values of this matrix to those in the specified column-major array.
*
* @param mat An array containing 16 elements in column-major format.
*/
void set(const float *mat);
/**
* Sets the values of this matrix to those of the specified matrix.
*
* @param mat The source matrix.
*/
void set(const Mat4 &mat);
/**
* Sets this matrix to the identity matrix.
*/
void setIdentity();
/**
* Sets all elements of the current matrix to zero.
*/
void setZero();
/**
* Subtracts the specified matrix from the current matrix.
*
* @param mat The matrix to subtract.
*/
void subtract(const Mat4 &mat);
/**
* Subtracts the specified matrix from the current matrix.
*
* @param m1 The first matrix.
* @param m2 The second matrix.
* @param dst A matrix to store the result in.
*/
static void subtract(const Mat4 &m1, const Mat4 &m2, Mat4 *dst);
/**
* Transforms the specified vector by this matrix.
*
* The result of the transformation is stored directly into vector.
*
* @param vector The vector to transform.
*/
void transformVector(Vec4 *vector) const;
/**
* Transforms the specified vector by this matrix.
*
* @param vector The vector to transform.
* @param dst A vector to store the transformed point in.
*/
void transformVector(const Vec4 &vector, Vec4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation.
*
* @param x The amount to translate along the x-axis.
* @param y The amount to translate along the y-axis.
* @param z The amount to translate along the z-axis.
*/
void translate(float x, float y, float z);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation and stores the result in dst.
*
* @param x The amount to translate along the x-axis.
* @param y The amount to translate along the y-axis.
* @param z The amount to translate along the z-axis.
* @param dst A matrix to store the result in.
*/
void translate(float x, float y, float z, Mat4 *dst) const;
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation.
*
* @param t The translation values along the x, y and z axes.
*/
void translate(const Vec3 &t);
/**
* Post-multiplies this matrix by the matrix corresponding to the
* specified translation and stores the result in dst.
*
* @param t The translation values along the x, y and z axes.
* @param dst A matrix to store the result in.
*/
void translate(const Vec3 &t, Mat4 *dst) const;
/**
* Transposes this matrix.
*/
void transpose();
/**
* Get the Transposed matrix.
*/
Mat4 getTransposed() const;
/**
* Calculates the inverse transpose of a matrix and save the results to out matrix
*/
static void inverseTranspose(const Mat4 &mat, Mat4 *dst);
/**
* Calculates the sum of this matrix with the given matrix.
*
* Note: this does not modify this matrix.
*
* @param mat The matrix to add.
* @return The matrix sum.
*/
inline const Mat4 operator+(const Mat4 &mat) const;
/**
* Adds the given matrix to this matrix.
*
* @param mat The matrix to add.
* @return This matrix, after the addition occurs.
*/
inline Mat4 &operator+=(const Mat4 &mat);
/**
* Calculates the difference of this matrix with the given matrix.
*
* Note: this does not modify this matrix.
*
* @param mat The matrix to subtract.
* @return The matrix difference.
*/
inline const Mat4 operator-(const Mat4 &mat) const;
/**
* Subtracts the given matrix from this matrix.
*
* @param mat The matrix to subtract.
* @return This matrix, after the subtraction occurs.
*/
inline Mat4 &operator-=(const Mat4 &mat);
/**
* Calculates the negation of this matrix.
*
* Note: this does not modify this matrix.
*
* @return The negation of this matrix.
*/
inline const Mat4 operator-() const;
/**
* Calculates the matrix product of this matrix with the given matrix.
*
* Note: this does not modify this matrix.
*
* @param mat The matrix to multiply by.
* @return The matrix product.
*/
inline const Mat4 operator*(const Mat4 &mat) const;
/**
* Right-multiplies this matrix by the given matrix.
*
* @param mat The matrix to multiply by.
* @return This matrix, after the multiplication occurs.
*/
inline Mat4 &operator*=(const Mat4 &mat);
/**
* Determines if this matrix is approximately equal to the given matrix.
*/
bool approxEquals(const Mat4 &v, float precision = CC_FLOAT_CMP_PRECISION) const;
/** equals to a matrix full of zeros */
static const Mat4 ZERO;
/** equals to the identity matrix */
static const Mat4 IDENTITY;
private:
static void createBillboardHelper(const Vec3 &objectPosition, const Vec3 &cameraPosition,
const Vec3 &cameraUpVector, const Vec3 *cameraForwardVector,
Mat4 *dst);
};
/**
* Transforms the given vector by the given matrix.
*
* Note: this treats the given vector as a vector and not as a point.
*
* @param v The vector to transform.
* @param m The matrix to transform by.
* @return This vector, after the transformation occurs.
*/
inline Vec4 &operator*=(Vec4 &v, const Mat4 &m);
/**
* Transforms the given vector by the given matrix.
*
* Note: this treats the given vector as a vector and not as a point.
*
* @param m The matrix to transform by.
* @param v The vector to transform.
* @return The resulting transformed vector.
*/
inline const Vec4 operator*(const Mat4 &m, const Vec4 &v);
NS_CC_MATH_END
/**
end of base group
@}
*/
#include "math/Mat4.inl"

86
cocos/math/Mat4.inl Normal file
View File

@@ -0,0 +1,86 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Mat4.h"
NS_CC_MATH_BEGIN
inline const Mat4 Mat4::operator+(const Mat4& mat) const
{
Mat4 result(*this);
result.add(mat);
return result;
}
inline Mat4& Mat4::operator+=(const Mat4& mat)
{
add(mat);
return *this;
}
inline const Mat4 Mat4::operator-(const Mat4& mat) const
{
Mat4 result(*this);
result.subtract(mat);
return result;
}
inline Mat4& Mat4::operator-=(const Mat4& mat)
{
subtract(mat);
return *this;
}
inline const Mat4 Mat4::operator-() const
{
Mat4 mat(*this);
mat.negate();
return mat;
}
inline const Mat4 Mat4::operator*(const Mat4& mat) const
{
Mat4 result(*this);
result.multiply(mat);
return result;
}
inline Mat4& Mat4::operator*=(const Mat4& mat)
{
multiply(mat);
return *this;
}
inline Vec4& operator*=(Vec4& v, const Mat4& m)
{
m.transformVector(&v);
return v;
}
inline const Vec4 operator*(const Mat4& m, const Vec4& v)
{
Vec4 x;
m.transformVector(v, &x);
return x;
}
NS_CC_MATH_END

60
cocos/math/Math.cpp Normal file
View File

@@ -0,0 +1,60 @@
/****************************************************************************
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 "math/Math.h"
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstring>
namespace cc {
namespace math {
const float PI = static_cast<float>(3.14159265358979323846264338327950288419716939937511);
const float PI_2 = math::PI * 2.0F;
const float PI_DIV2 = math::PI * 0.5F;
const float PI_DIV3 = math::PI / 3.0F;
const float PI_DIV4 = math::PI / 4.0F;
const float PI_DIV5 = math::PI / 5.0F;
const float PI_DIV6 = math::PI / 6.0F;
const float PI_DIV8 = math::PI / 8.0F;
const float PI_SQR = static_cast<float>(9.86960440108935861883449099987615113531369940724079);
const float PI_INV = static_cast<float>(0.31830988618379067153776752674502872406891929148091);
const float EPSILON = std::numeric_limits<float>::epsilon();
const float LOW_EPSILON = static_cast<float>(1e-04);
const float POS_INFINITY = std::numeric_limits<float>::infinity();
const float NEG_INFINITY = -std::numeric_limits<float>::infinity();
const float LN2 = std::log(2.0F);
const float LN10 = std::log(10.0F);
const float LN2_INV = 1.0F / LN2;
const float LN10_INV = 1.0F / LN10;
const float DEG_TO_RAD = static_cast<float>(0.01745329);
const float RAD_TO_DEG = static_cast<float>(57.29577);
const float MIN_FLOAT = 1.175494351e-38F;
const float MAX_FLOAT = 3.402823466e+38F;
} // namespace math
} // namespace cc

83
cocos/math/Math.h Normal file
View File

@@ -0,0 +1,83 @@
/****************************************************************************
Copyright (c) 2017-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 <cmath>
#include <cstdint>
#include "base/Macros.h"
namespace cc {
namespace math {
extern CC_DLL const float PI;
extern CC_DLL const float PI_2;
extern CC_DLL const float PI_DIV2;
extern CC_DLL const float PI_DIV3;
extern CC_DLL const float PI_DIV4;
extern CC_DLL const float PI_DIV5;
extern CC_DLL const float PI_DIV6;
extern CC_DLL const float PI_DIV8;
extern CC_DLL const float PI_SQR;
extern CC_DLL const float PI_INV;
extern CC_DLL const float EPSILON;
extern CC_DLL const float LOW_EPSILON;
extern CC_DLL const float POS_INFINITY;
extern CC_DLL const float NEG_INFINITY;
extern CC_DLL const float LN2;
extern CC_DLL const float LN10;
extern CC_DLL const float LN2_INV;
extern CC_DLL const float LN10_INV;
extern CC_DLL const float DEG_TO_RAD;
extern CC_DLL const float RAD_TO_DEG;
extern CC_DLL const float MIN_FLOAT;
extern CC_DLL const float MAX_FLOAT;
#define CC_FLOAT_CMP_PRECISION (0.00001F)
template <typename T>
inline T sgn(T x) {
return (x < T(0) ? T(-1) : (x > T(0) ? T(1) : T(0)));
}
template <typename T>
inline bool isPowerOfTwo(T n) {
return (n & (n - 1)) == 0;
}
inline bool isEqualF(float lhs, float rhs, float precision = 0.000001F) {
const bool hasInf = std::isinf(lhs) || std::isinf(rhs);
return !hasInf && (std::fabs(lhs - rhs) <= (std::fmax(std::fmax(std::fabs(lhs), std::fabs(rhs)), 1.0F) * precision));
}
inline bool isNotEqualF(float lhs, float rhs, float precision = 0.000001F) { // same as !isEqualF
const bool hasInf = std::isinf(lhs) || std::isinf(rhs);
return hasInf || (std::fabs(lhs - rhs) > (std::fmax(std::fmax(std::fabs(lhs), std::fabs(rhs)), 1.0F) * precision));
}
inline bool isNotZeroF(float v, float precision = 0.000001F) { // same as isNotEqualF(v, 0.0F)
return std::isinf(v) || (std::fabs(v) > (std::fmax(std::fabs(v), 1.0F) * precision));
}
} // namespace math
} // namespace cc

102
cocos/math/MathBase.h Normal file
View File

@@ -0,0 +1,102 @@
/****************************************************************************
Copyright (c) 2017-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.
****************************************************************************/
#ifndef __CCMATHBASE_H__
#define __CCMATHBASE_H__
#include <memory>
#include "base/Macros.h"
#if CC_PLATFORM != CC_PLATFORM_EMSCRIPTEN
#include "base/std/hash/hash.h"
#endif
/**
* @addtogroup base
* @{
*/
/**Util macro for conversion from degrees to radians.*/
#define MATH_DEG_TO_RAD(x) ((x)*0.0174532925f)
/**Util macro for conversion from radians to degrees.*/
#define MATH_RAD_TO_DEG(x) ((x)*57.29577951f)
/**
@{ Util macro for const float such as epsilon, small float and float precision tolerance.
*/
#define MATH_FLOAT_SMALL 1.0e-37f
#define MATH_TOLERANCE 2e-37f
#define MATH_PIOVER2 1.57079632679489661923f
#define MATH_EPSILON 0.000001f
/**@}*/
//#define MATH_PIOVER4 0.785398163397448309616f
//#define MATH_PIX2 6.28318530717958647693f
//#define MATH_E 2.71828182845904523536f
//#define MATH_LOG10E 0.4342944819032518f
//#define MATH_LOG2E 1.442695040888963387f
//#define MATH_PI 3.14159265358979323846f
//#define MATH_RANDOM_MINUS1_1() ((2.0f*((float)rand()/RAND_MAX))-1.0f) // Returns a random float between -1 and 1.
//#define MATH_RANDOM_0_1() ((float)rand()/RAND_MAX) // Returns a random float between 0 and 1.
//#define MATH_CLAMP(x, lo, hi) ((x < lo) ? lo : ((x > hi) ? hi : x))
//#ifndef M_1_PI
//#define M_1_PI 0.31830988618379067154
#ifdef __cplusplus
#define NS_CC_MATH_BEGIN namespace cc {
#define NS_CC_MATH_END }
#define USING_NS_CC_MATH using namespace cc
#else
#define NS_CC_MATH_BEGIN
#define NS_CC_MATH_END
#define USING_NS_CC_MATH
#endif
NS_CC_MATH_BEGIN
#if CC_PLATFORM != CC_PLATFORM_EMSCRIPTEN
template <typename T, typename Enable = std::enable_if_t<std::is_class<T>::value>>
struct Hasher final {
// NOTE: ccstd::hash_t is a typedef of uint32_t now, sizeof(ccstd::hash_t) == sizeof(size_t) on 32 bits architecture device,
// sizeof(ccstd::hash_t) < sizeof(size_t) on 64 bits architecture device.
// STL containers like ccstd::unordered_map<K, V, Hasher> expects the custom Hasher function to return size_t.
// So it's safe to return ccstd::hash_t for operator() function now.
// If we need to define ccstd::hash_t to uint64_t someday, we must take care of the return value of operator(),
// it should be size_t and we need to convert hash value from uint64_t to uint32_t for 32 bit architecture device.
ccstd::hash_t operator()(const T &info) const;
};
// make this ccstd::hash compatible
template <typename T, typename Enable = std::enable_if_t<std::is_class<T>::value>>
ccstd::hash_t hash_value(const T &info) { return Hasher<T>()(info); } // NOLINT(readability-identifier-naming)
#endif // CC_PLATFORM != CC_PLATFORM_EMSCRIPTEN
NS_CC_MATH_END
/**
* end of base group
* @}
*/
#endif // __CCMATHBASE_H__

286
cocos/math/MathUtil.cpp Normal file
View File

@@ -0,0 +1,286 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/MathUtil.h"
#include "base/Macros.h"
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
#include <cpu-features.h>
#endif
//#define USE_NEON32 : neon 32 code will be used
//#define USE_NEON64 : neon 64 code will be used
//#define INCLUDE_NEON32 : neon 32 code included
//#define INCLUDE_NEON64 : neon 64 code included
//#define USE_SSE : SSE code used
//#define INCLUDE_SSE : SSE code included
#if (CC_PLATFORM == CC_PLATFORM_IOS)
#if defined(__arm64__)
#define USE_NEON64
#define INCLUDE_NEON64
#endif
#elif (CC_PLATFORM == CC_PLATFORM_ANDROID)
#if defined(__arm64__) || defined(__aarch64__)
#define USE_NEON64
#define INCLUDE_NEON64
#elif defined(__ARM_NEON__)
#define INCLUDE_NEON32
#endif
#endif
#if defined(__SSE__)
#define USE_SSE
#define INCLUDE_SSE
#endif
#ifdef INCLUDE_NEON32
#include "math/MathUtilNeon.inl"
#endif
#ifdef INCLUDE_NEON64
#include "math/MathUtilNeon64.inl"
#endif
#ifdef INCLUDE_SSE
#include "math/MathUtilSSE.inl"
#endif
#include <cstring>
#include "math/MathUtil.inl"
NS_CC_MATH_BEGIN
void MathUtil::smooth(float *x, float target, float elapsedTime, float responseTime) {
CC_ASSERT(x);
if (elapsedTime > 0) {
*x += (target - *x) * elapsedTime / (elapsedTime + responseTime);
}
}
void MathUtil::smooth(float *x, float target, float elapsedTime, float riseTime, float fallTime) {
CC_ASSERT(x);
if (elapsedTime > 0) {
float delta = target - *x;
*x += delta * elapsedTime / (elapsedTime + (delta > 0 ? riseTime : fallTime));
}
}
float MathUtil::lerp(float from, float to, float alpha) {
return from * (1.0F - alpha) + to * alpha;
}
bool MathUtil::isNeon32Enabled() {
#ifdef USE_NEON32
return true;
#elif (defined(INCLUDE_NEON32) && (CC_PLATFORM == CC_PLATFORM_ANDROID))
class AndroidNeonChecker {
public:
AndroidNeonChecker() {
_isNeonEnabled = (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0);
}
bool isNeonEnabled() const { return _isNeonEnabled; }
private:
bool _isNeonEnabled;
};
static AndroidNeonChecker checker;
return checker.isNeonEnabled();
#else
return false;
#endif
}
bool MathUtil::isNeon64Enabled() {
#ifdef USE_NEON64
return true;
#else
return false;
#endif
}
void MathUtil::addMatrix(const float *m, float scalar, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::addMatrix(m, scalar, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::addMatrix(m, scalar, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::addMatrix(m, scalar, dst);
} else {
MathUtilC::addMatrix(m, scalar, dst);
}
#else
MathUtilC::addMatrix(m, scalar, dst);
#endif
}
void MathUtil::addMatrix(const float *m1, const float *m2, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::addMatrix(m1, m2, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::addMatrix(m1, m2, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::addMatrix(m1, m2, dst);
} else {
MathUtilC::addMatrix(m1, m2, dst);
}
#else
MathUtilC::addMatrix(m1, m2, dst);
#endif
}
void MathUtil::subtractMatrix(const float *m1, const float *m2, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::subtractMatrix(m1, m2, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::subtractMatrix(m1, m2, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::subtractMatrix(m1, m2, dst);
} else {
MathUtilC::subtractMatrix(m1, m2, dst);
}
#else
MathUtilC::subtractMatrix(m1, m2, dst);
#endif
}
void MathUtil::multiplyMatrix(const float *m, float scalar, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::multiplyMatrix(m, scalar, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::multiplyMatrix(m, scalar, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::multiplyMatrix(m, scalar, dst);
} else {
MathUtilC::multiplyMatrix(m, scalar, dst);
}
#else
MathUtilC::multiplyMatrix(m, scalar, dst);
#endif
}
void MathUtil::multiplyMatrix(const float *m1, const float *m2, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::multiplyMatrix(m1, m2, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::multiplyMatrix(m1, m2, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::multiplyMatrix(m1, m2, dst);
} else {
MathUtilC::multiplyMatrix(m1, m2, dst);
}
#else
MathUtilC::multiplyMatrix(m1, m2, dst);
#endif
}
void MathUtil::negateMatrix(const float *m, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::negateMatrix(m, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::negateMatrix(m, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::negateMatrix(m, dst);
} else {
MathUtilC::negateMatrix(m, dst);
}
#else
MathUtilC::negateMatrix(m, dst);
#endif
}
void MathUtil::transposeMatrix(const float *m, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::transposeMatrix(m, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::transposeMatrix(m, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::transposeMatrix(m, dst);
} else {
MathUtilC::transposeMatrix(m, dst);
}
#else
MathUtilC::transposeMatrix(m, dst);
#endif
}
void MathUtil::transformVec4(const float *m, float x, float y, float z, float w, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::transformVec4(m, x, y, z, w, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::transformVec4(m, x, y, z, w, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::transformVec4(m, x, y, z, w, dst);
} else {
MathUtilC::transformVec4(m, x, y, z, w, dst);
}
#else
MathUtilC::transformVec4(m, x, y, z, w, dst);
#endif
}
void MathUtil::transformVec4(const float *m, const float *v, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::transformVec4(m, v, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::transformVec4(m, v, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::transformVec4(m, v, dst);
} else {
MathUtilC::transformVec4(m, v, dst);
}
#else
MathUtilC::transformVec4(m, v, dst);
#endif
}
void MathUtil::crossVec3(const float *v1, const float *v2, float *dst) {
#ifdef USE_NEON32
MathUtilNeon::crossVec3(v1, v2, dst);
#elif defined(USE_NEON64)
MathUtilNeon64::crossVec3(v1, v2, dst);
#elif defined(INCLUDE_NEON32)
if (isNeon32Enabled()) {
MathUtilNeon::crossVec3(v1, v2, dst);
} else {
MathUtilC::crossVec3(v1, v2, dst);
}
#else
MathUtilC::crossVec3(v1, v2, dst);
#endif
}
void MathUtil::combineHash(size_t &seed, const size_t &v) {
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
NS_CC_MATH_END

149
cocos/math/MathUtil.h Normal file
View File

@@ -0,0 +1,149 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#ifndef MATHUTIL_H_
#define MATHUTIL_H_
#ifdef __SSE__
#include <xmmintrin.h>
#endif
#include "math/MathBase.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
/**
* Defines a math utility class.
*
* This is primarily used for optimized internal math operations.
*/
class CC_DLL MathUtil {
friend class Mat4;
friend class Vec3;
public:
/**
* Updates the given scalar towards the given target using a smoothing function.
* The given response time determines the amount of smoothing (lag). A longer
* response time yields a smoother result and more lag. To force the scalar to
* follow the target closely, provide a response time that is very small relative
* to the given elapsed time.
*
* @param x the scalar to update.
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param responseTime response time (in the same units as elapsedTime).
*/
static void smooth(float *x, float target, float elapsedTime, float responseTime);
/**
* Updates the given scalar towards the given target using a smoothing function.
* The given rise and fall times determine the amount of smoothing (lag). Longer
* rise and fall times yield a smoother result and more lag. To force the scalar to
* follow the target closely, provide rise and fall times that are very small relative
* to the given elapsed time.
*
* @param x the scalar to update.
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param riseTime response time for rising slope (in the same units as elapsedTime).
* @param fallTime response time for falling slope (in the same units as elapsedTime).
*/
static void smooth(float *x, float target, float elapsedTime, float riseTime, float fallTime);
/**
* Linearly interpolates between from value to to value by alpha which is in
* the range [0,1]
*
* @param from the from value.
* @param to the to value.
* @param alpha the alpha value between [0,1]
*
* @return interpolated float value
*/
static float lerp(float from, float to, float alpha);
/**
* Add hash_combine math according to:
* https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
* @param seed
* @param v
*/
static void combineHash(size_t &seed, const size_t &v);
private:
//Indicates that if neon is enabled
static bool isNeon32Enabled();
static bool isNeon64Enabled();
private:
#ifdef __SSE__
static void addMatrix(const __m128 m[4], float scalar, __m128 dst[4]);
static void addMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]);
static void subtractMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]);
static void multiplyMatrix(const __m128 m[4], float scalar, __m128 dst[4]);
static void multiplyMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4]);
static void negateMatrix(const __m128 m[4], __m128 dst[4]);
static void transposeMatrix(const __m128 m[4], __m128 dst[4]);
static void transformVec4(const __m128 m[4], const __m128 &v, __m128 &dst);
#endif
static void addMatrix(const float *m, float scalar, float *dst);
static void addMatrix(const float *m1, const float *m2, float *dst);
static void subtractMatrix(const float *m1, const float *m2, float *dst);
static void multiplyMatrix(const float *m, float scalar, float *dst);
static void multiplyMatrix(const float *m1, const float *m2, float *dst);
static void negateMatrix(const float *m, float *dst);
static void transposeMatrix(const float *m, float *dst);
static void transformVec4(const float *m, float x, float y, float z, float w, float *dst);
static void transformVec4(const float *m, const float *v, float *dst);
static void crossVec3(const float *v1, const float *v2, float *dst);
};
NS_CC_MATH_END
/**
end of base group
@}
*/
#define MATRIX_SIZE (sizeof(float) * 16)
#endif

220
cocos/math/MathUtil.inl Normal file
View File

@@ -0,0 +1,220 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
NS_CC_MATH_BEGIN
class MathUtilC
{
public:
inline static void addMatrix(const float* m, float scalar, float* dst);
inline static void addMatrix(const float* m1, const float* m2, float* dst);
inline static void subtractMatrix(const float* m1, const float* m2, float* dst);
inline static void multiplyMatrix(const float* m, float scalar, float* dst);
inline static void multiplyMatrix(const float* m1, const float* m2, float* dst);
inline static void negateMatrix(const float* m, float* dst);
inline static void transposeMatrix(const float* m, float* dst);
inline static void transformVec4(const float* m, float x, float y, float z, float w, float* dst);
inline static void transformVec4(const float* m, const float* v, float* dst);
inline static void crossVec3(const float* v1, const float* v2, float* dst);
};
inline void MathUtilC::addMatrix(const float* m, float scalar, float* dst)
{
dst[0] = m[0] + scalar;
dst[1] = m[1] + scalar;
dst[2] = m[2] + scalar;
dst[3] = m[3] + scalar;
dst[4] = m[4] + scalar;
dst[5] = m[5] + scalar;
dst[6] = m[6] + scalar;
dst[7] = m[7] + scalar;
dst[8] = m[8] + scalar;
dst[9] = m[9] + scalar;
dst[10] = m[10] + scalar;
dst[11] = m[11] + scalar;
dst[12] = m[12] + scalar;
dst[13] = m[13] + scalar;
dst[14] = m[14] + scalar;
dst[15] = m[15] + scalar;
}
inline void MathUtilC::addMatrix(const float* m1, const float* m2, float* dst)
{
dst[0] = m1[0] + m2[0];
dst[1] = m1[1] + m2[1];
dst[2] = m1[2] + m2[2];
dst[3] = m1[3] + m2[3];
dst[4] = m1[4] + m2[4];
dst[5] = m1[5] + m2[5];
dst[6] = m1[6] + m2[6];
dst[7] = m1[7] + m2[7];
dst[8] = m1[8] + m2[8];
dst[9] = m1[9] + m2[9];
dst[10] = m1[10] + m2[10];
dst[11] = m1[11] + m2[11];
dst[12] = m1[12] + m2[12];
dst[13] = m1[13] + m2[13];
dst[14] = m1[14] + m2[14];
dst[15] = m1[15] + m2[15];
}
inline void MathUtilC::subtractMatrix(const float* m1, const float* m2, float* dst)
{
dst[0] = m1[0] - m2[0];
dst[1] = m1[1] - m2[1];
dst[2] = m1[2] - m2[2];
dst[3] = m1[3] - m2[3];
dst[4] = m1[4] - m2[4];
dst[5] = m1[5] - m2[5];
dst[6] = m1[6] - m2[6];
dst[7] = m1[7] - m2[7];
dst[8] = m1[8] - m2[8];
dst[9] = m1[9] - m2[9];
dst[10] = m1[10] - m2[10];
dst[11] = m1[11] - m2[11];
dst[12] = m1[12] - m2[12];
dst[13] = m1[13] - m2[13];
dst[14] = m1[14] - m2[14];
dst[15] = m1[15] - m2[15];
}
inline void MathUtilC::multiplyMatrix(const float* m, float scalar, float* dst)
{
dst[0] = m[0] * scalar;
dst[1] = m[1] * scalar;
dst[2] = m[2] * scalar;
dst[3] = m[3] * scalar;
dst[4] = m[4] * scalar;
dst[5] = m[5] * scalar;
dst[6] = m[6] * scalar;
dst[7] = m[7] * scalar;
dst[8] = m[8] * scalar;
dst[9] = m[9] * scalar;
dst[10] = m[10] * scalar;
dst[11] = m[11] * scalar;
dst[12] = m[12] * scalar;
dst[13] = m[13] * scalar;
dst[14] = m[14] * scalar;
dst[15] = m[15] * scalar;
}
inline void MathUtilC::multiplyMatrix(const float* m1, const float* m2, float* dst)
{
// Support the case where m1 or m2 is the same array as dst.
float product[16];
product[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
product[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
product[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
product[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
product[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
product[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
product[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
product[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
product[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
product[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
product[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
product[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
product[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
product[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
product[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
product[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
memcpy(dst, product, MATRIX_SIZE);
}
inline void MathUtilC::negateMatrix(const float* m, float* dst)
{
dst[0] = -m[0];
dst[1] = -m[1];
dst[2] = -m[2];
dst[3] = -m[3];
dst[4] = -m[4];
dst[5] = -m[5];
dst[6] = -m[6];
dst[7] = -m[7];
dst[8] = -m[8];
dst[9] = -m[9];
dst[10] = -m[10];
dst[11] = -m[11];
dst[12] = -m[12];
dst[13] = -m[13];
dst[14] = -m[14];
dst[15] = -m[15];
}
inline void MathUtilC::transposeMatrix(const float* m, float* dst)
{
float t[16] = {
m[0], m[4], m[8], m[12],
m[1], m[5], m[9], m[13],
m[2], m[6], m[10], m[14],
m[3], m[7], m[11], m[15]
};
memcpy(dst, t, MATRIX_SIZE);}
inline void MathUtilC::transformVec4(const float* m, float x, float y, float z, float w, float* dst)
{
dst[0] = x * m[0] + y * m[4] + z * m[8] + w * m[12];
dst[1] = x * m[1] + y * m[5] + z * m[9] + w * m[13];
dst[2] = x * m[2] + y * m[6] + z * m[10] + w * m[14];
dst[3] = x * m[3] + y * m[7] + z * m[11] + w * m[15];
}
inline void MathUtilC::transformVec4(const float* m, const float* v, float* dst)
{
// Handle case where v == dst.
float x = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12];
float y = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13];
float z = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14];
float w = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15];
dst[0] = x;
dst[1] = y;
dst[2] = z;
dst[3] = w;
}
inline void MathUtilC::crossVec3(const float* v1, const float* v2, float* dst)
{
float x = (v1[1] * v2[2]) - (v1[2] * v2[1]);
float y = (v1[2] * v2[0]) - (v1[0] * v2[2]);
float z = (v1[0] * v2[1]) - (v1[1] * v2[0]);
dst[0] = x;
dst[1] = y;
dst[2] = z;
}
NS_CC_MATH_END

273
cocos/math/MathUtilNeon.inl Normal file
View File

@@ -0,0 +1,273 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
NS_CC_MATH_BEGIN
class MathUtilNeon
{
public:
inline static void addMatrix(const float* m, float scalar, float* dst);
inline static void addMatrix(const float* m1, const float* m2, float* dst);
inline static void subtractMatrix(const float* m1, const float* m2, float* dst);
inline static void multiplyMatrix(const float* m, float scalar, float* dst);
inline static void multiplyMatrix(const float* m1, const float* m2, float* dst);
inline static void negateMatrix(const float* m, float* dst);
inline static void transposeMatrix(const float* m, float* dst);
inline static void transformVec4(const float* m, float x, float y, float z, float w, float* dst);
inline static void transformVec4(const float* m, const float* v, float* dst);
inline static void crossVec3(const float* v1, const float* v2, float* dst);
};
inline void MathUtilNeon::addMatrix(const float* m, float scalar, float* dst)
{
asm volatile(
"vld1.32 {q0, q1}, [%1]! \n\t" // M[m0-m7]
"vld1.32 {q2, q3}, [%1] \n\t" // M[m8-m15]
"vld1.32 {d8[0]}, [%2] \n\t" // s
"vmov.f32 s17, s16 \n\t" // s
"vmov.f32 s18, s16 \n\t" // s
"vmov.f32 s19, s16 \n\t" // s
"vadd.f32 q8, q0, q4 \n\t" // DST->M[m0-m3] = M[m0-m3] + s
"vadd.f32 q9, q1, q4 \n\t" // DST->M[m4-m7] = M[m4-m7] + s
"vadd.f32 q10, q2, q4 \n\t" // DST->M[m8-m11] = M[m8-m11] + s
"vadd.f32 q11, q3, q4 \n\t" // DST->M[m12-m15] = M[m12-m15] + s
"vst1.32 {q8, q9}, [%0]! \n\t" // DST->M[m0-m7]
"vst1.32 {q10, q11}, [%0] \n\t" // DST->M[m8-m15]
:
: "r"(dst), "r"(m), "r"(&scalar)
: "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "memory"
);
}
inline void MathUtilNeon::addMatrix(const float* m1, const float* m2, float* dst)
{
asm volatile(
"vld1.32 {q0, q1}, [%1]! \n\t" // M1[m0-m7]
"vld1.32 {q2, q3}, [%1] \n\t" // M1[m8-m15]
"vld1.32 {q8, q9}, [%2]! \n\t" // M2[m0-m7]
"vld1.32 {q10, q11}, [%2] \n\t" // M2[m8-m15]
"vadd.f32 q12, q0, q8 \n\t" // DST->M[m0-m3] = M1[m0-m3] + M2[m0-m3]
"vadd.f32 q13, q1, q9 \n\t" // DST->M[m4-m7] = M1[m4-m7] + M2[m4-m7]
"vadd.f32 q14, q2, q10 \n\t" // DST->M[m8-m11] = M1[m8-m11] + M2[m8-m11]
"vadd.f32 q15, q3, q11 \n\t" // DST->M[m12-m15] = M1[m12-m15] + M2[m12-m15]
"vst1.32 {q12, q13}, [%0]! \n\t" // DST->M[m0-m7]
"vst1.32 {q14, q15}, [%0] \n\t" // DST->M[m8-m15]
:
: "r"(dst), "r"(m1), "r"(m2)
: "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"
);
}
inline void MathUtilNeon::subtractMatrix(const float* m1, const float* m2, float* dst)
{
asm volatile(
"vld1.32 {q0, q1}, [%1]! \n\t" // M1[m0-m7]
"vld1.32 {q2, q3}, [%1] \n\t" // M1[m8-m15]
"vld1.32 {q8, q9}, [%2]! \n\t" // M2[m0-m7]
"vld1.32 {q10, q11}, [%2] \n\t" // M2[m8-m15]
"vsub.f32 q12, q0, q8 \n\t" // DST->M[m0-m3] = M1[m0-m3] - M2[m0-m3]
"vsub.f32 q13, q1, q9 \n\t" // DST->M[m4-m7] = M1[m4-m7] - M2[m4-m7]
"vsub.f32 q14, q2, q10 \n\t" // DST->M[m8-m11] = M1[m8-m11] - M2[m8-m11]
"vsub.f32 q15, q3, q11 \n\t" // DST->M[m12-m15] = M1[m12-m15] - M2[m12-m15]
"vst1.32 {q12, q13}, [%0]! \n\t" // DST->M[m0-m7]
"vst1.32 {q14, q15}, [%0] \n\t" // DST->M[m8-m15]
:
: "r"(dst), "r"(m1), "r"(m2)
: "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"
);
}
inline void MathUtilNeon::multiplyMatrix(const float* m, float scalar, float* dst)
{
asm volatile(
"vld1.32 {d0[0]}, [%2] \n\t" // M[m0-m7]
"vld1.32 {q4-q5}, [%1]! \n\t" // M[m8-m15]
"vld1.32 {q6-q7}, [%1] \n\t" // s
"vmul.f32 q8, q4, d0[0] \n\t" // DST->M[m0-m3] = M[m0-m3] * s
"vmul.f32 q9, q5, d0[0] \n\t" // DST->M[m4-m7] = M[m4-m7] * s
"vmul.f32 q10, q6, d0[0] \n\t" // DST->M[m8-m11] = M[m8-m11] * s
"vmul.f32 q11, q7, d0[0] \n\t" // DST->M[m12-m15] = M[m12-m15] * s
"vst1.32 {q8-q9}, [%0]! \n\t" // DST->M[m0-m7]
"vst1.32 {q10-q11}, [%0] \n\t" // DST->M[m8-m15]
:
: "r"(dst), "r"(m), "r"(&scalar)
: "q0", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "memory"
);
}
inline void MathUtilNeon::multiplyMatrix(const float* m1, const float* m2, float* dst)
{
asm volatile(
"vld1.32 {d16 - d19}, [%1]! \n\t" // M1[m0-m7]
"vld1.32 {d20 - d23}, [%1] \n\t" // M1[m8-m15]
"vld1.32 {d0 - d3}, [%2]! \n\t" // M2[m0-m7]
"vld1.32 {d4 - d7}, [%2] \n\t" // M2[m8-m15]
"vmul.f32 q12, q8, d0[0] \n\t" // DST->M[m0-m3] = M1[m0-m3] * M2[m0]
"vmul.f32 q13, q8, d2[0] \n\t" // DST->M[m4-m7] = M1[m4-m7] * M2[m4]
"vmul.f32 q14, q8, d4[0] \n\t" // DST->M[m8-m11] = M1[m8-m11] * M2[m8]
"vmul.f32 q15, q8, d6[0] \n\t" // DST->M[m12-m15] = M1[m12-m15] * M2[m12]
"vmla.f32 q12, q9, d0[1] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m1]
"vmla.f32 q13, q9, d2[1] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m5]
"vmla.f32 q14, q9, d4[1] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m9]
"vmla.f32 q15, q9, d6[1] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m13]
"vmla.f32 q12, q10, d1[0] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m2]
"vmla.f32 q13, q10, d3[0] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m6]
"vmla.f32 q14, q10, d5[0] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m10]
"vmla.f32 q15, q10, d7[0] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m14]
"vmla.f32 q12, q11, d1[1] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m3]
"vmla.f32 q13, q11, d3[1] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m7]
"vmla.f32 q14, q11, d5[1] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m11]
"vmla.f32 q15, q11, d7[1] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m15]
"vst1.32 {d24 - d27}, [%0]! \n\t" // DST->M[m0-m7]
"vst1.32 {d28 - d31}, [%0] \n\t" // DST->M[m8-m15]
: // output
: "r"(dst), "r"(m1), "r"(m2) // input - note *value* of pointer doesn't change.
: "memory", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
);
}
inline void MathUtilNeon::negateMatrix(const float* m, float* dst)
{
asm volatile(
"vld1.32 {q0-q1}, [%1]! \n\t" // load m0-m7
"vld1.32 {q2-q3}, [%1] \n\t" // load m8-m15
"vneg.f32 q4, q0 \n\t" // negate m0-m3
"vneg.f32 q5, q1 \n\t" // negate m4-m7
"vneg.f32 q6, q2 \n\t" // negate m8-m15
"vneg.f32 q7, q3 \n\t" // negate m8-m15
"vst1.32 {q4-q5}, [%0]! \n\t" // store m0-m7
"vst1.32 {q6-q7}, [%0] \n\t" // store m8-m15
:
: "r"(dst), "r"(m)
: "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "memory"
);
}
inline void MathUtilNeon::transposeMatrix(const float* m, float* dst)
{
asm volatile(
"vld4.32 {d0[0], d2[0], d4[0], d6[0]}, [%1]! \n\t" // DST->M[m0, m4, m8, m12] = M[m0-m3]
"vld4.32 {d0[1], d2[1], d4[1], d6[1]}, [%1]! \n\t" // DST->M[m1, m5, m9, m12] = M[m4-m7]
"vld4.32 {d1[0], d3[0], d5[0], d7[0]}, [%1]! \n\t" // DST->M[m2, m6, m10, m12] = M[m8-m11]
"vld4.32 {d1[1], d3[1], d5[1], d7[1]}, [%1] \n\t" // DST->M[m3, m7, m11, m12] = M[m12-m15]
"vst1.32 {q0-q1}, [%0]! \n\t" // DST->M[m0-m7]
"vst1.32 {q2-q3}, [%0] \n\t" // DST->M[m8-m15]
:
: "r"(dst), "r"(m)
: "q0", "q1", "q2", "q3", "memory"
);
}
inline void MathUtilNeon::transformVec4(const float* m, float x, float y, float z, float w, float* dst)
{
asm volatile(
"vld1.32 {d0[0]}, [%1] \n\t" // V[x]
"vld1.32 {d0[1]}, [%2] \n\t" // V[y]
"vld1.32 {d1[0]}, [%3] \n\t" // V[z]
"vld1.32 {d1[1]}, [%4] \n\t" // V[w]
"vld1.32 {d18 - d21}, [%5]! \n\t" // M[m0-m7]
"vld1.32 {d22 - d25}, [%5] \n\t" // M[m8-m15]
"vmul.f32 q13, q9, d0[0] \n\t" // DST->V = M[m0-m3] * V[x]
"vmla.f32 q13, q10, d0[1] \n\t" // DST->V += M[m4-m7] * V[y]
"vmla.f32 q13, q11, d1[0] \n\t" // DST->V += M[m8-m11] * V[z]
"vmla.f32 q13, q12, d1[1] \n\t" // DST->V += M[m12-m15] * V[w]
"vst1.32 {d26}, [%0]! \n\t" // DST->V[x, y]
"vst1.32 {d27[0]}, [%0] \n\t" // DST->V[z]
:
: "r"(dst), "r"(&x), "r"(&y), "r"(&z), "r"(&w), "r"(m)
: "q0", "q9", "q10","q11", "q12", "q13", "memory"
);
}
inline void MathUtilNeon::transformVec4(const float* m, const float* v, float* dst)
{
asm volatile
(
"vld1.32 {d0, d1}, [%1] \n\t" // V[x, y, z, w]
"vld1.32 {d18 - d21}, [%2]! \n\t" // M[m0-m7]
"vld1.32 {d22 - d25}, [%2] \n\t" // M[m8-m15]
"vmul.f32 q13, q9, d0[0] \n\t" // DST->V = M[m0-m3] * V[x]
"vmla.f32 q13, q10, d0[1] \n\t" // DST->V = M[m4-m7] * V[y]
"vmla.f32 q13, q11, d1[0] \n\t" // DST->V = M[m8-m11] * V[z]
"vmla.f32 q13, q12, d1[1] \n\t" // DST->V = M[m12-m15] * V[w]
"vst1.32 {d26, d27}, [%0] \n\t" // DST->V
:
: "r"(dst), "r"(v), "r"(m)
: "q0", "q9", "q10","q11", "q12", "q13", "memory"
);
}
inline void MathUtilNeon::crossVec3(const float* v1, const float* v2, float* dst)
{
asm volatile(
"vld1.32 {d1[1]}, [%1] \n\t" //
"vld1.32 {d0}, [%2] \n\t" //
"vmov.f32 s2, s1 \n\t" // q0 = (v1y, v1z, v1z, v1x)
"vld1.32 {d2[1]}, [%3] \n\t" //
"vld1.32 {d3}, [%4] \n\t" //
"vmov.f32 s4, s7 \n\t" // q1 = (v2z, v2x, v2y, v2z)
"vmul.f32 d4, d0, d2 \n\t" // x = v1y * v2z, y = v1z * v2x
"vmls.f32 d4, d1, d3 \n\t" // x -= v1z * v2y, y-= v1x - v2z
"vmul.f32 d5, d3, d1[1] \n\t" // z = v1x * v2y
"vmls.f32 d5, d0, d2[1] \n\t" // z-= v1y * vx
"vst1.32 {d4}, [%0]! \n\t" // V[x, y]
"vst1.32 {d5[0]}, [%0] \n\t" // V[z]
:
: "r"(dst), "r"(v1), "r"((v1+1)), "r"(v2), "r"((v2+1))
: "q0", "q1", "q2", "memory"
);
}
NS_CC_MATH_END

View File

@@ -0,0 +1,265 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
NS_CC_MATH_BEGIN
class MathUtilNeon64
{
public:
inline static void addMatrix(const float* m, float scalar, float* dst);
inline static void addMatrix(const float* m1, const float* m2, float* dst);
inline static void subtractMatrix(const float* m1, const float* m2, float* dst);
inline static void multiplyMatrix(const float* m, float scalar, float* dst);
inline static void multiplyMatrix(const float* m1, const float* m2, float* dst);
inline static void negateMatrix(const float* m, float* dst);
inline static void transposeMatrix(const float* m, float* dst);
inline static void transformVec4(const float* m, float x, float y, float z, float w, float* dst);
inline static void transformVec4(const float* m, const float* v, float* dst);
inline static void crossVec3(const float* v1, const float* v2, float* dst);
};
inline void MathUtilNeon64::addMatrix(const float* m, float scalar, float* dst)
{
asm volatile(
"ld4 {v0.4s, v1.4s, v2.4s, v3.4s}, [%1] \n\t" // M[m0-m7] M[m8-m15]
"ld1r {v4.4s}, [%2] \n\t" //ssss
"fadd v8.4s, v0.4s, v4.4s \n\t" // DST->M[m0-m3] = M[m0-m3] + s
"fadd v9.4s, v1.4s, v4.4s \n\t" // DST->M[m4-m7] = M[m4-m7] + s
"fadd v10.4s, v2.4s, v4.4s \n\t" // DST->M[m8-m11] = M[m8-m11] + s
"fadd v11.4s, v3.4s, v4.4s \n\t" // DST->M[m12-m15] = M[m12-m15] + s
"st4 {v8.4s, v9.4s, v10.4s, v11.4s}, [%0] \n\t" // Result in V9
:
: "r"(dst), "r"(m), "r"(&scalar)
: "v0", "v1", "v2", "v3", "v4", "v8", "v9", "v10", "v11", "memory"
);
}
inline void MathUtilNeon64::addMatrix(const float* m1, const float* m2, float* dst)
{
asm volatile(
"ld4 {v0.4s, v1.4s, v2.4s, v3.4s}, [%1] \n\t" // M1[m0-m7] M1[m8-m15]
"ld4 {v8.4s, v9.4s, v10.4s, v11.4s}, [%2] \n\t" // M2[m0-m7] M2[m8-m15]
"fadd v12.4s, v0.4s, v8.4s \n\t" // DST->M[m0-m3] = M1[m0-m3] + M2[m0-m3]
"fadd v13.4s, v1.4s, v9.4s \n\t" // DST->M[m4-m7] = M1[m4-m7] + M2[m4-m7]
"fadd v14.4s, v2.4s, v10.4s \n\t" // DST->M[m8-m11] = M1[m8-m11] + M2[m8-m11]
"fadd v15.4s, v3.4s, v11.4s \n\t" // DST->M[m12-m15] = M1[m12-m15] + M2[m12-m15]
"st4 {v12.4s, v13.4s, v14.4s, v15.4s}, [%0] \n\t" // DST->M[m0-m7] DST->M[m8-m15]
:
: "r"(dst), "r"(m1), "r"(m2)
: "v0", "v1", "v2", "v3", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "memory"
);
}
inline void MathUtilNeon64::subtractMatrix(const float* m1, const float* m2, float* dst)
{
asm volatile(
"ld4 {v0.4s, v1.4s, v2.4s, v3.4s}, [%1] \n\t" // M1[m0-m7] M1[m8-m15]
"ld4 {v8.4s, v9.4s, v10.4s, v11.4s}, [%2] \n\t" // M2[m0-m7] M2[m8-m15]
"fsub v12.4s, v0.4s, v8.4s \n\t" // DST->M[m0-m3] = M1[m0-m3] - M2[m0-m3]
"fsub v13.4s, v1.4s, v9.4s \n\t" // DST->M[m4-m7] = M1[m4-m7] - M2[m4-m7]
"fsub v14.4s, v2.4s, v10.4s \n\t" // DST->M[m8-m11] = M1[m8-m11] - M2[m8-m11]
"fsub v15.4s, v3.4s, v11.4s \n\t" // DST->M[m12-m15] = M1[m12-m15] - M2[m12-m15]
"st4 {v12.4s, v13.4s, v14.4s, v15.4s}, [%0] \n\t" // DST->M[m0-m7] DST->M[m8-m15]
:
: "r"(dst), "r"(m1), "r"(m2)
: "v0", "v1", "v2", "v3", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", "memory"
);
}
inline void MathUtilNeon64::multiplyMatrix(const float* m, float scalar, float* dst)
{
asm volatile(
"ld1 {v0.s}[0], [%2] \n\t" //s
"ld4 {v4.4s, v5.4s, v6.4s, v7.4s}, [%1] \n\t" //M[m0-m7] M[m8-m15]
"fmul v8.4s, v4.4s, v0.s[0] \n\t" // DST->M[m0-m3] = M[m0-m3] * s
"fmul v9.4s, v5.4s, v0.s[0] \n\t" // DST->M[m4-m7] = M[m4-m7] * s
"fmul v10.4s, v6.4s, v0.s[0] \n\t" // DST->M[m8-m11] = M[m8-m11] * s
"fmul v11.4s, v7.4s, v0.s[0] \n\t" // DST->M[m12-m15] = M[m12-m15] * s
"st4 {v8.4s, v9.4s, v10.4s, v11.4s}, [%0] \n\t" // DST->M[m0-m7] DST->M[m8-m15]
:
: "r"(dst), "r"(m), "r"(&scalar)
: "v0", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "memory"
);
}
inline void MathUtilNeon64::multiplyMatrix(const float* m1, const float* m2, float* dst)
{
asm volatile(
"ld1 {v8.4s, v9.4s, v10.4s, v11.4s}, [%1] \n\t" // M1[m0-m7] M1[m8-m15] M2[m0-m7] M2[m8-m15]
"ld4 {v0.4s, v1.4s, v2.4s, v3.4s}, [%2] \n\t" // M2[m0-m15]
"fmul v12.4s, v8.4s, v0.s[0] \n\t" // DST->M[m0-m3] = M1[m0-m3] * M2[m0]
"fmul v13.4s, v8.4s, v0.s[1] \n\t" // DST->M[m4-m7] = M1[m4-m7] * M2[m4]
"fmul v14.4s, v8.4s, v0.s[2] \n\t" // DST->M[m8-m11] = M1[m8-m11] * M2[m8]
"fmul v15.4s, v8.4s, v0.s[3] \n\t" // DST->M[m12-m15] = M1[m12-m15] * M2[m12]
"fmla v12.4s, v9.4s, v1.s[0] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m1]
"fmla v13.4s, v9.4s, v1.s[1] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m5]
"fmla v14.4s, v9.4s, v1.s[2] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m9]
"fmla v15.4s, v9.4s, v1.s[3] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m13]
"fmla v12.4s, v10.4s, v2.s[0] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m2]
"fmla v13.4s, v10.4s, v2.s[1] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m6]
"fmla v14.4s, v10.4s, v2.s[2] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m10]
"fmla v15.4s, v10.4s, v2.s[3] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m14]
"fmla v12.4s, v11.4s, v3.s[0] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m3]
"fmla v13.4s, v11.4s, v3.s[1] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m7]
"fmla v14.4s, v11.4s, v3.s[2] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m11]
"fmla v15.4s, v11.4s, v3.s[3] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m15]
"st1 {v12.4s, v13.4s, v14.4s, v15.4s}, [%0] \n\t" // DST->M[m0-m7]// DST->M[m8-m15]
: // output
: "r"(dst), "r"(m1), "r"(m2) // input - note *value* of pointer doesn't change.
: "memory", "v0", "v1", "v2", "v3", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
);
}
inline void MathUtilNeon64::negateMatrix(const float* m, float* dst)
{
asm volatile(
"ld4 {v0.4s, v1.4s, v2.4s, v3.4s}, [%1] \n\t" // load m0-m7 load m8-m15
"fneg v4.4s, v0.4s \n\t" // negate m0-m3
"fneg v5.4s, v1.4s \n\t" // negate m4-m7
"fneg v6.4s, v2.4s \n\t" // negate m8-m15
"fneg v7.4s, v3.4s \n\t" // negate m8-m15
"st4 {v4.4s, v5.4s, v6.4s, v7.4s}, [%0] \n\t" // store m0-m7 store m8-m15
:
: "r"(dst), "r"(m)
: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "memory"
);
}
inline void MathUtilNeon64::transposeMatrix(const float* m, float* dst)
{
asm volatile(
"ld4 {v0.4s, v1.4s, v2.4s, v3.4s}, [%1] \n\t" // DST->M[m0, m4, m8, m12] = M[m0-m3]
//DST->M[m1, m5, m9, m12] = M[m4-m7]
"st1 {v0.4s, v1.4s, v2.4s, v3.4s}, [%0] \n\t"
:
: "r"(dst), "r"(m)
: "v0", "v1", "v2", "v3", "memory"
);
}
inline void MathUtilNeon64::transformVec4(const float* m, float x, float y, float z, float w, float* dst)
{
asm volatile(
"ld1 {v0.s}[0], [%1] \n\t" // V[x]
"ld1 {v0.s}[1], [%2] \n\t" // V[y]
"ld1 {v0.s}[2], [%3] \n\t" // V[z]
"ld1 {v0.s}[3], [%4] \n\t" // V[w]
"ld1 {v9.4s, v10.4s, v11.4s, v12.4s}, [%5] \n\t" // M[m0-m7] M[m8-m15]
"fmul v13.4s, v9.4s, v0.s[0] \n\t" // DST->V = M[m0-m3] * V[x]
"fmla v13.4s, v10.4s, v0.s[1] \n\t" // DST->V += M[m4-m7] * V[y]
"fmla v13.4s, v11.4s, v0.s[2] \n\t" // DST->V += M[m8-m11] * V[z]
"fmla v13.4s, v12.4s, v0.s[3] \n\t" // DST->V += M[m12-m15] * V[w]
"st1 {v13.4s}, [%0] \n\t" // DST->V
:
: "r"(dst), "r"(&x), "r"(&y), "r"(&z), "r"(&w), "r"(m)
: "v0", "v9", "v10","v11", "v12", "v13", "memory"
);
}
inline void MathUtilNeon64::transformVec4(const float* m, const float* v, float* dst)
{
asm volatile
(
"ld1 {v0.4s}, [%1] \n\t" // V[x, y, z, w]
"ld1 {v9.4s, v10.4s, v11.4s, v12.4s}, [%2] \n\t" // M[m0-m7] M[m8-m15]
"fmul v13.4s, v9.4s, v0.s[0] \n\t" // DST->V = M[m0-m3] * V[x]
"fmla v13.4s, v10.4s, v0.s[1] \n\t" // DST->V = M[m4-m7] * V[y]
"fmla v13.4s, v11.4s, v0.s[2] \n\t" // DST->V = M[m8-m11] * V[z]
"fmla v13.4s, v12.4s, v0.s[3] \n\t" // DST->V = M[m12-m15] * V[w]
"st1 {v13.4s}, [%0] \n\t" // DST->V
:
: "r"(dst), "r"(v), "r"(m)
: "v0", "v9", "v10","v11", "v12", "v13", "memory"
);
}
inline void MathUtilNeon64::crossVec3(const float* v1, const float* v2, float* dst)
{
asm volatile(
"ld1 {v0.2s}, [%2] \n\t"
"ld1 {v0.s}[2], [%1] \n\t"
"mov v0.s[3], v0.s[0] \n\t" // q0 = (v1y, v1z, v1x, v1x)
"ld1 {v1.4s}, [%3] \n\t"
"mov v1.s[3], v1.s[0] \n\t" // q1 = (v2x, v2y, v2z, v2x)
"fmul v2.4s, v0.4s, v1.4s \n\t" // x = v1y * v2z, y = v1z * v2x
"mov v0.s[0], v0.s[1] \n\t"
"mov v0.s[1], v0.s[2] \n\t"
"mov v0.s[2], v0.s[3] \n\t"
"mov v1.s[3], v1.s[2] \n\t"
"fmul v0.4s, v0.4s, v1.4s \n\t"
"mov v0.s[3], v0.s[1] \n\t"
"mov v0.s[1], v0.s[2] \n\t"
"mov v0.s[2], v0.s[0] \n\t"
"fsub v2.4s, v0.4s, v2.4s \n\t"
"mov v2.s[0], v2.s[1] \n\t"
"mov v2.s[1], v2.s[2] \n\t"
"mov v2.s[2], v2.s[3] \n\t"
"st1 {v2.2s}, [%0], 8 \n\t" // V[x, y]
"st1 {v2.s}[2], [%0] \n\t" // V[z]
:
: "r"(dst), "r"(v1), "r"((v1+1)), "r"(v2), "r"((v2+1))
: "v0", "v1", "v2", "memory"
);
}
NS_CC_MATH_END

179
cocos/math/MathUtilSSE.inl Normal file
View File

@@ -0,0 +1,179 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
NS_CC_MATH_BEGIN
#ifdef __SSE__
void MathUtil::addMatrix(const __m128 m[4], float scalar, __m128 dst[4])
{
__m128 s = _mm_set1_ps(scalar);
dst[0] = _mm_add_ps(m[0], s);
dst[1] = _mm_add_ps(m[1], s);
dst[2] = _mm_add_ps(m[2], s);
dst[3] = _mm_add_ps(m[3], s);
}
void MathUtil::addMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4])
{
dst[0] = _mm_add_ps(m1[0], m2[0]);
dst[1] = _mm_add_ps(m1[1], m2[1]);
dst[2] = _mm_add_ps(m1[2], m2[2]);
dst[3] = _mm_add_ps(m1[3], m2[3]);
}
void MathUtil::subtractMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4])
{
dst[0] = _mm_sub_ps(m1[0], m2[0]);
dst[1] = _mm_sub_ps(m1[1], m2[1]);
dst[2] = _mm_sub_ps(m1[2], m2[2]);
dst[3] = _mm_sub_ps(m1[3], m2[3]);
}
void MathUtil::multiplyMatrix(const __m128 m[4], float scalar, __m128 dst[4])
{
__m128 s = _mm_set1_ps(scalar);
dst[0] = _mm_mul_ps(m[0], s);
dst[1] = _mm_mul_ps(m[1], s);
dst[2] = _mm_mul_ps(m[2], s);
dst[3] = _mm_mul_ps(m[3], s);
}
void MathUtil::multiplyMatrix(const __m128 m1[4], const __m128 m2[4], __m128 dst[4])
{
__m128 dst0, dst1, dst2, dst3;
{
__m128 e0 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(0, 0, 0, 0));
__m128 e1 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(1, 1, 1, 1));
__m128 e2 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(2, 2, 2, 2));
__m128 e3 = _mm_shuffle_ps(m2[0], m2[0], _MM_SHUFFLE(3, 3, 3, 3));
__m128 v0 = _mm_mul_ps(m1[0], e0);
__m128 v1 = _mm_mul_ps(m1[1], e1);
__m128 v2 = _mm_mul_ps(m1[2], e2);
__m128 v3 = _mm_mul_ps(m1[3], e3);
__m128 a0 = _mm_add_ps(v0, v1);
__m128 a1 = _mm_add_ps(v2, v3);
__m128 a2 = _mm_add_ps(a0, a1);
dst0 = a2;
}
{
__m128 e0 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(0, 0, 0, 0));
__m128 e1 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(1, 1, 1, 1));
__m128 e2 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(2, 2, 2, 2));
__m128 e3 = _mm_shuffle_ps(m2[1], m2[1], _MM_SHUFFLE(3, 3, 3, 3));
__m128 v0 = _mm_mul_ps(m1[0], e0);
__m128 v1 = _mm_mul_ps(m1[1], e1);
__m128 v2 = _mm_mul_ps(m1[2], e2);
__m128 v3 = _mm_mul_ps(m1[3], e3);
__m128 a0 = _mm_add_ps(v0, v1);
__m128 a1 = _mm_add_ps(v2, v3);
__m128 a2 = _mm_add_ps(a0, a1);
dst1 = a2;
}
{
__m128 e0 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(0, 0, 0, 0));
__m128 e1 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(1, 1, 1, 1));
__m128 e2 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(2, 2, 2, 2));
__m128 e3 = _mm_shuffle_ps(m2[2], m2[2], _MM_SHUFFLE(3, 3, 3, 3));
__m128 v0 = _mm_mul_ps(m1[0], e0);
__m128 v1 = _mm_mul_ps(m1[1], e1);
__m128 v2 = _mm_mul_ps(m1[2], e2);
__m128 v3 = _mm_mul_ps(m1[3], e3);
__m128 a0 = _mm_add_ps(v0, v1);
__m128 a1 = _mm_add_ps(v2, v3);
__m128 a2 = _mm_add_ps(a0, a1);
dst2 = a2;
}
{
__m128 e0 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(0, 0, 0, 0));
__m128 e1 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(1, 1, 1, 1));
__m128 e2 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(2, 2, 2, 2));
__m128 e3 = _mm_shuffle_ps(m2[3], m2[3], _MM_SHUFFLE(3, 3, 3, 3));
__m128 v0 = _mm_mul_ps(m1[0], e0);
__m128 v1 = _mm_mul_ps(m1[1], e1);
__m128 v2 = _mm_mul_ps(m1[2], e2);
__m128 v3 = _mm_mul_ps(m1[3], e3);
__m128 a0 = _mm_add_ps(v0, v1);
__m128 a1 = _mm_add_ps(v2, v3);
__m128 a2 = _mm_add_ps(a0, a1);
dst3 = a2;
}
dst[0] = dst0;
dst[1] = dst1;
dst[2] = dst2;
dst[3] = dst3;
}
void MathUtil::negateMatrix(const __m128 m[4], __m128 dst[4])
{
__m128 z = _mm_setzero_ps();
dst[0] = _mm_sub_ps(z, m[0]);
dst[1] = _mm_sub_ps(z, m[1]);
dst[2] = _mm_sub_ps(z, m[2]);
dst[3] = _mm_sub_ps(z, m[3]);
}
void MathUtil::transposeMatrix(const __m128 m[4], __m128 dst[4])
{
__m128 tmp0 = _mm_shuffle_ps(m[0], m[1], 0x44);
__m128 tmp2 = _mm_shuffle_ps(m[0], m[1], 0xEE);
__m128 tmp1 = _mm_shuffle_ps(m[2], m[3], 0x44);
__m128 tmp3 = _mm_shuffle_ps(m[2], m[3], 0xEE);
dst[0] = _mm_shuffle_ps(tmp0, tmp1, 0x88);
dst[1] = _mm_shuffle_ps(tmp0, tmp1, 0xDD);
dst[2] = _mm_shuffle_ps(tmp2, tmp3, 0x88);
dst[3] = _mm_shuffle_ps(tmp2, tmp3, 0xDD);
}
void MathUtil::transformVec4(const __m128 m[4], const __m128& v, __m128& dst)
{
__m128 col1 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
__m128 col2 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
__m128 col3 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
__m128 col4 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3));
dst = _mm_add_ps(
_mm_add_ps(_mm_mul_ps(m[0], col1), _mm_mul_ps(m[1], col2)),
_mm_add_ps(_mm_mul_ps(m[2], col3), _mm_mul_ps(m[3], col4))
);
}
#endif
NS_CC_MATH_END

585
cocos/math/Quaternion.cpp Normal file
View File

@@ -0,0 +1,585 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Quaternion.h"
#include <cmath>
#include <cstring>
#include "base/Macros.h"
#include "math/Mat3.h"
#include "math/Math.h"
#include "math/Utils.h"
NS_CC_MATH_BEGIN
const Quaternion Quaternion::ZERO(0.F, 0.F, 0.F, 0.F);
Quaternion::Quaternion(float xx, float yy, float zz, float ww)
: x(xx),
y(yy),
z(zz),
w(ww) {
}
Quaternion::Quaternion(float *array) {
set(array);
}
Quaternion::Quaternion(const Mat4 &m) {
set(m);
}
Quaternion::Quaternion(const Vec3 &axis, float angle) {
set(axis, angle);
}
const Quaternion &Quaternion::identity() {
static Quaternion value(0.F, 0.F, 0.F, 1.F);
return value;
}
const Quaternion &Quaternion::zero() {
static Quaternion value(0.F, 0.F, 0.F, 0.F);
return value;
}
bool Quaternion::isIdentity() const {
return x == 0.F && y == 0.F && z == 0.F && w == 1.F;
}
bool Quaternion::isZero() const {
return x == 0.F && y == 0.F && z == 0.F && w == 0.F;
}
void Quaternion::createFromRotationMatrix(const Mat4 &m, Quaternion *dst) {
m.getRotation(dst);
}
void Quaternion::createFromAxisAngle(const Vec3 &axis, float angle, Quaternion *dst) {
CC_ASSERT(dst);
float halfAngle = angle * 0.5F;
float sinHalfAngle = sinf(halfAngle);
Vec3 normal(axis);
normal.normalize();
dst->x = normal.x * sinHalfAngle;
dst->y = normal.y * sinHalfAngle;
dst->z = normal.z * sinHalfAngle;
dst->w = cosf(halfAngle);
}
void Quaternion::createFromAngleZ(float z, Quaternion *dst) {
CC_ASSERT(dst);
z *= mathutils::HALF_TO_RAD;
dst->x = dst->y = 0.F;
dst->z = sinf(z);
dst->w = cosf(z);
}
void Quaternion::conjugate() {
x = -x;
y = -y;
z = -z;
}
Quaternion Quaternion::getConjugated() const {
Quaternion q(*this);
q.conjugate();
return q;
}
void Quaternion::inverse() {
float dot = x * x + y * y + z * z + w * w;
float invDot = dot > 0.F ? 1.F / dot : 0.F;
x = -x * invDot;
y = -y * invDot;
z = -z * invDot;
w = w * invDot;
}
Quaternion Quaternion::getInversed() const {
Quaternion q(*this);
q.inverse();
return q;
}
void Quaternion::multiply(const Quaternion &q) {
multiply(*this, q, this);
}
void Quaternion::multiply(const Quaternion &q1, const Quaternion &q2, Quaternion *dst) {
CC_ASSERT(dst);
float x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
float y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
float z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
float w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
dst->x = x;
dst->y = y;
dst->z = z;
dst->w = w;
}
void Quaternion::normalize() {
float len = x * x + y * y + z * z + w * w;
if (len > 0.F) {
len = 1.F / sqrt(len);
x *= len;
y *= len;
z *= len;
w *= len;
} else {
x = 0.F;
y = 0.F;
z = 0.F;
w = 0.F;
}
}
Quaternion Quaternion::getNormalized() const {
Quaternion q(*this);
q.normalize();
return q;
}
void Quaternion::set(float xx, float yy, float zz, float ww) {
this->x = xx;
this->y = yy;
this->z = zz;
this->w = ww;
}
void Quaternion::set(const float *array) {
CC_ASSERT(array);
x = array[0];
y = array[1];
z = array[2];
w = array[3];
}
void Quaternion::set(const Mat4 &m) {
Quaternion::createFromRotationMatrix(m, this);
}
void Quaternion::set(const Vec3 &axis, float angle) {
Quaternion::createFromAxisAngle(axis, angle, this);
}
void Quaternion::set(const Quaternion &q) {
this->x = q.x;
this->y = q.y;
this->z = q.z;
this->w = q.w;
}
void Quaternion::setIdentity() {
x = 0.F;
y = 0.F;
z = 0.F;
w = 1.F;
}
float Quaternion::toAxisAngle(Vec3 *axis) const {
CC_ASSERT(axis);
Quaternion q(x, y, z, w);
q.normalize();
axis->x = q.x;
axis->y = q.y;
axis->z = q.z;
axis->normalize();
return (2.F * std::acos(q.w));
}
void Quaternion::lerp(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst) {
CC_ASSERT(dst);
CC_ASSERT(!(t < 0.F || t > 1.F));
float t1 = 1.F - t;
dst->x = t1 * q1.x + t * q2.x;
dst->y = t1 * q1.y + t * q2.y;
dst->z = t1 * q1.z + t * q2.z;
dst->w = t1 * q1.w + t * q2.w;
}
void Quaternion::slerp(const Quaternion &a, const Quaternion &b, float t, Quaternion *dst) {
// benchmarks: http://jsperf.com/quaternion-slerp-implementations
float scale0 = 0;
float scale1 = 0;
float bx = b.x;
float by = b.y;
float bz = b.z;
float bw = b.w;
// calc cosine
float cosom = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
// adjust signs (if necessary)
if (cosom < 0.F) {
cosom = -cosom;
bx = -bx;
by = -by;
bz = -bz;
bw = -bw;
}
// calculate coefficients
if ((1.F - cosom) > 0.000001F) {
// standard case (slerp)
const float omega = acos(cosom);
const float sinom = sinf(omega);
scale0 = sinf((1.0F - t) * omega) / sinom;
scale1 = sinf(t * omega) / sinom;
} else {
// "from" and "to" quaternions are very close
// ... so we can do a linear interpolation
scale0 = 1.0F - t;
scale1 = t;
}
// calculate final values
dst->x = scale0 * a.x + scale1 * bx;
dst->y = scale0 * a.y + scale1 * by;
dst->z = scale0 * a.z + scale1 * bz;
dst->w = scale0 * a.w + scale1 * bw;
}
void Quaternion::sqlerp(const Quaternion &a, const Quaternion &b, const Quaternion &c, const Quaternion &d, float t, Quaternion *dst) {
Quaternion q1(0.F, 0.F, 0.F, 1.F);
Quaternion q2(0.F, 0.F, 0.F, 1.F);
slerp(a, d, t, &q1);
slerp(b, c, t, &q2);
slerp(q1, q2, 2.F * t * (1.F - t), dst);
}
void Quaternion::squad(const Quaternion &q1, const Quaternion &q2, const Quaternion &s1, const Quaternion &s2, float t, Quaternion *dst) {
CC_ASSERT(!(t < 0.F || t > 1.F));
Quaternion dstQ(0.F, 0.F, 0.F, 1.F);
Quaternion dstS(0.F, 0.F, 0.F, 1.F);
slerpForSquad(q1, q2, t, &dstQ);
slerpForSquad(s1, s2, t, &dstS);
slerpForSquad(dstQ, dstS, 2.F * t * (1.F - t), dst);
}
float Quaternion::angle(const Quaternion &a, const Quaternion &b) {
const auto dot = std::min(std::abs(Quaternion::dot(a, b)), 1.0F);
return std::acos(dot) * 2.0F;
}
void Quaternion::rotateTowards(const Quaternion &from, const Quaternion &to, float maxStep, Quaternion *dst) {
const auto angle = Quaternion::angle(from, to);
if (angle == 0.0F) {
dst->set(to);
return;
}
const auto t = std::min(maxStep / (angle * 180.F / math::PI), 1.0F);
Quaternion::slerp(from, to, t, dst);
}
void Quaternion::fromViewUp(const Vec3 &view, Quaternion *out) {
CC_ASSERT(out);
fromViewUp(view, Vec3(0, 1, 0), out);
}
void Quaternion::fromViewUp(const Vec3 &view, const Vec3 &up, Quaternion *out) {
CC_ASSERT(out);
Mat3 mTemp{Mat3::IDENTITY};
Mat3::fromViewUp(view, up, &mTemp);
Quaternion::fromMat3(mTemp, out);
out->normalize();
}
void Quaternion::fromEuler(float x, float y, float z, Quaternion *dst) {
CC_ASSERT(dst);
float halfToRad = 0.5F * cc::math::PI / 180.F;
x *= halfToRad;
y *= halfToRad;
z *= halfToRad;
float sx = std::sin(x);
float cx = std::cos(x);
float sy = std::sin(y);
float cy = std::cos(y);
float sz = std::sin(z);
float cz = std::cos(z);
dst->x = sx * cy * cz + cx * sy * sz;
dst->y = cx * sy * cz + sx * cy * sz;
dst->z = cx * cy * sz - sx * sy * cz;
dst->w = cx * cy * cz - sx * sy * sz;
}
void Quaternion::toEuler(const Quaternion &q, bool outerZ, Vec3 *out) {
CC_ASSERT(out);
float x{q.x};
float y{q.y};
float z{q.z};
float w{q.w};
float bank{0};
float heading{0};
float attitude{0};
float test = x * y + z * w;
float r2d = 180.F / math::PI;
if (test > 0.499999) {
bank = 0;
heading = 2 * atan2(x, w) * r2d;
attitude = 90;
} else if (test < -0.499999) {
bank = 0;
heading = -2 * atan2(x, w) * r2d;
attitude = -90;
} else {
float sqx = x * x;
float sqy = y * y;
float sqz = z * z;
bank = atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz) * r2d;
heading = atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz) * r2d;
attitude = asin(2 * test) * r2d;
if (outerZ) {
bank = static_cast<float>(-180.F * math::sgn(bank + 1e-6) + bank);
heading = static_cast<float>(-180.F * math::sgn(heading + 1e-6) + heading);
attitude = static_cast<float>(180.F * math::sgn(attitude + 1e-6) - attitude);
}
}
out->x = bank;
out->y = heading;
out->z = attitude;
}
void Quaternion::fromMat3(const Mat3 &m, Quaternion *out) {
CC_ASSERT(out);
float m00 = m.m[0];
float m01 = m.m[1];
float m02 = m.m[2];
float m10 = m.m[3];
float m11 = m.m[4];
float m12 = m.m[5];
float m20 = m.m[6];
float m21 = m.m[7];
float m22 = m.m[8];
float fourXSquaredMinus1 = m00 - m11 - m22;
float fourYSquaredMinus1 = m11 - m00 - m22;
float fourZSquaredMinus1 = m22 - m00 - m11;
float fourWSquaredMinus1 = m00 + m11 + m22;
int biggestIndex = 0;
float fourBiggestSquaredMinus1 = fourWSquaredMinus1;
if (fourXSquaredMinus1 > fourBiggestSquaredMinus1) {
fourBiggestSquaredMinus1 = fourXSquaredMinus1;
biggestIndex = 1;
}
if (fourYSquaredMinus1 > fourBiggestSquaredMinus1) {
fourBiggestSquaredMinus1 = fourYSquaredMinus1;
biggestIndex = 2;
}
if (fourZSquaredMinus1 > fourBiggestSquaredMinus1) {
fourBiggestSquaredMinus1 = fourZSquaredMinus1;
biggestIndex = 3;
}
float biggestVal = std::sqrt(fourBiggestSquaredMinus1 + 1) * 0.5F;
float mult = 0.25F / biggestVal;
switch (biggestIndex) {
case 0:
out->w = biggestVal;
out->x = (m12 - m21) * mult;
out->y = (m20 - m02) * mult;
out->z = (m01 - m10) * mult;
break;
case 1:
out->w = (m12 - m21) * mult;
out->x = biggestVal;
out->y = (m01 + m10) * mult;
out->z = (m20 + m02) * mult;
break;
case 2:
out->w = (m20 - m02) * mult;
out->x = (m01 + m10) * mult;
out->y = biggestVal;
out->z = (m12 + m21) * mult;
break;
case 3:
out->w = (m01 - m10) * mult;
out->x = (m20 + m02) * mult;
out->y = (m12 + m21) * mult;
out->z = biggestVal;
break;
default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity.
CC_ASSERT(false);
out->w = 1.F;
out->x = 0.F;
out->y = 0.F;
out->z = 0.F;
break;
}
}
void Quaternion::slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float *dstx, float *dsty, float *dstz, float *dstw) {
// Fast slerp implementation by kwhatmough:
// It contains no division operations, no trig, no inverse trig
// and no sqrt. Not only does this code tolerate small constraint
// errors in the input quaternions, it actually corrects for them.
CC_ASSERT(dstx && dsty && dstz && dstw);
CC_ASSERT(!(t < 0.F || t > 1.F));
if (t == 0.F) {
*dstx = q1x;
*dsty = q1y;
*dstz = q1z;
*dstw = q1w;
return;
}
if (t == 1.F) {
*dstx = q2x;
*dsty = q2y;
*dstz = q2z;
*dstw = q2w;
return;
}
if (q1x == q2x && q1y == q2y && q1z == q2z && q1w == q2w) {
*dstx = q1x;
*dsty = q1y;
*dstz = q1z;
*dstw = q1w;
return;
}
float halfY;
float alpha;
float beta;
float u;
float f1;
float f2a;
float f2b;
float ratio1;
float ratio2;
float halfSecHalfTheta;
float versHalfTheta;
float sqNotU;
float sqU;
float cosTheta = q1w * q2w + q1x * q2x + q1y * q2y + q1z * q2z;
// As usual in all slerp implementations, we fold theta.
alpha = cosTheta >= 0 ? 1.F : -1.F;
halfY = 1.F + alpha * cosTheta;
// Here we bisect the interval, so we need to fold t as well.
f2b = t - 0.5F;
u = f2b >= 0 ? f2b : -f2b;
f2a = u - f2b;
f2b += u;
u += u;
f1 = 1.F - u;
// One iteration of Newton to get 1-cos(theta / 2) to good accuracy.
halfSecHalfTheta = 1.09F - (0.476537F - 0.0903321F * halfY) * halfY;
halfSecHalfTheta *= 1.5F - halfY * halfSecHalfTheta * halfSecHalfTheta;
versHalfTheta = 1.F - halfY * halfSecHalfTheta;
// Evaluate series expansions of the coefficients.
sqNotU = f1 * f1;
ratio2 = 0.0000440917108F * versHalfTheta;
ratio1 = -0.00158730159F + (sqNotU - 16.F) * ratio2;
ratio1 = 0.0333333333F + ratio1 * (sqNotU - 9.F) * versHalfTheta;
ratio1 = -0.333333333F + ratio1 * (sqNotU - 4.F) * versHalfTheta;
ratio1 = 1.F + ratio1 * (sqNotU - 1.F) * versHalfTheta;
sqU = u * u;
ratio2 = -0.00158730159F + (sqU - 16.F) * ratio2;
ratio2 = 0.0333333333F + ratio2 * (sqU - 9.F) * versHalfTheta;
ratio2 = -0.333333333F + ratio2 * (sqU - 4.F) * versHalfTheta;
ratio2 = 1.F + ratio2 * (sqU - 1.F) * versHalfTheta;
// Perform the bisection and resolve the folding done earlier.
f1 *= ratio1 * halfSecHalfTheta;
f2a *= ratio2;
f2b *= ratio2;
alpha *= f1 + f2a;
beta = f1 + f2b;
// Apply final coefficients to a and b as usual.
float w = alpha * q1w + beta * q2w;
float x = alpha * q1x + beta * q2x;
float y = alpha * q1y + beta * q2y;
float z = alpha * q1z + beta * q2z;
// This final adjustment to the quaternion's length corrects for
// any small constraint error in the inputs q1 and q2 But as you
// can see, it comes at the cost of 9 additional multiplication
// operations. If this error-correcting feature is not required,
// the following code may be removed.
f1 = 1.5F - 0.5F * (w * w + x * x + y * y + z * z);
*dstw = w * f1;
*dstx = x * f1;
*dsty = y * f1;
*dstz = z * f1;
}
void Quaternion::slerpForSquad(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst) {
CC_ASSERT(dst);
// cos(omega) = q1 * q2;
// slerp(q1, q2, t) = (q1*sin((1-t)*omega) + q2*sin(t*omega))/sin(omega);
// q1 = +- q2, slerp(q1,q2,t) = q1.
// This is a straight-forward implementation of the formula of slerp. It does not do any sign switching.
float c = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
if (std::abs(c) >= 1.F) {
dst->x = q1.x;
dst->y = q1.y;
dst->z = q1.z;
dst->w = q1.w;
return;
}
float omega = std::acos(c);
float s = std::sqrt(1.F - c * c);
if (std::abs(s) <= 0.00001F) {
dst->x = q1.x;
dst->y = q1.y;
dst->z = q1.z;
dst->w = q1.w;
return;
}
float r1 = std::sin((1 - t) * omega) / s;
float r2 = std::sin(t * omega) / s;
dst->x = (q1.x * r1 + q2.x * r2);
dst->y = (q1.y * r1 + q2.y * r2);
dst->z = (q1.z * r1 + q2.z * r2);
dst->w = (q1.w * r1 + q2.w * r2);
}
NS_CC_MATH_END

479
cocos/math/Quaternion.h Normal file
View File

@@ -0,0 +1,479 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#pragma once
#include "math/Mat4.h"
#include "math/Vec3.h"
//#include "Plane.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
class Mat4;
class Mat3;
/**
* Defines a 4-element quaternion that represents the orientation of an object in space.
*
* Quaternions are typically used as a replacement for Euler angles and rotation matrices as a way to achieve smooth interpolation and avoid gimbal lock.
*
* Note that this quaternion class does not automatically keep the quaternion normalized. Therefore, care must be taken to normalize the quaternion when necessary, by calling the normalize method.
* This class provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
*
* lerp (linear interpolation): the interpolation curve gives a straight line in quaternion space. It is simple and fast to compute. The only problem is that it does not provide constant angular velocity. Note that a constant velocity is not necessarily a requirement for a curve;
* slerp (spherical linear interpolation): the interpolation curve forms a great arc on the quaternion unit sphere. Slerp provides constant angular velocity;
* squad (spherical spline interpolation): interpolating between a series of rotations using slerp leads to the following problems:
* - the curve is not smooth at the control points;
* - the angular velocity is not constant;
* - the angular velocity is not continuous at the control points.
*
* Since squad is continuously differentiable, it remedies the first and third problems mentioned above.
* The slerp method provided here is intended for interpolation of principal rotations. It treats +q and -q as the same principal rotation and is at liberty to use the negative of either input. The resulting path is always the shorter arc.
*
* The lerp method provided here interpolates strictly in quaternion space. Note that the resulting path may pass through the origin if interpolating between a quaternion and its exact negative.
*
* As an example, consider the following quaternions:
*
* q1 = (0.6, 0.8, 0.0, 0.0),
* q2 = (0.0, 0.6, 0.8, 0.0),
* q3 = (0.6, 0.0, 0.8, 0.0), and
* q4 = (-0.8, 0.0, -0.6, 0.0).
* For the point p = (1.0, 1.0, 1.0), the following figures show the trajectories of p using lerp, slerp, and squad.
*/
class CC_DLL Quaternion {
public:
/**
* The x-value of the quaternion's vector component.
*/
float x{0.0F};
/**
* The y-value of the quaternion's vector component.
*/
float y{0.0F};
/**
* The z-value of the quaternion's vector component.
*/
float z{0.0F};
/**
* The scalar component of the quaternion.
*/
float w{1.0F};
/**
* Constructs a quaternion initialized to (0, 0, 0, 1).
*/
Quaternion() = default;
/**
* Constructs a quaternion.
*
* @param xx The x component of the quaternion.
* @param yy The y component of the quaternion.
* @param zz The z component of the quaternion.
* @param ww The w component of the quaternion.
*/
Quaternion(float xx, float yy, float zz, float ww);
/**
* Constructs a new quaternion from the values in the specified array.
*
* @param array The values for the new quaternion.
*/
explicit Quaternion(float *array);
/**
* Constructs a quaternion equal to the rotational part of the specified matrix.
*
* @param m The matrix.
*/
explicit Quaternion(const Mat4 &m);
/**
* Constructs a quaternion equal to the rotation from the specified axis and angle.
*
* @param axis A vector describing the axis of rotation.
* @param angle The angle of rotation (in radians).
*/
Quaternion(const Vec3 &axis, float angle);
/**
* Returns the identity quaternion.
*
* @return The identity quaternion.
*/
static const Quaternion &identity();
/**
* Returns the quaternion with all zeros.
*
* @return The quaternion.
*/
static const Quaternion &zero();
/**
* Determines if this quaternion is equal to the identity quaternion.
*
* @return true if it is the identity quaternion, false otherwise.
*/
bool isIdentity() const;
/**
* Determines if this quaternion is all zeros.
*
* @return true if this quaternion is all zeros, false otherwise.
*/
bool isZero() const;
/**
* Calculates the quaternion with Euler angles, the rotation order is YZX
*/
static void fromEuler(float x, float y, float z, Quaternion *dst);
/**
* Converts the quaternion to angles, result angle x, y in the range of [-180, 180], z in the range of [-90, 90] interval, the rotation order is YZX
*/
static void toEuler(const Quaternion &q, bool outerZ, Vec3 *out);
/**
* Creates a quaternion equal to the rotational part of the specified matrix
* and stores the result in dst.
*
* @param m The matrix.
* @param dst A quaternion to store the conjugate in.
*/
static void createFromRotationMatrix(const Mat4 &m, Quaternion *dst);
/**
* Creates this quaternion equal to the rotation from the specified axis and angle
* and stores the result in dst.
*
* @param axis A vector describing the axis of rotation.
* @param angle The angle of rotation (in radians).
* @param dst A quaternion to store the conjugate in.
*/
static void createFromAxisAngle(const Vec3 &axis, float angle, Quaternion *dst);
/**
* @en Calculates the quaternion with given 2D angle (0, 0, z).
* @zh 根据 2D 角度0, 0, z计算四元数
*
* @param out Output quaternion
* @param z Angle to rotate around Z axis in degrees.
*/
static void createFromAngleZ(float z, Quaternion *dst);
/**
* Sets this quaternion to the conjugate of itself.
*/
void conjugate();
/**
* Gets the conjugate of this quaternion.
*
*/
Quaternion getConjugated() const;
/**
* Sets this quaternion to the inverse of itself.
*
* Note that the inverse of a quaternion is equal to its conjugate
* when the quaternion is unit-length. For this reason, it is more
* efficient to use the conjugate method directly when you know your
* quaternion is already unit-length.
*/
void inverse();
/**
* Gets the inverse of this quaternion.
*
* Note that the inverse of a quaternion is equal to its conjugate
* when the quaternion is unit-length. For this reason, it is more
* efficient to use the conjugate method directly when you know your
* quaternion is already unit-length.
*/
Quaternion getInversed() const;
/**
* Multiplies this quaternion by the specified one and stores the result in this quaternion.
*
* @param q The quaternion to multiply.
*/
void multiply(const Quaternion &q);
/**
* Multiplies the specified quaternions and stores the result in dst.
*
* @param q1 The first quaternion.
* @param q2 The second quaternion.
* @param dst A quaternion to store the result in.
*/
static void multiply(const Quaternion &q1, const Quaternion &q2, Quaternion *dst);
/**
* Normalizes this quaternion to have unit length.
*
* If the quaternion already has unit length or if the length
* of the quaternion is zero, this method does nothing.
*/
void normalize();
/**
* Get the normalized quaternion.
*
* If the quaternion already has unit length or if the length
* of the quaternion is zero, this method simply copies
* this vector.
*/
Quaternion getNormalized() const;
/**
* Sets the elements of the quaternion to the specified values.
*
* @param xx The new x-value.
* @param yy The new y-value.
* @param zz The new z-value.
* @param ww The new w-value.
*/
void set(float xx, float yy, float zz, float ww);
/**
* Sets the elements of the quaternion from the values in the specified array.
*
* @param array An array containing the elements of the quaternion in the order x, y, z, w.
*/
void set(const float *array);
/**
* Sets the quaternion equal to the rotational part of the specified matrix.
*
* @param m The matrix.
*/
void set(const Mat4 &m);
/**
* Sets the quaternion equal to the rotation from the specified axis and angle.
*
* @param axis The axis of rotation.
* @param angle The angle of rotation (in radians).
*/
void set(const Vec3 &axis, float angle);
/**
* Sets the elements of this quaternion to a copy of the specified quaternion.
*
* @param q The quaternion to copy.
*/
void set(const Quaternion &q);
/**
* Sets this quaternion to be equal to the identity quaternion.
*/
void setIdentity();
/**
* Converts this Quaternion4f to axis-angle notation. The axis is normalized.
*
* @param e The Vec3f which stores the axis.
*
* @return The angle (in radians).
*/
float toAxisAngle(Vec3 *axis) const;
/**
* Interpolates between two quaternions using linear interpolation.
*
* The interpolation curve for linear interpolation between
* quaternions gives a straight line in quaternion space.
*
* @param q1 The first quaternion.
* @param q2 The second quaternion.
* @param t The interpolation coefficient.
* @param dst A quaternion to store the result in.
*/
static void lerp(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst);
/**
* Calculates the quaternion with the three-dimensional transform matrix, considering no scale included in the matrix
*/
static void fromMat3(const Mat3 &m, Quaternion *out);
/**
* Calculates the quaternion with the up direction and the direction of the viewport
*/
static void fromViewUp(const Vec3 &view, Quaternion *out);
static void fromViewUp(const Vec3 &view, const Vec3 &up, Quaternion *out);
/**
* Interpolates between two quaternions using spherical linear interpolation.
*
* Spherical linear interpolation provides smooth transitions between different
* orientations and is often useful for animating models or cameras in 3D.
*
* Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
* This method does not automatically normalize the input quaternions, so it is up to the
* caller to ensure they call normalize beforehand, if necessary.
*
* @param q1 The first quaternion.
* @param q2 The second quaternion.
* @param t The interpolation coefficient.
* @param dst A quaternion to store the result in.
*/
static void slerp(const Quaternion &a, const Quaternion &b, float t, Quaternion *dst);
/**
* @en Spherical quaternion interpolation with two control points
*
* @param out the receiving quaternion
* @param a the first operand
* @param b the second operand
* @param c the third operand
* @param d the fourth operand
* @param t interpolation amount, in the range [0-1], between the two inputs
* @returns out
*/
static void sqlerp(const Quaternion &a, const Quaternion &b, const Quaternion &c, const Quaternion &d, float t, Quaternion *dst);
/**
* Interpolates over a series of quaternions using spherical spline interpolation.
*
* Spherical spline interpolation provides smooth transitions between different
* orientations and is often useful for animating models or cameras in 3D.
*
* Note: For accurate interpolation, the input quaternions must be unit.
* This method does not automatically normalize the input quaternions,
* so it is up to the caller to ensure they call normalize beforehand, if necessary.
*
* @param q1 The first quaternion.
* @param q2 The second quaternion.
* @param s1 The first control point.
* @param s2 The second control point.
* @param t The interpolation coefficient.
* @param dst A quaternion to store the result in.
*/
/**
* @deprecated since v3.8.0 please use [[sqlerp]] instead
*/
static void squad(const Quaternion &q1, const Quaternion &q2, const Quaternion &s1, const Quaternion &s2, float t, Quaternion *dst);
/**
* @en Quaternion dot product (scalar product)
* @zh 四元数点积(数量积)
* @param a The first unit quaternion
* @param b The second unit quaternion
*/
static inline float dot(const Quaternion &a, const Quaternion &b) {
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
/**
* @en Gets the angular distance between two unit quaternions
* @zh 获取两个单位四元数的夹角
* @param a The first unit quaternion
* @param b The second unit quaternion
* @returns Angle between the two quaternions in radians
*/
static float angle(const Quaternion &a, const Quaternion &b);
/**
* @en Rotate a `from` unit quaternion towards `to` unit quaternion
* @zh 将一个起始单位四元数旋转到一个目标单位四元数
* @param from The first unit quaternion
* @param to The second unit quaternion
* @param maxStep The maximum angle of rotation in degrees
* @returns new unit quaternion generated during rotation
*/
static void rotateTowards(const Quaternion &from, const Quaternion &to, float maxStep, Quaternion *dst);
/**
* Calculates the quaternion product of this quaternion with the given quaternion.
*
* Note: this does not modify this quaternion.
*
* @param q The quaternion to multiply.
* @return The quaternion product.
*/
inline const Quaternion operator*(const Quaternion &q) const;
/**
* Multiplies this quaternion with the given quaternion.
*
* @param q The quaternion to multiply.
* @return This quaternion, after the multiplication occurs.
*/
inline Quaternion &operator*=(const Quaternion &q);
/**
* Determines if this quaternion is approximately equal to the given quaternion.
*/
inline bool approxEquals(const Quaternion &v, float precision = CC_FLOAT_CMP_PRECISION) const {
return math::isEqualF(x, v.x, precision) && math::isEqualF(y, v.y, precision) && math::isEqualF(z, v.z, precision) && math::isEqualF(w, v.w, precision);
}
/** equals to Quaternion(0,0,0, 0) */
static const Quaternion ZERO;
private:
/**
* Interpolates between two quaternions using spherical linear interpolation.
*
* Spherical linear interpolation provides smooth transitions between different
* orientations and is often useful for animating models or cameras in 3D.
*
* Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
* This method does not automatically normalize the input quaternions, so it is up to the
* caller to ensure they call normalize beforehand, if necessary.
*
* @param q1x The x component of the first quaternion.
* @param q1y The y component of the first quaternion.
* @param q1z The z component of the first quaternion.
* @param q1w The w component of the first quaternion.
* @param q2x The x component of the second quaternion.
* @param q2y The y component of the second quaternion.
* @param q2z The z component of the second quaternion.
* @param q2w The w component of the second quaternion.
* @param t The interpolation coefficient.
* @param dstx A pointer to store the x component of the slerp in.
* @param dsty A pointer to store the y component of the slerp in.
* @param dstz A pointer to store the z component of the slerp in.
* @param dstw A pointer to store the w component of the slerp in.
*/
/**
* @deprecated since v3.8.0
*/
static void slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float *dstx, float *dsty, float *dstz, float *dstw);
/**
* @deprecated since v3.8.0
*/
static void slerpForSquad(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst);
};
NS_CC_MATH_END
/**
end of base group
@}
*/
#include "math/Quaternion.inl"

38
cocos/math/Quaternion.inl Normal file
View File

@@ -0,0 +1,38 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Quaternion.h"
NS_CC_MATH_BEGIN
inline const Quaternion Quaternion::operator*(const Quaternion& q) const {
Quaternion result(*this);
result.multiply(q);
return result;
}
inline Quaternion& Quaternion::operator*=(const Quaternion& q) {
multiply(q);
return *this;
}
NS_CC_MATH_END

112
cocos/math/Utils.cpp Normal file
View File

@@ -0,0 +1,112 @@
/****************************************************************************
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 "math/Utils.h"
#include <algorithm>
#include <cmath>
#include <random>
#include "math/Math.h"
namespace {
std::random_device rd;
std::uniform_real_distribution<float> uniformReal{0.0F, 1.0F};
} // namespace
namespace cc {
namespace mathutils {
float random() {
return uniformReal(rd);
}
float absMaxComponent(const Vec3 &v) {
return absMax(absMax(v.x, v.y), v.z);
}
float maxComponent(const Vec3 &v) {
return std::max(std::max(v.x, v.y), v.z);
}
uint16_t floatToHalf(float fval) {
union {
float f;
unsigned int ui;
} u = {fval};
unsigned int ui = u.ui;
int s = (ui >> 16) & 0x8000; // NOLINT
int em = ui & 0x7fffffff; // NOLINT
/* bias exponent and round to nearest; 112 is relative exponent bias (127-15) */
int h = (em - (112 << 23) + (1 << 12)) >> 13;
/* underflow: flush to zero; 113 encodes exponent -14 */
h = (em < (113 << 23)) ? 0 : h;
/* overflow: infinity; 143 encodes exponent 16 */
h = (em >= (143 << 23)) ? 0x7c00 : h;
/* NaN; note that we convert all types of NaN to qNaN */
h = (em > (255 << 23)) ? 0x7e00 : h;
return static_cast<uint16_t>(s | h);
}
float halfToFloat(uint16_t hval) {
union {
float f;
unsigned int ui;
} u;
int s = (hval >> 15) & 0x00000001;
int em = hval & 0x00007fff;
int m = 0;
if (em > 0) {
/* normalized */
if (em > 30 << 10) {
/* overflow: infinity */
em = 255 << 23;
} else {
em = (em + (112 << 10)) << 13;
}
} else {
/* denormalized */
if (em > 25 << 10) {
/* underflow: flush to zero */
em = 0;
} else {
em = (em + (113 << 10)) >> 1;
}
}
u.ui = ((s << 31)) | em | m; // NOLINT
return u.f;
}
} // namespace mathutils
} // namespace cc

292
cocos/math/Utils.h Normal file
View File

@@ -0,0 +1,292 @@
/****************************************************************************
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 <algorithm>
#include <cmath>
#include "math/Vec3.h"
namespace cc {
namespace mathutils {
constexpr auto EPSILON = 0.000001;
constexpr auto D2R = M_PI / 180.0;
constexpr auto R2D = 180.0 / M_PI;
constexpr auto HALF_TO_RAD = 0.5 * D2R;
/**
* @en Tests whether or not the arguments have approximately the same value, within an absolute<br/>
* or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less<br/>
* than or equal to 1.0, and a relative tolerance is used for larger values)
* @zh 在glMatrix的绝对或相对容差范围内测试参数是否具有近似相同的值。<br/>
* EPSILON(小于等于1.0的值采用绝对公差大于1.0的值采用相对公差)
* @param a The first number to test.
* @param b The second number to test.
* @return True if the numbers are approximately equal, false otherwise.
*/
template <typename F>
bool equals(F a, F b) {
static_assert(std::is_floating_point<F>::value, "number expected");
return std::fabs(a - b) <= EPSILON * std::max(1.0F, std::max(std::fabs(a), std::fabs(b)));
}
/**
* @en Tests whether or not the arguments have approximately the same value by given maxDiff<br/>
* @zh 通过给定的最大差异,测试参数是否具有近似相同的值。
* @param a The first number to test.
* @param b The second number to test.
* @param maxDiff Maximum difference.
* @return True if the numbers are approximately equal, false otherwise.
*/
template <typename F>
bool approx(F a, F b, F maxDiff) {
static_assert(std::is_floating_point<F>::value, "number expected");
return std::fabs(a - b) <= maxDiff;
}
template <typename F>
bool approx(F a, F b) {
static_assert(std::is_floating_point<F>::value, "number expected");
return std::fabs(a - b) <= EPSILON;
}
/**
* @en Clamps a value between a minimum float and maximum float value.<br/>
* @zh 返回最小浮点数和最大浮点数之间的一个数值。可以使用 clamp 函数将不断变化的数值限制在范围内。
* @param val
* @param min
* @param max
*/
template <typename F>
typename std::enable_if<std::is_arithmetic<F>::value, F>::type
clamp(F val, F min, F max) {
if (min > max) {
const auto temp = min;
min = max;
max = temp;
}
return val < min ? min : val > max ? max
: val;
}
/**
* @en Clamps a value between 0 and 1.<br/>
* @zh 将值限制在0和1之间。
* @param val
*/
template <typename F>
auto clamp01(F val) {
static_assert(std::is_floating_point<F>::value, "number expected");
return val < 0 ? 0 : val > 1 ? 1
: val;
}
/**
* @param from
* @param to
* @param ratio - The interpolation coefficient.
*/
template <typename F>
auto lerp(F from, F to, F ratio) {
static_assert(std::is_floating_point<F>::value, "number expected");
return from + (to - from) * ratio;
}
/**
* @en Convert Degree To Radian<br/>
* @zh 把角度换算成弧度。
* @param {Number} a Angle in Degrees
*/
template <typename F>
auto toRadian(F a) {
static_assert(std::is_floating_point<F>::value, "number expected");
return a * D2R;
}
/**
* @en Convert Radian To Degree<br/>
* @zh 把弧度换算成角度。
* @param {Number} a Angle in Radian
*/
template <typename F>
auto toDegree(F a) {
return a * R2D;
}
/**
* @method random
*/
float random();
/**
* @en Returns a floating-point random number between min (inclusive) and max (exclusive).<br/>
* @zh 返回最小(包含)和最大(不包含)之间的浮点随机数。
* @method randomRange
* @param min
* @param max
* @return The random number.
*/
template <typename T>
auto randomRange(T min, T max) {
return random() * (max - min) + min;
}
/**
* @en Returns a random integer between min (inclusive) and max (exclusive).<br/>
* @zh 返回最小(包含)和最大(不包含)之间的随机整数。
* @param min
* @param max
* @return The random integer.
*/
template <typename T>
auto randomRangeInt(T min, T max) {
static_assert(std::is_arithmetic<T>::value, "number expected");
return floor(randomRange(min, max));
}
/**
* Linear congruential generator using Hull-Dobell Theorem.
*
* @param seed The random seed.
* @return The pseudo random.
*/
template <typename In>
auto pseudoRandom(In seed) {
static_assert(std::is_arithmetic<In>::value, "number expected");
seed = (seed * 9301 + 49297) % 233280;
return seed / 233280.0;
}
/**
* Returns a floating-point pseudo-random number between min (inclusive) and max (exclusive).
*
* @param seed
* @param min
* @param max
* @return The random number.
*/
template <typename In>
auto pseudoRandomRange(In seed, In min, In max) {
static_assert(std::is_arithmetic<In>::value, "number expected");
return pseudoRandom(seed) * (max - min) + min;
}
/**
* @en Returns a pseudo-random integer between min (inclusive) and max (exclusive).<br/>
* @zh 返回最小(包含)和最大(不包含)之间的浮点伪随机数。
* @param seed
* @param min
* @param max
* @return The random integer.
*/
template <typename In>
auto pseudoRandomRangeInt(In seed, In min, In max) {
return floor(pseudoRandomRange(seed, min, max));
}
/**
* Returns the next power of two for the value.<br/>
*
* @param val
* @return The the next power of two.
*/
template <typename T>
auto nextPow2(T val) {
// ref: https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--val;
val = (val >> 1) | val;
val = (val >> 2) | val;
val = (val >> 4) | val;
val = (val >> 8) | val;
val = (val >> 16) | val;
++val;
return val;
}
/**
* @en Returns float remainder for t / length.<br/>
* @zh 返回t / length的浮点余数。
* @param t Time start at 0.
* @param length Time of one cycle.
* @return The Time wrapped in the first cycle.
*/
template <typename T>
auto repeat(T t, T length) {
return t - floor(t / length) * length;
}
/**
* Returns time wrapped in ping-pong mode.
*
* @param t Time start at 0.
* @param length Time of one cycle.
* @return The time wrapped in the first cycle.
*/
template <typename T>
auto pingPong(T t, T length) {
t = repeat(t, length * 2);
t = length - std::fabs(t - length);
return t;
}
/**
* @en Returns ratio of a value within a given range.<br/>
* @zh 返回给定范围内的值的比率。
* @param from Start value.
* @param to End value.
* @param value Given value.
* @return The ratio between [from, to].
*/
template <typename T>
auto inverseLerp(T from, T to, T value) {
return (value - from) / (to - from);
}
/**
* @zh 对所有分量的绝对值进行比较大小,返回绝对值最大的分量。
* @param v 类 Vec3 结构
* @returns 绝对值最大的分量
*/
float absMaxComponent(const Vec3 &v);
float maxComponent(const Vec3 &v);
/**
* @zh 对 a b 的绝对值进行比较大小,返回绝对值最大的值。
* @param a number
* @param b number
*/
template <typename F>
auto absMax(F a, F b) {
return std::fabs(a) > std::fabs(b) ? a : b;
}
uint16_t floatToHalf(float fval);
float halfToFloat(uint16_t hval);
} // namespace mathutils
} // namespace cc

300
cocos/math/Vec2.cpp Normal file
View File

@@ -0,0 +1,300 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Vec2.h"
#include "base/Macros.h"
#include "math/MathUtil.h"
NS_CC_MATH_BEGIN
// returns true if segment a-b intersects with segment c-d. s->e is the overlap part
bool isOneDimensionSegmentOverlap(float a, float b, float c, float d, float *s, float *e) {
float abmin = std::min(a, b);
float abmax = std::max(a, b);
float cdmin = std::min(c, d);
float cdmax = std::max(c, d);
if (abmax < cdmin || cdmax < abmin) {
// abmin->abmax->cdmin->cdmax or cdmin->cdmax->abmin->abmax
return false;
}
if (abmin >= cdmin && abmin <= cdmax) {
// cdmin->abmin->cdmax->abmax or cdmin->abmin->abmax->cdmax
if (s != nullptr) *s = abmin;
if (e != nullptr) *e = cdmax < abmax ? cdmax : abmax;
} else if (abmax >= cdmin && abmax <= cdmax) {
// ABmin->CDmin->ABmax->CDmax
if (s != nullptr) *s = cdmin;
if (e != nullptr) *e = abmax;
} else {
// ABmin->CDmin->CDmax->ABmax
if (s != nullptr) *s = cdmin;
if (e != nullptr) *e = cdmax;
}
return true;
}
// cross product of 2 vector. a->b X c->d
float crossProduct2Vector(const Vec2 &a, const Vec2 &b, const Vec2 &c, const Vec2 &d) {
return (d.y - c.y) * (b.x - a.x) - (d.x - c.x) * (b.y - a.y);
}
float Vec2::angle(const Vec2 &v1, const Vec2 &v2) {
const auto magSqr1 = v1.x * v1.x + v1.y * v1.y;
const auto magSqr2 = v2.x * v2.x + v2.y * v2.y;
if (magSqr1 == 0.0F || magSqr2 == 0.0F) {
return 0.0F;
}
const auto dot = v1.x * v2.x + v1.y * v2.y;
auto cosine = dot / (sqrt(magSqr1 * magSqr2));
cosine = clampf(cosine, -1.0, 1.0);
return acos(cosine);
}
void Vec2::add(const Vec2 &v1, const Vec2 &v2, Vec2 *dst) {
CC_ASSERT(dst);
dst->x = v1.x + v2.x;
dst->y = v1.y + v2.y;
}
void Vec2::clamp(const Vec2 &min, const Vec2 &max) {
CC_ASSERT(!(min.x > max.x || min.y > max.y));
// Clamp the x value.
if (x < min.x) {
x = min.x;
}
if (x > max.x) {
x = max.x;
}
// Clamp the y value.
if (y < min.y) {
y = min.y;
}
if (y > max.y) {
y = max.y;
}
}
void Vec2::clamp(const Vec2 &v, const Vec2 &min, const Vec2 &max, Vec2 *dst) {
CC_ASSERT(dst);
CC_ASSERT(!(min.x > max.x || min.y > max.y));
// Clamp the x value.
dst->x = v.x;
if (dst->x < min.x) {
dst->x = min.x;
}
if (dst->x > max.x) {
dst->x = max.x;
}
// Clamp the y value.
dst->y = v.y;
if (dst->y < min.y) {
dst->y = min.y;
}
if (dst->y > max.y) {
dst->y = max.y;
}
}
float Vec2::distance(const Vec2 &v) const {
float dx = v.x - x;
float dy = v.y - y;
return std::sqrt(dx * dx + dy * dy);
}
float Vec2::dot(const Vec2 &v1, const Vec2 &v2) {
return (v1.x * v2.x + v1.y * v2.y);
}
float Vec2::length() const {
return std::sqrt(x * x + y * y);
}
void Vec2::normalize() {
float len = x * x + y * y;
if (len > 0.0F) {
len = 1.0F / std::sqrt(len);
x *= len;
y *= len;
}
}
Vec2 Vec2::getNormalized() const {
Vec2 v(*this);
v.normalize();
return v;
}
void Vec2::rotate(const Vec2 &point, float angle) {
float sinAngle = std::sin(angle);
float cosAngle = std::cos(angle);
if (point.isZero()) {
float tempX = x * cosAngle - y * sinAngle;
y = y * cosAngle + x * sinAngle;
x = tempX;
} else {
float tempX = x - point.x;
float tempY = y - point.y;
x = tempX * cosAngle - tempY * sinAngle + point.x;
y = tempY * cosAngle + tempX * sinAngle + point.y;
}
}
void Vec2::set(const float *array) {
CC_ASSERT(array);
x = array[0];
y = array[1];
}
void Vec2::subtract(const Vec2 &v1, const Vec2 &v2, Vec2 *dst) {
CC_ASSERT(dst);
dst->x = v1.x - v2.x;
dst->y = v1.y - v2.y;
}
bool Vec2::equals(const Vec2 &target) const {
return (std::abs(this->x - target.x) < FLT_EPSILON) && (std::abs(this->y - target.y) < FLT_EPSILON);
}
bool Vec2::fuzzyEquals(const Vec2 &b, float var) const {
if (x - var <= b.x && b.x <= x + var) {
if (y - var <= b.y && b.y <= y + var) {
return true;
}
}
return false;
}
float Vec2::getAngle(const Vec2 &other) const {
return Vec2::angle(*this, other);
}
Vec2 Vec2::rotateByAngle(const Vec2 &pivot, float angle) const {
return pivot + (*this - pivot).rotate(Vec2::forAngle(angle));
}
bool Vec2::isLineIntersect(const Vec2 &a, const Vec2 &b,
const Vec2 &c, const Vec2 &d,
float *s, float *t) {
// FAIL: Line undefined
if ((a.x == b.x && a.y == b.y) || (c.x == d.x && c.y == d.y)) {
return false;
}
const float denom = crossProduct2Vector(a, b, c, d);
if (denom == 0) {
// Lines parallel or overlap
return false;
}
if (s != nullptr) *s = crossProduct2Vector(c, d, c, a) / denom;
if (t != nullptr) *t = crossProduct2Vector(a, b, c, a) / denom;
return true;
}
bool Vec2::isLineParallel(const Vec2 &a, const Vec2 &b,
const Vec2 &c, const Vec2 &d) {
// FAIL: Line undefined
if ((a.x == b.x && a.y == b.y) || (c.x == d.x && c.y == d.y)) {
return false;
}
if (crossProduct2Vector(a, b, c, d) == 0) {
// line overlap
return !(crossProduct2Vector(c, d, c, a) == 0 || crossProduct2Vector(a, b, c, a) == 0);
}
return false;
}
bool Vec2::isLineOverlap(const Vec2 &a, const Vec2 &b,
const Vec2 &c, const Vec2 &d) {
// FAIL: Line undefined
if ((a.x == b.x && a.y == b.y) || (c.x == d.x && c.y == d.y)) {
return false;
}
return (crossProduct2Vector(a, b, c, d) == 0 && (crossProduct2Vector(c, d, c, a) == 0 || crossProduct2Vector(a, b, c, a) == 0));
}
bool Vec2::isSegmentOverlap(const Vec2 &a, const Vec2 &b, const Vec2 &c, const Vec2 &d, Vec2 *s, Vec2 *e) {
if (isLineOverlap(a, b, c, d)) {
return isOneDimensionSegmentOverlap(a.x, b.x, c.x, d.x, &s->x, &e->x) &&
isOneDimensionSegmentOverlap(a.y, b.y, c.y, d.y, &s->y, &e->y);
}
return false;
}
bool Vec2::isSegmentIntersect(const Vec2 &a, const Vec2 &b, const Vec2 &c, const Vec2 &d) {
float s;
float t;
return (isLineIntersect(a, b, c, d, &s, &t) && (s >= 0.0F && s <= 1.0F && t >= 0.0F && t <= 1.0F));
}
Vec2 Vec2::getIntersectPoint(const Vec2 &a, const Vec2 &b, const Vec2 &c, const Vec2 &d) {
float s;
float t;
if (isLineIntersect(a, b, c, d, &s, &t)) {
// Vec2 of intersection
Vec2 p;
p.x = a.x + s * (b.x - a.x);
p.y = a.y + s * (b.y - a.y);
return p;
}
return Vec2::ZERO;
}
const Vec2 Vec2::ZERO(0.0F, 0.0F);
const Vec2 Vec2::ONE(1.0F, 1.0F);
const Vec2 Vec2::UNIT_X(1.0F, 0.0F);
const Vec2 Vec2::UNIT_Y(0.0F, 1.0F);
const Vec2 Vec2::ANCHOR_MIDDLE(0.5F, 0.5F);
const Vec2 Vec2::ANCHOR_BOTTOM_LEFT(0.0F, 0.0F);
const Vec2 Vec2::ANCHOR_TOP_LEFT(0.0F, 1.0F);
const Vec2 Vec2::ANCHOR_BOTTOM_RIGHT(1.0F, 0.0F);
const Vec2 Vec2::ANCHOR_TOP_RIGHT(1.0F, 1.0F);
const Vec2 Vec2::ANCHOR_MIDDLE_RIGHT(1.0F, 0.5F);
const Vec2 Vec2::ANCHOR_MIDDLE_LEFT(0.0F, 0.5F);
const Vec2 Vec2::ANCHOR_MIDDLE_TOP(0.5F, 1.0F);
const Vec2 Vec2::ANCHOR_MIDDLE_BOTTOM(0.5F, 0.0F);
NS_CC_MATH_END

703
cocos/math/Vec2.h Normal file
View File

@@ -0,0 +1,703 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#pragma once
#include <algorithm>
#include <cmath>
#include <functional>
#include "math/Math.h"
#include "math/MathBase.h"
NS_CC_MATH_BEGIN
/** Clamp a value between from and to.
*/
inline float clampf(float value, float minInclusive, float maxInclusive) {
if (minInclusive > maxInclusive) {
std::swap(minInclusive, maxInclusive);
}
return value < minInclusive ? minInclusive : value < maxInclusive ? value
: maxInclusive;
}
class Mat4;
/**
* Defines a 2-element floating point vector.
*/
class CC_DLL Vec2 {
public:
/**
* The x coordinate.
*/
float x{0.F};
/**
* The y coordinate.
*/
float y{0.F};
/**
* Constructs a new vector initialized to all zeros.
*/
Vec2();
/**
* Constructs a new vector initialized to the specified values.
*
* @param xx The x coordinate.
* @param yy The y coordinate.
*/
Vec2(float xx, float yy);
/**
* Constructs a new vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y.
*/
explicit Vec2(const float *array);
/**
* Constructs a vector that describes the direction between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
Vec2(const Vec2 &p1, const Vec2 &p2);
/**
* Constructs a new vector that is a copy of the specified vector.
*
* @param copy The vector to copy.
*/
Vec2(const Vec2 &copy);
/**
* Destructor.
*/
~Vec2();
/**
* Indicates whether this vector contains all zeros.
*
* @return true if this vector contains all zeros, false otherwise.
*/
inline bool isZero() const;
/**
* Indicates whether this vector contains all ones.
*
* @return true if this vector contains all ones, false otherwise.
*/
inline bool isOne() const;
/**
* Returns the angle (in radians) between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The angle between the two vectors (in radians).
*/
static float angle(const Vec2 &v1, const Vec2 &v2);
/**
* Adds the elements of the specified vector to this one.
*
* @param v The vector to add.
*/
inline void add(const Vec2 &v);
/**
* Adds the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void add(const Vec2 &v1, const Vec2 &v2, Vec2 *dst);
/**
* Clamps this vector within the specified range.
*
* @param min The minimum value.
* @param max The maximum value.
*/
void clamp(const Vec2 &min, const Vec2 &max);
/**
* Clamps the specified vector within the specified range and returns it in dst.
*
* @param v The vector to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @param dst A vector to store the result in.
*/
static void clamp(const Vec2 &v, const Vec2 &min, const Vec2 &max, Vec2 *dst);
/**
* Returns the distance between this vector and v.
*
* @param v The other vector.
*
* @return The distance between this vector and v.
*
* @see distanceSquared
*/
float distance(const Vec2 &v) const;
/**
* Returns the squared distance between this vector and v.
*
* When it is not necessary to get the exact distance between
* two vectors (for example, when simply comparing the
* distance between different vectors), it is advised to use
* this method instead of distance.
*
* @param v The other vector.
*
* @return The squared distance between this vector and v.
*
* @see distance
*/
inline float distanceSquared(const Vec2 &v) const;
/**
* Returns the dot product of this vector and the specified vector.
*
* @param v The vector to compute the dot product with.
*
* @return The dot product.
*/
inline float dot(const Vec2 &v) const;
/**
* Returns the dot product between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The dot product between the vectors.
*/
static float dot(const Vec2 &v1, const Vec2 &v2);
/**
* Computes the length of this vector.
*
* @return The length of the vector.
*
* @see lengthSquared
*/
float length() const;
/**
* Returns the squared length of this vector.
*
* When it is not necessary to get the exact length of a
* vector (for example, when simply comparing the lengths of
* different vectors), it is advised to use this method
* instead of length.
*
* @return The squared length of the vector.
*
* @see length
*/
inline float lengthSquared() const;
/**
* Negates this vector.
*/
inline void negate();
/**
* Normalizes this vector.
*
* This method normalizes this Vec2 so that it is of
* unit length (in other words, the length of the vector
* after calling this method will be 1.0f). If the vector
* already has unit length or if the length of the vector
* is zero, this method does nothing.
*
* @return This vector, after the normalization occurs.
*/
void normalize();
/**
Get the normalized vector.
*/
Vec2 getNormalized() const;
/**
* Scales all elements of this vector by the specified value.
*
* @param scalar The scalar value.
*/
inline void scale(float scalar);
/**
* Scales each element of this vector by the matching component of scale.
*
* @param scale The vector to scale by.
*/
inline void scale(const Vec2 &scale);
/**
* Rotates this vector by angle (specified in radians) around the given point.
*
* @param point The point to rotate around.
* @param angle The angle to rotate by (in radians).
*/
void rotate(const Vec2 &point, float angle);
/**
* Sets the elements of this vector to the specified values.
*
* @param xx The new x coordinate.
* @param yy The new y coordinate.
*/
inline void set(float xx, float yy);
/**
* Sets the elements of this vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y.
*/
void set(const float *array);
/**
* Sets the elements of this vector to those in the specified vector.
*
* @param v The vector to copy.
*/
inline void set(const Vec2 &v);
/**
* Sets this vector to the directional vector between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
inline void set(const Vec2 &p1, const Vec2 &p2);
/**
* Sets the elements of this vector to zero.
*/
inline void setZero();
/**
* Subtracts this vector and the specified vector as (this - v)
* and stores the result in this vector.
*
* @param v The vector to subtract.
*/
inline void subtract(const Vec2 &v);
/**
* Subtracts the specified vectors and stores the result in dst.
* The resulting vector is computed as (v1 - v2).
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst The destination vector.
*/
static void subtract(const Vec2 &v1, const Vec2 &v2, Vec2 *dst);
/**
* Updates this vector towards the given target using a smoothing function.
* The given response time determines the amount of smoothing (lag). A longer
* response time yields a smoother result and more lag. To force this vector to
* follow the target closely, provide a response time that is very small relative
* to the given elapsed time.
*
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param responseTime response time (in the same units as elapsedTime).
*/
inline void smooth(const Vec2 &target, float elapsedTime, float responseTime);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline const Vec2 operator+(const Vec2 &v) const;
/**
* Adds the given vector to this vector.
*
* @param v The vector to add.
* @return This vector, after the addition occurs.
*/
inline Vec2 &operator+=(const Vec2 &v);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline const Vec2 operator-(const Vec2 &v) const;
/**
* Subtracts the given vector from this vector.
*
* @param v The vector to subtract.
* @return This vector, after the subtraction occurs.
*/
inline Vec2 &operator-=(const Vec2 &v);
/**
* Calculates the negation of this vector.
*
* Note: this does not modify this vector.
*
* @return The negation of this vector.
*/
inline const Vec2 operator-() const;
/**
* Calculates the scalar product of this vector with the given value.
*
* Note: this does not modify this vector.
*
* @param s The value to scale by.
* @return The scaled vector.
*/
inline const Vec2 operator*(float s) const;
/**
* Scales this vector by the given value.
*
* @param s The value to scale by.
* @return This vector, after the scale occurs.
*/
inline Vec2 &operator*=(float s);
/**
* Returns the components of this vector divided by the given constant
*
* Note: this does not modify this vector.
*
* @param s the constant to divide this vector with
* @return a smaller vector
*/
inline const Vec2 operator/(float s) const;
/**
* Determines if this vector is less than the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is less than the given vector, false otherwise.
*/
inline bool operator<(const Vec2 &v) const;
/**
* Determines if this vector is greater than the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is greater than the given vector, false otherwise.
*/
inline bool operator>(const Vec2 &v) const;
/**
* Determines if this vector is equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is equal to the given vector, false otherwise.
*/
inline bool operator==(const Vec2 &v) const;
/**
* Determines if this vector is not equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is not equal to the given vector, false otherwise.
*/
inline bool operator!=(const Vec2 &v) const;
/**
* Determines if this vector is approximately equal to the given vector.
*/
inline bool approxEquals(const Vec2 &v, float precision = CC_FLOAT_CMP_PRECISION) const {
return math::isEqualF(x, v.x, precision) && math::isEqualF(y, v.y, precision);
}
inline void setPoint(float xx, float yy);
/**
* @js NA
*/
bool equals(const Vec2 &target) const;
/** @returns if points have fuzzy equality which means equal with some degree of variance.
@since v2.1.4
*/
bool fuzzyEquals(const Vec2 &b, float var) const;
/** Calculates distance between point an origin
@return float
@since v2.1.4
*/
inline float getLength() const {
return sqrtf(x * x + y * y);
};
/** Calculates the square length of a Vec2 (not calling sqrt() )
@return float
@since v2.1.4
*/
inline float getLengthSq() const {
return dot(*this); //x*x + y*y;
};
/** Calculates the square distance between two points (not calling sqrt() )
@return float
@since v2.1.4
*/
inline float getDistanceSq(const Vec2 &other) const {
return (*this - other).getLengthSq();
};
/** Calculates the distance between two points
@return float
@since v2.1.4
*/
inline float getDistance(const Vec2 &other) const {
return (*this - other).getLength();
};
/** @returns the angle in radians between this vector and the x axis
@since v2.1.4
*/
inline float getAngle() const {
return atan2f(y, x);
};
/** @returns the angle in radians between two vector directions
@since v2.1.4
*/
float getAngle(const Vec2 &other) const;
/** Calculates cross product of two points.
@return float
@since v2.1.4
*/
inline float cross(const Vec2 &other) const {
return x * other.y - y * other.x;
};
/** Calculates perpendicular of v, rotated 90 degrees counter-clockwise -- cross(v, perp(v)) >= 0
@return Vec2
@since v2.1.4
*/
inline Vec2 getPerp() const {
return Vec2(-y, x);
};
/** Calculates midpoint between two points.
@return Vec2
@since v3.0
*/
inline Vec2 getMidpoint(const Vec2 &other) const {
return Vec2((x + other.x) / 2.0F, (y + other.y) / 2.0F);
}
/** Clamp a point between from and to.
@since v3.0
*/
inline Vec2 getClampPoint(const Vec2 &minInclusive, const Vec2 &maxInclusive) const {
return Vec2(clampf(x, minInclusive.x, maxInclusive.x), clampf(y, minInclusive.y, maxInclusive.y));
}
/** Run a math operation function on each point component
* absf, floorf, ceilf, roundf
* any function that has the signature: float func(float);
* For example: let's try to take the floor of x,y
* p.compOp(floorf);
@since v3.0
*/
inline Vec2 compOp(const std::function<float(float)> &function) const {
return Vec2(function(x), function(y));
}
/** Calculates perpendicular of v, rotated 90 degrees clockwise -- cross(v, rperp(v)) <= 0
@return Vec2
@since v2.1.4
*/
inline Vec2 getRPerp() const {
return Vec2(y, -x);
};
/** Calculates the projection of this over other.
@return Vec2
@since v2.1.4
*/
inline Vec2 project(const Vec2 &other) const {
return other * (dot(other) / other.dot(other));
};
/** Complex multiplication of two points ("rotates" two points).
@return Vec2 vector with an angle of this.getAngle() + other.getAngle(),
and a length of this.getLength() * other.getLength().
@since v2.1.4
*/
inline Vec2 rotate(const Vec2 &other) const {
return Vec2(x * other.x - y * other.y, x * other.y + y * other.x);
};
/** Unrotates two points.
@return Vec2 vector with an angle of this.getAngle() - other.getAngle(),
and a length of this.getLength() * other.getLength().
@since v2.1.4
*/
inline Vec2 unrotate(const Vec2 &other) const {
return Vec2(x * other.x + y * other.y, y * other.x - x * other.y);
};
/** Linear Interpolation between two points a and b
@returns
alpha == 0 ? a
alpha == 1 ? b
otherwise a value between a..b
@since v2.1.4
*/
inline Vec2 lerp(const Vec2 &other, float alpha) const {
return *this * (1.F - alpha) + other * alpha;
};
/** Rotates a point counter clockwise by the angle around a pivot
@param pivot is the pivot, naturally
@param angle is the angle of rotation ccw in radians
@returns the rotated point
@since v2.1.4
*/
Vec2 rotateByAngle(const Vec2 &pivot, float angle) const;
static inline Vec2 forAngle(const float a) {
return Vec2(cosf(a), sinf(a));
}
/** A general line-line intersection test
@param a the start point for the first line L1 = (a - b)
@param b the end point for the first line L1 = (a - b)
@param c the start point for the second line L2 = (c - d)
@param d the end point for the second line L2 = (c - d)
@param s the range for a hitpoint in L1 (p = a + s*(b - a))
@param t the range for a hitpoint in L2 (p = c + t*(d - c))
@return whether these two lines intersects.
Note that to truly test intersection for segments we have to make
sure that s & t lie within [0..1] and for rays, make sure s & t > 0
the hit point is c + t * (d - c);
the hit point also is a + s * (b - a);
@since 3.0
*/
static bool isLineIntersect(const Vec2 &a, const Vec2 &b,
const Vec2 &c, const Vec2 &d,
float *s = nullptr, float *t = nullptr);
/**
returns true if Line a-b overlap with segment c-d
@since v3.0
*/
static bool isLineOverlap(const Vec2 &a, const Vec2 &b,
const Vec2 &c, const Vec2 &d);
/**
returns true if Line a-b parallel with segment c-d
@since v3.0
*/
static bool isLineParallel(const Vec2 &a, const Vec2 &b,
const Vec2 &c, const Vec2 &d);
/**
returns true if Segment a-b overlap with segment c-d
@since v3.0
*/
static bool isSegmentOverlap(const Vec2 &a, const Vec2 &b,
const Vec2 &c, const Vec2 &d,
Vec2 *s = nullptr, Vec2 *e = nullptr);
/**
returns true if Segment a-b intersects with segment c-d
@since v3.0
*/
static bool isSegmentIntersect(const Vec2 &a, const Vec2 &b, const Vec2 &c, const Vec2 &d);
/**
returns the intersection point of line a-b, c-d
@since v3.0
*/
static Vec2 getIntersectPoint(const Vec2 &a, const Vec2 &b, const Vec2 &c, const Vec2 &d);
/** equals to Vec2(0,0) */
static const Vec2 ZERO;
/** equals to Vec2(1,1) */
static const Vec2 ONE;
/** equals to Vec2(1,0) */
static const Vec2 UNIT_X;
/** equals to Vec2(0,1) */
static const Vec2 UNIT_Y;
/** equals to Vec2(0.5, 0.5) */
static const Vec2 ANCHOR_MIDDLE;
/** equals to Vec2(0, 0) */
static const Vec2 ANCHOR_BOTTOM_LEFT;
/** equals to Vec2(0, 1) */
static const Vec2 ANCHOR_TOP_LEFT;
/** equals to Vec2(1, 0) */
static const Vec2 ANCHOR_BOTTOM_RIGHT;
/** equals to Vec2(1, 1) */
static const Vec2 ANCHOR_TOP_RIGHT;
/** equals to Vec2(1, 0.5) */
static const Vec2 ANCHOR_MIDDLE_RIGHT;
/** equals to Vec2(0, 0.5) */
static const Vec2 ANCHOR_MIDDLE_LEFT;
/** equals to Vec2(0.5, 1) */
static const Vec2 ANCHOR_MIDDLE_TOP;
/** equals to Vec2(0.5, 0) */
static const Vec2 ANCHOR_MIDDLE_BOTTOM;
};
/**
* Calculates the scalar product of the given vector with the given value.
*
* @param x The value to scale by.
* @param v The vector to scale.
* @return The scaled vector.
*/
inline const Vec2 operator*(float x, const Vec2 &v);
using Point = Vec2;
NS_CC_MATH_END
#include "math/Vec2.inl"

199
cocos/math/Vec2.inl Normal file
View File

@@ -0,0 +1,199 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Vec2.h"
NS_CC_MATH_BEGIN
inline Vec2::Vec2()
: x(0.0f), y(0.0f) {
}
inline Vec2::Vec2(float xx, float yy)
: x(xx), y(yy) {
}
inline Vec2::Vec2(const float* array) {
set(array);
}
inline Vec2::Vec2(const Vec2& p1, const Vec2& p2) {
set(p1, p2);
}
inline Vec2::Vec2(const Vec2& copy) {
set(copy);
}
inline Vec2::~Vec2() {
}
inline bool Vec2::isZero() const {
return x == 0.0f && y == 0.0f;
}
bool Vec2::isOne() const {
return x == 1.0f && y == 1.0f;
}
inline void Vec2::add(const Vec2& v) {
x += v.x;
y += v.y;
}
inline float Vec2::distanceSquared(const Vec2& v) const {
float dx = v.x - x;
float dy = v.y - y;
return (dx * dx + dy * dy);
}
inline float Vec2::dot(const Vec2& v) const {
return (x * v.x + y * v.y);
}
inline float Vec2::lengthSquared() const {
return (x * x + y * y);
}
inline void Vec2::negate() {
x = -x;
y = -y;
}
inline void Vec2::scale(float scalar) {
x *= scalar;
y *= scalar;
}
inline void Vec2::scale(const Vec2& scale) {
x *= scale.x;
y *= scale.y;
}
inline void Vec2::set(float xx, float yy) {
this->x = xx;
this->y = yy;
}
inline void Vec2::set(const Vec2& v) {
this->x = v.x;
this->y = v.y;
}
inline void Vec2::set(const Vec2& p1, const Vec2& p2) {
x = p2.x - p1.x;
y = p2.y - p1.y;
}
void Vec2::setZero() {
x = y = 0.0f;
}
inline void Vec2::subtract(const Vec2& v) {
x -= v.x;
y -= v.y;
}
inline void Vec2::smooth(const Vec2& target, float elapsedTime, float responseTime) {
if (elapsedTime > 0) {
*this += (target - *this) * (elapsedTime / (elapsedTime + responseTime));
}
}
inline const Vec2 Vec2::operator+(const Vec2& v) const {
Vec2 result(*this);
result.add(v);
return result;
}
inline Vec2& Vec2::operator+=(const Vec2& v) {
add(v);
return *this;
}
inline const Vec2 Vec2::operator-(const Vec2& v) const {
Vec2 result(*this);
result.subtract(v);
return result;
}
inline Vec2& Vec2::operator-=(const Vec2& v) {
subtract(v);
return *this;
}
inline const Vec2 Vec2::operator-() const {
Vec2 result(*this);
result.negate();
return result;
}
inline const Vec2 Vec2::operator*(float s) const {
Vec2 result(*this);
result.scale(s);
return result;
}
inline Vec2& Vec2::operator*=(float s) {
scale(s);
return *this;
}
inline const Vec2 Vec2::operator/(const float s) const {
const float inv = 1.0f / s;
return Vec2(this->x * inv, this->y * inv);
}
inline bool Vec2::operator<(const Vec2& v) const {
if (x == v.x) {
return y < v.y;
}
return x < v.x;
}
inline bool Vec2::operator>(const Vec2& v) const {
if (x == v.x) {
return y > v.y;
}
return x > v.x;
}
inline bool Vec2::operator==(const Vec2& v) const {
return x == v.x && y == v.y;
}
inline bool Vec2::operator!=(const Vec2& v) const {
return x != v.x || y != v.y;
}
inline const Vec2 operator*(float x, const Vec2& v) {
Vec2 result(v);
result.scale(x);
return result;
}
void Vec2::setPoint(float xx, float yy) {
this->x = xx;
this->y = yy;
}
NS_CC_MATH_END

403
cocos/math/Vec3.cpp Normal file
View File

@@ -0,0 +1,403 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Vec3.h"
#include "base/Macros.h"
#include "math/Mat3.h"
#include "math/Math.h"
#include "math/MathUtil.h"
#include "math/Quaternion.h"
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
#include <cpu-features.h>
#endif
#if (CC_PLATFORM == CC_PLATFORM_IOS)
#if defined(__arm64__)
#define USE_NEON64
#define INCLUDE_NEON64
#endif
#elif (CC_PLATFORM == CC_PLATFORM_ANDROID)
#if defined(__arm64__) || defined(__aarch64__)
#define USE_NEON64
#define INCLUDE_NEON64
#elif defined(__ARM_NEON__)
#define INCLUDE_NEON32
#endif
#endif
#if defined(USE_NEON64) || defined(USE_NEON32) || defined(INCLUDE_NEON32)
#include "enoki/array.h"
#ifndef ENOKI_ARM_NEON
#error "ENOKI_ARM_NEON isn't enabled!"
#endif
using SimdVec4 = enoki::Array<float, 4>;
#endif
NS_CC_MATH_BEGIN
Vec3::Vec3(float xx, float yy, float zz)
: x(xx),
y(yy),
z(zz) {
}
Vec3::Vec3(const float *array) {
set(array);
}
Vec3::Vec3(const Vec3 &p1, const Vec3 &p2) {
set(p1, p2);
}
Vec3::Vec3(const Vec3 &copy) {
set(copy);
}
Vec3 Vec3::fromColor(unsigned int color) {
float components[3];
int componentIndex = 0;
for (int i = 2; i >= 0; --i) {
auto component = (color >> i * 8) & 0x0000ff;
components[componentIndex++] = static_cast<float>(component) / 255.0F;
}
Vec3 value(components);
return value;
}
void Vec3::transformInverseRTS(const Vec3 &v, const Quaternion &r, const Vec3 &t, const Vec3 &s, Vec3 *out) {
CC_ASSERT(out);
const float x = v.x - t.x;
const float y = v.y - t.y;
const float z = v.z - t.z;
const float ix = r.w * x - r.y * z + r.z * y;
const float iy = r.w * y - r.z * x + r.x * z;
const float iz = r.w * z - r.x * y + r.y * x;
const float iw = r.x * x + r.y * y + r.z * z;
out->x = (ix * r.w + iw * r.x + iy * r.z - iz * r.y) / s.x;
out->y = (iy * r.w + iw * r.y + iz * r.x - ix * r.z) / s.y;
out->z = (iz * r.w + iw * r.z + ix * r.y - iy * r.x) / s.z;
}
float Vec3::angle(const Vec3 &v1, const Vec3 &v2) {
const auto magSqr1 = v1.x * v1.x + v1.y * v1.y + v1.z * v1.z;
const auto magSqr2 = v2.x * v2.x + v2.y * v2.y + v2.z * v2.z;
if (magSqr1 == 0.0F || magSqr2 == 0.0F) {
return 0.0F;
}
const auto dot = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
auto cosine = dot / (sqrt(magSqr1 * magSqr2));
cosine = clampf(cosine, -1.0, 1.0);
return acos(cosine);
}
void Vec3::add(const Vec3 &v1, const Vec3 &v2, Vec3 *dst) {
CC_ASSERT(dst);
dst->x = v1.x + v2.x;
dst->y = v1.y + v2.y;
dst->z = v1.z + v2.z;
}
void Vec3::clamp(const Vec3 &min, const Vec3 &max) {
CC_ASSERT(!(min.x > max.x || min.y > max.y || min.z > max.z));
// Clamp the x value.
if (x < min.x) {
x = min.x;
}
if (x > max.x) {
x = max.x;
}
// Clamp the y value.
if (y < min.y) {
y = min.y;
}
if (y > max.y) {
y = max.y;
}
// Clamp the z value.
if (z < min.z) {
z = min.z;
}
if (z > max.z) {
z = max.z;
}
}
void Vec3::clamp(const Vec3 &v, const Vec3 &min, const Vec3 &max, Vec3 *dst) {
CC_ASSERT(dst);
CC_ASSERT(!(min.x > max.x || min.y > max.y || min.z > max.z));
// Clamp the x value.
dst->x = v.x;
if (dst->x < min.x) {
dst->x = min.x;
}
if (dst->x > max.x) {
dst->x = max.x;
}
// Clamp the y value.
dst->y = v.y;
if (dst->y < min.y) {
dst->y = min.y;
}
if (dst->y > max.y) {
dst->y = max.y;
}
// Clamp the z value.
dst->z = v.z;
if (dst->z < min.z) {
dst->z = min.z;
}
if (dst->z > max.z) {
dst->z = max.z;
}
}
void Vec3::cross(const Vec3 &v) {
cross(*this, v, this);
}
void Vec3::cross(const Vec3 &v1, const Vec3 &v2, Vec3 *dst) {
dst->set(
v1.y * v2.z - v1.z * v2.y,
v1.z * v2.x - v1.x * v2.z,
v1.x * v2.y - v1.y * v2.x);
}
void Vec3::multiply(const Vec3 &v) {
x *= v.x;
y *= v.y;
z *= v.z;
}
void Vec3::multiply(const Vec3 &v1, const Vec3 &v2, Vec3 *dst) {
dst->x = v1.x * v2.x;
dst->y = v1.y * v2.y;
dst->z = v1.z * v2.z;
}
void Vec3::transformMat3(const Vec3 &v, const Mat3 &m) {
const float ix = v.x;
const float iy = v.y;
const float iz = v.z;
x = ix * m.m[0] + iy * m.m[3] + iz * m.m[6];
y = ix * m.m[1] + iy * m.m[4] + iz * m.m[7];
z = ix * m.m[2] + iy * m.m[5] + iz * m.m[8];
}
void Vec3::transformMat4Neon(const Vec3 &v, const Mat4 &m) {
#if defined(USE_NEON64) || defined(USE_NEON32) || defined(INCLUDE_NEON32)
alignas(16) float tmpV0[4];
auto row0 = enoki::load_unaligned<SimdVec4>(&m.m[0]);
auto row1 = enoki::load_unaligned<SimdVec4>(&m.m[4]);
auto row2 = enoki::load_unaligned<SimdVec4>(&m.m[8]);
auto row3 = enoki::load_unaligned<SimdVec4>(&m.m[12]);
row0 *= v.x;
row1 *= v.y;
row2 *= v.z;
row0 = row0 + row1 + row2 + row3;
enoki::store(tmpV0, row0);
float rhw;
if (CC_PREDICT_TRUE(math::isNotZeroF(tmpV0[3]))) {
rhw = 1.F / tmpV0[3];
} else {
rhw = 1.F;
}
SimdVec4 tmpV1{rhw};
row0 *= tmpV1;
enoki::store(tmpV0, row0);
x = tmpV0[0];
y = tmpV0[1];
z = tmpV0[2];
#endif
}
void Vec3::transformMat4C(const Vec3 &v, const Mat4 &m) {
alignas(16) float tmp[4] = {v.x, v.y, v.z, 1.0F};
MathUtil::transformVec4(m.m, tmp, tmp);
float rhw = math::isNotZeroF(tmp[3]) ? 1.F / tmp[3] : 1.F;
x = tmp[0] * rhw;
y = tmp[1] * rhw;
z = tmp[2] * rhw;
}
void Vec3::transformMat4(const Vec3 &v, const Mat4 &m) {
#if defined(USE_NEON64)
transformMat4Neon(v, m);
#elif defined(INCLUDE_NEON32)
if (CC_PREDICT_TRUE(MathUtil::isNeon32Enabled())) {
transformMat4Neon(v, m);
} else {
transformMat4C(v, m);
}
#else
transformMat4C(v, m);
#endif
}
void Vec3::transformMat4(const Vec3 &v, const Mat4 &m, Vec3 *dst) {
dst->transformMat4(v, m);
}
void Vec3::transformMat4Normal(const Vec3 &v, const Mat4 &m, Vec3 *dst) {
float x = v.x;
float y = v.y;
float z = v.z;
float rhw = m.m[3] * x + m.m[7] * y + m.m[11] * z;
rhw = (rhw != 0.0F ? 1.0F / rhw : 1.0F);
dst->x = (m.m[0] * x + m.m[4] * y + m.m[8] * z) * rhw;
dst->y = (m.m[1] * x + m.m[5] * y + m.m[9] * z) * rhw;
dst->z = (m.m[2] * x + m.m[6] * y + m.m[10] * z) * rhw;
}
void Vec3::moveTowards(const Vec3 &current, const Vec3 &target, float maxStep, Vec3 *dst) {
const auto deltaX = target.x - current.x;
const auto deltaY = target.y - current.y;
const auto deltaZ = target.z - current.z;
const auto distanceSqr = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
if (distanceSqr == 0.0F || (maxStep >= 0.0F && distanceSqr < maxStep * maxStep)) {
dst->set(target);
return;
}
const auto distance = std::sqrt(distanceSqr);
const auto scale = maxStep / distance;
dst->set(
current.x + deltaX * scale,
current.y + deltaY * scale,
current.z + deltaZ * scale);
}
void Vec3::transformQuat(const Quaternion &q) {
const float qx = q.x;
const float qy = q.y;
const float qz = q.z;
const float qw = q.w;
// calculate quat * vec
const float ix = qw * x + qy * z - qz * y;
const float iy = qw * y + qz * x - qx * z;
const float iz = qw * z + qx * y - qy * x;
const float iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
}
float Vec3::distance(const Vec3 &v) const {
const float dx = v.x - x;
const float dy = v.y - y;
const float dz = v.z - z;
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
float Vec3::distanceSquared(const Vec3 &v) const {
const float dx = v.x - x;
const float dy = v.y - y;
const float dz = v.z - z;
return (dx * dx + dy * dy + dz * dz);
}
float Vec3::dot(const Vec3 &v) const {
return (x * v.x + y * v.y + z * v.z);
}
float Vec3::dot(const Vec3 &v1, const Vec3 &v2) {
return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
}
void Vec3::normalize() {
float len = x * x + y * y + z * z;
if (len > 0.0F) {
len = 1.0F / std::sqrt(len);
x *= len;
y *= len;
z *= len;
}
}
Vec3 Vec3::getNormalized() const {
Vec3 v(*this);
v.normalize();
return v;
}
void Vec3::subtract(const Vec3 &v1, const Vec3 &v2, Vec3 *dst) {
CC_ASSERT(dst);
dst->x = v1.x - v2.x;
dst->y = v1.y - v2.y;
dst->z = v1.z - v2.z;
}
void Vec3::max(const Vec3 &v1, const Vec3 &v2, Vec3 *dst) {
CC_ASSERT(dst);
dst->x = std::fmaxf(v1.x, v2.x);
dst->y = std::fmaxf(v1.y, v2.y);
dst->z = std::fmaxf(v1.z, v2.z);
}
void Vec3::min(const Vec3 &v1, const Vec3 &v2, Vec3 *dst) {
CC_ASSERT(dst);
dst->x = std::fminf(v1.x, v2.x);
dst->y = std::fminf(v1.y, v2.y);
dst->z = std::fminf(v1.z, v2.z);
}
void Vec3::smooth(const Vec3 &target, float elapsedTime, float responseTime) {
if (elapsedTime > 0.0F) {
*this += (target - *this) * (elapsedTime / (elapsedTime + responseTime));
}
}
const Vec3 Vec3::ZERO(0.0F, 0.0F, 0.0F);
const Vec3 Vec3::ONE(1.0F, 1.0F, 1.0F);
const Vec3 Vec3::UNIT_X(1.0F, 0.0F, 0.0F);
const Vec3 Vec3::UNIT_Y(0.0F, 1.0F, 0.0F);
const Vec3 Vec3::UNIT_Z(0.0F, 0.0F, 1.0F);
const Vec3 Vec3::FORWARD(0.0F, 0.0F, -1.0F);
NS_CC_MATH_END

655
cocos/math/Vec3.h Normal file
View File

@@ -0,0 +1,655 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#pragma once
#include <cmath>
#include "math/Math.h"
#include "math/MathBase.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
class Mat4;
class Quaternion;
class Mat3;
/**
* Defines a 3-element floating point vector.
*
* When using a vector to represent a surface normal,
* the vector should typically be normalized.
* Other uses of directional vectors may wish to leave
* the magnitude of the vector intact. When used as a point,
* the elements of the vector represent a position in 3D space.
*/
class CC_DLL Vec3 {
public:
/**
* The x-coordinate.
*/
float x{};
/**
* The y-coordinate.
*/
float y{};
/**
* The z-coordinate.
*/
float z{};
/**
* Constructs a new vector initialized to all zeros.
*/
Vec3() = default;
/**
* Constructs a new vector initialized to the specified values.
*
* @param xx The x coordinate.
* @param yy The y coordinate.
* @param zz The z coordinate.
*/
Vec3(float xx, float yy, float zz);
/**
* Constructs a new vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z.
*/
explicit Vec3(const float *array);
/**
* Constructs a vector that describes the direction between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
Vec3(const Vec3 &p1, const Vec3 &p2);
/**
* Constructs a new vector that is a copy of the specified vector.
*
* @param copy The vector to copy.
*/
Vec3(const Vec3 &copy);
/**
* Creates a new vector from an integer interpreted as an RGB value.
* E.g. 0xff0000 represents red or the vector (1, 0, 0).
*
* @param color The integer to interpret as an RGB value.
*
* @return A vector corresponding to the interpreted RGB color.
*/
static Vec3 fromColor(unsigned int color);
/**
* Destructor.
*/
~Vec3() = default;
/**
* Indicates whether this vector contains all zeros.
*
* @return true if this vector contains all zeros, false otherwise.
*/
inline bool isZero() const;
/**
* Indicates whether this vector contains all ones.
*
* @return true if this vector contains all ones, false otherwise.
*/
inline bool isOne() const;
/**
* Returns the angle (in radians) between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The angle between the two vectors (in radians).
*/
static float angle(const Vec3 &v1, const Vec3 &v2);
/**
* Transforms the current vector with given scale, rotation and translation in reverse order
*/
static void transformInverseRTS(const Vec3 &v, const Quaternion &r, const Vec3 &t, const Vec3 &s, Vec3 *out);
/**
* Adds the elements of the specified vector to this one.
*
* @param v The vector to add.
*/
inline void add(const Vec3 &v);
/**
* Adds the elements of this vector to the specified values.
*
* @param xx The add x coordinate.
* @param yy The add y coordinate.
* @param zz The add z coordinate.
*/
inline void add(float xx, float yy, float zz);
/**
* Adds the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void add(const Vec3 &v1, const Vec3 &v2, Vec3 *dst);
/**
* Clamps this vector within the specified range.
*
* @param min The minimum value.
* @param max The maximum value.
*/
void clamp(const Vec3 &min, const Vec3 &max);
/**
* Clamps the specified vector within the specified range and returns it in dst.
*
* @param v The vector to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @param dst A vector to store the result in.
*/
static void clamp(const Vec3 &v, const Vec3 &min, const Vec3 &max, Vec3 *dst);
/**
* Sets this vector to the cross product between itself and the specified vector.
*
* @param v The vector to compute the cross product with.
*/
void cross(const Vec3 &v);
/**
* Computes the cross product of the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void cross(const Vec3 &v1, const Vec3 &v2, Vec3 *dst);
/**
* Multiply the elements of the specified vector to this one.
*
* @param v The vector to multiply.
*/
void multiply(const Vec3 &v);
/**
* Multiply the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void multiply(const Vec3 &v1, const Vec3 &v2, Vec3 *dst);
/**
* Transforms this vector by the specified Mat3 and stores the result in this vector.
*
* @param v The Vec3 to transform.
* @param m The matrix.
*/
void transformMat3(const Vec3 &v, const Mat3 &m);
/**
* Transforms the input vector by the specified Mat4 and stores the result in this vector.
*
* @param v The Vec3 to transform.
* @param m The matrix.
*/
void transformMat4(const Vec3 &v, const Mat4 &m);
/**
* Transforms this vector by the specified Mat4 and stores the result in this vector.
* @param m The matrix.
*/
inline void transformMat4(const Mat4 &m) {
transformMat4(*this, m);
}
/**
* Transforms vector v by the specified Mat4 and stores the result in dst vector.
* @zh 向量与四维矩阵乘法,默认向量第四位为 1。
* @param v The Vec3 to transform.
* @param m The matrix.
* @param dst The destination vector
*/
static void transformMat4(const Vec3 &v, const Mat4 &m, Vec3 *dst);
/**
* @en Vector and fourth order matrix multiplication, will complete the vector with a fourth element as one
* @zh 向量与四维矩阵乘法,默认向量第四位为 0。
*/
static void transformMat4Normal(const Vec3 &v, const Mat4 &m, Vec3 *dst);
/**
* @en Calculates a new position from current to target no more than `maxStep` distance.
* @zh 计算一个新位置从当前位置移动不超过 `maxStep` 距离到目标位置。
* @param current current position
* @param target target position
* @param maxStep maximum moving distance
*/
static void moveTowards(const Vec3 &current, const Vec3 &target, float maxStep, Vec3 *dst);
/**
* Transforms this vector by the specified quaternion and stores the result in this vector.
*
* @param q The quaternion to multiply.
*/
void transformQuat(const Quaternion &q);
/**
* Returns the distance between this vector and v.
*
* @param v The other vector.
*
* @return The distance between this vector and v.
*
* @see distanceSquared
*/
float distance(const Vec3 &v) const;
/**
* Returns the squared distance between this vector and v.
*
* When it is not necessary to get the exact distance between
* two vectors (for example, when simply comparing the
* distance between different vectors), it is advised to use
* this method instead of distance.
*
* @param v The other vector.
*
* @return The squared distance between this vector and v.
*
* @see distance
*/
float distanceSquared(const Vec3 &v) const;
/**
* Returns the dot product of this vector and the specified vector.
*
* @param v The vector to compute the dot product with.
*
* @return The dot product.
*/
float dot(const Vec3 &v) const;
/**
* Returns the dot product between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The dot product between the vectors.
*/
static float dot(const Vec3 &v1, const Vec3 &v2);
/**
* Computes the length of this vector.
*
* @return The length of the vector.
*
* @see lengthSquared
*/
inline float length() const;
/**
* Returns the squared length of this vector.
*
* When it is not necessary to get the exact length of a
* vector (for example, when simply comparing the lengths of
* different vectors), it is advised to use this method
* instead of length.
*
* @return The squared length of the vector.
*
* @see length
*/
inline float lengthSquared() const;
/**
* Negates this vector.
*/
inline void negate();
/**
* Normalizes this vector.
*
* This method normalizes this Vec3 so that it is of
* unit length (in other words, the length of the vector
* after calling this method will be 1.0f). If the vector
* already has unit length or if the length of the vector
* is zero, this method does nothing.
*/
void normalize();
/**
* Get the normalized vector.
*
* @return normalized vector.
*/
Vec3 getNormalized() const;
/**
* Scales all elements of this vector by the specified value.
*
* @param scalar The scalar value.
*/
inline void scale(float scalar);
/**
* Sets the elements of this vector to the specified values.
*
* @param xx The new x coordinate.
* @param yy The new y coordinate.
* @param zz The new z coordinate.
*/
inline void set(float xx, float yy, float zz);
/**
* Sets the elements of this vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z.
*/
inline void set(const float *array);
/**
* Sets the elements of this vector to those in the specified vector.
*
* @param v The vector to copy.
*/
inline void set(const Vec3 &v);
/**
* Sets this vector to the directional vector between the specified points.
*
* @param p1 The vector to subtract.
* @param p2 The vector to subtracted.
*/
inline void set(const Vec3 &p1, const Vec3 &p2);
/**
* Sets the elements of this vector to zero.
*/
inline void setZero();
/**
* Subtracts this vector and the specified vector as (this - v)
* and stores the result in this vector.
*
* @param v The vector to subtract.
*/
inline void subtract(const Vec3 &v);
/**
* Subtracts the specified vectors and stores the result in dst.
* The resulting vector is computed as (v1 - v2).
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst The destination vector.
*/
static void subtract(const Vec3 &v1, const Vec3 &v2, Vec3 *dst);
/**
* Get the maximum value in the vector
*
* @param v1 To be compared vector.
* @param v2 To be compared vector.
* @param dst The destination vector.
*/
static void max(const Vec3 &v1, const Vec3 &v2, Vec3 *dst);
/**
* Get the minimum value in the vector
*
* @param v1 To be compared vector.
* @param v2 To be compared vector.
* @param dst The destination vector.
*/
static void min(const Vec3 &v1, const Vec3 &v2, Vec3 *dst);
/**
* Updates this vector towards the given target using a smoothing function.
* The given response time determines the amount of smoothing (lag). A longer
* response time yields a smoother result and more lag. To force this vector to
* follow the target closely, provide a response time that is very small relative
* to the given elapsed time.
*
* @param target target value.
* @param elapsedTime elapsed time between calls.
* @param responseTime response time (in the same units as elapsedTime).
*/
void smooth(const Vec3 &target, float elapsedTime, float responseTime);
/**
* Linear interpolation between two vectors A and B by alpha which
* is in the range [0,1]
*/
inline Vec3 lerp(const Vec3 &target, float alpha) const;
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline const Vec3 operator+(const Vec3 &v) const;
/**
* Adds the given vector to this vector.
*
* @param v The vector to add.
* @return This vector, after the addition occurs.
*/
inline Vec3 &operator+=(const Vec3 &v);
/**
* Calculates the difference of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to subtract.
* @return The vector difference.
*/
inline const Vec3 operator-(const Vec3 &v) const;
/**
* Subtracts the given vector from this vector.
*
* @param v The vector to subtract.
* @return This vector, after the subtraction occurs.
*/
inline Vec3 &operator-=(const Vec3 &v);
/**
* Calculates the negation of this vector.
*
* Note: this does not modify this vector.
*
* @return The negation of this vector.
*/
inline const Vec3 operator-() const;
/**
* Calculates the scalar product of this vector with the given value.
*
* Note: this does not modify this vector.
*
* @param s The value to scale by.
* @return The scaled vector.
*/
inline const Vec3 operator*(float s) const;
/**
* Multiply with a vector.
*
* @param rhs The value to scale by.
* @return The scaled vector.
*/
inline Vec3 operator*(const Vec3 &rhs) const;
/**
* Scales this vector by the given value.
*
* @param s The value to scale by.
* @return This vector, after the scale occurs.
*/
inline Vec3 &operator*=(float s);
/**
* Returns the components of this vector divided by the given constant
*
* Note: this does not modify this vector.
*
* @param s the constant to divide this vector with
* @return a smaller vector
*/
inline const Vec3 operator/(float s) const;
/**
* Divide by a vector.
*
* Note: this does not modify this vector.
*
* @param rhs the vector to divide this vector with
* @return a vector
*/
inline Vec3 operator/(const Vec3 &rhs) const;
/**
* Returns true if the vector's scalar components are all greater
* that the ones of the vector it is compared against.
*
* @param rhs Compare the size of two vectors
* @return bool
*/
inline bool operator<(const Vec3 &rhs) const {
return x < rhs.x && y < rhs.y && z < rhs.z;
}
inline bool operator<=(const Vec3 &rhs) const {
return x <= rhs.x && y <= rhs.y && z <= rhs.z;
}
/**
* Returns true if the vector's scalar components are all smaller
* that the ones of the vector it is compared against.
*
* @param rhs Compare the size of two vectors
* @return bool
*/
inline bool operator>(const Vec3 &rhs) const {
return x > rhs.x && y > rhs.y && z > rhs.z;
}
inline bool operator>=(const Vec3 &rhs) const {
return x >= rhs.x && y >= rhs.y && z >= rhs.z;
}
/**
* Determines if this vector is equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is equal to the given vector, false otherwise.
*/
inline bool operator==(const Vec3 &v) const;
/**
* Assign from another vector.
*
* @param rhs the vector to divide this vector with
*
* @return a vector
*/
inline Vec3 &operator=(const Vec3 &rhs) noexcept = default;
/**
* Determines if this vector is not equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is not equal to the given vector, false otherwise.
*/
inline bool operator!=(const Vec3 &v) const;
/**
* Determines if this vector is approximately equal to the given vector.
*/
inline bool approxEquals(const Vec3 &v, float precision = CC_FLOAT_CMP_PRECISION) const {
return math::isEqualF(x, v.x, precision) && math::isEqualF(y, v.y, precision) && math::isEqualF(z, v.z, precision);
}
/** equals to Vec3(0,0,0) */
static const Vec3 ZERO;
/** equals to Vec3(1,1,1) */
static const Vec3 ONE;
/** equals to Vec3(1,0,0) */
static const Vec3 UNIT_X;
/** equals to Vec3(0,1,0) */
static const Vec3 UNIT_Y;
/** equals to Vec3(0,0,1) */
static const Vec3 UNIT_Z;
/** equals to Vec3(0,0,-1) */
static const Vec3 FORWARD;
private:
void transformMat4C(const Vec3 &v, const Mat4 &m);
void transformMat4Neon(const Vec3 &v, const Mat4 &m);
};
/**
* Calculates the scalar product of the given vector with the given value.
*
* @param x The value to scale by.
* @param v The vector to scale.
* @return The scaled vector.
*/
inline const Vec3 operator*(float x, const Vec3 &v);
//typedef Vec3 Point3;
NS_CC_MATH_END
/**
end of base group
@}
*/
#include "math/Vec3.inl"

176
cocos/math/Vec3.inl Normal file
View File

@@ -0,0 +1,176 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#pragma once
#include <cmath>
#include "math/Mat4.h"
#include "math/Vec3.h"
NS_CC_MATH_BEGIN
inline bool Vec3::isZero() const {
return x == 0.0f && y == 0.0f && z == 0.0f;
}
inline bool Vec3::isOne() const {
return x == 1.0f && y == 1.0f && z == 1.0f;
}
inline void Vec3::add(const Vec3& v) {
x += v.x;
y += v.y;
z += v.z;
}
inline void Vec3::add(float xx, float yy, float zz) {
x += xx;
y += yy;
z += zz;
}
inline float Vec3::length() const {
return std::sqrt(x * x + y * y + z * z);
}
inline float Vec3::lengthSquared() const {
return (x * x + y * y + z * z);
}
inline void Vec3::negate() {
x = -x;
y = -y;
z = -z;
}
inline void Vec3::scale(float scalar) {
x *= scalar;
y *= scalar;
z *= scalar;
}
inline Vec3 Vec3::lerp(const Vec3& target, float alpha) const {
return *this * (1.f - alpha) + target * alpha;
}
inline void Vec3::set(float xx, float yy, float zz) {
this->x = xx;
this->y = yy;
this->z = zz;
}
inline void Vec3::set(const float* array) {
CC_ASSERT(array);
x = array[0];
y = array[1];
z = array[2];
}
inline void Vec3::set(const Vec3& v) {
this->x = v.x;
this->y = v.y;
this->z = v.z;
}
inline void Vec3::set(const Vec3& p1, const Vec3& p2) {
x = p2.x - p1.x;
y = p2.y - p1.y;
z = p2.z - p1.z;
}
inline void Vec3::setZero() {
x = y = z = 0.0f;
}
inline void Vec3::subtract(const Vec3& v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
inline const Vec3 Vec3::operator+(const Vec3& v) const {
Vec3 result(*this);
result.add(v);
return result;
}
inline Vec3& Vec3::operator+=(const Vec3& v) {
add(v);
return *this;
}
inline const Vec3 Vec3::operator-(const Vec3& v) const {
Vec3 result(*this);
result.subtract(v);
return result;
}
inline Vec3& Vec3::operator-=(const Vec3& v) {
subtract(v);
return *this;
}
inline const Vec3 Vec3::operator-() const {
Vec3 result(*this);
result.negate();
return result;
}
inline const Vec3 Vec3::operator*(float s) const {
Vec3 result(*this);
result.scale(s);
return result;
}
inline Vec3 Vec3::operator*(const Vec3& rhs) const {
return Vec3(x * rhs.x, y * rhs.y, z * rhs.z);
}
inline Vec3& Vec3::operator*=(float s) {
scale(s);
return *this;
}
inline const Vec3 Vec3::operator/(const float s) const {
const float inv = 1.0F / s;
return Vec3(this->x * inv, this->y * inv, this->z * inv);
}
inline Vec3 Vec3::operator/(const Vec3& rhs) const {
return Vec3(x / rhs.x, y / rhs.y, z / rhs.z);
}
inline bool Vec3::operator==(const Vec3& v) const {
return x == v.x && y == v.y && z == v.z;
}
inline bool Vec3::operator!=(const Vec3& v) const {
return x != v.x || y != v.y || z != v.z;
}
inline const Vec3 operator*(float x, const Vec3& v) {
Vec3 result(v);
result.scale(x);
return result;
}
NS_CC_MATH_END

342
cocos/math/Vec4.cpp Normal file
View File

@@ -0,0 +1,342 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Vec4.h"
#include <cmath>
#include "base/Macros.h"
#include "math/MathUtil.h"
#if CC_PLATFORM != CC_PLATFORM_EMSCRIPTEN
#include "base/std/hash/hash.h"
#endif
NS_CC_MATH_BEGIN
Vec4::Vec4()
: x(0.0F),
y(0.0F),
z(0.0F),
w(0.0F) {
}
Vec4::Vec4(float xx, float yy, float zz, float ww)
: x(xx),
y(yy),
z(zz),
w(ww) {
}
Vec4::Vec4(const float *src) {
set(src);
}
Vec4::Vec4(const Vec4 &p1, const Vec4 &p2) {
set(p1, p2);
}
Vec4::Vec4(const Vec4 &copy) {
set(copy);
}
Vec4 Vec4::fromColor(unsigned int color) {
float components[4];
int componentIndex = 0;
for (int i = 3; i >= 0; --i) {
uint32_t component = (color >> i * 8) & 0x000000ff;
components[componentIndex++] = static_cast<float>(component) / 255.0F;
}
Vec4 value(components);
return value;
}
bool Vec4::isZero() const {
return x == 0.0F && y == 0.0F && z == 0.0F && w == 0.0F;
}
bool Vec4::isOne() const {
return x == 1.0F && y == 1.0F && z == 1.0F && w == 1.0F;
}
float Vec4::angle(const Vec4 &v1, const Vec4 &v2) {
const float dx = (v1.y * v2.z - v1.z * v2.y);
const float dy = (v1.z * v2.x - v1.x * v2.z);
const float dz = (v1.x * v2.y - v1.y * v2.x);
const float dotVal = (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
return std::atan2(std::sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dotVal);
}
void Vec4::add(const Vec4 &v) {
x += v.x;
y += v.y;
z += v.z;
w += v.w;
}
void Vec4::add(const Vec4 &v1, const Vec4 &v2, Vec4 *dst) {
CC_ASSERT(dst);
dst->x = v1.x + v2.x;
dst->y = v1.y + v2.y;
dst->z = v1.z + v2.z;
dst->w = v1.w + v2.w;
}
void Vec4::clamp(const Vec4 &min, const Vec4 &max) {
CC_ASSERT(!(min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
// Clamp the x value.
if (x < min.x) {
x = min.x;
}
if (x > max.x) {
x = max.x;
}
// Clamp the y value.
if (y < min.y) {
y = min.y;
}
if (y > max.y) {
y = max.y;
}
// Clamp the z value.
if (z < min.z) {
z = min.z;
}
if (z > max.z) {
z = max.z;
}
// Clamp the z value.
if (w < min.w) {
w = min.w;
}
if (w > max.w) {
w = max.w;
}
}
void Vec4::clamp(const Vec4 &v, const Vec4 &min, const Vec4 &max, Vec4 *dst) {
CC_ASSERT(dst);
CC_ASSERT(!(min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
// Clamp the x value.
dst->x = v.x;
if (dst->x < min.x) {
dst->x = min.x;
}
if (dst->x > max.x) {
dst->x = max.x;
}
// Clamp the y value.
dst->y = v.y;
if (dst->y < min.y) {
dst->y = min.y;
}
if (dst->y > max.y) {
dst->y = max.y;
}
// Clamp the z value.
dst->z = v.z;
if (dst->z < min.z) {
dst->z = min.z;
}
if (dst->z > max.z) {
dst->z = max.z;
}
// Clamp the w value.
dst->w = v.w;
if (dst->w < min.w) {
dst->w = min.w;
}
if (dst->w > max.w) {
dst->w = max.w;
}
}
float Vec4::distance(const Vec4 &v) const {
float dx = v.x - x;
float dy = v.y - y;
float dz = v.z - z;
float dw = v.w - w;
return std::sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
}
float Vec4::distanceSquared(const Vec4 &v) const {
float dx = v.x - x;
float dy = v.y - y;
float dz = v.z - z;
float dw = v.w - w;
return (dx * dx + dy * dy + dz * dz + dw * dw);
}
float Vec4::dot(const Vec4 &v) const {
return (x * v.x + y * v.y + z * v.z + w * v.w);
}
float Vec4::dot(const Vec4 &v1, const Vec4 &v2) {
return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w);
}
float Vec4::length() const {
return std::sqrt(x * x + y * y + z * z + w * w);
}
float Vec4::lengthSquared() const {
return (x * x + y * y + z * z + w * w);
}
void Vec4::negate() {
x = -x;
y = -y;
z = -z;
w = -w;
}
/**
* The inverse value of this vector.
*
* This method set each component to its inverse value, zero
* will become infinity.
*/
void Vec4::inverse(const Vec4 &v, Vec4 *dst) {
CC_ASSERT(dst);
dst->x = 1.0F / v.x;
dst->y = 1.0F / v.y;
dst->z = 1.0F / v.z;
dst->w = 1.0F / v.w;
}
void Vec4::normalize() {
float n = x * x + y * y + z * z + w * w;
// Already normalized.
if (n == 1.0F) {
return;
}
n = std::sqrt(n);
// Too close to zero.
if (n < MATH_TOLERANCE) {
return;
}
n = 1.0F / n;
x *= n;
y *= n;
z *= n;
w *= n;
}
Vec4 Vec4::getNormalized() const {
Vec4 v(*this);
v.normalize();
return v;
}
void Vec4::scale(float scalar) {
x *= scalar;
y *= scalar;
z *= scalar;
w *= scalar;
}
void Vec4::set(float xx, float yy, float zz, float ww) {
this->x = xx;
this->y = yy;
this->z = zz;
this->w = ww;
}
void Vec4::set(const float *array) {
CC_ASSERT(array);
x = array[0];
y = array[1];
z = array[2];
w = array[3];
}
void Vec4::set(const Vec4 &v) {
this->x = v.x;
this->y = v.y;
this->z = v.z;
this->w = v.w;
}
void Vec4::set(const Vec4 &p1, const Vec4 &p2) {
x = p2.x - p1.x;
y = p2.y - p1.y;
z = p2.z - p1.z;
w = p2.w - p1.w;
}
void Vec4::subtract(const Vec4 &v) {
x -= v.x;
y -= v.y;
z -= v.z;
w -= v.w;
}
void Vec4::subtract(const Vec4 &v1, const Vec4 &v2, Vec4 *dst) {
CC_ASSERT(dst);
dst->x = v1.x - v2.x;
dst->y = v1.y - v2.y;
dst->z = v1.z - v2.z;
dst->w = v1.w - v2.w;
}
void Vec4::lerp(const Vec4 &a, const Vec4 &b, float t, Vec4 *dst) {
CC_ASSERT(dst);
dst->x = a.x + t * (b.x - a.x);
dst->y = a.y + t * (b.y - a.y);
dst->z = a.z + t * (b.z - a.z);
dst->w = a.w + t * (b.w - a.w);
}
const Vec4 Vec4::ZERO = Vec4(0.0F, 0.0F, 0.0F, 0.0F);
const Vec4 Vec4::ONE = Vec4(1.0F, 1.0F, 1.0F, 1.0F);
const Vec4 Vec4::UNIT_X = Vec4(1.0F, 0.0F, 0.0F, 0.0F);
const Vec4 Vec4::UNIT_Y = Vec4(0.0F, 1.0F, 0.0F, 0.0F);
const Vec4 Vec4::UNIT_Z = Vec4(0.0F, 0.0F, 1.0F, 0.0F);
const Vec4 Vec4::UNIT_W = Vec4(0.0F, 0.0F, 0.0F, 1.0F);
#if CC_PLATFORM != CC_PLATFORM_EMSCRIPTEN
template <>
ccstd::hash_t Hasher<Vec4>::operator()(const Vec4 &v) const {
return ccstd::hash_range(reinterpret_cast<const uint64_t *>(&v.x),
reinterpret_cast<const uint64_t *>(&v.x + 4));
}
#endif
NS_CC_MATH_END

483
cocos/math/Vec4.h Normal file
View File

@@ -0,0 +1,483 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#pragma once
#undef __SSE__
#ifdef __SSE__
#include <xmmintrin.h>
#endif
#include "math/Math.h"
#include "math/MathBase.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
class Mat4;
/**
* Defines 4-element floating point vector.
*/
class CC_DLL Vec4 {
public:
#ifdef __SSE__
union {
struct {
float x;
float y;
float z;
float w;
};
__m128 v;
};
#else
/**
* The x-coordinate.
*/
float x;
/**
* The y-coordinate.
*/
float y;
/**
* The z-coordinate.
*/
float z;
/**
* The w-coordinate.
*/
float w;
#endif
/**
* Constructs a new vector initialized to all zeros.
*/
Vec4();
/**
* Constructs a new vector initialized to the specified values.
*
* @param xx The x coordinate.
* @param yy The y coordinate.
* @param zz The z coordinate.
* @param ww The w coordinate.
*/
Vec4(float xx, float yy, float zz, float ww);
/**
* Constructs a new vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z, w.
*/
explicit Vec4(const float *src);
/**
* Constructs a vector that describes the direction between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
Vec4(const Vec4 &p1, const Vec4 &p2);
/**
* Constructor.
*
* Creates a new vector that is a copy of the specified vector.
*
* @param copy The vector to copy.
*/
Vec4(const Vec4 &copy);
/**
* Creates a new vector from an integer interpreted as an RGBA value.
* E.g. 0xff0000ff represents opaque red or the vector (1, 0, 0, 1).
*
* @param color The integer to interpret as an RGBA value.
*
* @return A vector corresponding to the interpreted RGBA color.
*/
static Vec4 fromColor(unsigned int color);
/**
* Indicates whether this vector contains all zeros.
*
* @return true if this vector contains all zeros, false otherwise.
*/
bool isZero() const;
/**
* Indicates whether this vector contains all ones.
*
* @return true if this vector contains all ones, false otherwise.
*/
bool isOne() const;
/**
* Returns the angle (in radians) between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The angle between the two vectors (in radians).
*/
static float angle(const Vec4 &v1, const Vec4 &v2);
/**
* Adds the elements of the specified vector to this one.
*
* @param v The vector to add.
*/
void add(const Vec4 &v);
/**
* Adds the specified vectors and stores the result in dst.
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst A vector to store the result in.
*/
static void add(const Vec4 &v1, const Vec4 &v2, Vec4 *dst);
/**
* Clamps this vector within the specified range.
*
* @param min The minimum value.
* @param max The maximum value.
*/
void clamp(const Vec4 &min, const Vec4 &max);
/**
* Clamps the specified vector within the specified range and returns it in dst.
*
* @param v The vector to clamp.
* @param min The minimum value.
* @param max The maximum value.
* @param dst A vector to store the result in.
*/
static void clamp(const Vec4 &v, const Vec4 &min, const Vec4 &max, Vec4 *dst);
/**
* Returns the distance between this vector and v.
*
* @param v The other vector.
*
* @return The distance between this vector and v.
*
* @see distanceSquared
*/
float distance(const Vec4 &v) const;
/**
* Returns the squared distance between this vector and v.
*
* When it is not necessary to get the exact distance between
* two vectors (for example, when simply comparing the
* distance between different vectors), it is advised to use
* this method instead of distance.
*
* @param v The other vector.
*
* @return The squared distance between this vector and v.
*
* @see distance
*/
float distanceSquared(const Vec4 &v) const;
/**
* Returns the dot product of this vector and the specified vector.
*
* @param v The vector to compute the dot product with.
*
* @return The dot product.
*/
float dot(const Vec4 &v) const;
/**
* Returns the dot product between the specified vectors.
*
* @param v1 The first vector.
* @param v2 The second vector.
*
* @return The dot product between the vectors.
*/
static float dot(const Vec4 &v1, const Vec4 &v2);
/**
* Computes the length of this vector.
*
* @return The length of the vector.
*
* @see lengthSquared
*/
float length() const;
/**
* Returns the squared length of this vector.
*
* When it is not necessary to get the exact length of a
* vector (for example, when simply comparing the lengths of
* different vectors), it is advised to use this method
* instead of length.
*
* @return The squared length of the vector.
*
* @see length
*/
float lengthSquared() const;
/**
* Negates this vector.
*/
void negate();
/**
* The inverse value of this vector.
*
* This method set each component to its inverse value, zero
* will become infinity.
*/
static void inverse(const Vec4 &v, Vec4 *dst);
/**
* Normalizes this vector.
*
* This method normalizes this Vec4 so that it is of
* unit length (in other words, the length of the vector
* after calling this method will be 1.0f). If the vector
* already has unit length or if the length of the vector
* is zero, this method does nothing.
*
* @return This vector, after the normalization occurs.
*/
void normalize();
/**
* Get the normalized vector.
*/
Vec4 getNormalized() const;
/**
* Scales all elements of this vector by the specified value.
*
* @param scalar The scalar value.
*/
void scale(float scalar);
/**
* Sets the elements of this vector to the specified values.
*
* @param xx The new x coordinate.
* @param yy The new y coordinate.
* @param zz The new z coordinate.
* @param ww The new w coordinate.
*/
void set(float xx, float yy, float zz, float ww);
/**
* Sets the elements of this vector from the values in the specified array.
*
* @param array An array containing the elements of the vector in the order x, y, z, w.
*/
void set(const float *array);
/**
* Sets the elements of this vector to those in the specified vector.
*
* @param v The vector to copy.
*/
void set(const Vec4 &v);
/**
* Sets this vector to the directional vector between the specified points.
*
* @param p1 The first point.
* @param p2 The second point.
*/
void set(const Vec4 &p1, const Vec4 &p2);
/**
* Subtracts this vector and the specified vector as (this - v)
* and stores the result in this vector.
*
* @param v The vector to subtract.
*/
void subtract(const Vec4 &v);
/**
* Subtracts the specified vectors and stores the result in dst.
* The resulting vector is computed as (v1 - v2).
*
* @param v1 The first vector.
* @param v2 The second vector.
* @param dst The destination vector.
*/
static void subtract(const Vec4 &v1, const Vec4 &v2, Vec4 *dst);
/**
* @en Calculates the linear interpolation between two vectors with a given ratio
* @zh 逐元素向量线性插值: A + t * (B - A)
*/
static void lerp(const Vec4 &a, const Vec4 &b, float t, Vec4 *dst);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline const Vec4 operator+(const Vec4 &v) const;
/**
* Adds the given vector to this vector.
*
* @param v The vector to add.
* @return This vector, after the addition occurs.
*/
inline Vec4 &operator+=(const Vec4 &v);
/**
* Calculates the sum of this vector with the given vector.
*
* Note: this does not modify this vector.
*
* @param v The vector to add.
* @return The vector sum.
*/
inline const Vec4 operator-(const Vec4 &v) const;
/**
* Subtracts the given vector from this vector.
*
* @param v The vector to subtract.
* @return This vector, after the subtraction occurs.
*/
inline Vec4 &operator-=(const Vec4 &v);
/**
* Calculates the negation of this vector.
*
* Note: this does not modify this vector.
*
* @return The negation of this vector.
*/
inline const Vec4 operator-() const;
/**
* Calculates the scalar product of this vector with the given value.
*
* Note: this does not modify this vector.
*
* @param s The value to scale by.
* @return The scaled vector.
*/
inline const Vec4 operator*(float s) const;
/**
* Scales this vector by the given value.
*
* @param s The value to scale by.
* @return This vector, after the scale occurs.
*/
inline Vec4 &operator*=(float s);
/**
* Returns the components of this vector divided by the given constant
*
* Note: this does not modify this vector.
*
* @param s the constant to divide this vector with
* @return a smaller vector
*/
inline const Vec4 operator/(float s) const;
/**
* Determines if this vector is less than the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is less than the given vector, false otherwise.
*/
inline bool operator<(const Vec4 &v) const;
/**
* Determines if this vector is equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is equal to the given vector, false otherwise.
*/
inline bool operator==(const Vec4 &v) const;
/**
* Determines if this vector is not equal to the given vector.
*
* @param v The vector to compare against.
*
* @return True if this vector is not equal to the given vector, false otherwise.
*/
inline bool operator!=(const Vec4 &v) const;
/**
* Determines if this vector is approximately equal to the given vector.
*/
inline bool approxEquals(const Vec4 &v, float precision = CC_FLOAT_CMP_PRECISION) const {
return math::isEqualF(x, v.x, precision) && math::isEqualF(y, v.y, precision) && math::isEqualF(z, v.z, precision) && math::isEqualF(w, v.w, precision);
}
/** equals to Vec4(0,0,0,0) */
static const Vec4 ZERO;
/** equals to Vec4(1,1,1,1) */
static const Vec4 ONE;
/** equals to Vec4(1,0,0,0) */
static const Vec4 UNIT_X;
/** equals to Vec4(0,1,0,0) */
static const Vec4 UNIT_Y;
/** equals to Vec4(0,0,1,0) */
static const Vec4 UNIT_Z;
/** equals to Vec4(0,0,0,1) */
static const Vec4 UNIT_W;
};
/**
* Calculates the scalar product of the given vector with the given value.
*
* @param x The value to scale by.
* @param v The vector to scale.
* @return The scaled vector.
*/
inline const Vec4 operator*(float x, const Vec4 &v);
NS_CC_MATH_END
/**
end of base group
@}
*/
#include "math/Vec4.inl"

116
cocos/math/Vec4.inl Normal file
View File

@@ -0,0 +1,116 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Original file from GamePlay3D: http://gameplay3d.org
This file was modified to fit the cocos2d-x project
*/
#include "math/Mat4.h"
#include "math/Vec4.h"
NS_CC_MATH_BEGIN
inline const Vec4 Vec4::operator+(const Vec4& v) const
{
Vec4 result(*this);
result.add(v);
return result;
}
inline Vec4& Vec4::operator+=(const Vec4& v)
{
add(v);
return *this;
}
inline const Vec4 Vec4::operator-(const Vec4& v) const
{
Vec4 result(*this);
result.subtract(v);
return result;
}
inline Vec4& Vec4::operator-=(const Vec4& v)
{
subtract(v);
return *this;
}
inline const Vec4 Vec4::operator-() const
{
Vec4 result(*this);
result.negate();
return result;
}
inline const Vec4 Vec4::operator*(float s) const
{
Vec4 result(*this);
result.scale(s);
return result;
}
inline Vec4& Vec4::operator*=(float s)
{
scale(s);
return *this;
}
inline const Vec4 Vec4::operator/(const float s) const
{
return Vec4(this->x / s, this->y / s, this->z / s, this->w / s);
}
inline bool Vec4::operator<(const Vec4& v) const
{
if (x == v.x)
{
if (y == v.y)
{
if (z < v.z)
{
if (w < v.w)
{
return w < v.w;
}
}
return z < v.z;
}
return y < v.y;
}
return x < v.x;
}
inline bool Vec4::operator==(const Vec4& v) const
{
return x==v.x && y==v.y && z==v.z && w==v.w;
}
inline bool Vec4::operator!=(const Vec4& v) const
{
return x!=v.x || y!=v.y || z!=v.z || w!=v.w;
}
inline const Vec4 operator*(float x, const Vec4& v)
{
Vec4 result(v);
result.scale(x);
return result;
}
NS_CC_MATH_END