初始化

This commit is contained in:
SmallMain
2022-06-25 00:23:03 +08:00
commit ef0589e8e5
2264 changed files with 617829 additions and 0 deletions

View File

@@ -0,0 +1,282 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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/CCGeometry.h"
#include <algorithm>
#include <cmath>
#include "base/ccMacros.h"
// implementation of Vec2
NS_CC_BEGIN
// implementation of Size
Size::Size(void) : width(0), height(0)
{
}
Size::Size(float w, float h) : width(w), height(h)
{
}
Size::Size(const Size& other) : width(other.width), height(other.height)
{
}
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
{
CCASSERT(a!=0, "CCSize division by 0.");
return Size(this->width / a, this->height / a);
}
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(void)
{
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.origin.x, other.origin.y, other.size.width, other.size.height);
}
Rect& Rect::operator= (const Rect& other)
{
setRect(other.origin.x, other.origin.y, other.size.width, other.size.height);
return *this;
}
void Rect::setRect(float x, float y, float width, float height)
{
// CGRect can support width<0 or height<0
// CCASSERT(width >= 0.0f && height >= 0.0f, "width and height of Rect must not less than 0.");
origin.x = x;
origin.y = y;
size.width = width;
size.height = height;
}
bool Rect::equals(const Rect& rect) const
{
return (origin.equals(rect.origin) &&
size.equals(rect.size));
}
float Rect::getMaxX() const
{
return origin.x + size.width;
}
float Rect::getMidX() const
{
return origin.x + size.width / 2.0f;
}
float Rect::getMinX() const
{
return origin.x;
}
float Rect::getMaxY() const
{
return origin.y + size.height;
}
float Rect::getMidY() const
{
return origin.y + size.height / 2.0f;
}
float Rect::getMinY() const
{
return origin.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 cocos2d::Vec2 &center, float radius) const
{
Vec2 rectangleCenter((origin.x + size.width / 2),
(origin.y + size.height / 2));
float w = size.width / 2;
float h = size.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 - origin.x - w),
std::abs(center.y - origin.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 = origin.x;
float thisRightX = origin.x + size.width;
float thisTopY = origin.y + size.height;
float thisBottomY = origin.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.origin.x;
float otherRightX = rect.origin.x + rect.size.width;
float otherTopY = rect.origin.y + rect.size.height;
float otherBottomY = rect.origin.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);
NS_CC_END

View File

@@ -0,0 +1,223 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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.
****************************************************************************/
#ifndef __MATH_CCGEOMETRY_H__
#define __MATH_CCGEOMETRY_H__
#include "base/ccMacros.h"
#include "math/CCMath.h"
/**
* @addtogroup base
* @{
*/
NS_CC_BEGIN
class CC_DLL Size
{
public:
/**Width of the Size.*/
float width;
/**Height of the Size.*/
float height;
public:
/**Conversion from Vec2 to Size.*/
operator Vec2() const
{
return Vec2(width, height);
}
public:
/**
@{
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);
/**@}*/
/**
* @js NA
* @lua NA
*/
Size& operator= (const Size& other);
/**
* @js NA
* @lua NA
*/
Size& operator= (const Vec2& point);
/**
* @js NA
* @lua NA
*/
Size operator+(const Size& right) const;
/**
* @js NA
* @lua NA
*/
Size operator-(const Size& right) const;
/**
* @js NA
* @lua NA
*/
Size operator*(float a) const;
/**
* @js NA
* @lua NA
*/
Size operator/(float a) const;
/**
Set the width and height of Size.
* @js NA
* @lua NA
*/
void setSize(float width, float height);
/**
Check if two size is the same.
* @js NA
*/
bool equals(const Size& target) const;
/**Size(0,0).*/
static const Size ZERO;
};
/**Rectangle area.*/
class CC_DLL Rect
{
public:
/**Low left point of rect.*/
Vec2 origin;
/**Width and height of the rect.*/
Size size;
public:
/**
Constructor an empty Rect.
* @js NA
*/
Rect();
/**
Constructor a rect.
* @js NA
*/
Rect(float x, float y, float width, float height);
/**
Constructor a rect.
* @js NA
*/
Rect(const Vec2& pos, const Size& dimension);
/**
Copy constructor.
* @js NA
* @lua NA
*/
Rect(const Rect& other);
/**
* @js NA
* @lua NA
*/
Rect& operator= (const Rect& other);
/**
Set the x, y, width and height of Rect.
* @js NA
* @lua NA
*/
void setRect(float x, float y, float width, float height);
/**
Get the left of the rect.
* @js NA
*/
float getMinX() const; /// return the leftmost x-value of current rect
/**
Get the X coordinate of center point.
* @js NA
*/
float getMidX() const; /// return the midpoint x-value of current rect
/**
Get the right of rect.
* @js NA
*/
float getMaxX() const; /// return the rightmost x-value of current rect
/**
Get the bottom of rect.
* @js NA
*/
float getMinY() const; /// return the bottommost y-value of current rect
/**
Get the Y coordinate of center point.
* @js NA
*/
float getMidY() const; /// return the midpoint y-value of current rect
/**
Get top of rect.
* @js NA
*/
float getMaxY() const; /// return the topmost y-value of current rect
/**
Compare two rects.
* @js NA
*/
bool equals(const Rect& rect) const;
/**
Check if the points is contained in the rect.
* @js NA
*/
bool containsPoint(const Vec2& point) const;
/**
Check the intersect status of two rects.
* @js NA
*/
bool intersectsRect(const Rect& rect) const;
/**
Check the intersect status of the rect and a circle.
* @js NA
*/
bool intersectsCircle(const Vec2& center, float radius) const;
/**
Get the min rect which can contain this and rect.
* @js NA
* @lua NA
*/
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;
};
NS_CC_END
// end of base group
/// @}
#endif // __MATH_CCGEOMETRY_H__

View File

@@ -0,0 +1,36 @@
/****************************************************************************
Copyright (c) 2017-2018 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 engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
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 __CC_MATH_H__
#define __CC_MATH_H__
#include "math/Vec2.h"
#include "math/Vec3.h"
#include "math/Vec4.h"
#include "math/Mat4.h"
#include "math/Quaternion.h"
#include "math/Mat3.hpp"
#endif

View File

@@ -0,0 +1,78 @@
/****************************************************************************
Copyright (c) 2017-2018 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 engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
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 <string.h>
#include "base/ccMacros.h"
/**
* @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 cocos2d {
#define NS_CC_MATH_END }
#define USING_NS_CC_MATH using namespace cocos2d
#else
#define NS_CC_MATH_BEGIN
#define NS_CC_MATH_END
#define USING_NS_CC_MATH
#endif
/**
* end of base group
* @}
*/
#endif // __CCMATHBASE_H__

View File

@@ -0,0 +1,142 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2011 ForzeField Studios S.L
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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/CCVertex.h"
#include "base/ccMacros.h"
NS_CC_BEGIN
void ccVertexLineToPolygon(Vec2 *points, float stroke, Vec2 *vertices, unsigned int offset, unsigned int nuPoints)
{
nuPoints += offset;
if(nuPoints<=1) return;
stroke *= 0.5f;
unsigned int idx;
unsigned int nuPointsMinus = nuPoints-1;
for(unsigned int i = offset; i<nuPoints; i++)
{
idx = i*2;
Vec2 p1 = points[i];
Vec2 perpVector;
if(i == 0)
perpVector = (p1 - points[i+1]).getNormalized().getPerp();
else if(i == nuPointsMinus)
perpVector = (points[i-1] - p1).getNormalized().getPerp();
else
{
Vec2 p2 = points[i+1];
Vec2 p0 = points[i-1];
Vec2 p2p1 = (p2 - p1).getNormalized();
Vec2 p0p1 = (p0 - p1).getNormalized();
// Calculate angle between vectors
float angle = acosf(p2p1.dot(p0p1));
if(angle < CC_DEGREES_TO_RADIANS(70))
perpVector = p2p1.getMidpoint(p0p1).getNormalized().getPerp();
else if(angle < CC_DEGREES_TO_RADIANS(170))
perpVector = p2p1.getMidpoint(p0p1).getNormalized();
else
perpVector = (p2 - p0).getNormalized().getPerp();
}
perpVector = perpVector * stroke;
vertices[idx].set(p1.x + perpVector.x, p1.y + perpVector.y);
vertices[idx + 1].set(p1.x - perpVector.x, p1.y - perpVector.y);
}
// Validate vertexes
offset = (offset==0) ? 0 : offset-1;
for(unsigned int i = offset; i<nuPointsMinus; i++)
{
idx = i*2;
const unsigned int idx1 = idx+2;
Vec2 p1 = vertices[idx];
Vec2 p2 = vertices[idx+1];
Vec2 p3 = vertices[idx1];
Vec2 p4 = vertices[idx1+1];
float s;
//BOOL fixVertex = !ccpLineIntersect(Vec2(p1.x, p1.y), Vec2(p4.x, p4.y), Vec2(p2.x, p2.y), Vec2(p3.x, p3.y), &s, &t);
bool fixVertex = !ccVertexLineIntersect(p1.x, p1.y, p4.x, p4.y, p2.x, p2.y, p3.x, p3.y, &s);
if(!fixVertex)
if (s<0.0f || s>1.0f)
fixVertex = true;
if(fixVertex)
{
vertices[idx1] = p4;
vertices[idx1+1] = p3;
}
}
}
bool ccVertexLineIntersect(float Ax, float Ay,
float Bx, float By,
float Cx, float Cy,
float Dx, float Dy, float *T)
{
float distAB, theCos, theSin, newX;
// FAIL: Line undefined
if ((Ax==Bx && Ay==By) || (Cx==Dx && Cy==Dy)) return false;
// Translate system to make A the origin
Bx-=Ax; By-=Ay;
Cx-=Ax; Cy-=Ay;
Dx-=Ax; Dy-=Ay;
// Length of segment AB
distAB = sqrtf(Bx*Bx+By*By);
// Rotate the system so that point B is on the positive X axis.
theCos = Bx/distAB;
theSin = By/distAB;
newX = Cx*theCos+Cy*theSin;
Cy = Cy*theCos-Cx*theSin; Cx = newX;
newX = Dx*theCos+Dy*theSin;
Dy = Dy*theCos-Dx*theSin; Dx = newX;
// FAIL: Lines are parallel.
if (Cy == Dy) return false;
// Discover the relative position of the intersection in the line AB
*T = (Dx+(Cx-Dx)*Dy/(Dy-Cy))/distAB;
// Success.
return true;
}
NS_CC_END

