Add setLocalScaling() method to CollisionShape and ProxyShape and fix issue in collision detection test method

This commit is contained in:
Daniel Chappuis 2015-11-19 07:20:43 +01:00
parent 4eceb7e7c6
commit 3476f3e9c4
26 changed files with 279 additions and 55 deletions

View File

@ -197,15 +197,22 @@ void CollisionBody::updateBroadPhaseState() const {
// For all the proxy collision shapes of the body
for (ProxyShape* shape = mProxyCollisionShapes; shape != NULL; shape = shape->mNext) {
// Recompute the world-space AABB of the collision shape
AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, mTransform *shape->getLocalToBodyTransform());
// Update the broad-phase state for the proxy collision shape
mWorld.mCollisionDetection.updateProxyCollisionShape(shape, aabb);
// Update the proxy
updateProxyShapeInBroadPhase(shape);
}
}
// Update the broad-phase state of a proxy collision shape of the body
void CollisionBody::updateProxyShapeInBroadPhase(ProxyShape* proxyShape) const {
// Recompute the world-space AABB of the collision shape
AABB aabb;
proxyShape->getCollisionShape()->computeAABB(aabb, mTransform * proxyShape->getLocalToBodyTransform());
// Update the broad-phase state for the proxy collision shape
mWorld.mCollisionDetection.updateProxyCollisionShape(proxyShape, aabb);
}
// Set whether or not the body is active
/**
* @param isActive True if you want to activate the body

View File

@ -102,6 +102,9 @@ class CollisionBody : public Body {
/// Update the broad-phase state for this body (because it has moved for instance)
virtual void updateBroadPhaseState() const;
/// Update the broad-phase state of a proxy collision shape of the body
void updateProxyShapeInBroadPhase(ProxyShape* proxyShape) const;
/// Ask the broad-phase to test again the collision shapes of the body for collision
/// (as if the body has moved).
void askForBroadPhaseCollisionCheck() const;

View File

@ -335,9 +335,11 @@ void CollisionDetection::computeNarrowPhaseBetweenShapes(CollisionCallback* call
CollisionShapeInfo shape2Info(shape2, shape2->getCollisionShape(), shape2->getLocalToWorldTransform(),
pair, shape2->getCachedCollisionData());
TestCollisionBetweenShapesCallback narrowPhaseCallback(callback);
// Use the narrow-phase collision detection algorithm to check
// if there really is a collision
narrowPhaseAlgorithm->testCollision(shape1Info, shape2Info, this);
narrowPhaseAlgorithm->testCollision(shape1Info, shape2Info, &narrowPhaseCallback);
}
// Add all the contact manifolds (between colliding bodies) to the bodies
@ -518,3 +520,9 @@ EventListener* CollisionDetection::getWorldEventListener() {
MemoryAllocator& CollisionDetection::getWorldMemoryAllocator() {
return mWorld->mMemoryAllocator;
}
// Called by a narrow-phase collision algorithm when a new contact has been found
void TestCollisionBetweenShapesCallback::notifyContact(OverlappingPair* overlappingPair,
const ContactPointInfo& contactInfo) {
mCollisionCallback->notifyContact(contactInfo);
}

View File

@ -47,6 +47,26 @@ class BroadPhaseAlgorithm;
class CollisionWorld;
class CollisionCallback;
// Class TestCollisionBetweenShapesCallback
class TestCollisionBetweenShapesCallback : public NarrowPhaseCallback {
private:
CollisionCallback* mCollisionCallback;
public:
// Constructor
TestCollisionBetweenShapesCallback(CollisionCallback* callback)
: mCollisionCallback(callback) {
}
// Called by a narrow-phase collision algorithm when a new contact has been found
virtual void notifyContact(OverlappingPair* overlappingPair,
const ContactPointInfo& contactInfo);
};
// Class CollisionDetection
/**
* This class computes the collision detection algorithms. We first

View File

@ -152,6 +152,12 @@ class ProxyShape {
/// Return the pointer to the cached collision data
void** getCachedCollisionData();
/// Return the scaling vector of the collision shape
Vector3 getScaling() const;
/// Set the scaling vector of the collision shape
virtual void setScaling(const Vector3& scaling);
// -------------------- Friendship -------------------- //
friend class OverlappingPair;
@ -293,6 +299,21 @@ inline void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBit
mCollideWithMaskBits = collideWithMaskBits;
}
// Return the scaling vector of the collision shape
inline Vector3 ProxyShape::getScaling() const {
return mCollisionShape->getScaling();
}
// Set the scaling vector of the collision shape
inline void ProxyShape::setScaling(const Vector3& scaling) {
// Set the local scaling of the collision shape
mCollisionShape->setLocalScaling(scaling);
// Notify the body that the proxy shape has to be updated in the broad-phase
mBody->updateProxyShapeInBroadPhase(this);
}
}
#endif

View File

@ -37,6 +37,19 @@ const int TreeNode::NULL_TREE_NODE = -1;
// Constructor
DynamicAABBTree::DynamicAABBTree(decimal extraAABBGap) : mExtraAABBGap(extraAABBGap) {
init();
}
// Destructor
DynamicAABBTree::~DynamicAABBTree() {
// Free the allocated memory for the nodes
free(mNodes);
}
// Initialize the tree
void DynamicAABBTree::init() {
mRootNodeID = TreeNode::NULL_TREE_NODE;
mNbNodes = 0;
mNbAllocatedNodes = 8;
@ -56,11 +69,14 @@ DynamicAABBTree::DynamicAABBTree(decimal extraAABBGap) : mExtraAABBGap(extraAABB
mFreeNodeID = 0;
}
// Destructor
DynamicAABBTree::~DynamicAABBTree() {
// Clear all the nodes and reset the tree
void DynamicAABBTree::reset() {
// Free the allocated memory for the nodes
free(mNodes);
// Initialize the tree
init();
}
// Allocate and return a new node in the tree

View File

@ -159,6 +159,9 @@ class DynamicAABBTree {
/// Internally add an object into the tree
int addObjectInternal(const AABB& aabb);
/// Initialize the tree
void init();
#ifndef NDEBUG
/// Check if the tree structure is valid (for debugging purpose)
@ -214,6 +217,9 @@ class DynamicAABBTree {
/// Return the root AABB of the tree
AABB getRootAABB() const;
/// Clear all the nodes and reset the tree
void reset();
};
// Return true if the node is a leaf of the tree

View File

@ -86,7 +86,7 @@ void ConvexVsTriangleCallback::testTriangle(const Vector3* trianglePoints) {
// Create a triangle collision shape
// TODO : Do we need to use a collision margin for a triangle ?
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2], 0.0);
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2]);
// Select the collision algorithm to use between the triangle and the convex shape
NarrowPhaseAlgorithm* algo = mCollisionDetection->getCollisionAlgorithm(triangleShape.getType(),

View File

@ -97,6 +97,9 @@ class BoxShape : public ConvexShape {
/// Return the extents of the box
Vector3 getExtent() const;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
@ -112,6 +115,14 @@ inline Vector3 BoxShape::getExtent() const {
return mExtent + Vector3(mMargin, mMargin, mMargin);
}
// Set the scaling vector of the collision shape
inline void BoxShape::setLocalScaling(const Vector3& scaling) {
mExtent = (mExtent / mScaling) * scaling;
CollisionShape::setLocalScaling(scaling);
}
// Return the local bounds of the shape in x, y and z directions
/// This method is used to compute the AABB of the box
/**

View File

@ -102,6 +102,9 @@ class CapsuleShape : public ConvexShape {
/// Return the height of the capsule
decimal getHeight() const;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
@ -125,6 +128,15 @@ inline decimal CapsuleShape::getHeight() const {
return mHalfHeight + mHalfHeight;
}
/// Set the scaling vector of the collision shape
inline void CapsuleShape::setLocalScaling(const Vector3& scaling) {
mHalfHeight = (mHalfHeight / mScaling.y) * scaling.y;
mRadius = (mRadius / mScaling.x) * scaling.x;
CollisionShape::setLocalScaling(scaling);
}
// Return the number of bytes used by the collision shape
inline size_t CapsuleShape::getSizeInBytes() const {
return sizeof(CapsuleShape);

View File

@ -32,7 +32,7 @@
using namespace reactphysics3d;
// Constructor
CollisionShape::CollisionShape(CollisionShapeType type) : mType(type){
CollisionShape::CollisionShape(CollisionShapeType type) : mType(type), mScaling(1.0, 1.0, 1.0) {
}

View File

@ -60,6 +60,9 @@ class CollisionShape {
/// Type of the collision shape
CollisionShapeType mType;
/// Scaling vector of the collision shape
Vector3 mScaling;
// -------------------- Methods -------------------- //
@ -97,6 +100,12 @@ class CollisionShape {
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const=0;
/// Return the scaling vector of the collision shape
Vector3 getScaling() const;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local inertia tensor of the collision shapes
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const=0;
@ -129,6 +138,16 @@ inline bool CollisionShape::isConvex(CollisionShapeType shapeType) {
return shapeType != CONCAVE_MESH;
}
// Return the scaling vector of the collision shape
inline Vector3 CollisionShape::getScaling() const {
return mScaling;
}
// Set the scaling vector of the collision shape
inline void CollisionShape::setLocalScaling(const Vector3& scaling) {
mScaling = scaling;
}
// Return the maximum number of contact manifolds allowed in an overlapping
// pair wit the given two collision shape types
inline int CollisionShape::computeNbMaxContactManifolds(CollisionShapeType shapeType1,

View File

@ -80,15 +80,15 @@ void ConcaveMeshShape::initBVHTree() {
// Get the vertices components of the triangle
if (vertexType == TriangleVertexArray::VERTEX_FLOAT_TYPE) {
const float* vertices = (float*)(verticesStart + vertexIndex * vertexStride);
trianglePoints[k][0] = decimal(vertices[0]);
trianglePoints[k][1] = decimal(vertices[1]);
trianglePoints[k][2] = decimal(vertices[2]);
trianglePoints[k][0] = decimal(vertices[0]) * mScaling.x;
trianglePoints[k][1] = decimal(vertices[1]) * mScaling.y;
trianglePoints[k][2] = decimal(vertices[2]) * mScaling.z;
}
else if (vertexType == TriangleVertexArray::VERTEX_DOUBLE_TYPE) {
const double* vertices = (double*)(verticesStart + vertexIndex * vertexStride);
trianglePoints[k][0] = decimal(vertices[0]);
trianglePoints[k][1] = decimal(vertices[1]);
trianglePoints[k][2] = decimal(vertices[2]);
trianglePoints[k][0] = decimal(vertices[0]) * mScaling.x;
trianglePoints[k][1] = decimal(vertices[1]) * mScaling.y;
trianglePoints[k][2] = decimal(vertices[2]) * mScaling.z;
}
}
@ -133,15 +133,15 @@ void ConcaveMeshShape::getTriangleVerticesWithIndexPointer(int32 subPart, int32
// Get the vertices components of the triangle
if (vertexType == TriangleVertexArray::VERTEX_FLOAT_TYPE) {
const float* vertices = (float*)(verticesStart + vertexIndex * vertexStride);
outTriangleVertices[k][0] = decimal(vertices[0]);
outTriangleVertices[k][1] = decimal(vertices[1]);
outTriangleVertices[k][2] = decimal(vertices[2]);
outTriangleVertices[k][0] = decimal(vertices[0]) * mScaling.x;
outTriangleVertices[k][1] = decimal(vertices[1]) * mScaling.y;
outTriangleVertices[k][2] = decimal(vertices[2]) * mScaling.z;
}
else if (vertexType == TriangleVertexArray::VERTEX_DOUBLE_TYPE) {
const double* vertices = (double*)(verticesStart + vertexIndex * vertexStride);
outTriangleVertices[k][0] = decimal(vertices[0]);
outTriangleVertices[k][1] = decimal(vertices[1]);
outTriangleVertices[k][2] = decimal(vertices[2]);
outTriangleVertices[k][0] = decimal(vertices[0]) * mScaling.x;
outTriangleVertices[k][1] = decimal(vertices[1]) * mScaling.y;
outTriangleVertices[k][2] = decimal(vertices[2]) * mScaling.z;
}
}
}

View File

@ -30,7 +30,6 @@
#include "ConcaveShape.h"
#include "collision/broadphase/DynamicAABBTree.h"
#include "collision/TriangleMesh.h"
#include <iostream>
namespace reactphysics3d {
@ -130,6 +129,9 @@ class ConcaveMeshShape : public ConcaveShape {
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local inertia tensor of the collision shape
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const;
@ -150,14 +152,16 @@ inline size_t ConcaveMeshShape::getSizeInBytes() const {
inline Vector3 ConcaveMeshShape::getLocalSupportPointWithMargin(const Vector3& direction,
void** cachedCollisionData) const {
// TODO : Implement this
// Should not be used
assert(false);
return Vector3(0, 0, 0);
}
// Return a local support point in a given direction without the object margin
inline Vector3 ConcaveMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
void** cachedCollisionData) const {
// TODO : Implement this
// Should not be used
assert(false);
return Vector3(0.0, 0.0, 0.0);
}
@ -176,6 +180,18 @@ inline void ConcaveMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
max = treeAABB.getMax();
}
// Set the local scaling vector of the collision shape
inline void ConcaveMeshShape::setLocalScaling(const Vector3& scaling) {
CollisionShape::setLocalScaling(scaling);
// Reset the Dynamic AABB Tree
mDynamicAABBTree.reset();
// Rebuild Dynamic AABB Tree here
initBVHTree();
}
// Return the local inertia tensor of the sphere
/**
* @param[out] tensor The 3x3 inertia tensor matrix of the shape in local-space
@ -213,9 +229,6 @@ inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int nodeId)
// Call the callback to test narrow-phase collision with this triangle
mTriangleTestCallback.testTriangle(trianglePoints);
// TODO : Delete this
std::cout << "Notify triangle test" << std::endl;
}
}

View File

@ -105,6 +105,9 @@ class ConeShape : public ConvexShape {
/// Return the height
decimal getHeight() const;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
@ -128,6 +131,15 @@ inline decimal ConeShape::getHeight() const {
return decimal(2.0) * mHalfHeight;
}
// Set the scaling vector of the collision shape
inline void ConeShape::setLocalScaling(const Vector3& scaling) {
mHalfHeight = (mHalfHeight / mScaling.y) * scaling.y;
mRadius = (mRadius / mScaling.x) * scaling.x;
CollisionShape::setLocalScaling(scaling);
}
// Return the number of bytes used by the collision shape
inline size_t ConeShape::getSizeInBytes() const {
return sizeof(ConeShape);

View File

@ -148,7 +148,7 @@ Vector3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direct
*((int*)(*cachedCollisionData)) = maxVertex;
// Return the support vertex
return mVertices[maxVertex];
return mVertices[maxVertex] * mScaling;
}
else { // If the edges information is not used
@ -171,7 +171,7 @@ Vector3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direct
assert(maxDotProduct >= decimal(0.0));
// Return the vertex with the largest dot product in the support direction
return mVertices[indexMaxDotProduct];
return mVertices[indexMaxDotProduct] * mScaling;
}
}

View File

@ -44,7 +44,7 @@ class CollisionWorld;
// TODO : Make possible to create a ConvexMeshShape using a TriangleMesh as for
// the ConcaveMeshShape
// TODO : Make possible for the user to have a scaling factor on the mesh
// TODO : Check that scaling factor is working after the change of the previous TODO
// Class ConvexMeshShape
/**
@ -64,6 +64,8 @@ class CollisionWorld;
*/
class ConvexMeshShape : public ConvexShape {
// TODO : Implement method setLocalScaling() here
protected :
// -------------------- Attributes -------------------- //

View File

@ -102,6 +102,9 @@ class CylinderShape : public ConvexShape {
/// Return the height
decimal getHeight() const;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
@ -125,6 +128,15 @@ inline decimal CylinderShape::getHeight() const {
return mHalfHeight + mHalfHeight;
}
// Set the scaling vector of the collision shape
inline void CylinderShape::setLocalScaling(const Vector3& scaling) {
mHalfHeight = (mHalfHeight / mScaling.y) * scaling.y;
mRadius = (mRadius / mScaling.x) * scaling.x;
CollisionShape::setLocalScaling(scaling);
}
// Return the number of bytes used by the collision shape
inline size_t CylinderShape::getSizeInBytes() const {
return sizeof(CylinderShape);

View File

@ -35,7 +35,7 @@ using namespace reactphysics3d;
/**
* @param radius Radius of the sphere (in meters)
*/
SphereShape::SphereShape(decimal radius) : ConvexShape(SPHERE, radius), mRadius(radius) {
SphereShape::SphereShape(decimal radius) : ConvexShape(SPHERE, radius) {
assert(radius > decimal(0.0));
}
@ -51,7 +51,7 @@ bool SphereShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape*
const Vector3 sphereCenter = proxyShape->getLocalToWorldTransform().getPosition();
const Vector3 m = ray.point1 - sphereCenter;
decimal c = m.dot(m) - mRadius * mRadius;
decimal c = m.dot(m) - mMargin * mMargin;
// If the origin of the ray is inside the sphere, we return no intersection
if (c < decimal(0.0)) return false;

View File

@ -48,8 +48,6 @@ class SphereShape : public ConvexShape {
// -------------------- Attributes -------------------- //
/// Radius of the sphere
decimal mRadius;
// -------------------- Methods -------------------- //
@ -89,6 +87,9 @@ class SphereShape : public ConvexShape {
/// Return the radius of the sphere
decimal getRadius() const;
/// Set the scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
@ -104,7 +105,15 @@ class SphereShape : public ConvexShape {
* @return Radius of the sphere (in meters)
*/
inline decimal SphereShape::getRadius() const {
return mRadius;
return mMargin;
}
// Set the scaling vector of the collision shape
inline void SphereShape::setLocalScaling(const Vector3& scaling) {
mMargin = (mMargin / mScaling.x) * scaling.x;
CollisionShape::setLocalScaling(scaling);
}
// Return the number of bytes used by the collision shape
@ -145,12 +154,12 @@ inline Vector3 SphereShape::getLocalSupportPointWithoutMargin(const Vector3& dir
inline void SphereShape::getLocalBounds(Vector3& min, Vector3& max) const {
// Maximum bounds
max.x = mRadius;
max.y = mRadius;
max.z = mRadius;
max.x = mMargin;
max.y = mMargin;
max.z = mMargin;
// Minimum bounds
min.x = -mRadius;
min.x = -mMargin;
min.y = min.x;
min.z = min.x;
}
@ -162,7 +171,7 @@ inline void SphereShape::getLocalBounds(Vector3& min, Vector3& max) const {
* @param mass Mass to use to compute the inertia tensor of the collision shape
*/
inline void SphereShape::computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const {
decimal diag = decimal(0.4) * mass * mRadius * mRadius;
decimal diag = decimal(0.4) * mass * mMargin * mMargin;
tensor.setAllValues(diag, 0.0, 0.0,
0.0, diag, 0.0,
0.0, 0.0, diag);
@ -177,7 +186,7 @@ inline void SphereShape::computeLocalInertiaTensor(Matrix3x3& tensor, decimal ma
inline void SphereShape::computeAABB(AABB& aabb, const Transform& transform) {
// Get the local extents in x,y and z direction
Vector3 extents(mRadius, mRadius, mRadius);
Vector3 extents(mMargin, mMargin, mMargin);
// Update the AABB with the new minimum and maximum coordinates
aabb.setMin(transform.getPosition() - extents);
@ -186,7 +195,7 @@ inline void SphereShape::computeAABB(AABB& aabb, const Transform& transform) {
// Return true if a point is inside the collision shape
inline bool SphereShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
return (localPoint.lengthSquare() < mRadius * mRadius);
return (localPoint.lengthSquare() < mMargin * mMargin);
}
}

View File

@ -38,9 +38,8 @@ using namespace reactphysics3d;
* @param point3 Third point of the triangle
* @param margin The collision margin (in meters) around the collision shape
*/
TriangleShape::TriangleShape(const Vector3& point1, const Vector3& point2,
const Vector3& point3, decimal margin)
: ConvexShape(TRIANGLE, margin) {
TriangleShape::TriangleShape(const Vector3& point1, const Vector3& point2, const Vector3& point3)
: ConvexShape(TRIANGLE, 0) {
mPoints[0] = point1;
mPoints[1] = point2;
mPoints[2] = point3;

View File

@ -77,8 +77,7 @@ class TriangleShape : public ConvexShape {
// -------------------- Methods -------------------- //
/// Constructor
TriangleShape(const Vector3& point1, const Vector3& point2,
const Vector3& point3, decimal margin);
TriangleShape(const Vector3& point1, const Vector3& point2, const Vector3& point3);
/// Destructor
virtual ~TriangleShape();
@ -86,6 +85,9 @@ class TriangleShape : public ConvexShape {
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
/// Set the local scaling vector of the collision shape
virtual void setLocalScaling(const Vector3& scaling);
/// Return the local inertia tensor of the collision shape
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const;
@ -102,8 +104,6 @@ inline size_t TriangleShape::getSizeInBytes() const {
inline Vector3 TriangleShape::getLocalSupportPointWithMargin(const Vector3& direction,
void** cachedCollisionData) const {
// TODO : Do we need to use margin for triangle support point ?
return getLocalSupportPointWithoutMargin(direction, cachedCollisionData);
}
@ -129,6 +129,16 @@ inline void TriangleShape::getLocalBounds(Vector3& min, Vector3& max) const {
max.setAllValues(xAxis.getMaxValue(), yAxis.getMaxValue(), zAxis.getMaxValue());
}
// Set the local scaling vector of the collision shape
inline void TriangleShape::setLocalScaling(const Vector3& scaling) {
mPoints[0] = (mPoints[0] / mScaling) * scaling;
mPoints[1] = (mPoints[1] / mScaling) * scaling;
mPoints[2] = (mPoints[2] / mScaling) * scaling;
CollisionShape::setLocalScaling(scaling);
}
// Return the local inertia tensor of the triangle shape
/**
* @param[out] tensor The 3x3 inertia tensor matrix of the shape in local-space

View File

@ -145,7 +145,9 @@ struct Vector2 {
friend Vector2 operator-(const Vector2& vector);
friend Vector2 operator*(const Vector2& vector, decimal number);
friend Vector2 operator*(decimal number, const Vector2& vector);
friend Vector2 operator*(const Vector2& vector1, const Vector2& vector2);
friend Vector2 operator/(const Vector2& vector, decimal number);
friend Vector2 operator/(const Vector2& vector1, const Vector2& vector2);
};
// Set the vector to zero
@ -279,12 +281,24 @@ inline Vector2 operator*(const Vector2& vector, decimal number) {
return Vector2(number * vector.x, number * vector.y);
}
// Overloaded operator for multiplication of two vectors
inline Vector2 operator*(const Vector2& vector1, const Vector2& vector2) {
return Vector2(vector1.x * vector2.x, vector1.y * vector2.y);
}
// Overloaded operator for division by a number
inline Vector2 operator/(const Vector2& vector, decimal number) {
assert(number > MACHINE_EPSILON);
return Vector2(vector.x / number, vector.y / number);
}
// Overload operator for division between two vectors
inline Vector2 operator/(const Vector2& vector1, const Vector2& vector2) {
assert(vector2.x > MACHINE_EPSILON);
assert(vector2.y > MACHINE_EPSILON);
return Vector2(vector1.x / vector2.x, vector1.y / vector2.y);
}
// Overloaded operator for multiplication with a number
inline Vector2 operator*(decimal number, const Vector2& vector) {
return vector * number;

View File

@ -157,7 +157,9 @@ struct Vector3 {
friend Vector3 operator-(const Vector3& vector);
friend Vector3 operator*(const Vector3& vector, decimal number);
friend Vector3 operator*(decimal number, const Vector3& vector);
friend Vector3 operator*(const Vector3& vector1, const Vector3& vector2);
friend Vector3 operator/(const Vector3& vector, decimal number);
friend Vector3 operator/(const Vector3& vector1, const Vector3& vector2);
};
// Set the vector to zero
@ -311,11 +313,24 @@ inline Vector3 operator/(const Vector3& vector, decimal number) {
return Vector3(vector.x / number, vector.y / number, vector.z / number);
}
// Overload operator for division between two vectors
inline Vector3 operator/(const Vector3& vector1, const Vector3& vector2) {
assert(vector2.x > MACHINE_EPSILON);
assert(vector2.y > MACHINE_EPSILON);
assert(vector2.z > MACHINE_EPSILON);
return Vector3(vector1.x / vector2.x, vector1.y / vector2.y, vector1.z / vector2.z);
}
// Overloaded operator for multiplication with a number
inline Vector3 operator*(decimal number, const Vector3& vector) {
return vector * number;
}
// Overload operator for multiplication between two vectors
inline Vector3 operator*(const Vector3& vector1, const Vector3& vector2) {
return Vector3(vector1.x * vector2.x, vector1.y * vector2.y, vector1.z * vector2.z);
}
// Assignment operator
inline Vector3& Vector3::operator=(const Vector3& vector) {
if (&vector != this) {

View File

@ -201,10 +201,17 @@ class TestVector2 : public Test {
vector4 /= 3;
test(vector3 == Vector2(60, 330));
test(vector4 == Vector2(5, 20));
Vector2 vector5(21, 80);
Vector2 vector6(7, 10);
Vector2 vector7 = vector5 * vector6;
test(vector7 == Vector2(147, 800));
Vector2 vector8 = vector5 / vector6;
test(approxEqual(vector8.x, 3));
test(approxEqual(vector8.y, 8));
// Negative operator
Vector2 vector5(-34, 5);
Vector2 negative = -vector5;
Vector2 vector9(-34, 5);
Vector2 negative = -vector9;
test(negative == Vector2(34, -5));
}
};

View File

@ -225,10 +225,18 @@ class TestVector3 : public Test {
vector4 /= 3;
test(vector3 == Vector3(60, 330, 620));
test(vector4 == Vector3(5, 20, 11));
Vector3 vector5(21, 80, 45);
Vector3 vector6(7, 10, 3);
Vector3 vector7 = vector5 * vector6;
test(vector7 == Vector3(147, 800, 135));
Vector3 vector8 = vector5 / vector6;
test(approxEqual(vector8.x, 3));
test(approxEqual(vector8.y, 8));
test(approxEqual(vector8.z, 15));
// Negative operator
Vector3 vector5(-34, 5, 422);
Vector3 negative = -vector5;
Vector3 vector9(-34, 5, 422);
Vector3 negative = -vector9;
test(negative == Vector3(34, -5, -422));
}
};