Apply changes from latest known public version of bounce dated 2019-11-13
This commit is contained in:
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
291
include/bounce/cloth/cloth_particle.h
Normal file
291
include/bounce/cloth/cloth_particle.h
Normal 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
|
@ -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
|
34
include/bounce/cloth/cloth_time_step.h
Normal file
34
include/bounce/cloth/cloth_time_step.h
Normal 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
|
@ -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
|
@ -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
|
75
include/bounce/cloth/contacts/cloth_sphere_shape_contact.h
Normal file
75
include/bounce/cloth/contacts/cloth_sphere_shape_contact.h
Normal 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
|
@ -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
|
121
include/bounce/cloth/forces/element_force.h
Normal file
121
include/bounce/cloth/forces/element_force.h
Normal 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
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
264
include/bounce/cloth/forces/stretch_force.h
Normal file
264
include/bounce/cloth/forces/stretch_force.h
Normal 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
|
@ -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;
|
||||
|
||||
|
@ -57,7 +57,7 @@ struct b3GarmentMesh
|
||||
b3GarmentMesh();
|
||||
~b3GarmentMesh();
|
||||
|
||||
void Set(b3Garment* garment, float32 desiredArea);
|
||||
void Set(b3Garment* garment, scalar desiredArea);
|
||||
};
|
||||
|
||||
#endif
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
83
include/bounce/cloth/shapes/cloth_capsule_shape.h
Normal file
83
include/bounce/cloth/shapes/cloth_capsule_shape.h
Normal 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
|
139
include/bounce/cloth/shapes/cloth_shape.h
Normal file
139
include/bounce/cloth/shapes/cloth_shape.h
Normal 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
|
74
include/bounce/cloth/shapes/cloth_sphere_shape.h
Normal file
74
include/bounce/cloth/shapes/cloth_sphere_shape.h
Normal 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
|
93
include/bounce/cloth/shapes/cloth_triangle_shape.h
Normal file
93
include/bounce/cloth/shapes/cloth_triangle_shape.h
Normal 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
|
71
include/bounce/cloth/shapes/cloth_world_shape.h
Normal file
71
include/bounce/cloth/shapes/cloth_world_shape.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
40
include/bounce/collision/sat/sat_hull_and_edge.h
Normal file
40
include/bounce/collision/sat/sat_hull_and_edge.h
Normal 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
|
33
include/bounce/collision/sat/sat_hull_and_vertex.h
Normal file
33
include/bounce/collision/sat/sat_hull_and_vertex.h
Normal 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
|
370
include/bounce/collision/shapes/aabb.h
Normal file
370
include/bounce/collision/shapes/aabb.h
Normal 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
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
240
include/bounce/collision/shapes/cone_hull.h
Normal file
240
include/bounce/collision/shapes/cone_hull.h
Normal 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
|
322
include/bounce/collision/shapes/cylinder_hull.h
Normal file
322
include/bounce/collision/shapes/cylinder_hull.h
Normal 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
|
@ -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
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
168
include/bounce/collision/shapes/sdf.h
Normal file
168
include/bounce/collision/shapes/sdf.h
Normal 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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
71
include/bounce/collision/time_of_impact.h
Normal file
71
include/bounce/collision/time_of_impact.h
Normal 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
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
59
include/bounce/common/memory/frame_allocator.h
Normal file
59
include/bounce/common/memory/frame_allocator.h
Normal 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
|
101
include/bounce/common/profiler.h
Normal file
101
include/bounce/common/profiler.h
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
{
|
||||
if ((m_count + 1) == N)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
B3_ASSERT(m_back < N);
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
{
|
||||
b3Free(m_elements);
|
||||
}
|
||||
m_elements = NULL;
|
||||
m_elements = nullptr;
|
||||
}
|
||||
|
||||
const T& Top() const
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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() { }
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
123
include/bounce/dynamics/joints/friction_joint.h
Normal file
123
include/bounce/dynamics/joints/friction_joint.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ struct b3Jacobian
|
||||
|
||||
struct b3JointSolverDef
|
||||
{
|
||||
float32 dt;
|
||||
scalar dt;
|
||||
u32 count;
|
||||
b3Joint** joints;
|
||||
b3Position* positions;
|
||||
|
135
include/bounce/dynamics/joints/motor_joint.h
Normal file
135
include/bounce/dynamics/joints/motor_joint.h
Normal 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
|
@ -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
|
208
include/bounce/dynamics/joints/prismatic_joint.h
Normal file
208
include/bounce/dynamics/joints/prismatic_joint.h
Normal 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
|
@ -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
|
@ -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;
|
||||
|
||||
|
@ -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
|
@ -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
|
242
include/bounce/dynamics/joints/wheel_joint.h
Normal file
242
include/bounce/dynamics/joints/wheel_joint.h
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
49
include/bounce/dynamics/shapes/sdf_shape.h
Normal file
49
include/bounce/dynamics/shapes/sdf_shape.h
Normal 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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
54
include/bounce/dynamics/shapes/triangle_shape.h
Normal file
54
include/bounce/dynamics/shapes/triangle_shape.h
Normal 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
|
@ -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
Reference in New Issue
Block a user