View File

@@ -0,0 +1,57 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2011 ForzeField Studios S.L
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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.
****************************************************************************/
#ifndef __CCVERTEX_H__
#define __CCVERTEX_H__
#include "base/ccTypes.h"
/**
* @addtogroup base
* @{
*/
NS_CC_BEGIN
/** @file CCVertex.h */
/** converts a line to a polygon */
void CC_DLL ccVertexLineToPolygon(Vec2 *points, float stroke, Vec2 *vertices, unsigned int offset, unsigned int nuPoints);
/** returns whether or not the line intersects */
bool CC_DLL ccVertexLineIntersect(float Ax, float Ay,
float Bx, float By,
float Cx, float Cy,
float Dx, float Dy, float *T);
NS_CC_END
// end of base group
/// @}
#endif /* __CCVERTEX_H__ */

View File

@@ -0,0 +1,375 @@
/****************************************************************************
Copyright (c) 2018 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/Mat3.hpp"
#include <cmath>
#include "math/Quaternion.h"
#include "math/MathUtil.h"
#include "base/ccMacros.h"
NS_CC_MATH_BEGIN
Mat3::Mat3()
{
*this = IDENTITY;
}
Mat3::Mat3(float m11, float m12, float m13, float m21, float m22, float m23,
float m31, float m32, float m33)
{
set(m11, m12, m13, m21, m22, m23, m31, m32, m33);
}
Mat3::Mat3(const float* mat)
{
set(mat);
}
Mat3::Mat3(const Mat3& copy)
{
memcpy(m, copy.m, MATRIX3_SIZE);
}
Mat3::~Mat3()
{
}
void Mat3::set(float m11, float m12, float m13, float m21, float m22, float m23, float m31, float m32, float m33)
{
m[0] = m11;
m[1] = m21;
m[2] = m31;
m[3] = m12;
m[4] = m22;
m[5] = m32;
m[6] = m13;
m[7] = m23;
m[8] = m33;
}
void Mat3::set(const float* mat)
{
GP_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::transpose()
{
float a01 = m[1], a02 = m[2], 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(Mat3 &out, const Mat3 &mat)
{
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], a01 = m[1], a02 = m[2];
float a10 = m[3], a11 = m[4], a12 = m[5];
float a20 = m[6], a21 = m[7], 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;
det = 1.0 / 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(Mat3 &out, const Mat3 &mat)
{
float a00 = mat.m[0], a01 = mat.m[1], a02 = mat.m[2];
float a10 = mat.m[3], a11 = mat.m[4], a12 = mat.m[5];
float a20 = mat.m[6], a21 = mat.m[7], 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(Mat3 &out, const Mat3 &a, const Mat3 &b)
{
float a00 = a.m[0], a01 = a.m[1], a02 = a.m[2];
float a10 = a.m[3], a11 = a.m[4], a12 = a.m[5];
float a20 = a.m[6], a21 = a.m[7], a22 = a.m[8];
float b00 = b.m[0], b01 = b.m[1], b02 = b.m[2];
float b10 = b.m[3], b11 = b.m[4], b12 = b.m[5];
float b20 = b.m[6], b21 = b.m[7], 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(Mat3 &out, const Mat3 &mat, const Vec2 &vec)
{
float a00 = mat.m[0], a01 = mat.m[1], a02 = mat.m[2];
float a10 = mat.m[3], a11 = mat.m[4], a12 = mat.m[5];
float a20 = mat.m[6], a21 = mat.m[7], a22 = mat.m[8];
float x = vec.x, 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(Mat3 &out, const Mat3 &mat, float rad)
{
float a00 = mat.m[0], a01 = mat.m[1], a02 = mat.m[2];
float a10 = mat.m[3], a11 = mat.m[4], a12 = mat.m[5];
float a20 = mat.m[6], a21 = mat.m[7], 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(Mat3 &out, const Mat3 &mat, const Vec2 &vec)
{
float x = vec.x, 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(Mat3 &out, const Mat4 &mat)
{
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(Mat3 &out, const Vec2 &vec)
{
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(Mat3 &out, float rad)
{
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(Mat3 &out, const Vec2 &vec)
{
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(Mat3 &out, const Quaternion &quat)
{
float x = quat.x, y = quat.y, z = quat.z, 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(Mat3 &out, const Mat3 &a, const Mat3 &b)
{
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(Mat3 &out, const Mat3 &a, const Mat3 &b)
{
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];
}
const Mat3 Mat3::IDENTITY = Mat3(
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f);
const Mat3 Mat3::ZERO = Mat3(
0, 0, 0,
0, 0, 0,
0, 0, 0);
NS_CC_MATH_END

View File

@@ -0,0 +1,232 @@
/****************************************************************************
Copyright (c) 2018 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.
****************************************************************************/
#ifndef MATH_MAT3_H
#define MATH_MAT3_H
#define MATRIX3_SIZE ( sizeof(float) * 9)
#include "base/ccMacros.h"
#include "math/Vec2.h"
#include "math/Vec3.h"
#include "math/Vec4.h"
#include "math/Mat4.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
class CC_DLL Mat3
{
public:
/**
* Stores the columns of this 3x3 matrix.
* */
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 value.
*
* @param m11 The first element of the first row.
* @param m12 The second element of the first row.
* @param m13 The third element of the first row.
* @param m21 The first element of the second row.
* @param m22 The second element of the second row.
* @param m23 The third element of the second row.
* @param m31 The first element of the third row.
* @param m32 The second element of the third row.
* @param m33 The third element of the third row.
*/
Mat3(float m11, float m12, float m13, float m21, float m22, float m23, 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 3 6
* 1 4 7
* 2 5 8
*
* @param mat An array containing 16 elements in column-major order.
*/
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);
/**
* Destructor.
*/
~Mat3();
/**
* Sets the values of this matrix.
*
* @param m11 The first element of the first row.
* @param m12 The second element of the first row.
* @param m13 The third element of the first row.
* @param m21 The first element of the second row.
* @param m22 The second element of the second row.
* @param m23 The third element of the second row.
* @param m31 The first element of the third row.
* @param m32 The second element of the third row.
* @param m33 The third element of the third row.
*/
void set(float m11, float m12, float m13, float m21, float m22, float m23,
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 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(Mat3& out, const Mat3& mat);
/**
* Inverts a matrix.
*/
void inverse();
/**
* Calculates the adjugate of a matrix.
*/
static void adjoint(Mat3& out, const Mat3& mat);
/**
* Calculates the determinant of a matrix.
*/
float determinant();
/**
* Multiply two matrices explicitly.
*/
static void multiply(Mat3& out, const Mat3& a, const Mat3& b);
/**
* Multiply a matrix with a translation matrix given by a translation offset.
*/
static void translate(Mat3& out, const Mat3& mat, const Vec2& vec);
/**
* Rotates a matrix by the given angle.
*/
static void rotate(Mat3& out, const Mat3& mat, float rad);
/**
* Multiply a matrix with a scale matrix given by a scale vector.
*/
static void scale(Mat3& out, const Mat3& mat, const Vec2& vec);
/**
* Copies the upper-left 3x3 values of a 4x4 matrix into a 3x3 matrix.
*/
static void fromMat4(Mat3& out, const Mat4& mat);
/**
* Creates a matrix from a translation offset.
*/
static void fromTranslation(Mat3& out, const Vec2& vec);
/**
* Creates a matrix from a given angle.
*/
static void fromRotation(Mat3& out, float rad);
/**
* Creates a matrix from a scale vector.
*/
static void fromScaling(Mat3& out, const Vec2& vec);
/**
* Calculates a 3x3 matrix from the given quaternion.
*/
static void fromQuat(Mat3& out, const Quaternion& quat);
/**
* Adds two matrices.
*/
static void add(Mat3& out, const Mat3& a, const Mat3& b);
/**
* Subtracts matrix b from matrix a.
*/
static void subtract(Mat3& out, const Mat3& a, const Mat3& b);
/** 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
@}
*/
#endif

View File

@@ -0,0 +1,981 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 <cmath>
#include "math/Quaternion.h"
#include "math/MathUtil.h"
#include "base/ccMacros.h"
NS_CC_MATH_BEGIN
Mat4::Mat4()
{
*this = IDENTITY;
}
Mat4::Mat4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
{
set(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44);
}
Mat4::Mat4(const float* mat)
{
set(mat);
}
Mat4::Mat4(const Mat4& copy)
{
memcpy(m, copy.m, MATRIX_SIZE);
}
Mat4::~Mat4()
{
}
void Mat4::createLookAt(const Vec3& eyePosition, const Vec3& targetPosition, const Vec3& up, Mat4* dst)
{
createLookAt(eyePosition.x, eyePosition.y, eyePosition.z, targetPosition.x, targetPosition.y, targetPosition.z,
up.x, up.y, up.z, dst);
}
void Mat4::createLookAt(float eyePositionX, float eyePositionY, float eyePositionZ,
float targetPositionX, float targetPositionY, float targetPositionZ,
float upX, float upY, float upZ, Mat4* dst)
{
GP_ASSERT(dst);
Vec3 eye(eyePositionX, eyePositionY, eyePositionZ);
Vec3 target(targetPositionX, targetPositionY, targetPositionZ);
Vec3 up(upX, upY, upZ);
up.normalize();
Vec3 zaxis;
Vec3::subtract(eye, target, &zaxis);
zaxis.normalize();
Vec3 xaxis;
Vec3::cross(up, zaxis, &xaxis);
xaxis.normalize();
Vec3 yaxis;
Vec3::cross(zaxis, xaxis, &yaxis);
yaxis.normalize();
dst->m[0] = xaxis.x;
dst->m[1] = yaxis.x;
dst->m[2] = zaxis.x;
dst->m[3] = 0.0f;
dst->m[4] = xaxis.y;
dst->m[5] = yaxis.y;
dst->m[6] = zaxis.y;
dst->m[7] = 0.0f;
dst->m[8] = xaxis.z;
dst->m[9] = yaxis.z;
dst->m[10] = zaxis.z;
dst->m[11] = 0.0f;
dst->m[12] = -Vec3::dot(xaxis, eye);
dst->m[13] = -Vec3::dot(yaxis, eye);
dst->m[14] = -Vec3::dot(zaxis, eye);
dst->m[15] = 1.0f;
}
void Mat4::createPerspective(float fieldOfView, float aspectRatio,
float zNearPlane, float zFarPlane, Mat4* dst)
{
GP_ASSERT(dst);
GP_ASSERT(zFarPlane != zNearPlane);
float f_n = 1.0f / (zFarPlane - zNearPlane);
float theta = MATH_DEG_TO_RAD(fieldOfView) * 0.5f;
if (std::abs(std::fmod(theta, MATH_PIOVER2)) < MATH_EPSILON)
{
CCLOGERROR("Invalid field of view value (%f) causes attempted calculation tan(%f), which is undefined.", fieldOfView, theta);
return;
}
float divisor = std::tan(theta);
GP_ASSERT(divisor);
float factor = 1.0f / divisor;
memset(dst, 0, MATRIX_SIZE);
GP_ASSERT(aspectRatio);
dst->m[0] = (1.0f / aspectRatio) * factor;
dst->m[5] = factor;
dst->m[10] = (-(zFarPlane + zNearPlane)) * f_n;
dst->m[11] = -1.0f;
dst->m[14] = -2.0f * zFarPlane * zNearPlane * f_n;
}
void Mat4::createOrthographic(float left, float right, float bottom, float top, float zNearPlane, float zFarPlane, Mat4* dst)
{
createOrthographicOffCenter(left, right, bottom, top, zNearPlane, zFarPlane, dst);
}
void Mat4::createOrthographicOffCenter(float left, float right, float bottom, float top,
float zNearPlane, float zFarPlane, Mat4* dst)
{
GP_ASSERT(dst);
GP_ASSERT(right != left);
GP_ASSERT(top != bottom);
GP_ASSERT(zFarPlane != zNearPlane);
memset(dst, 0, MATRIX_SIZE);
dst->m[0] = 2 / (right - left);
dst->m[5] = 2 / (top - bottom);
dst->m[10] = 2 / (zNearPlane - zFarPlane);
dst->m[12] = (left + right) / (left - right);
dst->m[13] = (top + bottom) / (bottom - top);
dst->m[14] = (zNearPlane + zFarPlane) / (zNearPlane - zFarPlane);
dst->m[15] = 1;
}
void Mat4::createBillboard(const Vec3& objectPosition, const Vec3& cameraPosition,
const Vec3& cameraUpVector, Mat4* dst)
{
createBillboardHelper(objectPosition, cameraPosition, cameraUpVector, nullptr, dst);
}
void Mat4::createBillboard(const Vec3& objectPosition, const Vec3& cameraPosition,
const Vec3& cameraUpVector, const Vec3& cameraForwardVector,
Mat4* dst)
{
createBillboardHelper(objectPosition, cameraPosition, cameraUpVector, &cameraForwardVector, dst);
}
void Mat4::createBillboardHelper(const Vec3& objectPosition, const Vec3& cameraPosition,
const Vec3& cameraUpVector, const Vec3* cameraForwardVector,
Mat4* dst)
{
Vec3 delta(objectPosition, cameraPosition);
bool isSufficientDelta = delta.lengthSquared() > MATH_EPSILON;
dst->setIdentity();
dst->m[3] = objectPosition.x;
dst->m[7] = objectPosition.y;
dst->m[11] = objectPosition.z;
// As per the contracts for the 2 variants of createBillboard, we need
// either a safe default or a sufficient distance between object and camera.
if (cameraForwardVector || isSufficientDelta)
{
Vec3 target = isSufficientDelta ? cameraPosition : (objectPosition - *cameraForwardVector);
// A billboard is the inverse of a lookAt rotation
Mat4 lookAt;
createLookAt(objectPosition, target, cameraUpVector, &lookAt);
dst->m[0] = lookAt.m[0];
dst->m[1] = lookAt.m[4];
dst->m[2] = lookAt.m[8];
dst->m[4] = lookAt.m[1];
dst->m[5] = lookAt.m[5];
dst->m[6] = lookAt.m[9];
dst->m[8] = lookAt.m[2];
dst->m[9] = lookAt.m[6];
dst->m[10] = lookAt.m[10];
}
}
// void Mat4::createReflection(const Plane& plane, Mat4* dst)
// {
// Vec3 normal(plane.getNormal());
// float k = -2.0f * plane.getDistance();
// dst->setIdentity();
// dst->m[0] -= 2.0f * normal.x * normal.x;
// dst->m[5] -= 2.0f * normal.y * normal.y;
// dst->m[10] -= 2.0f * normal.z * normal.z;
// dst->m[1] = dst->m[4] = -2.0f * normal.x * normal.y;
// dst->m[2] = dst->m[8] = -2.0f * normal.x * normal.z;
// dst->m[6] = dst->m[9] = -2.0f * normal.y * normal.z;
// dst->m[3] = k * normal.x;
// dst->m[7] = k * normal.y;
// dst->m[11] = k * normal.z;
// }
void Mat4::createScale(const Vec3& scale, Mat4* dst)
{
GP_ASSERT(dst);
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[0] = scale.x;
dst->m[5] = scale.y;
dst->m[10] = scale.z;
}
void Mat4::createScale(float xScale, float yScale, float zScale, Mat4* dst)
{
GP_ASSERT(dst);
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[0] = xScale;
dst->m[5] = yScale;
dst->m[10] = zScale;
}
void Mat4::createRotation(const Quaternion& q, Mat4* dst)
{
GP_ASSERT(dst);
float x2 = q.x + q.x;
float y2 = q.y + q.y;
float z2 = q.z + q.z;
float xx2 = q.x * x2;
float yy2 = q.y * y2;
float zz2 = q.z * z2;
float xy2 = q.x * y2;
float xz2 = q.x * z2;
float yz2 = q.y * z2;
float wx2 = q.w * x2;
float wy2 = q.w * y2;
float wz2 = q.w * z2;
dst->m[0] = 1.0f - yy2 - zz2;
dst->m[1] = xy2 + wz2;
dst->m[2] = xz2 - wy2;
dst->m[3] = 0.0f;
dst->m[4] = xy2 - wz2;
dst->m[5] = 1.0f - xx2 - zz2;
dst->m[6] = yz2 + wx2;
dst->m[7] = 0.0f;
dst->m[8] = xz2 + wy2;
dst->m[9] = yz2 - wx2;
dst->m[10] = 1.0f - xx2 - yy2;
dst->m[11] = 0.0f;
dst->m[12] = 0.0f;
dst->m[13] = 0.0f;
dst->m[14] = 0.0f;
dst->m[15] = 1.0f;
}
void Mat4::createRotation(const Vec3& axis, float angle, Mat4* dst)
{
GP_ASSERT(dst);
float x = axis.x;
float y = axis.y;
float z = axis.z;
// Make sure the input axis is normalized.
float n = x*x + y*y + z*z;
if (n != 1.0f)
{
// Not normalized.
n = std::sqrt(n);
// Prevent divide too close to zero.
if (n > 0.000001f)
{
n = 1.0f / n;
x *= n;
y *= n;
z *= n;
}
}
float c = std::cos(angle);
float s = std::sin(angle);
float t = 1.0f - c;
float tx = t * x;
float ty = t * y;
float tz = t * z;
float txy = tx * y;
float txz = tx * z;
float tyz = ty * z;
float sx = s * x;
float sy = s * y;
float sz = s * z;
dst->m[0] = c + tx*x;
dst->m[1] = txy + sz;
dst->m[2] = txz - sy;
dst->m[3] = 0.0f;
dst->m[4] = txy - sz;
dst->m[5] = c + ty*y;
dst->m[6] = tyz + sx;
dst->m[7] = 0.0f;
dst->m[8] = txz + sy;
dst->m[9] = tyz - sx;
dst->m[10] = c + tz*z;
dst->m[11] = 0.0f;
dst->m[12] = 0.0f;
dst->m[13] = 0.0f;
dst->m[14] = 0.0f;
dst->m[15] = 1.0f;
}
void Mat4::createRotationX(float angle, Mat4* dst)
{
GP_ASSERT(dst);
memcpy(dst, &IDENTITY, MATRIX_SIZE);
float c = std::cos(angle);
float s = std::sin(angle);
dst->m[5] = c;
dst->m[6] = s;
dst->m[9] = -s;
dst->m[10] = c;
}
void Mat4::createRotationY(float angle, Mat4* dst)
{
GP_ASSERT(dst);
memcpy(dst, &IDENTITY, MATRIX_SIZE);
float c = std::cos(angle);
float s = std::sin(angle);
dst->m[0] = c;
dst->m[2] = -s;
dst->m[8] = s;
dst->m[10] = c;
}
void Mat4::createRotationZ(float angle, Mat4* dst)
{
GP_ASSERT(dst);
memcpy(dst, &IDENTITY, MATRIX_SIZE);
float c = std::cos(angle);
float s = std::sin(angle);
dst->m[0] = c;
dst->m[1] = s;
dst->m[4] = -s;
dst->m[5] = c;
}
void Mat4::createTranslation(const Vec3& translation, Mat4* dst)
{
GP_ASSERT(dst);
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[12] = translation.x;
dst->m[13] = translation.y;
dst->m[14] = translation.z;
}
void Mat4::createTranslation(float xTranslation, float yTranslation, float zTranslation, Mat4* dst)
{
GP_ASSERT(dst);
memcpy(dst, &IDENTITY, MATRIX_SIZE);
dst->m[12] = xTranslation;
dst->m[13] = yTranslation;
dst->m[14] = zTranslation;
}
void Mat4::add(float scalar)
{
add(scalar, this);
}
void Mat4::add(float scalar, Mat4* dst)
{
GP_ASSERT(dst);
#ifdef __SSE__
MathUtil::addMatrix(col, scalar, dst->col);
#else
MathUtil::addMatrix(m, scalar, dst->m);
#endif
}
void Mat4::add(const Mat4& mat)
{
add(*this, mat, this);
}
void Mat4::add(const Mat4& m1, const Mat4& m2, Mat4* dst)
{
GP_ASSERT(dst);
#ifdef __SSE__
MathUtil::addMatrix(m1.col, m2.col, dst->col);
#else
MathUtil::addMatrix(m1.m, m2.m, dst->m);
#endif
}
bool Mat4::decompose(Vec3* scale, Quaternion* rotation, Vec3* translation) const
{
if (translation)
{
// Extract the translation.
translation->x = m[12];
translation->y = m[13];
translation->z = m[14];
}
// Nothing left to do.
if (scale == nullptr && rotation == nullptr)
return true;
// Extract the scale.
// This is simply the length of each axis (row/column) in the matrix.
Vec3 xaxis(m[0], m[1], m[2]);
float scaleX = xaxis.length();
Vec3 yaxis(m[4], m[5], m[6]);
float scaleY = yaxis.length();
Vec3 zaxis(m[8], m[9], m[10]);
float scaleZ = zaxis.length();
// Determine if we have a negative scale (true if determinant is less than zero).
// In this case, we simply negate a single axis of the scale.
float det = determinant();
if (det < 0)
scaleZ = -scaleZ;
if (scale)
{
scale->x = scaleX;
scale->y = scaleY;
scale->z = scaleZ;
}
// Nothing left to do.
if (rotation == nullptr)
return true;
// Scale too close to zero, can't decompose rotation.
if (scaleX < MATH_TOLERANCE || scaleY < MATH_TOLERANCE || std::abs(scaleZ) < MATH_TOLERANCE)
return false;
float rn;
// Factor the scale out of the matrix axes.
rn = 1.0f / scaleX;
xaxis.x *= rn;
xaxis.y *= rn;
xaxis.z *= rn;
rn = 1.0f / scaleY;
yaxis.x *= rn;
yaxis.y *= rn;
yaxis.z *= rn;
rn = 1.0f / scaleZ;
zaxis.x *= rn;
zaxis.y *= rn;
zaxis.z *= rn;
// Now calculate the rotation from the resulting matrix (axes).
float trace = xaxis.x + yaxis.y + zaxis.z + 1.0f;
if (trace > MATH_EPSILON)
{
float s = 0.5f / std::sqrt(trace);
rotation->w = 0.25f / s;
rotation->x = (yaxis.z - zaxis.y) * s;
rotation->y = (zaxis.x - xaxis.z) * s;
rotation->z = (xaxis.y - yaxis.x) * s;
}
else
{
// Note: since xaxis, yaxis, and zaxis are normalized,
// we will never divide by zero in the code below.
if (xaxis.x > yaxis.y && xaxis.x > zaxis.z)
{
float s = 0.5f / std::sqrt(1.0f + xaxis.x - yaxis.y - zaxis.z);
rotation->w = (yaxis.z - zaxis.y) * s;
rotation->x = 0.25f / s;
rotation->y = (yaxis.x + xaxis.y) * s;
rotation->z = (zaxis.x + xaxis.z) * s;
}
else if (yaxis.y > zaxis.z)
{
float s = 0.5f / std::sqrt(1.0f + yaxis.y - xaxis.x - zaxis.z);
rotation->w = (zaxis.x - xaxis.z) * s;
rotation->x = (yaxis.x + xaxis.y) * s;
rotation->y = 0.25f / s;
rotation->z = (zaxis.y + yaxis.z) * s;
}
else
{
float s = 0.5f / std::sqrt(1.0f + zaxis.z - xaxis.x - yaxis.y);
rotation->w = (xaxis.y - yaxis.x ) * s;
rotation->x = (zaxis.x + xaxis.z ) * s;
rotation->y = (zaxis.y + yaxis.z ) * s;
rotation->z = 0.25f / s;
}
}
return true;
}
float Mat4::determinant() const
{
float a0 = m[0] * m[5] - m[1] * m[4];
float a1 = m[0] * m[6] - m[2] * m[4];
float a2 = m[0] * m[7] - m[3] * m[4];
float a3 = m[1] * m[6] - m[2] * m[5];
float a4 = m[1] * m[7] - m[3] * m[5];
float a5 = m[2] * m[7] - m[3] * m[6];
float b0 = m[8] * m[13] - m[9] * m[12];
float b1 = m[8] * m[14] - m[10] * m[12];
float b2 = m[8] * m[15] - m[11] * m[12];
float b3 = m[9] * m[14] - m[10] * m[13];
float b4 = m[9] * m[15] - m[11] * m[13];
float b5 = m[10] * m[15] - m[11] * m[14];
// Calculate the determinant.
return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
}
void Mat4::getScale(Vec3* scale) const
{
decompose(scale, nullptr, nullptr);
}
bool Mat4::getRotation(Quaternion* rotation) const
{
return decompose(nullptr, rotation, nullptr);
}
void Mat4::getTranslation(Vec3* translation) const
{
decompose(nullptr, nullptr, translation);
}
void Mat4::getUpVector(Vec3* dst) const
{
GP_ASSERT(dst);
dst->x = m[4];
dst->y = m[5];
dst->z = m[6];
}
void Mat4::getDownVector(Vec3* dst) const
{
GP_ASSERT(dst);
dst->x = -m[4];
dst->y = -m[5];
dst->z = -m[6];
}
void Mat4::getLeftVector(Vec3* dst) const
{
GP_ASSERT(dst);
dst->x = -m[0];
dst->y = -m[1];
dst->z = -m[2];
}
void Mat4::getRightVector(Vec3* dst) const
{
GP_ASSERT(dst);
dst->x = m[0];
dst->y = m[1];
dst->z = m[2];
}
void Mat4::getForwardVector(Vec3* dst) const
{
GP_ASSERT(dst);
dst->x = -m[8];
dst->y = -m[9];
dst->z = -m[10];
}
void Mat4::getBackVector(Vec3* dst) const
{
GP_ASSERT(dst);
dst->x = m[8];
dst->y = m[9];
dst->z = m[10];
}
Mat4 Mat4::getInversed() const
{
Mat4 mat(*this);
mat.inverse();
return mat;
}
bool Mat4::inverse()
{
float a0 = m[0] * m[5] - m[1] * m[4];
float a1 = m[0] * m[6] - m[2] * m[4];
float a2 = m[0] * m[7] - m[3] * m[4];
float a3 = m[1] * m[6] - m[2] * m[5];
float a4 = m[1] * m[7] - m[3] * m[5];
float a5 = m[2] * m[7] - m[3] * m[6];
float b0 = m[8] * m[13] - m[9] * m[12];
float b1 = m[8] * m[14] - m[10] * m[12];
float b2 = m[8] * m[15] - m[11] * m[12];
float b3 = m[9] * m[14] - m[10] * m[13];
float b4 = m[9] * m[15] - m[11] * m[13];
float b5 = m[10] * m[15] - m[11] * m[14];
// Calculate the determinant.
float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
// Close to zero, can't invert.
if (std::abs(det) <= MATH_TOLERANCE)
return false;
// Support the case where m == dst.
Mat4 inverse;
inverse.m[0] = m[5] * b5 - m[6] * b4 + m[7] * b3;
inverse.m[1] = -m[1] * b5 + m[2] * b4 - m[3] * b3;
inverse.m[2] = m[13] * a5 - m[14] * a4 + m[15] * a3;
inverse.m[3] = -m[9] * a5 + m[10] * a4 - m[11] * a3;
inverse.m[4] = -m[4] * b5 + m[6] * b2 - m[7] * b1;
inverse.m[5] = m[0] * b5 - m[2] * b2 + m[3] * b1;
inverse.m[6] = -m[12] * a5 + m[14] * a2 - m[15] * a1;
inverse.m[7] = m[8] * a5 - m[10] * a2 + m[11] * a1;
inverse.m[8] = m[4] * b4 - m[5] * b2 + m[7] * b0;
inverse.m[9] = -m[0] * b4 + m[1] * b2 - m[3] * b0;
inverse.m[10] = m[12] * a4 - m[13] * a2 + m[15] * a0;
inverse.m[11] = -m[8] * a4 + m[9] * a2 - m[11] * a0;
inverse.m[12] = -m[4] * b3 + m[5] * b1 - m[6] * b0;
inverse.m[13] = m[0] * b3 - m[1] * b1 + m[2] * b0;
inverse.m[14] = -m[12] * a3 + m[13] * a1 - m[14] * a0;
inverse.m[15] = m[8] * a3 - m[9] * a1 + m[10] * a0;
multiply(inverse, 1.0f / det, this);
return true;
}
bool Mat4::isIdentity() const
{
return (memcmp(m, &IDENTITY, MATRIX_SIZE) == 0);
}
void Mat4::multiply(float scalar)
{
multiply(scalar, this);
}
void Mat4::multiply(float scalar, Mat4* dst) const
{
multiply(*this, scalar, dst);
}
void Mat4::multiply(const Mat4& m, float scalar, Mat4* dst)
{
GP_ASSERT(dst);
#ifdef __SSE__
MathUtil::multiplyMatrix(m.col, scalar, dst->col);
#else
MathUtil::multiplyMatrix(m.m, scalar, dst->m);
#endif
}
void Mat4::multiply(const Mat4& mat)
{
multiply(*this, mat, this);
}
void Mat4::multiply(const Mat4& m1, const Mat4& m2, Mat4* dst)
{
GP_ASSERT(dst);
#ifdef __SSE__
MathUtil::multiplyMatrix(m1.col, m2.col, dst->col);
#else
MathUtil::multiplyMatrix(m1.m, m2.m, dst->m);
#endif
}
void Mat4::negate()
{
#ifdef __SSE__
MathUtil::negateMatrix(col, col);
#else
MathUtil::negateMatrix(m, m);
#endif
}
Mat4 Mat4::getNegated() const
{
Mat4 mat(*this);
mat.negate();
return mat;
}
void Mat4::rotate(const Quaternion& q)
{
rotate(q, this);
}
void Mat4::rotate(const Quaternion& q, Mat4* dst) const
{
Mat4 r;
createRotation(q, &r);
multiply(*this, r, dst);
}
void Mat4::rotate(const Vec3& axis, float angle)
{
rotate(axis, angle, this);
}
void Mat4::rotate(const Vec3& axis, float angle, Mat4* dst) const
{
Mat4 r;
createRotation(axis, angle, &r);
multiply(*this, r, dst);
}
void Mat4::rotateX(float angle)
{
rotateX(angle, this);
}
void Mat4::rotateX(float angle, Mat4* dst) const
{
Mat4 r;
createRotationX(angle, &r);
multiply(*this, r, dst);
}
void Mat4::rotateY(float angle)
{
rotateY(angle, this);
}
void Mat4::rotateY(float angle, Mat4* dst) const
{
Mat4 r;
createRotationY(angle, &r);
multiply(*this, r, dst);
}
void Mat4::rotateZ(float angle)
{
rotateZ(angle, this);
}
void Mat4::rotateZ(float angle, Mat4* dst) const
{
Mat4 r;
createRotationZ(angle, &r);
multiply(*this, r, dst);
}
void Mat4::scale(float value)
{
scale(value, this);
}
void Mat4::scale(float value, Mat4* dst) const
{
scale(value, value, value, dst);
}
void Mat4::scale(float xScale, float yScale, float zScale)
{
scale(xScale, yScale, zScale, this);
}
void Mat4::scale(float xScale, float yScale, float zScale, Mat4* dst) const
{
Mat4 s;
createScale(xScale, yScale, zScale, &s);
multiply(*this, s, dst);
}
void Mat4::scale(const Vec3& s)
{
scale(s.x, s.y, s.z, this);
}
void Mat4::scale(const Vec3& s, Mat4* dst) const
{
scale(s.x, s.y, s.z, dst);
}
void Mat4::set(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44)
{
m[0] = m11;
m[1] = m21;
m[2] = m31;
m[3] = m41;
m[4] = m12;
m[5] = m22;
m[6] = m32;
m[7] = m42;
m[8] = m13;
m[9] = m23;
m[10] = m33;
m[11] = m43;
m[12] = m14;
m[13] = m24;
m[14] = m34;
m[15] = m44;
}
void Mat4::set(const float* mat)
{
GP_ASSERT(mat);
memcpy(this->m, mat, MATRIX_SIZE);
}
void Mat4::set(const Mat4& mat)
{
memcpy(this->m, mat.m, MATRIX_SIZE);
}
void Mat4::setIdentity()
{
memcpy(m, &IDENTITY, MATRIX_SIZE);
}
void Mat4::setZero()
{
memset(m, 0, MATRIX_SIZE);
}
void Mat4::subtract(const Mat4& mat)
{
subtract(*this, mat, this);
}
void Mat4::subtract(const Mat4& m1, const Mat4& m2, Mat4* dst)
{
GP_ASSERT(dst);
#ifdef __SSE__
MathUtil::subtractMatrix(m1.col, m2.col, dst->col);
#else
MathUtil::subtractMatrix(m1.m, m2.m, dst->m);
#endif
}
void Mat4::transformVector(Vec3* vector) const
{
GP_ASSERT(vector);
transformVector(vector->x, vector->y, vector->z, 0.0f, vector);
}
void Mat4::transformVector(const Vec3& vector, Vec3* dst) const
{
transformVector(vector.x, vector.y, vector.z, 0.0f, dst);
}
void Mat4::transformVector(float x, float y, float z, float w, Vec3* dst) const
{
GP_ASSERT(dst);
MathUtil::transformVec4(m, x, y, z, w, (float*)dst);
}
void Mat4::transformVector(Vec4* vector) const
{
GP_ASSERT(vector);
transformVector(*vector, vector);
}
void Mat4::transformVector(const Vec4& vector, Vec4* dst) const
{
GP_ASSERT(dst);
#ifdef __SSE__
MathUtil::transformVec4(col, vector.v, dst->v);
#else
MathUtil::transformVec4(m, (const float*) &vector, (float*)dst);
#endif
}
void Mat4::translate(float x, float y, float z)
{
translate(x, y, z, this);
}
void Mat4::translate(float x, float y, float z, Mat4* dst) const
{
Mat4 t;
createTranslation(x, y, z, &t);
multiply(*this, t, dst);
}
void Mat4::translate(const Vec3& t)
{
translate(t.x, t.y, t.z, this);
}
void Mat4::translate(const Vec3& t, Mat4* dst) const
{
translate(t.x, t.y, t.z, dst);
}
void Mat4::transpose()
{
#ifdef __SSE__
MathUtil::transposeMatrix(col, col);
#else
MathUtil::transposeMatrix(m, m);
#endif
}
Mat4 Mat4::getTransposed() const
{
Mat4 mat(*this);
mat.transpose();
return mat;
}
const Mat4 Mat4::IDENTITY = Mat4(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
const Mat4 Mat4::ZERO = Mat4(
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 );
NS_CC_MATH_END

999
cocos2d-x/cocos/math/Mat4.h Normal file
View File

@@ -0,0 +1,999 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 MATH_MAT4_H
#define MATH_MAT4_H
#include "base/ccMacros.h"
#include "math/Vec3.h"
#include "math/Vec4.h"
#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.
* */
#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 m11 The first element of the first row.
* @param m12 The second element of the first row.
* @param m13 The third element of the first row.
* @param m14 The fourth element of the first row.
* @param m21 The first element of the second row.
* @param m22 The second element of the second row.
* @param m23 The third element of the second row.
* @param m24 The fourth element of the second row.
* @param m31 The first element of the third row.
* @param m32 The second element of the third row.
* @param m33 The third element of the third row.
* @param m34 The fourth element of the third row.
* @param m41 The first element of the fourth row.
* @param m42 The second element of the fourth row.
* @param m43 The third element of the fourth row.
* @param m44 The fourth element of the fourth row.
*/
Mat4(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44);
/**
* 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.
*/
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();
/**
* 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 targetCenterX, float targetCenterY, float targetCenterZ,
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);
/**
* Creates an orthographic projection matrix.
*
* @param width The width of the view.
* @param height The height of the view.
* @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);
/**
* 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 createOrthographicOffCenter(float left, float right, float bottom, float top,
float zNearPlane, float zFarPlane, 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);
/**
* 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();
/**
* 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 m11 The first element of the first row.
* @param m12 The second element of the first row.
* @param m13 The third element of the first row.
* @param m14 The fourth element of the first row.
* @param m21 The first element of the second row.
* @param m22 The second element of the second row.
* @param m23 The third element of the second row.
* @param m24 The fourth element of the second row.
* @param m31 The first element of the third row.
* @param m32 The second element of the third row.
* @param m33 The third element of the third row.
* @param m34 The fourth element of the third row.
* @param m41 The first element of the fourth row.
* @param m42 The second element of the fourth row.
* @param m43 The third element of the fourth row.
* @param m44 The fourth element of the fourth row.
*/
void set(float m11, float m12, float m13, float m14, float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34, float m41, float m42, float m43, float m44);
/**
* 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 point by this matrix.
*
* The result of the transformation is stored directly into point.
*
* @param point The point to transform and also a vector to hold the result in.
*/
inline void transformPoint(Vec3* point) const { GP_ASSERT(point); transformVector(point->x, point->y, point->z, 1.0f, point); }
/**
* Transforms the specified point by this matrix, and stores
* the result in dst.
*
* @param point The point to transform.
* @param dst A vector to store the transformed point in.
*/
inline void transformPoint(const Vec3& point, Vec3* dst) const { GP_ASSERT(dst); transformVector(point.x, point.y, point.z, 1.0f, dst); }
/**
* Transforms the specified vector by this matrix by
* treating the fourth (w) coordinate as zero.
*
* The result of the transformation is stored directly into vector.
*
* @param vector The vector to transform and also a vector to hold the result in.
*/
void transformVector(Vec3* vector) const;
/**
* Transforms the specified vector by this matrix by
* treating the fourth (w) coordinate as zero, and stores the
* result in dst.
*
* @param vector The vector to transform.
* @param dst A vector to store the transformed vector in.
*/
void transformVector(const Vec3& vector, Vec3* dst) const;
/**
* Transforms the specified vector by this matrix.
*
* @param x The vector x-coordinate to transform by.
* @param y The vector y-coordinate to transform by.
* @param z The vector z-coordinate to transform by.
* @param w The vector w-coordinate to transform by.
* @param dst A vector to store the transformed point in.
*/
void transformVector(float x, float y, float z, float w, Vec3* dst) const;
/**
* 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 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);
/** 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 Vec3& operator*=(Vec3& 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 Vec3 operator*(const Mat4& m, const Vec3& v);
/**
* 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"
#endif // MATH_MAT4_H

View File

@@ -0,0 +1,97 @@
/**
Copyright 2013 BlackBerry Inc.
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 Vec3& operator*=(Vec3& v, const Mat4& m)
{
m.transformVector(&v);
return v;
}
inline const Vec3 operator*(const Mat4& m, const Vec3& v)
{
Vec3 x;
m.transformVector(v, &x);
return x;
}
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

View File

@@ -0,0 +1,286 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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/ccMacros.h"
#if (CC_TARGET_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_TARGET_PLATFORM == CC_PLATFORM_IOS)
#if defined (__arm64__)
#define USE_NEON64
#define INCLUDE_NEON64
#elif defined (__ARM_NEON__)
#define USE_NEON32
#define INCLUDE_NEON32
#else
#endif
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#if defined (__arm64__) || defined (__aarch64__)
#define USE_NEON64
#define INCLUDE_NEON64
#elif defined (__ARM_NEON__)
#define INCLUDE_NEON32
#else
#endif
#else
#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 "math/MathUtil.inl"
NS_CC_MATH_BEGIN
void MathUtil::smooth(float* x, float target, float elapsedTime, float responseTime)
{
GP_ASSERT(x);
if (elapsedTime > 0)
{
*x += (target - *x) * elapsedTime / (elapsedTime + responseTime);
}
}
void MathUtil::smooth(float* x, float target, float elapsedTime, float riseTime, float fallTime)
{
GP_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_TARGET_PLATFORM == CC_PLATFORM_ANDROID) )
class AndroidNeonChecker
{
public:
AndroidNeonChecker()
{
if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM && (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0)
_isNeonEnabled = true;
else
_isNeonEnabled = false;
}
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

View File

@@ -0,0 +1,149 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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/CCMathBase.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

View File

@@ -0,0 +1,218 @@
/**
Copyright 2013 BlackBerry Inc.
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];
}
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

View File

@@ -0,0 +1,271 @@
/**
Copyright 2013 BlackBerry Inc.
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.
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[x, y] // DST->V[z]
"st1 {v13.2s}, [%0], 8 \n\t"
"st1 {v13.s}[2], [%0] \n\t"
:
: "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

View File

@@ -0,0 +1,157 @@
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

View File

@@ -0,0 +1,479 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 "base/ccMacros.h"
NS_CC_MATH_BEGIN
const Quaternion Quaternion::ZERO(0.0f, 0.0f, 0.0f, 0.0f);
Quaternion::Quaternion()
: x(0.0f), y(0.0f), z(0.0f), w(1.0f)
{
}
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);
}
Quaternion::Quaternion(const Quaternion& copy)
{
set(copy);
}
Quaternion::~Quaternion()
{
}
const Quaternion& Quaternion::identity()
{
static Quaternion value(0.0f, 0.0f, 0.0f, 1.0f);
return value;
}
const Quaternion& Quaternion::zero()
{
static Quaternion value(0.0f, 0.0f, 0.0f, 0.0f);
return value;
}
bool Quaternion::isIdentity() const
{
return x == 0.0f && y == 0.0f && z == 0.0f && w == 1.0f;
}
bool Quaternion::isZero() const
{
return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
}
void Quaternion::createFromRotationMatrix(const Mat4& m, Quaternion* dst)
{
m.getRotation(dst);
}
void Quaternion::createFromAxisAngle(const Vec3& axis, float angle, Quaternion* dst)
{
GP_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::conjugate()
{
x = -x;
y = -y;
z = -z;
//w = w;
}
Quaternion Quaternion::getConjugated() const
{
Quaternion q(*this);
q.conjugate();
return q;
}
bool Quaternion::inverse()
{
float n = x * x + y * y + z * z + w * w;
if (n == 1.0f)
{
x = -x;
y = -y;
z = -z;
//w = w;
return true;
}
// Too close to zero.
if (n < 0.000001f)
return false;
n = 1.0f / n;
x = -x * n;
y = -y * n;
z = -z * n;
w = w * n;
return true;
}
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)
{
GP_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 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 < 0.000001f)
return;
n = 1.0f / n;
x *= n;
y *= n;
z *= n;
w *= n;
}
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(float* array)
{
GP_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.0f;
y = 0.0f;
z = 0.0f;
w = 1.0f;
}
float Quaternion::toAxisAngle(Vec3* axis) const
{
GP_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.0f * std::acos(q.w));
}
void Quaternion::toEuler(Vec3* e) const
{
toEuler(*this, e);
}
void Quaternion::toEuler(const Quaternion& q, Vec3* e, bool outerZ)
{
float bank = 0;
float heading = 0;
float attitude = 0;
const float test = q.x * q.y + q.z * q.w;
if (test > 0.499999) {
bank = 0; // default to zero
heading = CC_RADIANS_TO_DEGREES(2 * atan2(q.x, q.w));
attitude = 90;
}
else if (test < -0.499999) {
bank = 0; // default to zero
heading = -CC_RADIANS_TO_DEGREES(2 * atan2(q.x, q.w));
attitude = -90;
}
else {
const float sqx = q.x * q.x;
const float sqy = q.y * q.y;
const float sqz = q.z * q.z;
bank = CC_RADIANS_TO_DEGREES(atan2(2 * q.x * q.w - 2 * q.y * q.z, 1 - 2 * sqx - 2 * sqz));
heading = CC_RADIANS_TO_DEGREES(atan2(2 * q.y * q.w - 2 * q.x * q.z, 1 - 2 * sqy - 2 * sqz));
attitude = CC_RADIANS_TO_DEGREES(asin(2 * test));
if (outerZ) {
bank = -180 * CC_SIGN(bank + 1e-6) + bank;
heading = -180 * CC_SIGN(heading + 1e-6) + heading;
attitude = 180 * CC_SIGN(attitude + 1e-6) - attitude;
}
}
e->x = bank;
e->y = heading;
e->z = attitude;
}
void Quaternion::lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
{
GP_ASSERT(dst);
GP_ASSERT(!(t < 0.0f || t > 1.0f));
if (t == 0.0f)
{
memcpy(dst, &q1, sizeof(float) * 4);
return;
}
else if (t == 1.0f)
{
memcpy(dst, &q2, sizeof(float) * 4);
return;
}
float t1 = 1.0f - 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& q1, const Quaternion& q2, float t, Quaternion* dst)
{
GP_ASSERT(dst);
slerp(q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w, t, &dst->x, &dst->y, &dst->z, &dst->w);
}
void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
{
GP_ASSERT(!(t < 0.0f || t > 1.0f));
Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
slerpForSquad(q1, q2, t, &dstQ);
slerpForSquad(s1, s2, t, &dstS);
slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
}
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.
GP_ASSERT(dstx && dsty && dstz && dstw);
GP_ASSERT(!(t < 0.0f || t > 1.0f));
if (t == 0.0f)
{
*dstx = q1x;
*dsty = q1y;
*dstz = q1z;
*dstw = q1w;
return;
}
else if (t == 1.0f)
{
*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, alpha, beta;
float u, f1, f2a, f2b;
float ratio1, ratio2;
float halfSecHalfTheta, versHalfTheta;
float sqNotU, sqU;
float cosTheta = q1w * q2w + q1x * q2x + q1y * q2y + q1z * q2z;
// As usual in all slerp implementations, we fold theta.
alpha = cosTheta >= 0 ? 1.0f : -1.0f;
halfY = 1.0f + 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.0f - 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.0f - halfY * halfSecHalfTheta;
// Evaluate series expansions of the coefficients.
sqNotU = f1 * f1;
ratio2 = 0.0000440917108f * versHalfTheta;
ratio1 = -0.00158730159f + (sqNotU - 16.0f) * ratio2;
ratio1 = 0.0333333333f + ratio1 * (sqNotU - 9.0f) * versHalfTheta;
ratio1 = -0.333333333f + ratio1 * (sqNotU - 4.0f) * versHalfTheta;
ratio1 = 1.0f + ratio1 * (sqNotU - 1.0f) * versHalfTheta;
sqU = u * u;
ratio2 = -0.00158730159f + (sqU - 16.0f) * ratio2;
ratio2 = 0.0333333333f + ratio2 * (sqU - 9.0f) * versHalfTheta;
ratio2 = -0.333333333f + ratio2 * (sqU - 4.0f) * versHalfTheta;
ratio2 = 1.0f + ratio2 * (sqU - 1.0f) * 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)
{
GP_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.0f)
{
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.0f - 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

View File

@@ -0,0 +1,435 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 QUATERNION_H_
#define QUATERNION_H_
#include "math/Vec3.h"
#include "math/Mat4.h"
//#include "Plane.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
class Mat4;
/**
* 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
{
friend class Curve;
friend class Transform;
public:
/**
* The x-value of the quaternion's vector component.
*/
float x;
/**
* The y-value of the quaternion's vector component.
*/
float y;
/**
* The z-value of the quaternion's vector component.
*/
float z;
/**
* The scalar component of the quaternion.
*/
float w;
/**
* Constructs a quaternion initialized to (0, 0, 0, 1).
*/
Quaternion();
/**
* Constructs a quaternion initialized to (0, 0, 0, 1).
*
* @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.
*/
Quaternion(float* array);
/**
* Constructs a quaternion equal to the rotational part of the specified matrix.
*
* @param m The matrix.
*/
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);
/**
* Constructs a new quaternion that is a copy of the specified one.
*
* @param copy The quaternion to copy.
*/
Quaternion(const Quaternion& copy);
/**
* Destructor.
*/
~Quaternion();
/**
* 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;
/**
* 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);
/**
* 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.
*
* @return true if the inverse can be computed, false otherwise.
*/
bool 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(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* e) const;
/**
* Converts this Quaternion4f to euler angle.
*
* @param e The Vec3f which stores the euler angle.
*/
void toEuler(Vec3* e) const;
/**
* Converts this Quaternion4f to euler angle.
*
* @param e The Vec3f which stores the euler angle.
*/
static void toEuler(const Quaternion& q, Vec3* e, bool outerZ = false);
/**
* 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);
/**
* 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& q1, const Quaternion& q2, 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.
*/
static void squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, 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;
/**
* Calculates the quaternion product of this quaternion with the given vec3.
* @param v The vec3 to multiply.
* @return The vec3 product.
*/
inline Vec3 operator*(const Vec3& v) 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);
/** 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.
*/
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);
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"
#endif

