Apply changes from latest known public version of bounce dated 2019-11-13

This commit is contained in:
Luke Benstead
2020-01-25 12:31:05 +00:00
parent f87e2a6378
commit a61262407c
431 changed files with 108959 additions and 26372 deletions

View File

@ -22,7 +22,6 @@
// Include this file header in your project to directly access Bounce objects.
#include <bounce/common/settings.h>
#include <bounce/common/time.h>
#include <bounce/common/draw.h>
#include <bounce/common/math/math.h>
@ -31,14 +30,18 @@
#include <bounce/collision/sat/sat.h>
#include <bounce/collision/collision.h>
#include <bounce/collision/broad_phase.h>
#include <bounce/collision/time_of_impact.h>
#include <bounce/collision/shapes/sphere.h>
#include <bounce/collision/shapes/capsule.h>
#include <bounce/collision/shapes/hull.h>
#include <bounce/collision/shapes/box_hull.h>
#include <bounce/collision/shapes/cylinder_hull.h>
#include <bounce/collision/shapes/cone_hull.h>
#include <bounce/collision/shapes/qhull.h>
#include <bounce/collision/shapes/mesh.h>
#include <bounce/collision/shapes/grid_mesh.h>
#include <bounce/collision/shapes/sdf.h>
#include <bounce/dynamics/joints/mouse_joint.h>
#include <bounce/dynamics/joints/spring_joint.h>
@ -46,11 +49,17 @@
#include <bounce/dynamics/joints/sphere_joint.h>
#include <bounce/dynamics/joints/revolute_joint.h>
#include <bounce/dynamics/joints/cone_joint.h>
#include <bounce/dynamics/joints/friction_joint.h>
#include <bounce/dynamics/joints/motor_joint.h>
#include <bounce/dynamics/joints/prismatic_joint.h>
#include <bounce/dynamics/joints/wheel_joint.h>
#include <bounce/dynamics/shapes/sphere_shape.h>
#include <bounce/dynamics/shapes/capsule_shape.h>
#include <bounce/dynamics/shapes/triangle_shape.h>
#include <bounce/dynamics/shapes/hull_shape.h>
#include <bounce/dynamics/shapes/mesh_shape.h>
#include <bounce/dynamics/shapes/sdf_shape.h>
#include <bounce/dynamics/contacts/contact.h>
#include <bounce/dynamics/contacts/convex_contact.h>
@ -63,17 +72,25 @@
#include <bounce/rope/rope.h>
#include <bounce/sparse/sparse.h>
#include <bounce/cloth/cloth_mesh.h>
#include <bounce/cloth/grid_cloth_mesh.h>
#include <bounce/cloth/garment_cloth_mesh.h>
#include <bounce/cloth/cloth.h>
#include <bounce/cloth/particle.h>
#include <bounce/cloth/cloth_triangle.h>
#include <bounce/cloth/forces/strech_force.h>
#include <bounce/cloth/cloth.h>
#include <bounce/cloth/cloth_particle.h>
#include <bounce/cloth/shapes/cloth_sphere_shape.h>
#include <bounce/cloth/shapes/cloth_capsule_shape.h>
#include <bounce/cloth/shapes/cloth_triangle_shape.h>
#include <bounce/cloth/shapes/cloth_world_shape.h>
#include <bounce/cloth/forces/stretch_force.h>
#include <bounce/cloth/forces/shear_force.h>
#include <bounce/cloth/forces/spring_force.h>
#include <bounce/cloth/forces/mouse_force.h>
#include <bounce/cloth/forces/element_force.h>
#include <bounce/cloth/garment/sewing_pattern.h>
#include <bounce/cloth/garment/garment.h>
@ -83,5 +100,11 @@
#include <bounce/softbody/block_softbody_mesh.h>
#include <bounce/softbody/softbody.h>
#include <bounce/softbody/softbody_node.h>
#include <bounce/softbody/softbody_element.h>
#include <bounce/softbody/shapes/softbody_sphere_shape.h>
#include <bounce/softbody/shapes/softbody_world_shape.h>
#include <bounce/softbody/joints/softbody_anchor.h>
#endif

View File

@ -25,102 +25,113 @@
#include <bounce/common/math/transform.h>
#include <bounce/cloth/cloth_contact_manager.h>
class b3World;
struct b3ClothMesh;
struct b3ParticleDef;
class b3Particle;
struct b3ClothParticleDef;
class b3ClothParticle;
struct b3ForceDef;
class b3Force;
class b3ClothTriangle;
struct b3ClothSphereShapeDef;
class b3ClothSphereShape;
struct b3ClothMesh;
struct b3ClothCapsuleShapeDef;
class b3ClothCapsuleShape;
class b3RayCastListener;
struct b3ClothTriangleShapeDef;
class b3ClothTriangleShape;
struct b3ClothWorldShapeDef;
class b3ClothWorldShape;
struct b3RayCastInput;
struct b3RayCastOutput;
struct b3ClothTimeStep;
struct b3ClothRayCastSingleOutput
{
u32 triangle;
float32 fraction;
b3ClothTriangleShape* triangle;
scalar fraction;
b3Vec3 normal;
};
// Cloth definition
// This requires defining a cloth mesh which is typically bound to a render mesh
// This requires defining a cloth mesh which is typically bound to a render mesh
// and some uniform parameters.
struct b3ClothDef
{
b3ClothDef()
{
mesh = nullptr;
density = 0.0f;
streching = 0.0f;
shearing = 0.0f;
bending = 0.0f;
sewing = 0.0f;
damping = 0.0f;
thickness = 0.0f;
friction = 0.2f;
density = scalar(0);
streching = scalar(0);
strechDamping = scalar(0);
shearing = scalar(0);
shearDamping = scalar(0);
bending = scalar(0);
bendDamping = scalar(0);
sewing = scalar(0);
sewDamping = scalar(0);
thickness = scalar(0);
friction = scalar(0.2);
}
// Cloth mesh
const b3ClothMesh* mesh;
// Cloth density in kg/m^2
float32 density;
scalar density;
// Streching stiffness
float32 streching;
scalar streching;
// Strech damping stiffness
scalar strechDamping;
// Shearing stiffness
float32 shearing;
scalar shearing;
// Shear damping stiffness
scalar shearDamping;
// Bending stiffness
float32 bending;
scalar bending;
// Sewing stiffness
float32 sewing;
// Bend damping stiffness
scalar bendDamping;
// Damping stiffness
float32 damping;
// Sewing stiffness
scalar sewing;
// Sew damping stiffness
scalar sewDamping;
// Cloth thickness
float32 thickness;
// Shape thickness
scalar thickness;
// Cloth coefficient of friction
float32 friction;
// Shape coefficient of friction
scalar friction;
};
// A cloth represents a deformable surface as a collection of particles.
// Particles may be connected with each other by springs.
// Particles may be connected with each other by forces.
class b3Cloth
{
public:
b3Cloth();
b3Cloth(const b3ClothDef& def);
~b3Cloth();
// Set the acceleration of gravity.
void SetGravity(const b3Vec3& gravity);
// Get the acceleration of gravity.
b3Vec3 GetGravity() const;
// Attach a world to this cloth.
// The cloth will be able to respond to collisions with the rigid bodies in the attached world.
void SetWorld(b3World* world);
// Get the world attached to this cloth.
const b3World* GetWorld() const;
b3World* GetWorld();
// Create a particle.
b3Particle* CreateParticle(const b3ParticleDef& def);
b3ClothParticle* CreateParticle(const b3ClothParticleDef& def);
// Destroy a given particle.
void DestroyParticle(b3Particle* particle);
void DestroyParticle(b3ClothParticle* particle);
// Return the list of particles in this cloth.
const b3List2<b3ClothParticle>& GetParticleList() const;
// Create a force.
b3Force* CreateForce(const b3ForceDef& def);
@ -128,82 +139,158 @@ public:
// Destroy a given force.
void DestroyForce(b3Force* force);
// Perform a ray cast with the cloth.
bool RayCastSingle(b3ClothRayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const;
// Perform a ray cast with a given cloth mesh triangle.
bool RayCast(b3RayCastOutput* output, const b3RayCastInput* input, u32 triangleIndex) const;
// Return the cloth mesh proxy.
const b3ClothMesh* GetMesh() const;
// Return the cloth particle given the vertex index.
b3Particle* GetParticle(u32 i);
// Return the cloth triangle given the triangle index.
b3ClothTriangle* GetTriangle(u32 i);
// Return the list of particles in this cloth.
const b3List2<b3Particle>& GetParticleList() const;
// Return the list of forces in this cloth.
const b3List2<b3Force>& GetForceList() const;
// Return the kinetic (or dynamic) energy in this system.
float32 GetEnergy() const;
// Create a sphere shape.
b3ClothSphereShape* CreateSphereShape(const b3ClothSphereShapeDef& def);
// Destroy a given sphere shape.
void DestroySphereShape(b3ClothSphereShape* shape);
// Return the list of sphere shapes in this cloth.
const b3List2<b3ClothSphereShape>& GetSphereShapeList() const;
// Create a capsule shape.
b3ClothCapsuleShape* CreateCapsuleShape(const b3ClothCapsuleShapeDef& def);
// Destroy a given capsule shape.
void DestroyCapsuleShape(b3ClothCapsuleShape* shape);
// Return the list of capsule shapes in this cloth.
const b3List2<b3ClothCapsuleShape>& GetCapsuleShapeList() const;
// Create a triangle shape.
b3ClothTriangleShape* CreateTriangleShape(const b3ClothTriangleShapeDef& def);
// Destroy a given triangle shape.
void DestroyTriangleShape(b3ClothTriangleShape* shape);
// Return the list of triangle shapes in this cloth.
const b3List2<b3ClothTriangleShape>& GetTriangleShapeList() const;
// Create a new world shape.
b3ClothWorldShape* CreateWorldShape(const b3ClothWorldShapeDef& def);
// Destroy a given world shape.
void DestroyWorldShape(b3ClothWorldShape* shape);
// Return the list of world shapes in this cloth.
const b3List2<b3ClothWorldShape>& GetWorldShapeList() const;
// Set the acceleration of gravity.
void SetGravity(const b3Vec3& gravity);
// Get the acceleration of gravity.
b3Vec3 GetGravity() const;
// Perform a time step.
void Step(float32 dt, u32 velocityIterations, u32 positionIterations);
void Step(scalar dt, u32 velocityIterations, u32 positionIterations);
// Debug draw the cloth using the associated cloth mesh.
// Perform a ray cast with the cloth.
bool RayCastSingle(b3ClothRayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const;
// Get the cloth mesh.
const b3ClothMesh* GetMesh() const;
// Get mesh particle.
b3ClothParticle* GetParticle(u32 index);
// Get mesh sphere.
b3ClothSphereShape* GetSphere(u32 index);
// Get mesh triangle.
b3ClothTriangleShape* GetTriangle(u32 index);
// Enable or disable self-collision.
void EnableSelfCollision(bool flag);
// Is self-collision enabled?
bool IsSelfCollisionEnabled() const;
// Return the kinetic (or dynamic) energy in this system.
scalar GetEnergy() const;
// Debug draw the cloth entities.
void Draw() const;
private:
friend class b3Particle;
friend class b3ClothTriangle;
friend class b3ClothParticle;
friend class b3ClothSphereShape;
friend class b3ClothCapsuleShape;
friend class b3ClothTriangleShape;
friend class b3ClothWorldShape;
friend class b3ShearForce;
friend class b3StrechForce;
friend class b3StretchForce;
friend class b3SpringForce;
friend class b3MouseForce;
friend class b3ClothContactManager;
// Compute mass of each particle.
void ComputeMass();
// Rest the mass data of the cloth.
void ResetMass();
// Solve
void Solve(float32 dt, const b3Vec3& gravity, u32 velocityIterations, u32 positionIterations);
void Solve(const b3ClothTimeStep& step);
// Stack allocator
b3StackAllocator m_stackAllocator;
// The world attached to this cloth
b3World* m_world;
// Gravity acceleration
b3Vec3 m_gravity;
// Proxy mesh
const b3ClothMesh* m_mesh;
// Particles
b3Particle** m_particles;
// Triangles
b3ClothTriangle* m_triangles;
// Cloth density
float32 m_density;
// Pool of particles
b3BlockPool m_particleBlocks;
// Pool of sphere shapes
b3BlockPool m_sphereShapeBlocks;
// Pool of capsule shapes
b3BlockPool m_capsuleShapeBlocks;
// Pool of triangle shapes
b3BlockPool m_triangleShapeBlocks;
// Pool of world shapes
b3BlockPool m_worldShapeBlocks;
// List of particles
b3List2<b3Particle> m_particleList;
b3List2<b3ClothParticle> m_particleList;
// List of forces
b3List2<b3Force> m_forceList;
// List of sphere shapes
b3List2<b3ClothSphereShape> m_sphereShapeList;
// List of capsule shapes
b3List2<b3ClothCapsuleShape> m_capsuleShapeList;
// List of triangle shapes
b3List2<b3ClothTriangleShape> m_triangleShapeList;
// List of world shapes
b3List2<b3ClothWorldShape> m_worldShapeList;
// Contact manager
b3ClothContactManager m_contactManager;
// Used to compute the time step ratio to
// support variable time steps.
scalar m_inv_dt0;
// Mesh
const b3ClothMesh* m_mesh;
// Mesh vertex particles
b3ClothParticle** m_particles;
// Mesh vertex sphere shapes
b3ClothSphereShape** m_spheres;
// Mesh triangle triangle shapes
b3ClothTriangleShape** m_triangles;
// Self-collision activation flag
bool m_enableSelfCollision;
};
inline void b3Cloth::SetGravity(const b3Vec3& gravity)
@ -216,24 +303,9 @@ inline b3Vec3 b3Cloth::GetGravity() const
return m_gravity;
}
inline const b3World* b3Cloth::GetWorld() const
inline bool b3Cloth::IsSelfCollisionEnabled() const
{
return m_world;
}
inline b3World* b3Cloth::GetWorld()
{
return m_world;
}
inline const b3ClothMesh* b3Cloth::GetMesh() const
{
return m_mesh;
}
inline const b3List2<b3Particle>& b3Cloth::GetParticleList() const
{
return m_particleList;
return m_enableSelfCollision;
}
inline const b3List2<b3Force>& b3Cloth::GetForceList() const
@ -241,4 +313,34 @@ inline const b3List2<b3Force>& b3Cloth::GetForceList() const
return m_forceList;
}
inline const b3List2<b3ClothParticle>& b3Cloth::GetParticleList() const
{
return m_particleList;
}
inline const b3List2<b3ClothSphereShape>& b3Cloth::GetSphereShapeList() const
{
return m_sphereShapeList;
}
inline const b3List2<b3ClothCapsuleShape>& b3Cloth::GetCapsuleShapeList() const
{
return m_capsuleShapeList;
}
inline const b3List2<b3ClothTriangleShape>& b3Cloth::GetTriangleShapeList() const
{
return m_triangleShapeList;
}
inline const b3List2<b3ClothWorldShape>& b3Cloth::GetWorldShapeList() const
{
return m_worldShapeList;
}
inline const b3ClothMesh* b3Cloth::GetMesh() const
{
return m_mesh;
}
#endif

View File

@ -19,8 +19,9 @@
#ifndef B3_CLOTH_CONTACT_MANAGER_H
#define B3_CLOTH_CONTACT_MANAGER_H
#include <bounce/cloth/contacts/cloth_particle_body_contact.h>
#include <bounce/cloth/contacts/cloth_particle_triangle_contact.h>
#include <bounce/cloth/contacts/cloth_sphere_triangle_contact.h>
#include <bounce/cloth/contacts/cloth_sphere_shape_contact.h>
#include <bounce/cloth/contacts/cloth_capsule_capsule_contact.h>
#include <bounce/collision/broad_phase.h>
#include <bounce/common/memory/block_pool.h>
#include <bounce/common/template/list.h>
@ -34,30 +35,27 @@ public:
b3ClothContactManager();
void FindNewContacts();
void AddPair(void* data1, void* data2);
void FindNewClothContacts();
void AddPSPair(b3Particle* p1, b3Shape* s2);
void FindNewBodyContacts();
void UpdateContacts();
void UpdateClothContacts();
void UpdateBodyContacts();
b3ParticleTriangleContact* CreateParticleTriangleContact();
void Destroy(b3ParticleTriangleContact* c);
b3ClothSphereAndTriangleContact* CreateSphereAndTriangleContact();
void Destroy(b3ClothSphereAndTriangleContact* c);
b3ParticleBodyContact* CreateParticleBodyContact();
void Destroy(b3ParticleBodyContact* c);
b3ClothSphereAndShapeContact* CreateSphereAndShapeContact();
void Destroy(b3ClothSphereAndShapeContact* c);
b3BlockPool m_particleTriangleContactBlocks;
b3BlockPool m_particleBodyContactBlocks;
b3ClothCapsuleAndCapsuleContact* CreateCapsuleAndCapsuleContact();
void Destroy(b3ClothCapsuleAndCapsuleContact* c);
b3BlockPool m_sphereAndTriangleContactBlocks;
b3BlockPool m_sphereAndShapeContactBlocks;
b3BlockPool m_capsuleAndCapsuleContactBlocks;
b3Cloth* m_cloth;
b3BroadPhase m_broadPhase;
b3List2<b3ParticleTriangleContact> m_particleTriangleContactList;
b3List2<b3ParticleBodyContact> m_particleBodyContactList;
b3List2<b3ClothSphereAndTriangleContact> m_sphereAndTriangleContactList;
b3List2<b3ClothSphereAndShapeContact> m_sphereAndShapeContactList;
b3List2<b3ClothCapsuleAndCapsuleContact> m_capsuleAndCapsuleContactList;
};
#endif

View File

@ -21,10 +21,11 @@
#include <bounce/common/math/mat22.h>
#include <bounce/common/math/mat33.h>
#include <bounce/cloth/cloth_time_step.h>
class b3StackAllocator;
class b3Particle;
class b3ClothParticle;
class b3Force;
struct b3DenseVec3;
@ -34,9 +35,10 @@ struct b3SparseMat33View;
struct b3ClothForceSolverDef
{
b3ClothTimeStep step;
b3StackAllocator* stack;
u32 particleCount;
b3Particle** particles;
b3ClothParticle** particles;
u32 forceCount;
b3Force** forces;
};
@ -59,14 +61,16 @@ public:
b3ClothForceSolver(const b3ClothForceSolverDef& def);
~b3ClothForceSolver();
void Solve(float32 dt, const b3Vec3& gravity);
void Solve(const b3Vec3& gravity);
private:
void ApplyForces();
b3StackAllocator* m_allocator;
b3ClothTimeStep m_step;
b3StackAllocator* m_stack;
u32 m_particleCount;
b3Particle** m_particles;
b3ClothParticle** m_particles;
u32 m_forceCount;
b3Force** m_forces;

View File

@ -34,6 +34,16 @@ struct b3ClothMeshMesh
u32 startTriangle;
};
struct b3ClothMeshShearingLine
{
u32 v1, v2;
};
struct b3ClothMeshBendingLine
{
u32 v1, v2;
};
struct b3ClothMeshSewingLine
{
u32 s1, s2;
@ -48,6 +58,10 @@ struct b3ClothMesh
b3ClothMeshTriangle* triangles;
u32 meshCount;
b3ClothMeshMesh* meshes;
u32 shearingLineCount;
b3ClothMeshShearingLine* shearingLines;
u32 bendingLineCount;
b3ClothMeshBendingLine* bendingLines;
u32 sewingLineCount;
b3ClothMeshSewingLine* sewingLines;
};

View File

@ -0,0 +1,291 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_PARTICLE_H
#define B3_CLOTH_PARTICLE_H
#include <bounce/common/template/list.h>
#include <bounce/common/math/vec3.h>
class b3Cloth;
// Static particle: Zero mass. Can be moved manually.
// Kinematic particle: Zero mass. Non-zero velocity, can be moved by the solver.
// Dynamic particle: Non-zero mass. Non-zero velocity determined by force, can be moved by the solver.
enum b3ClothParticleType
{
e_staticClothParticle,
e_kinematicClothParticle,
e_dynamicClothParticle
};
// Particle definition
struct b3ClothParticleDef
{
b3ClothParticleDef()
{
type = e_staticClothParticle;
position.SetZero();
velocity.SetZero();
force.SetZero();
meshIndex = B3_MAX_U32;
userData = nullptr;
}
b3ClothParticleType type;
b3Vec3 position;
b3Vec3 velocity;
b3Vec3 force;
u32 meshIndex;
void* userData;
};
// A cloth particle.
class b3ClothParticle
{
public:
// Set the particle type.
void SetType(b3ClothParticleType type);
// Get the particle type.
b3ClothParticleType GetType() const;
// Set the particle position.
// If the particle is dynamic changing the position directly might lead
// to physically incorrect simulation behaviour.
void SetPosition(const b3Vec3& position);
// Get the particle position.
const b3Vec3& GetPosition() const;
// Set the particle velocity.
void SetVelocity(const b3Vec3& velocity);
// Get the particle velocity.
const b3Vec3& GetVelocity() const;
// Get the particle mass.
scalar GetMass() const;
// Get the applied force.
const b3Vec3& GetForce() const;
// Apply a force.
void ApplyForce(const b3Vec3& force);
// Get the applied translation.
const b3Vec3& GetTranslation() const;
// Apply a translation.
void ApplyTranslation(const b3Vec3& translation);
// Get the mesh index.
u32 GetMeshIndex() const;
// Set the user data.
void SetUserData(void* userData);
// Get the user data.
const void* GetUserData() const;
void* GetUserData();
// Get the next particle in the cloth list of particles.
b3ClothParticle* GetNext();
const b3ClothParticle* GetNext() const;
private:
friend class b3List2<b3ClothParticle>;
friend class b3Cloth;
friend class b3ClothContactManager;
friend class b3ClothSolver;
friend class b3ClothForceSolver;
friend class b3ClothSphereShape;
friend class b3ClothCapsuleShape;
friend class b3ClothTriangleShape;
friend class b3ClothSphereAndShapeContact;
friend class b3ClothSphereAndTriangleContact;
friend class b3ClothCapsuleAndCapsuleContact;
friend class b3ClothContactSolver;
friend class b3Force;
friend class b3StretchForce;
friend class b3ShearForce;
friend class b3SpringForce;
friend class b3MouseForce;
friend class b3ElementForce;
b3ClothParticle(const b3ClothParticleDef& def, b3Cloth* cloth);
~b3ClothParticle();
// Synchronize spheres
void SynchronizeSpheres();
// Synchronize capsules
void SynchronizeCapsules();
// Synchronize triangles
void SynchronizeTriangles();
// Destroy spheres.
void DestroySpheres();
// Destroy capsules.
void DestroyCapsules();
// Destroy triangles.
void DestroyTriangles();
// Destroy forces.
void DestroyForces();
// Destroy contacts.
void DestroyContacts();
// Type
b3ClothParticleType m_type;
// Position
b3Vec3 m_position;
// Velocity
b3Vec3 m_velocity;
// Applied external force
b3Vec3 m_force;
// Applied translation
b3Vec3 m_translation;
// Mass
scalar m_mass;
// Inverse mass
scalar m_invMass;
// Mesh index.
u32 m_meshIndex;
// Solver temp identifier
u32 m_solverId;
// Solver temp solution
b3Vec3 m_x;
// User data
void* m_userData;
// Cloth
b3Cloth* m_cloth;
// Links to the cloth particle list.
b3ClothParticle* m_prev;
b3ClothParticle* m_next;
};
inline b3ClothParticleType b3ClothParticle::GetType() const
{
return m_type;
}
inline void b3ClothParticle::SetPosition(const b3Vec3& position)
{
m_position = position;
m_translation.SetZero();
SynchronizeSpheres();
SynchronizeCapsules();
SynchronizeTriangles();
}
inline const b3Vec3& b3ClothParticle::GetPosition() const
{
return m_position;
}
inline void b3ClothParticle::SetVelocity(const b3Vec3& velocity)
{
if (m_type == e_staticClothParticle)
{
return;
}
m_velocity = velocity;
}
inline const b3Vec3& b3ClothParticle::GetVelocity() const
{
return m_velocity;
}
inline scalar b3ClothParticle::GetMass() const
{
return m_mass;
}
inline const b3Vec3& b3ClothParticle::GetForce() const
{
return m_force;
}
inline void b3ClothParticle::ApplyForce(const b3Vec3& force)
{
if (m_type != e_dynamicClothParticle)
{
return;
}
m_force += force;
}
inline const b3Vec3& b3ClothParticle::GetTranslation() const
{
return m_translation;
}
inline void b3ClothParticle::ApplyTranslation(const b3Vec3& translation)
{
m_translation += translation;
}
inline u32 b3ClothParticle::GetMeshIndex() const
{
return m_meshIndex;
}
inline void b3ClothParticle::SetUserData(void* userData)
{
m_userData = userData;
}
inline const void* b3ClothParticle::GetUserData() const
{
return m_userData;
}
inline void* b3ClothParticle::GetUserData()
{
return m_userData;
}
inline b3ClothParticle* b3ClothParticle::GetNext()
{
return m_next;
}
inline const b3ClothParticle* b3ClothParticle::GetNext() const
{
return m_next;
}
#endif

View File

@ -24,18 +24,22 @@
class b3StackAllocator;
class b3Particle;
class b3ClothParticle;
class b3Force;
class b3ParticleBodyContact;
class b3ParticleTriangleContact;
class b3ClothSphereAndShapeContact;
class b3ClothSphereAndTriangleContact;
class b3ClothCapsuleAndCapsuleContact;
struct b3ClothTimeStep;
struct b3ClothSolverDef
{
b3StackAllocator* stack;
u32 particleCapacity;
u32 forceCapacity;
u32 bodyContactCapacity;
u32 shapeContactCapacity;
u32 triangleContactCapacity;
u32 capsuleContactCapacity;
};
class b3ClothSolver
@ -44,30 +48,35 @@ public:
b3ClothSolver(const b3ClothSolverDef& def);
~b3ClothSolver();
void Add(b3Particle* p);
void Add(b3ClothParticle* p);
void Add(b3Force* f);
void Add(b3ParticleBodyContact* c);
void Add(b3ParticleTriangleContact* c);
void Add(b3ClothSphereAndShapeContact* c);
void Add(b3ClothSphereAndTriangleContact* c);
void Add(b3ClothCapsuleAndCapsuleContact* c);
void Solve(float32 dt, const b3Vec3& gravity, u32 velocityIterations, u32 positionIterations);
void Solve(const b3ClothTimeStep& step, const b3Vec3& gravity);
private:
b3StackAllocator* m_allocator;
b3StackAllocator* m_stack;
u32 m_particleCapacity;
u32 m_particleCount;
b3Particle** m_particles;
b3ClothParticle** m_particles;
u32 m_forceCapacity;
u32 m_forceCount;
b3Force** m_forces;
u32 m_bodyContactCapacity;
u32 m_bodyContactCount;
b3ParticleBodyContact** m_bodyContacts;
u32 m_shapeContactCapacity;
u32 m_shapeContactCount;
b3ClothSphereAndShapeContact** m_shapeContacts;
u32 m_triangleContactCapacity;
u32 m_triangleContactCount;
b3ParticleTriangleContact** m_triangleContacts;
b3ClothSphereAndTriangleContact** m_triangleContacts;
u32 m_capsuleContactCapacity;
u32 m_capsuleContactCount;
b3ClothCapsuleAndCapsuleContact** m_capsuleContacts;
};
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include <bounce/common/settings.h>
#ifndef B3_CLOTH_TIME_STEP_H
#define B3_CLOTH_TIME_STEP_H
// Time step parameters
struct b3ClothTimeStep
{
scalar dt;
scalar inv_dt;
scalar dt_ratio;
u32 velocityIterations;
u32 positionIterations;
};
#endif

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_CAPSULE_AND_CAPSULE_CONTACT_H
#define B3_CLOTH_CAPSULE_AND_CAPSULE_CONTACT_H
#include <bounce/common/template/list.h>
#include <bounce/common/math/vec2.h>
#include <bounce/common/math/vec3.h>
class b3ClothCapsuleShape;
// Contact between capsules
class b3ClothCapsuleAndCapsuleContact
{
public:
private:
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ClothCapsuleShape;
friend class b3ClothContactManager;
friend class b3ClothContactSolver;
friend class b3List2<b3ClothCapsuleAndCapsuleContact>;
b3ClothCapsuleAndCapsuleContact() { }
~b3ClothCapsuleAndCapsuleContact() { }
void Update();
b3ClothCapsuleShape* m_s1;
b3ClothCapsuleShape* m_s2;
bool m_active;
scalar m_w1, m_w2, m_w3, m_w4;
b3Vec3 m_normal1;
scalar m_normalImpulse;
b3Vec3 m_tangent1;
b3Vec3 m_tangent2;
b3Vec2 m_tangentImpulse;
b3ClothCapsuleAndCapsuleContact* m_prev;
b3ClothCapsuleAndCapsuleContact* m_next;
};
#endif

View File

@ -21,35 +21,65 @@
#include <bounce/common/math/mat22.h>
#include <bounce/common/math/mat33.h>
#include <bounce/cloth/cloth_time_step.h>
class b3StackAllocator;
class b3Particle;
class b3ClothParticle;
class b3Body;
class b3ParticleBodyContact;
class b3ParticleTriangleContact;
class b3ClothSphereAndShapeContact;
class b3ClothSphereAndTriangleContact;
class b3ClothCapsuleAndCapsuleContact;
struct b3ClothSolverBodyContactVelocityConstraint
struct b3ClothSolverShapeContactVelocityConstraint
{
u32 indexA;
float32 invMassA;
b3Mat33 invIA;
scalar invMassA;
b3Body* bodyB;
float32 invMassB;
b3Mat33 invIB;
float32 friction;
b3Vec3 point;
b3Vec3 rA;
b3Vec3 rB;
scalar friction;
b3Vec3 normal;
float32 normalMass;
float32 normalImpulse;
float32 velocityBias;
scalar normalMass;
scalar normalImpulse;
b3Vec3 tangent1;
b3Vec3 tangent2;
scalar tangentMass;
b3Vec2 tangentImpulse;
};
struct b3ClothSolverShapeContactPositionConstraint
{
u32 indexA;
scalar invMassA;
scalar radiusA;
scalar radiusB;
b3Vec3 normal;
b3Vec3 pointB;
};
struct b3ClothSolverTriangleContactVelocityConstraint
{
u32 indexA;
scalar invMassA;
u32 indexB;
scalar invMassB;
u32 indexC;
scalar invMassC;
u32 indexD;
scalar invMassD;
scalar wB, wC, wD;
b3Vec3 normal;
scalar normalMass;
scalar normalImpulse;
scalar friction;
b3Vec3 tangent1;
b3Vec3 tangent2;
@ -57,88 +87,85 @@ struct b3ClothSolverBodyContactVelocityConstraint
b3Vec2 tangentImpulse;
};
struct b3ClothSolverBodyContactPositionConstraint
{
u32 indexA;
float32 invMassA;
b3Mat33 invIA;
float32 radiusA;
b3Vec3 localCenterA;
b3Body* bodyB;
float32 invMassB;
b3Mat33 invIB;
float32 radiusB;
b3Vec3 localCenterB;
b3Vec3 rA;
b3Vec3 rB;
b3Vec3 normalA;
b3Vec3 localPointA;
b3Vec3 localPointB;
};
struct b3ClothSolverTriangleContactVelocityConstraint
{
u32 indexA;
float32 invMassA;
u32 indexB;
float32 invMassB;
u32 indexC;
float32 invMassC;
u32 indexD;
float32 invMassD;
float32 wB, wC, wD;
b3Vec3 normal;
float32 normalMass;
float32 normalImpulse;
float32 friction;
b3Vec3 tangent1;
b3Vec3 tangent2;
float32 tangentMass1;
float32 tangentMass2;
float32 tangentImpulse1;
float32 tangentImpulse2;
};
struct b3ClothSolverTriangleContactPositionConstraint
{
u32 indexA;
float32 invMassA;
float32 radiusA;
scalar invMassA;
scalar radiusA;
u32 indexB;
float32 invMassB;
scalar invMassB;
u32 indexC;
float32 invMassC;
scalar invMassC;
u32 indexD;
float32 invMassD;
float32 triangleRadius;
scalar invMassD;
scalar triangleRadius;
float32 wB, wC, wD;
scalar wB, wC, wD;
};
struct b3ClothSolverCapsuleContactVelocityConstraint
{
u32 indexA;
scalar invMassA;
u32 indexB;
scalar invMassB;
u32 indexC;
scalar invMassC;
u32 indexD;
scalar invMassD;
scalar wA, wB, wC, wD;
b3Vec3 normal;
scalar normalMass;
scalar normalImpulse;
scalar friction;
b3Vec3 tangent1;
b3Vec3 tangent2;
b3Mat22 tangentMass;
b3Vec2 tangentImpulse;
};
struct b3ClothSolverCapsuleContactPositionConstraint
{
u32 indexA;
scalar invMassA;
u32 indexB;
scalar invMassB;
scalar radiusA;
u32 indexC;
scalar invMassC;
u32 indexD;
scalar invMassD;
scalar radiusB;
scalar wA, wB, wC, wD;
};
struct b3ClothContactSolverDef
{
b3ClothTimeStep step;
b3StackAllocator* allocator;
b3Vec3* positions;
b3Vec3* velocities;
u32 bodyContactCount;
b3ParticleBodyContact** bodyContacts;
u32 shapeContactCount;
b3ClothSphereAndShapeContact** shapeContacts;
u32 triangleContactCount;
b3ParticleTriangleContact** triangleContacts;
b3ClothSphereAndTriangleContact** triangleContacts;
u32 capsuleContactCount;
b3ClothCapsuleAndCapsuleContact** capsuleContacts;
};
inline float32 b3MixFriction(float32 u1, float32 u2)
inline scalar b3MixFriction(scalar u1, scalar u2)
{
return b3Sqrt(u1 * u2);
}
@ -149,34 +176,45 @@ public:
b3ClothContactSolver(const b3ClothContactSolverDef& def);
~b3ClothContactSolver();
void InitializeBodyContactConstraints();
void InitializeShapeContactConstraints();
void InitializeTriangleContactConstraints();
void InitializeCapsuleContactConstraints();
void WarmStartBodyContactConstraints();
void WarmStartShapeContactConstraints();
void WarmStartTriangleContactConstraints();
void WarmStartCapsuleContactConstraints();
void SolveBodyContactVelocityConstraints();
void SolveShapeContactVelocityConstraints();
void SolveTriangleContactVelocityConstraints();
void SolveCapsuleContactVelocityConstraints();
void StoreImpulses();
bool SolveBodyContactPositionConstraints();
bool SolveShapeContactPositionConstraints();
bool SolveTriangleContactPositionConstraints();
bool SolveCapsuleContactPositionConstraints();
protected:
b3ClothTimeStep m_step;
b3StackAllocator* m_allocator;
b3Vec3* m_positions;
b3Vec3* m_velocities;
u32 m_bodyContactCount;
b3ParticleBodyContact** m_bodyContacts;
b3ClothSolverBodyContactVelocityConstraint* m_bodyVelocityConstraints;
b3ClothSolverBodyContactPositionConstraint* m_bodyPositionConstraints;
u32 m_shapeContactCount;
b3ClothSphereAndShapeContact** m_shapeContacts;
b3ClothSolverShapeContactVelocityConstraint* m_shapeVelocityConstraints;
b3ClothSolverShapeContactPositionConstraint* m_shapePositionConstraints;
u32 m_triangleContactCount;
b3ParticleTriangleContact** m_triangleContacts;
b3ClothSphereAndTriangleContact** m_triangleContacts;
b3ClothSolverTriangleContactVelocityConstraint* m_triangleVelocityConstraints;
b3ClothSolverTriangleContactPositionConstraint* m_trianglePositionConstraints;
u32 m_capsuleContactCount;
b3ClothCapsuleAndCapsuleContact** m_capsuleContacts;
b3ClothSolverCapsuleContactVelocityConstraint* m_capsuleVelocityConstraints;
b3ClothSolverCapsuleContactPositionConstraint* m_capsulePositionConstraints;
};
#endif

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_SPHERE_AND_SHAPE_CONTACT_H
#define B3_CLOTH_SPHERE_AND_SHAPE_CONTACT_H
#include <bounce/common/template/list.h>
#include <bounce/common/math/vec2.h>
#include <bounce/common/math/vec3.h>
#include <bounce/common/math/transform.h>
class b3ClothSphereShape;
class b3ClothWorldShape;
// A contact between a sphere and a shape
class b3ClothSphereAndShapeContact
{
public:
private:
friend class b3List2<b3ClothSphereAndShapeContact>;
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ClothSphereShape;
friend class b3ClothWorldShape;
friend class b3ClothContactManager;
friend class b3ClothSolver;
friend class b3ClothContactSolver;
friend struct b3ClothSphereAndShapeContactWorldPoint;
b3ClothSphereAndShapeContact() { }
~b3ClothSphereAndShapeContact() { }
void Update();
b3ClothSphereShape* m_s1;
b3ClothWorldShape* m_s2;
bool m_active;
b3Vec3 m_normal2;
b3Vec3 m_point2;
scalar m_normalImpulse;
b3Vec3 m_tangent1, m_tangent2;
b3Vec2 m_tangentImpulse;
b3ClothSphereAndShapeContact* m_prev;
b3ClothSphereAndShapeContact* m_next;
};
struct b3ClothSphereAndShapeContactWorldPoint
{
void Initialize(const b3ClothSphereAndShapeContact* c, scalar rA, const b3Vec3& cA, scalar rB);
b3Vec3 point;
b3Vec3 normal;
scalar separation;
};
#endif

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_SPHERE_AND_TRIANGLE_CONTACT_H
#define B3_CLOTH_SPHERE_AND_TRIANGLE_CONTACT_H
#include <bounce/common/template/list.h>
#include <bounce/common/math/vec2.h>
#include <bounce/common/math/vec3.h>
class b3ClothSphereShape;
class b3ClothTriangleShape;
// Contact between sphere and a triangle
class b3ClothSphereAndTriangleContact
{
public:
private:
friend class b3List2<b3ClothSphereAndTriangleContact>;
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ClothSphereShape;
friend class b3ClothTriangleShape;
friend class b3ClothContactManager;
friend class b3ClothContactSolver;
b3ClothSphereAndTriangleContact() { }
~b3ClothSphereAndTriangleContact() { }
void Update();
b3ClothSphereShape* m_s1;
b3ClothTriangleShape* m_s2;
bool m_active;
scalar m_w1, m_w2, m_w3;
b3Vec3 m_normal1;
scalar m_normalImpulse;
b3Vec3 m_tangent1;
b3Vec3 m_tangent2;
b3Vec2 m_tangentImpulse;
b3ClothSphereAndTriangleContact* m_prev;
b3ClothSphereAndTriangleContact* m_next;
};
#endif

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_ELEMENT_FORCE_H
#define B3_ELEMENT_FORCE_H
#include <bounce/cloth/forces/force.h>
#include <bounce/common/math/mat22.h>
#include <bounce/common/math/mat33.h>
// Element force definition.
// This requires defining the triangle in the rest state and
// some material parameters.
struct b3ElementForceDef : public b3ForceDef
{
b3ElementForceDef()
{
type = e_elementForce;
E_x = scalar(0);
E_y = scalar(0);
E_s = scalar(0);
nu_xy = scalar(0);
nu_yx = scalar(0);
}
// Particle 1
b3ClothParticle* p1;
// Particle 2
b3ClothParticle* p2;
// Particle 3
b3ClothParticle* p3;
// Triangle vertices in rest state
b3Vec3 v1, v2, v3;
// Young Modulus in x direction
scalar E_x;
// Young Modulus in y direction
scalar E_y;
// Shear Modulus
scalar E_s;
// x, y Poisson's Ratio
scalar nu_xy;
// y, x Poisson's Ratio
scalar nu_yx;
};
// Element force acting on a cloth triangle.
class b3ElementForce : public b3Force
{
public:
// Has this force a given particle?
bool HasParticle(const b3ClothParticle* particle) const;
private:
friend class b3Force;
friend class b3Cloth;
b3ElementForce(const b3ElementForceDef* def);
~b3ElementForce();
void Apply(const b3ClothForceSolverData* data);
// Particle 1
b3ClothParticle* m_p1;
// Particle 2
b3ClothParticle* m_p2;
// Particle 3
b3ClothParticle* m_p3;
// Rest triangle vertices in 2D
b3Vec2 m_x1, m_x2, m_x3;
// Rest triangle area in 2D
scalar m_A;
// Initial inverse deformation in 2D
b3Mat22 m_invS;
// Young Modulus in 2D
scalar m_E_x, m_E_y, m_E_s;
// Poisson Ratio in 2D
scalar m_nu_xy, m_nu_yx;
// Elasticity tensor
// This is a 3x3 matrix
b3Mat33 m_C;
// Shape functions (barycentric) matrix
// This is a 3x6 matrix
scalar m_B[18];
// Blocked stiffness matrix
// This is a 6x6 matrix
b3Mat22 m_K[9];
};
#endif

View File

@ -22,17 +22,18 @@
#include <bounce/common/math/transform.h>
#include <bounce/common/template/list.h>
struct b3ClothForceSolverData;
class b3ClothParticle;
class b3Particle;
struct b3ClothForceSolverData;
// Force types
enum b3ForceType
{
e_strechForce,
e_stretchForce,
e_shearForce,
e_springForce,
e_mouseForce,
e_elementForce,
};
struct b3ForceDef
@ -40,24 +41,26 @@ struct b3ForceDef
b3ForceType type;
};
//
// A force acts on a set of particles.
class b3Force
{
public:
//
// Get the force type.
b3ForceType GetType() const;
//
b3Force* GetNext();
// Has this force a given particle?
virtual bool HasParticle(const b3ClothParticle* particle) const = 0;
//
virtual bool HasParticle(const b3Particle* particle) const = 0;
// Get the next force in the cloth force list.
const b3Force* GetNext() const;
b3Force* GetNext();
protected:
friend class b3List2<b3Force>;
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ClothForceSolver;
friend class b3Particle;
// Factory create and destroy.
static b3Force* Create(const b3ForceDef* def);
static void Destroy(b3Force* f);
@ -66,13 +69,9 @@ protected:
virtual void Apply(const b3ClothForceSolverData* data) = 0;
// Force type
b3ForceType m_type;
//
b3Force* m_prev;
//
b3Force* m_next;
};
@ -81,6 +80,11 @@ inline b3ForceType b3Force::GetType() const
return m_type;
}
inline const b3Force* b3Force::GetNext() const
{
return m_next;
}
inline b3Force* b3Force::GetNext()
{
return m_next;

View File

@ -21,51 +21,93 @@
#include <bounce/cloth/forces/force.h>
class b3ClothTriangle;
// Mouse force definition.
// This requires defining a particle and a triangle
// and the coordinates of the particle local to the triangle
// in the rest state using a barycentric coordinate system.
// You must also provide spring parameters.
struct b3MouseForceDef : public b3ForceDef
{
b3MouseForceDef()
{
type = e_mouseForce;
type = e_mouseForce;
w2 = scalar(0);
w3 = scalar(0);
w4 = scalar(0);
restLength = scalar(0);
mouse = scalar(0);
damping = scalar(0);
}
// Particle
b3Particle* particle;
// Triangle
b3ClothTriangle* triangle;
// Particle 1
b3ClothParticle* p1;
// Particle 2
b3ClothParticle* p2;
// Particle 3
b3ClothParticle* p3;
// Particle 4
b3ClothParticle* p4;
// Barycentric coordinates on triangle
float32 w2, w3, w4;
scalar w2, w3, w4;
// Mouse stiffness
float32 mouse;
scalar mouse;
// Damping stiffness
float32 damping;
scalar damping;
// Rest length
scalar restLength;
};
// Mouse force acting on a particle and triangle.
// This force will keep a point on one particle and the other on the
// triangle to a given desired distance.
class b3MouseForce : public b3Force
{
public:
bool HasParticle(const b3Particle* particle) const;
// Has this force a given particle?
bool HasParticle(const b3ClothParticle* particle) const;
b3Particle* GetParticle() const;
// Get the particle 1.
const b3ClothParticle* GetParticle1() const;
b3ClothParticle* GetParticle1();
// Get the particle 2.
const b3ClothParticle* GetParticle2() const;
b3ClothParticle* GetParticle2();
b3ClothTriangle* GetTriangle() const;
// Get the particle 3.
const b3ClothParticle* GetParticle3() const;
b3ClothParticle* GetParticle3();
// Get the particle 4.
const b3ClothParticle* GetParticle4() const;
b3ClothParticle* GetParticle4();
// Get the natural spring length.
scalar GetRestLenght() const;
float32 GetMouseStiffness() const;
// Get the mouse stiffness.
scalar GetMouseStiffness() const;
float32 GetDampingStiffness() const;
// Get the damping stiffness.
scalar GetDampingStiffness() const;
// Get the force acting on particle 1.
b3Vec3 GetActionForce1() const;
// Get the force acting on particle 2.
b3Vec3 GetActionForce2() const;
// Get the force acting on particle 3.
b3Vec3 GetActionForce3() const;
// Get the force acting on particle 4.
b3Vec3 GetActionForce4() const;
private:
friend class b3Force;
@ -76,43 +118,85 @@ private:
void Apply(const b3ClothForceSolverData* data);
// Solver shared
// Particle 1
b3ClothParticle* m_p1;
// Particle
b3Particle* m_particle;
// Particle 2
b3ClothParticle* m_p2;
// Triangle
b3ClothTriangle* m_triangle;
// Barycentric coordinates
float32 m_w2, m_w3, m_w4;
// Particle 3
b3ClothParticle* m_p3;
// Particle 4
b3ClothParticle* m_p4;
// Barycentric coordinates in the rest state
scalar m_w2, m_w3, m_w4;
// Mouse stiffness
float32 m_km;
scalar m_km;
// Damping stiffness
float32 m_kd;
scalar m_kd;
// Rest length
scalar m_L0;
// Action forces
b3Vec3 m_f1, m_f2, m_f3, m_f4;
};
inline b3Particle* b3MouseForce::GetParticle() const
inline const b3ClothParticle* b3MouseForce::GetParticle1() const
{
return m_particle;
return m_p1;
}
inline b3ClothTriangle* b3MouseForce::GetTriangle() const
inline b3ClothParticle* b3MouseForce::GetParticle1()
{
return m_triangle;
return m_p1;
}
inline float32 b3MouseForce::GetMouseStiffness() const
inline const b3ClothParticle* b3MouseForce::GetParticle2() const
{
return m_p2;
}
inline b3ClothParticle* b3MouseForce::GetParticle2()
{
return m_p2;
}
inline const b3ClothParticle* b3MouseForce::GetParticle3() const
{
return m_p3;
}
inline b3ClothParticle* b3MouseForce::GetParticle3()
{
return m_p3;
}
inline const b3ClothParticle* b3MouseForce::GetParticle4() const
{
return m_p4;
}
inline b3ClothParticle* b3MouseForce::GetParticle4()
{
return m_p4;
}
inline scalar b3MouseForce::GetRestLenght() const
{
return m_L0;
}
inline scalar b3MouseForce::GetMouseStiffness() const
{
return m_km;
}
inline float32 b3MouseForce::GetDampingStiffness() const
inline scalar b3MouseForce::GetDampingStiffness() const
{
return m_kd;
}

View File

@ -21,41 +21,88 @@
#include <bounce/cloth/forces/force.h>
class b3ClothTriangle;
// Shear force definition.
// This requires defining the (u, v) coordinates
// of the triangle and some parameters.
struct b3ShearForceDef : public b3ForceDef
{
b3ShearForceDef()
{
type = e_shearForce;
u1 = scalar(0);
v1 = scalar(0);
u2 = scalar(0);
v2 = scalar(0);
u3 = scalar(0);
v3 = scalar(0);
alpha = scalar(0);
shearing = scalar(0);
damping = scalar(0);
}
// Initialize this definition from rest positions
void Initialize(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3);
// Particle 1
b3ClothParticle* p1;
// Triangle
b3ClothTriangle* triangle;
// Particle 2
b3ClothParticle* p2;
// Particle 3
b3ClothParticle* p3;
// (u, v) coordinates for vertex 1 in the rest state
scalar u1, v1;
// (u, v) coordinates for vertex 2 in the rest state
scalar u2, v2;
// (u, v) coordinates for vertex 3 in the rest state
scalar u3, v3;
// Typically this is the triangle area in the rest state.
scalar alpha;
// Shearing stiffness
float32 shearing;
scalar shearing;
// Damping stiffness
float32 damping;
scalar damping;
};
// Shear force acting on a cloth triangle.
class b3ShearForce : public b3Force
{
public:
bool HasParticle(const b3Particle* particle) const;
// Has this force a given particle?
bool HasParticle(const b3ClothParticle* particle) const;
b3ClothTriangle* GetTriangle() const;
// Get the particle 1.
const b3ClothParticle* GetParticle1() const { return m_p1; }
b3ClothParticle* GetParticle1() { return m_p1; }
float32 GetShearingStiffness() const;
// Get the particle 2.
const b3ClothParticle* GetParticle2() const { return m_p2; }
b3ClothParticle* GetParticle2() { return m_p2; }
// Get the particle 3.
const b3ClothParticle* GetParticle3() const { return m_p3; }
b3ClothParticle* GetParticle3() { return m_p3; }
float32 GetDampingStiffness() const;
// Get the shearing stiffness.
scalar GetShearingStiffness() const;
// Get the damping stiffness.
scalar GetDampingStiffness() const;
// Get the force acting on particle 1.
b3Vec3 GetActionForce1() const;
// Get the force acting on particle 2.
b3Vec3 GetActionForce2() const;
// Get the force acting on particle 3.
b3Vec3 GetActionForce3() const;
private:
friend class b3Force;
@ -66,32 +113,42 @@ private:
void Apply(const b3ClothForceSolverData* data);
// Solver shared
// Particle 1
b3ClothParticle* m_p1;
// Triangle
b3ClothTriangle* m_triangle;
// Particle 2
b3ClothParticle* m_p2;
// Particle 3
b3ClothParticle* m_p3;
// Alpha
scalar m_alpha;
// (u, v) matrix
scalar m_du1, m_dv1;
scalar m_du2, m_dv2;
scalar m_inv_det;
// dwudx, dwvdx
b3Vec3 m_dwudx, m_dwvdx;
// Shearing stiffness
float32 m_ks;
scalar m_ks;
// Damping stiffness
float32 m_kd;
scalar m_kd;
// Action forces
b3Vec3 m_f1, m_f2, m_f3;
};
inline b3ClothTriangle* b3ShearForce::GetTriangle() const
{
return m_triangle;
}
inline float32 b3ShearForce::GetShearingStiffness() const
inline scalar b3ShearForce::GetShearingStiffness() const
{
return m_ks;
}
inline float32 b3ShearForce::GetDampingStiffness() const
inline scalar b3ShearForce::GetDampingStiffness() const
{
return m_kd;
}

View File

@ -21,54 +21,68 @@
#include <bounce/cloth/forces/force.h>
// Spring force definition.
// This requires defining two particles, the
// natural spring rest length, and the spring parameters.
struct b3SpringForceDef : public b3ForceDef
{
b3SpringForceDef()
{
type = e_springForce;
p1 = nullptr;
p2 = nullptr;
restLength = 0.0f;
structural = 0.0f;
damping = 0.0f;
restLength = scalar(0);
structural = scalar(0);
damping = scalar(0);
}
//
void Initialize(b3Particle* particle1, b3Particle* particle2, float32 structuralStiffness, float32 dampingStiffness);
// Initialize this definition from particles and stiffnesses.
void Initialize(b3ClothParticle* particle1, b3ClothParticle* particle2, scalar structuralStiffness, scalar dampingStiffness);
// Particle 1
b3Particle* p1;
b3ClothParticle* p1;
// Particle 2
b3Particle* p2;
b3ClothParticle* p2;
// Rest length
float32 restLength;
scalar restLength;
// Structural stiffness
float32 structural;
scalar structural;
// Damping stiffness
float32 damping;
scalar damping;
};
//
// A spring force acting on two particles
// to maintain them at a desired distance.
class b3SpringForce : public b3Force
{
public:
b3Particle* GetParticle1();
// Does this force contain a given particle?
bool HasParticle(const b3ClothParticle* particle) const;
b3Particle* GetParticle2();
// Get the particle 1.
const b3ClothParticle* GetParticle1() const { return m_p1; }
b3ClothParticle* GetParticle1() { return m_p1; }
float32 GetRestLenght() const;
// Get the particle 2.
const b3ClothParticle* GetParticle2() const { return m_p2; }
b3ClothParticle* GetParticle2() { return m_p2; }
float32 GetStructuralStiffness() const;
// Get the spring natural rest length.
scalar GetRestLenght() const;
float32 GetDampingStiffness() const;
// Get the spring stiffness.
scalar GetStructuralStiffness() const;
// Get the damping stiffness.
scalar GetDampingStiffness() const;
// Get the force acting on particle 1.
b3Vec3 GetActionForce() const;
bool HasParticle(const b3Particle* particle) const;
// Get the force acting on particle 2.
b3Vec3 GetReactionForce() const;
private:
friend class b3Force;
friend class b3Cloth;
@ -78,60 +92,48 @@ private:
void Apply(const b3ClothForceSolverData* data);
// Solver shared
// Particle 1
b3Particle* m_p1;
b3ClothParticle* m_p1;
// Particle 2
b3Particle* m_p2;
b3ClothParticle* m_p2;
// Rest length
float32 m_L0;
// Spring natural rest length
scalar m_L0;
// Structural stiffness
float32 m_ks;
// Spring stiffness
scalar m_ks;
// Damping stiffness
float32 m_kd;
scalar m_kd;
// Applied internal force (on particle 1)
b3Vec3 m_f;
// Action forces
b3Vec3 m_f1, m_f2;
};
inline b3Particle * b3SpringForce::GetParticle1()
{
return m_p1;
}
inline b3Particle* b3SpringForce::GetParticle2()
{
return m_p2;
}
inline float32 b3SpringForce::GetRestLenght() const
inline scalar b3SpringForce::GetRestLenght() const
{
return m_L0;
}
inline float32 b3SpringForce::GetStructuralStiffness() const
inline scalar b3SpringForce::GetStructuralStiffness() const
{
return m_ks;
}
inline float32 b3SpringForce::GetDampingStiffness() const
inline scalar b3SpringForce::GetDampingStiffness() const
{
return m_kd;
}
inline b3Vec3 b3SpringForce::GetActionForce() const
{
return m_f;
return m_f1;
}
inline bool b3SpringForce::HasParticle(const b3Particle* particle) const
inline b3Vec3 b3SpringForce::GetReactionForce() const
{
return m_p1 == particle || m_p2 == particle;
return m_f2;
}
#endif

View File

@ -0,0 +1,264 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_STRETCH_FORCE_H
#define B3_STRETCH_FORCE_H
#include <bounce/cloth/forces/force.h>
// Stretch force definition.
// This requires defining the (u, v) coordinates
// of the triangle and some parameters.
struct b3StretchForceDef : public b3ForceDef
{
b3StretchForceDef()
{
type = e_stretchForce;
u1 = scalar(0);
v1 = scalar(0);
u2 = scalar(0);
v2 = scalar(0);
u3 = scalar(0);
v3 = scalar(0);
alpha = scalar(0);
stretching_u = scalar(0);
damping_u = scalar(0);
b_u = scalar(1);
stretching_v = scalar(0);
damping_v = scalar(0);
b_v = scalar(1);
}
// Initialize this definition from rest positions
void Initialize(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3);
// Particle 1
b3ClothParticle* p1;
// Particle 2
b3ClothParticle* p2;
// Particle 3
b3ClothParticle* p3;
// (u, v) coordinates for vertex 1 in the rest state
scalar u1, v1;
// (u, v) coordinates for vertex 2 in the rest state
scalar u2, v2;
// (u, v) coordinates for vertex 3 in the rest state
scalar u3, v3;
// Typically this is the triangle area in the rest state.
scalar alpha;
// Stretching stiffness in u direction
scalar stretching_u;
// Damping stiffness in u direction
scalar damping_u;
// Desired strechiness in u direction
scalar b_u;
// Stretching stiffness in v direction
scalar stretching_v;
// Damping stiffness in v direction
scalar damping_v;
// Desired strechiness in v direction
scalar b_v;
};
// Stretch force acting on a cloth triangle.
// This maintains the triangle edge lengths in the (u, v)
// frame of reference at a given desired normalized rest distance
// in the direction of the u and v coordinates.
class b3StretchForce : public b3Force
{
public:
// Has this force a given particle?
bool HasParticle(const b3ClothParticle* particle) const;
// Get the particle 1.
b3ClothParticle* GetParticle1();
const b3ClothParticle* GetParticle1() const;
// Get the particle 2.
b3ClothParticle* GetParticle2();
const b3ClothParticle* GetParticle2() const;
// Get the particle 2.
b3ClothParticle* GetParticle3();
const b3ClothParticle* GetParticle3() const;
// Get the spring stiffness in the u direction.
scalar GetStrechingStiffnessU() const;
// Get the damping stiffness in the u direction.
scalar GetDampingStiffnessU() const;
// Get the normalized rest lenght in the u direction.
scalar GetBU() const;
// Get the spring stiffness in the v direction.
scalar GetStrechingStiffnessV() const;
// Get the damping stiffness in the v direction.
scalar GetDampingStiffnessV() const;
// Get the normalized rest lenght in the v direction.
scalar GetBV() const;
// Get the force acting on particle 1.
b3Vec3 GetActionForce1() const;
// Get the force acting on particle 2.
b3Vec3 GetActionForce2() const;
// Get the force acting on particle 3.
b3Vec3 GetActionForce3() const;
private:
friend class b3Force;
friend class b3Cloth;
b3StretchForce(const b3StretchForceDef* def);
~b3StretchForce();
void Apply(const b3ClothForceSolverData* data);
// Particle 1
b3ClothParticle* m_p1;
// Particle 2
b3ClothParticle* m_p2;
// Particle 3
b3ClothParticle* m_p3;
// Alpha
scalar m_alpha;
// (u, v) matrix
scalar m_du1, m_dv1;
scalar m_du2, m_dv2;
scalar m_inv_det;
// dwudx, dwvdx
b3Vec3 m_dwudx, m_dwvdx;
// Streching stiffness in u direction
scalar m_ks_u;
// Damping stiffness in u direction
scalar m_kd_u;
// Desired strechiness in u direction
scalar m_b_u;
// Streching stiffness in v direction
scalar m_ks_v;
// Damping stiffness in v direction
scalar m_kd_v;
// Desired strechiness in v direction
scalar m_b_v;
// Action forces
b3Vec3 m_f1, m_f2, m_f3;
};
inline b3ClothParticle* b3StretchForce::GetParticle1()
{
return m_p1;
}
inline const b3ClothParticle* b3StretchForce::GetParticle1() const
{
return m_p1;
}
inline b3ClothParticle* b3StretchForce::GetParticle2()
{
return m_p2;
}
inline const b3ClothParticle* b3StretchForce::GetParticle2() const
{
return m_p2;
}
inline b3ClothParticle* b3StretchForce::GetParticle3()
{
return m_p3;
}
inline const b3ClothParticle* b3StretchForce::GetParticle3() const
{
return m_p3;
}
inline scalar b3StretchForce::GetStrechingStiffnessU() const
{
return m_ks_u;
}
inline scalar b3StretchForce::GetDampingStiffnessU() const
{
return m_kd_u;
}
inline scalar b3StretchForce::GetBU() const
{
return m_b_u;
}
inline scalar b3StretchForce::GetStrechingStiffnessV() const
{
return m_ks_v;
}
inline scalar b3StretchForce::GetDampingStiffnessV() const
{
return m_kd_v;
}
inline scalar b3StretchForce::GetBV() const
{
return m_b_v;
}
inline b3Vec3 b3StretchForce::GetActionForce1() const
{
return m_f1;
}
inline b3Vec3 b3StretchForce::GetActionForce2() const
{
return m_f2;
}
inline b3Vec3 b3StretchForce::GetActionForce3() const
{
return m_f3;
}
#endif

View File

@ -40,7 +40,7 @@ struct b3RectangleGarment : public b3Garment
b3RectanglePattern rectangle;
b3SewingPattern* rectanglePatterns[1];
b3RectangleGarment(float32 ex = 1.0f, float32 ey = 1.0f) : rectangle(ex, ey)
b3RectangleGarment(scalar ex = scalar(1), scalar ey = scalar(1)) : rectangle(ex, ey)
{
rectanglePatterns[0] = &rectangle;
@ -57,7 +57,7 @@ struct b3CircleGarment : public b3Garment
b3CirclePattern<> circle;
b3SewingPattern* circlePatterns[1];
b3CircleGarment(float32 r = 1.0f) : circle(r)
b3CircleGarment(scalar r = scalar(1)) : circle(r)
{
circlePatterns[0] = &circle;

View File

@ -57,7 +57,7 @@ struct b3GarmentMesh
b3GarmentMesh();
~b3GarmentMesh();
void Set(b3Garment* garment, float32 desiredArea);
void Set(b3Garment* garment, scalar desiredArea);
};
#endif

View File

@ -32,10 +32,10 @@ struct b3RectanglePattern : public b3SewingPattern
{
b3Vec2 rectangleVertices[4];
b3RectanglePattern(float32 ex = 1.0f, float32 ey = 1.0f)
b3RectanglePattern(scalar ex = scalar(1), scalar ey = scalar(1))
{
B3_ASSERT(ex > 0.0f);
B3_ASSERT(ey > 0.0f);
B3_ASSERT(ex > scalar(0));
B3_ASSERT(ey > scalar(0));
// R, CCW
rectangleVertices[0].Set(ex, -ey);
@ -55,19 +55,19 @@ struct b3CirclePattern : public b3SewingPattern
{
b3Vec2 circleVertices[E];
b3CirclePattern(float32 radius = 1.0f)
b3CirclePattern(scalar radius = scalar(1))
{
b3Vec2 center = b3Vec2_zero;
float32 x = 2.0f * B3_PI / float32(E);
float32 c = cos(x);
float32 s = sin(x);
scalar x = scalar(2) * B3_PI / scalar(E);
scalar c = cos(x);
scalar s = sin(x);
b3Mat22 R;
R.x.Set(c, s);
R.y.Set(-s, c);
b3Vec2 n(1.0f, 0.0f);
b3Vec2 n(1, 0);
circleVertices[0] = center + radius * n;
for (u32 i = 1; i < E; ++i)
{

View File

@ -22,33 +22,36 @@
#include <bounce/cloth/cloth_mesh.h>
// A (H + 1) x (W + 1) grid mesh stored in row-major order.
// v(i, j) = i + (W + 1) + j
template<u32 W = 1, u32 H = 1>
struct b3GridClothMesh : public b3ClothMesh
{
b3Vec3 gridVertices[(H + 1) * (W + 1)];
b3ClothMeshTriangle gridTriangles[2 * H * W];
b3ClothMeshMesh gridMesh;
b3ClothMeshShearingLine gridShearingLines[2 * H * W];
b3ClothMeshBendingLine gridBendingLines[(H + 1) * (W - 1) + (W + 1) * (H - 1)];
// Set this grid to a W (width) per H (height) dimensioned grid centered at the origin and aligned
// with the world x-z axes.
b3GridClothMesh()
{
vertexCount = 0;
for (u32 i = 0; i <= H; ++i)
for (u32 j = 0; j <= W; ++j)
{
for (u32 j = 0; j <= W; ++j)
for (u32 i = 0; i <= H; ++i)
{
gridVertices[vertexCount++].Set(float32(j), 0.0f, float32(i));
u32 vertex = GetVertex(i, j);
gridVertices[vertex].Set(scalar(j), scalar(0), scalar(i));
++vertexCount;
}
}
B3_ASSERT(vertexCount == (W + 1) * (H + 1));
B3_ASSERT(vertexCount == (H + 1) * (W + 1));
b3Vec3 translation;
translation.x = -0.5f * float32(W);
translation.y = 0.0f;
translation.z = -0.5f * float32(H);
translation.x = scalar(-0.5) * scalar(W);
translation.y = scalar(0);
translation.z = scalar(-0.5) * scalar(H);
for (u32 i = 0; i < vertexCount; ++i)
{
@ -60,25 +63,82 @@ struct b3GridClothMesh : public b3ClothMesh
{
for (u32 j = 0; j < W; ++j)
{
u32 v1 = i * (W + 1) + j;
u32 v2 = (i + 1) * (W + 1) + j;
u32 v3 = (i + 1) * (W + 1) + (j + 1);
u32 v4 = i * (W + 1) + (j + 1);
// 1*|----|*4
// |----|
// 2*|----|*3
u32 v1 = GetVertex(i, j);
u32 v2 = GetVertex(i + 1, j);
u32 v3 = GetVertex(i + 1, j + 1);
u32 v4 = GetVertex(i, j + 1);
b3ClothMeshTriangle* t1 = gridTriangles + triangleCount++;
t1->v1 = v3;
t1->v1 = v1;
t1->v2 = v2;
t1->v3 = v1;
t1->v3 = v3;
b3ClothMeshTriangle* t2 = gridTriangles + triangleCount++;
t2->v1 = v1;
t2->v1 = v3;
t2->v2 = v4;
t2->v3 = v3;
t2->v3 = v1;
}
}
B3_ASSERT(triangleCount == 2 * H * W);
shearingLineCount = 0;
for (u32 i = 0; i < H; ++i)
{
for (u32 j = 0; j < W; ++j)
{
// 1*|----|*4
// |----|
// 2*|----|*3
u32 v1 = GetVertex(i, j);
u32 v2 = GetVertex(i + 1, j);
u32 v3 = GetVertex(i + 1, j + 1);
u32 v4 = GetVertex(i, j + 1);
gridShearingLines[shearingLineCount].v1 = v1;
gridShearingLines[shearingLineCount].v2 = v3;
++shearingLineCount;
gridShearingLines[shearingLineCount].v1 = v4;
gridShearingLines[shearingLineCount].v2 = v2;
++shearingLineCount;
}
}
B3_ASSERT(shearingLineCount == 2 * H * W);
bendingLineCount = 0;
for (u32 i = 0; i <= H; ++i)
{
for (u32 j = 0; j < W - 1; ++j)
{
u32 v1 = GetVertex(i, j);
u32 v2 = GetVertex(i, j + 2);
gridBendingLines[bendingLineCount].v1 = v1;
gridBendingLines[bendingLineCount].v2 = v2;
++bendingLineCount;
}
}
for (u32 j = 0; j <= W; ++j)
{
for (u32 i = 0; i < H - 1; ++i)
{
u32 v1 = GetVertex(i, j);
u32 v2 = GetVertex(i + 2, j);
gridBendingLines[bendingLineCount].v1 = v1;
gridBendingLines[bendingLineCount].v2 = v2;
++bendingLineCount;
}
}
B3_ASSERT(bendingLineCount == (H + 1) * (W - 1) + (W + 1) * (H - 1));
gridMesh.startTriangle = 0;
gridMesh.triangleCount = triangleCount;
gridMesh.startVertex = 0;
@ -88,9 +148,18 @@ struct b3GridClothMesh : public b3ClothMesh
triangles = gridTriangles;
meshCount = 1;
meshes = &gridMesh;
shearingLines = gridShearingLines;
bendingLines = gridBendingLines;
sewingLineCount = 0;
sewingLines = nullptr;
}
u32 GetVertex(u32 i, u32 j)
{
B3_ASSERT(i < H + 1);
B3_ASSERT(j < W + 1);
return i * (W + 1) + j;
}
};
#endif

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_CAPSULE_SHAPE_H
#define B3_CLOTH_CAPSULE_SHAPE_H
#include <bounce/cloth/shapes/cloth_shape.h>
#include <bounce/collision/shapes/aabb.h>
#include <bounce/common/template/list.h>
class b3ClothParticle;
struct b3ClothCapsuleShapeDef : b3ClothShapeDef
{
b3ClothParticle* p1;
b3ClothParticle* p2;
};
// A cloth capsule shape
class b3ClothCapsuleShape : public b3ClothShape
{
public:
// Return the particle 1.
b3ClothParticle* GetParticle1() { return m_p1; }
const b3ClothParticle* GetParticle1() const { return m_p1; }
// Return the particle 2.
b3ClothParticle* GetParticle2() { return m_p2; }
const b3ClothParticle* GetParticle2() const { return m_p2; }
// Return the next capsule in the cloth capsule list.
b3ClothCapsuleShape* GetNext() { return m_next; }
const b3ClothCapsuleShape* GetNext() const { return m_next; }
private:
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ShearForce;
friend class b3StretchForce;
friend class b3MouseForce;
friend class b3ClothContactManager;
friend class b3ClothSphereAndTriangleContact;
friend class b3ClothCapsuleAndCapsuleContact;
friend class b3ClothSolver;
friend class b3ClothContactSolver;
friend class b3List2<b3ClothCapsuleShape>;
b3ClothCapsuleShape(const b3ClothCapsuleShapeDef& def, b3Cloth* cloth);
~b3ClothCapsuleShape();
// Compute AABB
b3AABB ComputeAABB() const;
// Synchronize AABB
void Synchronize(const b3Vec3& displacement);
// Destroy contacts
void DestroyContacts();
// Particles
b3ClothParticle* m_p1;
b3ClothParticle* m_p2;
// Links to the cloth capsule shape list.
b3ClothCapsuleShape* m_prev;
b3ClothCapsuleShape* m_next;
};
#endif

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_SHAPE_H
#define B3_CLOTH_SHAPE_H
#include <bounce/common/settings.h>
class b3Cloth;
// Cloth shape type
enum b3ClothShapeType
{
e_clothSphereShape,
e_clothCapsuleShape,
e_clothTriangleShape,
e_clothWorldShape,
e_maxClothShapes
};
// Cloth shape definition
struct b3ClothShapeDef
{
b3ClothShapeDef()
{
radius = scalar(0);
friction = scalar(0);
density = scalar(0);
meshIndex = B3_MAX_U32;
}
scalar radius;
scalar friction;
scalar density;
u32 meshIndex;
};
// Cloth shape
class b3ClothShape
{
public:
// Get the shape type.
b3ClothShapeType GetType() const;
// Get the cloth.
b3Cloth* GetCloth();
const b3Cloth* GetCloth() const;
// Get the shape radius.
scalar GetRadius() const;
// Get the shape density.
scalar GetDensity() const;
// Set the coefficient of friction of this shape.
void SetFriction(scalar friction);
// Get the coefficient of friction of this shape.
// This represents both static and dynamic friction.
scalar GetFriction() const;
protected:
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ClothContactManager;
friend class b3ClothContactSolver;
// Type
b3ClothShapeType m_type;
// Cloth
b3Cloth* m_cloth;
// Radius
scalar m_radius;
// Coefficient of friction
scalar m_friction;
// Density
scalar m_density;
// Broadphase ID
u32 m_broadPhaseId;
// Mesh index
u32 m_meshIndex;
};
inline b3ClothShapeType b3ClothShape::GetType() const
{
return m_type;
}
inline b3Cloth* b3ClothShape::GetCloth()
{
return m_cloth;
}
inline const b3Cloth* b3ClothShape::GetCloth() const
{
return m_cloth;
}
inline scalar b3ClothShape::GetRadius() const
{
return m_radius;
}
inline void b3ClothShape::SetFriction(scalar friction)
{
m_friction = friction;
}
inline scalar b3ClothShape::GetFriction() const
{
return m_friction;
}
inline scalar b3ClothShape::GetDensity() const
{
return m_density;
}
#endif

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_SPHERE_SHAPE_H
#define B3_CLOTH_SPHERE_SHAPE_H
#include <bounce/cloth/shapes/cloth_shape.h>
#include <bounce/collision/shapes/aabb.h>
#include <bounce/common/template/list.h>
class b3ClothParticle;
struct b3ClothSphereShapeDef : b3ClothShapeDef
{
b3ClothParticle* p;
};
// A cloth sphere shape
class b3ClothSphereShape : public b3ClothShape
{
public:
// Return the cloth particle.
b3ClothParticle* GetParticle() { return m_p; }
const b3ClothParticle* GetParticle() const { return m_p; }
// Return the next sphere in the cloth.
b3ClothSphereShape* GetNext() { return m_next; };
const b3ClothSphereShape* GetNext() const { return m_next; };
private:
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ClothContactManager;
friend class b3ClothSphereAndTriangleContact;
friend class b3ClothSphereAndShapeContact;
friend class b3ClothSolver;
friend class b3ClothContactSolver;
friend class b3List2<b3ClothSphereShape>;
b3ClothSphereShape(const b3ClothSphereShapeDef& def, b3Cloth* cloth);
~b3ClothSphereShape();
// Compute AABB
b3AABB ComputeAABB() const;
// Synchronize AABB
void Synchronize(const b3Vec3& displacement);
// Destroy contacts
void DestroyContacts();
// Particle
b3ClothParticle* m_p;
// Links to the cloth sphere shape list.
b3ClothSphereShape* m_prev;
b3ClothSphereShape* m_next;
};
#endif

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_TRIANGLE_SHAPE_H
#define B3_CLOTH_TRIANGLE_SHAPE_H
#include <bounce/cloth/shapes/cloth_shape.h>
#include <bounce/collision/shapes/aabb.h>
#include <bounce/common/template/list.h>
class b3ClothParticle;
struct b3ClothTriangleShapeDef : public b3ClothShapeDef
{
b3ClothParticle* p1;
b3ClothParticle* p2;
b3ClothParticle* p3;
b3Vec3 v1, v2, v3;
};
// A triangle shape
class b3ClothTriangleShape : public b3ClothShape
{
public:
// Return the particle 1.
b3ClothParticle* GetParticle1() { return m_p1; }
const b3ClothParticle* GetParticle1() const { return m_p1; }
// Return the particle 2.
b3ClothParticle* GetParticle2() { return m_p2; }
const b3ClothParticle* GetParticle2() const { return m_p2; }
// Return the particle 3.
b3ClothParticle* GetParticle3() { return m_p3; }
const b3ClothParticle* GetParticle3() const { return m_p3; }
// Return the next triangle shape in the cloth list of shapes.
b3ClothTriangleShape* GetNext() { return m_next; }
const b3ClothTriangleShape* GetNext() const { return m_next; }
private:
friend class b3Cloth;
friend class b3ClothParticle;
friend class b3ShearForce;
friend class b3StretchForce;
friend class b3MouseForce;
friend class b3ClothContactManager;
friend class b3ClothSphereAndTriangleContact;
friend class b3ClothSolver;
friend class b3ClothContactSolver;
friend class b3List2<b3ClothTriangleShape>;
b3ClothTriangleShape(const b3ClothTriangleShapeDef& def, b3Cloth* cloth);
~b3ClothTriangleShape();
// Compute AABB
b3AABB ComputeAABB() const;
// Synchronize the AABB
void Synchronize(const b3Vec3& displacement);
// Destroy shape contacts
void DestroyContacts();
// Particles
b3ClothParticle* m_p1;
b3ClothParticle* m_p2;
b3ClothParticle* m_p3;
// Rest area. Used for computing the mass of the particles.
scalar m_area;
// Links to the cloth triangle shape list.
b3ClothTriangleShape* m_prev;
b3ClothTriangleShape* m_next;
};
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CLOTH_WORLD_SHAPE_H
#define B3_CLOTH_WORLD_SHAPE_H
#include <bounce/cloth/shapes/cloth_shape.h>
#include <bounce/common/template/list.h>
#include <bounce/collision/shapes/aabb.h>
class b3Cloth;
class b3Shape;
struct b3ClothWorldShapeDef : b3ClothShapeDef
{
const b3Shape* shape;
};
class b3ClothWorldShape : public b3ClothShape
{
public:
// Return the attached world shape.
const b3Shape* GetShape() { return m_shape; }
const b3Shape* GetShape() const { return m_shape; }
// Return the next world shape in the cloth list of world shapes.
b3ClothWorldShape* GetNext() { return m_next; }
const b3ClothWorldShape* GetNext() const { return m_next; }
private:
friend class b3Cloth;
friend class b3ClothContactManager;
friend class b3ClothSphereAndShapeContact;
friend class b3ClothContactSolver;
friend class b3List2<b3ClothWorldShape>;
b3ClothWorldShape(const b3ClothWorldShapeDef& def, b3Cloth* cloth);
~b3ClothWorldShape();
// Compute AABB.
b3AABB ComputeAABB() const;
// Synchronize AABB.
void Synchronize(const b3Vec3& displacement);
// Destroy contacts.
void DestroyContacts();
// Shape in the world.
const b3Shape* m_shape;
// Cloth list links.
b3ClothWorldShape* m_prev;
b3ClothWorldShape* m_next;
};
#endif

View File

@ -41,7 +41,7 @@ public:
~b3BroadPhase();
// Create a proxy and return a index to it.
u32 CreateProxy(const b3AABB3& aabb, void* userData);
u32 CreateProxy(const b3AABB& aabb, void* userData);
// Destroy a given proxy and remove it from the broadphase.
void DestroyProxy(u32 proxyId);
@ -49,13 +49,13 @@ public:
// Update an existing proxy AABB with a given AABB and a displacement.
// displacement = dt * velocity
// Return true if the proxy has moved.
bool MoveProxy(u32 proxyId, const b3AABB3& aabb, const b3Vec3& displacement);
bool MoveProxy(u32 proxyId, const b3AABB& aabb, const b3Vec3& displacement);
// Force move the proxy
void TouchProxy(u32 proxyId);
// Get the AABB of a given proxy.
const b3AABB3& GetAABB(u32 proxyId) const;
const b3AABB& GetAABB(u32 proxyId) const;
// Get the user data attached to a proxy.
void* GetUserData(u32 proxyId) const;
@ -68,7 +68,7 @@ public:
// Notify the client callback the AABBs that are overlapping with the passed AABB.
template<class T>
void QueryAABB(T* callback, const b3AABB3& aabb) const;
void QueryAABB(T* callback, const b3AABB& aabb) const;
// Notify the client callback the AABBs that are overlapping the
// passed ray.
@ -114,7 +114,7 @@ private :
u32 m_pairCount;
};
inline const b3AABB3& b3BroadPhase::GetAABB(u32 proxyId) const
inline const b3AABB& b3BroadPhase::GetAABB(u32 proxyId) const
{
return m_tree.GetAABB(proxyId);
}
@ -130,7 +130,7 @@ inline u32 b3BroadPhase::GetProxyCount() const
}
template<class T>
inline void b3BroadPhase::QueryAABB(T* callback, const b3AABB3& aabb) const
inline void b3BroadPhase::QueryAABB(T* callback, const b3AABB& aabb) const
{
return m_tree.QueryAABB(callback, aabb);
}
@ -174,7 +174,7 @@ inline void b3BroadPhase::FindPairs(T* callback)
continue;
}
const b3AABB3& aabb = m_tree.GetAABB(m_queryProxyId);
const b3AABB& aabb = m_tree.GetAABB(m_queryProxyId);
m_tree.QueryAABB(this, aabb);
}

View File

@ -19,25 +19,24 @@
#ifndef B3_COLLISION_H
#define B3_COLLISION_H
#include <bounce/common/geometry.h>
#include <bounce/collision/shapes/aabb3.h>
#include <bounce/common/math/vec3.h>
// Input for a ray cast.
struct b3RayCastInput
{
b3Vec3 p1; // first point on segment
b3Vec3 p2; // second point on segment
float32 maxFraction; // maximum intersection
scalar maxFraction; // maximum intersection
};
// Output of a ray cast.
struct b3RayCastOutput
{
float32 fraction; // time of intersection on ray-segment
scalar fraction; // time of intersection on ray-segment
b3Vec3 normal; // surface normal of intersection
};
// Perform a ray-cast on a triangle.
// Perform a ray-cast against a triangle.
bool b3RayCast(b3RayCastOutput* output, const b3RayCastInput* input,
const b3Vec3& v1, const b3Vec3& v2, const b3Vec3& v3);

View File

@ -31,7 +31,7 @@ struct b3SimplexVertex
b3Vec3 point1; // support vertex on proxy 1
b3Vec3 point2; // support vertex on proxy 2
b3Vec3 point; // minkowski vertex
float32 weight; // barycentric coordinate for point
scalar weight; // barycentric coordinate for point
u32 index1; // support 1 vertex index
u32 index2; // support 2 vertex index
};
@ -56,7 +56,7 @@ struct b3Simplex
void WriteCache(b3SimplexCache* cache) const;
float32 GetMetric() const;
scalar GetMetric() const;
};
// The output of the GJK algorithm.
@ -67,13 +67,13 @@ struct b3GJKOutput
{
b3Vec3 point1; // closest point on proxy 1
b3Vec3 point2; // closest point on proxy 2
float32 distance; // euclidean distance between the closest points
scalar distance; // euclidean distance between the closest points
u32 iterations; // number of GJK iterations
};
// Find the closest points and distance between two proxies.
b3GJKOutput b3GJK(const b3Transform& xf1, const b3GJKProxy& proxy1,
const b3Transform& xf2, const b3GJKProxy& proxy2);
const b3Transform& xf2, const b3GJKProxy& proxy2, bool applyRadius);
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -84,7 +84,7 @@ b3GJKOutput b3GJK(const b3Transform& xf1, const b3GJKProxy& proxy1,
// for the first time.
struct b3SimplexCache
{
float32 metric; // distance or area or volume
scalar metric; // lenght or area or volume
u32 iterations; // number of GJK iterations
u16 count; // number of support vertices
u8 index1[4]; // support vertices on proxy 1
@ -114,18 +114,4 @@ b3GJKOutput b3GJK(const b3Transform& xf1, const b3GJKProxy& proxy1,
const b3Transform& xf2, const b3GJKProxy& proxy2,
bool applyRadius, b3SimplexCache* cache);
// The output of the GJK-based shape cast algorithm.
struct b3GJKShapeCastOutput
{
float32 t; // time of impact
b3Vec3 point; // contact point at t
b3Vec3 normal; // contact normal at t
u32 iterations; // number of iterations
};
// Find the time of impact between two proxies given the relative target translation vector.
bool b3GJKShapeCast(b3GJKShapeCastOutput* output,
const b3Transform& xf1, const b3GJKProxy& proxy1,
const b3Transform& xf2, const b3GJKProxy& proxy2, const b3Vec3& translation2);
#endif

View File

@ -26,7 +26,7 @@ struct b3GJKProxy
{
const b3Vec3* vertices; // vertices in this proxy
u32 vertexCount; // number of vertices
float32 radius; // proxy radius
scalar radius; // proxy radius
b3Vec3 vertexBuffer[3]; // vertex buffer for convenience
// Get the number of vertices in this proxy.
@ -57,10 +57,10 @@ inline const b3Vec3& b3GJKProxy::GetVertex(u32 index) const
inline u32 b3GJKProxy::GetSupportIndex(const b3Vec3& d) const
{
u32 maxIndex = 0;
float32 maxProjection = b3Dot(d, vertices[maxIndex]);
scalar maxProjection = b3Dot(d, vertices[maxIndex]);
for (u32 i = 1; i < vertexCount; ++i)
{
float32 projection = b3Dot(d, vertices[i]);
scalar projection = b3Dot(d, vertices[i]);
if (projection > maxProjection)
{
maxIndex = i;

View File

@ -28,10 +28,10 @@ struct b3Hull;
struct b3FaceQuery
{
u32 index;
float32 separation;
scalar separation;
};
float32 b3Project(const b3Hull* hull, const b3Plane& plane);
scalar b3Project(const b3Hull* hull, const b3Plane& plane);
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Hull* hull2);
@ -42,12 +42,12 @@ struct b3EdgeQuery
{
u32 index1;
u32 index2;
float32 separation;
scalar separation;
};
bool b3IsMinkowskiFace(const b3Vec3& A, const b3Vec3& B, const b3Vec3& B_x_A, const b3Vec3& C, const b3Vec3& D, const b3Vec3& D_x_C);
float32 b3Project(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C1);
scalar b3Project(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C1);
b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Hull* hull2);
@ -94,13 +94,13 @@ struct b3FeatureCache
// Read the current state of the cache.
// Return e_unkown if neither a separation or penetration was detected.
b3SATCacheType ReadState(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Hull* hull2, float32 totalRadius);
const b3Transform& xf2, const b3Hull* hull2, scalar totalRadius);
b3SATCacheType ReadEdge(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Hull* hull2, float32 totalRadius);
const b3Transform& xf2, const b3Hull* hull2, scalar totalRadius);
b3SATCacheType ReadFace(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Hull* hull2, float32 totalRadius);
const b3Transform& xf2, const b3Hull* hull2, scalar totalRadius);
b3SATFeaturePair m_featurePair;
};

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_HULL_AND_EDGE_SAT_H
#define B3_HULL_AND_EDGE_SAT_H
#include <bounce/collision/sat/sat.h>
struct b3Capsule;
///////////////////////////////////////////////////////////////////////////////////////////////////
scalar b3ProjectEdge(const b3Capsule* hull, const b3Plane& plane);
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Capsule* hull2);
///////////////////////////////////////////////////////////////////////////////////////////////////
scalar b3ProjectEdge(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C2);
b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Capsule* hull2);
#endif

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_HULL_AND_VERTEX_SAT_H
#define B3_HULL_AND_VERTEX_SAT_H
#include <bounce/collision/sat/sat.h>
struct b3Sphere;
///////////////////////////////////////////////////////////////////////////////////////////////////
scalar b3ProjectVertex(const b3Sphere* hull, const b3Plane& plane);
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Hull* hull1,
const b3Transform& xf2, const b3Sphere* hull2);
#endif

View File

@ -0,0 +1,370 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_AABB_H
#define B3_AABB_H
#include <bounce/common/math/transform.h>
#include <bounce/collision/collision.h>
// A min-max representation of a three-dimensional AABB.
struct b3AABB
{
// Constructor. Does nothing for performance.
b3AABB() { }
// Get the support vertex in a given direction.
b3Vec3 GetSupportVertex(const b3Vec3& direction) const
{
b3Vec3 support;
support.x = direction.x < scalar(0) ? lowerBound.x : upperBound.x;
support.y = direction.y < scalar(0) ? lowerBound.y : upperBound.y;
support.z = direction.z < scalar(0) ? lowerBound.z : upperBound.z;
return support;
}
// Set this AABB from a list of points.
void Set(const b3Vec3* points, u32 count)
{
lowerBound = upperBound = points[0];
for (u32 i = 1; i < count; ++i)
{
lowerBound = b3Min(lowerBound, points[i]);
upperBound = b3Max(upperBound, points[i]);
}
}
// Set this AABB from a list of points and a transform.
void Set(const b3Vec3* points, u32 count, const b3Transform& xf)
{
lowerBound = upperBound = b3Mul(xf, points[0]);
for (u32 i = 1; i < count; ++i)
{
b3Vec3 v = b3Mul(xf, points[i]);
lowerBound = b3Min(lowerBound, v);
upperBound = b3Max(upperBound, v);
}
}
// Set this AABB from a list of points, a local scale, and a transform.
void Set(const b3Vec3* points, u32 count, const b3Vec3& scale, const b3Transform& xf)
{
lowerBound = upperBound = b3Mul(xf, b3MulCW(scale, points[0]));
for (u32 i = 1; i < count; ++i)
{
b3Vec3 v = b3Mul(xf, b3MulCW(scale, points[i]));
lowerBound = b3Min(lowerBound, v);
upperBound = b3Max(upperBound, v);
}
}
// Set this AABB from two points.
void SetSegment(const b3Vec3& p1, const b3Vec3& p2)
{
lowerBound = b3Min(p1, p2);
upperBound = b3Max(p1, p2);
}
// Set this AABB from three points.
void SetTriangle(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3)
{
lowerBound = b3Min(p1, b3Min(p2, p3));
upperBound = b3Max(p1, b3Max(p2, p3));
}
// Set this AABB from a center point and a radius vector.
void Set(const b3Vec3& center, const b3Vec3& r)
{
lowerBound = center - r;
upperBound = center + r;
}
// Set this AABB from a center point and a radius value.
void Set(const b3Vec3& center, scalar radius)
{
b3Vec3 r(radius, radius, radius);
Set(center, r);
}
// Extend this AABB by a radius value.
void Extend(scalar s)
{
b3Vec3 r(s, s, s);
lowerBound -= r;
upperBound += r;
}
// Extend this AABB by a radius vector.
void Extend(const b3Vec3& r)
{
lowerBound -= r;
upperBound += r;
}
// Get the center of this AABB.
b3Vec3 GetCenter() const
{
return scalar(0.5) * (lowerBound + upperBound);
}
// Get the half-extents of this AABB.
b3Vec3 GetExtents() const
{
return scalar(0.5) * (upperBound - lowerBound);
}
// Get the width of this AABB.
scalar GetWidth() const
{
return upperBound.x - lowerBound.x;
}
// Get the height of this AABB.
scalar GetHeight() const
{
return upperBound.y - lowerBound.y;
}
// Get the depth of this AABB.
scalar GetDepth() const
{
return upperBound.z - lowerBound.z;
}
// Get the volume of this AABB.
scalar GetVolume() const
{
b3Vec3 d = upperBound - lowerBound;
return d.x * d.y * d.z;
}
// Get the surface area of this AABB.
scalar GetSurfaceArea() const
{
b3Vec3 d = upperBound - lowerBound;
return scalar(2) * (d.x * d.y + d.y * d.z + d.z * d.x);
}
// Get the index of the longest axis of this AABB.
u32 GetLongestAxisIndex() const
{
b3Vec3 d = upperBound - lowerBound;
scalar maxValue = d.x;
u32 maxIndex = 0;
if (d.y > maxValue)
{
maxValue = d.y;
maxIndex = 1;
}
if (d.z > maxValue)
{
maxValue = d.z;
maxIndex = 2;
}
return maxIndex;
}
// Test if this AABB contains a point.
bool Contains(const b3Vec3& point) const
{
return lowerBound.x <= point.x && point.x <= upperBound.x &&
lowerBound.y <= point.y && point.y <= upperBound.y &&
lowerBound.z <= point.z && point.z <= upperBound.z;
}
// Test if this AABB contains another AABB.
bool Contains(const b3AABB& aabb) const
{
return Contains(aabb.lowerBound) && Contains(aabb.upperBound);
}
// Perform a ray-cast against this AABB.
bool RayCast(b3RayCastOutput* output, const b3RayCastInput& input) const
{
b3Vec3 p1 = input.p1;
b3Vec3 p2 = input.p2;
b3Vec3 d = p2 - p1;
b3Vec3 normals[6];
normals[0].Set(scalar(-1), scalar(0), scalar(0));
normals[1].Set(scalar(1), scalar(0), scalar(0));
normals[2].Set(scalar(0), scalar(-1), scalar(0));
normals[3].Set(scalar(0), scalar(1), scalar(0));
normals[4].Set(scalar(0), scalar(0), scalar(-1));
normals[5].Set(scalar(0), scalar(0), scalar(1));
u32 index = B3_MAX_U32;
scalar lower = scalar(0);
scalar upper = input.maxFraction;
u32 planeIndex = 0;
for (u32 i = 0; i < 3; ++i)
{
scalar numerators[2], denominators[2];
numerators[0] = p1[i] - lowerBound[i];
numerators[1] = upperBound[i] - p1[i];
denominators[0] = -d[i];
denominators[1] = d[i];
for (u32 j = 0; j < 2; ++j)
{
scalar numerator = numerators[j];
scalar denominator = denominators[j];
if (denominator == scalar(0))
{
// s is parallel to this half-space.
if (numerator < scalar(0))
{
// s is outside of this half-space.
// dot(n, p1) and dot(n, p2) < 0.
return false;
}
}
else
{
if (denominator < scalar(0))
{
// s enters this half-space.
if (numerator < lower * denominator)
{
// Increase lower.
lower = numerator / denominator;
index = planeIndex;
}
}
else
{
// s exits the half-space.
if (numerator < upper * denominator)
{
// Decrease upper.
upper = numerator / denominator;
}
}
// Exit if intersection becomes empty.
if (upper < lower)
{
return false;
}
}
++planeIndex;
}
}
B3_ASSERT(lower >= scalar(0) && lower <= input.maxFraction);
if (index != B3_MAX_U32)
{
output->fraction = lower;
output->normal = normals[index];
return true;
}
return false;
}
b3Vec3 lowerBound; // lower vertex
b3Vec3 upperBound; // upper vertex
};
// Compute an AABB that encloses two AABBs.
inline b3AABB b3Combine(const b3AABB& a, const b3AABB& b)
{
b3AABB aabb;
aabb.lowerBound = b3Min(a.lowerBound, b.lowerBound);
aabb.upperBound = b3Max(a.upperBound, b.upperBound);
return aabb;
}
// Test if two AABBs are overlapping.
inline bool b3TestOverlap(const b3AABB& a, const b3AABB& b)
{
return (a.lowerBound.x <= b.upperBound.x) && (a.lowerBound.y <= b.upperBound.y) && (a.lowerBound.z <= b.upperBound.z) &&
(a.upperBound.x >= b.lowerBound.x) && (a.upperBound.y >= b.lowerBound.y) && (a.upperBound.z >= b.lowerBound.z);
}
// Transform a AABB by a given frame.
inline b3AABB b3TransformAABB(const b3AABB& local_aabb, const b3Transform& xf)
{
b3Vec3 local_center = local_aabb.GetCenter();
b3Vec3 local_radius = local_aabb.GetExtents();
b3Vec3 center = xf * local_center;
b3Mat33 rotation = b3Abs(b3QuatMat33(xf.rotation));
b3Vec3 radius;
radius.x = b3Dot(local_radius, rotation.x);
radius.y = b3Dot(local_radius, rotation.y);
radius.z = b3Dot(local_radius, rotation.z);
b3AABB aabb;
aabb.Set(center, radius);
return aabb;
}
// Transform a AABB given a local scale by a given frame.
inline b3AABB b3TransformAABB(const b3AABB& local_aabb, const b3Vec3& local_scale, const b3Transform& xf)
{
b3Vec3 local_center = local_aabb.GetCenter();
b3Vec3 local_radius = b3MulCW(b3Abs(local_scale), local_aabb.GetExtents());
b3Vec3 center = xf * local_center;
b3Mat33 rotation = b3Abs(b3QuatMat33(xf.rotation));
b3Vec3 radius;
radius.x = b3Dot(local_radius, rotation.x);
radius.y = b3Dot(local_radius, rotation.y);
radius.z = b3Dot(local_radius, rotation.z);
b3AABB aabb;
aabb.Set(center, radius);
return aabb;
}
// Scale an AABB by a scale.
// The scale can be non-uniform and negative.
inline b3AABB b3ScaleAABB(const b3AABB& aabb, const b3Vec3& scale)
{
b3AABB scaled_aabb;
scaled_aabb.lowerBound.x = scale.x > scalar(0) ? scale.x * aabb.lowerBound.x : scale.x * aabb.upperBound.x;
scaled_aabb.lowerBound.y = scale.y > scalar(0) ? scale.y * aabb.lowerBound.y : scale.y * aabb.upperBound.y;
scaled_aabb.lowerBound.z = scale.z > scalar(0) ? scale.z * aabb.lowerBound.z : scale.z * aabb.upperBound.z;
scaled_aabb.upperBound.x = scale.x > scalar(0) ? scale.x * aabb.upperBound.x : scale.x * aabb.lowerBound.x;
scaled_aabb.upperBound.y = scale.y > scalar(0) ? scale.y * aabb.upperBound.y : scale.y * aabb.lowerBound.y;
scaled_aabb.upperBound.z = scale.z > scalar(0) ? scale.z * aabb.upperBound.z : scale.z * aabb.lowerBound.z;
return scaled_aabb;
}
#endif

View File

@ -32,140 +32,74 @@ struct b3BoxHull : public b3Hull
b3BoxHull() { }
// Construct this box from three extents and centered at the origin.
b3BoxHull(float32 ex, float32 ey, float32 ez)
b3BoxHull(scalar ex, scalar ey, scalar ez)
{
Set(ex, ey, ez);
SetExtents(ex, ey, ez);
}
// Set this box to the unit box centered at the origin.
void SetIdentity()
{
boxVertices[0] = b3Vec3(1.0f, 1.0f, -1.0f);
boxVertices[1] = b3Vec3(-1.0f, 1.0f, -1.0f);
boxVertices[2] = b3Vec3(-1.0f, -1.0f, -1.0f);
boxVertices[3] = b3Vec3(1.0f, -1.0f, -1.0f);
boxVertices[4] = b3Vec3(1.0f, 1.0f, 1.0f);
boxVertices[5] = b3Vec3(-1.0f, 1.0f, 1.0f);
boxVertices[6] = b3Vec3(-1.0f, -1.0f, 1.0f);
boxVertices[7] = b3Vec3(1.0f, -1.0f, 1.0f);
boxVertices[0] = b3Vec3(-1, -1, 1);
boxVertices[1] = b3Vec3(1, -1, -1);
boxVertices[2] = b3Vec3(1, 1, 1);
boxVertices[3] = b3Vec3(-1, 1, -1);
boxVertices[4] = b3Vec3(1, 1, -1);
boxVertices[5] = b3Vec3(-1, 1, 1);
boxVertices[6] = b3Vec3(1, -1, 1);
boxVertices[7] = b3Vec3(-1, -1, -1);
boxEdges[0] = b3MakeEdge(1, 1, 0, 2);
boxEdges[1] = b3MakeEdge(2, 0, 5, 21);
boxEdges[2] = b3MakeEdge(2, 3, 0, 4);
boxEdges[3] = b3MakeEdge(6, 2, 2, 18);
boxEdges[4] = b3MakeEdge(6, 5, 0, 6);
boxEdges[5] = b3MakeEdge(5, 4, 4, 17);
boxEdges[6] = b3MakeEdge(5, 7, 0, 0);
boxEdges[7] = b3MakeEdge(1, 6, 3, 22);
boxEdges[8] = b3MakeEdge(4, 9, 1, 10);
boxEdges[9] = b3MakeEdge(7, 8, 4, 23);
boxEdges[10] = b3MakeEdge(7, 11, 1, 12);
boxEdges[11] = b3MakeEdge(3, 10, 2, 16);
boxEdges[12] = b3MakeEdge(3, 13, 1, 14);
boxEdges[13] = b3MakeEdge(0, 12, 5, 19);
boxEdges[14] = b3MakeEdge(0, 15, 1, 8);
boxEdges[15] = b3MakeEdge(4, 14, 3, 20);
boxEdges[16] = b3MakeEdge(7, 17, 2, 3);
boxEdges[17] = b3MakeEdge(6, 16, 4, 9);
boxEdges[18] = b3MakeEdge(2, 19, 2, 11);
boxEdges[19] = b3MakeEdge(3, 18, 5, 1);
boxEdges[20] = b3MakeEdge(0, 21, 3, 7);
boxEdges[21] = b3MakeEdge(1, 20, 5, 13);
boxEdges[22] = b3MakeEdge(5, 23, 3, 15);
boxEdges[23] = b3MakeEdge(4, 22, 4, 5);
boxEdges[0] = b3MakeEdge(0, 1, 0, 6, 2);
boxEdges[1] = b3MakeEdge(5, 0, 1, 12, 8);
boxEdges[2] = b3MakeEdge(5, 3, 0, 0, 4);
boxEdges[3] = b3MakeEdge(3, 2, 5, 19, 13);
boxEdges[4] = b3MakeEdge(3, 5, 0, 2, 6);
boxEdges[5] = b3MakeEdge(7, 4, 3, 15, 18);
boxEdges[6] = b3MakeEdge(7, 7, 0, 4, 0);
boxEdges[7] = b3MakeEdge(0, 6, 2, 9, 14);
boxEdges[8] = b3MakeEdge(0, 9, 1, 1, 10);
boxEdges[9] = b3MakeEdge(6, 8, 2, 16, 7);
boxEdges[10] = b3MakeEdge(6, 11, 1, 8, 12);
boxEdges[11] = b3MakeEdge(2, 10, 4, 22, 17);
boxEdges[12] = b3MakeEdge(2, 13, 1, 10, 1);
boxEdges[13] = b3MakeEdge(5, 12, 5, 3, 23);
boxEdges[14] = b3MakeEdge(7, 15, 2, 7, 16);
boxEdges[15] = b3MakeEdge(1, 14, 3, 20, 5);
boxEdges[16] = b3MakeEdge(1, 17, 2, 14, 9);
boxEdges[17] = b3MakeEdge(6, 16, 4, 11, 21);
boxEdges[18] = b3MakeEdge(3, 19, 3, 5, 20);
boxEdges[19] = b3MakeEdge(4, 18, 5, 23, 3);
boxEdges[20] = b3MakeEdge(4, 21, 3, 18, 15);
boxEdges[21] = b3MakeEdge(1, 20, 4, 17, 22);
boxEdges[22] = b3MakeEdge(4, 23, 4, 21, 11);
boxEdges[23] = b3MakeEdge(2, 22, 5, 13, 19);
boxFaces[0].edge = 6;
boxFaces[1].edge = 14;
boxFaces[2].edge = 18;
boxFaces[0].edge = 0;
boxFaces[1].edge = 8;
boxFaces[2].edge = 7;
boxFaces[3].edge = 15;
boxFaces[4].edge = 9;
boxFaces[5].edge = 21;
boxFaces[4].edge = 21;
boxFaces[5].edge = 23;
boxPlanes[0] = b3Plane(b3Vec3(-1.0f, 0.0f, 0.0f), boxVertices[1]);
boxPlanes[1] = b3Plane(b3Vec3(1.0f, 0.0f, 0.0f), boxVertices[0]);
boxPlanes[2] = b3Plane(b3Vec3(0.0f, -1.0f, 0.0f), boxVertices[2]);
boxPlanes[3] = b3Plane(b3Vec3(0.0f, 1.0f, 0.0f), boxVertices[1]);
boxPlanes[4] = b3Plane(b3Vec3(0.0f, 0.0f, 1.0f), boxVertices[4]);
boxPlanes[5] = b3Plane(b3Vec3(0.0f, 0.0f, -1.0f), boxVertices[0]);
centroid = b3Vec3(0.0f, 0.0f, 0.0f);
vertices = boxVertices;
vertexCount = 8;
edges = boxEdges;
edgeCount = 24;
faces = boxFaces;
planes = boxPlanes;
faceCount = 6;
boxPlanes[0].normal = b3Vec3(-1, 0, 0);
boxPlanes[0].offset = 1;
Validate();
}
// Set this box from three extents and centered at the origin.
void Set(float32 ex, float32 ey, float32 ez)
{
b3Transform xf;
xf.position.SetZero();
xf.rotation = b3Diagonal(ex, ey, ez);
SetTransform(xf);
}
boxPlanes[1].normal = b3Vec3(0, 0, 1);
boxPlanes[1].offset = 1;
boxPlanes[2].normal = b3Vec3(0, -1, 0);
boxPlanes[2].offset = 1;
boxPlanes[3].normal = b3Vec3(0, 0, -1);
boxPlanes[3].offset = 1;
boxPlanes[4].normal = b3Vec3(1, 0, 0);
boxPlanes[4].offset = 1;
boxPlanes[5].normal = b3Vec3(0, 1, 0);
boxPlanes[5].offset = 1;
// Set this box to the unit box and transform it.
void SetTransform(const b3Transform& T)
{
boxVertices[0] = b3Vec3(1.0f, 1.0f, -1.0f);
boxVertices[1] = b3Vec3(-1.0f, 1.0f, -1.0f);
boxVertices[2] = b3Vec3(-1.0f, -1.0f, -1.0f);
boxVertices[3] = b3Vec3(1.0f, -1.0f, -1.0f);
boxVertices[4] = b3Vec3(1.0f, 1.0f, 1.0f);
boxVertices[5] = b3Vec3(-1.0f, 1.0f, 1.0f);
boxVertices[6] = b3Vec3(-1.0f, -1.0f, 1.0f);
boxVertices[7] = b3Vec3(1.0f, -1.0f, 1.0f);
for (u32 i = 0; i < 8; ++i)
{
boxVertices[i] = T * boxVertices[i];
}
boxEdges[0] = b3MakeEdge(1, 1, 0, 2);
boxEdges[1] = b3MakeEdge(2, 0, 5, 21);
boxEdges[2] = b3MakeEdge(2, 3, 0, 4);
boxEdges[3] = b3MakeEdge(6, 2, 2, 18);
boxEdges[4] = b3MakeEdge(6, 5, 0, 6);
boxEdges[5] = b3MakeEdge(5, 4, 4, 17);
boxEdges[6] = b3MakeEdge(5, 7, 0, 0);
boxEdges[7] = b3MakeEdge(1, 6, 3, 22);
boxEdges[8] = b3MakeEdge(4, 9, 1, 10);
boxEdges[9] = b3MakeEdge(7, 8, 4, 23);
boxEdges[10] = b3MakeEdge(7, 11, 1, 12);
boxEdges[11] = b3MakeEdge(3, 10, 2, 16);
boxEdges[12] = b3MakeEdge(3, 13, 1, 14);
boxEdges[13] = b3MakeEdge(0, 12, 5, 19);
boxEdges[14] = b3MakeEdge(0, 15, 1, 8);
boxEdges[15] = b3MakeEdge(4, 14, 3, 20);
boxEdges[16] = b3MakeEdge(7, 17, 2, 3);
boxEdges[17] = b3MakeEdge(6, 16, 4, 9);
boxEdges[18] = b3MakeEdge(2, 19, 2, 11);
boxEdges[19] = b3MakeEdge(3, 18, 5, 1);
boxEdges[20] = b3MakeEdge(0, 21, 3, 7);
boxEdges[21] = b3MakeEdge(1, 20, 5, 13);
boxEdges[22] = b3MakeEdge(5, 23, 3, 15);
boxEdges[23] = b3MakeEdge(4, 22, 4, 5);
boxFaces[0].edge = 6;
boxFaces[1].edge = 14;
boxFaces[2].edge = 18;
boxFaces[3].edge = 15;
boxFaces[4].edge = 9;
boxFaces[5].edge = 21;
boxPlanes[0] = b3Plane(b3Vec3(-1.0f, 0.0f, 0.0f), boxVertices[1]);
boxPlanes[1] = b3Plane(b3Vec3(1.0f, 0.0f, 0.0f), boxVertices[0]);
boxPlanes[2] = b3Plane(b3Vec3(0.0f, -1.0f, 0.0f), boxVertices[2]);
boxPlanes[3] = b3Plane(b3Vec3(0.0f, 1.0f, 0.0f), boxVertices[1]);
boxPlanes[4] = b3Plane(b3Vec3(0.0f, 0.0f, 1.0f), boxVertices[4]);
boxPlanes[5] = b3Plane(b3Vec3(0.0f, 0.0f, -1.0f), boxVertices[0]);
centroid = b3Vec3(0.0f, 0.0f, 0.0f);
centroid = b3Vec3(0, 0, 0);
vertices = boxVertices;
vertexCount = 8;
edges = boxEdges;
@ -174,10 +108,17 @@ struct b3BoxHull : public b3Hull
planes = boxPlanes;
faceCount = 6;
centroid = T * centroid;
Validate();
}
// Set this box from three extents and centered and aligned at the origin.
void SetExtents(scalar ex, scalar ey, scalar ez)
{
SetIdentity();
b3Vec3 scale(ex, ey, ez);
Scale(scale);
}
};
extern const b3BoxHull b3BoxHull_identity;

View File

@ -23,23 +23,18 @@
struct b3Capsule
{
//
b3Vec3 vertex1, vertex2;
scalar radius;
b3Capsule() { }
//
b3Capsule(const b3Vec3& v1, const b3Vec3& v2, float32 r)
b3Capsule(const b3Vec3& v1, const b3Vec3& v2, scalar r)
{
vertices[0] = v1;
vertices[1] = v2;
vertex1 = v1;
vertex2 = v2;
radius = r;
}
//
~b3Capsule() { }
b3Vec3 vertices[2];
float32 radius;
const b3Vec3& GetVertex(u32 index) const;
u32 GetSupportVertex(const b3Vec3& direction) const;
};
@ -49,12 +44,12 @@ extern const b3Capsule b3Capsule_identity;
inline const b3Vec3& b3Capsule::GetVertex(u32 index) const
{
return vertices[index];
return (&vertex1)[index];
}
inline u32 b3Capsule::GetSupportVertex(const b3Vec3& d) const
{
if (b3Dot(d, vertices[0]) > b3Dot(d, vertices[1]))
if (b3Dot(d, vertex1) > b3Dot(d, vertex2))
{
return 0;
}

View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CONE_HULL_H
#define B3_CONE_HULL_H
#include <bounce/collision/shapes/hull.h>
// A cone with 20 segments.
struct b3ConeHull : public b3Hull
{
b3Vec3 coneVertices[21];
b3HalfEdge coneEdges[80];
b3Face coneFaces[21];
b3Plane conePlanes[21];
// Does nothing for performance.
b3ConeHull()
{
}
// Construct this cone from radius and y extent centered at the origin.
// The cone will have radius and extent set to 1;
b3ConeHull(scalar radius, scalar ey)
{
SetExtents(radius, ey);
}
// Set this cone to the unit cylinder centered at the origin.
void SetIdentity()
{
coneVertices[0] = b3Vec3(-0.95105665922164916992, -1.00000000000000000000, -0.30901667475700378418);
coneVertices[1] = b3Vec3(-0.95105648040771484375, -1.00000000000000000000, 0.30901741981506347656);
coneVertices[2] = b3Vec3(0.30901747941970825195, -1.00000000000000000000, 0.95105648040771484375);
coneVertices[3] = b3Vec3(0.95105648040771484375, -1.00000000000000000000, -0.30901703238487243652);
coneVertices[4] = b3Vec3(-0.58778500556945800781, -1.00000000000000000000, 0.80901730060577392578);
coneVertices[5] = b3Vec3(-0.30901724100112915039, -1.00000000000000000000, -0.95105648040771484375);
coneVertices[6] = b3Vec3(0.30901682376861572266, -1.00000000000000000000, -0.95105654001235961914);
coneVertices[7] = b3Vec3(0.80901741981506347656, -1.00000000000000000000, 0.58778494596481323242);
coneVertices[8] = b3Vec3(-0.80901724100112915039, -1.00000000000000000000, -0.58778500556945800781);
coneVertices[9] = b3Vec3(0.95105683803558349609, -1.00000000000000000000, 0.30901655554771423340);
coneVertices[10] = b3Vec3(-0.30901664495468139648, -1.00000000000000000000, 0.95105671882629394531);
coneVertices[11] = b3Vec3(0.80901694297790527344, -1.00000000000000000000, -0.58778530359268188477);
coneVertices[12] = b3Vec3(0.58778578042984008789, -1.00000000000000000000, 0.80901682376861572266);
coneVertices[13] = b3Vec3(0.58778512477874755859, -1.00000000000000000000, -0.80901706218719482422);
coneVertices[14] = b3Vec3(-0.80901682376861572266, -1.00000000000000000000, 0.58778566122055053711);
coneVertices[15] = b3Vec3(-0.58778554201126098633, -1.00000000000000000000, -0.80901688337326049805);
coneVertices[16] = b3Vec3(0.00000044982880353928, -1.00000000000000000000, 1.00000011920928955078);
coneVertices[17] = b3Vec3(-0.00000022072345018387, -1.00000000000000000000, -1.00000000000000000000);
coneVertices[18] = b3Vec3(-1.00000011920928955078, -1.00000000000000000000, 0.00000039115548133850);
coneVertices[19] = b3Vec3(0.00000000000000000000, 1.00000000000000000000, 0.00000000000000000000);
coneVertices[20] = b3Vec3(1.00000000000000000000, -1.00000000000000000000, 0.00000000000000000000);
coneEdges[0] = b3MakeEdge(0, 1, 0, 4, 2);
coneEdges[1] = b3MakeEdge(19, 0, 1, 8, 6);
coneEdges[2] = b3MakeEdge(19, 3, 0, 0, 4);
coneEdges[3] = b3MakeEdge(8, 2, 17, 11, 71);
coneEdges[4] = b3MakeEdge(8, 5, 0, 2, 0);
coneEdges[5] = b3MakeEdge(0, 4, 2, 7, 10);
coneEdges[6] = b3MakeEdge(0, 7, 1, 1, 8);
coneEdges[7] = b3MakeEdge(18, 6, 2, 44, 5);
coneEdges[8] = b3MakeEdge(18, 9, 1, 6, 1);
coneEdges[9] = b3MakeEdge(19, 8, 3, 46, 45);
coneEdges[10] = b3MakeEdge(8, 11, 2, 5, 12);
coneEdges[11] = b3MakeEdge(15, 10, 17, 71, 3);
coneEdges[12] = b3MakeEdge(15, 13, 2, 10, 14);
coneEdges[13] = b3MakeEdge(5, 12, 12, 67, 70);
coneEdges[14] = b3MakeEdge(5, 15, 2, 12, 16);
coneEdges[15] = b3MakeEdge(17, 14, 11, 68, 66);
coneEdges[16] = b3MakeEdge(17, 17, 2, 14, 18);
coneEdges[17] = b3MakeEdge(6, 16, 14, 73, 69);
coneEdges[18] = b3MakeEdge(6, 19, 2, 16, 20);
coneEdges[19] = b3MakeEdge(13, 18, 13, 74, 72);
coneEdges[20] = b3MakeEdge(13, 21, 2, 18, 22);
coneEdges[21] = b3MakeEdge(11, 20, 20, 61, 75);
coneEdges[22] = b3MakeEdge(11, 23, 2, 20, 24);
coneEdges[23] = b3MakeEdge(3, 22, 8, 57, 60);
coneEdges[24] = b3MakeEdge(3, 25, 2, 22, 26);
coneEdges[25] = b3MakeEdge(20, 24, 7, 58, 56);
coneEdges[26] = b3MakeEdge(20, 27, 2, 24, 28);
coneEdges[27] = b3MakeEdge(9, 26, 18, 79, 59);
coneEdges[28] = b3MakeEdge(9, 29, 2, 26, 30);
coneEdges[29] = b3MakeEdge(7, 28, 16, 77, 78);
coneEdges[30] = b3MakeEdge(7, 31, 2, 28, 32);
coneEdges[31] = b3MakeEdge(12, 30, 15, 55, 76);
coneEdges[32] = b3MakeEdge(12, 33, 2, 30, 34);
coneEdges[33] = b3MakeEdge(2, 32, 6, 51, 54);
coneEdges[34] = b3MakeEdge(2, 35, 2, 32, 36);
coneEdges[35] = b3MakeEdge(16, 34, 5, 52, 50);
coneEdges[36] = b3MakeEdge(16, 37, 2, 34, 38);
coneEdges[37] = b3MakeEdge(10, 36, 19, 65, 53);
coneEdges[38] = b3MakeEdge(10, 39, 2, 36, 40);
coneEdges[39] = b3MakeEdge(4, 38, 10, 63, 64);
coneEdges[40] = b3MakeEdge(4, 41, 2, 38, 42);
coneEdges[41] = b3MakeEdge(14, 40, 9, 49, 62);
coneEdges[42] = b3MakeEdge(14, 43, 2, 40, 44);
coneEdges[43] = b3MakeEdge(1, 42, 4, 47, 48);
coneEdges[44] = b3MakeEdge(1, 45, 2, 42, 7);
coneEdges[45] = b3MakeEdge(18, 44, 3, 9, 46);
coneEdges[46] = b3MakeEdge(1, 47, 3, 45, 9);
coneEdges[47] = b3MakeEdge(19, 46, 4, 48, 43);
coneEdges[48] = b3MakeEdge(14, 49, 4, 43, 47);
coneEdges[49] = b3MakeEdge(19, 48, 9, 62, 41);
coneEdges[50] = b3MakeEdge(2, 51, 5, 35, 52);
coneEdges[51] = b3MakeEdge(19, 50, 6, 54, 33);
coneEdges[52] = b3MakeEdge(19, 53, 5, 50, 35);
coneEdges[53] = b3MakeEdge(16, 52, 19, 37, 65);
coneEdges[54] = b3MakeEdge(12, 55, 6, 33, 51);
coneEdges[55] = b3MakeEdge(19, 54, 15, 76, 31);
coneEdges[56] = b3MakeEdge(3, 57, 7, 25, 58);
coneEdges[57] = b3MakeEdge(19, 56, 8, 60, 23);
coneEdges[58] = b3MakeEdge(19, 59, 7, 56, 25);
coneEdges[59] = b3MakeEdge(20, 58, 18, 27, 79);
coneEdges[60] = b3MakeEdge(11, 61, 8, 23, 57);
coneEdges[61] = b3MakeEdge(19, 60, 20, 75, 21);
coneEdges[62] = b3MakeEdge(4, 63, 9, 41, 49);
coneEdges[63] = b3MakeEdge(19, 62, 10, 64, 39);
coneEdges[64] = b3MakeEdge(10, 65, 10, 39, 63);
coneEdges[65] = b3MakeEdge(19, 64, 19, 53, 37);
coneEdges[66] = b3MakeEdge(5, 67, 11, 15, 68);
coneEdges[67] = b3MakeEdge(19, 66, 12, 70, 13);
coneEdges[68] = b3MakeEdge(19, 69, 11, 66, 15);
coneEdges[69] = b3MakeEdge(17, 68, 14, 17, 73);
coneEdges[70] = b3MakeEdge(15, 71, 12, 13, 67);
coneEdges[71] = b3MakeEdge(19, 70, 17, 3, 11);
coneEdges[72] = b3MakeEdge(6, 73, 13, 19, 74);
coneEdges[73] = b3MakeEdge(19, 72, 14, 69, 17);
coneEdges[74] = b3MakeEdge(19, 75, 13, 72, 19);
coneEdges[75] = b3MakeEdge(13, 74, 20, 21, 61);
coneEdges[76] = b3MakeEdge(7, 77, 15, 31, 55);
coneEdges[77] = b3MakeEdge(19, 76, 16, 78, 29);
coneEdges[78] = b3MakeEdge(9, 79, 16, 29, 77);
coneEdges[79] = b3MakeEdge(19, 78, 18, 59, 27);
coneFaces[0].edge = 0;
coneFaces[1].edge = 6;
coneFaces[2].edge = 5;
coneFaces[3].edge = 46;
coneFaces[4].edge = 43;
coneFaces[5].edge = 50;
coneFaces[6].edge = 33;
coneFaces[7].edge = 56;
coneFaces[8].edge = 23;
coneFaces[9].edge = 62;
coneFaces[10].edge = 39;
coneFaces[11].edge = 66;
coneFaces[12].edge = 13;
coneFaces[13].edge = 72;
coneFaces[14].edge = 17;
coneFaces[15].edge = 76;
coneFaces[16].edge = 29;
coneFaces[17].edge = 3;
coneFaces[18].edge = 27;
coneFaces[19].edge = 37;
coneFaces[20].edge = 21;
conePlanes[0].normal = b3Vec3(-0.79889804124832153320, 0.44279259443283081055, -0.40705847740173339844);
conePlanes[0].offset = 0.44279259443283081055;
conePlanes[1].normal = b3Vec3(-0.88558518886566162109, 0.44279265403747558594, -0.14026281237602233887);
conePlanes[1].offset = 0.44279262423515319824;
conePlanes[2].normal = b3Vec3(0.00000000000000000000, -1.00000000000000000000, 0.00000000000000000000);
conePlanes[2].offset = 1.00000000000000000000;
conePlanes[3].normal = b3Vec3(-0.88558501005172729492, 0.44279259443283081055, 0.14026330411434173584);
conePlanes[3].offset = 0.44279262423515319824;
conePlanes[4].normal = b3Vec3(-0.79889774322509765625, 0.44279259443283081055, 0.40705913305282592773);
conePlanes[4].offset = 0.44279265403747558594;
conePlanes[5].normal = b3Vec3(0.14026331901550292969, 0.44279259443283081055, 0.88558501005172729492);
conePlanes[5].offset = 0.44279265403747558594;
conePlanes[6].normal = b3Vec3(0.40705907344818115234, 0.44279259443283081055, 0.79889774322509765625);
conePlanes[6].offset = 0.44279265403747558594;
conePlanes[7].normal = b3Vec3(0.88558512926101684570, 0.44279256463050842285, -0.14026297628879547119);
conePlanes[7].offset = 0.44279259443283081055;
conePlanes[8].normal = b3Vec3(0.79889786243438720703, 0.44279253482818603516, -0.40705886483192443848);
conePlanes[8].offset = 0.44279256463050842285;
conePlanes[9].normal = b3Vec3(-0.63400870561599731445, 0.44279262423515319824, 0.63400918245315551758);
conePlanes[9].offset = 0.44279256463050842285;
conePlanes[10].normal = b3Vec3(-0.40705844759941101074, 0.44279259443283081055, 0.79889804124832153320);
conePlanes[10].offset = 0.44279265403747558594;
conePlanes[11].normal = b3Vec3(-0.14026300609111785889, 0.44279259443283081055, -0.88558506965637207031);
conePlanes[11].offset = 0.44279253482818603516;
conePlanes[12].normal = b3Vec3(-0.40705892443656921387, 0.44279259443283081055, -0.79889780282974243164);
conePlanes[12].offset = 0.44279259443283081055;
conePlanes[13].normal = b3Vec3(0.40705865621566772461, 0.44279253482818603516, -0.79889798164367675781);
conePlanes[13].offset = 0.44279259443283081055;
conePlanes[14].normal = b3Vec3(0.14026281237602233887, 0.44279256463050842285, -0.88558518886566162109);
conePlanes[14].offset = 0.44279259443283081055;
conePlanes[15].normal = b3Vec3(0.63400930166244506836, 0.44279262423515319824, 0.63400864601135253906);
conePlanes[15].offset = 0.44279265403747558594;
conePlanes[16].normal = b3Vec3(0.79889810085296630859, 0.44279265403747558594, 0.40705841779708862305);
conePlanes[16].offset = 0.44279265403747558594;
conePlanes[17].normal = b3Vec3(-0.63400924205780029297, 0.44279265403747558594, -0.63400876522064208984);
conePlanes[17].offset = 0.44279265403747558594;
conePlanes[18].normal = b3Vec3(0.88558530807495117188, 0.44279265403747558594, 0.14026220142841339111);
conePlanes[18].offset = 0.44279268383979797363;
conePlanes[19].normal = b3Vec3(-0.14026261866092681885, 0.44279259443283081055, 0.88558512926101684570);
conePlanes[19].offset = 0.44279259443283081055;
conePlanes[20].normal = b3Vec3(0.63400888442993164063, 0.44279256463050842285, -0.63400906324386596680);
conePlanes[20].offset = 0.44279259443283081055;
centroid = b3Vec3(-0.00000003081002830641, -0.50000011920928955078, 0.00000003992893837790);
vertices = coneVertices;
vertexCount = 21;
edges = coneEdges;
edgeCount = 80;
faces = coneFaces;
planes = conePlanes;
faceCount = 21;
Validate();
}
// Construct this cylinder from radius and y extent centered at the origin.
void SetExtents(scalar radius, scalar ey)
{
SetIdentity();
b3Vec3 scale(radius, ey, radius);
Scale(scale);
}
};
extern const b3ConeHull b3ConeHull_identity;
#endif

View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_CYLINDER_HULL_H
#define B3_CYLINDER_HULL_H
#include <bounce/collision/shapes/hull.h>
// A cylinder with 20 segments.
struct b3CylinderHull : public b3Hull
{
b3Vec3 cylinderVertices[40];
b3HalfEdge cylinderEdges[120];
b3Face cylinderFaces[22];
b3Plane cylinderPlanes[22];
// Does nothing for performance.
b3CylinderHull()
{
}
// Construct this cylinder from radius and y extent centered at the origin.
b3CylinderHull(scalar radius, scalar ey)
{
SetExtents(radius, ey);
}
// Set this cylinder to the unit cylinder centered at the origin.
void SetIdentity()
{
cylinderVertices[0] = b3Vec3(0.80901741981506347656, 1, 0.58778494596481323242);
cylinderVertices[1] = b3Vec3(-0.80901724100112915039, -1, -0.58778500556945800781);
cylinderVertices[2] = b3Vec3(-0.30901724100112915039, 1, -0.95105648040771484375);
cylinderVertices[3] = b3Vec3(0.30901747941970825195, 1, 0.95105648040771484375);
cylinderVertices[4] = b3Vec3(0.95105648040771484375, 1, -0.30901703238487243652);
cylinderVertices[5] = b3Vec3(-0.95105648040771484375, -1, 0.30901741981506347656);
cylinderVertices[6] = b3Vec3(0.58778512477874755859, -1, -0.80901706218719482422);
cylinderVertices[7] = b3Vec3(0.95105683803558349609, -1, 0.30901655554771423340);
cylinderVertices[8] = b3Vec3(-0.58778500556945800781, 1, 0.80901730060577392578);
cylinderVertices[9] = b3Vec3(0.30901747941970825195, -1, 0.95105648040771484375);
cylinderVertices[10] = b3Vec3(-0.30901724100112915039, -1, -0.95105648040771484375);
cylinderVertices[11] = b3Vec3(-0.95105648040771484375, 1, 0.30901741981506347656);
cylinderVertices[12] = b3Vec3(0.95105648040771484375, -1, -0.30901703238487243652);
cylinderVertices[13] = b3Vec3(0.58778512477874755859, 1, -0.80901706218719482422);
cylinderVertices[14] = b3Vec3(-0.80901724100112915039, 1, -0.58778500556945800781);
cylinderVertices[15] = b3Vec3(-0.58778500556945800781, -1, 0.80901730060577392578);
cylinderVertices[16] = b3Vec3(-0.30901664495468139648, -1, 0.95105671882629394531);
cylinderVertices[17] = b3Vec3(0.95105683803558349609, 1, 0.30901655554771423340);
cylinderVertices[18] = b3Vec3(-0.95105665922164916992, 1, -0.30901667475700378418);
cylinderVertices[19] = b3Vec3(0.30901682376861572266, 1, -0.95105654001235961914);
cylinderVertices[20] = b3Vec3(-0.95105665922164916992, -1, -0.30901667475700378418);
cylinderVertices[21] = b3Vec3(0.30901682376861572266, -1, -0.95105654001235961914);
cylinderVertices[22] = b3Vec3(0.80901741981506347656, -1, 0.58778494596481323242);
cylinderVertices[23] = b3Vec3(-0.30901664495468139648, 1, 0.95105671882629394531);
cylinderVertices[24] = b3Vec3(-0.80901682376861572266, 1, 0.58778566122055053711);
cylinderVertices[25] = b3Vec3(0.80901694297790527344, -1, -0.58778530359268188477);
cylinderVertices[26] = b3Vec3(-0.58778554201126098633, -1, -0.80901688337326049805);
cylinderVertices[27] = b3Vec3(0.58778578042984008789, -1, 0.80901682376861572266);
cylinderVertices[28] = b3Vec3(0.58778578042984008789, 1, 0.80901682376861572266);
cylinderVertices[29] = b3Vec3(-0.80901682376861572266, -1, 0.58778566122055053711);
cylinderVertices[30] = b3Vec3(0.80901694297790527344, 1, -0.58778530359268188477);
cylinderVertices[31] = b3Vec3(-0.58778554201126098633, 1, -0.80901688337326049805);
cylinderVertices[32] = b3Vec3(1, 1, 0);
cylinderVertices[33] = b3Vec3(0.00000044982880353928, -1, 1.00000011920928955078);
cylinderVertices[34] = b3Vec3(-1.00000011920928955078, 1, 0.00000039115548133850);
cylinderVertices[35] = b3Vec3(-0.00000022072345018387, -1, -1);
cylinderVertices[36] = b3Vec3(0.00000044982880353928, 1, 1.00000011920928955078);
cylinderVertices[37] = b3Vec3(-0.00000022072345018387, 1, -1);
cylinderVertices[38] = b3Vec3(1, -1, 0);
cylinderVertices[39] = b3Vec3(-1.00000011920928955078, -1, 0.00000039115548133850);
cylinderEdges[0] = b3MakeEdge(0, 1, 0, 6, 2);
cylinderEdges[1] = b3MakeEdge(22, 0, 1, 12, 8);
cylinderEdges[2] = b3MakeEdge(22, 3, 0, 0, 4);
cylinderEdges[3] = b3MakeEdge(7, 2, 4, 72, 13);
cylinderEdges[4] = b3MakeEdge(7, 5, 0, 2, 6);
cylinderEdges[5] = b3MakeEdge(17, 4, 16, 15, 73);
cylinderEdges[6] = b3MakeEdge(17, 7, 0, 4, 0);
cylinderEdges[7] = b3MakeEdge(0, 6, 2, 9, 14);
cylinderEdges[8] = b3MakeEdge(0, 9, 1, 1, 10);
cylinderEdges[9] = b3MakeEdge(28, 8, 2, 48, 7);
cylinderEdges[10] = b3MakeEdge(28, 11, 1, 8, 12);
cylinderEdges[11] = b3MakeEdge(27, 10, 9, 75, 49);
cylinderEdges[12] = b3MakeEdge(27, 13, 1, 10, 1);
cylinderEdges[13] = b3MakeEdge(22, 12, 4, 3, 74);
cylinderEdges[14] = b3MakeEdge(17, 15, 2, 7, 16);
cylinderEdges[15] = b3MakeEdge(32, 14, 16, 101, 5);
cylinderEdges[16] = b3MakeEdge(32, 17, 2, 14, 18);
cylinderEdges[17] = b3MakeEdge(4, 16, 10, 102, 100);
cylinderEdges[18] = b3MakeEdge(4, 19, 2, 16, 20);
cylinderEdges[19] = b3MakeEdge(30, 18, 11, 104, 103);
cylinderEdges[20] = b3MakeEdge(30, 21, 2, 18, 22);
cylinderEdges[21] = b3MakeEdge(13, 20, 15, 115, 105);
cylinderEdges[22] = b3MakeEdge(13, 23, 2, 20, 24);
cylinderEdges[23] = b3MakeEdge(19, 22, 14, 112, 114);
cylinderEdges[24] = b3MakeEdge(19, 25, 2, 22, 26);
cylinderEdges[25] = b3MakeEdge(37, 24, 21, 93, 113);
cylinderEdges[26] = b3MakeEdge(37, 27, 2, 24, 28);
cylinderEdges[27] = b3MakeEdge(2, 26, 6, 94, 92);
cylinderEdges[28] = b3MakeEdge(2, 29, 2, 26, 30);
cylinderEdges[29] = b3MakeEdge(31, 28, 7, 91, 95);
cylinderEdges[30] = b3MakeEdge(31, 31, 2, 28, 32);
cylinderEdges[31] = b3MakeEdge(14, 30, 5, 55, 90);
cylinderEdges[32] = b3MakeEdge(14, 33, 2, 30, 34);
cylinderEdges[33] = b3MakeEdge(18, 32, 3, 52, 54);
cylinderEdges[34] = b3MakeEdge(18, 35, 2, 32, 36);
cylinderEdges[35] = b3MakeEdge(34, 34, 20, 111, 53);
cylinderEdges[36] = b3MakeEdge(34, 37, 2, 34, 38);
cylinderEdges[37] = b3MakeEdge(11, 36, 13, 109, 110);
cylinderEdges[38] = b3MakeEdge(11, 39, 2, 36, 40);
cylinderEdges[39] = b3MakeEdge(24, 38, 12, 106, 108);
cylinderEdges[40] = b3MakeEdge(24, 41, 2, 38, 42);
cylinderEdges[41] = b3MakeEdge(8, 40, 17, 116, 107);
cylinderEdges[42] = b3MakeEdge(8, 43, 2, 40, 44);
cylinderEdges[43] = b3MakeEdge(23, 42, 18, 118, 117);
cylinderEdges[44] = b3MakeEdge(23, 45, 2, 42, 46);
cylinderEdges[45] = b3MakeEdge(36, 44, 19, 97, 119);
cylinderEdges[46] = b3MakeEdge(36, 47, 2, 44, 48);
cylinderEdges[47] = b3MakeEdge(3, 46, 8, 98, 96);
cylinderEdges[48] = b3MakeEdge(3, 49, 2, 46, 9);
cylinderEdges[49] = b3MakeEdge(28, 48, 9, 11, 99);
cylinderEdges[50] = b3MakeEdge(1, 51, 3, 54, 52);
cylinderEdges[51] = b3MakeEdge(20, 50, 4, 88, 56);
cylinderEdges[52] = b3MakeEdge(20, 53, 3, 50, 33);
cylinderEdges[53] = b3MakeEdge(18, 52, 20, 35, 89);
cylinderEdges[54] = b3MakeEdge(14, 55, 3, 33, 50);
cylinderEdges[55] = b3MakeEdge(1, 54, 5, 57, 31);
cylinderEdges[56] = b3MakeEdge(1, 57, 4, 51, 58);
cylinderEdges[57] = b3MakeEdge(26, 56, 5, 90, 55);
cylinderEdges[58] = b3MakeEdge(26, 59, 4, 56, 60);
cylinderEdges[59] = b3MakeEdge(10, 58, 7, 95, 91);
cylinderEdges[60] = b3MakeEdge(10, 61, 4, 58, 62);
cylinderEdges[61] = b3MakeEdge(35, 60, 6, 92, 94);
cylinderEdges[62] = b3MakeEdge(35, 63, 4, 60, 64);
cylinderEdges[63] = b3MakeEdge(21, 62, 21, 113, 93);
cylinderEdges[64] = b3MakeEdge(21, 65, 4, 62, 66);
cylinderEdges[65] = b3MakeEdge(6, 64, 14, 114, 112);
cylinderEdges[66] = b3MakeEdge(6, 67, 4, 64, 68);
cylinderEdges[67] = b3MakeEdge(25, 66, 15, 105, 115);
cylinderEdges[68] = b3MakeEdge(25, 69, 4, 66, 70);
cylinderEdges[69] = b3MakeEdge(12, 68, 11, 103, 104);
cylinderEdges[70] = b3MakeEdge(12, 71, 4, 68, 72);
cylinderEdges[71] = b3MakeEdge(38, 70, 10, 100, 102);
cylinderEdges[72] = b3MakeEdge(38, 73, 4, 70, 3);
cylinderEdges[73] = b3MakeEdge(7, 72, 16, 5, 101);
cylinderEdges[74] = b3MakeEdge(27, 75, 4, 13, 76);
cylinderEdges[75] = b3MakeEdge(9, 74, 9, 99, 11);
cylinderEdges[76] = b3MakeEdge(9, 77, 4, 74, 78);
cylinderEdges[77] = b3MakeEdge(33, 76, 8, 96, 98);
cylinderEdges[78] = b3MakeEdge(33, 79, 4, 76, 80);
cylinderEdges[79] = b3MakeEdge(16, 78, 19, 119, 97);
cylinderEdges[80] = b3MakeEdge(16, 81, 4, 78, 82);
cylinderEdges[81] = b3MakeEdge(15, 80, 18, 117, 118);
cylinderEdges[82] = b3MakeEdge(15, 83, 4, 80, 84);
cylinderEdges[83] = b3MakeEdge(29, 82, 17, 107, 116);
cylinderEdges[84] = b3MakeEdge(29, 85, 4, 82, 86);
cylinderEdges[85] = b3MakeEdge(5, 84, 12, 108, 106);
cylinderEdges[86] = b3MakeEdge(5, 87, 4, 84, 88);
cylinderEdges[87] = b3MakeEdge(39, 86, 13, 110, 109);
cylinderEdges[88] = b3MakeEdge(39, 89, 4, 86, 51);
cylinderEdges[89] = b3MakeEdge(20, 88, 20, 53, 111);
cylinderEdges[90] = b3MakeEdge(31, 91, 5, 31, 57);
cylinderEdges[91] = b3MakeEdge(26, 90, 7, 59, 29);
cylinderEdges[92] = b3MakeEdge(37, 93, 6, 27, 61);
cylinderEdges[93] = b3MakeEdge(35, 92, 21, 63, 25);
cylinderEdges[94] = b3MakeEdge(10, 95, 6, 61, 27);
cylinderEdges[95] = b3MakeEdge(2, 94, 7, 29, 59);
cylinderEdges[96] = b3MakeEdge(36, 97, 8, 47, 77);
cylinderEdges[97] = b3MakeEdge(33, 96, 19, 79, 45);
cylinderEdges[98] = b3MakeEdge(9, 99, 8, 77, 47);
cylinderEdges[99] = b3MakeEdge(3, 98, 9, 49, 75);
cylinderEdges[100] = b3MakeEdge(32, 101, 10, 17, 71);
cylinderEdges[101] = b3MakeEdge(38, 100, 16, 73, 15);
cylinderEdges[102] = b3MakeEdge(12, 103, 10, 71, 17);
cylinderEdges[103] = b3MakeEdge(4, 102, 11, 19, 69);
cylinderEdges[104] = b3MakeEdge(25, 105, 11, 69, 19);
cylinderEdges[105] = b3MakeEdge(30, 104, 15, 21, 67);
cylinderEdges[106] = b3MakeEdge(29, 107, 12, 85, 39);
cylinderEdges[107] = b3MakeEdge(24, 106, 17, 41, 83);
cylinderEdges[108] = b3MakeEdge(11, 109, 12, 39, 85);
cylinderEdges[109] = b3MakeEdge(5, 108, 13, 87, 37);
cylinderEdges[110] = b3MakeEdge(34, 111, 13, 37, 87);
cylinderEdges[111] = b3MakeEdge(39, 110, 20, 89, 35);
cylinderEdges[112] = b3MakeEdge(21, 113, 14, 65, 23);
cylinderEdges[113] = b3MakeEdge(19, 112, 21, 25, 63);
cylinderEdges[114] = b3MakeEdge(13, 115, 14, 23, 65);
cylinderEdges[115] = b3MakeEdge(6, 114, 15, 67, 21);
cylinderEdges[116] = b3MakeEdge(15, 117, 17, 83, 41);
cylinderEdges[117] = b3MakeEdge(8, 116, 18, 43, 81);
cylinderEdges[118] = b3MakeEdge(16, 119, 18, 81, 43);
cylinderEdges[119] = b3MakeEdge(23, 118, 19, 45, 79);
cylinderFaces[0].edge = 0;
cylinderFaces[1].edge = 8;
cylinderFaces[2].edge = 7;
cylinderFaces[3].edge = 50;
cylinderFaces[4].edge = 56;
cylinderFaces[5].edge = 55;
cylinderFaces[6].edge = 27;
cylinderFaces[7].edge = 95;
cylinderFaces[8].edge = 47;
cylinderFaces[9].edge = 99;
cylinderFaces[10].edge = 17;
cylinderFaces[11].edge = 103;
cylinderFaces[12].edge = 85;
cylinderFaces[13].edge = 109;
cylinderFaces[14].edge = 65;
cylinderFaces[15].edge = 115;
cylinderFaces[16].edge = 73;
cylinderFaces[17].edge = 41;
cylinderFaces[18].edge = 117;
cylinderFaces[19].edge = 79;
cylinderFaces[20].edge = 53;
cylinderFaces[21].edge = 113;
cylinderPlanes[0].normal = b3Vec3(0.89100682735443115234, 0, 0.45399010181427001953);
cylinderPlanes[0].offset = 0.98768866062164306641;
cylinderPlanes[1].normal = b3Vec3(0.70710718631744384766, 0, 0.70710641145706176758);
cylinderPlanes[1].offset = 0.98768854141235351563;
cylinderPlanes[2].normal = b3Vec3(0, 1, 0);
cylinderPlanes[2].offset = 1;
cylinderPlanes[3].normal = b3Vec3(-0.89100670814514160156, 0, -0.45399013161659240723);
cylinderPlanes[3].offset = 0.98768842220306396484;
cylinderPlanes[4].normal = b3Vec3(0, -1, 0);
cylinderPlanes[4].offset = 1;
cylinderPlanes[5].normal = b3Vec3(-0.70710712671279907227, 0, -0.70710653066635131836);
cylinderPlanes[5].offset = 0.98768848180770874023;
cylinderPlanes[6].normal = b3Vec3(-0.15643458068370819092, 0, -0.98768836259841918945);
cylinderPlanes[6].offset = 0.98768842220306396484;
cylinderPlanes[7].normal = b3Vec3(-0.45399063825607299805, 0, -0.89100646972656250000);
cylinderPlanes[7].offset = 0.98768842220306396484;
cylinderPlanes[8].normal = b3Vec3(0.15643493831157684326, 0, 0.98768830299377441406);
cylinderPlanes[8].offset = 0.98768848180770874023;
cylinderPlanes[9].normal = b3Vec3(0.45399075746536254883, 0, 0.89100635051727294922);
cylinderPlanes[9].offset = 0.98768836259841918945;
cylinderPlanes[10].normal = b3Vec3(0.98768830299377441406, 0, -0.15643455088138580322);
cylinderPlanes[10].offset = 0.98768830299377441406;
cylinderPlanes[11].normal = b3Vec3(0.89100646972656250000, 0, -0.45399051904678344727);
cylinderPlanes[11].offset = 0.98768830299377441406;
cylinderPlanes[12].normal = b3Vec3(-0.89100635051727294922, 0, 0.45399084687232971191);
cylinderPlanes[12].offset = 0.98768842220306396484;
cylinderPlanes[13].normal = b3Vec3(-0.98768830299377441406, 0, 0.15643493831157684326);
cylinderPlanes[13].offset = 0.98768842220306396484;
cylinderPlanes[14].normal = b3Vec3(0.45399031043052673340, 0, -0.89100658893585205078);
cylinderPlanes[14].offset = 0.98768830299377441406;
cylinderPlanes[15].normal = b3Vec3(0.70710670948028564453, 0, -0.70710688829421997070);
cylinderPlanes[15].offset = 0.98768830299377441406;
cylinderPlanes[16].normal = b3Vec3(0.98768848180770874023, 0, 0.15643368661403656006);
cylinderPlanes[16].offset = 0.98768854141235351563;
cylinderPlanes[17].normal = b3Vec3(-0.70710653066635131836, 0, 0.70710712671279907227);
cylinderPlanes[17].offset = 0.98768854141235351563;
cylinderPlanes[18].normal = b3Vec3(-0.45399010181427001953, 0, 0.89100670814514160156);
cylinderPlanes[18].offset = 0.98768842220306396484;
cylinderPlanes[19].normal = b3Vec3(-0.15643416345119476318, 0, 0.98768842220306396484);
cylinderPlanes[19].offset = 0.98768848180770874023;
cylinderPlanes[20].normal = b3Vec3(-0.98768842220306396484, 0, -0.15643437206745147705);
cylinderPlanes[20].offset = 0.98768848180770874023;
cylinderPlanes[21].normal = b3Vec3(0.15643437206745147705, 0, -0.98768842220306396484);
cylinderPlanes[21].offset = 0.98768836259841918945;
centroid = b3Vec3(0, 0, 0);
vertices = cylinderVertices;
vertexCount = 40;
edges = cylinderEdges;
edgeCount = 120;
faces = cylinderFaces;
planes = cylinderPlanes;
faceCount = 22;
Validate();
}
// Construct this cylinder from radius and y extent centered at the origin.
void SetExtents(scalar radius, scalar ey)
{
SetIdentity();
b3Vec3 scale(radius, ey, radius);
Scale(scale);
}
};
extern const b3CylinderHull b3CylinderHull_identity;
#endif

View File

@ -26,28 +26,30 @@
template<u32 H = 1, u32 W = 1>
struct b3GridMesh : public b3Mesh
{
b3Vec3 gridVertices[ (H + 1) * (W + 1) ];
b3Triangle gridTriangles[2 * H * W];
b3Vec3 gridVertices[(H + 1) * (W + 1)];
b3MeshTriangle gridTriangles[2 * H * W];
// Set this grid to a W (width) per H (height) dimensioned grid centered at the origin and aligned
// with the world x-z axes.
b3GridMesh()
{
vertexCount = 0;
for (u32 i = 0; i <= H; ++i)
for (u32 j = 0; j <= W; ++j)
{
for (u32 j = 0; j <= W; ++j)
for (u32 i = 0; i <= H; ++i)
{
gridVertices[vertexCount++].Set(float32(j), 0.0f, float32(i));
u32 vertex = GetVertex(i, j);
gridVertices[vertex].Set(scalar(j), 0, scalar(i));
++vertexCount;
}
}
B3_ASSERT(vertexCount == (H + 1) * (W + 1));
b3Vec3 translation;
translation.x = -0.5f * float32(W);
translation.y = 0.0f;
translation.z = -0.5f * float32(H);
translation.x = scalar(-0.5) * scalar(W);
translation.y = 0;
translation.z = scalar(-0.5) * scalar(H);
for (u32 i = 0; i < vertexCount; ++i)
{
@ -59,20 +61,23 @@ struct b3GridMesh : public b3Mesh
{
for (u32 j = 0; j < W; ++j)
{
u32 v1 = i * (W + 1) + j;
u32 v2 = (i + 1) * (W + 1) + j;
u32 v3 = (i + 1) * (W + 1) + (j + 1);
u32 v4 = i * (W + 1) + (j + 1);
// 1*|----|*4
// |----|
// 2*|----|*3
u32 v1 = GetVertex(i, j);
u32 v2 = GetVertex(i + 1, j);
u32 v3 = GetVertex(i + 1, j + 1);
u32 v4 = GetVertex(i, j + 1);
b3Triangle* t1 = gridTriangles + triangleCount++;
t1->v1 = v3;
b3MeshTriangle* t1 = gridTriangles + triangleCount++;
t1->v1 = v1;
t1->v2 = v2;
t1->v3 = v1;
t1->v3 = v3;
b3Triangle* t2 = gridTriangles + triangleCount++;
t2->v1 = v1;
b3MeshTriangle* t2 = gridTriangles + triangleCount++;
t2->v1 = v3;
t2->v2 = v4;
t2->v3 = v3;
t2->v3 = v1;
}
}
@ -81,6 +86,13 @@ struct b3GridMesh : public b3Mesh
vertices = gridVertices;
triangles = gridTriangles;
}
u32 GetVertex(u32 i, u32 j)
{
B3_ASSERT(i < H + 1);
B3_ASSERT(j < W + 1);
return i * (W + 1) + j;
}
};
#endif

View File

@ -31,6 +31,7 @@ struct b3HalfEdge
u32 origin;
u32 twin;
u32 face;
u32 prev;
u32 next;
};
@ -61,6 +62,15 @@ struct b3Hull
void Validate() const;
void Validate(const b3Face* face) const;
void Validate(const b3HalfEdge* edge) const;
void Dump() const;
void Scale(const b3Vec3& scale);
void Rotate(const b3Quat& rotation);
void Translate(const b3Vec3& translation);
// Scale -> Rotate -> Translate
void Transform(const b3Transform& xf, const b3Vec3& scale);
};
#include <bounce/collision/shapes/hull.inl>

View File

@ -1,9 +1,10 @@
inline b3HalfEdge b3MakeEdge(u32 origin, u32 twin, u32 face, u32 next)
inline b3HalfEdge b3MakeEdge(u32 origin, u32 twin, u32 face, u32 prev, u32 next)
{
b3HalfEdge edge;
edge.origin = origin;
edge.twin = twin;
edge.face = face;
edge.prev = prev;
edge.next = next;
return edge;
}
@ -31,10 +32,10 @@ inline const b3Plane& b3Hull::GetPlane(u32 index) const
inline u32 b3Hull::GetSupportVertex(const b3Vec3& direction) const
{
u32 maxIndex = 0;
float32 maxProjection = b3Dot(direction, vertices[maxIndex]);
scalar maxProjection = b3Dot(direction, vertices[maxIndex]);
for (u32 i = 1; i < vertexCount; ++i)
{
float32 projection = b3Dot(direction, vertices[i]);
scalar projection = b3Dot(direction, vertices[i]);
if (projection > maxProjection)
{
maxIndex = i;
@ -47,10 +48,10 @@ inline u32 b3Hull::GetSupportVertex(const b3Vec3& direction) const
inline u32 b3Hull::GetSupportFace(const b3Vec3& direction) const
{
u32 maxIndex = 0;
float32 maxProjection = b3Dot(direction, planes[maxIndex].normal);
scalar maxProjection = b3Dot(direction, planes[maxIndex].normal);
for (u32 i = 1; i < faceCount; ++i)
{
float32 projection = b3Dot(direction, planes[i].normal);
scalar projection = b3Dot(direction, planes[i].normal);
if (projection > maxProjection)
{
maxIndex = i;

View File

@ -19,40 +19,72 @@
#ifndef B3_MESH_H
#define B3_MESH_H
#include <bounce/common/geometry.h>
#include <bounce/collision/trees/static_tree.h>
struct b3Triangle
#define B3_NULL_VERTEX B3_MAX_U32
// Mesh triangle.
struct b3MeshTriangle
{
// Test if this triangle contains a given vertex.
bool TestVertex(u32 v) const
{
return v == v1 || v == v2 || v == v3;
}
// Write an indexed vertex to this triangle.
u32& GetVertex(u32 i) { return (&v1)[i]; }
// Test if this triangle contains two vertices.
bool TestEdge(u32 _v1, u32 _v2) const
{
return TestVertex(_v1) && TestVertex(_v2);
}
// Read an indexed vertex from this triangle.
u32 GetVertex(u32 i) const { return (&v1)[i]; }
// The triangle vertices in the mesh.
u32 v1, v2, v3;
};
// Mesh triangle adjacency.
// This is used for smooth edge collision.
struct b3MeshTriangleWings
{
// Write an indexed edge wing vertex to this triangle.
u32& GetVertex(u32 i) { return (&u1)[i]; }
// Read an indexed edge wing vertex from this triangle.
u32 GetVertex(u32 i) const { return (&u1)[i]; }
// The wing vertex of each edge in this triangle.
// An edge is a boundary if its wing vertex is set to B3_NULL_VERTEX.
u32 u1, u2, u3;
};
struct b3Mesh
{
u32 vertexCount;
b3Vec3* vertices;
u32 triangleCount;
b3Triangle* triangles;
b3MeshTriangle* triangles;
b3MeshTriangleWings* triangleWings;
b3StaticTree tree;
b3Mesh();
~b3Mesh();
// Build the static AABB tree.
void BuildTree();
// Build mesh adjacency.
// This won't work properly if there are non-manifold edges.
void BuildAdjacency();
const b3Vec3& GetVertex(u32 index) const;
const b3Triangle& GetTriangle(u32 index) const;
const b3MeshTriangle* GetTriangle(u32 index) const;
const b3MeshTriangleWings* GetTriangleWings(u32 index) const;
b3AABB GetTriangleAABB(u32 index) const;
u32 GetSize() const;
b3AABB3 GetTriangleAABB(u32 index) const;
void Scale(const b3Vec3& scale);
void Rotate(const b3Quat& rotation);
void Translate(const b3Vec3& translation);
void BuildTree();
// Scale -> Rotate -> Translate
void Transform(const b3Transform& xf, const b3Vec3& scale);
};
inline const b3Vec3& b3Mesh::GetVertex(u32 index) const
@ -60,9 +92,24 @@ inline const b3Vec3& b3Mesh::GetVertex(u32 index) const
return vertices[index];
}
inline const b3Triangle& b3Mesh::GetTriangle(u32 index) const
inline const b3MeshTriangle* b3Mesh::GetTriangle(u32 index) const
{
return triangles[index];
return triangles + index;
}
inline const b3MeshTriangleWings* b3Mesh::GetTriangleWings(u32 index) const
{
return triangleWings + index;
}
inline b3AABB b3Mesh::GetTriangleAABB(u32 index) const
{
const b3MeshTriangle* triangle = triangles + index;
b3AABB aabb;
aabb.SetTriangle(vertices[triangle->v1], vertices[triangle->v2], vertices[triangle->v3]);
return aabb;
}
inline u32 b3Mesh::GetSize() const
@ -70,32 +117,10 @@ inline u32 b3Mesh::GetSize() const
u32 size = 0;
size += sizeof(b3Mesh);
size += sizeof(b3Vec3) * vertexCount;
size += sizeof(b3Triangle) * triangleCount;
size += sizeof(b3MeshTriangle) * triangleCount;
size += sizeof(b3MeshTriangleWings) * triangleCount;
size += tree.GetSize();
return size;
}
inline b3AABB3 b3Mesh::GetTriangleAABB(u32 index) const
{
const b3Triangle* triangle = triangles + index;
b3AABB3 aabb;
aabb.Set(vertices[triangle->v1], vertices[triangle->v2], vertices[triangle->v3]);
return aabb;
}
inline void b3Mesh::BuildTree()
{
b3AABB3* aabbs = (b3AABB3*)b3Alloc(triangleCount * sizeof(b3AABB3));
for (u32 i = 0; i < triangleCount; ++i)
{
aabbs[i] = GetTriangleAABB(i);
}
tree.Build(aabbs, triangleCount);
b3Free(aabbs);
}
#endif
#endif

View File

@ -52,15 +52,15 @@ struct b3QHull : public b3Hull
// Set this hull as a sphere located at the origin
// given the radius.
void SetAsSphere(float32 radius = 1.0f);
void SetAsSphere(scalar radius = 1, u32 subdivisions = 0);
// Set this hull as a cylinder located at the origin
// given the radius and extent along the y axis.
void SetAsCylinder(float32 radius = 1.0f, float32 ey = 1.0f);
// given the radius, extent along the y axis, and number of segments.
void SetAsCylinder(scalar radius = 1, scalar ey = 1, u32 segments = 20);
// Set this hull as a cone located at the origin
// given the radius and extent along the y axis.
void SetAsCone(float32 radius = 1.0f, float32 ey = 1.0f);
// given the radius, extent along the y axis, and number of segments.
void SetAsCone(scalar radius = 1, scalar ey = 1, u32 segments = 20);
};
#endif

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_SDF_H
#define B3_SDF_H
#include <bounce/collision/shapes/aabb.h>
struct b3MultiIndex
{
unsigned int& operator[](unsigned int i)
{
return v[i];
}
const unsigned int& operator[](unsigned int i) const
{
return v[i];
}
unsigned int v[3];
};
struct b3Cell32
{
unsigned int v[32];
};
// This class stores a discretized signed distance function (SDF)
// generated by Discregrid.
// Discregrid is available at https://github.com/InteractiveComputerGraphics/Discregrid
// Inside Discregrid, there is a tool called GenerateSDF that can
// generate an SDF of a triangle mesh stored in .obj file format.
// You may call this tool from a command line.
// For example, the following command will generate an SDF for a given .obj mesh.
// GenerateSDF -r "32 32 32" -d "-5 -5 -5 5 5 5" teapot.obj
// The parameters are:
// 1. r - resolution
// 2. d - domain (an AABB)
// 3. input filename
// You will need to set a reasonable large domain depending on the radius of
// the vertices that can collide against the SDF because the SDF
// can only return valid output values for points that are inside the domain.
// Therefore, its a good idea to set the domain to the AABB containing the
// associated object extended by twice the largest vertex radius that can collide against this SDF.
// Generally, the greater the SDF resolution the more accurate is the result of the signed distance function.
class b3SDF
{
public:
// Construct this SDF
b3SDF();
// Destruct this SDF
~b3SDF();
// Read this SDF from a .cdf (binary) file given the filename.
// Returns true if this SDF was loaded sucessfuly and false otherwise.
bool Load(const char* filename);
// Return the domain (AABB) of this SDF.
const b3AABB& GetDomain() const
{
return m_domain;
}
// Evaluate the signed distance function for a point if the point is inside the domain of this SDF.
// Optionally output the normal at the SDF boundary.
// Return true if the output values are valid and false otherwise.
bool Evaluate(const b3Vec3& point, double& distance, b3Vec3* normal = nullptr) const
{
return interpolate(0, distance, point, normal);
}
private:
bool interpolate(unsigned int field_id, double& dist, b3Vec3 const& x, b3Vec3* gradient = nullptr) const;
b3MultiIndex singleToMultiIndex(unsigned int i) const;
unsigned int multiToSingleIndex(b3MultiIndex const& ijk) const;
b3AABB subdomain(b3MultiIndex const& ijk) const;
b3AABB subdomain(unsigned int l) const;
b3AABB m_domain;
unsigned int m_resolution[3];
b3Vec3 m_cell_size;
b3Vec3 m_inv_cell_size;
std::size_t m_n_cells;
std::size_t m_n_fields;
struct b3SDFNodeArray
{
double& operator[](u32 i)
{
B3_ASSERT(i < count);
return values[i];
}
const double& operator[](u32 i) const
{
B3_ASSERT(i < count);
return values[i];
}
u32 count;
double* values;
};
struct b3SDFCellArray
{
b3Cell32& operator[](u32 i)
{
B3_ASSERT(i < count);
return values[i];
}
const b3Cell32& operator[](u32 i) const
{
B3_ASSERT(i < count);
return values[i];
}
u32 count;
b3Cell32* values;
};
struct b3SDFCellMapArray
{
unsigned int& operator[](u32 i)
{
B3_ASSERT(i < count);
return values[i];
}
const unsigned int& operator[](u32 i) const
{
B3_ASSERT(i < count);
return values[i];
}
u32 count;
unsigned int* values;
};
u32 m_nodeCount;
b3SDFNodeArray* m_nodes;
u32 m_cellCount;
b3SDFCellArray* m_cells;
u32 m_cellMapCount;
b3SDFCellMapArray* m_cell_map;
};
#endif

View File

@ -27,7 +27,7 @@ struct b3Sphere
b3Sphere() { }
//
b3Sphere(const b3Vec3& v, float32 r)
b3Sphere(const b3Vec3& v, scalar r)
{
vertex = v;
radius = r;
@ -37,7 +37,7 @@ struct b3Sphere
~b3Sphere() { }
b3Vec3 vertex;
float32 radius;
scalar radius;
const b3Vec3& GetVertex(u32 index) const;
u32 GetSupportVertex(const b3Vec3& direction) const;

View File

@ -37,20 +37,20 @@ struct b3TriangleHull : public b3Hull
void Set(const b3Vec3& A, const b3Vec3& B, const b3Vec3& C)
{
centroid = (A + B + C) / 3.0f;
centroid = (A + B + C) / scalar(3);
triangleVertices[0] = A;
triangleVertices[1] = B;
triangleVertices[2] = C;
// Each edge must be followed by its twin.
triangleEdges[0] = b3MakeEdge(0, 1, 0, 2); // Face 0 - Edge 0
triangleEdges[2] = b3MakeEdge(1, 3, 0, 4); // Face 0 - Edge 1
triangleEdges[4] = b3MakeEdge(2, 5, 0, 0); // Face 0 - Edge 2
triangleEdges[0] = b3MakeEdge(0, 1, 0, 4, 2); // Face 0 - Edge 0
triangleEdges[2] = b3MakeEdge(1, 3, 0, 0, 4); // Face 0 - Edge 1
triangleEdges[4] = b3MakeEdge(2, 5, 0, 2, 0); // Face 0 - Edge 2
triangleEdges[1] = b3MakeEdge(1, 0, 1, 3); // Face 1 - Edge 0
triangleEdges[3] = b3MakeEdge(2, 2, 1, 5); // Face 1 - Edge 1
triangleEdges[5] = b3MakeEdge(0, 4, 1, 1); // Face 1 - Edge 2
triangleEdges[1] = b3MakeEdge(1, 0, 1, 3, 5); // Face 1 - Edge 0
triangleEdges[3] = b3MakeEdge(2, 2, 1, 5, 1); // Face 1 - Edge 1
triangleEdges[5] = b3MakeEdge(0, 4, 1, 1, 3); // Face 1 - Edge 2
triangleFaces[0].edge = 0;
triangleFaces[1].edge = 1;

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_TIME_OF_IMPACT_H
#define B3_TIME_OF_IMPACT_H
#include <bounce/collision/gjk/gjk_proxy.h>
#include <bounce/collision/shapes/aabb.h>
#include <bounce/common/math/transform.h>
// Input parameters for b3TimeOfImpact
struct b3TOIInput
{
b3GJKProxy proxyA;
b3GJKProxy proxyB;
b3Sweep sweepA;
b3Sweep sweepB;
scalar tMax; // sweep interval in [0, 1]
};
// Output parameters of b3TimeOfImpact
struct b3TOIOutput
{
enum State
{
e_unknown,
e_failed,
e_overlapped,
e_touching,
e_separated
};
State state;
scalar t;
u32 iterations;
};
// Compute the time of impact between two shapes.
// This is represented as a fraction between [0, tMax].
// Use b3GJK to compute the contact point and normal at the time of impact.
b3TOIOutput b3TimeOfImpact(const b3TOIInput& input);
// Compute the time of impact between two shapes.
// This is represented as a fraction between [0, 1].
// You must supply the linear displacements of each shape.
// Use b3GJK to compute the contact point and normal at the time of impact.
b3TOIOutput b3TimeOfImpact(const b3Transform& xf1, const b3GJKProxy& proxy1, const b3Vec3& d1,
const b3Transform& xf2, const b3GJKProxy& proxy2, const b3Vec3& d2,
u32 maxIterations = 20);
// Compute the time of impact between two AABBs.
// This is represented as a fraction between [0, 1].
// You must supply the linear displacements of each AABB center.
b3TOIOutput b3TimeOfImpact(const b3AABB& aabb1, const b3Vec3& d1, const b3AABB& aabb2, const b3Vec3& d2);
#endif

View File

@ -20,29 +20,29 @@
#define B3_DYNAMIC_TREE_H
#include <bounce/common/template/stack.h>
#include <bounce/collision/shapes/aabb3.h>
#include <bounce/collision/shapes/aabb.h>
#include <bounce/collision/collision.h>
#define B3_NULL_NODE_D (0xFFFFFFFF)
// AABB tree for dynamic AABBs.
class b3DynamicTree
class b3DynamicTree
{
public :
public:
b3DynamicTree();
~b3DynamicTree();
// Insert a node into the tree and return its ID.
u32 InsertNode(const b3AABB3& aabb, void* userData);
u32 InsertNode(const b3AABB& aabb, void* userData);
// Remove a node from the tree.
void RemoveNode(u32 proxyId);
// Update a node AABB.
void UpdateNode(u32 proxyId, const b3AABB3& aabb);
void UpdateNode(u32 proxyId, const b3AABB& aabb);
// Get the (fat) AABB of a given proxy.
const b3AABB3& GetAABB(u32 proxyId) const;
const b3AABB& GetAABB(u32 proxyId) const;
// Get the data associated with a given proxy.
void* GetUserData(u32 proxyId) const;
@ -53,8 +53,8 @@ public :
// Keep reporting the client callback the AABBs that are overlapping with
// the given AABB. The client callback must return true if the query
// must be stopped or false to continue looking for more overlapping pairs.
template<class T>
void QueryAABB(T* callback, const b3AABB3& aabb) const;
template<class T>
void QueryAABB(T* callback, const b3AABB& aabb) const;
// Keep reporting the client callback all AABBs that are overlapping with
// the given ray. The client callback must return the new intersection fraction.
@ -67,23 +67,23 @@ public :
// Draw this tree.
void Draw() const;
private :
struct b3Node
private:
struct b3Node
{
// Is this node a leaf?
bool IsLeaf() const
bool IsLeaf() const
{
//A node is a leaf if child 2 == B3_NULL_NODE_D or height == 0.
return child1 == B3_NULL_NODE_D;
}
// The fattened node AABB.
b3AABB3 aabb;
b3AABB aabb;
// The associated user data.
void* userData;
union
union
{
u32 parent;
u32 next;
@ -96,18 +96,18 @@ private :
// leaf if 0, free node if -1
i32 height;
};
// Insert a node into the tree.
void InsertLeaf(u32 node);
// Remove a node from the tree.
void RemoveLeaf(u32 node);
// Rebuild the hierarchy starting from the given node.
void WalkBackNodeAndCombineVolumes(u32 node);
// Find the best node that can be merged with a given AABB.
u32 FindBest(const b3AABB3& aabb) const;
void Refit(u32 node);
// Pick the best node that can be merged with a given AABB.
u32 PickBest(const b3AABB& aabb) const;
// Peel a node from the free list and insert into the node array.
// Allocate a new node if necessary. The function returns the new node index.
@ -129,7 +129,7 @@ private :
u32 m_freeList;
};
inline const b3AABB3& b3DynamicTree::GetAABB(u32 proxyId) const
inline const b3AABB& b3DynamicTree::GetAABB(u32 proxyId) const
{
B3_ASSERT(proxyId != B3_NULL_NODE_D && proxyId < m_nodeCapacity);
return m_nodes[proxyId].aabb;
@ -149,12 +149,12 @@ inline bool b3DynamicTree::TestOverlap(u32 proxy1, u32 proxy2) const
}
template<class T>
inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB3& aabb) const
inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB& aabb) const
{
b3Stack<u32, 256> stack;
stack.Push(m_root);
while (stack.IsEmpty() == false)
while (stack.IsEmpty() == false)
{
u32 nodeIndex = stack.Top();
stack.Pop();
@ -166,16 +166,16 @@ inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB3& aabb) const
const b3Node* node = m_nodes + nodeIndex;
if (b3TestOverlap(node->aabb, aabb) == true)
if (b3TestOverlap(node->aabb, aabb) == true)
{
if (node->IsLeaf() == true)
if (node->IsLeaf() == true)
{
if (callback->Report(nodeIndex) == false)
if (callback->Report(nodeIndex) == false)
{
return;
}
}
else
else
{
stack.Push(node->child1);
stack.Push(node->child2);
@ -185,55 +185,142 @@ inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB3& aabb) const
}
template<class T>
inline void b3DynamicTree::RayCast(T* callback, const b3RayCastInput& input) const
inline void b3DynamicTree::RayCast(T* callback, const b3RayCastInput& input) const
{
b3Vec3 p1 = input.p1;
b3Vec3 p2 = input.p2;
b3Vec3 d = p2 - p1;
float32 maxFraction = input.maxFraction;
b3Vec3 r = p2 - p1;
B3_ASSERT(b3LengthSquared(r) > scalar(0));
r.Normalize();
scalar maxFraction = input.maxFraction;
// Build an AABB for the segment.
b3Vec3 q2;
b3AABB segmentAABB;
{
q2 = p1 + maxFraction * (p2 - p1);
segmentAABB.lowerBound = b3Min(p1, q2);
segmentAABB.upperBound = b3Max(p1, q2);
}
// Ensure non-degenerate segment.
B3_ASSERT(b3Dot(d, d) > B3_EPSILON * B3_EPSILON);
b3Vec3 e1 = b3Vec3_x;
b3Vec3 e2 = b3Vec3_y;
b3Vec3 e3 = b3Vec3_z;
b3Stack<u32, 256> stack;
stack.Push(m_root);
while (stack.IsEmpty() == false)
while (stack.IsEmpty() == false)
{
u32 nodeIndex = stack.Top();
stack.Pop();
if (nodeIndex == B3_NULL_NODE_D)
if (nodeIndex == B3_NULL_NODE_D)
{
continue;
}
const b3Node* node = m_nodes + nodeIndex;
float32 minFraction;
if (node->aabb.TestRay(minFraction, p1, p2, maxFraction) == true)
if (b3TestOverlap(segmentAABB, node->aabb) == false)
{
if (node->IsLeaf() == true)
{
b3RayCastInput subInput;
subInput.p1 = input.p1;
subInput.p2 = input.p2;
subInput.maxFraction = maxFraction;
continue;
}
// Separating axis for segment (Gino, p80).
b3Vec3 c = node->aabb.GetCenter();
b3Vec3 h = node->aabb.GetExtents();
float32 newFraction = callback->Report(subInput, nodeIndex);
b3Vec3 s = p1 - c;
b3Vec3 t = q2 - c;
if (newFraction == 0.0f)
{
// The client has stopped the query.
return;
}
}
else
// |sigma + tau| > |sigma - tau| + 2 * eta
scalar sigma_1 = s.x;
scalar tau_1 = t.x;
scalar eta_1 = h.x;
scalar s1 = b3Abs(sigma_1 + tau_1) - (b3Abs(sigma_1 - tau_1) + scalar(2) * eta_1);
if (s1 > scalar(0))
{
continue;
}
scalar sigma_2 = s.y;
scalar tau_2 = t.y;
scalar eta_2 = h.y;
scalar s2 = b3Abs(sigma_2 + tau_2) - (b3Abs(sigma_2 - tau_2) + scalar(2) * eta_2);
if (s2 > scalar(0))
{
continue;
}
scalar sigma_3 = s.z;
scalar tau_3 = t.z;
scalar eta_3 = h.z;
scalar s3 = b3Abs(sigma_3 + tau_3) - (b3Abs(sigma_3 - tau_3) + scalar(2) * eta_3);
if (s3 > scalar(0))
{
continue;
}
// v = cross(ei, r)
// |dot(v, s)| > dot(|v|, h)
b3Vec3 v1 = b3Cross(e1, r);
b3Vec3 abs_v1 = b3Abs(v1);
scalar s4 = b3Abs(b3Dot(v1, s)) - b3Dot(abs_v1, h);
if (s4 > scalar(0))
{
continue;
}
b3Vec3 v2 = b3Cross(e2, r);
b3Vec3 abs_v2 = b3Abs(v2);
scalar s5 = b3Abs(b3Dot(v2, s)) - b3Dot(abs_v2, h);
if (s5 > scalar(0))
{
continue;
}
b3Vec3 v3 = b3Cross(e3, r);
b3Vec3 abs_v3 = b3Abs(v3);
scalar s6 = b3Abs(b3Dot(v3, s)) - b3Dot(abs_v3, h);
if (s6 > scalar(0))
{
continue;
}
if (node->IsLeaf() == true)
{
b3RayCastInput subInput;
subInput.p1 = input.p1;
subInput.p2 = input.p2;
subInput.maxFraction = maxFraction;
scalar newMaxFraction = callback->Report(subInput, nodeIndex);
if (newMaxFraction == scalar(0))
{
stack.Push(node->child1);
stack.Push(node->child2);
// The client has stopped the query.
return;
}
if (newMaxFraction > scalar(0))
{
// Update the segment AABB.
maxFraction = newMaxFraction;
q2 = p1 + maxFraction * (p2 - p1);
segmentAABB.lowerBound = b3Min(p1, q2);
segmentAABB.upperBound = b3Max(p1, q2);
}
}
else
{
stack.Push(node->child1);
stack.Push(node->child2);
}
}
}

View File

@ -20,7 +20,7 @@
#define B3_STATIC_TREE_H
#include <bounce/common/template/stack.h>
#include <bounce/collision/shapes/aabb3.h>
#include <bounce/collision/shapes/aabb.h>
#include <bounce/collision/collision.h>
#define B3_NULL_NODE_S (0xFFFFFFFF)
@ -33,10 +33,10 @@ public:
~b3StaticTree();
// Build this tree from a list of AABBs.
void Build(const b3AABB3* aabbs, u32 count);
void Build(const b3AABB* aabbs, u32 count);
// Get the AABB of a given proxy.
const b3AABB3& GetAABB(u32 proxyId) const;
const b3AABB& GetAABB(u32 proxyId) const;
// Get the user data associated with a given proxy.
u32 GetUserData(u32 proxyId) const;
@ -45,7 +45,7 @@ public:
// the given AABB. The client callback must return true if the query
// must be stopped or false to continue looking for more overlapping pairs.
template<class T>
void QueryAABB(T* callback, const b3AABB3& aabb) const;
void QueryAABB(T* callback, const b3AABB& aabb) const;
// Report the client callback all AABBs that are overlapping with
// the given ray. The client callback must return the new intersection fraction
@ -56,12 +56,13 @@ public:
// Draw this tree.
void Draw() const;
// Get the size in bytes of this tree.
u32 GetSize() const;
private :
// A node in a static tree.
struct b3Node
{
b3AABB3 aabb;
b3AABB aabb;
u32 child1;
union
{
@ -76,15 +77,18 @@ private :
}
};
//
void Build(const b3AABB3* set, b3Node* node, u32* indices, u32 count, u32 minObjectsPerLeaf, u32 nodeCapacity, u32& leafCount, u32& internalCount);
// Build this tree recursively.
void RecurseBuild(const b3AABB* set, b3Node* node, u32* indices, u32 count, u32 minObjectsPerLeaf, u32 nodeCapacity, u32& leafCount, u32& internalCount);
// The root of this tree.
u32 m_root;
// The nodes of this tree stored in an array.
u32 m_nodeCount;
b3Node* m_nodes;
};
inline const b3AABB3& b3StaticTree::GetAABB(u32 proxyId) const
inline const b3AABB& b3StaticTree::GetAABB(u32 proxyId) const
{
B3_ASSERT(proxyId < m_nodeCount);
return m_nodes[proxyId].aabb;
@ -98,17 +102,15 @@ inline u32 b3StaticTree::GetUserData(u32 proxyId) const
}
template<class T>
inline void b3StaticTree::QueryAABB(T* callback, const b3AABB3& aabb) const
inline void b3StaticTree::QueryAABB(T* callback, const b3AABB& aabb) const
{
if (m_nodeCount == 0)
{
return;
}
u32 root = 0;
b3Stack<u32, 256> stack;
stack.Push(root);
stack.Push(m_root);
while (stack.IsEmpty() == false)
{
@ -151,20 +153,32 @@ inline void b3StaticTree::RayCast(T* callback, const b3RayCastInput& input) cons
b3Vec3 p1 = input.p1;
b3Vec3 p2 = input.p2;
b3Vec3 d = p2 - p1;
float32 maxFraction = input.maxFraction;
b3Vec3 r = p2 - p1;
B3_ASSERT(b3LengthSquared(r) > scalar(0));
r.Normalize();
// Ensure non-degenerate segment.
B3_ASSERT(b3Dot(d, d) > B3_EPSILON * B3_EPSILON);
scalar maxFraction = input.maxFraction;
u32 root = 0;
// Build an AABB for the segment.
b3Vec3 q2;
b3AABB segmentAABB;
{
q2 = p1 + maxFraction * (p2 - p1);
segmentAABB.lowerBound = b3Min(p1, q2);
segmentAABB.upperBound = b3Max(p1, q2);
}
b3Vec3 e1 = b3Vec3_x;
b3Vec3 e2 = b3Vec3_y;
b3Vec3 e3 = b3Vec3_z;
b3Stack<u32, 256> stack;
stack.Push(root);
while (stack.IsEmpty() == false)
stack.Push(m_root);
while (stack.IsEmpty() == false)
{
u32 nodeIndex = stack.Top();
u32 nodeIndex = stack.Top();
stack.Pop();
if (nodeIndex == B3_NULL_NODE_S)
@ -174,29 +188,103 @@ inline void b3StaticTree::RayCast(T* callback, const b3RayCastInput& input) cons
const b3Node* node = m_nodes + nodeIndex;
float32 minFraction;
if (node->aabb.TestRay(minFraction, p1, p2, maxFraction) == true)
if (b3TestOverlap(segmentAABB, node->aabb) == false)
{
if (node->IsLeaf() == true)
{
b3RayCastInput subInput;
subInput.p1 = input.p1;
subInput.p2 = input.p2;
subInput.maxFraction = maxFraction;
continue;
}
float32 newFraction = callback->Report(subInput, nodeIndex);
// Separating axis for segment (Gino, p80).
b3Vec3 c = node->aabb.GetCenter();
b3Vec3 h = node->aabb.GetExtents();
if (newFraction == 0.0f)
{
// The client has stopped the query.
return;
}
}
else
b3Vec3 s = p1 - c;
b3Vec3 t = q2 - c;
// |sigma + tau| > |sigma - tau| + 2 * eta
scalar sigma_1 = s.x;
scalar tau_1 = t.x;
scalar eta_1 = h.x;
scalar s1 = b3Abs(sigma_1 + tau_1) - (b3Abs(sigma_1 - tau_1) + scalar(2) * eta_1);
if (s1 > scalar(0))
{
continue;
}
scalar sigma_2 = s.y;
scalar tau_2 = t.y;
scalar eta_2 = h.y;
scalar s2 = b3Abs(sigma_2 + tau_2) - (b3Abs(sigma_2 - tau_2) + scalar(2) * eta_2);
if (s2 > scalar(0))
{
continue;
}
scalar sigma_3 = s.z;
scalar tau_3 = t.z;
scalar eta_3 = h.z;
scalar s3 = b3Abs(sigma_3 + tau_3) - (b3Abs(sigma_3 - tau_3) + scalar(2) * eta_3);
if (s3 > scalar(0))
{
continue;
}
// v = cross(ei, r)
// |dot(v, s)| > dot(|v|, h)
b3Vec3 v1 = b3Cross(e1, r);
b3Vec3 abs_v1 = b3Abs(v1);
scalar s4 = b3Abs(b3Dot(v1, s)) - b3Dot(abs_v1, h);
if (s4 > scalar(0))
{
continue;
}
b3Vec3 v2 = b3Cross(e2, r);
b3Vec3 abs_v2 = b3Abs(v2);
scalar s5 = b3Abs(b3Dot(v2, s)) - b3Dot(abs_v2, h);
if (s5 > scalar(0))
{
continue;
}
b3Vec3 v3 = b3Cross(e3, r);
b3Vec3 abs_v3 = b3Abs(v3);
scalar s6 = b3Abs(b3Dot(v3, s)) - b3Dot(abs_v3, h);
if (s6 > scalar(0))
{
continue;
}
if (node->IsLeaf() == true)
{
b3RayCastInput subInput;
subInput.p1 = input.p1;
subInput.p2 = input.p2;
subInput.maxFraction = maxFraction;
scalar newMaxFraction = callback->Report(subInput, nodeIndex);
if (newMaxFraction == scalar(0))
{
stack.Push(node->child1);
stack.Push(node->child2);
// The client has stopped the query.
return;
}
if (newMaxFraction > scalar(0))
{
// Update the segment AABB.
maxFraction = newMaxFraction;
q2 = p1 + maxFraction * (p2 - p1);
segmentAABB.lowerBound = b3Min(p1, q2);
segmentAABB.upperBound = b3Max(p1, q2);
}
}
else
{
stack.Push(node->child1);
stack.Push(node->child2);
}
}
}

View File

@ -20,16 +20,16 @@
#define B3_DRAW_H
#include <bounce/common/math/math.h>
#include <bounce/collision/shapes/aabb3.h>
#include <bounce/collision/shapes/aabb.h>
// Color channels used by the debug draw interface.
struct b3Color
{
b3Color() { }
b3Color(float32 R, float32 G, float32 B, float32 A = 1.0f) : r(R), g(G), b(B), a(A) { }
b3Color(scalar R, scalar G, scalar B, scalar A = scalar(1)) : r(R), g(G), b(B), a(A) { }
float32 r, g, b, a;
scalar r, g, b, a;
};
// Color pallete commonly used by the debug draw interface.
@ -72,7 +72,7 @@ public :
void AppendFlags(u32 flags);
// Draw a point.
virtual void DrawPoint(const b3Vec3& p, float32 size, const b3Color& color) = 0;
virtual void DrawPoint(const b3Vec3& p, scalar size, const b3Color& color) = 0;
// Draw a line segment.
virtual void DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color) = 0;
@ -90,31 +90,31 @@ public :
virtual void DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color) = 0;
// Draw a circle with center, normal, and radius.
virtual void DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color) = 0;
virtual void DrawCircle(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color) = 0;
// Draw a solid circle with center, normal, and radius.
virtual void DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color) = 0;
virtual void DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color) = 0;
// Draw a plane with center, normal and radius.
virtual void DrawPlane(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color) = 0;
virtual void DrawPlane(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color) = 0;
// Draw a solid plane with center, normal and radius.
virtual void DrawSolidPlane(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color) = 0;
virtual void DrawSolidPlane(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color) = 0;
// Draw a sphere with center, and radius.
virtual void DrawSphere(const b3Vec3& center, float32 radius, const b3Color& color) = 0;
virtual void DrawSphere(const b3Vec3& center, scalar radius, const b3Color& color) = 0;
// Draw a solid sphere with center, radius, and rotation.
virtual void DrawSolidSphere(const b3Vec3& center, float32 radius, const b3Mat33& rotation, const b3Color& color) = 0;
virtual void DrawSolidSphere(const b3Vec3& center, scalar radius, const b3Quat& rotation, const b3Color& color) = 0;
// Draw a capsule with segment, and radius.
virtual void DrawCapsule(const b3Vec3& p1, const b3Vec3& p2, float32 radius, const b3Color& color) = 0;
virtual void DrawCapsule(const b3Vec3& p1, const b3Vec3& p2, scalar radius, const b3Color& color) = 0;
// Draw a solid capsule with segment, radius, and rotation.
virtual void DrawSolidCapsule(const b3Vec3& p1, const b3Vec3& p2, float32 radius, const b3Mat33& rotation, const b3Color& color) = 0;
virtual void DrawSolidCapsule(const b3Vec3& p1, const b3Vec3& p2, scalar radius, const b3Quat& rotation, const b3Color& color) = 0;
// Draw a AABB.
virtual void DrawAABB(const b3AABB3& aabb, const b3Color& color) = 0;
virtual void DrawAABB(const b3AABB& aabb, const b3Color& color) = 0;
// Draw a transform.
virtual void DrawTransform(const b3Transform& xf) = 0;

View File

@ -37,7 +37,7 @@ struct b3Ray3
b3Vec3 direction;
b3Vec3 origin;
float32 fraction;
scalar fraction;
};
// A plane in constant normal form.
@ -48,7 +48,7 @@ struct b3Plane
b3Plane() { }
// Set this plane from a normal and a signed distance from its origin.
b3Plane(const b3Vec3& _normal, float32 _offset)
b3Plane(const b3Vec3& _normal, scalar _offset)
{
normal = _normal;
offset = _offset;
@ -70,14 +70,14 @@ struct b3Plane
}
b3Vec3 normal;
float32 offset;
scalar offset;
};
// Transform a plane by a given frame.
inline b3Plane b3Mul(const b3Transform& T, const b3Plane& plane)
{
b3Vec3 normal = b3Mul(T.rotation, plane.normal);
return b3Plane(normal, plane.offset + b3Dot(normal, T.position));
return b3Plane(normal, plane.offset + b3Dot(normal, T.translation));
}
// Transform a plane by a given frame.
@ -87,7 +87,7 @@ inline b3Plane operator*(const b3Transform& T, const b3Plane& plane)
}
// Compute the distance between a point and a plane.
inline float32 b3Distance(const b3Vec3& P, const b3Plane& plane)
inline scalar b3Distance(const b3Vec3& P, const b3Plane& plane)
{
return b3Dot(plane.normal, P) - plane.offset;
}
@ -95,14 +95,14 @@ inline float32 b3Distance(const b3Vec3& P, const b3Plane& plane)
// Project a point onto a normal plane.
inline b3Vec3 b3ClosestPointOnPlane(const b3Vec3& P, const b3Plane& plane)
{
float32 fraction = b3Distance(P, plane);
scalar fraction = b3Distance(P, plane);
return P - fraction * plane.normal;
}
// Convert a point Q from Cartesian coordinates to Barycentric coordinates (u, v)
// with respect to a segment AB.
// The last output value is the divisor.
inline void b3BarycentricCoordinates(float32 out[3],
inline void b3BarycentricCoordinates(scalar out[3],
const b3Vec3& A, const b3Vec3& B,
const b3Vec3& Q)
{
@ -110,16 +110,17 @@ inline void b3BarycentricCoordinates(float32 out[3],
b3Vec3 QA = A - Q;
b3Vec3 QB = B - Q;
float32 divisor = b3Dot(AB, AB);
scalar divisor = b3Dot(AB, AB);
out[0] = b3Dot(QB, AB);
out[1] = -b3Dot(QA, AB);
out[2] = divisor;
}
// Convert a point Q from Cartesian coordinates to Barycentric coordinates (u, v, w)
// with respect to a triangle ABC.
// The last output value is the divisor.
inline void b3BarycentricCoordinates(float32 out[4],
inline void b3BarycentricCoordinates(scalar out[4],
const b3Vec3& A, const b3Vec3& B, const b3Vec3& C,
const b3Vec3& Q)
{
@ -136,7 +137,7 @@ inline void b3BarycentricCoordinates(float32 out[4],
b3Vec3 AB_x_AC = b3Cross(AB, AC);
//float32 divisor = b3Dot(AB_x_AC, AB_x_AC);
//scalar divisor = b3Dot(AB_x_AC, AB_x_AC);
out[0] = b3Dot(QB_x_QC, AB_x_AC);
out[1] = b3Dot(QC_x_QA, AB_x_AC);
@ -147,7 +148,7 @@ inline void b3BarycentricCoordinates(float32 out[4],
// Convert a point Q from Cartesian coordinates to Barycentric coordinates (u, v, w, x)
// with respect to a tetrahedron ABCD.
// The last output value is the (positive) divisor.
inline void b3BarycentricCoordinates(float32 out[5],
inline void b3BarycentricCoordinates(scalar out[5],
const b3Vec3& A, const b3Vec3& B, const b3Vec3& C, const b3Vec3& D,
const b3Vec3& Q)
{
@ -160,8 +161,8 @@ inline void b3BarycentricCoordinates(float32 out[5],
b3Vec3 QC = C - Q;
b3Vec3 QD = D - Q;
float32 divisor = b3Det(AB, AC, AD);
float32 sign = b3Sign(divisor);
scalar divisor = b3Det(AB, AC, AD);
scalar sign = b3Sign(divisor);
out[0] = sign * b3Det(QB, QC, QD);
out[1] = sign * b3Det(QA, QD, QC);
@ -173,22 +174,22 @@ inline void b3BarycentricCoordinates(float32 out[5],
// Project a point onto a segment AB.
inline b3Vec3 b3ClosestPointOnSegment(const b3Vec3& P, const b3Vec3& A, const b3Vec3& B)
{
float32 wAB[3];
scalar wAB[3];
b3BarycentricCoordinates(wAB, A, B, P);
if (wAB[1] <= 0.0f)
if (wAB[1] <= scalar(0))
{
return A;
}
if (wAB[0] <= 0.0f)
if (wAB[0] <= scalar(0))
{
return B;
}
float32 s = 1.0f / wAB[2];
float32 wA = s * wAB[0];
float32 wB = s * wAB[1];
scalar s = scalar(1) / wAB[2];
scalar wA = s * wAB[0];
scalar wB = s * wAB[1];
return wA * A + wB * B;
}

View File

@ -134,7 +134,7 @@ struct b3Mat43
};
// a * 3x4 = 3x4
inline b3Mat34 operator*(float32 s, const b3Mat34& A)
inline b3Mat34 operator*(scalar s, const b3Mat34& A)
{
return b3Mat34(s * A.x, s * A.y, s * A.z, s * A.w);
}
@ -152,7 +152,7 @@ inline b3Vec3 operator*(const b3Mat34& A, const b3Vec4& v)
}
// 1x3 * 3x1 = 1x1
inline float32 operator*(const b3Vec3& A, const b3Vec3& B)
inline scalar operator*(const b3Vec3& A, const b3Vec3& B)
{
return A.x * B.x + A.y * B.y + A.z * B.z;
}
@ -181,13 +181,13 @@ inline b3Vec3 operator*(const b3Mat32& A, const b3Vec2& B)
return B.x * A.x + B.y * A.y;
}
// 2x3 * 2x1 = 2x1
// 2x3 * 3x1 = 2x1
inline b3Vec2 operator*(const b3Mat23& A, const b3Vec3& B)
{
return B.x * A.x + B.y * A.y + B.z * A.z;
}
// 2x3 * 2x2 = 2x2
// 2x3 * 3x2 = 2x2
inline b3Mat22 operator*(const b3Mat23& A, const b3Mat32& B)
{
return b3Mat22(A * B.x, A * B.y);
@ -223,7 +223,7 @@ inline b3Mat23 operator*(const b3Mat24& A, const b3Mat43& B)
return b3Mat23(A * B.x, A * B.y, A * B.z);
}
// 2x4 * 2x4 = 2x4
// 2x4 * 4x4 = 2x4
inline b3Mat24 operator*(const b3Mat24& A, const b3Mat44& B)
{
return b3Mat24(A * B.x, A * B.y, A * B.z, A * B.w);

View File

@ -29,6 +29,30 @@ struct b3Mat22
// Set this matrix from two vectors.
b3Mat22(const b3Vec2& _x, const b3Vec2& _y) : x(_x), y(_y) { }
// Read an indexed column vector from this matrix.
const b3Vec2& operator[](u32 i) const
{
return (&x)[i];
}
// Write an indexed column vector to this matrix.
b3Vec2& operator[](u32 i)
{
return (&x)[i];
}
// Read an indexed element from this matrix.
scalar operator()(u32 i, u32 j) const
{
return (&x.x)[i + 2 * j];
}
// Write an indexed element from this matrix.
scalar& operator()(u32 i, u32 j)
{
return (&x.x)[i + 2 * j];
}
// Set this matrix to the zero matrix.
void SetZero()
@ -37,6 +61,13 @@ struct b3Mat22
y.SetZero();
}
// Set this matrix to the identity matrix.
void SetIdentity()
{
x.Set(scalar(1), scalar(0));
y.Set(scalar(0), scalar(1));
}
// Solve Ax = b.
// It doesn't compute the inverse.
// Therefore, is more efficient.
@ -64,15 +95,42 @@ inline b3Mat22 operator+(const b3Mat22& A, const b3Mat22& B)
return b3Mat22(A.x + B.x, A.y + B.y);
}
// Subtract two matrices.
inline b3Mat22 operator-(const b3Mat22& A, const b3Mat22& B)
{
return b3Mat22(A.x - B.x, A.y - B.y);
}
// Multiply two matrices.
inline b3Mat22 operator*(const b3Mat22& A, const b3Mat22& B)
{
return b3Mat22(A * B.x, A * B.y);
}
// Multiply a scalar times a matrix.
inline b3Mat22 operator*(scalar s, const b3Mat22& A)
{
return b3Mat22(s * A.x, s * A.y);
}
// Multiply a matrix times a vector.
inline b3Vec2 b3Mul(const b3Mat22& A, const b3Vec2& v)
{
return v.x * A.x + v.y * A.y;
}
// Transpose a matrix.
inline b3Mat22 b3Transpose(const b3Mat22& A)
{
return b3Mat22(
b3Vec2(A.x.x, A.y.x),
b3Vec2(A.x.y, A.y.y)
);
}
// Invert a matrix.
// If the matrix determinant is zero this returns
// the zero matrix.
b3Mat22 b3Inverse(const b3Mat22& A);
#endif
#endif

View File

@ -43,13 +43,13 @@ struct b3Mat33
}
// Read an indexed element from this matrix.
float32 operator()(u32 i, u32 j) const
scalar operator()(u32 i, u32 j) const
{
return (&x.x)[i + 3 * j];
}
// Write an indexed element from this matrix.
float32& operator()(u32 i, u32 j)
scalar& operator()(u32 i, u32 j)
{
return (&x.x)[i + 3 * j];
}
@ -81,9 +81,9 @@ struct b3Mat33
// Set this matrix to the identity matrix.
void SetIdentity()
{
x.Set(1.0f, 0.0f, 0.0f);
y.Set(0.0f, 1.0f, 0.0f);
z.Set(0.0f, 0.0f, 1.0f);
x.Set(scalar(1), scalar(0), scalar(0));
y.Set(scalar(0), scalar(1), scalar(0));
z.Set(scalar(0), scalar(0), scalar(1));
}
// Solve Ax = b.
@ -112,7 +112,7 @@ inline b3Mat33 operator-(const b3Mat33& A, const b3Mat33& B)
}
// Multiply a scalar times a matrix.
inline b3Mat33 operator*(float32 s, const b3Mat33& A)
inline b3Mat33 operator*(scalar s, const b3Mat33& A)
{
return b3Mat33(s * A.x, s * A.y, s * A.z);
}
@ -120,7 +120,7 @@ inline b3Mat33 operator*(float32 s, const b3Mat33& A)
// Negate a matrix.
inline b3Mat33 operator-(const b3Mat33& A)
{
return -1.0f * A;
return scalar(-1) * A;
}
// Multiply a matrix times a vector. If the matrix
@ -168,6 +168,12 @@ inline b3Mat33 b3MulT(const b3Mat33& A, const b3Mat33& B)
b3Vec3(b3Dot(A.x, B.z), b3Dot(A.y, B.z), b3Dot(A.z, B.z)));
}
// Return the absolute matrix of a given matrix.
inline b3Mat33 b3Abs(const b3Mat33& A)
{
return b3Mat33(b3Abs(A.x), b3Abs(A.y), b3Abs(A.z));
}
// Transpose a matrix.
inline b3Mat33 b3Transpose(const b3Mat33& A)
{
@ -179,23 +185,21 @@ inline b3Mat33 b3Transpose(const b3Mat33& A)
}
// Uniform scale matrix.
inline b3Mat33 b3Diagonal(float32 s)
inline b3Mat33 b3Diagonal(scalar s)
{
return b3Mat33(
b3Vec3(s, 0.0f, 0.0f),
b3Vec3(0.0f, s, 0.0f),
b3Vec3(0.0f, 0.0f, s)
);
b3Vec3(s, scalar(0), scalar(0)),
b3Vec3(scalar(0), s, scalar(0)),
b3Vec3(scalar(0), scalar(0), s));
}
// Uniform or non-uniform scale matrix.
inline b3Mat33 b3Diagonal(float32 x, float32 y, float32 z)
inline b3Mat33 b3Diagonal(scalar x, scalar y, scalar z)
{
return b3Mat33(
b3Vec3(x, 0.0f, 0.0f),
b3Vec3(0.0f, y, 0.0f),
b3Vec3(0.0f, 0.0f, z)
);
b3Vec3(x, scalar(0), scalar(0)),
b3Vec3(scalar(0), y, scalar(0)),
b3Vec3(scalar(0), scalar(0), z));
}
// Invert a matrix.
@ -212,14 +216,13 @@ b3Mat33 b3SymInverse(const b3Mat33& A);
inline b3Mat33 b3Skew(const b3Vec3& v)
{
return b3Mat33(
b3Vec3(0.0f, v.z, -v.y),
b3Vec3(-v.z, 0.0f, v.x),
b3Vec3(v.y, -v.x, 0.0f)
);
b3Vec3(scalar(0), v.z, -v.y),
b3Vec3(-v.z, scalar(0), v.x),
b3Vec3(v.y, -v.x, scalar(0)));
}
// Compute the dot product of two vectors.
inline float32 b3Inner(const b3Vec3& a, const b3Vec3& b)
inline scalar b3Inner(const b3Vec3& a, const b3Vec3& b)
{
return b3Dot(a, b);
}
@ -235,14 +238,19 @@ inline b3Mat33 b3Outer(const b3Vec3& a, const b3Vec3& b)
// The vector must be normalized.
inline void b3ComputeBasis(const b3Vec3& a, b3Vec3& b, b3Vec3& c)
{
// https://box2d.org/2014/02/computing-a-basis/
if (b3Abs(a.x) >= float32(0.57735027))
// https://box2d.org/2014/02/computing-a-basis/, (Erin)
// Suppose vector a has all equal components and is a unit vector : a = (s, s, s)
// Then 3*s*s = 1, s = sqrt(1/3).
// This means that at least one component of a unit vector must be greater or equal to s.
static const scalar sqrt_inv3 = b3Sqrt(scalar(1) / scalar(3));
if (b3Abs(a.x) >= sqrt_inv3)
{
b.Set(a.y, -a.x, 0.0f);
b.Set(a.y, -a.x, scalar(0));
}
else
{
b.Set(0.0f, a.z, -a.y);
b.Set(scalar(0), a.z, -a.y);
}
b.Normalize();
@ -250,41 +258,41 @@ inline void b3ComputeBasis(const b3Vec3& a, b3Vec3& b, b3Vec3& c)
}
// Rotation about the x-axis.
inline b3Mat33 b3Mat33RotationX(float32 angle)
inline b3Mat33 b3Mat33RotationX(scalar angle)
{
float32 c = cos(angle);
float32 s = sin(angle);
scalar c = cos(angle);
scalar s = sin(angle);
b3Mat33 R;
R.x.Set(1.0f, 0.0f, 0.0f);
R.y.Set(0.0f, c, s);
R.z.Set(0.0f, -s, c);
R.x.Set(scalar(1), scalar(0), scalar(0));
R.y.Set(scalar(0), c, s);
R.z.Set(scalar(0), -s, c);
return R;
}
// Rotation about the y-axis.
inline b3Mat33 b3Mat33RotationY(float32 angle)
inline b3Mat33 b3Mat33RotationY(scalar angle)
{
float32 c = cos(angle);
float32 s = sin(angle);
scalar c = cos(angle);
scalar s = sin(angle);
b3Mat33 R;
R.x.Set(c, 0.0f, -s);
R.y.Set(0.0f, 1.0f, 0.0f);
R.z.Set(s, 0.0f, c);
R.x.Set(c, scalar(0), -s);
R.y.Set(scalar(0), scalar(1), scalar(0));
R.z.Set(s, scalar(0), c);
return R;
}
// Rotation about the z-axis.
inline b3Mat33 b3Mat33RotationZ(float32 angle)
inline b3Mat33 b3Mat33RotationZ(scalar angle)
{
float32 c = cos(angle);
float32 s = sin(angle);
scalar c = cos(angle);
scalar s = sin(angle);
b3Mat33 R;
R.x.Set(c, s, 0.0f);
R.y.Set(-s, c, 0.0f);
R.z.Set(0.0f, 0.0f, 1.0f);
R.x.Set(c, s, scalar(0));
R.y.Set(-s, c, scalar(0));
R.z.Set(scalar(0), scalar(0), scalar(1));
return R;
}

View File

@ -46,7 +46,7 @@ struct b3Mat44
};
//
inline b3Mat44 operator*(float32 s, const b3Mat44& A)
inline b3Mat44 operator*(scalar s, const b3Mat44& A)
{
return b3Mat44(s * A.x, s * A.y, s * A.z, s * A.w);
}
@ -63,4 +63,9 @@ inline b3Mat44 operator*(const b3Mat44& A, const b3Mat44& B)
return b3Mat44(A * B.x, A * B.y, A * B.z, A * B.w);
}
inline b3Mat44 operator-(const b3Mat44& A)
{
return scalar(-1) * A;
}
#endif

View File

@ -23,23 +23,22 @@
#include <cstdlib> // For abs() with integral types
#include <bounce/common/settings.h>
inline bool b3IsInf(float32 x)
inline bool b3IsInf(scalar x)
{
return std::isinf(x);
}
inline bool b3IsNaN(float32 x)
inline bool b3IsNaN(scalar x)
{
return std::isnan(x);
}
inline bool b3IsValid(float32 fx)
inline bool b3IsValid(scalar fx)
{
i32 ix = *(i32*)(&fx);
return (ix & 0x7F800000) != 0x7F800000;
return std::isfinite(fx);
}
inline float32 b3Sqrt(float32 x)
inline scalar b3Sqrt(scalar x)
{
return std::sqrt(x);
}
@ -83,7 +82,7 @@ inline T b3Sign(T x)
}
template <class T>
inline u32 b3UniqueCount(T* V, u32 N)
inline u32 b3UniqueCount(const T* V, u32 N)
{
u32 count = 0;
for (u32 i = 0; i < N; ++i)
@ -104,4 +103,49 @@ inline u32 b3UniqueCount(T* V, u32 N)
return count;
}
#endif
// Multiply two matrices stored in column-major order.
// C = A * B
inline void b3Mul(scalar* C, const scalar* A, u32 AM, u32 AN, const scalar* B, u32 BM, u32 BN)
{
B3_ASSERT(AN == BM);
for (u32 i = 0; i < AM; ++i)
{
for (u32 j = 0; j < BN; ++j)
{
C[i + AM * j] = scalar(0);
for (u32 k = 0; k < AN; ++k)
{
C[i + AM * j] += A[i + AM * k] * B[k + BM * j];
}
}
}
}
// Return the transpose of a given matrix stored in column-major order.
// B = A^T
inline void b3Transpose(scalar* B, const scalar* A, u32 AM, u32 AN)
{
for (u32 i = 0; i < AM; ++i)
{
for (u32 j = 0; j < AN; ++j)
{
B[j + AN * i] = A[i + AM * j];
}
}
}
// Return the lenght of a given vector.
// ||v||
inline scalar b3Length(const scalar* v, u32 n)
{
scalar result(0);
for (u32 i = 0; i < n; ++i)
{
result += v[i] * v[i];
}
return b3Sqrt(result);
}
#endif

View File

@ -29,116 +29,165 @@ struct b3Quat
b3Quat() { }
// Set this quaternion from four values.
b3Quat(float32 _x, float32 _y, float32 _z, float32 _w) : x(_x), y(_y), z(_z), w(_w) { }
b3Quat(scalar _x, scalar _y, scalar _z, scalar _s) : v(_x, _y, _z), s(_s) { }
// Set this quaternion from an axis and an angle
// of rotation about the axis.
b3Quat(const b3Vec3& axis, float32 angle)
{
Set(axis, angle);
}
// Write an indexed value to this quaternion.
float32& operator[](u32 i)
{
return (&x)[i];
}
// Read an indexed value from this quaternion.
float32 operator[](u32 i) const
{
return (&x)[i];
}
// Add a quaternion to this quaternion.
void operator+=(const b3Quat& q)
{
x += q.x;
y += q.y;
z += q.z;
w += q.w;
v.x += q.v.x;
v.y += q.v.y;
v.z += q.v.z;
s += q.s;
}
// Subtract a quaternion from this quaternion.
void operator-=(const b3Quat& q)
{
x -= q.x;
y -= q.y;
z -= q.z;
w -= q.w;
v.x -= q.v.x;
v.y -= q.v.y;
v.z -= q.v.z;
s -= q.s;
}
// Set this quaternion to identity.
void SetIdentity()
{
x = y = z = 0.0f;
w = 1.0f;
v.x = v.y = v.z = scalar(0);
s = scalar(1);
}
// Set this quaternion from four values.
void Set(float32 _x, float32 _y, float32 _z, float32 _w)
void Set(scalar _x, scalar _y, scalar _z, scalar _s)
{
x = _x;
y = _y;
z = _z;
w = _w;
v.x = _x;
v.y = _y;
v.z = _z;
s = _s;
}
// Convert this quaternion to the unit quaternion. Return the length.
float32 Normalize()
scalar Normalize()
{
float32 length = b3Sqrt(x * x + y * y + z * z + w * w);
if (length > B3_EPSILON)
scalar len = b3Sqrt(v.x * v.x + v.y * v.y + v.z * v.z + s * s);
if (len > B3_EPSILON)
{
float32 s = 1.0f / length;
x *= s;
y *= s;
z *= s;
w *= s;
scalar inv_len = scalar(1) / len;
v *= inv_len;
s *= inv_len;
}
return length;
return len;
}
// Set this quaternion from an axis and full angle
// of rotation about the axis.
void Set(const b3Vec3& axis, float32 angle)
void SetAxisAngle(const b3Vec3& axis, scalar angle)
{
// half angle
float32 theta = 0.5f * angle;
scalar theta = scalar(0.5) * angle;
float32 sine = sin(theta);
x = sine * axis.x;
y = sine * axis.y;
z = sine * axis.z;
w = cos(theta);
v = sin(theta) * axis;
s = cos(theta);
}
// If this quaternion represents an orientation output
// the axis and angle of rotation about the axis.
void GetAxisAngle(b3Vec3* axis, float32* angle) const
void GetAxisAngle(b3Vec3* axis, scalar* angle) const
{
// sin^2 = 1 - cos^2
// sin = sqrt( sin^2 ) = ||v||
// axis = v / sin
b3Vec3 v(x, y, z);
float32 sine = b3Length(v);
scalar sine = b3Length(v);
axis->SetZero();
if (sine > B3_EPSILON)
{
float32 s = 1.0f / sine;
*axis = s * v;
scalar inv_sine = scalar(1) / sine;
*axis = inv_sine * v;
}
// cosine check
float32 cosine = b3Clamp(w, -1.0f, 1.0f);
scalar cosine = b3Clamp(s, scalar(-1), scalar(1));
// half angle
float32 theta = acos(cosine);
scalar theta = acos(cosine);
// full angle
*angle = 2.0f * theta;
*angle = scalar(2) * theta;
}
float32 x, y, z, w;
// Get the x axis.
b3Vec3 GetXAxis() const
{
scalar x = v.x, y = v.y, z = v.z, w = s;
scalar x2 = x + x, y2 = y + y, z2 = z + z;
scalar xx = x * x2, xy = x * y2, xz = x * z2;
scalar yy = y * y2, yz = y * z2, zz = z * z2;
scalar wx = w * x2, wy = w * y2, wz = w * z2;
return b3Vec3(scalar(1) - (yy + zz), xy + wz, xz - wy);
}
// Get the y axis.
b3Vec3 GetYAxis() const
{
scalar x = v.x, y = v.y, z = v.z, w = s;
scalar x2 = x + x, y2 = y + y, z2 = z + z;
scalar xx = x * x2, xy = x * y2, xz = x * z2;
scalar yy = y * y2, yz = y * z2, zz = z * z2;
scalar wx = w * x2, wy = w * y2, wz = w * z2;
return b3Vec3(xy - wz, scalar(1) - (xx + zz), yz + wx);
}
// Get the z axis.
b3Vec3 GetZAxis() const
{
scalar x = v.x, y = v.y, z = v.z, w = s;
scalar x2 = x + x, y2 = y + y, z2 = z + z;
scalar xx = x * x2, xy = x * y2, xz = x * z2;
scalar yy = y * y2, yz = y * z2, zz = z * z2;
scalar wx = w * x2, wy = w * y2, wz = w * z2;
return b3Vec3(xz + wy, yz - wx, scalar(1) - (xx + yy));
}
// Get the x, y, z axes.
b3Mat33 GetXYZAxes() const
{
scalar x = v.x, y = v.y, z = v.z, w = s;
scalar x2 = x + x, y2 = y + y, z2 = z + z;
scalar xx = x * x2, xy = x * y2, xz = x * z2;
scalar yy = y * y2, yz = y * z2, zz = z * z2;
scalar wx = w * x2, wy = w * y2, wz = w * z2;
return b3Mat33(
b3Vec3(scalar(1) - (yy + zz), xy + wz, xz - wy),
b3Vec3(xy - wz, scalar(1) - (xx + zz), yz + wx),
b3Vec3(xz + wy, yz - wx, scalar(1) - (xx + yy)));
}
// Get the angle about the x axis.
scalar GetXAngle() const
{
return atan2(v.x, s);
}
// Get the angle about the y axis.
scalar GetYAngle() const
{
return atan2(v.y, s);
}
// Get the angle about the z axis.
scalar GetZAngle() const
{
return atan2(v.z, s);
}
b3Vec3 v;
scalar s;
};
// Identity quaternion
@ -147,35 +196,34 @@ extern const b3Quat b3Quat_identity;
// Add two quaternions.
inline b3Quat operator+(const b3Quat& a, const b3Quat& b)
{
return b3Quat(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
return b3Quat(a.v.x + b.v.x, a.v.y + b.v.y, a.v.z + b.v.z, a.s + b.s);
}
// Subtract two quaternions.
inline b3Quat operator-(const b3Quat& a, const b3Quat& b)
{
return b3Quat(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
return b3Quat(a.v.x - b.v.x, a.v.y - b.v.y, a.v.z - b.v.z, a.s - b.s);
}
// Multiply a quaternion by a scalar.
inline b3Quat operator*(float32 s, const b3Quat& q)
inline b3Quat operator*(scalar s, const b3Quat& q)
{
return b3Quat(s * q.x, s * q.y, s * q.z, s * q.w);
return b3Quat(s * q.v.x, s * q.v.y, s * q.v.z, s * q.s);
}
// Negate a quaternion.
inline b3Quat operator-(const b3Quat& q)
{
return b3Quat(-q.x, -q.y, -q.z, -q.w);
return b3Quat(-q.v.x, -q.v.y, -q.v.z, -q.s);
}
// Multiply two quaternions.
inline b3Quat b3Mul(const b3Quat& a, const b3Quat& b)
{
return b3Quat(
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z,
a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x,
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z);
b3Quat result;
result.v = b3Cross(a.v, b.v) + a.s * b.v + b.s * a.v;
result.s = a.s * b.s - b3Dot(a.v, b.v);
return result;
}
// Multiply two quaternions.
@ -185,54 +233,51 @@ inline b3Quat operator*(const b3Quat& a, const b3Quat& b)
}
// Perform the dot poduct of two quaternions.
inline float32 b3Dot(const b3Quat& a, const b3Quat& b)
inline scalar b3Dot(const b3Quat& a, const b3Quat& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
return a.v.x * b.v.x + a.v.y * b.v.y + a.v.z * b.v.z + a.s * b.s;
}
// Return the conjugate of a quaternion.
// If the quaternion is unit this returns its inverse.
inline b3Quat b3Conjugate(const b3Quat& q)
{
return b3Quat(-q.x, -q.y, -q.z, q.w);
return b3Quat(-q.v.x, -q.v.y, -q.v.z, q.s);
}
// Multiply the conjugate of a quaternion times another quaternion.
inline b3Quat b3MulT(const b3Quat& a, const b3Quat& b)
inline b3Quat b3MulC(const b3Quat& a, const b3Quat& b)
{
return b3Mul(b3Conjugate(a), b);
}
// Return the length of a quaternion.
inline float32 b3Length(const b3Quat& q)
inline scalar b3Length(const b3Quat& q)
{
return b3Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
return b3Sqrt(q.v.x * q.v.x + q.v.y * q.v.y + q.v.z * q.v.z + q.s * q.s);
}
// Convert a quaternion to the unit quaternion.
inline b3Quat b3Normalize(const b3Quat& q)
{
float32 s = b3Length(q);
scalar s = b3Length(q);
if (s > B3_EPSILON)
{
s = 1.0f / s;
s = scalar(1) / s;
return s * q;
}
return b3Quat(0.0f, 0.0f, 0.0f, 1.0f);
return b3Quat(scalar(0), scalar(0), scalar(0), scalar(1));
}
// Rotate a vector.
inline b3Vec3 b3Mul(const b3Quat& q, const b3Vec3& v)
{
b3Vec3 qv(q.x, q.y, q.z);
float32 qs = q.w;
b3Vec3 t = 2.0f * b3Cross(qv, v);
return v + qs * t + b3Cross(qv, t);
b3Vec3 t = scalar(2) * b3Cross(q.v, v);
return v + q.s * t + b3Cross(q.v, t);
}
// Inverse rotate a vector.
inline b3Vec3 b3MulT(const b3Quat& q, const b3Vec3& v)
inline b3Vec3 b3MulC(const b3Quat& q, const b3Vec3& v)
{
return b3Mul(b3Conjugate(q), v);
}
@ -241,19 +286,20 @@ inline b3Vec3 b3MulT(const b3Quat& q, const b3Vec3& v)
inline b3Quat b3Mat33Quat(const b3Mat33& m)
{
// Check the diagonal.
float32 trace = m[0][0] + m[1][1] + m[2][2];
scalar trace = m[0][0] + m[1][1] + m[2][2];
if (trace > 0.0f)
if (trace > scalar(0))
{
b3Quat result;
float32 s = b3Sqrt(trace + 1.0f);
result.w = 0.5f * s;
float32 t = 0.5f / s;
result.x = t * (m[1][2] - m[2][1]);
result.y = t * (m[2][0] - m[0][2]);
result.z = t * (m[0][1] - m[1][0]);
scalar s = b3Sqrt(trace + scalar(1));
result.s = scalar(0.5) * s;
scalar t = scalar(0.5) / s;
result.v.x = t * (m[1][2] - m[2][1]);
result.v.y = t * (m[2][0] - m[0][2]);
result.v.z = t * (m[0][1] - m[1][0]);
return result;
}
@ -275,15 +321,15 @@ inline b3Quat b3Mat33Quat(const b3Mat33& m)
u32 j = next[i];
u32 k = next[j];
float32 s = sqrt((m[i][i] - (m[j][j] + m[k][k])) + 1.0f);
scalar s = b3Sqrt((m[i][i] - (m[j][j] + m[k][k])) + scalar(1));
float32 q[4];
q[i] = s * 0.5f;
scalar q[4];
q[i] = s * scalar(0.5);
float32 t;
if (s != 0.0f)
scalar t;
if (s != scalar(0))
{
t = 0.5f / s;
t = scalar(0.5) / s;
}
else
{
@ -295,64 +341,55 @@ inline b3Quat b3Mat33Quat(const b3Mat33& m)
q[k] = t * (m[i][k] + m[k][i]);
b3Quat result;
result.x = q[0];
result.y = q[1];
result.z = q[2];
result.w = q[3];
result.v.x = q[0];
result.v.y = q[1];
result.v.z = q[2];
result.s = q[3];
return result;
}
// Convert a rotation quaternion to a 3-by-3 rotation matrix.
inline b3Mat33 b3QuatMat33(const b3Quat& q)
{
float32 x = q.x, y = q.y, z = q.z, w = q.w;
float32 x2 = x + x, y2 = y + y, z2 = z + z;
float32 xx = x * x2, xy = x * y2, xz = x * z2;
float32 yy = y * y2, yz = y * z2, zz = z * z2;
float32 wx = w * x2, wy = w * y2, wz = w * z2;
return b3Mat33(
b3Vec3(1.0f - (yy + zz), xy + wz, xz - wy),
b3Vec3( xy - wz, 1.0f - (xx + zz), yz + wx),
b3Vec3( xz + wy, yz - wx, 1.0f - (xx + yy)));
return q.GetXYZAxes();
}
// Rotation about the x-axis.
inline b3Quat b3QuatRotationX(float32 angle)
inline b3Quat b3QuatRotationX(scalar angle)
{
float32 x = 0.5f * angle;
scalar x = scalar(0.5) * angle;
b3Quat q;
q.x = sin(x);
q.y = 0.0f;
q.z = 0.0f;
q.w = cos(x);
q.v.x = sin(x);
q.v.y = scalar(0);
q.v.z = scalar(0);
q.s = cos(x);
return q;
}
// Rotation about the y-axis.
inline b3Quat b3QuatRotationY(float32 angle)
inline b3Quat b3QuatRotationY(scalar angle)
{
float32 x = 0.5f * angle;
scalar x = scalar(0.5) * angle;
b3Quat q;
q.x = 0.0f;
q.y = sin(x);
q.z = 0.0f;
q.w = cos(x);
q.v.x = scalar(0);
q.v.y = sin(x);
q.v.z = scalar(0);
q.s = cos(x);
return q;
}
// Rotation about the z-axis.
inline b3Quat b3QuatRotationZ(float32 angle)
inline b3Quat b3QuatRotationZ(scalar angle)
{
float32 x = 0.5f * angle;
scalar x = scalar(0.5) * angle;
b3Quat q;
q.x = 0.0f;
q.y = 0.0f;
q.z = sin(x);
q.w = cos(x);
q.v.x = scalar(0);
q.v.y = scalar(0);
q.v.z = sin(x);
q.s = cos(x);
return q;
}

View File

@ -25,36 +25,25 @@
// A transform represents a rigid frame.
// It has a translation representing a position
// and a rotation matrix representing an orientation
// and a rotation quaternion representing an orientation
// relative to some reference frame.
struct b3Transform
{
// Default ctor does nothing for performance.
b3Transform() { }
// Set this transform from a rotation matrix and a translation vector.
b3Transform(const b3Mat33& _rotation, const b3Vec3& _translation)
{
rotation = _rotation;
position = _translation;
}
// Set this transform from a rotation quaternion and a translation vector.
b3Transform(const b3Quat& _rotation, const b3Vec3& _translation)
{
rotation = b3QuatMat33(_rotation);
position = _translation;
}
// Set this transform from a translation vector and a rotation quaternion.
b3Transform(const b3Vec3& _translation, const b3Quat& _rotation) : translation(_translation), rotation(_rotation) { }
// Set this transform to the identity transform.
void SetIdentity()
{
translation.SetZero();
rotation.SetIdentity();
position.SetZero();
}
b3Mat33 rotation;
b3Vec3 position; // in fact a translation
b3Vec3 translation;
b3Quat rotation;
};
// Identity transformation
@ -63,17 +52,20 @@ extern const b3Transform b3Transform_identity;
// Convert a transform to a 4-by-4 transformation matrix.
inline b3Mat44 b3TransformMat44(const b3Transform& T)
{
b3Vec3 t = T.translation;
b3Mat33 R = b3QuatMat33(T.rotation);
return b3Mat44(
b3Vec4(T.rotation.x.x, T.rotation.x.y, T.rotation.x.z, 0.0f),
b3Vec4(T.rotation.y.x, T.rotation.y.y, T.rotation.y.z, 0.0f),
b3Vec4(T.rotation.z.x, T.rotation.z.y, T.rotation.z.z, 0.0f),
b3Vec4(T.position.x, T.position.y, T.position.z, 1.0f));
b3Vec4(R.x.x, R.x.y, R.x.z, scalar(0)),
b3Vec4(R.y.x, R.y.y, R.y.z, scalar(0)),
b3Vec4(R.z.x, R.z.y, R.z.z, scalar(0)),
b3Vec4(t.x, t.y, t.z, scalar(1)));
}
// Multiply a transform times a vector.
inline b3Vec3 b3Mul(const b3Transform& T, const b3Vec3& v)
{
return b3Mul(T.rotation, v) + T.position;
return b3Mul(T.rotation, v) + T.translation;
}
// Multiply a transform times another transform.
@ -83,7 +75,7 @@ inline b3Transform b3Mul(const b3Transform& A, const b3Transform& B)
// [0 1][0 1] [0 1 ]
b3Transform C;
C.rotation = b3Mul(A.rotation, B.rotation);
C.position = b3Mul(A.rotation, B.position) + A.position;
C.translation = b3Mul(A.rotation, B.translation) + A.translation;
return C;
}
@ -94,8 +86,8 @@ inline b3Transform b3MulT(const b3Transform& A, const b3Transform& B)
//[A^-1 -A^-1*y][B x] = [A^-1*B A^-1(x-y)]
//[0 1 ][0 1] [0 1 ]
b3Transform C;
C.rotation = b3MulT(A.rotation, B.rotation);
C.position = b3MulT(A.rotation, B.position - A.position);
C.rotation = b3MulC(A.rotation, B.rotation);
C.translation = b3MulC(A.rotation, B.translation - A.translation);
return C;
}
@ -106,15 +98,15 @@ inline b3Vec3 b3MulT(const b3Transform& A, const b3Vec3& v)
{
//[A^-1 -A^-1*y][x] = A^-1*x - A^-1*y = A^-1 * (x - y)
//[0 1 ][1]
return b3MulT(A.rotation, v - A.position);
return b3MulC(A.rotation, v - A.translation);
}
// Inverse transform.
inline b3Transform b3Inverse(const b3Transform& T)
{
b3Transform B;
B.rotation = b3Transpose(T.rotation);
B.position = b3MulT(T.rotation, -T.position);
B.rotation = b3Conjugate(T.rotation);
B.translation = b3MulC(T.rotation, -T.translation);
return B;
}
@ -132,115 +124,43 @@ inline b3Transform operator*(const b3Transform& A, const b3Transform& B)
return b3Mul(A, B);
}
// A quaternion-based transform.
struct b3TransformQT
{
// Default ctor does nothing for performance.
b3TransformQT() { }
// Set this transform from a rotation matrix and a translation vector.
b3TransformQT(const b3Mat33& _rotation, const b3Vec3& _translation)
{
rotation = b3Mat33Quat(_rotation);
translation = _translation;
}
// Set this transform to the identity transform.
void SetIdentity()
{
rotation.SetIdentity();
translation.SetZero();
}
b3Quat rotation;
b3Vec3 translation;
};
// Convert a quaternion based transform to a matrix based transform.
inline b3Transform b3ConvertToTransform(const b3TransformQT& T)
{
return b3Transform(T.rotation, T.translation);
}
// Multiply a transform times another transform.
inline b3TransformQT b3Mul(const b3TransformQT& A, const b3TransformQT& B)
{
b3TransformQT C;
C.rotation = b3Mul(A.rotation, B.rotation);
C.translation = b3Mul(A.rotation, B.translation) + A.translation;
return C;
}
// Multiply the transpose of one transform (inverse
// transform) times another transform (composed transform).
inline b3TransformQT b3MulT(const b3TransformQT& A, const b3TransformQT& B)
{
b3TransformQT C;
C.rotation = b3MulT(A.rotation, B.rotation);
C.translation = b3MulT(A.rotation, B.translation - A.translation);
return C;
}
inline b3TransformQT operator*(const b3TransformQT& A, const b3TransformQT& B)
{
return b3Mul(A, B);
}
// Inverse transform a vector.
inline b3Vec3 b3MulT(const b3TransformQT& A, const b3Vec3& v)
{
return b3MulT(A.rotation, v - A.translation);
}
// Inverse transform.
inline b3TransformQT b3Inverse(const b3TransformQT& T)
{
b3TransformQT B;
B.rotation = b3Conjugate(T.rotation);
B.translation = b3MulT(T.rotation, -T.translation);
return B;
}
// Motion proxy for TOI computation.
struct b3Sweep
{
// Get this sweep transform at a given time between [0, 1]
b3Transform GetTransform(float32 t) const;
// Advance to a new initial state.
void Advance(float32 t);
b3Transform GetTransform(scalar t) const;
b3Vec3 localCenter; // local center
b3Quat orientation0; // last orientation
b3Vec3 worldCenter0; // last world center
float32 t0; // last fraction between [0, 1]
scalar t0; // last fraction between [0, 1]
b3Quat orientation; // world orientation
b3Vec3 worldCenter; // world center
};
inline b3Transform b3Sweep::GetTransform(float32 t) const
inline b3Transform b3Sweep::GetTransform(scalar t) const
{
b3Vec3 c = (1.0f - t) * worldCenter0 + t * worldCenter;
b3Quat q = (1.0f - t) * orientation0 + t * orientation;
b3Vec3 c = (scalar(1) - t) * worldCenter0 + t * worldCenter;
b3Quat q1 = orientation0;
b3Quat q2 = orientation;
if (b3Dot(q1, q2) < scalar(0))
{
q1 = -q1;
}
b3Quat q = (scalar(1) - t) * q1 + t * q2;
q.Normalize();
b3Transform xf;
xf.rotation = b3QuatMat33(q);
xf.position = c - b3Mul(q, localCenter);
xf.translation = c - b3Mul(q, localCenter);
xf.rotation = q;
return xf;
}
inline void b3Sweep::Advance(float32 t)
{
B3_ASSERT(t < 1.0f);
float32 dt = (t - t0) / (1.0f / t0);
worldCenter += dt * (worldCenter - worldCenter0);
orientation += dt * (orientation - orientation0);
orientation.Normalize();
t0 = t;
}
#endif

View File

@ -28,13 +28,13 @@ struct b3Vec2
b3Vec2() { }
// Set this vector from two components.
b3Vec2(float32 _x, float32 _y) : x(_x), y(_y) { }
b3Vec2(scalar _x, scalar _y) : x(_x), y(_y) { }
// Read an indexed component from this vector.
float32 operator[](u32 i) const { return (&x)[i]; }
scalar operator[](u32 i) const { return (&x)[i]; }
// Write an indexed component to this vector.
float32& operator[](u32 i) { return (&x)[i]; }
scalar& operator[](u32 i) { return (&x)[i]; }
// Add a vector to this vector.
void operator+=(const b3Vec2& v)
@ -51,14 +51,14 @@ struct b3Vec2
}
// Scale this vector.
void operator*=(float32 s)
void operator*=(scalar s)
{
x *= s;
y *= s;
}
// Scale this vector.
void operator/=(float32 s)
void operator/=(scalar s)
{
x /= s;
y /= s;
@ -67,11 +67,11 @@ struct b3Vec2
// Set this vector to the zero vector.
void SetZero()
{
x = y = 0.0f;
x = y = scalar(0);
}
// Set this vector from two components.
void Set(float32 _x, float32 _y)
void Set(scalar _x, scalar _y)
{
x = _x;
y = _y;
@ -80,7 +80,7 @@ struct b3Vec2
// Normalize this vector.
void Normalize()
{
float32 s = b3Sqrt(x * x + y * y);
scalar s = b3Sqrt(x * x + y * y);
if (s > B3_EPSILON)
{
x /= s;
@ -88,7 +88,7 @@ struct b3Vec2
}
}
float32 x, y;
scalar x, y;
};
// Zero vector
@ -119,49 +119,55 @@ inline b3Vec2 operator-(const b3Vec2& a, const b3Vec2& b)
}
// Multiply a vector by a scalar.
inline b3Vec2 operator*(float32 s, const b3Vec2& v)
inline b3Vec2 operator*(scalar s, const b3Vec2& v)
{
return b3Vec2(s * v.x, s * v.y);
}
// Multiply a vector by a scalar.
inline b3Vec2 operator*(const b3Vec2& v, float32 s)
inline b3Vec2 operator*(const b3Vec2& v, scalar s)
{
return s * v;
}
// Compute the dot product of two vectors.
inline float32 b3Dot(const b3Vec2& a, const b3Vec2& b)
inline scalar b3Dot(const b3Vec2& a, const b3Vec2& b)
{
return a.x * b.x + a.y * b.y;
}
// Compute the length of a vector.
inline float32 b3Length(const b3Vec2& v)
inline scalar b3Length(const b3Vec2& v)
{
return b3Sqrt(v.x * v.x + v.y * v.y);
}
// Compute the squared length of a vector.
inline scalar b3LengthSquared(const b3Vec2& v)
{
return v.x * v.x + v.y * v.y;
}
// Normalize a vector.
inline b3Vec2 b3Normalize(const b3Vec2& v)
{
float32 length = b3Length(v);
scalar length = b3Length(v);
if (length > B3_EPSILON)
{
float32 s = 1.0f / length;
scalar s = scalar(1) / length;
return s * v;
}
return v;
}
// Compute the euclidean distance between two points.
inline float32 b3Distance(const b3Vec2& a, const b3Vec2& b)
inline scalar b3Distance(const b3Vec2& a, const b3Vec2& b)
{
return b3Length(a - b);
}
// Compute the determinant of two 2D vectors.
inline float32 b3Det(const b3Vec2& a, const b3Vec2& b)
inline scalar b3Det(const b3Vec2& a, const b3Vec2& b)
{
return a.x * b.y - a.y * b.x;
}

View File

@ -28,16 +28,16 @@ struct b3Vec3
b3Vec3() { }
// Set this vector from three components.
b3Vec3(float32 _x, float32 _y, float32 _z) : x(_x), y(_y), z(_z) { }
b3Vec3(scalar _x, scalar _y, scalar _z) : x(_x), y(_y), z(_z) { }
// Read an indexed component from this vector.
float32 operator[](u32 i) const
scalar operator[](u32 i) const
{
return (&x)[i];
}
// Write an indexed component to this vector.
float32& operator[](u32 i)
scalar& operator[](u32 i)
{
return (&x)[i];
}
@ -59,7 +59,7 @@ struct b3Vec3
}
// Scale this vector.
void operator*=(float32 s)
void operator*=(scalar s)
{
x *= s;
y *= s;
@ -67,9 +67,9 @@ struct b3Vec3
}
// Scale this vector.
void operator/=(float32 a)
void operator/=(scalar a)
{
float32 s = 1.0f / a;
scalar s = scalar(1) / a;
x *= s;
y *= s;
z *= s;
@ -78,11 +78,11 @@ struct b3Vec3
// Set this vector to the zero vector.
void SetZero()
{
x = y = z = 0.0f;
x = y = z = scalar(0);
}
// Set this vector from three coordinates.
void Set(float32 _x, float32 _y, float32 _z)
void Set(scalar _x, scalar _y, scalar _z)
{
x = _x;
y = _y;
@ -90,12 +90,12 @@ struct b3Vec3
}
// Convert this vector to the unit vector. Return the length.
float32 Normalize()
scalar Normalize()
{
float32 length = b3Sqrt(x * x + y * y + z * z);
scalar length = b3Sqrt(x * x + y * y + z * z);
if (length > B3_EPSILON)
{
float32 s = 1.0f / length;
scalar s = scalar(1) / length;
x *= s;
y *= s;
z *= s;
@ -103,7 +103,7 @@ struct b3Vec3
return length;
}
float32 x, y, z;
scalar x, y, z;
};
// Zero vector
@ -137,25 +137,25 @@ inline b3Vec3 operator-(const b3Vec3& a, const b3Vec3& b)
}
// Compute a scalar-vector product.
inline b3Vec3 operator*(float32 s, const b3Vec3& v)
inline b3Vec3 operator*(scalar s, const b3Vec3& v)
{
return b3Vec3(s * v.x, s * v.y, s * v.z);
}
// Compute a scalar-vector product.
inline b3Vec3 operator*(const b3Vec3& v, float32 s)
inline b3Vec3 operator*(const b3Vec3& v, scalar s)
{
return s * v;
}
// Inverse multiply a scalar-vector.
inline b3Vec3 operator/(const b3Vec3& v, float32 s)
inline b3Vec3 operator/(const b3Vec3& v, scalar s)
{
return b3Vec3(v.x / s, v.y / s, v.z / s);
}
// Compute the dot-product of two vectors.
inline float32 b3Dot(const b3Vec3& a, const b3Vec3& b)
inline scalar b3Dot(const b3Vec3& a, const b3Vec3& b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
@ -168,19 +168,19 @@ inline b3Vec3 b3Cross(const b3Vec3& a, const b3Vec3& b)
// Compute the determinant of a matrix whose columns are three given vectors.
// Useful property: det(a, b, c) = det(c, a, b) = det(b, c, a).
inline float32 b3Det(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c)
inline scalar b3Det(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c)
{
return b3Dot(a, b3Cross(b, c));
}
// Compute the length of a vector.
inline float32 b3Length(const b3Vec3& v)
inline scalar b3Length(const b3Vec3& v)
{
return b3Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
// Compute the squared length of a vector.
inline float32 b3LengthSquared(const b3Vec3& v)
inline scalar b3LengthSquared(const b3Vec3& v)
{
return v.x * v.x + v.y * v.y + v.z * v.z;
}
@ -188,54 +188,53 @@ inline float32 b3LengthSquared(const b3Vec3& v)
// Compute the normalized vector of a (non-zero!) vector.
inline b3Vec3 b3Normalize(const b3Vec3& v)
{
float32 length = b3Length(v);
scalar length = b3Length(v);
if (length > B3_EPSILON)
{
float32 s = 1.0f / length;
scalar s = scalar(1) / length;
return s * v;
}
return v;
}
// Compute the euclidean distance between two points.
inline float32 b3Distance(const b3Vec3& a, const b3Vec3& b)
inline scalar b3Distance(const b3Vec3& a, const b3Vec3& b)
{
return b3Length(a - b);
}
// Compute the squared distance between two points.
inline float32 b3DistanceSquared(const b3Vec3& a, const b3Vec3& b)
inline scalar b3DistanceSquared(const b3Vec3& a, const b3Vec3& b)
{
b3Vec3 v = a - b;
return b3LengthSquared(v);
return b3LengthSquared(a - b);
}
// Compute the triangle area.
inline float32 b3Area(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c)
inline scalar b3Area(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c)
{
return 0.5f * b3Length(b3Cross(b - a, c - a));
return scalar(0.5) * b3Length(b3Cross(b - a, c - a));
}
// Compute the squared triangle area.
inline float32 b3AreaSquared(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c)
inline scalar b3AreaSquared(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c)
{
return 0.25f * b3LengthSquared(b3Cross(b - a, c - a));
return scalar(0.25) * b3LengthSquared(b3Cross(b - a, c - a));
}
// Compute the tetrahedron volume.
inline float32 b3Volume(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c, const b3Vec3& d)
// Compute the positive tetrahedron volume.
inline scalar b3Volume(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c, const b3Vec3& d)
{
float32 volume = b3Det(b - a, c - a, d - a);
// Force a positive volume.
float32 sign = b3Sign(volume);
const float32 inv6 = 1.0f / 6.0f;
const scalar inv6 = scalar(1) / scalar(6);
scalar volume = b3Det(b - a, c - a, d - a);
scalar sign = b3Sign(volume);
return sign * inv6 * volume;
}
// Compute the squared tetrahedron volume.
inline float32 b3VolumeSquared(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c, const b3Vec3& d)
inline scalar b3VolumeSquared(const b3Vec3& a, const b3Vec3& b, const b3Vec3& c, const b3Vec3& d)
{
float32 volume = b3Volume(a, b, c, d);
scalar volume = b3Volume(a, b, c, d);
return volume * volume;
}
@ -251,19 +250,41 @@ inline b3Vec3 b3Max(const b3Vec3& a, const b3Vec3& b)
return b3Vec3(b3Max(a.x, b.x), b3Max(a.y, b.y), b3Max(a.z, b.z));
}
// Find a perpendicular vector to a vector.
// Compute the absolute vector of a given vector (per-element).
inline b3Vec3 b3Abs(const b3Vec3& v)
{
return b3Vec3(b3Abs(v.x), b3Abs(v.y), b3Abs(v.z));
}
// Compute a perpendicular unit vector to a given unit vector.
inline b3Vec3 b3Perp(const b3Vec3& v)
{
// Box2D
// Suppose vector a has all equal components and is a unit vector: a = (s, s, s)
// Then 3*s*s = 1, s = sqrt(1/3) = 0.57735. This means that at least one component of a
// unit vector must be greater or equal to 0.57735.
if (b3Abs(v.x) >= float32(0.57735027))
static const scalar sqrt_inv3 = b3Sqrt(scalar(1) / scalar(3));
b3Vec3 u;
if (b3Abs(v.x) >= sqrt_inv3)
{
return b3Vec3(v.y, -v.x, 0.0f);
u.Set(v.y, -v.x, scalar(0));
}
else
{
u.Set(scalar(0), v.z, -v.y);
}
return b3Vec3(0.0f, v.z, -v.y);
u.Normalize();
return u;
}
// Multiply two vectors component-wise.
inline b3Vec3 b3MulCW(const b3Vec3& a, const b3Vec3& b)
{
return b3Vec3(a.x * b.x, a.y * b.y, a.z * b.z);
}
// Divide two vectors component-wise.
inline b3Vec3 b3DivCW(const b3Vec3& a, const b3Vec3& b)
{
return b3Vec3(a.x / b.x, a.y / b.y, a.z / b.z);
}
#endif

View File

@ -28,7 +28,7 @@ struct b3Vec4
b3Vec4() { }
//
b3Vec4(float32 _x, float32 _y, float32 _z, float32 _w)
b3Vec4(scalar _x, scalar _y, scalar _z, scalar _w)
{
x = _x;
y = _y;
@ -39,13 +39,10 @@ struct b3Vec4
//
void SetZero()
{
x = 0.0f;
y = 0.0f;
z = 0.0f;
w = 0.0f;
x = y = z = w = scalar(0);
}
float32 x, y, z, w;
scalar x, y, z, w;
};
//
@ -61,13 +58,13 @@ inline b3Vec4 operator-(const b3Vec4& a, const b3Vec4& b)
}
//
inline b3Vec4 operator*(float32 s, const b3Vec4& v)
inline b3Vec4 operator*(scalar s, const b3Vec4& v)
{
return b3Vec4(s * v.x, s * v.y, s * v.z, s * v.w);
}
//
inline float32 operator*(const b3Vec4& A, const b3Vec4& B)
inline scalar operator*(const b3Vec4& A, const b3Vec4& B)
{
return A.x * B.x + A.y * B.y + A.z * B.z + A.w * B.w;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_FRAME_ALLOCATOR_H
#define B3_FRAME_ALLOCATOR_H
#include <bounce/common/settings.h>
// Allocate 1 MiB from the stack.
// Increase as you want.
const u32 b3_maxFrameSize = B3_MiB(1);
// A small frame allocator.
class b3FrameAllocator
{
public:
b3FrameAllocator();
~b3FrameAllocator();
// Allocate a block of memory.
// Allocate using b3Alloc if the memory is full.
void* Allocate(u32 size);
// Free the memory if it was allocated by b3Alloc.
void Free(void* q);
// Reset the memory pointer.
// This function should be called at the beginning of a frame.
void Reset();
private:
// Block header
struct b3Block
{
u32 size;
void* p;
bool parent;
};
u8 m_memory[b3_maxFrameSize];
u8* m_p;
u32 m_allocatedSize;
};
#endif

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_PROFILER_H
#define B3_PROFILER_H
#include <bounce/common/math/math.h>
#include <bounce/common/memory/block_pool.h>
#include <bounce/common/time.h>
// Profiler node statistics
struct b3ProfilerNodeStat
{
const char* name;
scalar64 minElapsed;
scalar64 maxElapsed;
b3ProfilerNodeStat* next;
};
// A profiler node
struct b3ProfilerNode
{
const char* name;
scalar64 t0;
scalar64 t1;
scalar64 elapsed; // total elapsed time
u32 callCount; // number of calls inside the parent node
u32 callCountRec; // used for detecting recursive calls
b3ProfilerNode* parent; // parent node
b3ProfilerNode* head; // list of children
b3ProfilerNode* next; // link to the next node in the parent node list of children
b3ProfilerNodeStat* stat; // global node statistics
};
// A hierarchical profiler
class b3Profiler
{
public:
b3Profiler();
~b3Profiler();
// Must be called before profiling.
void Begin();
// Must be called after profiling.
void End();
// Begin a new scope.
void BeginScope(const char* name);
// End the top scope.
void EndScope();
// Get the root node.
b3ProfilerNode* GetRoot() { return m_root; }
// Get the top node.
b3ProfilerNode* GetTop() { return m_top; }
// Get the list of node statistics.
b3ProfilerNodeStat* GetStats() const { return m_stats; }
private:
b3ProfilerNode* CreateNode();
void DestroyNode(b3ProfilerNode* node);
void RecurseDestroyNode(b3ProfilerNode* node);
b3ProfilerNode* FindNode(const char* name);
b3ProfilerNodeStat* CreateStat();
b3ProfilerNodeStat* FindStat(const char* name);
b3BlockPool m_nodePool; // pool of nodes
b3BlockPool m_statPool; // pool of node stats
b3Time m_time; // timer
b3ProfilerNode* m_root; // tree root node
b3ProfilerNode* m_top; // top node
b3ProfilerNodeStat* m_stats; // node stats
};
#endif

View File

@ -31,19 +31,29 @@ typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef unsigned long long u64;
typedef double float64;
typedef float float32;
typedef float scalar;
typedef double scalar64;
// You can modify the following parameters as long
// as you know what you're doing.
#define B3_PI (3.14159265359f)
#define B3_MAX_FLOAT (FLT_MAX)
#define B3_EPSILON (FLT_EPSILON)
#define B3_MAX_U8 (0xFF)
#define B3_MAX_U32 (0xFFFFFFFF)
// This is a scalar type dependent variable.
// If scalar is float, you must set this constant to FLT_MAX.
// If scalar is double, you must set this constant to DBL_MAX.
#define B3_MAX_SCALAR (FLT_MAX)
// This is scalar type dependent variable.
// If scalar is float, you must set this constant to FLT_EPSILON.
// If scalar is double, you must set this constant to DBL_EPSILON.
#define B3_EPSILON (FLT_EPSILON)
// This is scalar type dependent variable.
// This is computed using double precision by default.
#define B3_PI scalar(3.14159265358979323846)
// Collision
// How much an AABB in the broad-phase should be extended by
@ -51,20 +61,19 @@ typedef float float32;
// A larger value increases performance when there are
// no objects closer to the AABB because no contacts are
// even created.
#define B3_AABB_EXTENSION (0.2f)
#define B3_AABB_EXTENSION scalar(0.2)
// This is used to extend AABBs in the broad-phase.
// Is used to predict the future position based on the current displacement.
// This is a dimensionless multiplier.
#define B3_AABB_MULTIPLIER (2.0f)
#define B3_AABB_MULTIPLIER scalar(2)
// Collision and constraint tolerance.
#define B3_LINEAR_SLOP (0.005f)
#define B3_ANGULAR_SLOP (2.0f / 180.0f * B3_PI)
#define B3_LINEAR_SLOP scalar(0.005)
#define B3_ANGULAR_SLOP (scalar(2.0) / scalar(180) * B3_PI)
// The radius of the hull shape skin.
#define B3_HULL_RADIUS (0.0f * B3_LINEAR_SLOP)
#define B3_HULL_RADIUS_SUM (2.0f * B3_HULL_RADIUS)
#define B3_HULL_RADIUS (scalar(0.0) * B3_LINEAR_SLOP)
// Dynamics
@ -82,32 +91,30 @@ typedef float float32;
// Maximum translation per step to prevent numerical instability
// due to large linear velocity.
#define B3_MAX_TRANSLATION (2.0f)
#define B3_MAX_TRANSLATION scalar(2.0)
#define B3_MAX_TRANSLATION_SQUARED (B3_MAX_TRANSLATION * B3_MAX_TRANSLATION)
// Maximum rotation per step to prevent numerical instability due to
// large angular velocity.
#define B3_MAX_ROTATION (0.5f * B3_PI)
#define B3_MAX_ROTATION (scalar(0.5) * B3_PI)
#define B3_MAX_ROTATION_SQUARED (B3_MAX_ROTATION * B3_MAX_ROTATION)
// The maximum position correction used when solving constraints. This helps to
// prevent overshoot.
#define B3_MAX_LINEAR_CORRECTION (0.2f)
#define B3_MAX_ANGULAR_CORRECTION (8.0f / 180.0f * B3_PI)
#define B3_MAX_LINEAR_CORRECTION scalar(0.2)
#define B3_MAX_ANGULAR_CORRECTION (scalar(8.0) / scalar(180) * B3_PI)
// This controls how faster overlaps should be resolved per step.
// This is less than and would be close to 1, so that the all overlap is resolved per step.
// However values very close to 1 may lead to overshoot.
#define B3_BAUMGARTE (0.1f)
#define B3_BAUMGARTE scalar(0.1)
// If the relative velocity of a contact point is below
// the threshold then restitution is not applied.
#define B3_VELOCITY_THRESHOLD (1.0f)
#define B3_VELOCITY_THRESHOLD scalar(1.0)
// Sleep
#define B3_TIME_TO_SLEEP (0.2f)
#define B3_SLEEP_LINEAR_TOL (0.05f)
#define B3_SLEEP_ANGULAR_TOL (2.0f / 180.0f * B3_PI)
// Time to sleep in seconds
#define B3_TIME_TO_SLEEP scalar(0.2)
// Memory

View File

@ -28,7 +28,7 @@ class b3List1
public:
b3List1()
{
m_head = NULL;
m_head = nullptr;
m_count = 0;
}
@ -58,7 +58,7 @@ class b3List2
public:
b3List2()
{
m_head = NULL;
m_head = nullptr;
m_count = 0;
}
@ -66,7 +66,7 @@ public:
void PushFront(T* link)
{
link->m_prev = NULL;
link->m_prev = nullptr;
link->m_next = m_head;
if (m_head)
{
@ -80,9 +80,9 @@ public:
{
link->m_prev = prev;
if (prev->m_next == NULL)
if (prev->m_next == nullptr)
{
link->m_next = NULL;
link->m_next = nullptr;
}
else
{

View File

@ -44,7 +44,7 @@ public:
{
if ((m_count + 1) == N)
{
return NULL;
return nullptr;
}
B3_ASSERT(m_back < N);

View File

@ -41,7 +41,7 @@ public:
{
b3Free(m_elements);
}
m_elements = NULL;
m_elements = nullptr;
}
const T& Top() const

View File

@ -52,13 +52,13 @@ public:
}
// Get the accumulated time in miliseconds from this timer.
float64 GetCurrentMilis() const
double GetCurrentMilis() const
{
return m_t;
}
// Get the elapsed time since this timer was updated.
float64 GetElapsedMilis() const
double GetElapsedMilis() const
{
return m_t - m_t0;
}
@ -66,37 +66,37 @@ public:
// Add the elapsed time since this function was called to this timer.
void Update()
{
static float64 inv_frequency = 0.0;
static double inv_frequency = 0.0;
if (inv_frequency == 0.0)
{
LARGE_INTEGER c;
QueryPerformanceFrequency(&c);
float64 cycles_per_s = float64(c.QuadPart);
float64 s_per_cycle = 1.0 / cycles_per_s;
float64 ms_per_cycle = 1000.0 * s_per_cycle;
double cycles_per_s = double(c.QuadPart);
double s_per_cycle = 1.0 / cycles_per_s;
double ms_per_cycle = 1000.0 * s_per_cycle;
inv_frequency = ms_per_cycle;
}
LARGE_INTEGER c;
QueryPerformanceCounter(&c);
float64 dt = inv_frequency * float64(c.QuadPart - m_c0);
double dt = inv_frequency * double(c.QuadPart - m_c0);
m_c0 = c.QuadPart;
Add(dt);
}
// Add time to this timer.
void Add(float64 dt)
void Add(double dt)
{
m_t0 = m_t;
m_t += dt;
}
private:
u64 m_c0;
float64 m_t0;
float64 m_t;
LONGLONG m_c0;
double m_t0;
double m_t;
};
#elif B3_PLATFORM == B3_MAC
@ -190,7 +190,7 @@ public:
{
struct timespec c;
clock_gettime(CLOCK_MONOTONIC, &c);
double dt = (double)(c.tv_nsec - m_c0.tv_nsec) * 1.0e-6;
double dt = 1000.0 * double(c.tv_sec - m_c0.tv_sec) + 1.0e-6 * double(c.tv_nsec - m_c0.tv_nsec);
m_c0 = c;
Add(dt);
}

View File

@ -50,17 +50,20 @@ struct b3BodyDef
{
type = e_staticBody;
awake = true;
allowSleep = true;
fixedRotationX = false;
fixedRotationY = false;
fixedRotationZ = false;
userData = NULL;
userData = nullptr;
position.SetZero();
orientation.SetIdentity();
linearVelocity.SetZero();
angularVelocity.SetZero();
gravityScale = 1.0f;
linearDamping = 0.0f;
angularDamping = 0.0f;
gravityScale.Set(scalar(1), scalar(1), scalar(1));
linearDamping.SetZero();
angularDamping.SetZero();
linearSleepTolerance = scalar(0.05);
angularSleepTolerance = scalar(2) / scalar(180) * B3_PI;
}
//
@ -69,6 +72,9 @@ struct b3BodyDef
//
bool awake;
//
bool allowSleep;
//
bool fixedRotationX;
@ -94,13 +100,19 @@ struct b3BodyDef
b3Vec3 angularVelocity;
//
float32 linearDamping;
b3Vec3 linearDamping;
//
float32 angularDamping;
b3Vec3 angularDamping;
//
float32 gravityScale;
b3Vec3 gravityScale;
//
scalar linearSleepTolerance;
//
scalar angularSleepTolerance;
};
class b3Body
@ -127,6 +139,10 @@ public:
// Therefore you can create shapes on the stack memory.
b3Shape* CreateShape(const b3ShapeDef& def);
// Get the list of all joints connected to this body.
const b3List2<b3JointEdge>& GetJointList() const;
b3List2<b3JointEdge>& GetJointList();
// Destroy a given shape from the body.
void DestroyShape(b3Shape* shape);
@ -135,11 +151,14 @@ public:
// Get the body world transform.
const b3Transform& GetTransform() const;
// Set the body world transform from a position, axis of rotation and an angle
// of rotation about the axis.
// Set the body world transform from a position and orientation quaternion.
// However, manipulating a body transform during the simulation may cause non-physical behaviour.
void SetTransform(const b3Vec3& position, const b3Vec3& axis, float32 angle);
void SetTransform(const b3Vec3& position, const b3Quat& orientation);
// Set the body world transform from a position and orientation matrix.
// However, manipulating a body transform during the simulation may cause non-physical behaviour.
void SetTransform(const b3Vec3& position, const b3Mat33& orientation);
// Get the position of the world body origin.
b3Vec3 GetPosition() const;
@ -195,10 +214,10 @@ public:
void ApplyAngularImpulse(const b3Vec3& impulse, bool wake);
// Get the mass of the body. Typically in kg/m^3.
float32 GetMass() const;
scalar GetMass() const;
// Get the inverse mass of the body. Typically in kg/m^3.
float32 GetInverseMass() const;
scalar GetInverseMass() const;
// Get the rotational inertia of the body about the local center of mass. Typically in kg/m^3.
const b3Mat33& GetInertia() const;
@ -221,13 +240,13 @@ public:
void ResetMass();
// Get the linear kinetic energy of the body in Joules (kg m^2/s^2).
float32 GetLinearEnergy() const;
scalar GetLinearEnergy() const;
// Get the angular kinetic energy of the body in Joules (kg m^2/s^2).
float32 GetAngularEnergy() const;
scalar GetAngularEnergy() const;
// Get the total kinetic energy of the body in Joules (kg m^2/s^2).
float32 GetEnergy() const;
scalar GetEnergy() const;
// Transform a vector to the local space of this body.
b3Vec3 GetLocalVector(const b3Vec3& vector) const;
@ -241,6 +260,12 @@ public:
// Transform a point to the world space.
b3Vec3 GetWorldPoint(const b3Vec3& localPoint) const;
// Transform a frame to the local space of this body.
b3Quat GetLocalFrame(const b3Quat& frame) const;
// Transform a frame to the world space.
b3Quat GetWorldFrame(const b3Quat& localFrame) const;
// Transform a frame to the local space of this body.
b3Transform GetLocalFrame(const b3Transform& frame) const;
@ -248,22 +273,22 @@ public:
b3Transform GetWorldFrame(const b3Transform& localFrame) const;
// Get the linear damping of the body.
float32 GetLinearDamping() const;
const b3Vec3& GetLinearDamping() const;
// Set the linear damping of the body. Zero is set by default.
void SetLinearDamping(float32 damping);
void SetLinearDamping(const b3Vec3& damping);
// Get the angular damping of the body.
float32 GetAngularDamping() const;
const b3Vec3& GetAngularDamping() const;
// Set the angular damping of the body. Zero is set by default.
void SetAngularDamping(float32 damping);
void SetAngularDamping(const b3Vec3& damping);
// Get the gravity scale of the body.
float32 GetGravityScale() const;
const b3Vec3& GetGravityScale() const;
// Set the gravity scale of the body. One is set by default.
void SetGravityScale(float32 scale);
void SetGravityScale(const b3Vec3& scale);
// See if the body is awake.
bool IsAwake() const;
@ -278,6 +303,27 @@ public:
// Set the user data to the body.
void SetUserData(void* _userData);
// Set the fixed rotation along the world axes.
void SetFixedRotation(bool flagX, bool flagY, bool flagZ);
// Set the linear sleep tolerance in meters per second.
void SetLinearSleepTolerance(scalar tolerance);
// Get the linear sleep tolerance in meters per second.
scalar GetLinearSleepTolerance() const;
// Set the angular sleep tolerance in radians per second.
void SetAngularSleepTolerance(scalar tolerance);
// Get the angular sleep tolerance in radians per second.
scalar GetAngularSleepTolerance() const;
// Set if automatic sleeping is allowed.
void SetSleepingAllowed(bool bit);
// Is automatic sleeping allowed?
bool IsSleepingAllowed() const;
// Get the next body in the world body list.
const b3Body* GetNext() const;
b3Body* GetNext();
@ -303,9 +349,14 @@ private:
friend class b3RevoluteJoint;
friend class b3SphereJoint;
friend class b3ConeJoint;
friend class b3FrictionJoint;
friend class b3MotorJoint;
friend class b3PrismaticJoint;
friend class b3WheelJoint;
friend class b3List2<b3Body>;
friend class b3Cloth;
friend class b3ClothSolver;
friend class b3ClothContactSolver;
@ -317,9 +368,10 @@ private:
{
e_awakeFlag = 0x0001,
e_islandFlag = 0x0002,
e_fixedRotationX = 0x0004,
e_fixedRotationY = 0x0008,
e_fixedRotationZ = 0x0010,
e_autoSleepFlag = 0x0004,
e_fixedRotationX = 0x0008,
e_fixedRotationY = 0x0010,
e_fixedRotationZ = 0x0020
};
b3Body(const b3BodyDef& def, b3World* world);
@ -343,7 +395,11 @@ private:
b3BodyType m_type;
u32 m_islandID;
u32 m_flags;
float32 m_sleepTime;
// Body sleeping
scalar m_linearSleepTolerance;
scalar m_angularSleepTolerance;
scalar m_sleepTime;
// The shapes attached to this body.
b3List1<b3Shape> m_shapeList;
@ -355,10 +411,10 @@ private:
void* m_userData;
// Body mass.
float32 m_mass;
scalar m_mass;
// Inverse body mass.
float32 m_invMass;
scalar m_invMass;
// Inertia about the body local center of mass.
b3Mat33 m_I;
@ -374,9 +430,9 @@ private:
b3Vec3 m_linearVelocity;
b3Vec3 m_angularVelocity;
float32 m_linearDamping;
float32 m_angularDamping;
float32 m_gravityScale;
b3Vec3 m_linearDamping;
b3Vec3 m_angularDamping;
b3Vec3 m_gravityScale;
// Motion proxy for CCD.
b3Sweep m_sweep;
@ -437,30 +493,56 @@ inline b3List1<b3Shape>& b3Body::GetShapeList()
return m_shapeList;
}
inline const b3List2<b3JointEdge>& b3Body::GetJointList() const
{
return m_jointEdges;
}
inline b3List2<b3JointEdge>& b3Body::GetJointList()
{
return m_jointEdges;
}
inline const b3Transform& b3Body::GetTransform() const
{
return m_xf;
}
inline void b3Body::SetTransform(const b3Vec3& position, const b3Vec3& axis, float32 angle)
inline void b3Body::SetTransform(const b3Vec3& position, const b3Quat& orientation)
{
b3Quat q = b3Quat(axis, angle);
m_xf.position = position;
m_xf.rotation = b3QuatMat33(q);
m_xf.translation = position;
m_xf.rotation = orientation;
m_sweep.worldCenter = b3Mul(m_xf, m_sweep.localCenter);
m_sweep.orientation = q;
m_sweep.orientation = orientation;
m_sweep.worldCenter0 = m_sweep.worldCenter;
m_sweep.orientation0 = m_sweep.orientation;
m_worldInvI = b3RotateToFrame(m_invI, orientation);
SynchronizeShapes();
}
inline void b3Body::SetTransform(const b3Vec3& position, const b3Mat33& orientation)
{
m_xf.translation = position;
m_xf.rotation = b3Mat33Quat(orientation);
m_sweep.worldCenter = b3Mul(m_xf, m_sweep.localCenter);
m_sweep.orientation = m_xf.rotation;
m_sweep.worldCenter0 = m_sweep.worldCenter;
m_sweep.orientation0 = m_sweep.orientation;
m_worldInvI = b3RotateToFrame(m_invI, orientation);
SynchronizeShapes();
}
inline b3Vec3 b3Body::GetPosition() const
{
return m_xf.position;
return m_xf.translation;
}
inline b3Quat b3Body::GetOrientation() const
@ -480,7 +562,7 @@ inline b3Vec3 b3Body::GetLocalCenter() const
inline b3Vec3 b3Body::GetLocalVector(const b3Vec3& vector) const
{
return b3MulT(m_xf.rotation, vector);
return b3MulC(m_xf.rotation, vector);
}
inline b3Vec3 b3Body::GetWorldVector(const b3Vec3& localVector) const
@ -498,6 +580,16 @@ inline b3Vec3 b3Body::GetWorldPoint(const b3Vec3& point) const
return b3Mul(m_xf, point);
}
inline b3Quat b3Body::GetLocalFrame(const b3Quat& frame) const
{
return b3MulC(m_sweep.orientation, frame);
}
inline b3Quat b3Body::GetWorldFrame(const b3Quat& localFrame) const
{
return b3Mul(m_sweep.orientation, localFrame);
}
inline b3Transform b3Body::GetLocalFrame(const b3Transform& xf) const
{
return b3MulT(m_xf, xf);
@ -525,13 +617,13 @@ inline void b3Body::SetAwake(bool flag)
if (!IsAwake())
{
m_flags |= e_awakeFlag;
m_sleepTime = 0.0f;
m_sleepTime = scalar(0);
}
}
else
{
m_flags &= ~e_awakeFlag;
m_sleepTime = 0.0f;
m_sleepTime = scalar(0);
m_force.SetZero();
m_torque.SetZero();
m_linearVelocity.SetZero();
@ -539,32 +631,32 @@ inline void b3Body::SetAwake(bool flag)
}
}
inline float32 b3Body::GetLinearDamping() const
inline const b3Vec3& b3Body::GetLinearDamping() const
{
return m_linearDamping;
}
inline void b3Body::SetLinearDamping(float32 damping)
inline void b3Body::SetLinearDamping(const b3Vec3& damping)
{
m_linearDamping = damping;
}
inline float32 b3Body::GetAngularDamping() const
inline const b3Vec3& b3Body::GetAngularDamping() const
{
return m_angularDamping;
}
inline void b3Body::SetAngularDamping(float32 damping)
inline void b3Body::SetAngularDamping(const b3Vec3& damping)
{
m_angularDamping = damping;
}
inline float32 b3Body::GetGravityScale() const
inline const b3Vec3& b3Body::GetGravityScale() const
{
return m_gravityScale;
}
inline void b3Body::SetGravityScale(float32 scale)
inline void b3Body::SetGravityScale(const b3Vec3& scale)
{
if (m_type != e_staticBody)
{
@ -589,7 +681,7 @@ inline void b3Body::SetLinearVelocity(const b3Vec3& linearVelocity)
return;
}
if (b3Dot(linearVelocity, linearVelocity) > 0.0f)
if (b3Dot(linearVelocity, linearVelocity) > scalar(0))
{
SetAwake(true);
}
@ -609,7 +701,7 @@ inline void b3Body::SetAngularVelocity(const b3Vec3& angularVelocity)
return;
}
if (b3Dot(angularVelocity, angularVelocity) > 0.0f)
if (b3Dot(angularVelocity, angularVelocity) > scalar(0))
{
SetAwake(true);
}
@ -617,12 +709,12 @@ inline void b3Body::SetAngularVelocity(const b3Vec3& angularVelocity)
m_angularVelocity = angularVelocity;
}
inline float32 b3Body::GetMass() const
inline scalar b3Body::GetMass() const
{
return m_mass;
}
inline float32 b3Body::GetInverseMass() const
inline scalar b3Body::GetInverseMass() const
{
return m_invMass;
}
@ -637,24 +729,24 @@ inline const b3Mat33& b3Body::GetInertia() const
return m_I;
}
inline float32 b3Body::GetLinearEnergy() const
inline scalar b3Body::GetLinearEnergy() const
{
b3Vec3 P = m_mass * m_linearVelocity;
return b3Dot(P, m_linearVelocity);
}
inline float32 b3Body::GetAngularEnergy() const
inline scalar b3Body::GetAngularEnergy() const
{
b3Mat33 I = b3RotateToFrame(m_I, m_xf.rotation);
b3Vec3 L = I * m_angularVelocity;
return b3Dot(L, m_angularVelocity);
}
inline float32 b3Body::GetEnergy() const
inline scalar b3Body::GetEnergy() const
{
float32 e1 = GetLinearEnergy();
float32 e2 = GetAngularEnergy();
return 0.5f * (e1 + e2);
scalar e1 = GetLinearEnergy();
scalar e2 = GetAngularEnergy();
return scalar(0.5) * (e1 + e2);
}
inline void b3Body::ApplyForce(const b3Vec3& force, const b3Vec3& point, bool wake)
@ -749,4 +841,32 @@ inline void b3Body::ApplyAngularImpulse(const b3Vec3& impulse, bool wake)
}
}
inline scalar b3Body::GetLinearSleepTolerance() const
{
return m_linearSleepTolerance;
}
inline scalar b3Body::GetAngularSleepTolerance() const
{
return m_angularSleepTolerance;
}
inline void b3Body::SetSleepingAllowed(bool flag)
{
if (flag)
{
m_flags |= e_autoSleepFlag;
}
else
{
m_flags &= ~e_autoSleepFlag;
SetAwake(true);
}
}
inline bool b3Body::IsSleepingAllowed() const
{
return (m_flags & e_autoSleepFlag) == e_autoSleepFlag;
}
#endif

View File

@ -22,9 +22,9 @@
#include <bounce/common/memory/block_pool.h>
#include <bounce/common/template/list.h>
#include <bounce/collision/broad_phase.h>
#include <bounce/dynamics/contacts/contact.h>
class b3Shape;
class b3Contact;
class b3ContactFilter;
class b3ContactListener;
struct b3MeshContactLink;
@ -51,7 +51,8 @@ public:
b3BlockPool m_convexBlocks;
b3BlockPool m_meshBlocks;
b3BlockPool* m_allocators[e_maxContact];
b3BroadPhase m_broadPhase;
b3List2<b3Contact> m_contactList;
b3List2<b3MeshContactLink> m_meshContactList;

View File

@ -27,18 +27,18 @@
// A combination of features used to uniquely identify a vertex on a feature.
struct b3FeaturePair
{
u32 inEdge1; // incoming edge on hull 1
u32 outEdge1; // outgoing edge on hull 1
u32 inEdge2; // incoming edge on hull 2
u32 inEdge1; // incoming side plane edge on hull 1
u32 outEdge1; // outgoing side plane edge on hull 1
u32 inEdge2; // incoming edge on hull 2
u32 outEdge2; // outgoing edge on hull 2
};
inline b3FeaturePair b3MakePair(u32 inEdge1, u32 inEdge2, u32 outEdge1, u32 outEdge2)
inline b3FeaturePair b3MakePair(u32 inEdge1, u32 outEdge1, u32 inEdge2, u32 outEdge2)
{
b3FeaturePair out;
out.inEdge1 = inEdge1;
out.inEdge2 = inEdge2;
out.outEdge1 = outEdge1;
out.inEdge2 = inEdge2;
out.outEdge2 = outEdge2;
return out;
}
@ -57,7 +57,7 @@ typedef b3Array<b3ClipVertex> b3ClipPolygon;
struct b3ClipPlane
{
b3Plane plane;
u32 id;
u32 edge;
};
struct b3Hull;
@ -90,10 +90,10 @@ u32 b3ClipEdgeToFace(b3ClipVertex vOut[2],
// Clip a segment by a hull face (side planes).
// Return the number of output points.
u32 b3ClipEdgeToFace(b3ClipVertex vOut[2],
const b3ClipVertex vIn[2], const b3Transform& xf, float32 r, u32 index, const b3Hull* hull);
const b3ClipVertex vIn[2], const b3Transform& xf, scalar r, u32 index, const b3Hull* hull);
// Clip a polygon by a hull face (side planes).
void b3ClipPolygonToFace(b3ClipPolygon& pOut,
const b3ClipPolygon& pIn, const b3Transform& xf, float32 r, u32 index, const b3Hull* hull);
const b3ClipPolygon& pIn, const b3Transform& xf, scalar r, u32 index, const b3Hull* hull);
#endif

View File

@ -22,14 +22,14 @@
#include <bounce/collision/gjk/gjk.h>
#include <bounce/collision/gjk/gjk_proxy.h>
#include <bounce/collision/sat/sat.h>
#include <bounce/collision/sat/sat_edge_and_hull.h>
#include <bounce/collision/sat/sat_vertex_and_hull.h>
#include <bounce/collision/sat/sat_hull_and_edge.h>
#include <bounce/collision/sat/sat_hull_and_vertex.h>
class b3Shape;
class b3SphereShape;
class b3CapsuleShape;
class b3TriangleShape;
class b3HullShape;
class b3MeshShape;
struct b3Manifold;
@ -70,25 +70,41 @@ void b3CollideSphereAndSphere(b3Manifold& manifold,
const b3Transform& xf1, const b3SphereShape* shape1,
const b3Transform& xf2, const b3SphereShape* shape2);
// Compute a manifold for a sphere and a hull.
void b3CollideSphereAndHull(b3Manifold& manifold,
const b3Transform& xf1, const b3SphereShape* shape1,
const b3Transform& xf2, const b3HullShape* shape2);
// Compute a manifold for a sphere and a capsule.
void b3CollideSphereAndCapsule(b3Manifold& manifold,
const b3Transform& xf1, const b3SphereShape* shape1,
const b3Transform& xf2, const b3CapsuleShape* shape2);
// Compute a manifold for a capsule and a sphere.
void b3CollideCapsuleAndSphere(b3Manifold& manifold,
const b3Transform& xf1, const b3CapsuleShape* shape1,
const b3Transform& xf2, const b3SphereShape* shape2);
// Compute a manifold for two capsules.
void b3CollideCapsuleAndCapsule(b3Manifold& manifold,
const b3Transform& xf1, const b3CapsuleShape* shape1,
const b3Transform& xf2, const b3CapsuleShape* shape2);
// Compute a manifold for a capsule and a hull.
void b3CollideCapsuleAndHull(b3Manifold& manifold,
const b3Transform& xf1, const b3CapsuleShape* shape1,
const b3Transform& xf2, const b3HullShape* shape2);
// Compute a manifold for a triangle and a sphere.
void b3CollideTriangleAndSphere(b3Manifold& manifold,
const b3Transform& xf1, const b3TriangleShape* shape1,
const b3Transform& xf2, const b3SphereShape* shape2);
// Compute a manifold for a triangle and a capsule.
void b3CollideTriangleAndCapsule(b3Manifold& manifold,
const b3Transform& xf1, const b3TriangleShape* shape1,
const b3Transform& xf2, const b3CapsuleShape* shape2);
// Compute a manifold for a triangle and a hull.
void b3CollideTriangleAndHull(b3Manifold& manifold,
const b3Transform& xf1, const b3TriangleShape* shape1,
const b3Transform& xf2, const b3HullShape* shape2,
b3ConvexCache* cache);
// Compute a manifold for a hull and a sphere.
void b3CollideHullAndSphere(b3Manifold& manifold,
const b3Transform& xf1, const b3HullShape* shape1,
const b3Transform& xf2, const b3SphereShape* shape2);
// Compute a manifold for a hull and a capsule.
void b3CollideHullAndCapsule(b3Manifold& manifold,
const b3Transform& xf1, const b3HullShape* shape1,
const b3Transform& xf2, const b3CapsuleShape* shape2);
// Compute a manifold for two hulls.
void b3CollideHullAndHull(b3Manifold& manifold,

View File

@ -22,8 +22,11 @@
#include <bounce/common/math/math.h>
#include <bounce/common/template/list.h>
#include <bounce/common/template/array.h>
#include <bounce/dynamics/shapes/shape.h>
#include <bounce/dynamics/contacts/manifold.h>
class b3BlockPool;
class b3Shape;
class b3Body;
class b3Contact;
@ -53,12 +56,6 @@ struct b3OverlappingPair
b3ContactEdge edgeB;
};
// todo
struct b3TOIEvent
{
float32 t;
};
enum b3ContactType
{
e_convexContact,
@ -66,6 +63,23 @@ enum b3ContactType
e_maxContact
};
typedef b3Contact* b3ContactCreateFcn(b3Shape* shapeA, b3Shape* shapeB, b3BlockPool* allocator);
typedef void b3ContactDestroyFcn(b3Contact* contact, b3BlockPool* allocator);
struct b3ContactRegister
{
b3ContactRegister()
{
createFcn = nullptr;
destroyFcn = nullptr;
}
b3ContactType contactType;
b3ContactCreateFcn* createFcn;
b3ContactDestroyFcn* destroyFcn;
bool primary;
};
class b3Contact
{
public:
@ -96,6 +110,12 @@ public:
// Are the shapes in this contact overlapping?
bool IsOverlapping() const;
// Has this contact at least one sensor shape?
bool IsSensorContact() const;
// Has this contact at least one dynamic body?
bool HasDynamicBody() const;
// Get the next contact in the world contact list.
const b3Contact* GetNext() const;
b3Contact* GetNext();
@ -113,32 +133,42 @@ protected:
e_islandFlag = 0x0002,
};
b3Contact() { }
b3Contact(b3Shape* shapeA, b3Shape* shapeB);
virtual ~b3Contact() { }
static b3ContactRegister s_registers[e_maxShapes][e_maxShapes];
static bool s_initialized;
static void AddPrimaryRegister(b3ContactCreateFcn* createFcn, b3ContactDestroyFcn* destoryFcn,
b3ShapeType type1, b3ShapeType type2,
b3ContactType contactType);
static void InitializePrimaryRegisters();
// Factory create.
static b3Contact* Create(b3Shape* shapeA, b3Shape* shapeB, b3BlockPool* allocators[e_maxContact]);
// Factory destroy.
static void Destroy(b3Contact* contact, b3BlockPool* allocators[e_maxContact]);
// Update the contact state.
void Update(b3ContactListener* listener);
// Test if the shapes in this contact are overlapping.
virtual bool TestOverlap() = 0;
// Initialize contact constraits.
// Initialize contact constraints.
virtual void Collide() = 0;
b3ContactType m_type;
u32 m_flags;
b3OverlappingPair m_pair;
// Collision event from discrete collision to
// discrete physics.
// Contact manifolds.
u32 m_manifoldCapacity;
b3Manifold* m_manifolds;
u32 m_manifoldCount;
// Time of impact event from continuous collision
// to continuous physics.
//b3TOIEvent m_toi;
// Links to the world contact list.
b3Contact* m_prev;
b3Contact* m_next;

View File

@ -81,7 +81,7 @@ public:
//
void Run(b3Manifold mOut[3], u32& numOut,
const b3Manifold* mIn, u32 numIn,
const b3Transform& xfA, float32 radiusA, const b3Transform& xfB, float32 radiusB);
const b3Transform& xfA, scalar radiusA, const b3Transform& xfB, scalar radiusB);
//
void Solve();
@ -97,8 +97,8 @@ private:
u32 m_iterations;
b3StackArray<b3Observation, 32> m_observations;
b3StackArray<b3Cluster, 32> m_clusters;
b3StackArray<b3Observation, 256> m_observations;
b3StackArray<b3Cluster, 256> m_clusters;
};
inline void b3ClusterSolver::AddObservation(const b3Observation& observation)

View File

@ -45,15 +45,15 @@ struct b3PositionConstraintManifold
struct b3ContactPositionConstraint
{
u32 indexA;
float32 invMassA;
scalar invMassA;
b3Mat33 localInvIA;
float32 radiusA;
scalar radiusA;
b3Vec3 localCenterA;
u32 indexB;
b3Vec3 localCenterB;
float32 invMassB;
scalar invMassB;
b3Mat33 localInvIB;
float32 radiusB;
scalar radiusB;
b3PositionConstraintManifold* manifolds;
u32 manifoldCount;
};
@ -64,9 +64,9 @@ struct b3VelocityConstraintPoint
b3Vec3 rB;
b3Vec3 normal;
float32 normalMass;
float32 normalImpulse;
float32 velocityBias;
scalar normalMass;
scalar normalImpulse;
scalar velocityBias;
};
struct b3VelocityConstraintManifold
@ -75,41 +75,32 @@ struct b3VelocityConstraintManifold
b3Vec3 rB;
b3Vec3 normal;
b3Vec3 tangent1;
b3Vec3 tangent2;
//float32 leverArm;
scalar motorImpulse;
scalar motorMass;
scalar motorSpeed;
b3Vec3 tangent1;
scalar tangentSpeed1;
b3Vec3 tangent2;
scalar tangentSpeed2;
b3Mat22 tangentMass;
b3Vec2 tangentImpulse;
float32 motorImpulse;
float32 motorMass;
b3VelocityConstraintPoint* points;
u32 pointCount;
};
// The idea is to allow anything to bounce off an inelastic surface.
inline float32 b3MixRestitution(float32 e1, float32 e2)
{
return b3Max(e1, e2);
}
// The idea is to drive the restitution to zero.
inline float32 b3MixFriction(float32 u1, float32 u2)
{
return b3Sqrt(u1 * u2);
}
struct b3ContactVelocityConstraint
{
u32 indexA;
float32 invMassA;
scalar invMassA;
b3Mat33 invIA;
float32 invMassB;
scalar invMassB;
u32 indexB;
b3Mat33 invIB;
float32 friction;
float32 restitution;
scalar friction;
scalar restitution;
b3VelocityConstraintManifold* manifolds;
u32 manifoldCount;
};
@ -122,9 +113,21 @@ struct b3ContactSolverDef
b3Contact** contacts;
u32 count;
b3StackAllocator* allocator;
float32 dt;
scalar dt;
};
// The idea is to allow anything to bounce off an inelastic surface.
inline scalar b3MixRestitution(scalar e1, scalar e2)
{
return b3Max(e1, e2);
}
// The idea is to drive the restitution to zero.
inline scalar b3MixFriction(scalar u1, scalar u2)
{
return b3Sqrt(u1 * u2);
}
class b3ContactSolver
{
public:
@ -146,7 +149,7 @@ protected:
b3ContactPositionConstraint* m_positionConstraints;
b3ContactVelocityConstraint* m_velocityConstraints;
u32 m_count;
float32 m_dt, m_invDt;
scalar m_dt, m_invDt;
b3StackAllocator* m_allocator;
};

View File

@ -26,8 +26,8 @@
class b3ConvexContact : public b3Contact
{
public:
private:
friend class b3ContactManager;
static b3Contact* Create(b3Shape* shapeA, b3Shape* shapeB, b3BlockPool* allocator);
static void Destroy(b3Contact* contact, b3BlockPool* allocator);
b3ConvexContact(b3Shape* shapeA, b3Shape* shapeB);
~b3ConvexContact() { }

View File

@ -71,8 +71,11 @@ struct b3ManifoldPoint
b3ManifoldPointKey key; // point identifier
float32 normalImpulse; // normal impulse
u32 persisting; // is this point persistent?
scalar normalImpulse; // normal impulse
u64 persistCount; // number of time steps this point is persisting
b3FeaturePair featurePair; // internal use
bool edgeContact; // internal use
};
// A contact manifold is a group of contact points with similar contact normal.
@ -89,21 +92,25 @@ struct b3Manifold
u32 pointCount; // number of manifold points
b3Vec2 tangentImpulse;
float32 motorImpulse;
scalar motorImpulse;
scalar motorSpeed; // target angular speed along the normal
scalar tangentSpeed1; // target speed along the first tangent
scalar tangentSpeed2; // target speed along the second tangent
};
struct b3WorldManifoldPoint
{
void Initialize(const b3ManifoldPoint* p, float32 rA, const b3Transform& xfA, float32 rB, const b3Transform& xfB);
void Initialize(const b3ManifoldPoint* p, scalar rA, const b3Transform& xfA, scalar rB, const b3Transform& xfB);
b3Vec3 point;
b3Vec3 normal;
float32 separation;
scalar separation;
};
struct b3WorldManifold
{
void Initialize(const b3Manifold* m, float32 rA, const b3Transform& xfA, float32 rB, const b3Transform& xfB);
void Initialize(const b3Manifold* m, scalar rA, const b3Transform& xfA, scalar rB, const b3Transform& xfB);
u32 pointCount;
b3WorldManifoldPoint points[B3_MAX_MANIFOLD_POINTS];

View File

@ -22,7 +22,7 @@
#include <bounce/dynamics/contacts/contact.h>
#include <bounce/dynamics/contacts/manifold.h>
#include <bounce/dynamics/contacts/collide/collide.h>
#include <bounce/collision/shapes/aabb3.h>
#include <bounce/collision/shapes/aabb.h>
// This structure helps replicate the convex contact per convex-triangle pair scenario,
// but efficiently. There is no need to store a manifold here since they're reduced
@ -46,10 +46,8 @@ struct b3MeshContactLink
class b3MeshContact : public b3Contact
{
public:
private:
friend class b3ContactManager;
friend class b3List2<b3MeshContact>;
friend class b3StaticTree;
static b3Contact* Create(b3Shape* shapeA, b3Shape* shapeB, b3BlockPool* allocator);
static void Destroy(b3Contact* contact, b3BlockPool* allocator);
b3MeshContact(b3Shape* shapeA, b3Shape* shapeB);
~b3MeshContact();
@ -57,12 +55,10 @@ private:
bool TestOverlap();
void Collide();
void CollideSphere();
void SynchronizeShapes();
bool MoveAABB(const b3AABB3& aabb, const b3Vec3& displacement);
bool MoveAABB(const b3AABB& aabb, const b3Vec3& displacement);
void FindNewPairs();
@ -70,10 +66,10 @@ private:
bool Report(u32 proxyId);
// Did the AABB move significantly?
bool m_aabbMoved;
bool m_aabbBMoved;
// The AABB A relative to shape B's origin.
b3AABB3 m_aabbA;
// The AABB B relative to shape A's origin.
b3AABB m_aabbB;
// Triangles potentially overlapping with the first shape.
u32 m_triangleCapacity;

View File

@ -22,6 +22,7 @@
#include <bounce/common/math/mat33.h>
class b3StackAllocator;
class b3ContactListener;
class b3Contact;
class b3Joint;
class b3Body;
@ -29,10 +30,12 @@ struct b3Velocity;
struct b3Position;
struct b3Profile;
struct b3ContactVelocityConstraint;
class b3Island
{
public :
b3Island(b3StackAllocator* stack, u32 bodyCapacity, u32 contactCapacity, u32 jointCapacity);
b3Island(b3StackAllocator* stack, u32 bodyCapacity, u32 contactCapacity, u32 jointCapacity, b3ContactListener* listener);
~b3Island();
void Clear();
@ -41,7 +44,7 @@ public :
void Add(b3Contact* contact);
void Add(b3Joint* joint);
void Solve(const b3Vec3& gravity, float32 dt, u32 velocityIterations, u32 positionIterations, u32 flags);
void Solve(const b3Vec3& gravity, scalar dt, u32 velocityIterations, u32 positionIterations, u32 flags);
private :
enum b3IslandFlags
{
@ -51,8 +54,11 @@ private :
friend class b3World;
void Report();
b3StackAllocator* m_allocator;
b3ContactListener* m_listener;
b3Body** m_bodies;
u32 m_bodyCapacity;
u32 m_bodyCount;

View File

@ -26,59 +26,84 @@ struct b3ConeJointDef : public b3JointDef
b3ConeJointDef()
{
type = e_coneJoint;
localFrameA.SetIdentity();
localFrameB.SetIdentity();
enableLimit = false;
coneAngle = 0.0f;
localAnchorA.SetZero();
localRotationA.SetIdentity();
localAnchorB.SetZero();
localRotationB.SetIdentity();
referenceRotation.SetIdentity();
enableConeLimit = false;
coneAngle = scalar(0);
enableTwistLimit = false;
lowerAngle = scalar(0);
upperAngle = scalar(0);
}
// Initialize this definition from bodies, cone axis, anchor point, and full cone angle in radians.
void Initialize(b3Body* bodyA, b3Body* bodyB, const b3Vec3& axis, const b3Vec3& anchor, float32 angle);
void Initialize(b3Body* bodyA, b3Body* bodyB, const b3Vec3& axis, const b3Vec3& anchor, scalar coneAngle);
// The joint anchor relative to body A's origin.
b3Vec3 localAnchorA;
// The joint frame relative to body A's frame.
b3Transform localFrameA;
b3Quat localRotationA;
// The joint frame relative to body B's origin.
b3Vec3 localAnchorB;
// The joint frame relative to body B's frame.
b3Transform localFrameB;
b3Quat localRotationB;
// Rotation from A to B in reference state
b3Quat referenceRotation;
// Enable cone angle limit.
bool enableLimit;
bool enableConeLimit;
// The full cone angle in radians.
float32 coneAngle;
scalar coneAngle;
// Enable the twist limit.
bool enableTwistLimit;
// The lower twist angle in radians
scalar lowerAngle;
// The upper twist angle in radians
scalar upperAngle;
};
// This joint constrains the bodies to share a common point (cone tip).
// It also constrains the relative rotation about an axis perpendicular
// to the cone axis.
// You can limit the relative rotation with a cone angle limit.
// This joint can be used to create structures such as ragdolls.
// You can limit the relative rotation around the cone axis with a
// twist limit.
// This joint was designed to create structures such as ragdolls.
class b3ConeJoint : public b3Joint
{
public:
// Get the joint frame on body A in world coordinates.
b3Transform GetFrameA() const;
// Get the joint frame on body B in world coordinates.
b3Transform GetFrameB() const;
// Get the joint frame relative to body A's frame.
const b3Transform& GetLocalFrameA() const;
// Get the joint frame relative to body B's frame.
const b3Transform& GetLocalFrameB() const;
// Is the joint limit enabled?
bool IsLimitEnabled() const;
// Set the joint limit enabled.
void SetEnableLimit(bool bit);
void SetEnableConeLimit(bool bit);
// Get the cone angle in radians.
float32 GetConeAngle() const;
// Is the joint cone limit enabled?
bool IsConeLimitEnabled() const;
// Set the cone angle in radians.
void SetConeAngle(float32 angle);
void SetConeAngle(scalar angle);
// Get the cone angle in radians.
scalar GetConeAngle() const;
// Set the joint twist limit enabled.
void SetEnableTwistLimit(bool bit);
// Is the joint twist limit enabled?
bool IsTwistLimitEnabled() const;
// Set/get the twist angles in radians.
void SetTwistLimits(scalar lowerAngle, scalar upperAngle);
scalar GetTwistLowerAngle() const;
scalar GetTwistUpperAngle() const;
// Draw this joint.
void Draw() const;
@ -98,16 +123,24 @@ private:
virtual bool SolvePositionConstraints(const b3SolverData* data);
// Solver shared
b3Transform m_localFrameA;
b3Transform m_localFrameB;
float32 m_coneAngle;
bool m_enableLimit;
b3Vec3 m_localAnchorA;
b3Quat m_localRotationA;
b3Vec3 m_localAnchorB;
b3Quat m_localRotationB;
b3Quat m_referenceRotation;
scalar m_coneAngle;
bool m_enableConeLimit;
scalar m_lowerAngle;
scalar m_upperAngle;
bool m_enableTwistLimit;
// Solver temp
u32 m_indexA;
u32 m_indexB;
float32 m_mA;
float32 m_mB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
@ -117,17 +150,23 @@ private:
b3Vec3 m_localCenterA;
b3Vec3 m_localCenterB;
// Point-to-point
// Linear
b3Vec3 m_rA;
b3Vec3 m_rB;
b3Mat33 m_mass;
b3Vec3 m_impulse;
// Limit
b3Vec3 m_limitAxis;
float32 m_limitMass;
float32 m_limitImpulse;
b3LimitState m_limitState;
// Cone limit
b3Vec3 m_coneAxis;
scalar m_coneMass;
scalar m_coneImpulse;
b3LimitState m_coneState;
// Twist limit
b3Vec3 m_twistAxis;
scalar m_twistMass;
scalar m_twistImpulse;
b3LimitState m_twistState;
};
#endif

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_FRICTION_JOINT_H
#define B3_FRICTION_JOINT_H
#include <bounce/dynamics/joints/joint.h>
struct b3FrictionJointDef : public b3JointDef
{
b3FrictionJointDef()
{
type = e_frictionJoint;
localAnchorA.SetZero();
localAnchorB.SetZero();
maxForce = scalar(0);
maxTorque = scalar(0);
}
// Initialize this definition from bodies and world anchor point.
void Initialize(b3Body* bodyA, b3Body* bodyB, const b3Vec3& anchor);
// The anchor point relative to body A's origin
b3Vec3 localAnchorA;
// The anchor point relative to body B's origin
b3Vec3 localAnchorB;
// The maximum friction force in N.
scalar maxForce;
// The maximum friction torque in N-m.
scalar maxTorque;
};
// Friction joint.
// This joint provides 3D linear and angular friction.
class b3FrictionJoint : public b3Joint
{
public:
// Get the anchor point on body A in world coordinates.
b3Vec3 GetAnchorA() const;
// Get the anchor point on body B in world coordinates.
b3Vec3 GetAnchorB() const;
// Get the local anchor point relative to body A's origin.
const b3Vec3& GetLocalAnchorA() const
{
return m_localAnchorA;
}
// Get the local anchor point relative to body B's origin.
const b3Vec3& GetLocalAnchorB() const
{
return m_localAnchorB;
}
// Set the maximum friction force in N.
void SetMaxForce(scalar force);
// Get the maximum friction force in N.
scalar GetMaxForce() const;
// Set the maximum friction torque in N*m.
void SetMaxTorque(scalar torque);
// Get the maximum friction torque in N*m.
scalar GetMaxTorque() const;
// Draw this joint.
void Draw() const;
private:
friend class b3Joint;
friend class b3JointManager;
friend class b3JointSolver;
b3FrictionJoint(const b3FrictionJointDef* def);
virtual void InitializeConstraints(const b3SolverData* data);
virtual void WarmStart(const b3SolverData* data);
virtual void SolveVelocityConstraints(const b3SolverData* data);
virtual bool SolvePositionConstraints(const b3SolverData* data);
// Solver shared
b3Vec3 m_localAnchorA;
b3Vec3 m_localAnchorB;
b3Vec3 m_linearImpulse;
b3Vec3 m_angularImpulse;
scalar m_maxForce;
scalar m_maxTorque;
// Solver temp
u32 m_indexA;
u32 m_indexB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
b3Vec3 m_rA;
b3Vec3 m_rB;
b3Mat33 m_linearMass;
b3Mat33 m_angularMass;
};
#endif

View File

@ -37,6 +37,10 @@ enum b3JointType
e_revoluteJoint,
e_sphereJoint,
e_coneJoint,
e_frictionJoint,
e_motorJoint,
e_prismaticJoint,
e_wheelJoint,
e_maxJoints,
};
@ -45,9 +49,9 @@ struct b3JointDef
b3JointDef()
{
type = e_unknownJoint;
bodyA = NULL;
bodyB = NULL;
userData = NULL;
bodyA = nullptr;
bodyB = nullptr;
userData = nullptr;
collideLinked = false;
}

View File

@ -34,7 +34,7 @@ struct b3Jacobian
struct b3JointSolverDef
{
float32 dt;
scalar dt;
u32 count;
b3Joint** joints;
b3Position* positions;

View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_MOTOR_JOINT_H
#define B3_MOTOR_JOINT_H
#include <bounce/dynamics/joints/joint.h>
// Motor joint definition.
struct b3MotorJointDef : public b3JointDef
{
b3MotorJointDef()
{
type = e_motorJoint;
linearOffset.SetZero();
angularOffset.SetIdentity();
maxForce = scalar(0);
maxTorque = scalar(0);
correctionFactor = 0.2f;
}
// Initialize the bodies and offsets using the current transforms.
void Initialize(b3Body* bodyA, b3Body* bodyB);
// Position of body B minus the position of body A, relative body A's origin, in meters.
b3Vec3 linearOffset;
// The body B rotation minus body A rotation.
b3Quat angularOffset;
// Maximum motor force in N.
scalar maxForce;
// Maximum torque in N-m.
scalar maxTorque;
// Position correction factor in the range [0, 1].
scalar correctionFactor;
};
// A motor joint can be used to control the relative movement between two bodies.
// Commonly it is used to control the motion of a dynamic body with respect
// to a static body.
class b3MotorJoint : public b3Joint
{
public:
b3Vec3 GetAnchorA() const;
b3Vec3 GetAnchorB() const;
// Set the target linear offset, in frame A, in meters.
void SetLinearOffset(const b3Vec3& linearOffset);
// Get the target linear offset, in frame A, in meters.
const b3Vec3& GetLinearOffset() const;
// Set the target angular offset, in frame A, in meters.
void SetAngularOffset(const b3Quat& angularOffset);
// Get the target angular offset, in frame A, in meters.
const b3Quat& GetAngularOffset() const;
// Set the maximum friction force in N.
void SetMaxForce(scalar force);
// Get the maximum friction force in N.
scalar GetMaxForce() const;
// Set the maximum friction torque in N-m.
void SetMaxTorque(scalar force);
// Get the maximum friction torque in N-m.
scalar GetMaxTorque() const;
// Set the position correction factor in the range [0, 1].
void SetCorrectionFactor(scalar factor);
// Get the position correction factor in the range [0, 1].
scalar GetCorrectionFactor() const;
// Draw this joint.
void Draw() const;
private:
friend class b3Joint;
friend class b3JointManager;
friend class b3JointSolver;
b3MotorJoint(const b3MotorJointDef* def);
virtual void InitializeConstraints(const b3SolverData* data);
virtual void WarmStart(const b3SolverData* data);
virtual void SolveVelocityConstraints(const b3SolverData* data);
virtual bool SolvePositionConstraints(const b3SolverData* data);
// Solver shared
b3Vec3 m_linearOffset;
b3Quat m_angularOffset;
b3Vec3 m_linearImpulse;
b3Vec3 m_angularImpulse;
scalar m_correctionFactor;
scalar m_maxForce;
scalar m_maxTorque;
// Solver temp
u32 m_indexA;
u32 m_indexB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
b3Vec3 m_localCenterA;
b3Vec3 m_localCenterB;
b3Vec3 m_linearError;
b3Vec3 m_angularVelocity;
b3Vec3 m_rA;
b3Vec3 m_rB;
b3Mat33 m_linearMass;
b3Mat33 m_angularMass;
};
#endif

View File

@ -29,15 +29,27 @@ struct b3MouseJointDef : public b3JointDef
{
type = e_mouseJoint;
target.SetZero();
maxForce = 0.0f;
maxForce = scalar(0);
frequencyHz = scalar(6);
dampingRatio = scalar(0.8);
}
// The initial world target point. Initially is assumed
// to be coincident to the body anchor (satisfied constraint).
// to be coincident to the body anchor.
b3Vec3 target;
// Maximum joint reaction force in newtons.
float32 maxForce;
// Maximum joint reaction force in N.
// Typically this is defined proportional to the body weight
// (k * m * g)
scalar maxForce;
// The mass-spring-damper frequency in Hz
scalar frequencyHz;
// The damping ration in the interval [0, 1]
// 0 = undamped spring
// 1 = critical damping
scalar dampingRatio;
};
// A mouse joint is used to make a local point on a body
@ -56,6 +68,30 @@ public:
// Set the world target point.
void SetTarget(const b3Vec3& target);
// Get the damper frequency in Hz.
scalar GetFrequency() const
{
return m_frequencyHz;
}
// Set the damper frequency in Hz.
void SetFrequency(scalar frequency)
{
m_frequencyHz = frequency;
}
// Get the damping ratio.
scalar GetDampingRatio() const
{
return m_dampingRatio;
}
// Set the damping ratio.
void SetDampingRatio(scalar ratio)
{
m_dampingRatio = ratio;
}
// Draw this joint.
void Draw() const;
@ -74,17 +110,21 @@ private:
// Solver shared
b3Vec3 m_worldTargetA;
b3Vec3 m_localAnchorB;
float32 m_maxForce;
scalar m_maxForce;
scalar m_frequencyHz;
scalar m_dampingRatio;
b3Mat33 m_gamma;
b3Vec3 m_bias;
// Solver temp
u32 m_indexB;
float32 m_mB;
scalar m_mB;
b3Mat33 m_iB;
b3Vec3 m_localCenterB;
b3Mat33 m_mass;
b3Vec3 m_rB;
b3Vec3 m_impulse;
b3Vec3 m_C;
};
#endif

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_PRISMATIC_JOINT_H
#define B3_PRISMATIC_JOINT_H
#include <bounce/dynamics/joints/joint.h>
// Prismatic joint definition.
// This requires defining an axis of motion and an anchor point.
// The definition uses local anchor points and a local axis so that the initial configuration
// can violate the constraint slightly. The joint translation is zero
// when the local anchor points coincide in world space. Using local
// anchors and a local axis helps when saving and loading a game.
struct b3PrismaticJointDef : public b3JointDef
{
b3PrismaticJointDef()
{
type = e_prismaticJoint;
localAnchorA.SetZero();
localAnchorB.SetZero();
localAxisA.Set(scalar(1), scalar(0), scalar(0));
referenceRotation.SetIdentity();
enableLimit = false;
lowerTranslation = scalar(0);
upperTranslation = scalar(0);
enableMotor = false;
maxMotorForce = scalar(0);
motorSpeed = scalar(0);
}
// Initialize the bodies, anchors, axis, and reference angle using the world
// anchor and unit world axis.
void Initialize(b3Body* bodyA, b3Body* bodyB, const b3Vec3& anchor, const b3Vec3& axis);
// The local anchor point relative to bodyA's origin.
b3Vec3 localAnchorA;
// The local anchor point relative to bodyB's origin.
b3Vec3 localAnchorB;
// The local translation unit axis in body A's frame.
b3Vec3 localAxisA;
// The constrained angle between the bodies.
b3Quat referenceRotation;
// Enable/disable the joint limit.
bool enableLimit;
// The lower translation limit, usually in meters.
scalar lowerTranslation;
// The upper translation limit, usually in meters.
scalar upperTranslation;
// Enable/disable the joint motor.
bool enableMotor;
// The maximum motor torque, usually in N-m.
scalar maxMotorForce;
// The desired motor speed in radians per second.
scalar motorSpeed;
};
// A prismatic joint.
// This joint provides translation (one degree of freedom)
// along an axis fixed in body A.
// Relative rotation is prevented.
// You can use a joint limit to restrict the range of motion
// and a joint motor to drive the motion or to model joint friction.
class b3PrismaticJoint : public b3Joint
{
public:
b3Vec3 GetAnchorA() const;
b3Vec3 GetAnchorB() const;
// The local anchor point relative to body A's origin.
const b3Vec3& GetLocalAnchorA() const { return m_localAnchorA; }
// The local anchor point relative to body B's origin.
const b3Vec3& GetLocalAnchorB() const { return m_localAnchorB; }
// The local joint axis relative to bodyA.
const b3Vec3& GetLocalAxisA() const { return m_localXAxisA; }
// Get the reference rotation.
const b3Quat& GetReferenceRotation() const { return m_referenceRotation; }
// Get the current joint translation, usually in meters.
scalar GetJointTranslation() const;
// Get the current joint translation speed, usually in meters per second.
scalar GetJointSpeed() const;
// Is the joint limit enabled?
bool IsLimitEnabled() const;
// Enable/disable the joint limit.
void EnableLimit(bool flag);
// Get the lower joint limit, usually in meters.
scalar GetLowerLimit() const;
// Get the upper joint limit, usually in meters.
scalar GetUpperLimit() const;
// Set the joint limits, usually in meters.
void SetLimits(scalar lower, scalar upper);
// Is the joint motor enabled?
bool IsMotorEnabled() const;
// Enable/disable the joint motor.
void EnableMotor(bool flag);
// Set the motor speed, usually in meters per second.
void SetMotorSpeed(scalar speed);
// Get the motor speed, usually in meters per second.
scalar GetMotorSpeed() const;
// Set the maximum motor force, usually in N.
void SetMaxMotorForce(scalar force);
// Get the maximum motor force, usually in N.
scalar GetMaxMotorForce() const { return m_maxMotorForce; }
// Draw this joint
void Draw() const;
protected:
friend class b3Joint;
b3PrismaticJoint(const b3PrismaticJointDef* def);
void InitializeConstraints(const b3SolverData* data);
void WarmStart(const b3SolverData* data);
void SolveVelocityConstraints(const b3SolverData* data);
bool SolvePositionConstraints(const b3SolverData* data);
// Solver shared
b3Vec3 m_localAnchorA;
b3Vec3 m_localAnchorB;
b3Vec3 m_localXAxisA;
b3Vec3 m_localYAxisA;
b3Vec3 m_localZAxisA;
b3Quat m_referenceRotation;
b3Vec2 m_linearImpulse;
b3Vec3 m_angularImpulse;
scalar m_limitImpulse;
scalar m_motorImpulse;
scalar m_lowerTranslation;
scalar m_upperTranslation;
scalar m_maxMotorForce;
scalar m_motorSpeed;
bool m_enableLimit;
bool m_enableMotor;
b3LimitState m_limitState;
// Solver temp
u32 m_indexA;
u32 m_indexB;
b3Vec3 m_localCenterA;
b3Vec3 m_localCenterB;
b3Mat33 m_localInvIA;
b3Mat33 m_localInvIB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
b3Vec3 m_axis;
b3Vec3 m_a1, m_a2;
scalar m_motorMass;
b3Vec3 m_perp1;
b3Vec3 m_s1, m_s2;
b3Vec3 m_perp2;
b3Vec3 m_s3, m_s4;
b3Mat22 m_linearMass;
b3Mat33 m_angularMass;
};
inline scalar b3PrismaticJoint::GetMotorSpeed() const
{
return m_motorSpeed;
}
#endif

View File

@ -32,15 +32,15 @@ struct b3RevoluteJointDef : public b3JointDef
localRotationB.SetIdentity();
referenceRotation.SetIdentity();
enableLimit = false;
lowerAngle = 0.0f;
upperAngle = 0.0f;
lowerAngle = scalar(0);
upperAngle = scalar(0);
enableMotor = false;
motorSpeed = 0.0f;
maxMotorTorque = 0.0f;
motorSpeed = scalar(0);
maxMotorTorque = scalar(0);
}
// Initialize this definition from hinge axis, anchor point, and the lower and upper angle limits in radians.
void Initialize(b3Body* bodyA, b3Body* bodyB, const b3Vec3& axis, const b3Vec3& anchor, float32 lowerAngle, float32 upperAngle);
void Initialize(b3Body* bodyA, b3Body* bodyB, const b3Vec3& axis, const b3Vec3& anchor, scalar lowerAngle, scalar upperAngle);
// The joint anchor relative body A's origin.
b3Vec3 localAnchorA;
@ -61,19 +61,19 @@ struct b3RevoluteJointDef : public b3JointDef
bool enableLimit;
// The hinge lower angle limit in radians.
float32 lowerAngle;
scalar lowerAngle;
// The hinge upper angle limit in radians.
float32 upperAngle;
scalar upperAngle;
// Enable the joint motor.
bool enableMotor;
// The desired motor speed in radians per second.
float32 motorSpeed;
scalar motorSpeed;
// The maximum motor torque in Newton per meter.
float32 maxMotorTorque;
scalar maxMotorTorque;
};
// A revolute joint constrains two bodies to share a point and an axis while
@ -105,13 +105,13 @@ public:
void SetEnableLimit(bool bit);
// Get the lower angle limit.
float32 GetLowerLimit() const;
scalar GetLowerLimit() const;
// Get the upper angle limit.
float32 GetUpperLimit() const;
scalar GetUpperLimit() const;
// Set the angle limits.
void SetLimits(float32 lowerAngle, float32 upperAngle);
void SetLimits(scalar lowerAngle, scalar upperAngle);
// Is the joint motor enabled?
bool IsMotorEnabled() const;
@ -120,16 +120,16 @@ public:
void SetEnableMotor(bool bit);
// Get the desired motor speed in radians per second.
float32 GetMotorSpeed() const;
scalar GetMotorSpeed() const;
// Set the desired motor speed in radians per second.
void SetMotorSpeed(float32 speed);
void SetMotorSpeed(scalar speed);
// Get the maximum motor torque in Newton per meter.
float32 GetMaxMotorTorque() const;
scalar GetMaxMotorTorque() const;
// Set the maximum motor torque in Newton per meter.
void SetMaxMotorTorque(float32 torque);
void SetMaxMotorTorque(scalar torque);
// Draw this joint.
void Draw() const;
@ -155,18 +155,18 @@ private:
b3Quat m_localRotationB;
bool m_enableMotor;
float32 m_motorSpeed;
float32 m_maxMotorTorque;
scalar m_motorSpeed;
scalar m_maxMotorTorque;
bool m_enableLimit;
float32 m_lowerAngle;
float32 m_upperAngle;
scalar m_lowerAngle;
scalar m_upperAngle;
// Solver temp
u32 m_indexA;
u32 m_indexB;
float32 m_mA;
float32 m_mB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
b3Vec3 m_localCenterA;
@ -174,30 +174,26 @@ private:
b3Mat33 m_localInvIA;
b3Mat33 m_localInvIB;
// Hinge motor
b3Vec3 m_motor_J1; // 1x3 (row)
b3Vec3 m_motor_J2; // 1x3 (row)
float32 m_motorMass;
float32 m_motorImpulse;
// Motor
scalar m_motorMass;
scalar m_motorImpulse;
b3Vec3 m_motorAxis;
// Hinge limit
// The limit axis and constraint space mass are the same as the motor's
b3LimitState m_limitState; // constraint state
float32 m_limitImpulse;
// Angle limit
// This reuses the motor Jacobian and mass
b3LimitState m_limitState;
scalar m_limitImpulse;
// Spherical
// Linear
b3Vec3 m_rA;
b3Vec3 m_rB;
b3Mat33 m_mass;
b3Vec3 m_impulse;
b3Mat33 m_linearMass;
b3Vec3 m_linearImpulse;
// Hinge
b3Mat23 m_J1;
b3Mat23 m_J2;
b3Mat32 m_J1T;
b3Mat32 m_J2T;
b3Mat22 m_K;
b3Vec2 m_axisImpulse;
// Angular
b3Vec3 m_a1, m_a2;
b3Mat22 m_angularMass;
b3Vec2 m_angularImpulse;
};
#endif

View File

@ -51,6 +51,18 @@ public:
// Get the anchor point on body B in world coordinates.
b3Vec3 GetAnchorB() const;
// Get the local anchor point relative to body A's origin.
const b3Vec3& GetLocalAnchorA() const
{
return m_localAnchorA;
}
// Get the local anchor point relative to body B's origin.
const b3Vec3& GetLocalAnchorB() const
{
return m_localAnchorB;
}
// Draw this joint.
void Draw() const;
private:
@ -72,8 +84,8 @@ private:
// Solver temp
u32 m_indexA;
u32 m_indexB;
float32 m_mA;
float32 m_mB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;

View File

@ -28,9 +28,9 @@ struct b3SpringJointDef : public b3JointDef
type = e_springJoint;
localAnchorA.SetZero();
localAnchorB.SetZero();
length = 0.0f;
frequencyHz = 0.0f;
dampingRatio = 0.0f;
length = scalar(0);
frequencyHz = scalar(0);
dampingRatio = scalar(0);
}
// Initialize this definition from bodies and world anchors.
@ -43,16 +43,16 @@ struct b3SpringJointDef : public b3JointDef
b3Vec3 localAnchorB;
// The spring rest length.
float32 length;
scalar length;
// The mass-spring-damper frequency in Hz
// 0 = disable softness
float32 frequencyHz;
scalar frequencyHz;
// The damping ration in the interval [0, 1]
// 0 = undamped spring
// 1 = critical damping
float32 dampingRatio;
scalar dampingRatio;
};
// A spring joint constrains the bodies to rotate relative to each
@ -76,22 +76,22 @@ public:
const b3Vec3& GetLocalAnchorB() const;
// Get the natural spring length.
float32 GetLength() const;
scalar GetLength() const;
// Set the natural spring length.
void SetLength(float32 length);
void SetLength(scalar length);
// Get the damper frequency in Hz.
float32 GetFrequency() const;
scalar GetFrequency() const;
// Set the damper frequency in Hz.
void SetFrequency(float32 frequency);
void SetFrequency(scalar frequency);
// Get the damping ratio.
float32 GetDampingRatio() const;
scalar GetDampingRatio() const;
// Set the damping ratio.
void SetDampingRatio(float32 ratio);
void SetDampingRatio(scalar ratio);
// Draw this joint.
void Draw() const;
@ -110,15 +110,15 @@ private:
// Solver shared
b3Vec3 m_localAnchorA;
b3Vec3 m_localAnchorB;
float32 m_length;
float32 m_frequencyHz;
float32 m_dampingRatio;
scalar m_length;
scalar m_frequencyHz;
scalar m_dampingRatio;
// Solver temp
u32 m_indexA;
u32 m_indexB;
float32 m_mA;
float32 m_mB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
b3Vec3 m_localCenterA;
@ -126,13 +126,13 @@ private:
b3Mat33 m_localInvIA;
b3Mat33 m_localInvIB;
float32 m_bias;
float32 m_gamma;
scalar m_bias;
scalar m_gamma;
b3Vec3 m_n;
b3Vec3 m_rA;
b3Vec3 m_rB;
float32 m_mass;
float32 m_impulse;
scalar m_mass;
scalar m_impulse;
};
#endif

View File

@ -29,6 +29,8 @@ struct b3WeldJointDef : public b3JointDef
localAnchorA.SetZero();
localAnchorB.SetZero();
referenceRotation.SetIdentity();
frequencyHz = scalar(0);
dampingRatio = scalar(0);
}
// Initialize this definition from bodies and world anchor point.
@ -42,20 +44,79 @@ struct b3WeldJointDef : public b3JointDef
// The initial relative rotation from body A to body B.
b3Quat referenceRotation;
// The mass-spring-damper frequency in Hertz.
// Disable softness with a value of 0.
// Rotation only.
scalar frequencyHz;
// The damping ratio.
// 0 = no damping.
// 1 = critical damping.
scalar dampingRatio;
};
// A weld joint removes the relative movement between two bodies.
// You need to specify the relative rotation and the local anchor points.
// @todo Soft this constraint.
class b3WeldJoint : public b3Joint
{
public:
// Set the joint anchor point in world coordinates.
// Calling this function will set the target relative rotation
// from body A to body B using the current body rotations.
void SetAnchor(const b3Vec3& anchor);
// Set the target relative rotation from body A to body B.
void SetReferenceRotation(const b3Quat& referenceRotation);
// Get the anchor point on body A in world coordinates.
b3Vec3 GetAnchorA() const;
// Get the anchor point on body B in world coordinates.
b3Vec3 GetAnchorB() const;
// Get the local anchor point relative to bodyA's origin.
const b3Vec3& GetLocalAnchorA() const
{
return m_localAnchorA;
}
// Get the local anchor point relative to bodyB's origin.
const b3Vec3& GetLocalAnchorB() const
{
return m_localAnchorB;
}
// Get the reference orientation.
const b3Quat& GetReferenceRotation() const
{
return m_referenceRotation;
}
// Set the frequency in Hz.
void SetFrequency(scalar hz)
{
m_frequencyHz = hz;
}
// Get the frequency in Hz.
scalar GetFrequency() const
{
return m_frequencyHz;
}
// Set the damping ratio.
void SetDampingRatio(scalar ratio)
{
m_dampingRatio = ratio;
}
// Get the damping ratio.
scalar GetDampingRatio() const
{
return m_dampingRatio;
}
// Draw this joint.
void Draw() const;
private:
@ -74,30 +135,32 @@ private:
b3Vec3 m_localAnchorA;
b3Vec3 m_localAnchorB;
b3Quat m_referenceRotation;
scalar m_frequencyHz;
scalar m_dampingRatio;
// Solver temp
u32 m_indexA;
u32 m_indexB;
float32 m_mA;
float32 m_mB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
b3Vec3 m_localCenterA;
b3Vec3 m_localCenterB;
b3Mat33 m_localInvIA;
b3Mat33 m_localInvIB;
// Point-to-point
// Linear
b3Vec3 m_rA;
b3Vec3 m_rB;
b3Vec3 m_impulse;
b3Mat33 m_mass;
b3Vec3 m_linearImpulse;
b3Mat33 m_linearMass;
// Weld constraint
b3Mat33 m_J1;
b3Mat33 m_J2;
b3Mat33 m_J1T;
b3Mat33 m_J2T;
b3Vec3 m_axisImpulse;
b3Mat33 m_K;
// Angular
b3Vec3 m_angularImpulse;
b3Mat33 m_angularMass;
b3Mat33 m_gamma;
b3Vec3 m_bias;
};
#endif

View File

@ -0,0 +1,242 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_WHEEL_JOINT_H
#define B3_WHEEL_JOINT_H
#include <bounce/dynamics/joints/joint.h>
// Wheel joint definition.
// This requires defining two axis and an anchor point.
// The anchor point usually coincides with the wheel position.
// The definition uses local anchor points and a local axes so that
// the initial configuration can violate the constraint slightly.
// The joint translation is zero when the local anchor points coincide in world space.
// Using local anchors and a local axes helps when saving and loading a game.
struct b3WheelJointDef : public b3JointDef
{
b3WheelJointDef()
{
type = e_wheelJoint;
localAnchorA.SetZero();
localAnchorB.SetZero();
localAxisA.Set(scalar(0), scalar(1), scalar(0));
localAxisB.Set(scalar(1), scalar(0), scalar(0));
enableMotor = false;
maxMotorTorque = scalar(0);
motorSpeed = scalar(0);
frequencyHz = scalar(4);
dampingRatio = scalar(0.7);
}
// Initialize the bodies, anchors, axis, and reference angle using the world
// anchor and world axes.
void Initialize(b3Body* bodyA, b3Body* bodyB, const b3Vec3& anchor, const b3Vec3& axisA, const b3Vec3& axisB);
// The local anchor point relative to bodyA's origin.
b3Vec3 localAnchorA;
// The local anchor point relative to bodyB's origin.
b3Vec3 localAnchorB;
// The local translation axis in body A.
b3Vec3 localAxisA;
// The local rotation axis in body B.
b3Vec3 localAxisB;
// Enable/disable the joint motor.
bool enableMotor;
// The maximum motor torque, usually in N-m.
scalar maxMotorTorque;
// The desired motor velocity in radians per second.
scalar motorSpeed;
// Suspension frequency, zero indicates no suspension
scalar frequencyHz;
// Suspension damping ratio, one indicates critical damping
scalar dampingRatio;
};
// A wheel joint.
// This joint will keep the motion of the anchor point along a translation
// axis fixed in body A.
// This joint maintains the initial angle between an axis on
// body A and another axis on body B.
// The anchor point usually coincides with the wheel position.
// You can control the spring parameters along the translation axis on body A.
// You can control the desired angular motor speed along the axis on body B.
// This joint is designed for vehicle suspensions.
class b3WheelJoint : public b3Joint
{
public:
b3Vec3 GetAnchorA() const;
b3Vec3 GetAnchorB() const;
// The local anchor point relative to body A's origin.
const b3Vec3& GetLocalAnchorA() const { return m_localAnchorA; }
// The local anchor point relative to body B's origin.
const b3Vec3& GetLocalAnchorB() const { return m_localAnchorB; }
// The local joint axis relative to bodyA.
const b3Vec3& GetLocalAxisA() const { return m_localXAxisA; }
// Get the current joint translation, usually in meters.
scalar GetJointTranslation() const;
// Get the current joint linear speed, usually in meters per second.
scalar GetJointLinearSpeed() const;
// Get the current joint rotation quaternion.
b3Quat GetJointRotation() const;
// Get the current joint angular speed in radians per second.
scalar GetJointAngularSpeed() const;
// Is the joint motor enabled?
bool IsMotorEnabled() const;
// Enable/disable the joint motor.
void EnableMotor(bool flag);
// Set the motor angular speed, usually in radians per second.
void SetMotorSpeed(scalar speed);
// Get the motor angular speed, usually in radians per second.
scalar GetMotorSpeed() const;
// Set/Get the maximum motor force, usually in N-m.
void SetMaxMotorTorque(scalar torque);
scalar GetMaxMotorTorque() const;
// Set/Get the spring frequency in hertz. Setting the frequency to zero disables the spring.
void SetSpringFrequencyHz(scalar hz);
scalar GetSpringFrequencyHz() const;
// Set/Get the spring damping ratio
void SetSpringDampingRatio(scalar ratio);
scalar GetSpringDampingRatio() const;
// Draw this joint.
void Draw() const;
protected:
friend class b3Joint;
b3WheelJoint(const b3WheelJointDef* def);
void InitializeConstraints(const b3SolverData* data);
void WarmStart(const b3SolverData* data);
void SolveVelocityConstraints(const b3SolverData* data);
bool SolvePositionConstraints(const b3SolverData* data);
scalar m_frequencyHz;
scalar m_dampingRatio;
// Solver shared
b3Vec3 m_localAnchorA;
b3Vec3 m_localAnchorB;
b3Vec3 m_localXAxisA;
b3Vec3 m_localYAxisA;
b3Vec3 m_localZAxisA;
b3Vec3 m_localXAxisB;
scalar m_referenceCosine;
scalar m_referenceAngle;
b3Vec2 m_linearImpulse;
scalar m_motorImpulse;
scalar m_springImpulse;
b3Vec3 m_u;
scalar m_angularMass;
scalar m_angularImpulse;
scalar m_maxMotorTorque;
scalar m_motorSpeed;
bool m_enableMotor;
// Solver temp
u32 m_indexA;
u32 m_indexB;
b3Vec3 m_localCenterA;
b3Vec3 m_localCenterB;
scalar m_mA;
scalar m_mB;
b3Mat33 m_iA;
b3Mat33 m_iB;
b3Mat33 m_localInvIA;
b3Mat33 m_localInvIB;
b3Vec3 m_a1, m_a2;
b3Vec3 m_perp1;
b3Vec3 m_s1, m_s2;
b3Vec3 m_perp2;
b3Vec3 m_s3, m_s4;
b3Mat22 m_linearMass;
b3Vec3 m_axisA;
b3Vec3 m_axisB;
scalar m_mass;
scalar m_motorMass;
scalar m_springMass;
scalar m_bias;
scalar m_gamma;
};
inline scalar b3WheelJoint::GetMotorSpeed() const
{
return m_motorSpeed;
}
inline scalar b3WheelJoint::GetMaxMotorTorque() const
{
return m_maxMotorTorque;
}
inline void b3WheelJoint::SetSpringFrequencyHz(scalar hz)
{
m_frequencyHz = hz;
}
inline scalar b3WheelJoint::GetSpringFrequencyHz() const
{
return m_frequencyHz;
}
inline void b3WheelJoint::SetSpringDampingRatio(scalar ratio)
{
m_dampingRatio = ratio;
}
inline scalar b3WheelJoint::GetSpringDampingRatio() const
{
return m_dampingRatio;
}
#endif

View File

@ -29,9 +29,9 @@ public:
void Swap(const b3CapsuleShape& other);
void ComputeMass(b3MassData* data, float32 density) const;
void ComputeMass(b3MassData* data, scalar density) const;
void ComputeAABB(b3AABB3* aabb, const b3Transform& xf) const;
void ComputeAABB(b3AABB* aabb, const b3Transform& xf) const;
bool TestSphere(const b3Sphere& sphere, const b3Transform& xf) const;
@ -39,7 +39,7 @@ public:
bool RayCast(b3RayCastOutput* output, const b3RayCastInput& input, const b3Transform& xf) const;
b3Vec3 m_centers[2];
b3Vec3 m_vertex1, m_vertex2;
};
#endif

View File

@ -25,15 +25,15 @@ struct b3Hull;
class b3HullShape : public b3Shape
{
public :
public:
b3HullShape();
~b3HullShape();
void Swap(const b3HullShape& other);
void ComputeMass(b3MassData* data, float32 density) const;
void ComputeMass(b3MassData* data, scalar density) const;
void ComputeAABB(b3AABB3* aabb, const b3Transform& xf) const;
void ComputeAABB(b3AABB* aabb, const b3Transform& xf) const;
bool TestSphere(const b3Sphere& sphere, const b3Transform& xf) const;
@ -44,4 +44,4 @@ public :
const b3Hull* m_hull;
};
#endif
#endif

View File

@ -31,11 +31,11 @@ public:
void Swap(const b3MeshShape& other);
void ComputeMass(b3MassData* data, float32 density) const;
void ComputeMass(b3MassData* data, scalar density) const;
void ComputeAABB(b3AABB3* output, const b3Transform& xf) const;
void ComputeAABB(b3AABB* output, const b3Transform& xf) const;
void ComputeAABB(b3AABB3* output, const b3Transform& xf, u32 childIndex) const;
void ComputeAABB(b3AABB* output, const b3Transform& xf, u32 childIndex) const;
bool TestSphere(const b3Sphere& sphere, const b3Transform& xf) const;
@ -48,6 +48,8 @@ public:
bool RayCast(b3RayCastOutput* output, const b3RayCastInput& input, const b3Transform& xf, u32 childIndex) const;
const b3Mesh* m_mesh;
b3Vec3 m_scale;
};
#endif
#endif

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_SDF_SHAPE_H
#define B3_SDF_SHAPE_H
#include <bounce/dynamics/shapes/shape.h>
class b3SDF;
class b3SDFShape : public b3Shape
{
public:
b3SDFShape();
~b3SDFShape();
void Swap(const b3SDFShape& other);
void ComputeMass(b3MassData* data, scalar density) const;
void ComputeAABB(b3AABB* output, const b3Transform& xf) const;
bool TestSphere(const b3Sphere& sphere, const b3Transform& xf) const;
bool TestSphere(b3TestSphereOutput* output, const b3Sphere& sphere, const b3Transform& xf) const;
bool RayCast(b3RayCastOutput* output, const b3RayCastInput& input, const b3Transform& xf) const;
const b3SDF* m_sdf;
b3Vec3 m_scale;
};
#endif

View File

@ -22,6 +22,7 @@
#include <bounce/common/math/transform.h>
#include <bounce/common/template/list.h>
#include <bounce/collision/collision.h>
#include <bounce/collision/shapes/aabb.h>
#include <bounce/collision/shapes/sphere.h>
struct b3ContactEdge;
@ -33,36 +34,39 @@ enum b3ShapeType
{
e_sphereShape,
e_capsuleShape,
e_triangleShape,
e_hullShape,
e_meshShape,
e_sdfShape,
e_maxShapes
};
// c2 = center
// separation = dot(c2 - c1, normal) - r1 - r2
struct b3TestSphereOutput
{
b3Vec3 point;
float32 separation;
b3Vec3 normal;
b3Vec3 point; // contact point on the shape
b3Vec3 normal; // contact normal on the shape towards the sphere
};
struct b3ShapeDef
{
b3ShapeDef()
{
shape = NULL;
userData = NULL;
shape = nullptr;
userData = nullptr;
isSensor = false;
density = 0.0f;
friction = 0.3f;
restitution = 0.0f;
density = scalar(0);
friction = scalar(0.3);
restitution = scalar(0);
}
const b3Shape* shape;
void* userData;
bool isSensor;
float32 density;
float32 restitution;
float32 friction;
scalar density;
scalar restitution;
scalar friction;
};
// This structure stores the mass-related data of a shape.
@ -72,7 +76,7 @@ struct b3MassData
b3Vec3 center;
// The mass of the shape, typically in kg.
float32 mass;
scalar mass;
// The rotational inertia of the shape about the local origin.
b3Mat33 I;
@ -92,17 +96,16 @@ public:
b3Body* GetBody();
// Calculate the mass data for this shape given the shape density.
virtual void ComputeMass(b3MassData* data, float32 density) const = 0;
virtual void ComputeMass(b3MassData* data, scalar density) const = 0;
// Compute the shape world AABB.
virtual void ComputeAABB(b3AABB3* aabb, const b3Transform& xf) const = 0;
virtual void ComputeAABB(b3AABB* aabb, const b3Transform& xf) const = 0;
// Test if a sphere is contained inside this shape.
virtual bool TestSphere(const b3Sphere& sphere, const b3Transform& xf) const = 0;
// Test if a sphere is contained inside this shape.
// If the sphere is inside this shape then return the minimum separation distance and normal.
// The direction of the normal points from this shape to the sphere.
// If the sphere is colliding with this shape then return the contact point and normal on the other shape.
virtual bool TestSphere(b3TestSphereOutput* output, const b3Sphere& sphere, const b3Transform& xf) const = 0;
// Compute the ray intersection point, normal of surface, and fraction.
@ -115,24 +118,24 @@ public:
bool IsSensor() const;
// Get the shape density.
float32 GetDensity() const;
scalar GetDensity() const;
// Set the shape density.
void SetDensity(float32 density);
void SetDensity(scalar density);
// Get the shape coefficient of restitution.
float32 GetRestitution() const;
scalar GetRestitution() const;
// Set the shape coefficient of restitution.
// This is a value in the range [0, 1].
void SetRestitution(float32 restitution);
void SetRestitution(scalar restitution);
// Get the shape coefficient of friction.
float32 GetFriction() const;
scalar GetFriction() const;
// Set the shape coefficient of friction.
// This is a value in the range [0, 1].
void SetFriction(float32 friction);
void SetFriction(scalar friction);
// Get the user data associated with this shape.
void* GetUserData() const;
@ -141,7 +144,11 @@ public:
void SetUserData(void* data);
// Get broadphase AABB
const b3AABB3& GetAABB() const;
const b3AABB& GetAABB() const;
// Get the list of contacts that contains this body.
const b3List2<b3ContactEdge>& GetContactList() const;
b3List2<b3ContactEdge>& GetContactList();
// Dump this shape to the log file.
void Dump(u32 bodyIndex) const;
@ -150,7 +157,10 @@ public:
const b3Shape* GetNext() const;
b3Shape* GetNext();
float32 m_radius;
// This function is used internally.
void SetShape(b3Shape* shape);
scalar m_radius;
protected:
friend class b3World;
friend class b3Body;
@ -171,9 +181,9 @@ protected:
b3ShapeType m_type;
bool m_isSensor;
void* m_userData;
float32 m_density;
float32 m_restitution;
float32 m_friction;
scalar m_density;
scalar m_restitution;
scalar m_friction;
u32 m_broadPhaseID;
// Contact edges for this shape contact graph.
@ -191,32 +201,32 @@ inline b3ShapeType b3Shape::GetType() const
return m_type;
}
inline float32 b3Shape::GetDensity() const
inline scalar b3Shape::GetDensity() const
{
return m_density;
}
inline void b3Shape::SetDensity(float32 density)
inline void b3Shape::SetDensity(scalar density)
{
m_density = density;
}
inline float32 b3Shape::GetRestitution() const
inline scalar b3Shape::GetRestitution() const
{
return m_restitution;
}
inline void b3Shape::SetRestitution(float32 restitution)
inline void b3Shape::SetRestitution(scalar restitution)
{
m_restitution = restitution;
}
inline float32 b3Shape::GetFriction() const
inline scalar b3Shape::GetFriction() const
{
return m_friction;
}
inline void b3Shape::SetFriction(float32 friction)
inline void b3Shape::SetFriction(scalar friction)
{
m_friction = friction;
}
@ -246,6 +256,16 @@ inline b3Body* b3Shape::GetBody()
return m_body;
}
inline const b3List2<b3ContactEdge>& b3Shape::GetContactList() const
{
return m_contactEdges;
}
inline b3List2<b3ContactEdge>& b3Shape::GetContactList()
{
return m_contactEdges;
}
inline const b3Shape* b3Shape::GetNext() const
{
return m_next;

View File

@ -29,9 +29,9 @@ public :
void Swap(const b3SphereShape& other);
void ComputeMass(b3MassData* data, float32 density) const;
void ComputeMass(b3MassData* data, scalar density) const;
void ComputeAABB(b3AABB3* aabb, const b3Transform& xf) const;
void ComputeAABB(b3AABB* aabb, const b3Transform& xf) const;
bool TestSphere(const b3Sphere& sphere, const b3Transform& xf) const;

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef B3_TRIANGLE_SHAPE_H
#define B3_TRIANGLE_SHAPE_H
#include <bounce/dynamics/shapes/shape.h>
class b3TriangleShape : public b3Shape
{
public:
b3TriangleShape();
~b3TriangleShape();
// Set this triangle as an isolated triangle.
void Set(const b3Vec3& v1, const b3Vec3& v2, const b3Vec3& v3);
void Swap(const b3TriangleShape& other);
void ComputeMass(b3MassData* data, scalar density) const;
void ComputeAABB(b3AABB* aabb, const b3Transform& xf) const;
bool TestSphere(const b3Sphere& sphere, const b3Transform& xf) const;
bool TestSphere(b3TestSphereOutput* output, const b3Sphere& sphere, const b3Transform& xf) const;
bool RayCast(b3RayCastOutput* output, const b3RayCastInput& input, const b3Transform& xf) const;
// The triangle vertices.
b3Vec3 m_vertex1, m_vertex2, m_vertex3;
// Optional edge wing vertices.
// These are used for smooth edge collision.
bool m_hasE1Vertex, m_hasE2Vertex, m_hasE3Vertex;
b3Vec3 m_e1Vertex, m_e2Vertex, m_e3Vertex;
};
#endif

View File

@ -40,8 +40,8 @@ struct b3SolverData
b3Position* positions;
b3Velocity* velocities;
b3Mat33* invInertias;
float32 dt;
float32 invdt;
scalar dt;
scalar invdt;
};
enum b3LimitState
@ -57,9 +57,9 @@ enum b3LimitState
// The result equals to transpose( skew(v) ) * skew(v) or diagonal(v^2) - outer(v, v)
inline b3Mat33 b3Steiner(const b3Vec3& v)
{
float32 xx = v.x * v.x;
float32 yy = v.y * v.y;
float32 zz = v.z * v.z;
scalar xx = v.x * v.x;
scalar yy = v.y * v.y;
scalar zz = v.z * v.z;
b3Mat33 S;
@ -95,7 +95,7 @@ inline b3Mat33 b3RotateToFrame(const b3Mat33& inertia, const b3Mat33& rotation)
// of the body frame relative to the inertial frame.
inline b3Mat33 b3RotateToFrame(const b3Mat33& inertia, const b3Quat& rotation)
{
b3Mat33 R = b3QuatMat33(rotation);
b3Mat33 R = rotation.GetXYZAxes();
return R * inertia * b3Transpose(R);
}
@ -104,19 +104,53 @@ inline b3Mat33 b3RotateToFrame(const b3Mat33& inertia, const b3Quat& rotation)
// the angular velocity of the rotating frame represented by the orientation.
inline b3Quat b3Derivative(const b3Quat& orientation, const b3Vec3& velocity)
{
b3Quat xf(0.5f * velocity.x, 0.5f * velocity.y, 0.5f * velocity.z, 0.0f);
return xf * orientation;
b3Quat w(velocity.x, velocity.y, velocity.z, scalar(0));
return scalar(0.5) * w * orientation;
}
// Integrate an orientation over a time step given
// the current orientation, angular velocity of the rotating frame
// represented by the orientation, and the time step dt.
inline b3Quat b3Integrate(const b3Quat& orientation, const b3Vec3& velocity, float32 dt)
inline b3Quat b3Integrate(const b3Quat& orientation, const b3Vec3& omega, scalar dt)
{
// Integrate from [t0, t0 + h] using the explicit Euler method
b3Quat qdot = b3Derivative(orientation, velocity);
b3Quat integral = dt * qdot;
return orientation + integral;
// "Practical Parameterization of Rotations Using the Exponential Map", Grassia
scalar h = dt;
scalar x = b3Length(omega);
const scalar kTol = scalar(10.0e-4);
b3Vec3 qv;
if (scalar(0.5) * h * x < kTol)
{
// Use first three terms of Taylor expansion of sin(h * x / 2)
// f'(0) / 1! * x = h / 2 * x
// f''(0) / 2! * x^2 = 0 * 2 / x ^ 2 = 0
// f'''(0) / 3! * x^3 = -x^3 * h^3 / 48
// Sum up, divide by x, and simplify (expand)
// s = h / 2 - (h * h * h) * x * x / 48
const scalar kInv48 = scalar(1) / scalar(48);
scalar s = scalar(0.5) * h - kInv48 * (h * h * h) * x * x;
qv = s * omega;
}
else
{
scalar s = sin(scalar(0.5) * h * x) / x;
qv = s * omega;
}
b3Quat q;
q.v = qv;
q.s = cos(scalar(0.5) * h * x);
b3Quat q1 = q * orientation;
q1.Normalize();
return q1;
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More