View File

@@ -0,0 +1,51 @@
/**
Copyright 2013 BlackBerry Inc.
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;
}
inline Vec3 Quaternion::operator*(const Vec3& v) const
{
Vec3 uv, uuv;
Vec3 qvec(x, y, z);
Vec3::cross(qvec, v, &uv);
Vec3::cross(qvec, uv, &uuv);
uv *= (2.0f * w);
uuv *= 2.0f;
return v + uv + uuv;
}
NS_CC_MATH_END

View File

@@ -0,0 +1,350 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 "math/MathUtil.h"
#include "base/ccMacros.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;
}
else
{
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)
{
float dz = v1.x * v2.y - v1.y * v2.x;
return atan2f(fabsf(dz) + MATH_FLOAT_SMALL, dot(v1, v2));
}
void Vec2::add(const Vec2& v1, const Vec2& v2, Vec2* dst)
{
GP_ASSERT(dst);
dst->x = v1.x + v2.x;
dst->y = v1.y + v2.y;
}
void Vec2::clamp(const Vec2& min, const Vec2& max)
{
GP_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)
{
GP_ASSERT(dst);
GP_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 n = x * x + y * y;
// 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;
}
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)
{
GP_ASSERT(array);
x = array[0];
y = array[1];
}
void Vec2::subtract(const Vec2& v1, const Vec2& v2, Vec2* dst)
{
GP_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
{
Vec2 a2 = getNormalized();
Vec2 b2 = other.getNormalized();
float angle = atan2f(a2.cross(b2), a2.dot(b2));
if (std::abs(angle) < FLT_EPSILON) return 0.f;
return angle;
}
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
if (crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0)
{
return false;
}
return true;
}
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;
}
if (crossProduct2Vector(A, B, C, D) == 0 &&
(crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0))
{
return true;
}
return false;
}
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, T;
if (isLineIntersect(A, B, C, D, &S, &T )&&
(S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f))
{
return true;
}
return false;
}
Vec2 Vec2::getIntersectPoint(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D)
{
float S, 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

772
cocos2d-x/cocos/math/Vec2.h Normal file
View File

@@ -0,0 +1,772 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 MATH_VEC2_H
#define MATH_VEC2_H
#include <algorithm>
#include <functional>
#include <cmath>
#include "math/CCMathBase.h"
/**
* @addtogroup base
* @{
*/
NS_CC_MATH_BEGIN
/** Clamp a value between from and to.
*/
inline float clampf(float value, float min_inclusive, float max_inclusive)
{
if (min_inclusive > max_inclusive) {
std::swap(min_inclusive, max_inclusive);
}
return value < min_inclusive ? min_inclusive : value < max_inclusive? value : max_inclusive;
}
class Mat4;
/**
* Defines a 2-element floating point vector.
*/
class CC_DLL Vec2
{
public:
/**
* The x coordinate.
*/
float x;
/**
* The y coordinate.
*/
float y;
/**
* 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.
*/
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;
//code added compatible for Point
public:
/**
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
bool fuzzyEquals(const Vec2& target, float variance) const;
/** Calculates distance between point an origin
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
inline float getDistanceSq(const Vec2& other) const {
return (*this - other).getLengthSq();
};
/** Calculates the distance between two points
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
inline float getAngle() const {
return atan2f(y, x);
};
/** @returns the angle in radians between two vector directions
@since v2.1.4
* @js NA
* @lua NA
*/
float getAngle(const Vec2& other) const;
/** Calculates cross product of two points.
@return float
@since v2.1.4
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
inline Vec2 getPerp() const {
return Vec2(-y, x);
};
/** Calculates midpoint between two points.
@return Vec2
@since v3.0
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
inline Vec2 getClampPoint(const Vec2& min_inclusive, const Vec2& max_inclusive) const
{
return Vec2(clampf(x,min_inclusive.x,max_inclusive.x), clampf(y, min_inclusive.y, max_inclusive.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
* @js NA
* @lua NA
*/
inline Vec2 compOp(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
* @js NA
* @lua NA
*/
inline Vec2 getRPerp() const {
return Vec2(y, -x);
};
/** Calculates the projection of this over other.
@return Vec2
@since v2.1.4
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
Vec2 rotateByAngle(const Vec2& pivot, float angle) const;
/**
* @js NA
* @lua NA
*/
static inline Vec2 forAngle(const float a)
{
return Vec2(cosf(a), sinf(a));
}
/** A general line-line intersection test
@param A the startpoint for the first line L1 = (A - B)
@param B the endpoint for the first line L1 = (A - B)
@param C the startpoint for the second line L2 = (C - D)
@param D the endpoint 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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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
* @js NA
* @lua NA
*/
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);
typedef Vec2 Point;
NS_CC_MATH_END
/**
end of base group
@}
*/
#include "math/Vec2.inl"
#endif // MATH_VEC2_H

View File

@@ -0,0 +1,234 @@
/**
Copyright 2013 BlackBerry Inc.
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
{
return Vec2(this->x / s, this->y / s);
}
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

View File

@@ -0,0 +1,283 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 "math/Mat3.hpp"
#include "math/MathUtil.h"
#include "base/ccMacros.h"
#include "math/Quaternion.h"
NS_CC_MATH_BEGIN
Vec3::Vec3()
: x(0.0f), y(0.0f), z(0.0f)
{
}
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)
{
int component = (color >> i*8) & 0x0000ff;
components[componentIndex++] = static_cast<float>(component) / 255.0f;
}
Vec3 value(components);
return value;
}
Vec3::~Vec3()
{
}
float Vec3::angle(const Vec3& v1, const Vec3& v2)
{
float dx = v1.y * v2.z - v1.z * v2.y;
float dy = v1.z * v2.x - v1.x * v2.z;
float dz = v1.x * v2.y - v1.y * v2.x;
return std::atan2(std::sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
}
void Vec3::add(const Vec3& v1, const Vec3& v2, Vec3* dst)
{
GP_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)
{
GP_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)
{
GP_ASSERT(dst);
GP_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)
{
GP_ASSERT(dst);
// NOTE: This code assumes Vec3 struct members are contiguous floats in memory.
// We might want to revisit this (and other areas of code that make this assumption)
// later to guarantee 100% safety/compatibility.
MathUtil::crossVec3(&v1.x, &v2.x, &dst->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)
{
float ix = v.x, iy = v.y, 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::transformMat4(const Vec3& v, const Mat4 &m)
{
float ix = v.x, iy = v.y, iz = v.z;
float rhw = m.m[3] * ix + m.m[7] * iy + m.m[11] * iz + m.m[15];
rhw = rhw ? 1 / rhw : 1;
x = (m.m[0] * ix + m.m[4] * iy + m.m[8] * iz + m.m[12]) * rhw;
y = (m.m[1] * ix + m.m[5] * iy + m.m[9] * iz + m.m[13]) * rhw;
z = (m.m[2] * ix + m.m[6] * iy + m.m[10] * iz + m.m[14]) * rhw;
}
void Vec3::transformQuat(const Quaternion& q)
{
float qx = q.x, qy = q.y, qz = q.z, qw = q.w;
// calculate quat * vec
float ix = qw * x + qy * z - qz * y;
float iy = qw * y + qz * x - qx * z;
float iz = qw * z + qx * y - qy * x;
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
{
float dx = v.x - x;
float dy = v.y - y;
float dz = v.z - z;
return std::sqrt(dx * dx + dy * dy + dz * dz);
}
float Vec3::distanceSquared(const Vec3& v) const
{
float dx = v.x - x;
float dy = v.y - y;
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 n = x * x + y * y + z * z;
// 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;
}
Vec3 Vec3::getNormalized() const
{
Vec3 v(*this);
v.normalize();
return v;
}
void Vec3::subtract(const Vec3& v1, const Vec3& v2, Vec3* dst)
{
GP_ASSERT(dst);
dst->x = v1.x - v2.x;
dst->y = v1.y - v2.y;
dst->z = v1.z - v2.z;
}
void Vec3::smooth(const Vec3& target, float elapsedTime, float responseTime)
{
if (elapsedTime > 0)
{
*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);
NS_CC_MATH_END

553
cocos2d-x/cocos/math/Vec3.h Normal file
View File

@@ -0,0 +1,553 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 MATH_VEC3_H
#define MATH_VEC3_H
#include <cmath>
#include "math/CCMathBase.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();
/**
* 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.
*/
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();
/**
* 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);
/**
* 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 this 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 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.
*
* @return This vector, after the normalization occurs.
*/
void normalize();
/**
* Get the 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.
*/
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);
/**
* 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;
/**
* 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;
/** Returns true if the vector's scalar components are all greater
that the ones of the vector it is compared against.
*/
inline bool operator < (const Vec3& rhs) const
{
if (x < rhs.x && y < rhs.y && z < rhs.z)
return true;
return false;
}
/** Returns true if the vector's scalar components are all smaller
that the ones of the vector it is compared against.
*/
inline bool operator >(const Vec3& rhs) const
{
if (x > rhs.x && y > rhs.y && z > rhs.z)
return true;
return false;
}
/**
* 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;
/**
* 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;
/** 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;
};
/**
* 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"
#endif // MATH_VEC3_H

View File

@@ -0,0 +1,190 @@
/**
Copyright 2013 BlackBerry Inc.
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 "math/Mat4.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)
{
GP_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*=(float s)
{
scale(s);
return *this;
}
inline const Vec3 Vec3::operator/(const float s) const
{
return Vec3(this->x / s, this->y / s, this->z / s);
}
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

View File

@@ -0,0 +1,317 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 "math/MathUtil.h"
#include "base/ccMacros.h"
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)
{
int component = (color >> i*8) & 0x000000ff;
components[componentIndex++] = static_cast<float>(component) / 255.0f;
}
Vec4 value(components);
return value;
}
Vec4::~Vec4()
{
}
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)
{
float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y;
float dy = v1.w * v2.y - v1.y * v2.w - v1.z * v2.x + v1.x * v2.z;
float dz = v1.w * v2.z - v1.z * v2.w - v1.x * v2.y + v1.y * v2.x;
return std::atan2(std::sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
}
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)
{
GP_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)
{
GP_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)
{
GP_ASSERT(dst);
GP_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;
}
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)
{
GP_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)
{
GP_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;
}
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);
NS_CC_MATH_END

470
cocos2d-x/cocos/math/Vec4.h Normal file
View File

@@ -0,0 +1,470 @@
/**
Copyright 2013 BlackBerry Inc.
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 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 MATH_VEC4_H
#define MATH_VEC4_H
#ifdef __SSE__
#include <xmmintrin.h>
#endif
#include "math/CCMathBase.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.
*/
Vec4(const float* array);
/**
* 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);
/**
* Destructor.
*/
~Vec4();
/**
* 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();
/**
* 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);
/**
* 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;
/** 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"
#endif // MATH_VEC4_H

View File

@@ -0,0 +1,114 @@
/**
Copyright 2013 BlackBerry Inc.
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