Compare commits
9 Commits
upstream_f
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
9f8dcae52a | ||
|
1509b9bd0e | ||
|
d728d45d70 | ||
|
d7010a99f9 | ||
|
795bef7394 | ||
|
950de0854b | ||
|
5522df60b0 | ||
|
77fb26b578 | ||
|
3992eb8cc4 |
@ -1,2 +0,0 @@
|
|||||||
cd ..\
|
|
||||||
premake5 solution_vs2019
|
|
2487
doc/doxyfile
2487
doc/doxyfile
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -45,7 +45,7 @@ int main(int argc, char** argv)
|
|||||||
world->SetGravity(gravity);
|
world->SetGravity(gravity);
|
||||||
|
|
||||||
// The fixed time step size.
|
// The fixed time step size.
|
||||||
const scalar timeStep = 1.0f / 60.0f;
|
const float32 timeStep = 1.0f / 60.0f;
|
||||||
|
|
||||||
// Number of iterations for the velocity constraint solver.
|
// Number of iterations for the velocity constraint solver.
|
||||||
const u32 velocityIterations = 8;
|
const u32 velocityIterations = 8;
|
||||||
@ -59,8 +59,14 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
// Create a box positioned at the world origin and
|
// Create a box positioned at the world origin and
|
||||||
// aligned with the world frame.
|
// aligned with the world frame.
|
||||||
b3BoxHull groundBox(10.0f, 1.0f, 10.0f);
|
b3BoxHull groundBox;
|
||||||
|
|
||||||
|
// Set the ground box dimensions using a linear scale transform.
|
||||||
|
b3Transform scale;
|
||||||
|
scale.position.SetZero();
|
||||||
|
scale.rotation = b3Diagonal(10.0f, 1.0f, 10.0f);
|
||||||
|
groundBox.SetTransform(scale);
|
||||||
|
|
||||||
// Create the box physics wrapper.
|
// Create the box physics wrapper.
|
||||||
b3HullShape groundShape;
|
b3HullShape groundShape;
|
||||||
groundShape.m_hull = &groundBox;
|
groundShape.m_hull = &groundBox;
|
||||||
@ -109,7 +115,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
// Decode the axis and angle of rotation about it from the quaternion.
|
// Decode the axis and angle of rotation about it from the quaternion.
|
||||||
b3Vec3 axis;
|
b3Vec3 axis;
|
||||||
scalar angle;
|
float32 angle;
|
||||||
orientation.GetAxisAngle(&axis, &angle);
|
orientation.GetAxisAngle(&axis, &angle);
|
||||||
|
|
||||||
// Visualize the body state in this frame.
|
// Visualize the body state in this frame.
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -35,23 +35,12 @@ bool b3BodyDragger::StartDragging()
|
|||||||
{
|
{
|
||||||
B3_ASSERT(IsDragging() == false);
|
B3_ASSERT(IsDragging() == false);
|
||||||
|
|
||||||
class RayCastFilter : public b3RayCastFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool ShouldRayCast(b3Shape* shape)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RayCastFilter filter;
|
|
||||||
|
|
||||||
b3RayCastSingleOutput out;
|
b3RayCastSingleOutput out;
|
||||||
if (m_world->RayCastSingle(&out, &filter, m_ray->A(), m_ray->B()) == false)
|
if (m_world->RayCastSingle(&out, m_ray->A(), m_ray->B()) == false)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_x = out.fraction;
|
m_x = out.fraction;
|
||||||
m_shape = out.shape;
|
m_shape = out.shape;
|
||||||
|
|
||||||
@ -65,7 +54,7 @@ bool b3BodyDragger::StartDragging()
|
|||||||
jd.bodyA = groundBody;
|
jd.bodyA = groundBody;
|
||||||
jd.bodyB = body;
|
jd.bodyB = body;
|
||||||
jd.target = out.point;
|
jd.target = out.point;
|
||||||
jd.maxForce = 1000.0f * body->GetMass();
|
jd.maxForce = 2000.0f * body->GetMass();
|
||||||
|
|
||||||
m_mouseJoint = (b3MouseJoint*)m_world->CreateJoint(jd);
|
m_mouseJoint = (b3MouseJoint*)m_world->CreateJoint(jd);
|
||||||
|
|
||||||
@ -90,10 +79,10 @@ void b3BodyDragger::StopDragging()
|
|||||||
m_shape = nullptr;
|
m_shape = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Shape* b3BodyDragger::GetShape() const
|
b3Body* b3BodyDragger::GetBody() const
|
||||||
{
|
{
|
||||||
B3_ASSERT(IsDragging() == true);
|
B3_ASSERT(IsDragging() == true);
|
||||||
return m_shape;
|
return m_shape->GetBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 b3BodyDragger::GetPointA() const
|
b3Vec3 b3BodyDragger::GetPointA() const
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <bounce/dynamics/shapes/shape.h>
|
#include <bounce/dynamics/shapes/shape.h>
|
||||||
#include <bounce/dynamics/body.h>
|
#include <bounce/dynamics/body.h>
|
||||||
#include <bounce/dynamics/world.h>
|
#include <bounce/dynamics/world.h>
|
||||||
#include <bounce/dynamics/world_listeners.h>
|
|
||||||
#include <bounce/dynamics/joints/mouse_joint.h>
|
#include <bounce/dynamics/joints/mouse_joint.h>
|
||||||
|
|
||||||
// A body shape dragger.
|
// A body shape dragger.
|
||||||
@ -44,14 +43,14 @@ public:
|
|||||||
|
|
||||||
b3Ray3* GetRay() const;
|
b3Ray3* GetRay() const;
|
||||||
|
|
||||||
b3Shape* GetShape() const;
|
b3Body* GetBody() const;
|
||||||
|
|
||||||
b3Vec3 GetPointA() const;
|
b3Vec3 GetPointA() const;
|
||||||
|
|
||||||
b3Vec3 GetPointB() const;
|
b3Vec3 GetPointB() const;
|
||||||
private:
|
private:
|
||||||
b3Ray3 * m_ray;
|
b3Ray3 * m_ray;
|
||||||
scalar m_x;
|
float32 m_x;
|
||||||
|
|
||||||
b3World* m_world;
|
b3World* m_world;
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ b3ClothDragger::b3ClothDragger(b3Ray3* ray, b3Cloth* cloth)
|
|||||||
m_staticDrag = true;
|
m_staticDrag = true;
|
||||||
m_ray = ray;
|
m_ray = ray;
|
||||||
m_cloth = cloth;
|
m_cloth = cloth;
|
||||||
m_isDragging = false;
|
m_triangle = nullptr;
|
||||||
m_km = 100000.0f;
|
m_km = 10000.0f;
|
||||||
m_kd = 1000.0f;
|
m_kd = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
b3ClothDragger::~b3ClothDragger()
|
b3ClothDragger::~b3ClothDragger()
|
||||||
@ -43,20 +43,22 @@ bool b3ClothDragger::StartDragging()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isDragging = true;
|
m_mesh = m_cloth->GetMesh();
|
||||||
|
m_triangleIndex = rayOut.triangle;
|
||||||
|
m_triangle = m_mesh->triangles + m_triangleIndex;
|
||||||
m_x = rayOut.fraction;
|
m_x = rayOut.fraction;
|
||||||
|
|
||||||
m_p1 = rayOut.triangle->GetParticle1();
|
b3Particle* p1 = m_cloth->GetParticle(m_triangle->v1);
|
||||||
m_p2 = rayOut.triangle->GetParticle2();
|
b3Particle* p2 = m_cloth->GetParticle(m_triangle->v2);
|
||||||
m_p3 = rayOut.triangle->GetParticle3();
|
b3Particle* p3 = m_cloth->GetParticle(m_triangle->v3);
|
||||||
|
|
||||||
b3Vec3 v1 = m_p1->GetPosition();
|
b3Vec3 v1 = p1->GetPosition();
|
||||||
b3Vec3 v2 = m_p2->GetPosition();
|
b3Vec3 v2 = p2->GetPosition();
|
||||||
b3Vec3 v3 = m_p3->GetPosition();
|
b3Vec3 v3 = p3->GetPosition();
|
||||||
|
|
||||||
b3Vec3 B = GetPointB();
|
b3Vec3 B = GetPointB();
|
||||||
|
|
||||||
scalar wABC[4];
|
float32 wABC[4];
|
||||||
b3BarycentricCoordinates(wABC, v1, v2, v3, B);
|
b3BarycentricCoordinates(wABC, v1, v2, v3, B);
|
||||||
|
|
||||||
if (wABC[3] > B3_EPSILON)
|
if (wABC[3] > B3_EPSILON)
|
||||||
@ -71,34 +73,33 @@ bool b3ClothDragger::StartDragging()
|
|||||||
|
|
||||||
if (m_staticDrag)
|
if (m_staticDrag)
|
||||||
{
|
{
|
||||||
m_t1 = m_p1->GetType();
|
m_t1 = p1->GetType();
|
||||||
m_p1->SetType(e_staticClothParticle);
|
p1->SetType(e_staticParticle);
|
||||||
|
|
||||||
m_t2 = m_p2->GetType();
|
m_t2 = p2->GetType();
|
||||||
m_p2->SetType(e_staticClothParticle);
|
p2->SetType(e_staticParticle);
|
||||||
|
|
||||||
m_t3 = m_p3->GetType();
|
m_t3 = p3->GetType();
|
||||||
m_p3->SetType(e_staticClothParticle);
|
p3->SetType(e_staticParticle);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b3ClothParticleDef pd;
|
b3ParticleDef pd;
|
||||||
pd.type = e_staticClothParticle;
|
pd.type = e_staticParticle;
|
||||||
pd.position = GetPointA();
|
pd.position = GetPointA();
|
||||||
|
|
||||||
m_particle = m_cloth->CreateParticle(pd);
|
m_particle = m_cloth->CreateParticle(pd);
|
||||||
|
|
||||||
|
b3ClothTriangle* triangle = m_cloth->GetTriangle(m_triangleIndex);
|
||||||
|
|
||||||
b3MouseForceDef def;
|
b3MouseForceDef def;
|
||||||
def.p1 = m_particle;
|
def.particle = m_particle;
|
||||||
def.p2 = m_p1;
|
def.triangle = triangle;
|
||||||
def.p3 = m_p2;
|
|
||||||
def.p4 = m_p3;
|
|
||||||
def.w2 = m_u;
|
def.w2 = m_u;
|
||||||
def.w3 = m_v;
|
def.w3 = m_v;
|
||||||
def.w4 = 1.0f - m_u - m_v;
|
def.w4 = (1.0f - m_u - m_v);
|
||||||
def.mouse = m_km;
|
def.mouse = m_km;
|
||||||
def.damping = m_kd;
|
def.damping = m_kd;
|
||||||
def.restLength = 0.0f;
|
|
||||||
|
|
||||||
m_mf = (b3MouseForce*)m_cloth->CreateForce(def);
|
m_mf = (b3MouseForce*)m_cloth->CreateForce(def);
|
||||||
}
|
}
|
||||||
@ -110,23 +111,24 @@ void b3ClothDragger::Drag()
|
|||||||
{
|
{
|
||||||
B3_ASSERT(IsDragging() == true);
|
B3_ASSERT(IsDragging() == true);
|
||||||
|
|
||||||
|
b3Vec3 A = GetPointA();
|
||||||
b3Vec3 B = GetPointB();
|
b3Vec3 B = GetPointB();
|
||||||
|
|
||||||
|
b3Vec3 dx = B - A;
|
||||||
|
|
||||||
if (m_staticDrag)
|
if (m_staticDrag)
|
||||||
{
|
{
|
||||||
b3Vec3 A = GetPointA();
|
b3Particle* p1 = m_cloth->GetParticle(m_triangle->v1);
|
||||||
|
p1->ApplyTranslation(dx);
|
||||||
|
|
||||||
b3Vec3 dx = B - A;
|
b3Particle* p2 = m_cloth->GetParticle(m_triangle->v2);
|
||||||
|
p2->ApplyTranslation(dx);
|
||||||
|
|
||||||
m_p1->ApplyTranslation(dx);
|
b3Particle* p3 = m_cloth->GetParticle(m_triangle->v3);
|
||||||
m_p2->ApplyTranslation(dx);
|
p3->ApplyTranslation(dx);
|
||||||
m_p3->ApplyTranslation(dx);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//b3Vec3 A = m_particle->GetPosition();
|
|
||||||
//b3Vec3 dx = B - A;
|
|
||||||
//m_particle->ApplyTranslation(dx);
|
|
||||||
m_particle->SetPosition(B);
|
m_particle->SetPosition(B);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,9 +154,9 @@ void b3ClothDragger::StopDragging()
|
|||||||
|
|
||||||
if (m_staticDrag)
|
if (m_staticDrag)
|
||||||
{
|
{
|
||||||
m_p1->SetType(m_t1);
|
m_cloth->GetParticle(m_triangle->v1)->SetType(m_t1);
|
||||||
m_p2->SetType(m_t2);
|
m_cloth->GetParticle(m_triangle->v2)->SetType(m_t2);
|
||||||
m_p3->SetType(m_t3);
|
m_cloth->GetParticle(m_triangle->v3)->SetType(m_t3);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -162,18 +164,18 @@ void b3ClothDragger::StopDragging()
|
|||||||
m_cloth->DestroyParticle(m_particle);
|
m_cloth->DestroyParticle(m_particle);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isDragging = false;
|
m_triangle = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 b3ClothDragger::GetPointA() const
|
b3Vec3 b3ClothDragger::GetPointA() const
|
||||||
{
|
{
|
||||||
B3_ASSERT(IsDragging() == true);
|
B3_ASSERT(IsDragging() == true);
|
||||||
|
|
||||||
b3Vec3 v1 = m_p1->GetPosition() + m_p1->GetTranslation();
|
b3Vec3 A = m_cloth->GetParticle(m_triangle->v1)->GetPosition();
|
||||||
b3Vec3 v2 = m_p2->GetPosition() + m_p2->GetTranslation();
|
b3Vec3 B = m_cloth->GetParticle(m_triangle->v2)->GetPosition();
|
||||||
b3Vec3 v3 = m_p3->GetPosition() + m_p3->GetTranslation();
|
b3Vec3 C = m_cloth->GetParticle(m_triangle->v3)->GetPosition();
|
||||||
|
|
||||||
return m_u * v1 + m_v * v2 + (1.0f - m_u - m_v) * v3;
|
return m_u * A + m_v * B + (1.0f - m_u - m_v) * C;
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 b3ClothDragger::GetPointB() const
|
b3Vec3 b3ClothDragger::GetPointB() const
|
||||||
|
@ -21,8 +21,9 @@
|
|||||||
|
|
||||||
#include <bounce/common/geometry.h>
|
#include <bounce/common/geometry.h>
|
||||||
#include <bounce/cloth/cloth.h>
|
#include <bounce/cloth/cloth.h>
|
||||||
#include <bounce/cloth/cloth_particle.h>
|
#include <bounce/cloth/cloth_mesh.h>
|
||||||
#include <bounce/cloth/shapes/cloth_triangle_shape.h>
|
#include <bounce/cloth/particle.h>
|
||||||
|
#include <bounce/cloth/cloth_triangle.h>
|
||||||
#include <bounce/cloth/forces/mouse_force.h>
|
#include <bounce/cloth/forces/mouse_force.h>
|
||||||
|
|
||||||
// A cloth triangle dragger.
|
// A cloth triangle dragger.
|
||||||
@ -36,13 +37,13 @@ public:
|
|||||||
|
|
||||||
bool GetStaticDrag() const;
|
bool GetStaticDrag() const;
|
||||||
|
|
||||||
void SetMouseStiffness(scalar k);
|
void SetMouseStiffness(float32 k);
|
||||||
|
|
||||||
scalar GetMouseStiffness();
|
float32 GetMouseStiffness();
|
||||||
|
|
||||||
void SetMouseDamping(scalar k);
|
void SetMouseDamping(float32 k);
|
||||||
|
|
||||||
scalar GetMouseDamping();
|
float32 GetMouseDamping();
|
||||||
|
|
||||||
bool IsDragging() const;
|
bool IsDragging() const;
|
||||||
|
|
||||||
@ -57,23 +58,21 @@ public:
|
|||||||
b3Vec3 GetPointB() const;
|
b3Vec3 GetPointB() const;
|
||||||
private:
|
private:
|
||||||
b3Ray3* m_ray;
|
b3Ray3* m_ray;
|
||||||
scalar m_x;
|
float32 m_x;
|
||||||
|
|
||||||
b3Cloth* m_cloth;
|
b3Cloth* m_cloth;
|
||||||
|
const b3ClothMesh* m_mesh;
|
||||||
bool m_isDragging;
|
u32 m_triangleIndex;
|
||||||
b3ClothParticle* m_p1;
|
b3ClothMeshTriangle* m_triangle;
|
||||||
b3ClothParticle* m_p2;
|
float32 m_u, m_v;
|
||||||
b3ClothParticle* m_p3;
|
|
||||||
scalar m_u, m_v;
|
|
||||||
|
|
||||||
scalar m_km;
|
float32 m_km;
|
||||||
scalar m_kd;
|
float32 m_kd;
|
||||||
b3ClothParticle* m_particle;
|
b3Particle* m_particle;
|
||||||
b3MouseForce* m_mf;
|
b3MouseForce* m_mf;
|
||||||
|
|
||||||
bool m_staticDrag;
|
bool m_staticDrag;
|
||||||
b3ClothParticleType m_t1, m_t2, m_t3;
|
b3ParticleType m_t1, m_t2, m_t3;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool b3ClothDragger::GetStaticDrag() const
|
inline bool b3ClothDragger::GetStaticDrag() const
|
||||||
@ -81,29 +80,29 @@ inline bool b3ClothDragger::GetStaticDrag() const
|
|||||||
return m_staticDrag;
|
return m_staticDrag;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void b3ClothDragger::SetMouseStiffness(scalar k)
|
inline void b3ClothDragger::SetMouseStiffness(float32 k)
|
||||||
{
|
{
|
||||||
m_km = k;
|
m_km = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline scalar b3ClothDragger::GetMouseStiffness()
|
inline float32 b3ClothDragger::GetMouseStiffness()
|
||||||
{
|
{
|
||||||
return m_km;
|
return m_km;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void b3ClothDragger::SetMouseDamping(scalar k)
|
inline void b3ClothDragger::SetMouseDamping(float32 k)
|
||||||
{
|
{
|
||||||
m_kd = k;
|
m_kd = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline scalar b3ClothDragger::GetMouseDamping()
|
inline float32 b3ClothDragger::GetMouseDamping()
|
||||||
{
|
{
|
||||||
return m_kd;
|
return m_kd;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool b3ClothDragger::IsDragging() const
|
inline bool b3ClothDragger::IsDragging() const
|
||||||
{
|
{
|
||||||
return m_isDragging;
|
return m_triangle != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -50,17 +50,17 @@ Camera::Camera()
|
|||||||
|
|
||||||
b3Mat44 Camera::BuildProjectionMatrix() const
|
b3Mat44 Camera::BuildProjectionMatrix() const
|
||||||
{
|
{
|
||||||
scalar w = m_width, h = m_height;
|
float32 w = m_width, h = m_height;
|
||||||
|
|
||||||
scalar t = tan(0.5f * m_fovy);
|
float32 t = tan(0.5f * m_fovy);
|
||||||
scalar ratio = w / h;
|
float32 ratio = w / h;
|
||||||
scalar sx = 1.0f / (ratio * t);
|
float32 sx = 1.0f / (ratio * t);
|
||||||
scalar sy = 1.0f / t;
|
float32 sy = 1.0f / t;
|
||||||
|
|
||||||
scalar inv_range = 1.0f / (m_zNear - m_zFar);
|
float32 inv_range = 1.0f / (m_zNear - m_zFar);
|
||||||
scalar sz = inv_range * (m_zNear + m_zFar);
|
float32 sz = inv_range * (m_zNear + m_zFar);
|
||||||
|
|
||||||
scalar tz = inv_range * m_zNear * m_zFar;
|
float32 tz = inv_range * m_zNear * m_zFar;
|
||||||
|
|
||||||
b3Mat44 m;
|
b3Mat44 m;
|
||||||
m.x = b3Vec4(sx, 0.0f, 0.0f, 0.0f);
|
m.x = b3Vec4(sx, 0.0f, 0.0f, 0.0f);
|
||||||
@ -73,8 +73,8 @@ b3Mat44 Camera::BuildProjectionMatrix() const
|
|||||||
b3Transform Camera::BuildWorldTransform() const
|
b3Transform Camera::BuildWorldTransform() const
|
||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation = m_q;
|
xf.rotation = b3QuatMat33(m_q);
|
||||||
xf.translation = (m_zoom * m_q.GetZAxis()) - m_center;
|
xf.position = (m_zoom * xf.rotation.z) - m_center;
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,8 +87,8 @@ b3Mat44 Camera::BuildWorldMatrix() const
|
|||||||
b3Transform Camera::BuildViewTransform() const
|
b3Transform Camera::BuildViewTransform() const
|
||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation = m_q;
|
xf.rotation = b3QuatMat33(m_q);
|
||||||
xf.translation = (m_zoom * m_q.GetZAxis()) - m_center;
|
xf.position = (m_zoom * xf.rotation.z) - m_center;
|
||||||
return b3Inverse(xf);
|
return b3Inverse(xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ b3Mat44 Camera::BuildViewMatrix() const
|
|||||||
|
|
||||||
b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw3) const
|
b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw3) const
|
||||||
{
|
{
|
||||||
scalar w = m_width, h = m_height;
|
float32 w = m_width, h = m_height;
|
||||||
b3Mat44 P = BuildProjectionMatrix();
|
b3Mat44 P = BuildProjectionMatrix();
|
||||||
b3Mat44 V = BuildViewMatrix();
|
b3Mat44 V = BuildViewMatrix();
|
||||||
|
|
||||||
@ -109,11 +109,11 @@ b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw3) const
|
|||||||
b3Vec4 pp = P * V * pw;
|
b3Vec4 pp = P * V * pw;
|
||||||
|
|
||||||
b3Vec3 pn(pp.x, pp.y, pp.z);
|
b3Vec3 pn(pp.x, pp.y, pp.z);
|
||||||
scalar inv_w = pp.w != 0.0f ? 1.0f / pp.w : 1.0f;
|
float32 inv_w = pp.w != 0.0f ? 1.0f / pp.w : 1.0f;
|
||||||
pn *= inv_w;
|
pn *= inv_w;
|
||||||
|
|
||||||
scalar u = 0.5f * (pn.x + 1.0f);
|
float32 u = 0.5f * (pn.x + 1.0f);
|
||||||
scalar v = 0.5f * (pn.y + 1.0f);
|
float32 v = 0.5f * (pn.y + 1.0f);
|
||||||
|
|
||||||
b3Vec2 ps;
|
b3Vec2 ps;
|
||||||
ps.x = u * w;
|
ps.x = u * w;
|
||||||
@ -123,10 +123,10 @@ b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw3) const
|
|||||||
|
|
||||||
b3Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const
|
b3Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const
|
||||||
{
|
{
|
||||||
scalar w = m_width, h = m_height;
|
float32 w = m_width, h = m_height;
|
||||||
|
|
||||||
scalar t = tan(0.5f * m_fovy);
|
float32 t = tan(0.5f * m_fovy);
|
||||||
scalar ratio = w / h;
|
float32 ratio = w / h;
|
||||||
|
|
||||||
b3Vec3 vv;
|
b3Vec3 vv;
|
||||||
vv.x = 2.0f * ratio * ps.x / w - ratio;
|
vv.x = 2.0f * ratio * ps.x / w - ratio;
|
||||||
@ -135,12 +135,12 @@ b3Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const
|
|||||||
|
|
||||||
b3Transform xf = BuildWorldTransform();
|
b3Transform xf = BuildWorldTransform();
|
||||||
|
|
||||||
b3Vec3 vw = b3Mul(xf.rotation, vv);
|
b3Vec3 vw = xf.rotation * vv;
|
||||||
vw.Normalize();
|
vw.Normalize();
|
||||||
|
|
||||||
b3Ray3 rw;
|
b3Ray3 rw;
|
||||||
rw.direction = vw;
|
rw.direction = vw;
|
||||||
rw.origin = xf.translation;
|
rw.origin = xf.position;
|
||||||
rw.fraction = m_zFar;
|
rw.fraction = m_zFar;
|
||||||
return rw;
|
return rw;
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ void Draw::EnableDrawTriangles(bool flag)
|
|||||||
g_glDrawTriangles = flag;
|
g_glDrawTriangles = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawPoint(const b3Vec3& p, scalar size, const b3Color& color)
|
void Draw::DrawPoint(const b3Vec3& p, float32 size, const b3Color& color)
|
||||||
{
|
{
|
||||||
m_points->Vertex(p, size, color);
|
m_points->Vertex(p, size, color);
|
||||||
}
|
}
|
||||||
@ -249,15 +249,14 @@ void Draw::DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawCircle(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color)
|
void Draw::DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
|
||||||
{
|
{
|
||||||
b3Vec3 n1, n3;
|
b3Vec3 n1, n3;
|
||||||
b3ComputeBasis(normal, n1, n3);
|
b3ComputeBasis(normal, n1, n3);
|
||||||
|
|
||||||
u32 kEdgeCount = 20;
|
u32 kEdgeCount = 20;
|
||||||
scalar kAngleInc = 2.0f * B3_PI / scalar(kEdgeCount);
|
float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
|
||||||
b3Quat q;
|
b3Quat q(normal, kAngleInc);
|
||||||
q.SetAxisAngle(normal, kAngleInc);
|
|
||||||
|
|
||||||
b3Vec3 p1 = center + radius * n1;
|
b3Vec3 p1 = center + radius * n1;
|
||||||
for (u32 i = 0; i < kEdgeCount; ++i)
|
for (u32 i = 0; i < kEdgeCount; ++i)
|
||||||
@ -273,7 +272,7 @@ void Draw::DrawCircle(const b3Vec3& normal, const b3Vec3& center, scalar radius,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color)
|
void Draw::DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
|
||||||
{
|
{
|
||||||
b3Color fillColor(color.r, color.g, color.b, color.a);
|
b3Color fillColor(color.r, color.g, color.b, color.a);
|
||||||
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
|
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
|
||||||
@ -282,10 +281,8 @@ void Draw::DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, scalar ra
|
|||||||
b3ComputeBasis(normal, n1, n3);
|
b3ComputeBasis(normal, n1, n3);
|
||||||
|
|
||||||
const u32 kEdgeCount = 20;
|
const u32 kEdgeCount = 20;
|
||||||
const scalar kAngleInc = 2.0f * B3_PI / scalar(kEdgeCount);
|
const float32 kAngleInc = 2.0f * B3_PI / float32(kEdgeCount);
|
||||||
|
b3Quat q(normal, kAngleInc);
|
||||||
b3Quat q;
|
|
||||||
q.SetAxisAngle(normal, kAngleInc);
|
|
||||||
|
|
||||||
b3Vec3 p1 = center + radius * n1;
|
b3Vec3 p1 = center + radius * n1;
|
||||||
for (u32 i = 0; i < kEdgeCount; ++i)
|
for (u32 i = 0; i < kEdgeCount; ++i)
|
||||||
@ -302,32 +299,32 @@ void Draw::DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, scalar ra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawSphere(const b3Vec3& center, scalar radius, const b3Color& color)
|
void Draw::DrawSphere(const b3Vec3& center, float32 radius, const b3Color& color)
|
||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation.SetIdentity();
|
xf.rotation.SetIdentity();
|
||||||
xf.translation = center;
|
xf.position = center;
|
||||||
|
|
||||||
m_wire->DrawSphere(radius, color, xf);
|
m_wire->DrawSphere(radius, color, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawSolidSphere(const b3Vec3& center, scalar radius, const b3Quat& rotation, const b3Color& color)
|
void Draw::DrawSolidSphere(const b3Vec3& center, float32 radius, const b3Mat33& rotation, const b3Color& color)
|
||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation = rotation;
|
xf.rotation = rotation;
|
||||||
xf.translation = center;
|
xf.position = center;
|
||||||
|
|
||||||
m_solid->DrawSphere(radius, color, xf);
|
m_solid->DrawSphere(radius, color, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawCapsule(const b3Vec3& c1, const b3Vec3& c2, scalar radius, const b3Color& color)
|
void Draw::DrawCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Color& color)
|
||||||
{
|
{
|
||||||
scalar height = b3Length(c1 - c2);
|
float32 height = b3Length(c1 - c2);
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation.SetIdentity();
|
xf.rotation.SetIdentity();
|
||||||
xf.translation = c1;
|
xf.position = c1;
|
||||||
m_wire->DrawSphere(radius, color, xf);
|
m_wire->DrawSphere(radius, color, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,20 +335,20 @@ void Draw::DrawCapsule(const b3Vec3& c1, const b3Vec3& c2, scalar radius, const
|
|||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation.SetIdentity();
|
xf.rotation.SetIdentity();
|
||||||
xf.translation = c2;
|
xf.position = c2;
|
||||||
m_wire->DrawSphere(radius, color, xf);
|
m_wire->DrawSphere(radius, color, xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, scalar radius, const b3Quat& rotation, const b3Color& c)
|
void Draw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, float32 radius, const b3Mat33& rotation, const b3Color& c)
|
||||||
{
|
{
|
||||||
scalar height = b3Length(c1 - c2);
|
float32 height = b3Length(c1 - c2);
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation = rotation;
|
xf.rotation = rotation;
|
||||||
xf.translation = c1;
|
xf.position = c1;
|
||||||
m_solid->DrawSphere(radius, c, xf);
|
m_solid->DrawSphere(radius, c, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,11 +359,9 @@ void Draw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, scalar radius, c
|
|||||||
R.y = (1.0f / height) * (c1 - c2);
|
R.y = (1.0f / height) * (c1 - c2);
|
||||||
b3ComputeBasis(R.y, R.z, R.x);
|
b3ComputeBasis(R.y, R.z, R.x);
|
||||||
|
|
||||||
b3Quat Q = b3Mat33Quat(R);
|
|
||||||
|
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.translation = 0.5f * (c1 + c2);
|
xf.position = 0.5f * (c1 + c2);
|
||||||
xf.rotation = Q;
|
xf.rotation = R;
|
||||||
|
|
||||||
m_solid->DrawCylinder(radius, height, c, xf);
|
m_solid->DrawCylinder(radius, height, c, xf);
|
||||||
}
|
}
|
||||||
@ -374,7 +369,7 @@ void Draw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, scalar radius, c
|
|||||||
{
|
{
|
||||||
b3Transform xf;
|
b3Transform xf;
|
||||||
xf.rotation = rotation;
|
xf.rotation = rotation;
|
||||||
xf.translation = c2;
|
xf.position = c2;
|
||||||
m_solid->DrawSphere(radius, c, xf);
|
m_solid->DrawSphere(radius, c, xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,24 +377,24 @@ void Draw::DrawSolidCapsule(const b3Vec3& c1, const b3Vec3& c2, scalar radius, c
|
|||||||
|
|
||||||
void Draw::DrawTransform(const b3Transform& xf)
|
void Draw::DrawTransform(const b3Transform& xf)
|
||||||
{
|
{
|
||||||
scalar lenght = 1.0f;
|
float32 lenght = 1.0f;
|
||||||
|
|
||||||
b3Vec3 translation = xf.translation;
|
b3Vec3 position = xf.position;
|
||||||
b3Mat33 rotation = b3QuatMat33(xf.rotation);
|
b3Mat33 rotation = xf.rotation;
|
||||||
|
|
||||||
b3Vec3 A = translation + lenght * rotation.x;
|
b3Vec3 A = position + lenght * rotation.x;
|
||||||
b3Vec3 B = translation + lenght * rotation.y;
|
b3Vec3 B = position + lenght * rotation.y;
|
||||||
b3Vec3 C = translation + lenght * rotation.z;
|
b3Vec3 C = position + lenght * rotation.z;
|
||||||
|
|
||||||
DrawSegment(translation, A, b3Color_red);
|
DrawSegment(position, A, b3Color_red);
|
||||||
DrawSegment(translation, B, b3Color_green);
|
DrawSegment(position, B, b3Color_green);
|
||||||
DrawSegment(translation, C, b3Color_blue);
|
DrawSegment(position, C, b3Color_blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawAABB(const b3AABB& aabb, const b3Color& color)
|
void Draw::DrawAABB(const b3AABB3& aabb, const b3Color& color)
|
||||||
{
|
{
|
||||||
b3Vec3 lower = aabb.lowerBound;
|
b3Vec3 lower = aabb.m_lower;
|
||||||
b3Vec3 upper = aabb.upperBound;
|
b3Vec3 upper = aabb.m_upper;
|
||||||
|
|
||||||
b3Vec3 vs[8];
|
b3Vec3 vs[8];
|
||||||
|
|
||||||
@ -430,12 +425,12 @@ void Draw::DrawAABB(const b3AABB& aabb, const b3Color& color)
|
|||||||
DrawSegment(vs[1], vs[7], color);
|
DrawSegment(vs[1], vs[7], color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawPlane(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color)
|
void Draw::DrawPlane(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
|
||||||
{
|
{
|
||||||
b3Vec3 n1, n2;
|
b3Vec3 n1, n2;
|
||||||
b3ComputeBasis(normal, n1, n2);
|
b3ComputeBasis(normal, n1, n2);
|
||||||
|
|
||||||
scalar scale = 2.0f * radius;
|
float32 scale = 2.0f * radius;
|
||||||
|
|
||||||
// v1__v4
|
// v1__v4
|
||||||
// | |
|
// | |
|
||||||
@ -453,14 +448,14 @@ void Draw::DrawPlane(const b3Vec3& normal, const b3Vec3& center, scalar radius,
|
|||||||
DrawSegment(center, center + normal, color);
|
DrawSegment(center, center + normal, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw::DrawSolidPlane(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color)
|
void Draw::DrawSolidPlane(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color)
|
||||||
{
|
{
|
||||||
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
|
b3Color frameColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 1.0f);
|
||||||
|
|
||||||
b3Vec3 n1, n2;
|
b3Vec3 n1, n2;
|
||||||
b3ComputeBasis(normal, n1, n2);
|
b3ComputeBasis(normal, n1, n2);
|
||||||
|
|
||||||
scalar scale = 2.0f * radius;
|
float32 scale = 2.0f * radius;
|
||||||
|
|
||||||
b3Vec3 v1 = center - scale * n1 - scale * n2;
|
b3Vec3 v1 = center - scale * n1 - scale * n2;
|
||||||
b3Vec3 v2 = center + scale * n1 - scale * n2;
|
b3Vec3 v2 = center + scale * n1 - scale * n2;
|
||||||
|
@ -42,13 +42,13 @@ public:
|
|||||||
b3Vec2 ConvertWorldToScreen(const b3Vec3& pw) const;
|
b3Vec2 ConvertWorldToScreen(const b3Vec3& pw) const;
|
||||||
b3Ray3 ConvertScreenToWorld(const b3Vec2& ps) const;
|
b3Ray3 ConvertScreenToWorld(const b3Vec2& ps) const;
|
||||||
|
|
||||||
scalar m_zoom;
|
float32 m_zoom;
|
||||||
b3Vec3 m_center;
|
b3Vec3 m_center;
|
||||||
b3Quat m_q;
|
b3Quat m_q;
|
||||||
scalar m_width, m_height;
|
float32 m_width, m_height;
|
||||||
scalar m_fovy;
|
float32 m_fovy;
|
||||||
scalar m_zNear;
|
float32 m_zNear;
|
||||||
scalar m_zFar;
|
float32 m_zFar;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Draw : public b3Draw
|
class Draw : public b3Draw
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
|
|
||||||
void EnableDrawTriangles(bool flag);
|
void EnableDrawTriangles(bool flag);
|
||||||
|
|
||||||
void DrawPoint(const b3Vec3& p, scalar size, const b3Color& color);
|
void DrawPoint(const b3Vec3& p, float32 size, const b3Color& color);
|
||||||
|
|
||||||
void DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color);
|
void DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color);
|
||||||
|
|
||||||
@ -79,23 +79,23 @@ public:
|
|||||||
|
|
||||||
void DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color);
|
void DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color);
|
||||||
|
|
||||||
void DrawCircle(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color);
|
void DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color);
|
||||||
|
|
||||||
void DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color);
|
void DrawSolidCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color);
|
||||||
|
|
||||||
void DrawSphere(const b3Vec3& center, scalar radius, const b3Color& color);
|
void DrawSphere(const b3Vec3& center, float32 radius, const b3Color& color);
|
||||||
|
|
||||||
void DrawSolidSphere(const b3Vec3& center, scalar radius, const b3Quat& rotation, const b3Color& color);
|
void DrawSolidSphere(const b3Vec3& center, float32 radius, const b3Mat33& rotation, const b3Color& color);
|
||||||
|
|
||||||
void DrawCapsule(const b3Vec3& p1, const b3Vec3& p2, scalar radius, const b3Color& color);
|
void DrawCapsule(const b3Vec3& p1, const b3Vec3& p2, float32 radius, const b3Color& color);
|
||||||
|
|
||||||
void DrawSolidCapsule(const b3Vec3& p1, const b3Vec3& p2, scalar radius, const b3Quat& rotation, const b3Color& color);
|
void DrawSolidCapsule(const b3Vec3& p1, const b3Vec3& p2, float32 radius, const b3Mat33& rotation, const b3Color& color);
|
||||||
|
|
||||||
void DrawPlane(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color);
|
void DrawPlane(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color);
|
||||||
|
|
||||||
void DrawSolidPlane(const b3Vec3& normal, const b3Vec3& center, scalar radius, const b3Color& color);
|
void DrawSolidPlane(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color);
|
||||||
|
|
||||||
void DrawAABB(const b3AABB& aabb, const b3Color& color);
|
void DrawAABB(const b3AABB3& aabb, const b3Color& color);
|
||||||
|
|
||||||
void DrawTransform(const b3Transform& xf);
|
void DrawTransform(const b3Transform& xf);
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ struct DrawPoints
|
|||||||
glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Color), m_colors, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(b3Color), m_colors, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
||||||
glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(scalar), m_sizes, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(float32), m_sizes, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
AssertGL();
|
AssertGL();
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ struct DrawPoints
|
|||||||
glDeleteBuffers(3, m_vboIds);
|
glDeleteBuffers(3, m_vboIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vertex(const b3Vec3& v, scalar size, const b3Color& color)
|
void Vertex(const b3Vec3& v, float32 size, const b3Color& color)
|
||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
@ -226,7 +226,7 @@ struct DrawPoints
|
|||||||
glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(scalar), m_sizes);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(float32), m_sizes);
|
||||||
glEnableVertexAttribArray(m_sizeAttribute);
|
glEnableVertexAttribArray(m_sizeAttribute);
|
||||||
glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ struct DrawPoints
|
|||||||
|
|
||||||
b3Vec3 m_vertices[e_vertexCapacity];
|
b3Vec3 m_vertices[e_vertexCapacity];
|
||||||
b3Color m_colors[e_vertexCapacity];
|
b3Color m_colors[e_vertexCapacity];
|
||||||
scalar m_sizes[e_vertexCapacity];
|
float32 m_sizes[e_vertexCapacity];
|
||||||
u32 m_count;
|
u32 m_count;
|
||||||
|
|
||||||
GLuint m_programId;
|
GLuint m_programId;
|
||||||
@ -365,7 +365,7 @@ struct DrawLines
|
|||||||
|
|
||||||
glDisableVertexAttribArray(m_colorAttribute);
|
glDisableVertexAttribArray(m_colorAttribute);
|
||||||
|
|
||||||
glDisableVertexAttribArray(m_vertexAttribute);
|
glEnableVertexAttribArray(m_vertexAttribute);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
@ -608,7 +608,7 @@ struct DrawWire
|
|||||||
glDeleteProgram(m_programId);
|
glDeleteProgram(m_programId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawSphere(scalar radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
if (!g_glDrawLines)
|
if (!g_glDrawLines)
|
||||||
{
|
{
|
||||||
@ -777,7 +777,7 @@ struct DrawSolid
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawCylinder(scalar radius, scalar height, const b3Color& c, const b3Transform& xf)
|
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
if (!g_glDrawTriangles)
|
if (!g_glDrawTriangles)
|
||||||
{
|
{
|
||||||
@ -820,7 +820,7 @@ struct DrawSolid
|
|||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawSphere(scalar radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
if (!g_glDrawTriangles)
|
if (!g_glDrawTriangles)
|
||||||
{
|
{
|
||||||
@ -874,4 +874,4 @@ struct DrawSolid
|
|||||||
DrawSolidCylinder m_cylinder;
|
DrawSolidCylinder m_cylinder;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -178,7 +178,7 @@ struct DrawPoints
|
|||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
||||||
glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||||
glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(scalar), m_sizes, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, e_vertexCapacity * sizeof(float32), m_sizes, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
AssertGL();
|
AssertGL();
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ struct DrawPoints
|
|||||||
glDeleteBuffers(3, m_vboIds);
|
glDeleteBuffers(3, m_vboIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vertex(const b3Vec3& v, scalar size, const b3Color& color)
|
void Vertex(const b3Vec3& v, float32 size, const b3Color& color)
|
||||||
{
|
{
|
||||||
if (m_count == e_vertexCapacity)
|
if (m_count == e_vertexCapacity)
|
||||||
{
|
{
|
||||||
@ -238,7 +238,7 @@ struct DrawPoints
|
|||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Color), m_colors);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b3Color), m_colors);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(scalar), m_sizes);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(float32), m_sizes);
|
||||||
|
|
||||||
glEnable(GL_PROGRAM_POINT_SIZE);
|
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||||
glDrawArrays(GL_POINTS, 0, m_count);
|
glDrawArrays(GL_POINTS, 0, m_count);
|
||||||
@ -260,7 +260,7 @@ struct DrawPoints
|
|||||||
|
|
||||||
b3Vec3 m_vertices[e_vertexCapacity];
|
b3Vec3 m_vertices[e_vertexCapacity];
|
||||||
b3Color m_colors[e_vertexCapacity];
|
b3Color m_colors[e_vertexCapacity];
|
||||||
scalar m_sizes[e_vertexCapacity];
|
float32 m_sizes[e_vertexCapacity];
|
||||||
u32 m_count;
|
u32 m_count;
|
||||||
|
|
||||||
GLuint m_programId;
|
GLuint m_programId;
|
||||||
@ -625,7 +625,7 @@ struct DrawWire
|
|||||||
glDeleteProgram(m_programId);
|
glDeleteProgram(m_programId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawSphere(scalar radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
if (!g_glDrawLines)
|
if (!g_glDrawLines)
|
||||||
{
|
{
|
||||||
@ -792,7 +792,7 @@ struct DrawSolid
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawCylinder(scalar radius, scalar height, const b3Color& c, const b3Transform& xf)
|
void DrawCylinder(float32 radius, float32 height, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
if (!g_glDrawTriangles)
|
if (!g_glDrawTriangles)
|
||||||
{
|
{
|
||||||
@ -831,7 +831,7 @@ struct DrawSolid
|
|||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawSphere(scalar radius, const b3Color& c, const b3Transform& xf)
|
void DrawSphere(float32 radius, const b3Color& c, const b3Transform& xf)
|
||||||
{
|
{
|
||||||
if (!g_glDrawTriangles)
|
if (!g_glDrawTriangles)
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,7 @@ void JsonProfiler::EndEvents()
|
|||||||
m_file = nullptr;
|
m_file = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonProfiler::BeginEvent(const char* name, scalar64 t)
|
void JsonProfiler::BeginEvent(const char* name, float64 t)
|
||||||
{
|
{
|
||||||
if (!m_writer)
|
if (!m_writer)
|
||||||
{
|
{
|
||||||
@ -86,7 +86,7 @@ void JsonProfiler::BeginEvent(const char* name, scalar64 t)
|
|||||||
|
|
||||||
const char* phase = "B";
|
const char* phase = "B";
|
||||||
|
|
||||||
scalar64 scale = 1000.0;
|
float64 scale = 1000.0;
|
||||||
|
|
||||||
m_writer->StartObject();
|
m_writer->StartObject();
|
||||||
m_writer->STRING("pid"); m_writer->Int(0);
|
m_writer->STRING("pid"); m_writer->Int(0);
|
||||||
@ -99,7 +99,7 @@ void JsonProfiler::BeginEvent(const char* name, scalar64 t)
|
|||||||
m_writer->EndObject();
|
m_writer->EndObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonProfiler::EndEvent(const char* name, scalar64 t)
|
void JsonProfiler::EndEvent(const char* name, float64 t)
|
||||||
{
|
{
|
||||||
if (!m_writer)
|
if (!m_writer)
|
||||||
{
|
{
|
||||||
@ -108,7 +108,7 @@ void JsonProfiler::EndEvent(const char* name, scalar64 t)
|
|||||||
|
|
||||||
const char* phase = "E";
|
const char* phase = "E";
|
||||||
|
|
||||||
scalar64 scale = 1000.0;
|
float64 scale = 1000.0;
|
||||||
|
|
||||||
m_writer->StartObject();
|
m_writer->StartObject();
|
||||||
m_writer->STRING("pid"); m_writer->Int(0);
|
m_writer->STRING("pid"); m_writer->Int(0);
|
||||||
|
@ -43,9 +43,9 @@ public:
|
|||||||
|
|
||||||
void EndEvents();
|
void EndEvents();
|
||||||
|
|
||||||
void BeginEvent(const char* name, scalar64 time);
|
void BeginEvent(const char* name, float64 time);
|
||||||
|
|
||||||
void EndEvent(const char* name, scalar64 time);
|
void EndEvent(const char* name, float64 time);
|
||||||
private:
|
private:
|
||||||
FILE* m_file;
|
FILE* m_file;
|
||||||
FileWriteStream* m_stream;
|
FileWriteStream* m_stream;
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
// error
|
// error
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <glfw/glfw3.h>
|
#include <glfw/glfw3.h>
|
||||||
|
|
||||||
#include <testbed/framework/model.h>
|
#include <testbed/framework/model.h>
|
||||||
@ -105,12 +103,14 @@ static void Run()
|
|||||||
|
|
||||||
while (glfwWindowShouldClose(g_window) == 0)
|
while (glfwWindowShouldClose(g_window) == 0)
|
||||||
{
|
{
|
||||||
g_frameAllocator->Reset();
|
|
||||||
|
|
||||||
g_profiler->Begin();
|
g_profiler->Begin();
|
||||||
|
|
||||||
|
g_profilerSt->Begin();
|
||||||
|
|
||||||
g_profiler->BeginScope("Frame");
|
g_profiler->BeginScope("Frame");
|
||||||
|
|
||||||
|
g_profilerSt->BeginScope("Frame");
|
||||||
|
|
||||||
g_view->BeginInterface();
|
g_view->BeginInterface();
|
||||||
|
|
||||||
if (g_model->IsPaused())
|
if (g_model->IsPaused())
|
||||||
@ -126,13 +126,22 @@ static void Run()
|
|||||||
|
|
||||||
g_model->Update();
|
g_model->Update();
|
||||||
|
|
||||||
|
g_profilerSt->EndScope();
|
||||||
|
|
||||||
g_profiler->EndScope();
|
g_profiler->EndScope();
|
||||||
|
|
||||||
if (g_settings->drawProfiler)
|
if (g_settings->drawProfileTree)
|
||||||
{
|
{
|
||||||
g_view->InterfaceProfiler();
|
g_view->InterfaceProfileTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_settings->drawProfileTreeStats)
|
||||||
|
{
|
||||||
|
g_view->InterfaceProfileTreeStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_profilerSt->End();
|
||||||
|
|
||||||
#if PROFILE_JSON == 1
|
#if PROFILE_JSON == 1
|
||||||
g_model->UpdateJson();
|
g_model->UpdateJson();
|
||||||
#endif
|
#endif
|
||||||
@ -151,7 +160,7 @@ int main(int argc, char** args)
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Report memory leaks
|
// Report memory leaks
|
||||||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
|
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
|
||||||
//_CrtSetBreakAlloc();
|
//_CrtSetBreakAlloc(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (glfwInit() == 0)
|
if (glfwInit() == 0)
|
||||||
@ -177,7 +186,7 @@ int main(int argc, char** args)
|
|||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
glfwMakeContextCurrent(g_window);
|
glfwMakeContextCurrent(g_window);
|
||||||
|
|
||||||
if (gladLoadGL() == 0)
|
if (gladLoadGL() == 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to load OpenGL extensions\n");
|
fprintf(stderr, "Failed to load OpenGL extensions\n");
|
||||||
|
@ -20,17 +20,14 @@
|
|||||||
#include <testbed/framework/view_model.h>
|
#include <testbed/framework/view_model.h>
|
||||||
#include <testbed/framework/test.h>
|
#include <testbed/framework/test.h>
|
||||||
|
|
||||||
b3FrameAllocator* g_frameAllocator = nullptr;
|
|
||||||
b3Profiler* g_profiler = nullptr;
|
|
||||||
|
|
||||||
Model::Model()
|
Model::Model()
|
||||||
{
|
{
|
||||||
m_viewModel = nullptr;
|
m_viewModel = nullptr;
|
||||||
g_draw = &m_draw;
|
g_draw = &m_draw;
|
||||||
g_camera = &m_camera;
|
g_camera = &m_camera;
|
||||||
g_profiler = &m_profiler;
|
g_profiler = &m_profiler;
|
||||||
g_frameAllocator = &m_frame;
|
g_profilerSt = &m_profilerSt;
|
||||||
|
|
||||||
#if (PROFILE_JSON == 1)
|
#if (PROFILE_JSON == 1)
|
||||||
g_jsonProfiler = &m_jsonProfiler;
|
g_jsonProfiler = &m_jsonProfiler;
|
||||||
#endif
|
#endif
|
||||||
@ -44,7 +41,7 @@ Model::Model()
|
|||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
|
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
|
||||||
glClearDepth(1.0f);
|
glClearDepth(1.0f);
|
||||||
|
|
||||||
Action_ResetCamera();
|
Action_ResetCamera();
|
||||||
@ -59,7 +56,7 @@ Model::~Model()
|
|||||||
g_draw = nullptr;
|
g_draw = nullptr;
|
||||||
g_camera = nullptr;
|
g_camera = nullptr;
|
||||||
g_profiler = nullptr;
|
g_profiler = nullptr;
|
||||||
g_frameAllocator = nullptr;
|
g_profilerSt = nullptr;
|
||||||
|
|
||||||
#if (PROFILE_JSON == 1)
|
#if (PROFILE_JSON == 1)
|
||||||
g_jsonProfiler = nullptr;
|
g_jsonProfiler = nullptr;
|
||||||
@ -117,11 +114,11 @@ void Model::Update()
|
|||||||
|
|
||||||
if (m_setTest)
|
if (m_setTest)
|
||||||
{
|
{
|
||||||
Action_ResetCamera();
|
|
||||||
delete m_test;
|
delete m_test;
|
||||||
m_test = g_tests[g_settings->testID].create();
|
m_test = g_tests[g_settings->testID].create();
|
||||||
m_setTest = false;
|
m_setTest = false;
|
||||||
m_pause = true;
|
m_pause = true;
|
||||||
|
Action_ResetCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_settings->drawGrid)
|
if (g_settings->drawGrid)
|
||||||
@ -132,9 +129,9 @@ void Model::Update()
|
|||||||
b3Vec3 vs[h * w];
|
b3Vec3 vs[h * w];
|
||||||
|
|
||||||
b3Vec3 t;
|
b3Vec3 t;
|
||||||
t.x = -0.5f * scalar(w) + 0.5f;
|
t.x = -0.5f * float32(w) + 0.5f;
|
||||||
t.y = 0.0f;
|
t.y = 0.0f;
|
||||||
t.z = -0.5f * scalar(h) + 0.5f;
|
t.z = -0.5f * float32(h) + 0.5f;
|
||||||
|
|
||||||
for (u32 i = 0; i < h; ++i)
|
for (u32 i = 0; i < h; ++i)
|
||||||
{
|
{
|
||||||
@ -143,9 +140,9 @@ void Model::Update()
|
|||||||
u32 iv = i * w + j;
|
u32 iv = i * w + j;
|
||||||
|
|
||||||
b3Vec3 v;
|
b3Vec3 v;
|
||||||
v.x = scalar(j);
|
v.x = float32(j);
|
||||||
v.y = 0.0f;
|
v.y = 0.0f;
|
||||||
v.z = scalar(i);
|
v.z = float32(i);
|
||||||
|
|
||||||
v += t;
|
v += t;
|
||||||
|
|
||||||
@ -153,55 +150,57 @@ void Model::Update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Color borderColor(0.0f, 0.0f, 0.0f, 1.0f);
|
b3Color color(0.2f, 0.2f, 0.2f, 1.0f);
|
||||||
b3Color centerColor(0.8f, 0.8f, 0.8f, 1.0f);
|
|
||||||
b3Color color(0.4f, 0.4f, 0.4f, 1.0f);
|
|
||||||
|
|
||||||
// Left to right lines
|
// Left-Right Lines
|
||||||
|
u32 hv1 = (h - 1) / 2 * w + 0;
|
||||||
|
u32 hv2 = (h - 1) / 2 * w + (w - 1);
|
||||||
|
{
|
||||||
|
b3Vec3 v1 = vs[hv1];
|
||||||
|
b3Vec3 v2 = vs[hv2];
|
||||||
|
|
||||||
|
b3Draw_draw->DrawSegment(v1, v2, b3Color_black);
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < h; ++i)
|
for (u32 i = 0; i < h; ++i)
|
||||||
{
|
{
|
||||||
|
if (i == hv1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
u32 iv1 = i * w + 0;
|
u32 iv1 = i * w + 0;
|
||||||
u32 iv2 = i * w + (w - 1);
|
u32 iv2 = i * w + (w - 1);
|
||||||
|
|
||||||
b3Vec3 v1 = vs[iv1];
|
b3Vec3 v1 = vs[iv1];
|
||||||
b3Vec3 v2 = vs[iv2];
|
b3Vec3 v2 = vs[iv2];
|
||||||
|
|
||||||
if (i == 0 || i == (h - 1))
|
|
||||||
{
|
|
||||||
b3Draw_draw->DrawSegment(v1, v2, borderColor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == (h - 1) / 2)
|
|
||||||
{
|
|
||||||
b3Draw_draw->DrawSegment(v1, v2, centerColor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Draw_draw->DrawSegment(v1, v2, color);
|
b3Draw_draw->DrawSegment(v1, v2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Up to bottom lines
|
// Up-Bottom Lines
|
||||||
|
u32 wv1 = 0 * w + (w - 1) / 2;
|
||||||
|
u32 wv2 = (h - 1) * w + (w - 1) / 2;
|
||||||
|
{
|
||||||
|
b3Vec3 v1 = vs[wv1];
|
||||||
|
b3Vec3 v2 = vs[wv2];
|
||||||
|
|
||||||
|
b3Draw_draw->DrawSegment(v1, v2, b3Color_black);
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 j = 0; j < w; ++j)
|
for (u32 j = 0; j < w; ++j)
|
||||||
{
|
{
|
||||||
|
if (j == wv1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
u32 iv1 = 0 * w + j;
|
u32 iv1 = 0 * w + j;
|
||||||
u32 iv2 = (h - 1) * w + j;
|
u32 iv2 = (h - 1) * w + j;
|
||||||
|
|
||||||
b3Vec3 v1 = vs[iv1];
|
b3Vec3 v1 = vs[iv1];
|
||||||
b3Vec3 v2 = vs[iv2];
|
b3Vec3 v2 = vs[iv2];
|
||||||
|
|
||||||
if (j == 0 || j == (w - 1))
|
|
||||||
{
|
|
||||||
b3Draw_draw->DrawSegment(v1, v2, borderColor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == (w - 1) / 2)
|
|
||||||
{
|
|
||||||
b3Draw_draw->DrawSegment(v1, v2, centerColor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Draw_draw->DrawSegment(v1, v2, color);
|
b3Draw_draw->DrawSegment(v1, v2, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,17 +233,15 @@ void Model::Update()
|
|||||||
|
|
||||||
#if (PROFILE_JSON == 1)
|
#if (PROFILE_JSON == 1)
|
||||||
|
|
||||||
static inline void RecurseEvents(b3ProfilerNode* node)
|
static inline void RecurseEvents(ProfilerNode* node)
|
||||||
{
|
{
|
||||||
g_jsonProfiler->BeginEvent(node->name, node->t0);
|
g_jsonProfiler->BeginEvent(node->name, node->t0);
|
||||||
|
|
||||||
g_jsonProfiler->EndEvent(node->name, node->t1);
|
g_jsonProfiler->EndEvent(node->name, node->t1);
|
||||||
|
|
||||||
b3ProfilerNode* child = node->head;
|
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||||
while (child)
|
|
||||||
{
|
{
|
||||||
RecurseEvents(child);
|
RecurseEvents(node->children[i]);
|
||||||
child = child->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +249,7 @@ void Model::UpdateJson()
|
|||||||
{
|
{
|
||||||
m_jsonProfiler.BeginEvents();
|
m_jsonProfiler.BeginEvents();
|
||||||
|
|
||||||
b3ProfilerNode* root = m_profiler.GetRoot();
|
ProfilerNode* root = m_profiler.GetRoot();
|
||||||
|
|
||||||
if (root)
|
if (root)
|
||||||
{
|
{
|
||||||
|
@ -20,11 +20,8 @@
|
|||||||
#define MODEL_H
|
#define MODEL_H
|
||||||
|
|
||||||
#include <testbed/framework/draw.h>
|
#include <testbed/framework/draw.h>
|
||||||
#include <bounce/common/profiler.h>
|
#include <testbed/framework/profiler.h>
|
||||||
|
#include <testbed/framework/profiler_st.h>
|
||||||
extern b3FrameAllocator* g_frameAllocator;
|
|
||||||
|
|
||||||
extern b3Profiler* g_profiler;
|
|
||||||
|
|
||||||
// Set to 1 to write profile events into a .json file. Set to 0 otherwise.
|
// Set to 1 to write profile events into a .json file. Set to 0 otherwise.
|
||||||
#define PROFILE_JSON 0
|
#define PROFILE_JSON 0
|
||||||
@ -56,12 +53,12 @@ public:
|
|||||||
void Command_Release_Mouse_Left(const b3Vec2& ps);
|
void Command_Release_Mouse_Left(const b3Vec2& ps);
|
||||||
void Command_Move_Cursor(const b3Vec2& ps);
|
void Command_Move_Cursor(const b3Vec2& ps);
|
||||||
|
|
||||||
void Command_ResizeCamera(scalar w, scalar h);
|
void Command_ResizeCamera(float32 w, float32 h);
|
||||||
void Command_RotateCameraX(scalar angle);
|
void Command_RotateCameraX(float32 angle);
|
||||||
void Command_RotateCameraY(scalar angle);
|
void Command_RotateCameraY(float32 angle);
|
||||||
void Command_TranslateCameraX(scalar d);
|
void Command_TranslateCameraX(float32 d);
|
||||||
void Command_TranslateCameraY(scalar d);
|
void Command_TranslateCameraY(float32 d);
|
||||||
void Command_ZoomCamera(scalar d);
|
void Command_ZoomCamera(float32 d);
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
@ -77,8 +74,8 @@ private:
|
|||||||
|
|
||||||
Draw m_draw;
|
Draw m_draw;
|
||||||
Camera m_camera;
|
Camera m_camera;
|
||||||
b3FrameAllocator m_frame;
|
Profiler m_profiler;
|
||||||
b3Profiler m_profiler;
|
ProfilerSt m_profilerSt;
|
||||||
|
|
||||||
#if (PROFILE_JSON == 1)
|
#if (PROFILE_JSON == 1)
|
||||||
JsonProfiler m_jsonProfiler;
|
JsonProfiler m_jsonProfiler;
|
||||||
@ -118,13 +115,13 @@ inline void Model::Action_ResetCamera()
|
|||||||
m_camera.m_zoom = 50.0f;
|
m_camera.m_zoom = 50.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Model::Command_ResizeCamera(scalar w, scalar h)
|
inline void Model::Command_ResizeCamera(float32 w, float32 h)
|
||||||
{
|
{
|
||||||
m_camera.m_width = w;
|
m_camera.m_width = w;
|
||||||
m_camera.m_height = h;
|
m_camera.m_height = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Model::Command_RotateCameraX(scalar angle)
|
inline void Model::Command_RotateCameraX(float32 angle)
|
||||||
{
|
{
|
||||||
b3Quat d = b3QuatRotationX(angle);
|
b3Quat d = b3QuatRotationX(angle);
|
||||||
|
|
||||||
@ -132,7 +129,7 @@ inline void Model::Command_RotateCameraX(scalar angle)
|
|||||||
m_camera.m_q.Normalize();
|
m_camera.m_q.Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Model::Command_RotateCameraY(scalar angle)
|
inline void Model::Command_RotateCameraY(float32 angle)
|
||||||
{
|
{
|
||||||
b3Quat d = b3QuatRotationY(angle);
|
b3Quat d = b3QuatRotationY(angle);
|
||||||
|
|
||||||
@ -140,21 +137,21 @@ inline void Model::Command_RotateCameraY(scalar angle)
|
|||||||
m_camera.m_q.Normalize();
|
m_camera.m_q.Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Model::Command_TranslateCameraX(scalar d)
|
inline void Model::Command_TranslateCameraX(float32 d)
|
||||||
{
|
{
|
||||||
b3Transform transform = m_camera.BuildWorldTransform();
|
b3Transform transform = m_camera.BuildWorldTransform();
|
||||||
|
|
||||||
m_camera.m_center += d * transform.rotation.GetXAxis();
|
m_camera.m_center += d * transform.rotation.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Model::Command_TranslateCameraY(scalar d)
|
inline void Model::Command_TranslateCameraY(float32 d)
|
||||||
{
|
{
|
||||||
b3Transform transform = m_camera.BuildWorldTransform();
|
b3Transform transform = m_camera.BuildWorldTransform();
|
||||||
|
|
||||||
m_camera.m_center += d * transform.rotation.GetYAxis();
|
m_camera.m_center += d * transform.rotation.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Model::Command_ZoomCamera(scalar d)
|
inline void Model::Command_ZoomCamera(float32 d)
|
||||||
{
|
{
|
||||||
m_camera.m_zoom += d;
|
m_camera.m_zoom += d;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ b3SoftBodyDragger::b3SoftBodyDragger(b3Ray3* ray, b3SoftBody* body)
|
|||||||
{
|
{
|
||||||
m_ray = ray;
|
m_ray = ray;
|
||||||
m_body = body;
|
m_body = body;
|
||||||
m_isDragging = false;
|
m_tetrahedron = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
b3SoftBodyDragger::~b3SoftBodyDragger()
|
b3SoftBodyDragger::~b3SoftBodyDragger()
|
||||||
@ -40,45 +40,41 @@ bool b3SoftBodyDragger::StartDragging()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isDragging = true;
|
m_mesh = m_body->GetMesh();
|
||||||
|
m_tetrahedron = m_mesh->tetrahedrons + rayOut.tetrahedron;
|
||||||
|
m_v1 = m_tetrahedron->v1;
|
||||||
|
m_v2 = m_tetrahedron->v2;
|
||||||
|
m_v3 = m_tetrahedron->v3;
|
||||||
|
m_v4 = m_tetrahedron->v4;
|
||||||
m_x = rayOut.fraction;
|
m_x = rayOut.fraction;
|
||||||
|
|
||||||
const b3SoftBodyMesh* mesh = m_body->GetMesh();
|
b3SoftBodyNode* n1 = m_body->GetVertexNode(m_v1);
|
||||||
const b3SoftBodyMeshTriangle* triangle = mesh->triangles + rayOut.triangle;
|
b3SoftBodyNode* n2 = m_body->GetVertexNode(m_v2);
|
||||||
|
b3SoftBodyNode* n3 = m_body->GetVertexNode(m_v3);
|
||||||
|
b3SoftBodyNode* n4 = m_body->GetVertexNode(m_v4);
|
||||||
|
|
||||||
m_n1 = m_body->GetNode(triangle->v1);
|
b3Vec3 v1 = n1->GetPosition();
|
||||||
m_n2 = m_body->GetNode(triangle->v2);
|
b3Vec3 v2 = n2->GetPosition();
|
||||||
m_n3 = m_body->GetNode(triangle->v3);
|
b3Vec3 v3 = n3->GetPosition();
|
||||||
|
b3Vec3 v4 = n4->GetPosition();
|
||||||
b3Vec3 v1 = m_n1->GetPosition();
|
|
||||||
b3Vec3 v2 = m_n2->GetPosition();
|
|
||||||
b3Vec3 v3 = m_n3->GetPosition();
|
|
||||||
|
|
||||||
b3Vec3 B = GetPointB();
|
b3Vec3 B = GetPointB();
|
||||||
|
|
||||||
scalar wABC[4];
|
float32 wABCD[5];
|
||||||
b3BarycentricCoordinates(wABC, v1, v2, v3, B);
|
b3BarycentricCoordinates(wABCD, v1, v2, v3, v4, B);
|
||||||
|
|
||||||
if (wABC[3] > B3_EPSILON)
|
if (wABCD[4] > B3_EPSILON)
|
||||||
{
|
{
|
||||||
m_tu = wABC[0] / wABC[3];
|
m_tu = wABCD[0] / wABCD[4];
|
||||||
m_tv = wABC[1] / wABC[3];
|
m_tv = wABCD[1] / wABCD[4];
|
||||||
m_tw = wABC[2] / wABC[3];
|
m_tw = wABCD[2] / wABCD[4];
|
||||||
|
m_tx = wABCD[3] / wABCD[4];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_tu = m_tv = m_tw = 0.0f;
|
m_tu = m_tv = m_tw = m_tx = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_t1 = m_n1->GetType();
|
|
||||||
m_n1->SetType(e_staticSoftBodyNode);
|
|
||||||
|
|
||||||
m_t2 = m_n2->GetType();
|
|
||||||
m_n2->SetType(e_staticSoftBodyNode);
|
|
||||||
|
|
||||||
m_t3 = m_n3->GetType();
|
|
||||||
m_n3->SetType(e_staticSoftBodyNode);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,31 +87,38 @@ void b3SoftBodyDragger::Drag()
|
|||||||
|
|
||||||
b3Vec3 dx = B - A;
|
b3Vec3 dx = B - A;
|
||||||
|
|
||||||
m_n1->ApplyTranslation(dx);
|
const float32 k = 100.0f;
|
||||||
m_n2->ApplyTranslation(dx);
|
|
||||||
m_n3->ApplyTranslation(dx);
|
b3Vec3 f = k * dx;
|
||||||
|
|
||||||
|
b3Vec3 f1 = m_tu * f;
|
||||||
|
b3Vec3 f2 = m_tv * f;
|
||||||
|
b3Vec3 f3 = m_tw * f;
|
||||||
|
b3Vec3 f4 = m_tx * f;
|
||||||
|
|
||||||
|
m_body->GetVertexNode(m_v1)->ApplyForce(f1);
|
||||||
|
m_body->GetVertexNode(m_v2)->ApplyForce(f2);
|
||||||
|
m_body->GetVertexNode(m_v3)->ApplyForce(f3);
|
||||||
|
m_body->GetVertexNode(m_v4)->ApplyForce(f4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void b3SoftBodyDragger::StopDragging()
|
void b3SoftBodyDragger::StopDragging()
|
||||||
{
|
{
|
||||||
B3_ASSERT(IsDragging() == true);
|
B3_ASSERT(IsDragging() == true);
|
||||||
|
|
||||||
m_n1->SetType(m_t1);
|
m_tetrahedron = nullptr;
|
||||||
m_n2->SetType(m_t2);
|
|
||||||
m_n3->SetType(m_t3);
|
|
||||||
|
|
||||||
m_isDragging = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 b3SoftBodyDragger::GetPointA() const
|
b3Vec3 b3SoftBodyDragger::GetPointA() const
|
||||||
{
|
{
|
||||||
B3_ASSERT(IsDragging() == true);
|
B3_ASSERT(IsDragging() == true);
|
||||||
|
|
||||||
b3Vec3 A = m_n1->GetPosition() + m_n1->GetTranslation();
|
b3Vec3 A = m_body->GetVertexNode(m_v1)->GetPosition();
|
||||||
b3Vec3 B = m_n2->GetPosition() + m_n2->GetTranslation();
|
b3Vec3 B = m_body->GetVertexNode(m_v2)->GetPosition();
|
||||||
b3Vec3 C = m_n3->GetPosition() + m_n3->GetTranslation();
|
b3Vec3 C = m_body->GetVertexNode(m_v3)->GetPosition();
|
||||||
|
b3Vec3 D = m_body->GetVertexNode(m_v4)->GetPosition();
|
||||||
|
|
||||||
return m_tu * A + m_tv * B + m_tw * C;
|
return m_tu * A + m_tv * B + m_tw * C + m_tx * D;
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 b3SoftBodyDragger::GetPointB() const
|
b3Vec3 b3SoftBodyDragger::GetPointB() const
|
||||||
|
@ -44,18 +44,18 @@ public:
|
|||||||
b3Vec3 GetPointB() const;
|
b3Vec3 GetPointB() const;
|
||||||
private:
|
private:
|
||||||
b3Ray3* m_ray;
|
b3Ray3* m_ray;
|
||||||
b3SoftBody* m_body;
|
float32 m_x;
|
||||||
|
|
||||||
bool m_isDragging;
|
b3SoftBody* m_body;
|
||||||
scalar m_x;
|
const b3SoftBodyMesh* m_mesh;
|
||||||
scalar m_tu, m_tv, m_tw;
|
const b3SoftBodyMeshTetrahedron* m_tetrahedron;
|
||||||
b3SoftBodyNode * m_n1, * m_n2, * m_n3;
|
u32 m_v1, m_v2, m_v3, m_v4;
|
||||||
b3SoftBodyNodeType m_t1, m_t2, m_t3;
|
float32 m_tu, m_tv, m_tw, m_tx;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool b3SoftBodyDragger::IsDragging() const
|
inline bool b3SoftBodyDragger::IsDragging() const
|
||||||
{
|
{
|
||||||
return m_isDragging;
|
return m_tetrahedron != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -17,10 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <testbed/framework/test.h>
|
#include <testbed/framework/test.h>
|
||||||
#include <bounce/common/profiler.h>
|
#include <testbed/framework/profiler.h>
|
||||||
|
#include <testbed/framework/profiler_st.h>
|
||||||
extern b3FrameAllocator* g_frameAllocator;
|
|
||||||
extern b3Profiler* g_profiler;
|
|
||||||
|
|
||||||
extern u32 b3_allocCalls, b3_maxAllocCalls;
|
extern u32 b3_allocCalls, b3_maxAllocCalls;
|
||||||
extern u32 b3_convexCalls, b3_convexCacheHits;
|
extern u32 b3_convexCalls, b3_convexCacheHits;
|
||||||
@ -30,18 +28,19 @@ extern bool b3_convexCache;
|
|||||||
void b3BeginProfileScope(const char* name)
|
void b3BeginProfileScope(const char* name)
|
||||||
{
|
{
|
||||||
g_profiler->BeginScope(name);
|
g_profiler->BeginScope(name);
|
||||||
|
g_profilerSt->BeginScope(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void b3EndProfileScope()
|
void b3EndProfileScope()
|
||||||
{
|
{
|
||||||
g_profiler->EndScope();
|
g_profiler->EndScope();
|
||||||
|
g_profilerSt->EndScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
Test::Test() :
|
Test::Test() :
|
||||||
m_bodyDragger(&m_ray, &m_world)
|
m_bodyDragger(&m_ray, &m_world)
|
||||||
{
|
{
|
||||||
b3Draw_draw = g_draw;
|
b3Draw_draw = g_draw;
|
||||||
b3FrameAllocator_sparseAllocator = g_frameAllocator;
|
|
||||||
b3_convexCache = g_testSettings->convexCache;
|
b3_convexCache = g_testSettings->convexCache;
|
||||||
|
|
||||||
m_world.SetContactListener(this);
|
m_world.SetContactListener(this);
|
||||||
@ -50,16 +49,13 @@ Test::Test() :
|
|||||||
m_ray.direction.Set(0.0f, 0.0f, -1.0f);
|
m_ray.direction.Set(0.0f, 0.0f, -1.0f);
|
||||||
m_ray.fraction = g_camera->m_zFar;
|
m_ray.fraction = g_camera->m_zFar;
|
||||||
|
|
||||||
m_groundHull.SetExtents(50.0f, 1.0f, 50.0f);
|
m_groundHull.Set(50.0f, 1.0f, 50.0f);
|
||||||
|
|
||||||
m_groundMesh.BuildTree();
|
m_groundMesh.BuildTree();
|
||||||
m_groundMesh.BuildAdjacency();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Test::~Test()
|
Test::~Test()
|
||||||
{
|
{
|
||||||
b3Draw_draw = nullptr;
|
b3Draw_draw = nullptr;
|
||||||
b3FrameAllocator_sparseAllocator = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test::Step()
|
void Test::Step()
|
||||||
@ -67,7 +63,7 @@ void Test::Step()
|
|||||||
b3_convexCache = g_testSettings->convexCache;
|
b3_convexCache = g_testSettings->convexCache;
|
||||||
|
|
||||||
// Step
|
// Step
|
||||||
scalar dt = g_testSettings->inv_hertz;
|
float32 dt = g_testSettings->inv_hertz;
|
||||||
|
|
||||||
m_world.SetSleeping(g_testSettings->sleep);
|
m_world.SetSleeping(g_testSettings->sleep);
|
||||||
m_world.SetWarmStart(g_testSettings->warmStart);
|
m_world.SetWarmStart(g_testSettings->warmStart);
|
||||||
@ -101,19 +97,19 @@ void Test::Step()
|
|||||||
g_draw->DrawString(b3Color_white, "Joints %d", m_world.GetJointList().m_count);
|
g_draw->DrawString(b3Color_white, "Joints %d", m_world.GetJointList().m_count);
|
||||||
g_draw->DrawString(b3Color_white, "Contacts %d", m_world.GetContactList().m_count);
|
g_draw->DrawString(b3Color_white, "Contacts %d", m_world.GetContactList().m_count);
|
||||||
|
|
||||||
scalar avgGjkIters = 0.0f;
|
float32 avgGjkIters = 0.0f;
|
||||||
if (b3_gjkCalls > 0)
|
if (b3_gjkCalls > 0)
|
||||||
{
|
{
|
||||||
avgGjkIters = scalar(b3_gjkIters) / scalar(b3_gjkCalls);
|
avgGjkIters = float32(b3_gjkIters) / float32(b3_gjkCalls);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "GJK Calls %d", b3_gjkCalls);
|
g_draw->DrawString(b3Color_white, "GJK Calls %d", b3_gjkCalls);
|
||||||
g_draw->DrawString(b3Color_white, "GJK Iterations %d (%d) (%f)", b3_gjkIters, b3_gjkMaxIters, avgGjkIters);
|
g_draw->DrawString(b3Color_white, "GJK Iterations %d (%d) (%f)", b3_gjkIters, b3_gjkMaxIters, avgGjkIters);
|
||||||
|
|
||||||
scalar convexCacheHitRatio = 0.0f;
|
float32 convexCacheHitRatio = 0.0f;
|
||||||
if (b3_convexCalls > 0)
|
if (b3_convexCalls > 0)
|
||||||
{
|
{
|
||||||
convexCacheHitRatio = scalar(b3_convexCacheHits) / scalar(b3_convexCalls);
|
convexCacheHitRatio = float32(b3_convexCacheHits) / float32(b3_convexCalls);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "Convex Calls %d", b3_convexCalls);
|
g_draw->DrawString(b3Color_white, "Convex Calls %d", b3_convexCalls);
|
||||||
|
@ -24,16 +24,15 @@
|
|||||||
|
|
||||||
#include <testbed/framework/body_dragger.h>
|
#include <testbed/framework/body_dragger.h>
|
||||||
#include <testbed/framework/cloth_dragger.h>
|
#include <testbed/framework/cloth_dragger.h>
|
||||||
#include <testbed/framework/softbody_dragger.h>
|
|
||||||
|
|
||||||
#include <testbed/framework/draw.h>
|
#include <testbed/framework/draw.h>
|
||||||
#include <testbed/framework/view_model.h>
|
#include <testbed/framework/view_model.h>
|
||||||
|
|
||||||
inline float RandomFloat(scalar a, scalar b)
|
inline float32 RandomFloat(float32 a, float32 b)
|
||||||
{
|
{
|
||||||
float x = float(rand()) / float(RAND_MAX);
|
float32 x = float32(rand()) / float32(RAND_MAX);
|
||||||
float diff = b - a;
|
float32 diff = b - a;
|
||||||
float r = x * diff;
|
float32 r = x * diff;
|
||||||
return a + r;
|
return a + r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,13 +20,12 @@
|
|||||||
#include <testbed/tests/convex_hull.h>
|
#include <testbed/tests/convex_hull.h>
|
||||||
#include <testbed/tests/cluster.h>
|
#include <testbed/tests/cluster.h>
|
||||||
#include <testbed/tests/distance_test.h>
|
#include <testbed/tests/distance_test.h>
|
||||||
#include <testbed/tests/linear_time_of_impact.h>
|
#include <testbed/tests/shape_cast.h>
|
||||||
#include <testbed/tests/time_of_impact.h>
|
|
||||||
#include <testbed/tests/aabb_time_of_impact.h>
|
|
||||||
#include <testbed/tests/collide_test.h>
|
#include <testbed/tests/collide_test.h>
|
||||||
#include <testbed/tests/capsule_collision.h>
|
#include <testbed/tests/capsule_collision.h>
|
||||||
#include <testbed/tests/hull_collision.h>
|
#include <testbed/tests/hull_collision.h>
|
||||||
#include <testbed/tests/deep_capsule.h>
|
#include <testbed/tests/deep_capsule.h>
|
||||||
|
#include <testbed/tests/degenerate_capsule.h>
|
||||||
#include <testbed/tests/box_face_contact.h>
|
#include <testbed/tests/box_face_contact.h>
|
||||||
#include <testbed/tests/box_edge_contact.h>
|
#include <testbed/tests/box_edge_contact.h>
|
||||||
#include <testbed/tests/linear_motion.h>
|
#include <testbed/tests/linear_motion.h>
|
||||||
@ -36,18 +35,14 @@
|
|||||||
#include <testbed/tests/capsule_spin.h>
|
#include <testbed/tests/capsule_spin.h>
|
||||||
#include <testbed/tests/quadric_shapes.h>
|
#include <testbed/tests/quadric_shapes.h>
|
||||||
#include <testbed/tests/compound_body.h>
|
#include <testbed/tests/compound_body.h>
|
||||||
#include <testbed/tests/spring_test.h>
|
#include <testbed/tests/spring.h>
|
||||||
#include <testbed/tests/motor_test.h>
|
|
||||||
#include <testbed/tests/weld_test.h>
|
#include <testbed/tests/weld_test.h>
|
||||||
#include <testbed/tests/cone_test.h>
|
#include <testbed/tests/cone_test.h>
|
||||||
#include <testbed/tests/revolute_test.h>
|
#include <testbed/tests/hinge_motor.h>
|
||||||
#include <testbed/tests/prismatic_test.h>
|
|
||||||
#include <testbed/tests/wheel_test.h>
|
|
||||||
#include <testbed/tests/hinge_chain.h>
|
#include <testbed/tests/hinge_chain.h>
|
||||||
#include <testbed/tests/newton_cradle.h>
|
#include <testbed/tests/newton_cradle.h>
|
||||||
#include <testbed/tests/ragdoll.h>
|
#include <testbed/tests/ragdoll.h>
|
||||||
#include <testbed/tests/mesh_contact_test.h>
|
#include <testbed/tests/mesh_contact_test.h>
|
||||||
#include <testbed/tests/triangle_contact_test.h>
|
|
||||||
#include <testbed/tests/hull_contact_test.h>
|
#include <testbed/tests/hull_contact_test.h>
|
||||||
#include <testbed/tests/sphere_stack.h>
|
#include <testbed/tests/sphere_stack.h>
|
||||||
#include <testbed/tests/capsule_stack.h>
|
#include <testbed/tests/capsule_stack.h>
|
||||||
@ -58,61 +53,46 @@
|
|||||||
#include <testbed/tests/pyramid.h>
|
#include <testbed/tests/pyramid.h>
|
||||||
#include <testbed/tests/pyramids.h>
|
#include <testbed/tests/pyramids.h>
|
||||||
#include <testbed/tests/ray_cast.h>
|
#include <testbed/tests/ray_cast.h>
|
||||||
#include <testbed/tests/convex_cast.h>
|
|
||||||
#include <testbed/tests/sensor_test.h>
|
#include <testbed/tests/sensor_test.h>
|
||||||
#include <testbed/tests/body_types.h>
|
#include <testbed/tests/body_types.h>
|
||||||
#include <testbed/tests/varying_friction.h>
|
#include <testbed/tests/varying_friction.h>
|
||||||
#include <testbed/tests/varying_restitution.h>
|
#include <testbed/tests/varying_restitution.h>
|
||||||
#include <testbed/tests/tumbler.h>
|
#include <testbed/tests/tumbler.h>
|
||||||
#include <testbed/tests/multiple_pendulum.h>
|
#include <testbed/tests/multiple_pendulum.h>
|
||||||
#include <testbed/tests/conveyor_belt.h>
|
|
||||||
#include <testbed/tests/table_cloth.h>
|
#include <testbed/tests/table_cloth.h>
|
||||||
#include <testbed/tests/cloth_sdf.h>
|
|
||||||
#include <testbed/tests/pinned_cloth.h>
|
#include <testbed/tests/pinned_cloth.h>
|
||||||
#include <testbed/tests/particle_types.h>
|
#include <testbed/tests/particle_types.h>
|
||||||
#include <testbed/tests/tension_mapping.h>
|
#include <testbed/tests/tension_mapping.h>
|
||||||
#include <testbed/tests/cloth_self_collision.h>
|
#include <testbed/tests/cloth_self_collision.h>
|
||||||
#include <testbed/tests/cape.h>
|
|
||||||
#include <testbed/tests/cloth_tearing.h>
|
|
||||||
#include <testbed/tests/cloth_element_test.h>
|
|
||||||
#include <testbed/tests/rope_test.h>
|
#include <testbed/tests/rope_test.h>
|
||||||
#include <testbed/tests/beam.h>
|
#include <testbed/tests/beam.h>
|
||||||
#include <testbed/tests/sheet.h>
|
|
||||||
#include <testbed/tests/node_types.h>
|
|
||||||
#include <testbed/tests/pinned_softbody.h>
|
#include <testbed/tests/pinned_softbody.h>
|
||||||
#include <testbed/tests/softbody_anchor.h>
|
|
||||||
#include <testbed/tests/smash_softbody.h>
|
#include <testbed/tests/smash_softbody.h>
|
||||||
#include <testbed/tests/tetgen_softbody.h>
|
|
||||||
|
|
||||||
TestEntry g_tests[] =
|
TestEntry g_tests[] =
|
||||||
{
|
{
|
||||||
{ "Convex Hull", &ConvexHull::Create },
|
{ "Convex Hull", &ConvexHull::Create },
|
||||||
{ "Cluster", &Cluster::Create },
|
{ "Cluster", &Cluster::Create },
|
||||||
{ "Distance", &Distance::Create },
|
{ "Distance", &Distance::Create },
|
||||||
{ "Linear Time of Impact", &LinearTimeOfImpact::Create },
|
{ "Shape Cast", &ShapeCast::Create },
|
||||||
{ "Time of Impact", &TimeOfImpact::Create },
|
|
||||||
{ "AABB Time of Impact", &AABBTimeOfImpact::Create },
|
|
||||||
{ "Capsule Collision", &CapsuleCollision::Create },
|
{ "Capsule Collision", &CapsuleCollision::Create },
|
||||||
{ "Hull Collision", &HullCollision::Create },
|
{ "Hull Collision", &HullCollision::Create },
|
||||||
{ "Deep Capsule", &DeepCapsule::Create },
|
{ "Deep Capsule", &DeepCapsule::Create },
|
||||||
|
{ "Degenerate Capsule", &DegenerateCapsule::Create },
|
||||||
{ "Box Face Contact", &BoxFaceContact::Create },
|
{ "Box Face Contact", &BoxFaceContact::Create },
|
||||||
{ "Box Edge Contact", &BoxEdgeContact::Create },
|
{ "Box Edge Contact", &BoxEdgeContact::Create },
|
||||||
{ "Capsule Spin", &CapsuleSpin::Create },
|
{ "Capsule Spin", &CapsuleSpin::Create },
|
||||||
{ "Hull Contact Test", &HullContactTest::Create },
|
{ "Hull Contact Test", &HullContactTest::Create },
|
||||||
{ "Triangle Contact Test", &TriangleContactTest::Create },
|
|
||||||
{ "Mesh Contact Test", &MeshContactTest::Create },
|
{ "Mesh Contact Test", &MeshContactTest::Create },
|
||||||
{ "Linear Motion", &LinearMotion::Create },
|
{ "Linear Motion", &LinearMotion::Create },
|
||||||
{ "Angular Motion", &AngularMotion::Create },
|
{ "Angular Motion", &AngularMotion::Create },
|
||||||
{ "Gyroscopic Motion", &GyroMotion::Create },
|
{ "Gyroscopic Motion", &GyroMotion::Create },
|
||||||
{ "Compound Body", &CompoundBody::Create },
|
{ "Compound Body", &CompoundBody::Create },
|
||||||
{ "Quadric Shapes", &QuadricShapes::Create },
|
{ "Quadric Shapes", &QuadricShapes::Create },
|
||||||
{ "Spring Test", &SpringTest::Create },
|
{ "Springs", &Spring::Create },
|
||||||
{ "Prismatic Test", &PrismaticTest::Create },
|
|
||||||
{ "Wheel Test", &WheelTest::Create },
|
|
||||||
{ "Weld Test", &WeldTest::Create },
|
{ "Weld Test", &WeldTest::Create },
|
||||||
{ "Cone Test", &ConeTest::Create },
|
{ "Cone Test", &ConeTest::Create },
|
||||||
{ "Motor Test", &MotorTest::Create },
|
{ "Hinge Motor", &HingeMotor::Create },
|
||||||
{ "Revolute Test", &RevoluteTest::Create },
|
|
||||||
{ "Hinge Chain", &HingeChain::Create },
|
{ "Hinge Chain", &HingeChain::Create },
|
||||||
{ "Ragdoll", &Ragdoll::Create },
|
{ "Ragdoll", &Ragdoll::Create },
|
||||||
{ "Newton's Cradle", &NewtonCradle::Create },
|
{ "Newton's Cradle", &NewtonCradle::Create },
|
||||||
@ -125,7 +105,6 @@ TestEntry g_tests[] =
|
|||||||
{ "Box Pyramid", &Pyramid::Create },
|
{ "Box Pyramid", &Pyramid::Create },
|
||||||
{ "Box Pyramid Rows", &Pyramids::Create },
|
{ "Box Pyramid Rows", &Pyramids::Create },
|
||||||
{ "Ray Cast", &RayCast::Create },
|
{ "Ray Cast", &RayCast::Create },
|
||||||
{ "Convex Cast", &ConvexCast::Create },
|
|
||||||
{ "Sensor Test", &SensorTest::Create },
|
{ "Sensor Test", &SensorTest::Create },
|
||||||
{ "Body Types", &BodyTypes::Create },
|
{ "Body Types", &BodyTypes::Create },
|
||||||
{ "Varying Friction", &VaryingFriction::Create },
|
{ "Varying Friction", &VaryingFriction::Create },
|
||||||
@ -133,23 +112,14 @@ TestEntry g_tests[] =
|
|||||||
{ "Tumbler", &Tumbler::Create },
|
{ "Tumbler", &Tumbler::Create },
|
||||||
{ "Initial Overlap", &InitialOverlap::Create },
|
{ "Initial Overlap", &InitialOverlap::Create },
|
||||||
{ "Multiple Pendulum", &MultiplePendulum::Create },
|
{ "Multiple Pendulum", &MultiplePendulum::Create },
|
||||||
{ "Conveyor Belt", &ConveyorBelt::Create },
|
|
||||||
{ "Table Cloth", &TableCloth::Create },
|
{ "Table Cloth", &TableCloth::Create },
|
||||||
{ "Cloth SDF", &ClothSDF::Create },
|
|
||||||
{ "Pinned Cloth", &PinnedCloth::Create },
|
{ "Pinned Cloth", &PinnedCloth::Create },
|
||||||
{ "Particle Types", &ParticleTypes::Create },
|
{ "Particle Types", &ParticleTypes::Create },
|
||||||
{ "Tension Mapping", &TensionMapping::Create },
|
{ "Tension Mapping", &TensionMapping::Create },
|
||||||
{ "Cloth Self-Collision", &ClothSelfCollision::Create },
|
{ "Cloth Self-Collision", &ClothSelfCollision::Create },
|
||||||
{ "Cloth Tearing", &ClothTearing::Create },
|
|
||||||
{ "Cloth Element Test", &ClothElementTest::Create },
|
|
||||||
{ "Cape", &Cape::Create },
|
|
||||||
{ "Beam", &Beam::Create },
|
{ "Beam", &Beam::Create },
|
||||||
{ "Sheet", &Sheet::Create },
|
|
||||||
{ "Node Types", &NodeTypes::Create },
|
|
||||||
{ "Pinned Soft Body", &PinnedSoftBody::Create },
|
{ "Pinned Soft Body", &PinnedSoftBody::Create },
|
||||||
{ "Soft Body Anchor", &SoftBodyAnchor::Create },
|
|
||||||
{ "Smash Soft Body", &SmashSoftBody::Create },
|
{ "Smash Soft Body", &SmashSoftBody::Create },
|
||||||
{ "TetGen Soft Body", &TetGenSoftBody::Create },
|
|
||||||
{ "Rope", &Rope::Create },
|
{ "Rope", &Rope::Create },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
@ -19,18 +19,14 @@
|
|||||||
#include <testbed/framework/view.h>
|
#include <testbed/framework/view.h>
|
||||||
#include <testbed/framework/view_model.h>
|
#include <testbed/framework/view_model.h>
|
||||||
#include <testbed/framework/test.h>
|
#include <testbed/framework/test.h>
|
||||||
#include <bounce/common/profiler.h>
|
#include <testbed/framework/profiler.h>
|
||||||
|
#include <testbed/framework/profiler_st.h>
|
||||||
extern b3Profiler* g_profiler;
|
|
||||||
|
|
||||||
#include <imgui/imgui.h>
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
#include <imgui/imgui_impl_glfw.h>
|
|
||||||
|
|
||||||
#if defined (U_OPENGL_2)
|
#if defined (U_OPENGL_2)
|
||||||
#include <imgui/imgui_impl_opengl2.h>
|
#include <imgui/imgui_impl_glfw_gl2.h>
|
||||||
#elif defined (U_OPENGL_4)
|
#elif defined (U_OPENGL_4)
|
||||||
#include <imgui/imgui_impl_opengl3.h>
|
#include <imgui/imgui_impl_glfw_gl3.h>
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -43,15 +39,16 @@ static inline bool GetTestName(void* userData, int idx, const char** name)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ImGui_OpenGL_Init()
|
static inline bool ImGui_GLFW_GL_Init(GLFWwindow* w, bool install_callbacks)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(U_OPENGL_2)
|
#if defined(U_OPENGL_2)
|
||||||
|
|
||||||
return ImGui_ImplOpenGL2_Init();
|
return ImGui_ImplGlfwGL2_Init(w, install_callbacks);
|
||||||
|
|
||||||
#elif defined(U_OPENGL_4)
|
#elif defined(U_OPENGL_4)
|
||||||
|
|
||||||
return ImGui_ImplOpenGL3_Init();
|
return ImGui_ImplGlfwGL3_Init(w, install_callbacks);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -59,16 +56,16 @@ static inline bool ImGui_OpenGL_Init()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ImGui_OpenGL_Shutdown()
|
static inline void ImGui_GLFW_GL_Shutdown()
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(U_OPENGL_2)
|
#if defined(U_OPENGL_2)
|
||||||
|
|
||||||
ImGui_ImplOpenGL2_Shutdown();
|
ImGui_ImplGlfwGL2_Shutdown();
|
||||||
|
|
||||||
#elif defined(U_OPENGL_4)
|
#elif defined(U_OPENGL_4)
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplGlfwGL3_Shutdown();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -78,16 +75,16 @@ static inline void ImGui_OpenGL_Shutdown()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ImGui_OpenGL_NewFrame()
|
static inline void ImGui_GLFW_GL_NewFrame()
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(U_OPENGL_2)
|
#if defined(U_OPENGL_2)
|
||||||
|
|
||||||
ImGui_ImplOpenGL2_NewFrame();
|
ImGui_ImplGlfwGL2_NewFrame();
|
||||||
|
|
||||||
#elif defined(U_OPENGL_4)
|
#elif defined(U_OPENGL_4)
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplGlfwGL3_NewFrame();
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -97,16 +94,16 @@ static inline void ImGui_OpenGL_NewFrame()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ImGui_OpenGL_RenderDrawData(ImDrawData* draw_data)
|
static inline void ImGui_GLFW_GL_RenderDrawData(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(U_OPENGL_2)
|
#if defined(U_OPENGL_2)
|
||||||
|
|
||||||
ImGui_ImplOpenGL2_RenderDrawData(draw_data);
|
ImGui_ImplGlfwGL2_RenderDrawData(draw_data);
|
||||||
|
|
||||||
#elif defined(U_OPENGL_4)
|
#elif defined(U_OPENGL_4)
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(draw_data);
|
ImGui_ImplGlfwGL3_RenderDrawData(draw_data);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -127,9 +124,9 @@ View::View(GLFWwindow* window)
|
|||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
io.IniFilename = NULL;
|
io.IniFilename = NULL;
|
||||||
|
io.Fonts[0].AddFontDefault();
|
||||||
|
|
||||||
ImGui_ImplGlfw_InitForOpenGL(m_window, false);
|
ImGui_GLFW_GL_Init(m_window, false);
|
||||||
ImGui_OpenGL_Init();
|
|
||||||
|
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
@ -139,8 +136,7 @@ View::View(GLFWwindow* window)
|
|||||||
View::~View()
|
View::~View()
|
||||||
{
|
{
|
||||||
// Destroy UI
|
// Destroy UI
|
||||||
ImGui_OpenGL_Shutdown();
|
ImGui_GLFW_GL_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
|
||||||
|
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
}
|
}
|
||||||
@ -149,7 +145,7 @@ b3Vec2 View::GetCursorPosition() const
|
|||||||
{
|
{
|
||||||
double x, y;
|
double x, y;
|
||||||
glfwGetCursorPos(m_window, &x, &y);
|
glfwGetCursorPos(m_window, &x, &y);
|
||||||
return b3Vec2(scalar(x), scalar(y));
|
return b3Vec2(float32(x), float32(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::Event_SetWindowSize(int w, int h)
|
void View::Event_SetWindowSize(int w, int h)
|
||||||
@ -190,9 +186,7 @@ void View::Event_Scroll(float dx, float dy)
|
|||||||
|
|
||||||
void View::BeginInterface()
|
void View::BeginInterface()
|
||||||
{
|
{
|
||||||
ImGui_OpenGL_NewFrame();
|
ImGui_GLFW_GL_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
|
||||||
ImGui::NewFrame();
|
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||||
}
|
}
|
||||||
@ -225,8 +219,9 @@ void View::Interface()
|
|||||||
|
|
||||||
if (ImGui::BeginMenu("View"))
|
if (ImGui::BeginMenu("View"))
|
||||||
{
|
{
|
||||||
|
ImGui::MenuItem("Profile Tree", "", &settings.drawProfileTree);
|
||||||
|
ImGui::MenuItem("Profile Tree Statistics", "", &settings.drawProfileTreeStats);
|
||||||
ImGui::MenuItem("Statistics", "", &settings.drawStats);
|
ImGui::MenuItem("Statistics", "", &settings.drawStats);
|
||||||
ImGui::MenuItem("Profiler", "", &settings.drawProfiler);
|
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
@ -408,7 +403,54 @@ void View::Interface()
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TreeNode(b3ProfilerNode* node, u32& index)
|
static void TreeNode(ProfilerNode* node, u32& index)
|
||||||
|
{
|
||||||
|
ImGui::PushID(index);
|
||||||
|
++index;
|
||||||
|
|
||||||
|
if (ImGui::TreeNode(node->name))
|
||||||
|
{
|
||||||
|
float64 elapsedTime = node->t1 - node->t0;
|
||||||
|
ImGui::Text("%.4f [ms]", elapsedTime);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||||
|
{
|
||||||
|
TreeNode(node->children[i], index);
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
void View::InterfaceProfileTree()
|
||||||
|
{
|
||||||
|
ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
|
||||||
|
ImVec2 ws = ImGui::GetWindowSize();
|
||||||
|
ImVec2 wp = ImGui::GetWindowPos();
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
|
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.0f);
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(0.0f, wp.y + ws.y));
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(g_camera->m_width - 250.0f, 0.0f));
|
||||||
|
|
||||||
|
ImGui::Begin("Profile Tree", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||||||
|
|
||||||
|
ProfilerNode* root = g_profiler->GetRoot();
|
||||||
|
if (root)
|
||||||
|
{
|
||||||
|
u32 index = 0;
|
||||||
|
TreeNode(root, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TreeNode(ProfilerStNode* node, u32& index)
|
||||||
{
|
{
|
||||||
ImGui::PushID(index);
|
ImGui::PushID(index);
|
||||||
++index;
|
++index;
|
||||||
@ -417,11 +459,9 @@ static void TreeNode(b3ProfilerNode* node, u32& index)
|
|||||||
{
|
{
|
||||||
ImGui::Text("%.4f (min = %.4f) (max = %.4f) (calls = %d) [ms]", node->elapsed, node->stat->minElapsed, node->stat->maxElapsed, node->callCount);
|
ImGui::Text("%.4f (min = %.4f) (max = %.4f) (calls = %d) [ms]", node->elapsed, node->stat->minElapsed, node->stat->maxElapsed, node->callCount);
|
||||||
|
|
||||||
b3ProfilerNode* n = node->head;
|
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||||
while(n)
|
|
||||||
{
|
{
|
||||||
TreeNode(n, index);
|
TreeNode(node->children[i], index);
|
||||||
n = n->next;
|
|
||||||
}
|
}
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
@ -429,7 +469,7 @@ static void TreeNode(b3ProfilerNode* node, u32& index)
|
|||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::InterfaceProfiler()
|
void View::InterfaceProfileTreeStats()
|
||||||
{
|
{
|
||||||
ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
|
ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
|
||||||
ImVec2 wp = ImGui::GetWindowPos();
|
ImVec2 wp = ImGui::GetWindowPos();
|
||||||
@ -438,15 +478,25 @@ void View::InterfaceProfiler()
|
|||||||
|
|
||||||
wp.y = wp.y + ws.y;
|
wp.y = wp.y + ws.y;
|
||||||
|
|
||||||
|
if (g_settings->drawProfileTree)
|
||||||
|
{
|
||||||
|
ImGui::Begin("Profile Tree", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||||||
|
ImVec2 ptwp = ImGui::GetWindowPos();
|
||||||
|
ImVec2 ptws = ImGui::GetWindowSize();
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
wp.y = ptwp.y + ptws.y;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
|
|
||||||
ImGui::SetNextWindowBgAlpha(0.0f);
|
ImGui::SetNextWindowBgAlpha(0.0f);
|
||||||
ImGui::SetNextWindowPos(ImVec2(0.0f, wp.y));
|
ImGui::SetNextWindowPos(ImVec2(0.0f, wp.y));
|
||||||
ImGui::SetNextWindowSize(ImVec2(g_camera->m_width - 250.0f, 0.0f));
|
ImGui::SetNextWindowSize(ImVec2(g_camera->m_width - 250.0f, 0.0f));
|
||||||
|
|
||||||
ImGui::Begin("Profiler", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
ImGui::Begin("Profile Tree Statistics", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||||||
|
|
||||||
b3ProfilerNode* root = g_profiler->GetRoot();
|
ProfilerStNode* root = g_profilerSt->GetRoot();
|
||||||
if (root)
|
if (root)
|
||||||
{
|
{
|
||||||
u32 index = 0;
|
u32 index = 0;
|
||||||
@ -464,5 +514,5 @@ void View::EndInterface()
|
|||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
||||||
ImGui_OpenGL_RenderDrawData(ImGui::GetDrawData());
|
ImGui_GLFW_GL_RenderDrawData(ImGui::GetDrawData());
|
||||||
}
|
}
|
@ -41,7 +41,8 @@ public:
|
|||||||
|
|
||||||
void BeginInterface();
|
void BeginInterface();
|
||||||
void Interface();
|
void Interface();
|
||||||
void InterfaceProfiler();
|
void InterfaceProfileTree();
|
||||||
|
void InterfaceProfileTreeStats();
|
||||||
void EndInterface();
|
void EndInterface();
|
||||||
private:
|
private:
|
||||||
friend class ViewModel;
|
friend class ViewModel;
|
||||||
|
@ -84,7 +84,7 @@ void ViewModel::Action_ResetCamera()
|
|||||||
|
|
||||||
void ViewModel::Event_SetWindowSize(int w, int h)
|
void ViewModel::Event_SetWindowSize(int w, int h)
|
||||||
{
|
{
|
||||||
m_model->Command_ResizeCamera(scalar(w), scalar(h));
|
m_model->Command_ResizeCamera(float32(w), float32(h));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewModel::Event_Press_Key(int button)
|
void ViewModel::Event_Press_Key(int button)
|
||||||
@ -148,7 +148,8 @@ void ViewModel::Event_Move_Cursor(float x, float y)
|
|||||||
|
|
||||||
b3Vec2 dp = ps - m_view->m_ps0;
|
b3Vec2 dp = ps - m_view->m_ps0;
|
||||||
|
|
||||||
b3Vec2 n = b3Normalize(dp);
|
float32 ndx = b3Clamp(dp.x, -1.0f, 1.0f);
|
||||||
|
float32 ndy = b3Clamp(dp.y, -1.0f, 1.0f);
|
||||||
|
|
||||||
bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS;
|
bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS;
|
||||||
bool leftDown = glfwGetMouseButton(m_view->m_window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
|
bool leftDown = glfwGetMouseButton(m_view->m_window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
|
||||||
@ -158,8 +159,8 @@ void ViewModel::Event_Move_Cursor(float x, float y)
|
|||||||
{
|
{
|
||||||
if (leftDown)
|
if (leftDown)
|
||||||
{
|
{
|
||||||
scalar ax = -0.005f * B3_PI * n.x;
|
float32 ax = -0.005f * B3_PI * ndx;
|
||||||
scalar ay = -0.005f * B3_PI * n.y;
|
float32 ay = -0.005f * B3_PI * ndy;
|
||||||
|
|
||||||
m_model->Command_RotateCameraY(ax);
|
m_model->Command_RotateCameraY(ax);
|
||||||
m_model->Command_RotateCameraX(ay);
|
m_model->Command_RotateCameraX(ay);
|
||||||
@ -167,8 +168,8 @@ void ViewModel::Event_Move_Cursor(float x, float y)
|
|||||||
|
|
||||||
if (rightDown)
|
if (rightDown)
|
||||||
{
|
{
|
||||||
scalar tx = 0.2f * n.x;
|
float32 tx = 0.2f * ndx;
|
||||||
scalar ty = -0.2f * n.y;
|
float32 ty = -0.2f * ndy;
|
||||||
|
|
||||||
m_model->Command_TranslateCameraX(tx);
|
m_model->Command_TranslateCameraX(tx);
|
||||||
m_model->Command_TranslateCameraY(ty);
|
m_model->Command_TranslateCameraY(ty);
|
||||||
@ -176,18 +177,16 @@ void ViewModel::Event_Move_Cursor(float x, float y)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_model->Command_Move_Cursor(ps);
|
m_model->Command_Move_Cursor(m_view->GetCursorPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewModel::Event_Scroll(float dx, float dy)
|
void ViewModel::Event_Scroll(float dx, float dy)
|
||||||
{
|
{
|
||||||
b3Vec2 n(dx, dy);
|
|
||||||
n.Normalize();
|
|
||||||
|
|
||||||
bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS;
|
bool shiftDown = glfwGetKey(m_view->m_window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS;
|
||||||
if (shiftDown)
|
if (shiftDown)
|
||||||
{
|
{
|
||||||
m_model->Command_ZoomCamera(1.0f * n.y);
|
float32 ny = b3Clamp(dy, -1.0f, 1.0f);
|
||||||
|
m_model->Command_ZoomCamera(1.0f * ny);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,9 @@ struct Settings
|
|||||||
drawLines = true;
|
drawLines = true;
|
||||||
drawTriangles = true;
|
drawTriangles = true;
|
||||||
drawGrid = true;
|
drawGrid = true;
|
||||||
|
drawProfileTree = false;
|
||||||
|
drawProfileTreeStats = false;
|
||||||
drawStats = false;
|
drawStats = false;
|
||||||
drawProfiler = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int testID;
|
int testID;
|
||||||
@ -42,8 +43,9 @@ struct Settings
|
|||||||
bool drawLines;
|
bool drawLines;
|
||||||
bool drawTriangles;
|
bool drawTriangles;
|
||||||
bool drawGrid;
|
bool drawGrid;
|
||||||
|
bool drawProfileTree;
|
||||||
|
bool drawProfileTreeStats;
|
||||||
bool drawStats;
|
bool drawStats;
|
||||||
bool drawProfiler;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1,178 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 AABB_TIME_OF_IMPACT_H
|
|
||||||
#define AABB_TIME_OF_IMPACT_H
|
|
||||||
|
|
||||||
class AABBTimeOfImpact : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AABBTimeOfImpact()
|
|
||||||
{
|
|
||||||
b3Vec3 cA = b3Vec3_zero;
|
|
||||||
b3Vec3 eA(1.0f, 1.0f, 1.0f);
|
|
||||||
m_aabbA.Set(cA, eA);
|
|
||||||
|
|
||||||
b3Vec3 cB(-2.0f, -2.0f, 0.0f);
|
|
||||||
b3Vec3 eB(1.0f, 1.0f, 1.0f);
|
|
||||||
m_aabbB.Set(cB, eB);
|
|
||||||
|
|
||||||
m_dB.Set(1.0f, 1.0f, 0.0f);
|
|
||||||
|
|
||||||
m_time = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "Arrows - Translate AABB");
|
|
||||||
|
|
||||||
g_draw->DrawAABB(m_aabbA, b3Color_white);
|
|
||||||
g_draw->DrawAABB(m_aabbB, b3Color_white);
|
|
||||||
|
|
||||||
b3Vec3 cA = m_aabbA.GetCenter();
|
|
||||||
b3Vec3 cB = m_aabbB.GetCenter();
|
|
||||||
|
|
||||||
b3Vec3 eA = m_aabbA.GetExtents();
|
|
||||||
b3Vec3 eB = m_aabbB.GetExtents();
|
|
||||||
|
|
||||||
b3Vec3 dA = b3Vec3_zero;
|
|
||||||
b3Vec3 dB = m_dB;
|
|
||||||
|
|
||||||
g_draw->DrawSegment(cA, cA + dA, b3Color_white);
|
|
||||||
g_draw->DrawSegment(cB, cB + dB, b3Color_white);
|
|
||||||
|
|
||||||
{
|
|
||||||
b3Vec3 cBt = cB + m_time * dB;
|
|
||||||
|
|
||||||
b3AABB B;
|
|
||||||
B.Set(cBt, eB);
|
|
||||||
|
|
||||||
g_draw->DrawAABB(B, b3Color_red);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3TOIOutput out = b3TimeOfImpact(m_aabbA, dA, m_aabbB, dB);
|
|
||||||
|
|
||||||
b3TOIOutput::State state = out.state;
|
|
||||||
scalar t = out.t;
|
|
||||||
|
|
||||||
if (state == b3TOIOutput::e_touching)
|
|
||||||
{
|
|
||||||
b3Vec3 cAt = cA + t * dA;
|
|
||||||
b3Vec3 cBt = cB + t * dB;
|
|
||||||
|
|
||||||
b3AABB A;
|
|
||||||
A.Set(cAt, eA);
|
|
||||||
|
|
||||||
b3AABB B;
|
|
||||||
B.Set(cBt, eB);
|
|
||||||
|
|
||||||
g_draw->DrawAABB(A, b3Color_black);
|
|
||||||
g_draw->DrawAABB(B, b3Color_black);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == b3TOIOutput::e_failed)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Failed");
|
|
||||||
}
|
|
||||||
else if (state == b3TOIOutput::e_overlapped)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Overlapped");
|
|
||||||
}
|
|
||||||
else if (state == b3TOIOutput::e_separated)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Separated!");
|
|
||||||
}
|
|
||||||
else if (state == b3TOIOutput::e_touching)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Touching!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int key)
|
|
||||||
{
|
|
||||||
const scalar dt = 0.01f;
|
|
||||||
const scalar d = 0.1f;
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_F)
|
|
||||||
{
|
|
||||||
m_time += dt;
|
|
||||||
if (m_time > 1.0f)
|
|
||||||
{
|
|
||||||
m_time = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_B)
|
|
||||||
{
|
|
||||||
m_time -= dt;
|
|
||||||
if (m_time < 0.0f)
|
|
||||||
{
|
|
||||||
m_time = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_LEFT)
|
|
||||||
{
|
|
||||||
m_aabbB.lowerBound.x -= d;
|
|
||||||
m_aabbB.upperBound.x -= d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_RIGHT)
|
|
||||||
{
|
|
||||||
m_aabbB.lowerBound.x += d;
|
|
||||||
m_aabbB.upperBound.x += d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_UP)
|
|
||||||
{
|
|
||||||
m_aabbB.lowerBound.y += d;
|
|
||||||
m_aabbB.upperBound.y += d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_DOWN)
|
|
||||||
{
|
|
||||||
m_aabbB.lowerBound.y -= d;
|
|
||||||
m_aabbB.upperBound.y -= d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_W)
|
|
||||||
{
|
|
||||||
m_aabbB.lowerBound.z += d;
|
|
||||||
m_aabbB.upperBound.z += d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
m_aabbB.lowerBound.z -= d;
|
|
||||||
m_aabbB.upperBound.z -= d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new AABBTimeOfImpact();
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar m_time;
|
|
||||||
|
|
||||||
b3AABB m_aabbA;
|
|
||||||
b3AABB m_aabbB;
|
|
||||||
b3Vec3 m_dB;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -32,8 +32,8 @@ public:
|
|||||||
b3Body* body = m_world.CreateBody(bd);
|
b3Body* body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape shape;
|
b3CapsuleShape shape;
|
||||||
shape.m_vertex1.Set(0.0f, 0.0f, -1.0f);
|
shape.m_centers[0].Set(0.0f, 0.0f, -1.0f);
|
||||||
shape.m_vertex2.Set(0.0f, 0.0f, 1.0f);
|
shape.m_centers[1].Set(0.0f, 0.0f, 1.0f);
|
||||||
shape.m_radius = 1.0f;
|
shape.m_radius = 1.0f;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
|
@ -19,34 +19,33 @@
|
|||||||
#ifndef BEAM_H
|
#ifndef BEAM_H
|
||||||
#define BEAM_H
|
#define BEAM_H
|
||||||
|
|
||||||
|
#include <testbed/framework/softbody_dragger.h>
|
||||||
|
|
||||||
class Beam : public Test
|
class Beam : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 5,
|
|
||||||
e_h = 2,
|
|
||||||
e_d = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
Beam()
|
Beam()
|
||||||
{
|
{
|
||||||
m_E0 = 1000.0f;
|
|
||||||
m_E = m_E0;
|
|
||||||
|
|
||||||
// Create soft body
|
// Create soft body
|
||||||
b3SoftBodyDef def;
|
b3SoftBodyDef def;
|
||||||
def.mesh = &m_mesh;
|
def.mesh = &m_mesh;
|
||||||
def.density = 0.2f;
|
def.density = 0.2f;
|
||||||
def.E = m_E0;
|
def.E = 1000.0f;
|
||||||
def.nu = 0.33f;
|
def.nu = 0.33f;
|
||||||
def.radius = 0.2f;
|
|
||||||
def.friction = 0.6f;
|
|
||||||
|
|
||||||
m_body = new b3SoftBody(def);
|
m_body = new b3SoftBody(def);
|
||||||
|
|
||||||
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
||||||
m_body->SetGravity(gravity);
|
m_body->SetGravity(gravity);
|
||||||
|
m_body->SetWorld(&m_world);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
||||||
|
{
|
||||||
|
b3SoftBodyNode* n = m_body->GetVertexNode(i);
|
||||||
|
|
||||||
|
n->SetRadius(0.05f);
|
||||||
|
n->SetFriction(0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
// Create body
|
// Create body
|
||||||
{
|
{
|
||||||
@ -56,7 +55,7 @@ public:
|
|||||||
|
|
||||||
b3Body* b = m_world.CreateBody(bd);
|
b3Body* b = m_world.CreateBody(bd);
|
||||||
|
|
||||||
m_wallHull.SetExtents(1.0f, 5.0f, 5.0f);
|
m_wallHull.Set(1.0f, 5.0f, 5.0f);
|
||||||
|
|
||||||
b3HullShape wallShape;
|
b3HullShape wallShape;
|
||||||
wallShape.m_hull = &m_wallHull;
|
wallShape.m_hull = &m_wallHull;
|
||||||
@ -65,20 +64,18 @@ public:
|
|||||||
sd.shape = &wallShape;
|
sd.shape = &wallShape;
|
||||||
|
|
||||||
b3Shape* wall = b->CreateShape(sd);
|
b3Shape* wall = b->CreateShape(sd);
|
||||||
|
|
||||||
b3SoftBodyWorldShapeDef ssd;
|
|
||||||
ssd.shape = wall;
|
|
||||||
|
|
||||||
m_body->CreateWorldShape(ssd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < e_h + 1; ++i)
|
b3AABB3 aabb;
|
||||||
{
|
aabb.m_lower.Set(-3.0f, -5.0f, -5.0f);
|
||||||
for (u32 k = 0; k < e_d + 1; ++k)
|
aabb.m_upper.Set(-2.0f, 5.0f, 5.0f);
|
||||||
{
|
|
||||||
u32 v = m_mesh.GetVertex(i, 0, k);
|
|
||||||
|
|
||||||
b3SoftBodyNode* n = m_body->GetNode(v);
|
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
||||||
|
{
|
||||||
|
b3SoftBodyNode* n = m_body->GetVertexNode(i);
|
||||||
|
b3Vec3 p = n->GetPosition();
|
||||||
|
if (aabb.Contains(p))
|
||||||
|
{
|
||||||
n->SetType(e_staticSoftBodyNode);
|
n->SetType(e_staticSoftBodyNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,9 +107,9 @@ public:
|
|||||||
b3Vec3 pA = m_bodyDragger->GetPointA();
|
b3Vec3 pA = m_bodyDragger->GetPointA();
|
||||||
b3Vec3 pB = m_bodyDragger->GetPointB();
|
b3Vec3 pB = m_bodyDragger->GetPointB();
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pA, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pB, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
g_draw->DrawSegment(pA, pB, b3Color_white);
|
||||||
}
|
}
|
||||||
@ -120,10 +117,8 @@ public:
|
|||||||
extern u32 b3_softBodySolverIterations;
|
extern u32 b3_softBodySolverIterations;
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
||||||
|
|
||||||
scalar E = m_body->GetEnergy();
|
float32 E = m_body->GetEnergy();
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
g_draw->DrawString(b3Color_white, "E = %f", E);
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "Up/Down - Young Modulus (%f)", m_E);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
void MouseMove(const b3Ray3& pw)
|
||||||
@ -151,37 +146,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyDown(int button)
|
|
||||||
{
|
|
||||||
if (button == GLFW_KEY_UP)
|
|
||||||
{
|
|
||||||
m_E = b3Clamp(m_E + scalar(10), scalar(0), m_E0);
|
|
||||||
for (u32 i = 0; i < m_mesh.tetrahedronCount; ++i)
|
|
||||||
{
|
|
||||||
m_body->GetElement(i)->SetE(m_E);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_DOWN)
|
|
||||||
{
|
|
||||||
m_E = b3Clamp(m_E - scalar(10), scalar(10), m_E0);
|
|
||||||
for (u32 i = 0; i < m_mesh.tetrahedronCount; ++i)
|
|
||||||
{
|
|
||||||
m_body->GetElement(i)->SetE(m_E);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new Beam();
|
return new Beam();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BlockSoftBodyMesh<e_w, e_h, e_d> m_mesh;
|
b3BlockSoftBodyMesh<5, 2, 2> m_mesh;
|
||||||
|
|
||||||
scalar m_E0;
|
|
||||||
scalar m_E;
|
|
||||||
|
|
||||||
b3SoftBody* m_body;
|
b3SoftBody* m_body;
|
||||||
b3SoftBodyDragger* m_bodyDragger;
|
b3SoftBodyDragger* m_bodyDragger;
|
||||||
|
|
||||||
|
@ -47,8 +47,8 @@ public:
|
|||||||
m_body = m_world.CreateBody(bd);
|
m_body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cap;
|
b3CapsuleShape cap;
|
||||||
cap.m_vertex1.Set(0.0f, 2.0f, 0.0f);
|
cap.m_centers[0].Set(0.0f, 2.0f, 0.0f);
|
||||||
cap.m_vertex2.Set(0.0f, -2.0f, 0.0f);
|
cap.m_centers[1].Set(0.0f, -2.0f, 0.0f);
|
||||||
cap.m_radius = 0.5f;
|
cap.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -94,7 +94,7 @@ public:
|
|||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
bd.position.Set(RandomFloat(-20.0f, 20.0f), RandomFloat(10.0f, 20.0f), RandomFloat(-20.0f, 20.0f));
|
bd.position.Set(RandomFloat(-20.0f, 20.0f), RandomFloat(10.0f, 20.0f), RandomFloat(-20.0f, 20.0f));
|
||||||
|
|
||||||
b3Vec3 n = m_body->GetTransform().translation - bd.position;
|
b3Vec3 n = m_body->GetTransform().position - bd.position;
|
||||||
n.Normalize();
|
n.Normalize();
|
||||||
|
|
||||||
bd.linearVelocity = 100.0f * n;
|
bd.linearVelocity = 100.0f * n;
|
||||||
@ -122,7 +122,7 @@ public:
|
|||||||
|
|
||||||
p.x -= 1.0f;
|
p.x -= 1.0f;
|
||||||
|
|
||||||
m_body->SetTransform(p, q);
|
m_body->SetTransform(p, b3Vec3(q.x, q.y, q.z), q.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button == GLFW_KEY_RIGHT)
|
if (button == GLFW_KEY_RIGHT)
|
||||||
@ -132,7 +132,7 @@ public:
|
|||||||
|
|
||||||
p.x += 1.0f;
|
p.x += 1.0f;
|
||||||
|
|
||||||
m_body->SetTransform(p, q);
|
m_body->SetTransform(p, b3Vec3(q.x, q.y, q.z), q.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button == GLFW_KEY_UP)
|
if (button == GLFW_KEY_UP)
|
||||||
@ -142,7 +142,7 @@ public:
|
|||||||
|
|
||||||
p.z += 1.0f;
|
p.z += 1.0f;
|
||||||
|
|
||||||
m_body->SetTransform(p, q);
|
m_body->SetTransform(p, b3Vec3(q.x, q.y, q.z), q.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button == GLFW_KEY_DOWN)
|
if (button == GLFW_KEY_DOWN)
|
||||||
@ -152,7 +152,7 @@ public:
|
|||||||
|
|
||||||
p.z -= 1.0f;
|
p.z -= 1.0f;
|
||||||
|
|
||||||
m_body->SetTransform(p, q);
|
m_body->SetTransform(p, b3Vec3(q.x, q.y, q.z), q.w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,19 +24,27 @@ class BoxEdgeContact : public Collide
|
|||||||
public:
|
public:
|
||||||
BoxEdgeContact()
|
BoxEdgeContact()
|
||||||
{
|
{
|
||||||
m_box.SetExtents(1.0f, 2.0f, 1.0f);
|
b3Transform xf;
|
||||||
|
xf.position.SetZero();
|
||||||
|
xf.rotation = b3Diagonal(1.0f, 2.0f, 1.0f);
|
||||||
|
m_box.SetTransform(xf);
|
||||||
|
|
||||||
m_sA.m_hull = &m_box;
|
m_sA.m_hull = &m_box;
|
||||||
m_xfA.translation.Set(1.500000, 1.000000, 0.000000);
|
|
||||||
m_xfA.rotation.SetIdentity();
|
|
||||||
m_shapeA = &m_sA;
|
|
||||||
|
|
||||||
m_sB.m_hull = &m_box;
|
m_sB.m_hull = &m_box;
|
||||||
m_xfB.translation.Set(-1.29999995, 1.34999979, 0.000000000);
|
|
||||||
m_xfB.rotation.Set(0.810514629, 0.342624813, 0.334119707, 0.337692767);
|
m_xfA.position.Set(1.500000, 1.000000, 0.000000);
|
||||||
m_shapeB = &m_sB;
|
m_xfA.rotation.x.Set(0.707107, 0.000000, -0.707107);
|
||||||
|
m_xfA.rotation.y.Set(0.000000, 1.000000, 0.000000);
|
||||||
|
m_xfA.rotation.z.Set(0.707107, 0.000000, 0.707107);
|
||||||
|
|
||||||
|
m_xfB.position.Set(-1.300000, 0.000000, 0.000000);
|
||||||
|
m_xfB.rotation.x.Set(0.809017, 0.266849, -0.523721);
|
||||||
|
m_xfB.rotation.y.Set(0.000000, 0.891007, 0.453991);
|
||||||
|
m_xfB.rotation.z.Set(0.587785, -0.367286, 0.720840);
|
||||||
|
|
||||||
m_cache.count = 0;
|
m_cache.count = 0;
|
||||||
|
m_shapeA = &m_sA;
|
||||||
|
m_shapeB = &m_sB;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
|
@ -24,24 +24,28 @@ class BoxFaceContact : public Collide
|
|||||||
public:
|
public:
|
||||||
BoxFaceContact()
|
BoxFaceContact()
|
||||||
{
|
{
|
||||||
m_boxA.SetExtents(1.0f, 2.0f, 1.0f);
|
b3Transform m;
|
||||||
b3Vec3 translation(0.0f, 2.0f, 0.0f);
|
m.rotation = b3Diagonal(1.0f, 2.0f, 1.0f);
|
||||||
m_boxA.Translate(translation);
|
m.position.Set(0.0f, 2.0f, 0.0f);
|
||||||
|
m_box1.SetTransform(m);
|
||||||
|
|
||||||
|
m.rotation = b3Diagonal(1.0f, 1.0f, 1.0f);
|
||||||
|
m.position.Set(0.0f, 0.0f, 0.0f);
|
||||||
|
m_box2.SetTransform(m);
|
||||||
|
|
||||||
m_sA.m_hull = &m_boxA;
|
|
||||||
|
|
||||||
m_xfA.SetIdentity();
|
m_xfA.SetIdentity();
|
||||||
|
m_xfA.position.SetZero();
|
||||||
m_shapeA = &m_sA;
|
m_xfA.rotation.SetIdentity();
|
||||||
|
m_sA.m_hull = &m_box1;
|
||||||
|
|
||||||
m_boxB.SetExtents(1.0f, 1.0f, 1.0f);
|
|
||||||
|
|
||||||
m_xfB.SetIdentity();
|
m_xfB.SetIdentity();
|
||||||
m_sB.m_hull = &m_boxB;
|
m_xfB.position.Set(0.0f, 0.0f, 0.0f);
|
||||||
|
m_xfB.rotation.SetIdentity();
|
||||||
|
m_sB.m_hull = &m_box2;
|
||||||
|
|
||||||
m_shapeB = &m_sB;
|
|
||||||
|
|
||||||
m_cache.count = 0;
|
m_cache.count = 0;
|
||||||
|
m_shapeA = &m_sA;
|
||||||
|
m_shapeB = &m_sB;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
@ -49,8 +53,8 @@ public:
|
|||||||
return new BoxFaceContact();
|
return new BoxFaceContact();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_boxA;
|
b3BoxHull m_box1;
|
||||||
b3BoxHull m_boxB;
|
b3BoxHull m_box2;
|
||||||
b3HullShape m_sA;
|
b3HullShape m_sA;
|
||||||
b3HullShape m_sB;
|
b3HullShape m_sB;
|
||||||
};
|
};
|
||||||
|
@ -24,15 +24,17 @@ class BoxStack : public Test
|
|||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
e_h = 5,
|
e_rowCount = 1,
|
||||||
e_w = 1,
|
e_columnCount = 5,
|
||||||
e_d = 1
|
e_depthCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
BoxStack()
|
BoxStack()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
|
bdef.type = b3BodyType::e_staticBody;
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
@ -45,53 +47,30 @@ public:
|
|||||||
body->CreateShape(sdef);
|
body->CreateShape(sdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 e(1.0f, 1.0f, 1.0f);
|
b3Vec3 boxScale(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
m_boxHull.SetExtents(e.x, e.y, e.z);
|
b3Vec3 stackOrigin(0.0f, 4.05f, 0.0f);
|
||||||
|
|
||||||
b3Vec3 separation;
|
for (u32 i = 0; i < e_rowCount; ++i)
|
||||||
separation.x = 1.0f;
|
|
||||||
separation.y = 1.0f;
|
|
||||||
separation.z = 1.0f;
|
|
||||||
|
|
||||||
b3Vec3 scale;
|
|
||||||
scale.x = 2.0f * e.x + separation.x;
|
|
||||||
scale.y = 2.0f * e.y + separation.y;
|
|
||||||
scale.z = 2.0f * e.z + separation.z;
|
|
||||||
|
|
||||||
b3Vec3 size;
|
|
||||||
size.x = 2.0f * e.x + scale.x * scalar(e_w - 1);
|
|
||||||
size.y = 2.0f * e.y + scale.y * scalar(e_h - 1);
|
|
||||||
size.z = 2.0f * e.z + scale.z * scalar(e_d - 1);
|
|
||||||
|
|
||||||
b3Vec3 translation;
|
|
||||||
translation.x = e.x - 0.5f * size.x;
|
|
||||||
translation.y = e.y - 0.5f * size.y;
|
|
||||||
translation.z = e.z - 0.5f * size.z;
|
|
||||||
|
|
||||||
translation.y += 9.0f;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < e_h; ++i)
|
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < e_w; ++j)
|
for (u32 j = 0; j < e_columnCount; ++j)
|
||||||
{
|
{
|
||||||
for (u32 k = 0; k < e_d; ++k)
|
for (u32 k = 0; k < e_depthCount; ++k)
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = b3BodyType::e_dynamicBody;
|
||||||
|
bdef.orientation.Set(b3Vec3(0.0f, 1.0f, 0.0f), 0.5f * B3_PI);
|
||||||
|
|
||||||
bdef.position.Set(scalar(j), scalar(i), scalar(k));
|
bdef.position.x = float32(i) * boxScale.x;
|
||||||
|
bdef.position.y = 2.5f * float32(j) * boxScale.y;
|
||||||
|
bdef.position.z = float32(k) * boxScale.z;
|
||||||
|
|
||||||
bdef.position.x *= scale.x;
|
bdef.position += stackOrigin;
|
||||||
bdef.position.y *= scale.y;
|
|
||||||
bdef.position.z *= scale.z;
|
|
||||||
|
|
||||||
bdef.position += translation;
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &m_boxHull;
|
hs.m_hull = &b3BoxHull_identity;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.density = 0.1f;
|
sdef.density = 0.1f;
|
||||||
@ -99,30 +78,15 @@ public:
|
|||||||
sdef.shape = &hs;
|
sdef.shape = &hs;
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
body->CreateShape(sdef);
|
||||||
|
|
||||||
u32 bodyIndex = GetBodyIndex(i, j, k);
|
|
||||||
|
|
||||||
m_bodies[bodyIndex] = body;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetBodyIndex(u32 i, u32 j, u32 k)
|
|
||||||
{
|
|
||||||
B3_ASSERT(i < e_h);
|
|
||||||
B3_ASSERT(j < e_w);
|
|
||||||
B3_ASSERT(k < e_d);
|
|
||||||
return k + e_d * (j + e_w * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new BoxStack();
|
return new BoxStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_boxHull;
|
|
||||||
b3Body* m_bodies[e_h * e_w * e_d];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,215 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 CAPE_H
|
|
||||||
#define CAPE_H
|
|
||||||
|
|
||||||
class Cape : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 5,
|
|
||||||
e_h = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
Cape()
|
|
||||||
{
|
|
||||||
// Translate the cloth mesh
|
|
||||||
for (u32 i = 0; i < m_clothMesh.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
m_clothMesh.vertices[i].y += 5.0f;
|
|
||||||
m_clothMesh.vertices[i].z -= 6.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create cloth
|
|
||||||
b3ClothDef def;
|
|
||||||
def.mesh = &m_clothMesh;
|
|
||||||
def.density = 0.2f;
|
|
||||||
def.streching = 100000.0f;
|
|
||||||
|
|
||||||
m_cloth = new b3Cloth(def);
|
|
||||||
|
|
||||||
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
|
||||||
|
|
||||||
// Freeze some particles
|
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
|
||||||
{
|
|
||||||
u32 vj = m_clothMesh.GetVertex(e_h, j);
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(vj);
|
|
||||||
p->SetType(e_kinematicClothParticle);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
|
||||||
|
|
||||||
{
|
|
||||||
// Create body
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = b3BodyType::e_kinematicBody;
|
|
||||||
|
|
||||||
m_body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
static b3BoxHull box(1.0f, 5.0f, 1.0f);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &box;
|
|
||||||
hs.m_radius = 0.25f;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.3f;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
m_body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store cloth vertices in body space
|
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
|
||||||
{
|
|
||||||
u32 vj = m_clothMesh.GetVertex(e_h, j);
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(vj);
|
|
||||||
b3Vec3 position = p->GetPosition();
|
|
||||||
|
|
||||||
m_localPoints[j] = m_body->GetLocalPoint(position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~Cape()
|
|
||||||
{
|
|
||||||
delete m_clothDragger;
|
|
||||||
delete m_cloth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int button)
|
|
||||||
{
|
|
||||||
b3Vec3 v = m_body->GetLinearVelocity();
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_LEFT)
|
|
||||||
{
|
|
||||||
v.x -= 5.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_RIGHT)
|
|
||||||
{
|
|
||||||
v.x += 5.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_UP)
|
|
||||||
{
|
|
||||||
v.z -= 5.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_DOWN)
|
|
||||||
{
|
|
||||||
v.z += 5.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_body->SetLinearVelocity(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
scalar inv_h = g_testSettings->hertz;
|
|
||||||
|
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
|
||||||
{
|
|
||||||
u32 vj = m_clothMesh.GetVertex(e_h, j);
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(vj);
|
|
||||||
b3Vec3 x0 = p->GetPosition();
|
|
||||||
|
|
||||||
b3Vec3 x = m_body->GetWorldPoint(m_localPoints[j]);
|
|
||||||
|
|
||||||
// Apply finite difference method
|
|
||||||
b3Vec3 v = inv_h * (x - x0);
|
|
||||||
|
|
||||||
p->SetVelocity(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_cloth->Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
m_cloth->Draw();
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_clothSolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_cloth->GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "Arrows - Apply Velocity");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseMove(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->Drag();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_clothDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new Cape();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3GridClothMesh<e_w, e_h> m_clothMesh;
|
|
||||||
b3Cloth* m_cloth;
|
|
||||||
b3ClothDragger* m_clothDragger;
|
|
||||||
b3Body* m_body;
|
|
||||||
b3Vec3 m_localPoints[e_w + 1];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -24,21 +24,25 @@ class CapsuleCollision : public Collide
|
|||||||
public:
|
public:
|
||||||
CapsuleCollision()
|
CapsuleCollision()
|
||||||
{
|
{
|
||||||
m_sA.m_vertex1.Set(0.0f, -5.0f, 0.0f);
|
m_xfA.SetIdentity();
|
||||||
m_sA.m_vertex2.Set(0.0f, 5.0f, 0.0f);
|
m_xfA.position.Set(0.0f, 0.0f, 0.0f);
|
||||||
|
//m_xfA.rotation = b3ConvertQuatToRot(b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.25f * B3_PI));
|
||||||
|
m_xfA.rotation.SetIdentity();
|
||||||
|
m_sA.m_centers[0].Set(0.0f, -5.0f, 0.0f);
|
||||||
|
m_sA.m_centers[1].Set(0.0f, 5.0f, 0.0f);
|
||||||
m_sA.m_radius = 1.0f;
|
m_sA.m_radius = 1.0f;
|
||||||
|
|
||||||
m_xfA.SetIdentity();
|
m_xfB.SetIdentity();
|
||||||
|
m_xfB.position.Set(0.f, 0.0f, 0.0f);
|
||||||
m_sB.m_vertex1.Set(0.0f, -1.0f, 0.0f);
|
//m_xfB.rotation = b3ConvertQuatToRot(b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.251f * B3_PI));
|
||||||
m_sB.m_vertex2.Set(0.0f, 1.0f, 0.0f);
|
m_xfB.rotation.SetIdentity();
|
||||||
|
m_sB.m_centers[0].Set(0.0f, -1.0f, 0.0f);
|
||||||
|
m_sB.m_centers[1].Set(0.0f, 1.0f, 0.0f);
|
||||||
m_sB.m_radius = 1.0f;
|
m_sB.m_radius = 1.0f;
|
||||||
|
|
||||||
m_xfB.SetIdentity();
|
m_cache.count = 0;
|
||||||
|
|
||||||
m_shapeA = &m_sA;
|
m_shapeA = &m_sA;
|
||||||
m_shapeB = &m_sB;
|
m_shapeB = &m_sB;
|
||||||
m_cache.count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
|
@ -40,15 +40,16 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = e_dynamicBody;
|
||||||
|
|
||||||
bdef.position.Set(0.0f, 10.0f, 0.0f);
|
bdef.position.Set(0.0f, 10.0f, 0.0f);
|
||||||
bdef.angularVelocity.Set(0.5f * B3_PI, 10.0f * B3_PI, 0.0f);
|
bdef.orientation.Set(b3Vec3(0.0f, 0.0f, -1.0f), 1.5f * B3_PI);
|
||||||
|
bdef.linearVelocity.Set(0.005f, -10.0f, 0.005f);
|
||||||
|
bdef.angularVelocity.Set(2000.0f * B3_PI, 2000.0f * B3_PI, 10000.0f * B3_PI);
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3CapsuleShape capsule;
|
b3CapsuleShape capsule;
|
||||||
capsule.m_vertex1.Set(0.0f, 4.0f, 0.0f);
|
capsule.m_centers[0].Set(0.0f, 4.0f, 0.0f);
|
||||||
capsule.m_vertex2.Set(0.0f, -4.0f, 0.0f);
|
capsule.m_centers[1].Set(0.0f, -4.0f, 0.0f);
|
||||||
capsule.m_radius = 0.5f;
|
capsule.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
|
@ -24,110 +24,104 @@ class CapsuleStack : public Test
|
|||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
e_h = 5,
|
e_rowCount = 1,
|
||||||
e_w = 1,
|
e_columnCount = 5,
|
||||||
e_d = 1
|
e_depthCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
CapsuleStack()
|
CapsuleStack()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bd;
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
bd.type = b3BodyType::e_staticBody;
|
||||||
|
|
||||||
|
b3Body* body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &m_groundHull;
|
hs.m_hull = &m_groundHull;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sd;
|
||||||
sdef.shape = &hs;
|
sd.shape = &hs;
|
||||||
sdef.friction = 1.0f;
|
|
||||||
|
body->CreateShape(sd);
|
||||||
body->CreateShape(sdef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scalar rx = 1.0f;
|
float32 height = 3.0f;
|
||||||
scalar r = 1.0f;
|
float32 radius = 1.0f;
|
||||||
|
float32 separation = 0.0f;
|
||||||
|
|
||||||
b3CapsuleShape capsule;
|
b3CapsuleShape capsule;
|
||||||
capsule.m_vertex1.Set(-rx, 0.0f, 0.0f);
|
capsule.m_centers[0].Set(0.0f, -0.5f * height, 0.0f);
|
||||||
capsule.m_vertex2.Set(rx, 0.0f, 0.0f);
|
capsule.m_centers[1].Set(0.0f, 0.5f * height, 0.0f);
|
||||||
capsule.m_radius = r;
|
capsule.m_radius = radius;
|
||||||
|
|
||||||
b3Vec3 e;
|
b3ShapeDef sdef;
|
||||||
e.x = rx + r;
|
sdef.shape = &capsule;
|
||||||
e.y = r;
|
sdef.density = 0.1f;
|
||||||
e.z = r;
|
sdef.friction = 0.4f;
|
||||||
|
|
||||||
b3Vec3 separation;
|
const u32 c = e_rowCount * e_columnCount * e_depthCount;
|
||||||
separation.x = 1.0f;
|
b3Body* bs[c];
|
||||||
separation.y = 1.0f;
|
u32 n = 0;
|
||||||
separation.z = 1.0f;
|
|
||||||
|
|
||||||
b3Vec3 scale;
|
b3AABB3 aabb;
|
||||||
scale.x = 2.0f * e.x + separation.x;
|
aabb.m_lower.Set(0.0f, 0.0f, 0.0f);
|
||||||
scale.y = 2.0f * e.y + separation.y;
|
aabb.m_upper.Set(0.0f, 0.0f, 0.0f);
|
||||||
scale.z = 2.0f * e.z + separation.z;
|
|
||||||
|
|
||||||
b3Vec3 size;
|
for (u32 i = 0; i < e_rowCount; ++i)
|
||||||
size.x = 2.0f * e.x + scale.x * scalar(e_w - 1);
|
|
||||||
size.y = 2.0f * e.y + scale.y * scalar(e_h - 1);
|
|
||||||
size.z = 2.0f * e.z + scale.z * scalar(e_d - 1);
|
|
||||||
|
|
||||||
b3Vec3 translation;
|
|
||||||
translation.x = e.x - 0.5f * size.x;
|
|
||||||
translation.y = e.y - 0.5f * size.y;
|
|
||||||
translation.z = e.z - 0.5f * size.z;
|
|
||||||
|
|
||||||
translation.y += 9.0f;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < e_h; ++i)
|
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < e_w; ++j)
|
for (u32 j = 0; j < e_columnCount; ++j)
|
||||||
{
|
{
|
||||||
for (u32 k = 0; k < e_d; ++k)
|
for (u32 k = 0; k < e_depthCount; ++k)
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = b3BodyType::e_dynamicBody;
|
||||||
|
|
||||||
bdef.position.Set(scalar(j), scalar(i), scalar(k));
|
bdef.position.x = (2.0f + separation) * float32(i) * (0.5f * height + radius);
|
||||||
|
bdef.position.y = 2.0f + (2.0f + separation) * float32(j) * radius;
|
||||||
bdef.position.x *= scale.x;
|
bdef.position.z = (2.0f + separation) * float32(k) * radius;
|
||||||
bdef.position.y *= scale.y;
|
|
||||||
bdef.position.z *= scale.z;
|
bdef.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
||||||
|
|
||||||
bdef.position += translation;
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
bs[n++] = body;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3Shape* shape = body->CreateShape(sdef);
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.3f;
|
|
||||||
sdef.shape = &capsule;
|
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
b3AABB3 aabb2;
|
||||||
|
shape->ComputeAABB(&aabb2, body->GetTransform());
|
||||||
|
|
||||||
u32 bodyIndex = GetBodyIndex(i, j, k);
|
aabb = b3Combine(aabb, aabb2);
|
||||||
|
|
||||||
m_bodies[bodyIndex] = body;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
u32 GetBodyIndex(u32 i, u32 j, u32 k)
|
b3Vec3 center = aabb.Centroid();
|
||||||
{
|
|
||||||
B3_ASSERT(i < e_h);
|
for (u32 i = 0; i < n; ++i)
|
||||||
B3_ASSERT(j < e_w);
|
{
|
||||||
B3_ASSERT(k < e_d);
|
b3Body* b = bs[i];
|
||||||
return k + e_d * (j + e_w * i);
|
const b3Vec3& p = b->GetSweep().worldCenter;
|
||||||
|
const b3Quat& q = b->GetSweep().orientation;
|
||||||
|
|
||||||
|
// centralize
|
||||||
|
b3Vec3 position = p - center;
|
||||||
|
|
||||||
|
// move up
|
||||||
|
position.y += 5.0f + 0.5f * aabb.Height() + radius;
|
||||||
|
|
||||||
|
// maintain orientation
|
||||||
|
b3Vec3 axis;
|
||||||
|
float32 angle;
|
||||||
|
q.GetAxisAngle(&axis, &angle);
|
||||||
|
b->SetTransform(position, axis, angle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new CapsuleStack();
|
return new CapsuleStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Body* m_bodies[e_h * e_w * e_d];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 CLOTH_ELEMENT_TEST_H
|
|
||||||
#define CLOTH_ELEMENT_TEST_H
|
|
||||||
|
|
||||||
class ClothElementTest : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 10,
|
|
||||||
e_h = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
ClothElementTest()
|
|
||||||
{
|
|
||||||
g_camera->m_zoom = 20.0f;
|
|
||||||
|
|
||||||
b3GridClothMesh<e_w, e_h> m;
|
|
||||||
|
|
||||||
b3ClothParticle** particles = (b3ClothParticle * *)b3Alloc(m.vertexCount * sizeof(b3ClothParticle*));
|
|
||||||
for (u32 i = 0; i < m.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
b3ClothParticleDef pd;
|
|
||||||
pd.type = e_dynamicClothParticle;
|
|
||||||
pd.position = m.vertices[i];
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth.CreateParticle(pd);
|
|
||||||
particles[i] = p;
|
|
||||||
|
|
||||||
b3ClothSphereShapeDef sd;
|
|
||||||
sd.p = p;
|
|
||||||
sd.radius = 0.2f;
|
|
||||||
sd.friction = 0.4f;
|
|
||||||
|
|
||||||
m_cloth.CreateSphereShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < m.triangleCount; ++i)
|
|
||||||
{
|
|
||||||
u32 v1 = m.triangles[i].v1;
|
|
||||||
u32 v2 = m.triangles[i].v2;
|
|
||||||
u32 v3 = m.triangles[i].v3;
|
|
||||||
|
|
||||||
b3Vec3 x1 = m.vertices[v1];
|
|
||||||
b3Vec3 x2 = m.vertices[v2];
|
|
||||||
b3Vec3 x3 = m.vertices[v3];
|
|
||||||
|
|
||||||
b3ClothParticle* p1 = particles[v1];
|
|
||||||
b3ClothParticle* p2 = particles[v2];
|
|
||||||
b3ClothParticle* p3 = particles[v3];
|
|
||||||
|
|
||||||
b3ClothTriangleShapeDef tsd;
|
|
||||||
tsd.p1 = p1;
|
|
||||||
tsd.p2 = p2;
|
|
||||||
tsd.p3 = p3;
|
|
||||||
tsd.v1 = x1;
|
|
||||||
tsd.v2 = x2;
|
|
||||||
tsd.v3 = x3;
|
|
||||||
tsd.density = 0.1f;
|
|
||||||
|
|
||||||
m_cloth.CreateTriangleShape(tsd);
|
|
||||||
|
|
||||||
b3ElementForceDef fd;
|
|
||||||
fd.p1 = p1;
|
|
||||||
fd.p2 = p2;
|
|
||||||
fd.p3 = p3;
|
|
||||||
fd.E_x = 500.0f;
|
|
||||||
fd.E_y = 500.0f;
|
|
||||||
fd.E_s = 500.0f;
|
|
||||||
fd.nu_xy = 0.3f;
|
|
||||||
fd.nu_yx = 0.3f;
|
|
||||||
fd.v1 = x1;
|
|
||||||
fd.v2 = x2;
|
|
||||||
fd.v3 = x3;
|
|
||||||
|
|
||||||
m_cloth.CreateForce(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < e_w + 1; ++i)
|
|
||||||
{
|
|
||||||
u32 vertex = m.GetVertex(0, i);
|
|
||||||
particles[vertex]->SetType(e_staticClothParticle);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Free(particles);
|
|
||||||
|
|
||||||
m_cloth.SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
|
||||||
|
|
||||||
m_clothDragger = new b3ClothDragger(&m_ray, &m_cloth);
|
|
||||||
m_clothDragger->SetStaticDrag(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
~ClothElementTest()
|
|
||||||
{
|
|
||||||
delete m_clothDragger;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
m_cloth.Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
m_cloth.Draw();
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_clothSolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_cloth.GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseMove(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->Drag();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_clothDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new ClothElementTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Cloth m_cloth;
|
|
||||||
b3ClothDragger* m_clothDragger;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,268 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 CLOTH_SDF_H
|
|
||||||
#define CLOTH_SDF_H
|
|
||||||
|
|
||||||
#define TINYOBJLOADER_IMPLEMENTATION
|
|
||||||
#include <tinyobjloader/tiny_obj_loader.h>
|
|
||||||
|
|
||||||
struct SDFMesh
|
|
||||||
{
|
|
||||||
u32 vertexCount;
|
|
||||||
b3Vec3* vertices;
|
|
||||||
u32 indexCount;
|
|
||||||
u32* indices;
|
|
||||||
|
|
||||||
SDFMesh()
|
|
||||||
{
|
|
||||||
vertexCount = 0;
|
|
||||||
vertices = nullptr;
|
|
||||||
indexCount = 0;
|
|
||||||
indices = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~SDFMesh()
|
|
||||||
{
|
|
||||||
free(vertices);
|
|
||||||
free(indices);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Load(const char* filename)
|
|
||||||
{
|
|
||||||
tinyobj::attrib_t attributes;
|
|
||||||
std::vector<tinyobj::shape_t> shapes;
|
|
||||||
std::vector<tinyobj::material_t> materials;
|
|
||||||
|
|
||||||
std::string warning;
|
|
||||||
std::string error;
|
|
||||||
bool ok = tinyobj::LoadObj(&attributes, &shapes, &materials, &warning, &error, filename);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(vertexCount == 0);
|
|
||||||
vertexCount = attributes.vertices.size() / 3;
|
|
||||||
vertices = (b3Vec3*)malloc(vertexCount * sizeof(b3Vec3));
|
|
||||||
for (size_t i = 0; i < attributes.vertices.size() / 3; ++i)
|
|
||||||
{
|
|
||||||
tinyobj::real_t x = attributes.vertices[3 * i + 0];
|
|
||||||
tinyobj::real_t y = attributes.vertices[3 * i + 1];
|
|
||||||
tinyobj::real_t z = attributes.vertices[3 * i + 2];
|
|
||||||
|
|
||||||
b3Vec3 v(x, y, z);
|
|
||||||
|
|
||||||
vertices[i] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(indexCount == 0);
|
|
||||||
for (size_t s = 0; s < shapes.size(); s++)
|
|
||||||
{
|
|
||||||
tinyobj::shape_t& shape = shapes[s];
|
|
||||||
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++)
|
|
||||||
{
|
|
||||||
indexCount += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
indices = (u32*)malloc(indexCount * sizeof(u32));
|
|
||||||
|
|
||||||
indexCount = 0;
|
|
||||||
for (size_t s = 0; s < shapes.size(); s++)
|
|
||||||
{
|
|
||||||
tinyobj::shape_t& shape = shapes[s];
|
|
||||||
|
|
||||||
size_t index_offset = 0;
|
|
||||||
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++)
|
|
||||||
{
|
|
||||||
unsigned char fv = shapes[s].mesh.num_face_vertices[f];
|
|
||||||
|
|
||||||
for (size_t v = 0; v < 3; v++)
|
|
||||||
{
|
|
||||||
tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
|
|
||||||
|
|
||||||
size_t vi = idx.vertex_index;
|
|
||||||
|
|
||||||
indices[indexCount++] = vi;
|
|
||||||
}
|
|
||||||
|
|
||||||
index_offset += fv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Draw(const b3Transform& xf, const b3Vec3& scale, const b3Color& color) const
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < indexCount / 3; ++i)
|
|
||||||
{
|
|
||||||
u32 i1 = indices[3 * i + 0];
|
|
||||||
u32 i2 = indices[3 * i + 1];
|
|
||||||
u32 i3 = indices[3 * i + 2];
|
|
||||||
|
|
||||||
b3Vec3 v1 = xf * b3MulCW(scale, vertices[i1]);
|
|
||||||
b3Vec3 v2 = xf * b3MulCW(scale, vertices[i2]);
|
|
||||||
b3Vec3 v3 = xf * b3MulCW(scale, vertices[i3]);
|
|
||||||
|
|
||||||
b3Vec3 n = b3Cross(v2 - v1, v3 - v1);
|
|
||||||
n.Normalize();
|
|
||||||
|
|
||||||
g_draw->DrawSolidTriangle(n, v1, v2, v3, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ClothSDF : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClothSDF()
|
|
||||||
{
|
|
||||||
// Translate the cloth mesh
|
|
||||||
for (u32 i = 0; i < m_clothMesh.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
m_clothMesh.vertices[i].y += 5.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create cloth
|
|
||||||
b3ClothDef def;
|
|
||||||
def.mesh = &m_clothMesh;
|
|
||||||
def.density = 0.2f;
|
|
||||||
def.streching = 10000.0f;
|
|
||||||
def.strechDamping = 100.0f;
|
|
||||||
def.thickness = 0.2f;
|
|
||||||
def.friction = 0.2f;
|
|
||||||
|
|
||||||
m_cloth = new b3Cloth(def);
|
|
||||||
|
|
||||||
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
|
||||||
|
|
||||||
{
|
|
||||||
bool ok = m_sdfMesh.Load("data/teapot.obj");
|
|
||||||
assert(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = e_staticBody;
|
|
||||||
|
|
||||||
b3Body* b = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
bool ok = m_sdf.Load("data/teapot.cdf");
|
|
||||||
assert(ok);
|
|
||||||
|
|
||||||
b3SDFShape sdfShape;
|
|
||||||
sdfShape.m_sdf = &m_sdf;
|
|
||||||
sdfShape.m_radius = 0.2f;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &sdfShape;
|
|
||||||
sd.friction = 1.0f;
|
|
||||||
|
|
||||||
m_sdfShape = (b3SDFShape*)b->CreateShape(sd);
|
|
||||||
|
|
||||||
b3ClothWorldShapeDef csd;
|
|
||||||
csd.shape = m_sdfShape;
|
|
||||||
|
|
||||||
m_cloth->CreateWorldShape(csd);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
|
||||||
}
|
|
||||||
|
|
||||||
~ClothSDF()
|
|
||||||
{
|
|
||||||
delete m_clothDragger;
|
|
||||||
delete m_cloth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
m_cloth->Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
m_cloth->Draw();
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* sdfBody = m_sdfShape->GetBody();
|
|
||||||
m_sdfMesh.Draw(sdfBody->GetTransform(), m_sdfShape->m_scale, b3Color_white);
|
|
||||||
|
|
||||||
extern u32 b3_clothSolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_cloth->GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseMove(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->Drag();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_clothDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new ClothSDF();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3GridClothMesh<10, 10> m_clothMesh;
|
|
||||||
b3Cloth* m_cloth;
|
|
||||||
b3ClothDragger* m_clothDragger;
|
|
||||||
|
|
||||||
SDFMesh m_sdfMesh;
|
|
||||||
b3SDF m_sdf;
|
|
||||||
b3SDFShape* m_sdfShape;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -22,82 +22,15 @@
|
|||||||
class ClothSelfCollision : public Test
|
class ClothSelfCollision : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w1 = 5,
|
|
||||||
e_h1 = 5,
|
|
||||||
e_w2 = 5,
|
|
||||||
e_h2 = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
ClothSelfCollision()
|
ClothSelfCollision()
|
||||||
{
|
{
|
||||||
b3GridClothMesh<e_w1, e_h1> mesh1;
|
// Translate the mesh
|
||||||
b3Quat qX = b3QuatRotationX(0.5f * B3_PI);
|
for (u32 i = 0; i < m_clothMesh.vertexCount; ++i)
|
||||||
for (u32 i = 0; i < mesh1.vertexCount; ++i)
|
|
||||||
{
|
{
|
||||||
mesh1.vertices[i] = b3Mul(qX, mesh1.vertices[i]);
|
m_clothMesh.vertices[i].y += 5.0f;
|
||||||
mesh1.vertices[i].y += 5.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b3GridClothMesh<e_w2, e_h2> mesh2;
|
// Create cloth
|
||||||
b3Quat qY = b3QuatRotationY(0.5f * B3_PI);
|
|
||||||
for (u32 i = 0; i < mesh2.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
mesh2.vertices[i] = b3Mul(qY * qX, mesh2.vertices[i]);
|
|
||||||
mesh2.vertices[i].y += 12.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge the meshes
|
|
||||||
m_clothMesh.vertexCount = mesh1.vertexCount + mesh2.vertexCount;
|
|
||||||
m_clothMesh.vertices = (b3Vec3*)b3Alloc(m_clothMesh.vertexCount * sizeof(b3Vec3));
|
|
||||||
|
|
||||||
u32* newVertices1 = (u32*)b3Alloc(mesh1.vertexCount * sizeof(u32));
|
|
||||||
u32 vertexIndex = 0;
|
|
||||||
for (u32 i = 0; i < mesh1.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
newVertices1[i] = vertexIndex;
|
|
||||||
m_clothMesh.vertices[vertexIndex++] = mesh1.vertices[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
u32* newVertices2 = (u32*)b3Alloc(mesh2.vertexCount * sizeof(u32));
|
|
||||||
for (u32 i = 0; i < mesh2.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
newVertices2[i] = vertexIndex;
|
|
||||||
m_clothMesh.vertices[vertexIndex++] = mesh2.vertices[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clothMesh.triangleCount = mesh1.triangleCount + mesh2.triangleCount;
|
|
||||||
m_clothMesh.triangles = (b3ClothMeshTriangle*)b3Alloc(m_clothMesh.triangleCount * sizeof(b3ClothMeshTriangle));
|
|
||||||
u32 triangleIndex = 0;
|
|
||||||
for (u32 i = 0; i < mesh1.triangleCount; ++i)
|
|
||||||
{
|
|
||||||
m_clothMesh.triangles[triangleIndex].v1 = newVertices1[mesh1.triangles[i].v1];
|
|
||||||
m_clothMesh.triangles[triangleIndex].v2 = newVertices1[mesh1.triangles[i].v2];
|
|
||||||
m_clothMesh.triangles[triangleIndex].v3 = newVertices1[mesh1.triangles[i].v3];
|
|
||||||
++triangleIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < mesh2.triangleCount; ++i)
|
|
||||||
{
|
|
||||||
m_clothMesh.triangles[triangleIndex].v1 = newVertices2[mesh2.triangles[i].v1];
|
|
||||||
m_clothMesh.triangles[triangleIndex].v2 = newVertices2[mesh2.triangles[i].v2];
|
|
||||||
m_clothMesh.triangles[triangleIndex].v3 = newVertices2[mesh2.triangles[i].v3];
|
|
||||||
++triangleIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clothMesh.meshCount = 1;
|
|
||||||
m_clothMesh.meshes = (b3ClothMeshMesh*)b3Alloc(sizeof(b3ClothMeshMesh));
|
|
||||||
m_clothMesh.meshes->startTriangle = 0;
|
|
||||||
m_clothMesh.meshes->triangleCount = m_clothMesh.triangleCount;
|
|
||||||
m_clothMesh.meshes->startVertex = 0;
|
|
||||||
m_clothMesh.meshes->vertexCount = m_clothMesh.vertexCount;
|
|
||||||
|
|
||||||
m_clothMesh.shearingLineCount = 0;
|
|
||||||
m_clothMesh.bendingLineCount = 0;
|
|
||||||
m_clothMesh.sewingLineCount = 0;
|
|
||||||
|
|
||||||
// Create the cloth
|
|
||||||
b3ClothDef def;
|
b3ClothDef def;
|
||||||
def.mesh = &m_clothMesh;
|
def.mesh = &m_clothMesh;
|
||||||
def.density = 1.0f;
|
def.density = 1.0f;
|
||||||
@ -108,37 +41,24 @@ public:
|
|||||||
m_cloth = new b3Cloth(def);
|
m_cloth = new b3Cloth(def);
|
||||||
|
|
||||||
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
||||||
m_cloth->EnableSelfCollision(true);
|
m_cloth->SetWorld(&m_world);
|
||||||
|
|
||||||
for (u32 i = 0; i < mesh1.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
u32 newVertex = newVertices1[i];
|
|
||||||
|
|
||||||
m_cloth->GetParticle(newVertex)->SetType(e_staticClothParticle);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Free(newVertices1);
|
|
||||||
b3Free(newVertices2);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
|
bd.type = e_staticBody;
|
||||||
|
|
||||||
b3Body* b = m_world.CreateBody(bd);
|
b3Body* b = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3HullShape hullShape;
|
b3CapsuleShape capsuleShape;
|
||||||
hullShape.m_hull = &m_groundHull;
|
capsuleShape.m_centers[0].Set(0.0f, 0.0f, -5.0f);
|
||||||
hullShape.m_radius = 0.0f;;
|
capsuleShape.m_centers[1].Set(0.0f, 0.0f, 5.0f);
|
||||||
|
capsuleShape.m_radius = 1.0f;;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
sd.shape = &hullShape;
|
sd.shape = &capsuleShape;
|
||||||
sd.friction = 1.0f;
|
sd.friction = 1.0f;
|
||||||
|
|
||||||
b3Shape* s = b->CreateShape(sd);
|
b->CreateShape(sd);
|
||||||
|
|
||||||
b3ClothWorldShapeDef csd;
|
|
||||||
csd.shape = s;
|
|
||||||
|
|
||||||
m_cloth->CreateWorldShape(csd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
||||||
@ -146,10 +66,6 @@ public:
|
|||||||
|
|
||||||
~ClothSelfCollision()
|
~ClothSelfCollision()
|
||||||
{
|
{
|
||||||
b3Free(m_clothMesh.vertices);
|
|
||||||
b3Free(m_clothMesh.triangles);
|
|
||||||
b3Free(m_clothMesh.meshes);
|
|
||||||
|
|
||||||
delete m_cloth;
|
delete m_cloth;
|
||||||
delete m_clothDragger;
|
delete m_clothDragger;
|
||||||
}
|
}
|
||||||
@ -167,27 +83,17 @@ public:
|
|||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
b3Vec3 pA = m_clothDragger->GetPointA();
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
b3Vec3 pB = m_clothDragger->GetPointB();
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pA, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pB, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
g_draw->DrawSegment(pA, pB, b3Color_white);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "S - Turn on/off self collision");
|
|
||||||
if (m_cloth->IsSelfCollisionEnabled())
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "Self collision enabled");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "Self collision disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_clothSolverIterations;
|
extern u32 b3_clothSolverIterations;
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
||||||
|
|
||||||
scalar E = m_cloth->GetEnergy();
|
float32 E = m_cloth->GetEnergy();
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
g_draw->DrawString(b3Color_white, "E = %f", E);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,20 +127,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyDown(int key)
|
|
||||||
{
|
|
||||||
if (key == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
m_cloth->EnableSelfCollision(!m_cloth->IsSelfCollisionEnabled());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new ClothSelfCollision();
|
return new ClothSelfCollision();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3ClothMesh m_clothMesh;
|
b3GridClothMesh<10, 10> m_clothMesh;
|
||||||
b3Cloth* m_cloth;
|
b3Cloth* m_cloth;
|
||||||
b3ClothDragger* m_clothDragger;
|
b3ClothDragger* m_clothDragger;
|
||||||
};
|
};
|
||||||
|
@ -1,571 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 CLOTH_TEARING_H
|
|
||||||
#define CLOTH_TEARING_H
|
|
||||||
|
|
||||||
class ClothTearing : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 10,
|
|
||||||
e_h = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
ClothTearing()
|
|
||||||
{
|
|
||||||
g_camera->m_zoom = 20.0f;
|
|
||||||
|
|
||||||
b3GridClothMesh<e_w, e_h> m;
|
|
||||||
|
|
||||||
b3ClothParticle** particles = (b3ClothParticle * *)b3Alloc(m.vertexCount * sizeof(b3ClothParticle*));
|
|
||||||
for (u32 i = 0; i < m.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
b3ClothParticleDef pd;
|
|
||||||
pd.type = e_dynamicClothParticle;
|
|
||||||
pd.position = m.vertices[i];
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth.CreateParticle(pd);
|
|
||||||
particles[i] = p;
|
|
||||||
|
|
||||||
b3ClothSphereShapeDef sd;
|
|
||||||
sd.p = p;
|
|
||||||
sd.radius = 0.2f;
|
|
||||||
sd.friction = 0.4f;
|
|
||||||
|
|
||||||
m_cloth.CreateSphereShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < m.triangleCount; ++i)
|
|
||||||
{
|
|
||||||
u32 v1 = m.triangles[i].v1;
|
|
||||||
u32 v2 = m.triangles[i].v2;
|
|
||||||
u32 v3 = m.triangles[i].v3;
|
|
||||||
|
|
||||||
b3ClothParticle* p1 = particles[v1];
|
|
||||||
b3ClothParticle* p2 = particles[v2];
|
|
||||||
b3ClothParticle* p3 = particles[v3];
|
|
||||||
|
|
||||||
b3ClothTriangleShapeDef tsd;
|
|
||||||
tsd.p1 = p1;
|
|
||||||
tsd.p2 = p2;
|
|
||||||
tsd.p3 = p3;
|
|
||||||
tsd.v1 = m.vertices[v1];
|
|
||||||
tsd.v2 = m.vertices[v2];
|
|
||||||
tsd.v3 = m.vertices[v3];
|
|
||||||
tsd.density = 0.1f;
|
|
||||||
|
|
||||||
m_cloth.CreateTriangleShape(tsd);
|
|
||||||
|
|
||||||
{
|
|
||||||
b3SpringForceDef sfd;
|
|
||||||
sfd.Initialize(p1, p2, 1000.0f, 10.0f);
|
|
||||||
|
|
||||||
CreateSpringForce(sfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3SpringForceDef sfd;
|
|
||||||
sfd.Initialize(p2, p3, 1000.0f, 10.0f);
|
|
||||||
|
|
||||||
CreateSpringForce(sfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3SpringForceDef sfd;
|
|
||||||
sfd.Initialize(p3, p1, 1000.0f, 10.0f);
|
|
||||||
|
|
||||||
CreateSpringForce(sfd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < e_w + 1; ++i)
|
|
||||||
{
|
|
||||||
u32 vertex = m.GetVertex(0, i);
|
|
||||||
particles[vertex]->SetType(e_staticClothParticle);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Free(particles);
|
|
||||||
|
|
||||||
m_cloth.SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
|
||||||
|
|
||||||
m_clothDragger = new b3ClothDragger(&m_ray, &m_cloth);
|
|
||||||
m_clothDragger->SetStaticDrag(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
~ClothTearing()
|
|
||||||
{
|
|
||||||
delete m_clothDragger;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* FindSpringForce(b3ClothParticle* p1, b3ClothParticle* p2)
|
|
||||||
{
|
|
||||||
for (b3Force* f = m_cloth.GetForceList().m_head; f; f = f->GetNext())
|
|
||||||
{
|
|
||||||
if (f->GetType() != e_springForce)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* sf = (b3SpringForce*)f;
|
|
||||||
|
|
||||||
b3ClothParticle* sp1 = sf->GetParticle1();
|
|
||||||
b3ClothParticle* sp2 = sf->GetParticle2();
|
|
||||||
|
|
||||||
if (sp1 == p1 && sp2 == p2)
|
|
||||||
{
|
|
||||||
return sf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sp1 == p2 && sp2 == p1)
|
|
||||||
{
|
|
||||||
return sf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* CreateSpringForce(const b3SpringForceDef& def)
|
|
||||||
{
|
|
||||||
b3SpringForce* sf = FindSpringForce(def.p1, def.p2);
|
|
||||||
if (sf != nullptr)
|
|
||||||
{
|
|
||||||
return sf;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (b3SpringForce*)m_cloth.CreateForce(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawSpringForces()
|
|
||||||
{
|
|
||||||
for (b3Force* f = m_cloth.GetForceList().m_head; f; f = f->GetNext())
|
|
||||||
{
|
|
||||||
if (f->GetType() != e_springForce)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* s = (b3SpringForce*)f;
|
|
||||||
|
|
||||||
b3ClothParticle* p1 = s->GetParticle1();
|
|
||||||
b3ClothParticle* p2 = s->GetParticle2();
|
|
||||||
|
|
||||||
g_draw->DrawSegment(p1->GetPosition(), p2->GetPosition(), b3Color_black);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Partition(b3ClothParticle* p, const b3Plane& plane,
|
|
||||||
b3Array<b3ClothTriangleShape*>& above,
|
|
||||||
b3Array<b3ClothTriangleShape*>& below)
|
|
||||||
{
|
|
||||||
for (b3ClothTriangleShape* t = m_cloth.GetTriangleShapeList().m_head; t; t = t->GetNext())
|
|
||||||
{
|
|
||||||
b3ClothParticle* p1 = t->GetParticle1();
|
|
||||||
b3ClothParticle* p2 = t->GetParticle2();
|
|
||||||
b3ClothParticle* p3 = t->GetParticle3();
|
|
||||||
|
|
||||||
if (p1 != p && p2 != p && p3 != p)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Vec3 x1 = p1->GetPosition();
|
|
||||||
b3Vec3 x2 = p2->GetPosition();
|
|
||||||
b3Vec3 x3 = p3->GetPosition();
|
|
||||||
|
|
||||||
b3Vec3 center = (x1 + x2 + x3) / 3.0f;
|
|
||||||
|
|
||||||
scalar distance = b3Distance(center, plane);
|
|
||||||
if (distance > 0.0f)
|
|
||||||
{
|
|
||||||
above.PushBack(t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
below.PushBack(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasSpring(const b3Array<b3ClothTriangleShape*>& triangles,
|
|
||||||
b3ClothParticle* pOld, b3ClothParticle* pOther)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < triangles.Count(); ++i)
|
|
||||||
{
|
|
||||||
b3ClothTriangleShape* triangle = triangles[i];
|
|
||||||
|
|
||||||
b3ClothParticle* tp1 = triangle->GetParticle1();
|
|
||||||
b3ClothParticle* tp2 = triangle->GetParticle2();
|
|
||||||
b3ClothParticle* tp3 = triangle->GetParticle3();
|
|
||||||
|
|
||||||
// 1, 2
|
|
||||||
if (tp1 == pOld && tp2 == pOther)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2, 1
|
|
||||||
if (tp2 == pOld && tp1 == pOther)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2, 3
|
|
||||||
if (tp2 == pOld && tp3 == pOther)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3, 2
|
|
||||||
if (tp3 == pOld && tp2 == pOther)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3, 1
|
|
||||||
if (tp3 == pOld && tp1 == pOther)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1, 3
|
|
||||||
if (tp1 == pOld && tp3 == pOther)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SplitParticle(b3ClothParticle* pOld, const b3Plane& plane)
|
|
||||||
{
|
|
||||||
// Collect triangles.
|
|
||||||
b3StackArray<b3ClothTriangleShape*, 32> trianglesAbove, trianglesBelow;
|
|
||||||
Partition(pOld, plane, trianglesAbove, trianglesBelow);
|
|
||||||
|
|
||||||
// There must be at least one triangle on each side of the plane.
|
|
||||||
if (trianglesAbove.Count() == 0 || trianglesBelow.Count() == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3ClothParticleDef pdNew;
|
|
||||||
pdNew.type = pOld->GetType();
|
|
||||||
pdNew.position = pOld->GetPosition() - 0.2f * plane.normal;
|
|
||||||
|
|
||||||
b3ClothParticle* pNew = m_cloth.CreateParticle(pdNew);
|
|
||||||
|
|
||||||
b3ClothSphereShapeDef ssdNew;
|
|
||||||
ssdNew.p = pNew;
|
|
||||||
ssdNew.radius = 0.2f;
|
|
||||||
ssdNew.friction = 0.4f;
|
|
||||||
|
|
||||||
m_cloth.CreateSphereShape(ssdNew);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < trianglesBelow.Count(); ++i)
|
|
||||||
{
|
|
||||||
b3ClothTriangleShape* triangle = trianglesBelow[i];
|
|
||||||
|
|
||||||
b3ClothParticle* p1 = triangle->GetParticle1();
|
|
||||||
b3ClothParticle* p2 = triangle->GetParticle2();
|
|
||||||
b3ClothParticle* p3 = triangle->GetParticle3();
|
|
||||||
|
|
||||||
m_cloth.DestroyTriangleShape(triangle);
|
|
||||||
|
|
||||||
if (p1 == pOld)
|
|
||||||
{
|
|
||||||
b3ClothTriangleShapeDef tdNew;
|
|
||||||
tdNew.p1 = pNew;
|
|
||||||
tdNew.p2 = p2;
|
|
||||||
tdNew.p3 = p3;
|
|
||||||
tdNew.v1 = pNew->GetPosition();
|
|
||||||
tdNew.v2 = p2->GetPosition();
|
|
||||||
tdNew.v3 = p3->GetPosition();
|
|
||||||
|
|
||||||
m_cloth.CreateTriangleShape(tdNew);
|
|
||||||
|
|
||||||
b3SpringForce* sf1 = FindSpringForce(p1, p2);
|
|
||||||
if (sf1)
|
|
||||||
{
|
|
||||||
b3SpringForceDef sNew;
|
|
||||||
sNew.p1 = pNew;
|
|
||||||
sNew.p2 = p2;
|
|
||||||
sNew.restLength = sf1->GetRestLenght();
|
|
||||||
sNew.structural = sf1->GetStructuralStiffness();
|
|
||||||
sNew.damping = sf1->GetDampingStiffness();
|
|
||||||
|
|
||||||
m_cloth.CreateForce(sNew);
|
|
||||||
|
|
||||||
if (HasSpring(trianglesAbove, p1, p2) == false)
|
|
||||||
{
|
|
||||||
m_cloth.DestroyForce(sf1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* sf2 = FindSpringForce(p3, p1);
|
|
||||||
if (sf2)
|
|
||||||
{
|
|
||||||
b3SpringForceDef sNew;
|
|
||||||
sNew.p1 = p3;
|
|
||||||
sNew.p2 = pNew;
|
|
||||||
sNew.restLength = sf2->GetRestLenght();
|
|
||||||
sNew.structural = sf2->GetStructuralStiffness();
|
|
||||||
sNew.damping = sf2->GetDampingStiffness();
|
|
||||||
|
|
||||||
m_cloth.CreateForce(sNew);
|
|
||||||
|
|
||||||
if (HasSpring(trianglesAbove, p3, p1) == false)
|
|
||||||
{
|
|
||||||
m_cloth.DestroyForce(sf2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p2 == pOld)
|
|
||||||
{
|
|
||||||
b3ClothTriangleShapeDef tdNew;
|
|
||||||
tdNew.p1 = p1;
|
|
||||||
tdNew.p2 = pNew;
|
|
||||||
tdNew.p3 = p3;
|
|
||||||
tdNew.v1 = p1->GetPosition();
|
|
||||||
tdNew.v2 = pNew->GetPosition();
|
|
||||||
tdNew.v3 = p3->GetPosition();
|
|
||||||
|
|
||||||
m_cloth.CreateTriangleShape(tdNew);
|
|
||||||
|
|
||||||
b3SpringForce* sf1 = FindSpringForce(p1, p2);
|
|
||||||
if (sf1)
|
|
||||||
{
|
|
||||||
b3SpringForceDef sNew;
|
|
||||||
sNew.p1 = p1;
|
|
||||||
sNew.p2 = pNew;
|
|
||||||
sNew.restLength = sf1->GetRestLenght();
|
|
||||||
sNew.structural = sf1->GetStructuralStiffness();
|
|
||||||
sNew.damping = sf1->GetDampingStiffness();
|
|
||||||
|
|
||||||
m_cloth.CreateForce(sNew);
|
|
||||||
|
|
||||||
if (HasSpring(trianglesAbove, p1, p2) == false)
|
|
||||||
{
|
|
||||||
m_cloth.DestroyForce(sf1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* sf2 = FindSpringForce(p2, p3);
|
|
||||||
if (sf2)
|
|
||||||
{
|
|
||||||
b3SpringForceDef sNew;
|
|
||||||
sNew.p1 = pNew;
|
|
||||||
sNew.p2 = p3;
|
|
||||||
sNew.restLength = sf2->GetRestLenght();
|
|
||||||
sNew.structural = sf2->GetStructuralStiffness();
|
|
||||||
sNew.damping = sf2->GetDampingStiffness();
|
|
||||||
|
|
||||||
m_cloth.CreateForce(sNew);
|
|
||||||
|
|
||||||
if (HasSpring(trianglesAbove, p2, p3) == false)
|
|
||||||
{
|
|
||||||
m_cloth.DestroyForce(sf2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p3 == pOld)
|
|
||||||
{
|
|
||||||
b3ClothTriangleShapeDef tdNew;
|
|
||||||
tdNew.p1 = p1;
|
|
||||||
tdNew.p2 = p2;
|
|
||||||
tdNew.p3 = pNew;
|
|
||||||
tdNew.v1 = p1->GetPosition();
|
|
||||||
tdNew.v2 = p2->GetPosition();
|
|
||||||
tdNew.v3 = pNew->GetPosition();
|
|
||||||
|
|
||||||
m_cloth.CreateTriangleShape(tdNew);
|
|
||||||
|
|
||||||
b3SpringForce* sf1 = FindSpringForce(p2, p3);
|
|
||||||
if (sf1)
|
|
||||||
{
|
|
||||||
b3SpringForceDef sNew;
|
|
||||||
sNew.p1 = p2;
|
|
||||||
sNew.p2 = pNew;
|
|
||||||
sNew.restLength = sf1->GetRestLenght();
|
|
||||||
sNew.structural = sf1->GetStructuralStiffness();
|
|
||||||
sNew.damping = sf1->GetDampingStiffness();
|
|
||||||
|
|
||||||
m_cloth.CreateForce(sNew);
|
|
||||||
|
|
||||||
if (HasSpring(trianglesAbove, p2, p3) == false)
|
|
||||||
{
|
|
||||||
m_cloth.DestroyForce(sf1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* sf2 = FindSpringForce(p3, p1);
|
|
||||||
if (sf2)
|
|
||||||
{
|
|
||||||
b3SpringForceDef sNew;
|
|
||||||
sNew.p1 = pNew;
|
|
||||||
sNew.p2 = p1;
|
|
||||||
sNew.restLength = sf2->GetRestLenght();
|
|
||||||
sNew.structural = sf2->GetStructuralStiffness();
|
|
||||||
sNew.damping = sf2->GetDampingStiffness();
|
|
||||||
|
|
||||||
m_cloth.CreateForce(sNew);
|
|
||||||
|
|
||||||
if (HasSpring(trianglesAbove, p3, p1) == false)
|
|
||||||
{
|
|
||||||
m_cloth.DestroyForce(sf2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Tear()
|
|
||||||
{
|
|
||||||
b3Force* f = m_cloth.GetForceList().m_head;
|
|
||||||
while (f)
|
|
||||||
{
|
|
||||||
if (f->GetType() != e_springForce)
|
|
||||||
{
|
|
||||||
f = f->GetNext();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SpringForce* s = (b3SpringForce*)f;
|
|
||||||
f = f->GetNext();
|
|
||||||
|
|
||||||
b3Vec3 tension = s->GetActionForce();
|
|
||||||
|
|
||||||
const scalar kMaxTension = 1000.0f;
|
|
||||||
|
|
||||||
if (b3LengthSquared(tension) <= kMaxTension * kMaxTension)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3ClothParticle* p1 = s->GetParticle1();
|
|
||||||
b3ClothParticle* p2 = s->GetParticle2();
|
|
||||||
|
|
||||||
b3Vec3 x1 = p1->GetPosition();
|
|
||||||
b3Vec3 x2 = p2->GetPosition();
|
|
||||||
|
|
||||||
if (p1->GetType() == e_dynamicClothParticle)
|
|
||||||
{
|
|
||||||
b3Vec3 n = b3Normalize(x2 - x1);
|
|
||||||
b3Plane plane(n, x1);
|
|
||||||
|
|
||||||
bool wasSplit = SplitParticle(p1, plane);
|
|
||||||
if (wasSplit)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p2->GetType() == e_dynamicClothParticle)
|
|
||||||
{
|
|
||||||
b3Vec3 n = b3Normalize(x1 - x2);
|
|
||||||
b3Plane plane(n, x2);
|
|
||||||
|
|
||||||
bool wasSplit = SplitParticle(p2, plane);
|
|
||||||
if (wasSplit)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
m_cloth.Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
while (Tear());
|
|
||||||
|
|
||||||
m_cloth.Draw();
|
|
||||||
|
|
||||||
DrawSpringForces();
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_clothSolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_cloth.GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseMove(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->Drag();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_clothDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_clothDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new ClothTearing();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Cloth m_cloth;
|
|
||||||
b3ClothDragger* m_clothDragger;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -38,9 +38,9 @@ public:
|
|||||||
{
|
{
|
||||||
for (u32 i = 0; i < e_count; ++i)
|
for (u32 i = 0; i < e_count; ++i)
|
||||||
{
|
{
|
||||||
scalar x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
scalar y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
scalar z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
|
|
||||||
b3Vec3 p(x, y, z);
|
b3Vec3 p(x, y, z);
|
||||||
m_points[i] = p;
|
m_points[i] = p;
|
||||||
@ -48,9 +48,9 @@ public:
|
|||||||
|
|
||||||
for (u32 i = 0; i < B3_MAX_MANIFOLDS; ++i)
|
for (u32 i = 0; i < B3_MAX_MANIFOLDS; ++i)
|
||||||
{
|
{
|
||||||
scalar r = RandomFloat(0.0f, 1.0f);
|
float32 r = RandomFloat(0.0f, 1.0f);
|
||||||
scalar g = RandomFloat(0.0f, 1.0f);
|
float32 g = RandomFloat(0.0f, 1.0f);
|
||||||
scalar b = RandomFloat(0.0f, 1.0f);
|
float32 b = RandomFloat(0.0f, 1.0f);
|
||||||
|
|
||||||
b3Color c(r, g, b);
|
b3Color c(r, g, b);
|
||||||
m_colors[i] = c;
|
m_colors[i] = c;
|
||||||
|
@ -68,43 +68,46 @@ public:
|
|||||||
{
|
{
|
||||||
if (key == GLFW_KEY_LEFT)
|
if (key == GLFW_KEY_LEFT)
|
||||||
{
|
{
|
||||||
m_xfB.translation.x -= 0.05f;
|
m_xfB.position.x -= 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_RIGHT)
|
if (key == GLFW_KEY_RIGHT)
|
||||||
{
|
{
|
||||||
m_xfB.translation.x += 0.05f;
|
m_xfB.position.x += 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_UP)
|
if (key == GLFW_KEY_UP)
|
||||||
{
|
{
|
||||||
m_xfB.translation.y += 0.05f;
|
m_xfB.position.y += 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_DOWN)
|
if (key == GLFW_KEY_DOWN)
|
||||||
{
|
{
|
||||||
m_xfB.translation.y -= 0.05f;
|
m_xfB.position.y -= 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_X)
|
if (key == GLFW_KEY_X)
|
||||||
{
|
{
|
||||||
b3Quat qx = b3QuatRotationX(0.05f * B3_PI);
|
b3Quat qx(b3Vec3(1.0f, 0.0f, 0.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfx = b3QuatMat33(qx);
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qx;
|
m_xfB.rotation = m_xfB.rotation * xfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_Y)
|
if (key == GLFW_KEY_Y)
|
||||||
{
|
{
|
||||||
b3Quat qy = b3QuatRotationY(0.05f * B3_PI);
|
b3Quat qy(b3Vec3(0.0f, 1.0f, 0.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfy = b3QuatMat33(qy);
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qy;
|
m_xfB.rotation = m_xfB.rotation * xfy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_Z)
|
if (key == GLFW_KEY_Z)
|
||||||
{
|
{
|
||||||
b3Quat qz = b3QuatRotationZ(0.05f * B3_PI);
|
b3Quat qy(b3Vec3(0.0f, 0.0f, 1.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfz = b3QuatMat33(qy);
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qz;
|
m_xfB.rotation = m_xfB.rotation * xfz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,33 +38,38 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
m_box1.SetExtents(1.0f, 1.0f, 1.0f);
|
b3Transform xf;
|
||||||
b3Vec3 translation(-5.0f, 10.0f, 0.0f);
|
xf.SetIdentity();
|
||||||
m_box1.Translate(translation);
|
xf.position.Set(-5.0f, 10.0f, 0.0f);
|
||||||
|
m_box1.SetTransform(xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Vec3 translation(5.0f, 10.0f, 0.0f);
|
b3Transform xf;
|
||||||
m_box2.SetExtents(1.0f, 1.0f, 1.0f);
|
xf.SetIdentity();
|
||||||
m_box2.Translate(translation);
|
xf.position.Set(5.0f, 10.0f, 0.0f);
|
||||||
|
m_box2.SetTransform(xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Vec3 translation(0.0f, 2.0f, 0.0f);
|
b3Transform xf;
|
||||||
m_box3.SetExtents(1.0f, 1.0f, 1.0f);
|
xf.SetIdentity();
|
||||||
m_box3.Translate(translation);
|
xf.position.Set(0.0f, 2.0f, 0.0f);
|
||||||
|
m_box3.SetTransform(xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Vec3 translation(0.0f, 6.0f, 0.0f);
|
b3Transform xf;
|
||||||
m_box4.SetExtents(1.0f, 1.0f, 1.0f);
|
xf.SetIdentity();
|
||||||
m_box4.Translate(translation);
|
xf.position.Set(0.0f, 6.0f, 0.0f);
|
||||||
|
m_box4.SetTransform(xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Vec3 translation(0.0f, 10.0f, 0.0f);
|
b3Transform xf;
|
||||||
m_box5.SetExtents(1.0f, 1.0f, 1.0f);
|
xf.SetIdentity();
|
||||||
m_box5.Translate(translation);
|
xf.position.Set(0.0f, 10.0f, 0.0f);
|
||||||
|
m_box5.SetTransform(xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -42,8 +42,8 @@ public:
|
|||||||
head = m_world.CreateBody(bd);
|
head = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
b3CapsuleShape cs;
|
||||||
cs.m_vertex1.Set(0.0f, 0.15f, 0.0f);
|
cs.m_centers[0].Set(0.0f, 0.15f, 0.0f);
|
||||||
cs.m_vertex2.Set(0.0f, -0.15f, 0.0f);
|
cs.m_centers[1].Set(0.0f, -0.15f, 0.0f);
|
||||||
cs.m_radius = 0.5f;
|
cs.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -55,22 +55,19 @@ public:
|
|||||||
{
|
{
|
||||||
b3Vec3 anchor(0.0f, 0.0f, 0.0f);
|
b3Vec3 anchor(0.0f, 0.0f, 0.0f);
|
||||||
b3Vec3 axis(0.0f, 1.0f, 0.0f);
|
b3Vec3 axis(0.0f, 1.0f, 0.0f);
|
||||||
scalar coneAngle = 0.5f * B3_PI;
|
float32 coneAngle = 0.5f * B3_PI;
|
||||||
|
|
||||||
b3ConeJointDef cd;
|
b3ConeJointDef cd;
|
||||||
cd.Initialize(ref, head, axis, anchor, coneAngle);
|
cd.Initialize(ref, head, axis, anchor, coneAngle);
|
||||||
cd.enableConeLimit = true;
|
cd.enableLimit = true;
|
||||||
|
|
||||||
cd.enableTwistLimit = true;
|
|
||||||
cd.lowerAngle = 0.0f;
|
|
||||||
cd.upperAngle = B3_PI;
|
|
||||||
|
|
||||||
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate the orientation
|
// Invalidate the orientation
|
||||||
b3Quat q = b3QuatRotationX(B3_PI);
|
b3Vec3 axis(1.0f, 0.0f, 0.0f);
|
||||||
head->SetTransform(head->GetPosition(), q);
|
float32 angle = B3_PI;
|
||||||
|
head->SetTransform(head->GetPosition(), axis, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
|
@ -1,282 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 CONVEX_CAST_H
|
|
||||||
#define CONVEX_CAST_H
|
|
||||||
|
|
||||||
class ConvexCast : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConvexCast()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(0.0f, 2.0f, 0.0f);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &b3BoxHull_identity;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
m_shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
m_grid.BuildTree();
|
|
||||||
m_grid.BuildAdjacency();
|
|
||||||
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(-10.0f, 5.0f, -2.0f);
|
|
||||||
bdef.orientation = b3QuatRotationZ(0.25f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3MeshShape hs;
|
|
||||||
hs.m_mesh = &m_grid;
|
|
||||||
hs.m_scale.Set(-1.0f, -1.0f, -2.0f);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(0.0f, 2.0f, 10.0f);
|
|
||||||
bdef.orientation = b3QuatRotationY(0.25f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &b3BoxHull_identity;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(-10.0f, 6.0f, -10.0f);
|
|
||||||
bdef.orientation = b3QuatRotationY(0.25f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
static b3BoxHull boxHull(2.0f, 4.0f, 0.5f);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &boxHull;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(10.0f, 2.0f, 0.0f);
|
|
||||||
bdef.orientation = b3QuatRotationY(0.20f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &b3BoxHull_identity;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(-10.0f, 2.0f, 14.0f);
|
|
||||||
bdef.orientation = b3QuatRotationY(0.05f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &b3BoxHull_identity;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(-14.0f, 2.0f, 5.0f);
|
|
||||||
bdef.orientation = b3QuatRotationY(-0.05f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &b3BoxHull_identity;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(20.0f, 2.0f, 5.0f);
|
|
||||||
bdef.orientation = b3QuatRotationY(-0.05f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &b3BoxHull_identity;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(12.0f, 2.0f, 5.0f);
|
|
||||||
bdef.orientation = b3QuatRotationY(-0.35f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3SphereShape hs;
|
|
||||||
hs.m_center.SetZero();
|
|
||||||
hs.m_radius = 2.5f;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.position.Set(0.0f, 1.0f, -12.0f);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3CapsuleShape hs;
|
|
||||||
hs.m_vertex1.Set(0.0f, 1.0f, 0.0f);
|
|
||||||
hs.m_vertex2.Set(0.0f, -1.0f, 0.0f);
|
|
||||||
hs.m_radius = 3.0f;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
b3Shape* shape = body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_d.Set(-50.0f, 2.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CastConvex() const
|
|
||||||
{
|
|
||||||
class ConvexCastFilter : public b3ConvexCastFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool ShouldConvexCast(b3Shape* shape)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ConvexCastFilter filter;
|
|
||||||
|
|
||||||
b3Body* body = m_shape->GetBody();
|
|
||||||
b3Transform xf = body->GetTransform();
|
|
||||||
|
|
||||||
m_world.DrawSolidShape(xf, m_shape, b3Color_red);
|
|
||||||
|
|
||||||
b3Vec3 p1 = xf.translation;
|
|
||||||
|
|
||||||
b3Vec3 p2 = p1 + m_d;
|
|
||||||
|
|
||||||
b3ConvexCastSingleOutput out;
|
|
||||||
if (m_world.ConvexCastSingle(&out, &filter, m_shape, m_d))
|
|
||||||
{
|
|
||||||
g_draw->DrawPoint(out.point, 4.0f, b3Color_red);
|
|
||||||
g_draw->DrawSegment(out.point, out.point + out.normal, b3Color_white);
|
|
||||||
|
|
||||||
b3Transform xft;
|
|
||||||
xft.rotation = xf.rotation;
|
|
||||||
xft.translation = xf.translation + out.fraction * m_d;
|
|
||||||
|
|
||||||
m_world.DrawShape(xft, m_shape, b3Color_red);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(p1, xft.translation, b3Color_green);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_draw->DrawSegment(p1, p2, b3Color_green);
|
|
||||||
|
|
||||||
b3Transform xf1;
|
|
||||||
xf1.rotation = xf.rotation;
|
|
||||||
xf1.translation = xf.translation + m_d;
|
|
||||||
|
|
||||||
m_world.DrawShape(xf1, m_shape, b3Color_red);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
scalar dt = g_testSettings->inv_hertz;
|
|
||||||
|
|
||||||
b3Quat q = b3QuatRotationY(0.05f * B3_PI * dt);
|
|
||||||
|
|
||||||
m_d = b3Mul(q, m_d);
|
|
||||||
|
|
||||||
CastConvex();
|
|
||||||
|
|
||||||
Test::Step();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new ConvexCast();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3GridMesh<5, 5> m_grid;
|
|
||||||
|
|
||||||
b3Shape* m_shape;
|
|
||||||
b3Vec3 m_d;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -66,9 +66,9 @@ public:
|
|||||||
m_count = 0;
|
m_count = 0;
|
||||||
for (u32 i = 0; i < e_count; ++i)
|
for (u32 i = 0; i < e_count; ++i)
|
||||||
{
|
{
|
||||||
float x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
|
|
||||||
// Clamp to force coplanarities.
|
// Clamp to force coplanarities.
|
||||||
// This will stress the convex hull creation code.
|
// This will stress the convex hull creation code.
|
||||||
@ -135,7 +135,7 @@ public:
|
|||||||
edge = m_hull.GetEdge(edge->next);
|
edge = m_hull.GetEdge(edge->next);
|
||||||
} while (edge != begin);
|
} while (edge != begin);
|
||||||
|
|
||||||
c /= scalar(vn);
|
c /= float32(vn);
|
||||||
g_draw->DrawSegment(c, c + n, b3Color_white);
|
g_draw->DrawSegment(c, c + n, b3Color_white);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 CONVEYOR_BELT_H
|
|
||||||
#define CONVEYOR_BELT_H
|
|
||||||
|
|
||||||
class ConveyorBelt : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
ConveyorBelt()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
// Ground
|
|
||||||
b3BodyDef bd;
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &hs;
|
|
||||||
|
|
||||||
body->CreateShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Platform
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.position.Set(0.0f, 5.0f, 0.0f);
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
m_platformHull.SetExtents(10.0f, 0.5f, 2.0f);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &m_platformHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &hs;
|
|
||||||
sd.friction = 0.8f;
|
|
||||||
m_platform = body->CreateShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boxes
|
|
||||||
m_boxHull.SetExtents(0.5f, 0.5f, 0.5f);
|
|
||||||
for (u32 i = 0; i < 5; ++i)
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = e_dynamicBody;
|
|
||||||
bd.position.Set(2.0f * i, 7.0f, 0.0f);
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &m_boxHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &hs;
|
|
||||||
sd.density = 0.2f;
|
|
||||||
|
|
||||||
body->CreateShape(sd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PreSolve(b3Contact* contact)
|
|
||||||
{
|
|
||||||
Test::PreSolve(contact);
|
|
||||||
|
|
||||||
b3Shape* shapeA = contact->GetShapeA();
|
|
||||||
b3Shape* shapeB = contact->GetShapeB();
|
|
||||||
|
|
||||||
if (shapeA == m_platform)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < contact->GetManifoldCount(); ++i)
|
|
||||||
{
|
|
||||||
b3Manifold* manifold = contact->GetManifold(i);
|
|
||||||
|
|
||||||
manifold->motorSpeed = 0.25f * B3_PI;
|
|
||||||
manifold->tangentSpeed2 = -2.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shapeB == m_platform)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < contact->GetManifoldCount(); ++i)
|
|
||||||
{
|
|
||||||
b3Manifold* manifold = contact->GetManifold(i);
|
|
||||||
|
|
||||||
manifold->motorSpeed = -0.25f * B3_PI;
|
|
||||||
manifold->tangentSpeed2 = 2.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new ConveyorBelt();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BoxHull m_platformHull;
|
|
||||||
b3Shape* m_platform;
|
|
||||||
b3BoxHull m_boxHull;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -24,17 +24,23 @@ class DeepCapsule : public Collide
|
|||||||
public:
|
public:
|
||||||
DeepCapsule()
|
DeepCapsule()
|
||||||
{
|
{
|
||||||
m_box.SetExtents(4.0f, 1.0f, 4.0f);
|
m_xfA.position.Set(0.0f, 0.0f, 0.0f);
|
||||||
m_sA.m_hull = &m_box;
|
m_xfA.rotation = b3QuatMat33(b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.55f * B3_PI));
|
||||||
|
|
||||||
|
m_sA.m_centers[0].Set(1.0f, -1.0f, 0.0f);
|
||||||
|
m_sA.m_centers[1].Set(0.0f, 1.0f, 0.0f);
|
||||||
|
m_sA.m_radius = 2.0f;
|
||||||
|
|
||||||
m_xfA.SetIdentity();
|
m_xfB.position.Set(0.f, 0.0f, 0.0f);
|
||||||
|
m_xfB.rotation = b3QuatMat33(b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.0f * B3_PI));
|
||||||
|
|
||||||
m_sB.m_vertex1.Set(1.0f, -1.0f, 0.0f);
|
b3Transform xf;
|
||||||
m_sB.m_vertex2.Set(0.0f, 1.0f, 0.0f);
|
xf.SetIdentity();
|
||||||
m_sB.m_radius = 2.0f;
|
xf.rotation = b3Diagonal(4.0f, 1.0f, 4.0f);
|
||||||
|
|
||||||
m_xfB.translation.Set(0.0f, 0.0f, 0.0f);
|
m_box.SetTransform(xf);
|
||||||
m_xfB.rotation = b3QuatRotationZ(0.55f * B3_PI);
|
|
||||||
|
m_sB.m_hull = &m_box;
|
||||||
|
|
||||||
m_shapeA = &m_sA;
|
m_shapeA = &m_sA;
|
||||||
m_shapeB = &m_sB;
|
m_shapeB = &m_sB;
|
||||||
@ -46,8 +52,8 @@ public:
|
|||||||
return new DeepCapsule();
|
return new DeepCapsule();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3HullShape m_sA;
|
b3CapsuleShape m_sA;
|
||||||
b3CapsuleShape m_sB;
|
b3HullShape m_sB;
|
||||||
b3BoxHull m_box;
|
b3BoxHull m_box;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,11 +24,15 @@ class Distance : public Test
|
|||||||
public:
|
public:
|
||||||
Distance()
|
Distance()
|
||||||
{
|
{
|
||||||
m_xfA.translation.Set(-5.0f, 0.0f, 0.0f);
|
m_xfA.SetIdentity();
|
||||||
|
m_xfA.position.Set(-5.0f, 0.0f, 0.0f);
|
||||||
m_xfA.rotation.SetIdentity();
|
m_xfA.rotation.SetIdentity();
|
||||||
m_shapeA.m_hull = &b3BoxHull_identity;
|
m_shapeA.m_centers[0].Set(0.0f, -2.0f, 0.0f);
|
||||||
|
m_shapeA.m_centers[1].Set(0.0f, 2.0f, 0.0f);
|
||||||
|
m_shapeA.m_radius = 1.0f;
|
||||||
|
|
||||||
m_xfB.translation.Set(5.0f, 0.0f, 0.0f);
|
m_xfB.SetIdentity();
|
||||||
|
m_xfB.position.Set(5.0f, 0.0f, 0.0f);
|
||||||
m_xfB.rotation.SetIdentity();
|
m_xfB.rotation.SetIdentity();
|
||||||
m_shapeB.m_hull = &b3BoxHull_identity;
|
m_shapeB.m_hull = &b3BoxHull_identity;
|
||||||
|
|
||||||
@ -75,43 +79,46 @@ public:
|
|||||||
{
|
{
|
||||||
if (key == GLFW_KEY_LEFT)
|
if (key == GLFW_KEY_LEFT)
|
||||||
{
|
{
|
||||||
m_xfB.translation.x -= 0.05f;
|
m_xfB.position.x -= 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_RIGHT)
|
if (key == GLFW_KEY_RIGHT)
|
||||||
{
|
{
|
||||||
m_xfB.translation.x += 0.05f;
|
m_xfB.position.x += 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_UP)
|
if (key == GLFW_KEY_UP)
|
||||||
{
|
{
|
||||||
m_xfB.translation.y += 0.05f;
|
m_xfB.position.y += 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_DOWN)
|
if (key == GLFW_KEY_DOWN)
|
||||||
{
|
{
|
||||||
m_xfB.translation.y -= 0.05f;
|
m_xfB.position.y -= 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_X)
|
if (key == GLFW_KEY_X)
|
||||||
{
|
{
|
||||||
b3Quat qx = b3QuatRotationX(0.05f * B3_PI);
|
b3Quat qx(b3Vec3(1.0f, 0.0f, 0.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfx = b3QuatMat33(qx);
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qx;
|
m_xfB.rotation = m_xfB.rotation * xfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_Y)
|
if (key == GLFW_KEY_Y)
|
||||||
{
|
{
|
||||||
b3Quat qy = b3QuatRotationY(0.05f * B3_PI);
|
b3Quat qy(b3Vec3(0.0f, 1.0f, 0.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfy = b3QuatMat33(qy);
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qy;
|
m_xfB.rotation = m_xfB.rotation * xfy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_Z)
|
if (key == GLFW_KEY_Z)
|
||||||
{
|
{
|
||||||
b3Quat qz = b3QuatRotationZ(0.05f * B3_PI);
|
b3Quat qy(b3Vec3(0.0f, 0.0f, 1.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfz = b3QuatMat33(qy);
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qz;
|
m_xfB.rotation = m_xfB.rotation * xfz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +127,7 @@ public:
|
|||||||
return new Distance();
|
return new Distance();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3HullShape m_shapeA;
|
b3CapsuleShape m_shapeA;
|
||||||
b3Transform m_xfA;
|
b3Transform m_xfA;
|
||||||
b3ShapeGJKProxy m_proxyA;
|
b3ShapeGJKProxy m_proxyA;
|
||||||
|
|
||||||
|
@ -40,14 +40,14 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = e_dynamicBody;
|
||||||
bdef.orientation.SetAxisAngle(b3Vec3(1.0f, 0.0f, 0.0f), 0.5f * B3_PI);
|
bdef.orientation.Set(b3Vec3(1.0f, 0.0f, 0.0f), 0.5f * B3_PI);
|
||||||
bdef.position.Set(0.0f, 10.0f, 0.0f);
|
bdef.position.Set(0.0f, 10.0f, 0.0f);
|
||||||
bdef.angularVelocity.Set(0.0f, 0.0f, 4.0f * B3_PI);
|
bdef.angularVelocity.Set(0.0f, 0.0f, 4.0f * B3_PI);
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
{
|
{
|
||||||
m_rotorBox.SetExtents(1.0f, 0.5f, 7.0f);
|
m_rotorBox.Set(1.0f, 0.5f, 7.0f);
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &m_rotorBox;
|
hull.m_hull = &m_rotorBox;
|
||||||
@ -60,7 +60,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
m_cylinderHull.SetExtents(0.95f, 4.0f);
|
m_cylinderHull.SetAsCylinder(0.95f, 4.0f);
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &m_cylinderHull;
|
hull.m_hull = &m_cylinderHull;
|
||||||
@ -86,7 +86,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_rotorBox;
|
b3BoxHull m_rotorBox;
|
||||||
b3CylinderHull m_cylinderHull;
|
b3QHull m_cylinderHull;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -24,10 +24,16 @@ class HingeChain : public Test
|
|||||||
public:
|
public:
|
||||||
HingeChain()
|
HingeChain()
|
||||||
{
|
{
|
||||||
static b3BoxHull box(2.0f, 4.0f, 0.5f);
|
static b3BoxHull doorHull;
|
||||||
|
{
|
||||||
|
b3Transform xf;
|
||||||
|
xf.position.SetZero();
|
||||||
|
xf.rotation = b3Diagonal(2.0f, 4.0f, 0.5f);
|
||||||
|
doorHull.SetTransform(xf);
|
||||||
|
}
|
||||||
|
|
||||||
scalar x = -50.0f;
|
float32 x = -50.0f;
|
||||||
scalar y = 0.0f;
|
float32 y = 0.0f;
|
||||||
|
|
||||||
b3Body* lastHinge;
|
b3Body* lastHinge;
|
||||||
{
|
{
|
||||||
@ -36,7 +42,7 @@ public:
|
|||||||
lastHinge = m_world.CreateBody(bd);
|
lastHinge = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &box;
|
hull.m_hull = &doorHull;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.shape = &hull;
|
sdef.shape = &hull;
|
||||||
@ -54,7 +60,7 @@ public:
|
|||||||
b3Body* hinge = m_world.CreateBody(bd);
|
b3Body* hinge = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &box;
|
hull.m_hull = &doorHull;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.shape = &hull;
|
sdef.shape = &hull;
|
||||||
|
@ -29,7 +29,7 @@ public:
|
|||||||
|
|
||||||
HullCollision()
|
HullCollision()
|
||||||
{
|
{
|
||||||
m_xfA.translation.Set(0.0f, 1.5f, 0.0f);
|
m_xfA.position.Set(0.0f, 1.5f, 0.0f);
|
||||||
m_xfA.rotation.SetIdentity();
|
m_xfA.rotation.SetIdentity();
|
||||||
|
|
||||||
m_xfB.SetIdentity();
|
m_xfB.SetIdentity();
|
||||||
@ -53,9 +53,9 @@ public:
|
|||||||
{
|
{
|
||||||
for (u32 i = 0; i < e_count; ++i)
|
for (u32 i = 0; i < e_count; ++i)
|
||||||
{
|
{
|
||||||
float x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
|
|
||||||
x = b3Clamp(x, -2.5f, 2.5f);
|
x = b3Clamp(x, -2.5f, 2.5f);
|
||||||
y = b3Clamp(y, -2.5f, 2.5f);
|
y = b3Clamp(y, -2.5f, 2.5f);
|
||||||
@ -68,9 +68,9 @@ public:
|
|||||||
|
|
||||||
for (u32 i = 0; i < e_count; ++i)
|
for (u32 i = 0; i < e_count; ++i)
|
||||||
{
|
{
|
||||||
float x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
|
|
||||||
x = b3Clamp(x, -2.5f, 2.5f);
|
x = b3Clamp(x, -2.5f, 2.5f);
|
||||||
y = b3Clamp(y, -2.5f, 2.5f);
|
y = b3Clamp(y, -2.5f, 2.5f);
|
||||||
@ -98,7 +98,7 @@ public:
|
|||||||
sB.m_hull = &hull2;
|
sB.m_hull = &hull2;
|
||||||
m_shapeB = &sB;
|
m_shapeB = &sB;
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "G - Generate random convex hulls");
|
g_draw->DrawString(b3Color_white, "G - Generate a random convex hull pair");
|
||||||
|
|
||||||
Collide::Step();
|
Collide::Step();
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,9 @@ public:
|
|||||||
{
|
{
|
||||||
// Clamp to force coplanarities.
|
// Clamp to force coplanarities.
|
||||||
// This will stress the generation code.
|
// This will stress the generation code.
|
||||||
float x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 x = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 y = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
float z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
float32 z = 3.0f * RandomFloat(-1.0f, 1.0f);
|
||||||
|
|
||||||
x = b3Clamp(x, -1.5f, 1.5f);
|
x = b3Clamp(x, -1.5f, 1.5f);
|
||||||
y = b3Clamp(y, -1.5f, 1.5f);
|
y = b3Clamp(y, -1.5f, 1.5f);
|
||||||
|
@ -38,7 +38,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 boxScale(1.0f, 0.5f, 2.0f);
|
b3Vec3 boxScale(1.0f, 0.5f, 2.0f);
|
||||||
static b3BoxHull boxHull(boxScale.x, boxScale.y, boxScale.z);
|
|
||||||
|
static b3BoxHull boxHull;
|
||||||
|
|
||||||
|
b3Transform m;
|
||||||
|
m.rotation = b3Diagonal(boxScale.x, boxScale.y, boxScale.z);
|
||||||
|
m.position.SetZero();
|
||||||
|
|
||||||
|
boxHull.SetTransform(m);
|
||||||
|
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
@ -63,8 +70,8 @@ public:
|
|||||||
bd.type = e_dynamicBody;
|
bd.type = e_dynamicBody;
|
||||||
bd.position.Set(0.0f, 1.5f, 0.0f);
|
bd.position.Set(0.0f, 1.5f, 0.0f);
|
||||||
|
|
||||||
b3Quat q_y = b3QuatRotationY(0.4f * B3_PI);
|
b3Quat q_y(b3Vec3(0.0f, 1.0f, 0.0f), 0.4f * B3_PI);
|
||||||
b3Quat q_z = b3QuatRotationZ(0.04f * B3_PI);
|
b3Quat q_z(b3Vec3(0.0f, 0.0f, 1.0f), 0.04f * B3_PI);
|
||||||
b3Quat q = q_z * q_y;
|
b3Quat q = q_z * q_y;
|
||||||
|
|
||||||
bd.orientation = q;
|
bd.orientation = q;
|
||||||
|
@ -45,9 +45,15 @@ public:
|
|||||||
|
|
||||||
b3Vec3 boxScale(1.0f, 0.5f, 3.0f);
|
b3Vec3 boxScale(1.0f, 0.5f, 3.0f);
|
||||||
|
|
||||||
static b3BoxHull boxHull(boxScale.x, boxScale.y, boxScale.z);
|
static b3BoxHull boxHull;
|
||||||
|
|
||||||
scalar y = 2.0f;
|
b3Transform m;
|
||||||
|
m.rotation = b3Diagonal(boxScale.x, boxScale.y, boxScale.z);
|
||||||
|
m.position.SetZero();
|
||||||
|
|
||||||
|
boxHull.SetTransform(m);
|
||||||
|
|
||||||
|
float32 y = 2.0f;
|
||||||
|
|
||||||
for (u32 i = 0; i < e_layerCount / 2; ++i)
|
for (u32 i = 0; i < e_layerCount / 2; ++i)
|
||||||
{
|
{
|
||||||
@ -56,7 +62,7 @@ public:
|
|||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
|
|
||||||
bd.position.x = 2.0f * scalar(j) * boxScale.x;
|
bd.position.x = 2.0f * float32(j) * boxScale.x;
|
||||||
bd.position.y = y;
|
bd.position.y = y;
|
||||||
bd.position.z = 0.0f;
|
bd.position.z = 0.0f;
|
||||||
|
|
||||||
@ -80,11 +86,11 @@ public:
|
|||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
|
|
||||||
bd.orientation = b3QuatRotationY(0.5f * B3_PI);
|
bd.orientation.Set(b3Vec3(0.0f, 1.0f, 0.0f), 0.5f * B3_PI);
|
||||||
|
|
||||||
bd.position.x = 2.0f * boxScale.x;
|
bd.position.x = 2.0f * boxScale.x;
|
||||||
bd.position.y = y;
|
bd.position.y = y;
|
||||||
bd.position.z = -2.0f * boxScale.x + 2.0f * scalar(j) * boxScale.x;
|
bd.position.z = -2.0f * boxScale.x + 2.0f * float32(j) * boxScale.x;
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
b3Body* body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ public:
|
|||||||
m_body = m_world.CreateBody(bdef);
|
m_body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3CapsuleShape shape;
|
b3CapsuleShape shape;
|
||||||
shape.m_vertex1.Set(0.0f, 1.0f, 0.0f);
|
shape.m_centers[0].Set(0.0f, 1.0f, 0.0f);
|
||||||
shape.m_vertex2.Set(0.0f, -1.0f, 0.0f);
|
shape.m_centers[1].Set(0.0f, -1.0f, 0.0f);
|
||||||
shape.m_radius = 1.0f;
|
shape.m_radius = 1.0f;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
@ -55,11 +55,16 @@ public:
|
|||||||
{
|
{
|
||||||
Test::Step();
|
Test::Step();
|
||||||
|
|
||||||
b3Vec3 p(0.0f, 0.0f, 0.0f);
|
b3Vec3 q(0.0f, 0.0f, 0.0f);
|
||||||
if (b3Distance(m_body->GetPosition(), p) > 50.0f)
|
b3Vec3 p = m_body->GetTransform().position;
|
||||||
|
if (b3Distance(p, q) > 50.0f)
|
||||||
{
|
{
|
||||||
b3Quat q = m_body->GetOrientation();
|
b3Quat quat = m_body->GetSweep().orientation;
|
||||||
m_body->SetTransform(p, q);
|
|
||||||
|
b3Vec3 axis;
|
||||||
|
float32 angle;
|
||||||
|
quat.GetAxisAngle(&axis, &angle);
|
||||||
|
m_body->SetTransform(q, axis, angle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 LINEAR_TIME_OF_IMPACT_H
|
|
||||||
#define LINEAR_TIME_OF_IMPACT_H
|
|
||||||
|
|
||||||
class LinearTimeOfImpact : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LinearTimeOfImpact()
|
|
||||||
{
|
|
||||||
m_shapeA.m_hull = &b3BoxHull_identity;
|
|
||||||
m_shapeA.m_radius = 0.0f;
|
|
||||||
|
|
||||||
m_shapeB.m_hull = &b3BoxHull_identity;
|
|
||||||
m_shapeB.m_radius = 0.0f;
|
|
||||||
|
|
||||||
m_xfA.translation.Set(0.0f, 0.0f, 0.0f);
|
|
||||||
m_xfA.rotation.SetIdentity();
|
|
||||||
|
|
||||||
m_xfB.translation.Set(5.0f, 1.0f, 0.0f);
|
|
||||||
m_xfB.rotation.SetIdentity();
|
|
||||||
|
|
||||||
m_proxyA.Set(&m_shapeA, 0);
|
|
||||||
m_proxyB.Set(&m_shapeB, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
b3Vec3 dA = b3Vec3_zero;
|
|
||||||
b3Vec3 dB(-10.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
b3TOIOutput out = b3TimeOfImpact(m_xfA, m_proxyA, dA, m_xfB, m_proxyB, dB);
|
|
||||||
|
|
||||||
b3TOIOutput::State state = out.state;
|
|
||||||
scalar t = out.t;
|
|
||||||
u32 iterations = out.iterations;
|
|
||||||
|
|
||||||
if (state == b3TOIOutput::e_touching)
|
|
||||||
{
|
|
||||||
b3Transform xfA;
|
|
||||||
xfA.rotation = m_xfA.rotation;
|
|
||||||
xfA.translation = m_xfA.translation + t * dA;
|
|
||||||
|
|
||||||
b3Transform xfB;
|
|
||||||
xfB.rotation = m_xfB.rotation;
|
|
||||||
xfB.translation = m_xfB.translation + t * dB;
|
|
||||||
|
|
||||||
b3GJKOutput query = b3GJK(xfA, m_proxyA, xfB, m_proxyB, false);
|
|
||||||
|
|
||||||
b3Vec3 p1 = query.point1;
|
|
||||||
b3Vec3 p2 = query.point2;
|
|
||||||
b3Vec3 n1 = b3Normalize(p2 - p1);
|
|
||||||
b3Vec3 p = 0.5f * (p1 + p2);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(p, 4.0f, b3Color_green);
|
|
||||||
g_draw->DrawSegment(p1, p1 + n1, b3Color_green);
|
|
||||||
|
|
||||||
m_world.DrawShape(xfA, &m_shapeA, b3Color_black);
|
|
||||||
m_world.DrawShape(xfB, &m_shapeB, b3Color_black);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == b3TOIOutput::e_failed)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Failed");
|
|
||||||
}
|
|
||||||
else if (state == b3TOIOutput::e_overlapped)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Overlapped");
|
|
||||||
}
|
|
||||||
else if (state == b3TOIOutput::e_separated)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Separated!");
|
|
||||||
}
|
|
||||||
else if (state == b3TOIOutput::e_touching)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Touching!");
|
|
||||||
}
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", out.iterations);
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "Left/Right/Up/Down Arrow - Translate shape");
|
|
||||||
g_draw->DrawString(b3Color_white, "X/Y/Z - Rotate shape");
|
|
||||||
|
|
||||||
g_draw->DrawTransform(m_xfA);
|
|
||||||
g_draw->DrawTransform(m_xfB);
|
|
||||||
|
|
||||||
m_world.DrawShape(m_xfA, &m_shapeA, b3Color_black);
|
|
||||||
m_world.DrawShape(m_xfB, &m_shapeB, b3Color_black);
|
|
||||||
|
|
||||||
m_world.DrawSolidShape(m_xfA, &m_shapeA, b3Color_white);
|
|
||||||
m_world.DrawSolidShape(m_xfB, &m_shapeB, b3Color_white);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(m_xfA.translation, m_xfA.translation + dA, b3Color_white);
|
|
||||||
g_draw->DrawSegment(m_xfB.translation, m_xfB.translation + dB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int key)
|
|
||||||
{
|
|
||||||
if (key == GLFW_KEY_LEFT)
|
|
||||||
{
|
|
||||||
m_xfB.translation.x -= 0.105f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_RIGHT)
|
|
||||||
{
|
|
||||||
m_xfB.translation.x += 0.105f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_UP)
|
|
||||||
{
|
|
||||||
m_xfB.translation.y += 0.105f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_DOWN)
|
|
||||||
{
|
|
||||||
m_xfB.translation.y -= 0.105f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_X)
|
|
||||||
{
|
|
||||||
b3Quat qx = b3QuatRotationX(0.05f * B3_PI);
|
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_Y)
|
|
||||||
{
|
|
||||||
b3Quat qy = b3QuatRotationY(0.05f * B3_PI);
|
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_Z)
|
|
||||||
{
|
|
||||||
b3Quat qz = b3QuatRotationZ(0.05f * B3_PI);
|
|
||||||
|
|
||||||
m_xfB.rotation = m_xfB.rotation * qz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new LinearTimeOfImpact();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3HullShape m_shapeA;
|
|
||||||
b3Transform m_xfA;
|
|
||||||
b3ShapeGJKProxy m_proxyA;
|
|
||||||
|
|
||||||
b3HullShape m_shapeB;
|
|
||||||
b3Transform m_xfB;
|
|
||||||
b3ShapeGJKProxy m_proxyB;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -25,7 +25,6 @@ public:
|
|||||||
MeshContactTest()
|
MeshContactTest()
|
||||||
{
|
{
|
||||||
m_gridMesh.BuildTree();
|
m_gridMesh.BuildTree();
|
||||||
m_gridMesh.BuildAdjacency();
|
|
||||||
|
|
||||||
// Transform grid into a terrain
|
// Transform grid into a terrain
|
||||||
for (u32 i = 0; i < m_terrainMesh.vertexCount; ++i)
|
for (u32 i = 0; i < m_terrainMesh.vertexCount; ++i)
|
||||||
@ -34,22 +33,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_terrainMesh.BuildTree();
|
m_terrainMesh.BuildTree();
|
||||||
m_terrainMesh.BuildAdjacency();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
b3Body* groundBody = m_world.CreateBody(bd);
|
m_ground = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3MeshShape ms;
|
b3MeshShape ms;
|
||||||
ms.m_mesh = &m_gridMesh;
|
ms.m_mesh = &m_gridMesh;
|
||||||
ms.m_scale.Set(2.0f, 1.0f, 2.0f);
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
sd.shape = &ms;
|
sd.shape = &ms;
|
||||||
|
|
||||||
m_groundShape = (b3MeshShape*)groundBody->CreateShape(sd);
|
m_ground->CreateShape(sd);
|
||||||
|
|
||||||
m_selection = m_groundShape->m_mesh->triangleCount / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -57,8 +52,8 @@ public:
|
|||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
bd.position.Set(0.0f, 5.0f, 0.0f);
|
bd.position.Set(0.0f, 5.0f, 0.0f);
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
m_body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
{
|
{
|
||||||
b3SphereShape sphere;
|
b3SphereShape sphere;
|
||||||
sphere.m_center.SetZero();
|
sphere.m_center.SetZero();
|
||||||
@ -69,43 +64,25 @@ public:
|
|||||||
sd.density = 1.0f;
|
sd.density = 1.0f;
|
||||||
sd.friction = 0.5f;
|
sd.friction = 0.5f;
|
||||||
|
|
||||||
m_bodyShape = body->CreateShape(sd);
|
m_body->CreateShape(sd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_drawEdgeTypes = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyDown(int key)
|
void KeyDown(int key)
|
||||||
{
|
{
|
||||||
u32 minSelection = 0;
|
|
||||||
if (key == GLFW_KEY_LEFT)
|
|
||||||
{
|
|
||||||
m_selection = m_selection == minSelection ? minSelection : m_selection - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 maxSelection = m_groundShape->m_mesh->triangleCount - 1;
|
|
||||||
if (key == GLFW_KEY_RIGHT)
|
|
||||||
{
|
|
||||||
m_selection = m_selection == maxSelection ? maxSelection : m_selection + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_E)
|
|
||||||
{
|
|
||||||
m_drawEdgeTypes = !m_drawEdgeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_S || key == GLFW_KEY_C || key == GLFW_KEY_H)
|
if (key == GLFW_KEY_S || key == GLFW_KEY_C || key == GLFW_KEY_H)
|
||||||
{
|
{
|
||||||
b3Body* body = m_bodyShape->GetBody();
|
if (m_body)
|
||||||
|
{
|
||||||
m_world.DestroyBody(body);
|
m_world.DestroyBody(m_body);
|
||||||
|
}
|
||||||
|
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
bd.position.Set(0.0f, 5.0f, 0.0f);
|
bd.position.Set(0.0f, 5.0f, 0.0f);
|
||||||
|
|
||||||
body = m_world.CreateBody(bd);
|
m_body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
if (key == GLFW_KEY_S)
|
if (key == GLFW_KEY_S)
|
||||||
{
|
{
|
||||||
@ -118,14 +95,14 @@ public:
|
|||||||
sd.density = 1.0f;
|
sd.density = 1.0f;
|
||||||
sd.friction = 0.5f;
|
sd.friction = 0.5f;
|
||||||
|
|
||||||
m_bodyShape = body->CreateShape(sd);
|
m_body->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_C)
|
if (key == GLFW_KEY_C)
|
||||||
{
|
{
|
||||||
b3CapsuleShape capsule;
|
b3CapsuleShape capsule;
|
||||||
capsule.m_vertex1.Set(0.0f, -1.0f, 0.0f);
|
capsule.m_centers[0].Set(0.0f, -1.0f, 0.0f);
|
||||||
capsule.m_vertex2.Set(0.0f, 1.0f, 0.0f);
|
capsule.m_centers[1].Set(0.0f, 1.0f, 0.0f);
|
||||||
capsule.m_radius = 1.0f;
|
capsule.m_radius = 1.0f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -133,7 +110,7 @@ public:
|
|||||||
sd.density = 1.0f;
|
sd.density = 1.0f;
|
||||||
sd.friction = 0.5f;
|
sd.friction = 0.5f;
|
||||||
|
|
||||||
m_bodyShape = body->CreateShape(sd);
|
m_body->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_H)
|
if (key == GLFW_KEY_H)
|
||||||
@ -146,43 +123,41 @@ public:
|
|||||||
sd.density = 1.0f;
|
sd.density = 1.0f;
|
||||||
sd.friction = 0.5f;
|
sd.friction = 0.5f;
|
||||||
|
|
||||||
m_bodyShape = body->CreateShape(sd);
|
m_body->CreateShape(sd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_G || key == GLFW_KEY_T)
|
if (key == GLFW_KEY_G || key == GLFW_KEY_T)
|
||||||
{
|
{
|
||||||
b3Body* groundBody = m_groundShape->GetBody();
|
if (m_ground)
|
||||||
m_world.DestroyBody(groundBody);
|
{
|
||||||
|
m_world.DestroyBody(m_ground);
|
||||||
|
}
|
||||||
|
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
groundBody = m_world.CreateBody(bd);
|
m_ground = m_world.CreateBody(bd);
|
||||||
|
|
||||||
if (key == GLFW_KEY_G)
|
if (key == GLFW_KEY_G)
|
||||||
{
|
{
|
||||||
b3MeshShape ms;
|
b3MeshShape ms;
|
||||||
ms.m_mesh = &m_gridMesh;
|
ms.m_mesh = &m_gridMesh;
|
||||||
ms.m_scale.Set(2.0f, 1.0f, 2.0f);
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
sd.shape = &ms;
|
sd.shape = &ms;
|
||||||
|
|
||||||
m_groundShape = (b3MeshShape*)groundBody->CreateShape(sd);
|
m_ground->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == GLFW_KEY_T)
|
if (key == GLFW_KEY_T)
|
||||||
{
|
{
|
||||||
b3MeshShape ms;
|
b3MeshShape ms;
|
||||||
ms.m_mesh = &m_terrainMesh;
|
ms.m_mesh = &m_terrainMesh;
|
||||||
ms.m_scale.Set(2.0f, 1.5f, 2.0f);
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
sd.shape = &ms;
|
sd.shape = &ms;
|
||||||
|
|
||||||
m_groundShape = (b3MeshShape*)groundBody->CreateShape(sd);
|
m_ground->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_selection = m_groundShape->m_mesh->triangleCount / 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,108 +165,6 @@ public:
|
|||||||
{
|
{
|
||||||
Test::Step();
|
Test::Step();
|
||||||
|
|
||||||
const b3Mesh* mesh = m_groundShape->m_mesh;
|
|
||||||
b3Vec3 scale = m_groundShape->m_scale;
|
|
||||||
b3Body* body = m_groundShape->GetBody();
|
|
||||||
b3Transform xf = body->GetTransform();
|
|
||||||
|
|
||||||
{
|
|
||||||
const b3MeshTriangle* triangle = mesh->triangles + m_selection;
|
|
||||||
const b3MeshTriangleWings* triangleWings = mesh->triangleWings + m_selection;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < 3; ++i)
|
|
||||||
{
|
|
||||||
u32 j = i + 1 < 3 ? i + 1 : 0;
|
|
||||||
|
|
||||||
u32 v1 = triangle->GetVertex(i);
|
|
||||||
u32 v2 = triangle->GetVertex(j);
|
|
||||||
|
|
||||||
b3Vec3 p1 = xf * b3MulCW(scale, mesh->vertices[v1]);
|
|
||||||
b3Vec3 p2 = xf * b3MulCW(scale, mesh->vertices[v2]);
|
|
||||||
|
|
||||||
b3Vec3 center = scalar(0.5) * (p1 + p2);
|
|
||||||
g_draw->DrawString(b3Color_white, center, "e%d", i);
|
|
||||||
|
|
||||||
u32 wingVertex = triangleWings->GetVertex(i);
|
|
||||||
|
|
||||||
if (wingVertex != B3_NULL_VERTEX)
|
|
||||||
{
|
|
||||||
b3Vec3 vertex = xf * b3MulCW(scale, mesh->vertices[wingVertex]);
|
|
||||||
g_draw->DrawString(b3Color_white, vertex, "u%d", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_drawEdgeTypes)
|
|
||||||
{
|
|
||||||
b3Vec3 eyePoint(0.0f, 10.0f, 0.0f);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < mesh->triangleCount; ++i)
|
|
||||||
{
|
|
||||||
b3MeshTriangle* triangle = mesh->triangles + i;
|
|
||||||
b3MeshTriangleWings* triangleWings = mesh->triangleWings + i;
|
|
||||||
|
|
||||||
b3Vec3 A = xf * b3MulCW(scale, mesh->vertices[triangle->v1]);
|
|
||||||
b3Vec3 B = xf * b3MulCW(scale, mesh->vertices[triangle->v2]);
|
|
||||||
b3Vec3 C = xf * b3MulCW(scale, mesh->vertices[triangle->v3]);
|
|
||||||
|
|
||||||
b3Vec3 N = b3Cross(B - A, C - A);
|
|
||||||
N.Normalize();
|
|
||||||
|
|
||||||
b3Plane plane(N, A);
|
|
||||||
if (b3Distance(eyePoint, plane) < 0.0f)
|
|
||||||
{
|
|
||||||
plane = b3Plane(-N, A);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 j = 0; j < 3; ++j)
|
|
||||||
{
|
|
||||||
u32 k = j + 1 < 3 ? j + 1 : 0;
|
|
||||||
|
|
||||||
u32 v1 = triangle->GetVertex(j);
|
|
||||||
u32 v2 = triangle->GetVertex(k);
|
|
||||||
|
|
||||||
u32 u = triangleWings->GetVertex(j);
|
|
||||||
|
|
||||||
b3Vec3 p1 = xf * b3MulCW(scale, mesh->vertices[v1]);
|
|
||||||
b3Vec3 p2 = xf * b3MulCW(scale, mesh->vertices[v2]);
|
|
||||||
|
|
||||||
b3Vec3 center = scalar(0.5) * (p1 + p2);
|
|
||||||
|
|
||||||
if (u == B3_NULL_VERTEX)
|
|
||||||
{
|
|
||||||
g_draw->DrawPoint(center, scalar(4), b3Color_white);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Vec3 wingVertex = xf * b3MulCW(scale, mesh->vertices[u]);
|
|
||||||
|
|
||||||
scalar d = b3Distance(wingVertex, plane);
|
|
||||||
|
|
||||||
const scalar kCoplanarTol = 0.005f;
|
|
||||||
|
|
||||||
if (d < -kCoplanarTol)
|
|
||||||
{
|
|
||||||
// Below <=> Convex
|
|
||||||
g_draw->DrawPoint(center, scalar(4), b3Color_green);
|
|
||||||
}
|
|
||||||
else if (d > kCoplanarTol)
|
|
||||||
{
|
|
||||||
// Above <=> Concave
|
|
||||||
g_draw->DrawPoint(center, scalar(4), b3Color_yellow);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// d > -e && d < e
|
|
||||||
// On <=> Coplanar
|
|
||||||
g_draw->DrawPoint(center, scalar(4), b3Color_red);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "E - View Edge Types");
|
|
||||||
g_draw->DrawString(b3Color_white, "Arrows - Select Face Wings");
|
|
||||||
g_draw->DrawString(b3Color_white, "S - Sphere");
|
g_draw->DrawString(b3Color_white, "S - Sphere");
|
||||||
g_draw->DrawString(b3Color_white, "C - Capsule");
|
g_draw->DrawString(b3Color_white, "C - Capsule");
|
||||||
g_draw->DrawString(b3Color_white, "H - Hull");
|
g_draw->DrawString(b3Color_white, "H - Hull");
|
||||||
@ -304,14 +177,11 @@ public:
|
|||||||
return new MeshContactTest();
|
return new MeshContactTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool m_drawEdgeTypes;
|
|
||||||
u32 m_selection;
|
|
||||||
|
|
||||||
b3GridMesh<25, 25> m_terrainMesh;
|
b3GridMesh<25, 25> m_terrainMesh;
|
||||||
b3GridMesh<25, 25> m_gridMesh;
|
b3GridMesh<25, 25> m_gridMesh;
|
||||||
|
|
||||||
b3MeshShape* m_groundShape;
|
b3Body* m_ground;
|
||||||
b3Shape* m_bodyShape;
|
b3Body* m_body;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 MOTOR_TEST_H
|
|
||||||
#define MOTOR_TEST_H
|
|
||||||
|
|
||||||
class MotorTest : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
MotorTest()
|
|
||||||
{
|
|
||||||
b3Body* ground = nullptr;
|
|
||||||
{
|
|
||||||
// Ground
|
|
||||||
b3BodyDef bd;
|
|
||||||
ground = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &hs;
|
|
||||||
|
|
||||||
ground->CreateShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Motorized body
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = e_dynamicBody;
|
|
||||||
bd.position.Set(0.0f, 8.0f, 0.0f);
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
m_boxHull.SetExtents(2.0f, 0.5f, 0.5f);
|
|
||||||
|
|
||||||
b3HullShape shape;
|
|
||||||
shape.m_hull = &m_boxHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &shape;
|
|
||||||
sd.friction = 0.3f;
|
|
||||||
sd.density = 2.0f;
|
|
||||||
body->CreateShape(sd);
|
|
||||||
|
|
||||||
b3MotorJointDef mjd;
|
|
||||||
mjd.Initialize(ground, body);
|
|
||||||
mjd.maxForce = 1000.0f;
|
|
||||||
mjd.maxTorque = 1000.0f;
|
|
||||||
m_joint = (b3MotorJoint*)m_world.CreateJoint(mjd);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_play = false;
|
|
||||||
m_x = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int key)
|
|
||||||
{
|
|
||||||
if (key == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
m_play = !m_play;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
if (m_play)
|
|
||||||
{
|
|
||||||
m_x += g_testSettings->inv_hertz;
|
|
||||||
|
|
||||||
if (m_x >= 2.0f * B3_PI)
|
|
||||||
{
|
|
||||||
m_x = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Vec3 linearOffset;
|
|
||||||
linearOffset.x = 8.0f * sinf(2.0f * m_x);
|
|
||||||
linearOffset.y = 8.0f + sinf(m_x);
|
|
||||||
linearOffset.z = 0.0f;
|
|
||||||
|
|
||||||
m_joint->SetLinearOffset(linearOffset);
|
|
||||||
|
|
||||||
b3Quat angularOffset;
|
|
||||||
angularOffset.SetAxisAngle(b3Vec3_z, m_x);
|
|
||||||
angularOffset.Normalize();
|
|
||||||
|
|
||||||
m_joint->SetAngularOffset(angularOffset);
|
|
||||||
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(linearOffset, 4.0f, b3Color(0.9f, 0.9f, 0.9f));
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "S - Play/Pause");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new MotorTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BoxHull m_boxHull;
|
|
||||||
b3MotorJoint* m_joint;
|
|
||||||
bool m_play;
|
|
||||||
scalar m_x;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -39,8 +39,8 @@ public:
|
|||||||
bs[1] = m_world.CreateBody(bd);
|
bs[1] = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape s;
|
b3CapsuleShape s;
|
||||||
s.m_vertex1.Set(0.5f, 0.0f, 0.0f);
|
s.m_centers[0].Set(0.5f, 0.0f, 0.0f);
|
||||||
s.m_vertex2.Set(-0.5f, 0.0f, 0.0f);
|
s.m_centers[1].Set(-0.5f, 0.0f, 0.0f);
|
||||||
s.m_radius = 0.05f;
|
s.m_radius = 0.05f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -60,8 +60,8 @@ public:
|
|||||||
bs[2] = m_world.CreateBody(bd);
|
bs[2] = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape s;
|
b3CapsuleShape s;
|
||||||
s.m_vertex1.Set(0.5f, 0.0f, 0.0f);
|
s.m_centers[0].Set(0.5f, 0.0f, 0.0f);
|
||||||
s.m_vertex2.Set(-0.5f, 0.0f, 0.0f);
|
s.m_centers[1].Set(-0.5f, 0.0f, 0.0f);
|
||||||
s.m_radius = 0.05f;
|
s.m_radius = 0.05f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -81,8 +81,8 @@ public:
|
|||||||
bs[3] = m_world.CreateBody(bd);
|
bs[3] = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape s;
|
b3CapsuleShape s;
|
||||||
s.m_vertex1.Set(0.5f, 0.0f, 0.0f);
|
s.m_centers[0].Set(0.5f, 0.0f, 0.0f);
|
||||||
s.m_vertex2.Set(-0.5f, 0.0f, 0.0f);
|
s.m_centers[1].Set(-0.5f, 0.0f, 0.0f);
|
||||||
s.m_radius = 0.05f;
|
s.m_radius = 0.05f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -102,8 +102,8 @@ public:
|
|||||||
bs[4] = m_world.CreateBody(bd);
|
bs[4] = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape s;
|
b3CapsuleShape s;
|
||||||
s.m_vertex1.Set(0.5f, 0.0f, 0.0f);
|
s.m_centers[0].Set(0.5f, 0.0f, 0.0f);
|
||||||
s.m_vertex2.Set(-0.5f, 0.0f, 0.0f);
|
s.m_centers[1].Set(-0.5f, 0.0f, 0.0f);
|
||||||
s.m_radius = 0.05f;
|
s.m_radius = 0.05f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -123,8 +123,8 @@ public:
|
|||||||
bs[5] = m_world.CreateBody(bd);
|
bs[5] = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape s;
|
b3CapsuleShape s;
|
||||||
s.m_vertex1.Set(0.5f, 0.0f, 0.0f);
|
s.m_centers[0].Set(0.5f, 0.0f, 0.0f);
|
||||||
s.m_vertex2.Set(-0.5f, 0.0f, 0.0f);
|
s.m_centers[1].Set(-0.5f, 0.0f, 0.0f);
|
||||||
s.m_radius = 0.05f;
|
s.m_radius = 0.05f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
|
@ -38,15 +38,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
b3CapsuleShape edge;
|
b3CapsuleShape edge;
|
||||||
edge.m_vertex1.Set(0.0f, -10.0f, 0.0f);
|
edge.m_centers[0].Set(0.0f, -10.0f, 0.0f);
|
||||||
edge.m_vertex2.Set(0.0f, 10.0f, 0.0f);
|
edge.m_centers[1].Set(0.0f, 10.0f, 0.0f);
|
||||||
edge.m_radius = 0.5f;
|
edge.m_radius = 0.5f;
|
||||||
|
|
||||||
b3Body* frame1, *frame2;
|
b3Body* frame1, *frame2;
|
||||||
|
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.orientation = b3QuatRotationZ(0.5f * B3_PI);
|
bd.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
||||||
bd.position.Set(0.0f, 10.0f, -5.0f);
|
bd.position.Set(0.0f, 10.0f, -5.0f);
|
||||||
|
|
||||||
frame1 = m_world.CreateBody(bd);
|
frame1 = m_world.CreateBody(bd);
|
||||||
@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.orientation = b3QuatRotationZ(0.5f * B3_PI);
|
bd.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
||||||
bd.position.Set(0.0f, 10.0f, 5.0f);
|
bd.position.Set(0.0f, 10.0f, 5.0f);
|
||||||
|
|
||||||
frame2 = m_world.CreateBody(bd);
|
frame2 = m_world.CreateBody(bd);
|
||||||
|
@ -1,222 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 NODE_TYPES_H
|
|
||||||
#define NODE_TYPES_H
|
|
||||||
|
|
||||||
class NodeTypes : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 5,
|
|
||||||
e_h = 2,
|
|
||||||
e_d = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
NodeTypes()
|
|
||||||
{
|
|
||||||
// Create soft body
|
|
||||||
b3SoftBodyDef def;
|
|
||||||
def.mesh = &m_mesh;
|
|
||||||
def.density = 0.2f;
|
|
||||||
def.E = 1000.0f;
|
|
||||||
def.nu = 0.33f;
|
|
||||||
def.radius = 0.2f;
|
|
||||||
def.friction = 0.6f;
|
|
||||||
|
|
||||||
m_body = new b3SoftBody(def);
|
|
||||||
|
|
||||||
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
|
||||||
m_body->SetGravity(gravity);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < e_h + 1; ++i)
|
|
||||||
{
|
|
||||||
for (u32 k = 0; k < e_d + 1; ++k)
|
|
||||||
{
|
|
||||||
u32 v = m_mesh.GetVertex(i, 0, k);
|
|
||||||
|
|
||||||
b3SoftBodyNode* n = m_body->GetNode(v);
|
|
||||||
n->SetType(e_staticSoftBodyNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bodyDragger = new b3SoftBodyDragger(&m_ray, m_body);
|
|
||||||
}
|
|
||||||
|
|
||||||
~NodeTypes()
|
|
||||||
{
|
|
||||||
delete m_bodyDragger;
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
m_bodyDragger->Drag();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_body->Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
m_body->Draw();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_bodyDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_bodyDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_softBodySolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_body->GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "S - Static");
|
|
||||||
g_draw->DrawString(b3Color_white, "D - Dynamic");
|
|
||||||
g_draw->DrawString(b3Color_white, "K - Kinematic");
|
|
||||||
g_draw->DrawString(b3Color_white, "Arrows - Apply Force/Velocity/Position");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetBodyType(b3SoftBodyNodeType type)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < e_h + 1; ++i)
|
|
||||||
{
|
|
||||||
for (u32 k = 0; k < e_d + 1; ++k)
|
|
||||||
{
|
|
||||||
u32 v = m_mesh.GetVertex(i, 0, k);
|
|
||||||
|
|
||||||
b3SoftBodyNode* n = m_body->GetNode(v);
|
|
||||||
n->SetType(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int button)
|
|
||||||
{
|
|
||||||
if (button == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
SetBodyType(e_staticSoftBodyNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_K)
|
|
||||||
{
|
|
||||||
SetBodyType(e_kinematicSoftBodyNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_D)
|
|
||||||
{
|
|
||||||
SetBodyType(e_dynamicSoftBodyNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
b3SoftBodyNode* n = m_body->GetNode(i);
|
|
||||||
|
|
||||||
b3Vec3 d;
|
|
||||||
d.SetZero();
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_LEFT)
|
|
||||||
{
|
|
||||||
d.x = -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_RIGHT)
|
|
||||||
{
|
|
||||||
d.x = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_UP)
|
|
||||||
{
|
|
||||||
d.y = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_DOWN)
|
|
||||||
{
|
|
||||||
d.y = -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_LEFT ||
|
|
||||||
button == GLFW_KEY_RIGHT ||
|
|
||||||
button == GLFW_KEY_UP ||
|
|
||||||
button == GLFW_KEY_DOWN)
|
|
||||||
{
|
|
||||||
if (n->GetType() == e_staticSoftBodyNode)
|
|
||||||
{
|
|
||||||
n->ApplyTranslation(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n->GetType() == e_kinematicSoftBodyNode)
|
|
||||||
{
|
|
||||||
b3Vec3 v = n->GetVelocity();
|
|
||||||
|
|
||||||
v += 5.0f * d;
|
|
||||||
|
|
||||||
n->SetVelocity(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n->GetType() == e_dynamicSoftBodyNode)
|
|
||||||
{
|
|
||||||
b3Vec3 f = 100.0f * d;
|
|
||||||
|
|
||||||
n->ApplyForce(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new NodeTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BlockSoftBodyMesh<e_w, e_h, e_d> m_mesh;
|
|
||||||
b3SoftBody* m_body;
|
|
||||||
b3SoftBodyDragger* m_bodyDragger;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -36,21 +36,10 @@ public:
|
|||||||
g_draw->DrawString(b3Color_white, "Arrows - Apply Force/Velocity/Position");
|
g_draw->DrawString(b3Color_white, "Arrows - Apply Force/Velocity/Position");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetClothType(b3ClothParticleType type)
|
void SetClothType(b3ParticleType type)
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
for (b3Particle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext())
|
||||||
{
|
{
|
||||||
u32 v = m_clothMesh.GetVertex(0, j);
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(v);
|
|
||||||
p->SetType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
|
||||||
{
|
|
||||||
u32 v = m_clothMesh.GetVertex(e_h, j);
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(v);
|
|
||||||
p->SetType(type);
|
p->SetType(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,20 +48,20 @@ public:
|
|||||||
{
|
{
|
||||||
if (button == GLFW_KEY_S)
|
if (button == GLFW_KEY_S)
|
||||||
{
|
{
|
||||||
SetClothType(e_staticClothParticle);
|
SetClothType(e_staticParticle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button == GLFW_KEY_K)
|
if (button == GLFW_KEY_K)
|
||||||
{
|
{
|
||||||
SetClothType(e_kinematicClothParticle);
|
SetClothType(e_kinematicParticle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button == GLFW_KEY_D)
|
if (button == GLFW_KEY_D)
|
||||||
{
|
{
|
||||||
SetClothType(e_dynamicClothParticle);
|
SetClothType(e_dynamicParticle);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (b3ClothParticle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext())
|
for (b3Particle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext())
|
||||||
{
|
{
|
||||||
b3Vec3 d;
|
b3Vec3 d;
|
||||||
d.SetZero();
|
d.SetZero();
|
||||||
@ -102,12 +91,12 @@ public:
|
|||||||
button == GLFW_KEY_UP ||
|
button == GLFW_KEY_UP ||
|
||||||
button == GLFW_KEY_DOWN)
|
button == GLFW_KEY_DOWN)
|
||||||
{
|
{
|
||||||
if (p->GetType() == e_staticClothParticle)
|
if (p->GetType() == e_staticParticle)
|
||||||
{
|
{
|
||||||
p->ApplyTranslation(d);
|
p->ApplyTranslation(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->GetType() == e_kinematicClothParticle)
|
if (p->GetType() == e_kinematicParticle)
|
||||||
{
|
{
|
||||||
b3Vec3 v = p->GetVelocity();
|
b3Vec3 v = p->GetVelocity();
|
||||||
|
|
||||||
@ -116,7 +105,7 @@ public:
|
|||||||
p->SetVelocity(v);
|
p->SetVelocity(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->GetType() == e_dynamicClothParticle)
|
if (p->GetType() == e_dynamicParticle)
|
||||||
{
|
{
|
||||||
b3Vec3 f = 100.0f * d;
|
b3Vec3 f = 100.0f * d;
|
||||||
|
|
||||||
|
@ -22,12 +22,6 @@
|
|||||||
class PinnedCloth : public Test
|
class PinnedCloth : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 10,
|
|
||||||
e_h = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
PinnedCloth()
|
PinnedCloth()
|
||||||
{
|
{
|
||||||
// Create cloth
|
// Create cloth
|
||||||
@ -39,24 +33,30 @@ public:
|
|||||||
m_cloth = new b3Cloth(def);
|
m_cloth = new b3Cloth(def);
|
||||||
|
|
||||||
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
||||||
|
m_cloth->SetWorld(&m_world);
|
||||||
|
|
||||||
// Freeze some particles
|
// Freeze some particles
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
b3AABB3 aabb1;
|
||||||
|
aabb1.m_lower.Set(-5.0f, -1.0f, -6.0f);
|
||||||
|
aabb1.m_upper.Set(5.0f, 1.0f, -4.0f);
|
||||||
|
|
||||||
|
b3AABB3 aabb2;
|
||||||
|
aabb2.m_lower.Set(-5.0f, -1.0f, 4.0f);
|
||||||
|
aabb2.m_upper.Set(5.0f, 1.0f, 6.0f);
|
||||||
|
|
||||||
|
for (b3Particle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext())
|
||||||
{
|
{
|
||||||
u32 v = m_clothMesh.GetVertex(0, j);
|
if (aabb1.Contains(p->GetPosition()))
|
||||||
|
{
|
||||||
|
p->SetType(e_staticParticle);
|
||||||
|
}
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(v);
|
if (aabb2.Contains(p->GetPosition()))
|
||||||
p->SetType(e_staticClothParticle);
|
{
|
||||||
|
p->SetType(e_staticParticle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
|
||||||
{
|
|
||||||
u32 v = m_clothMesh.GetVertex(e_h, j);
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(v);
|
|
||||||
p->SetType(e_staticClothParticle);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,9 +79,9 @@ public:
|
|||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
b3Vec3 pA = m_clothDragger->GetPointA();
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
b3Vec3 pB = m_clothDragger->GetPointB();
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pA, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pB, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
g_draw->DrawSegment(pA, pB, b3Color_white);
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ public:
|
|||||||
extern u32 b3_clothSolverIterations;
|
extern u32 b3_clothSolverIterations;
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
||||||
|
|
||||||
scalar E = m_cloth->GetEnergy();
|
float32 E = m_cloth->GetEnergy();
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
g_draw->DrawString(b3Color_white, "E = %f", E);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ public:
|
|||||||
return new PinnedCloth();
|
return new PinnedCloth();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3GridClothMesh<e_w, e_h> m_clothMesh;
|
b3GridClothMesh<10, 10> m_clothMesh;
|
||||||
b3Cloth* m_cloth;
|
b3Cloth* m_cloth;
|
||||||
b3ClothDragger* m_clothDragger;
|
b3ClothDragger* m_clothDragger;
|
||||||
};
|
};
|
||||||
|
@ -19,12 +19,14 @@
|
|||||||
#ifndef PINNED_SOFTBODY_H
|
#ifndef PINNED_SOFTBODY_H
|
||||||
#define PINNED_SOFTBODY_H
|
#define PINNED_SOFTBODY_H
|
||||||
|
|
||||||
|
#include <testbed/framework/softbody_dragger.h>
|
||||||
|
|
||||||
class PinnedSoftBody : public Test
|
class PinnedSoftBody : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PinnedSoftBody()
|
PinnedSoftBody()
|
||||||
{
|
{
|
||||||
m_mesh.SetAsSphere(4.0f, 0);
|
m_mesh.SetAsSphere(5.0f, 0);
|
||||||
|
|
||||||
// Create soft body
|
// Create soft body
|
||||||
b3SoftBodyDef def;
|
b3SoftBodyDef def;
|
||||||
@ -35,15 +37,20 @@ public:
|
|||||||
def.c_yield = 0.1f;
|
def.c_yield = 0.1f;
|
||||||
def.c_creep = 0.5f;
|
def.c_creep = 0.5f;
|
||||||
def.c_max = 1.0f;
|
def.c_max = 1.0f;
|
||||||
def.massDamping = 0.2f;
|
|
||||||
|
|
||||||
m_body = new b3SoftBody(def);
|
m_body = new b3SoftBody(def);
|
||||||
|
|
||||||
u32 pinIndex = ~0;
|
|
||||||
scalar pinDot = -B3_MAX_SCALAR;
|
|
||||||
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
||||||
{
|
{
|
||||||
scalar dot = b3Dot(m_mesh.vertices[i], b3Vec3_y);
|
b3SoftBodyNode* n = m_body->GetVertexNode(i);
|
||||||
|
n->SetMassDamping(0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 pinIndex = ~0;
|
||||||
|
float32 pinDot = -B3_MAX_FLOAT;
|
||||||
|
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
||||||
|
{
|
||||||
|
float32 dot = b3Dot(m_mesh.vertices[i], b3Vec3_y);
|
||||||
if (dot > pinDot)
|
if (dot > pinDot)
|
||||||
{
|
{
|
||||||
pinDot = dot;
|
pinDot = dot;
|
||||||
@ -51,7 +58,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b3SoftBodyNode* pinNode = m_body->GetNode(pinIndex);
|
b3SoftBodyNode* pinNode = m_body->GetVertexNode(pinIndex);
|
||||||
pinNode->SetType(e_staticSoftBodyNode);
|
pinNode->SetType(e_staticSoftBodyNode);
|
||||||
|
|
||||||
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
||||||
@ -84,9 +91,9 @@ public:
|
|||||||
b3Vec3 pA = m_bodyDragger->GetPointA();
|
b3Vec3 pA = m_bodyDragger->GetPointA();
|
||||||
b3Vec3 pB = m_bodyDragger->GetPointB();
|
b3Vec3 pB = m_bodyDragger->GetPointB();
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pA, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pB, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
g_draw->DrawSegment(pA, pB, b3Color_white);
|
||||||
}
|
}
|
||||||
@ -94,7 +101,7 @@ public:
|
|||||||
extern u32 b3_softBodySolverIterations;
|
extern u32 b3_softBodySolverIterations;
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
||||||
|
|
||||||
scalar E = m_body->GetEnergy();
|
float32 E = m_body->GetEnergy();
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
g_draw->DrawString(b3Color_white, "E = %f", E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 PRISMATIC_TEST_H
|
|
||||||
#define PRISMATIC_TEST_H
|
|
||||||
|
|
||||||
class PrismaticTest : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PrismaticTest()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
b3Body* ground = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape shape;
|
|
||||||
shape.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &shape;
|
|
||||||
|
|
||||||
ground->CreateShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* bA, * bB;
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = e_dynamicBody;
|
|
||||||
bd.position.Set(-5.0f, 5.0f, 0.0f);
|
|
||||||
|
|
||||||
bA = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
m_hullA.SetExtents(2.0f, 2.0f, 0.5f);
|
|
||||||
|
|
||||||
b3HullShape hull;
|
|
||||||
hull.m_hull = &m_hullA;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hull;
|
|
||||||
sdef.density = 1.0f;
|
|
||||||
|
|
||||||
bA->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = e_dynamicBody;
|
|
||||||
bd.position.Set(5.0f, 5.0f, 0.0f);
|
|
||||||
|
|
||||||
bB = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
m_hullB.SetExtents(2.0f, 2.0f, 0.5f);
|
|
||||||
|
|
||||||
b3HullShape hull;
|
|
||||||
hull.m_hull = &m_hullB;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hull;
|
|
||||||
sdef.density = 1.0f;
|
|
||||||
|
|
||||||
bB->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create prismatic joint
|
|
||||||
{
|
|
||||||
b3Vec3 anchor(0.0f, 5.0f, 0.0f);
|
|
||||||
b3Vec3 axis(1.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
b3PrismaticJointDef jd;
|
|
||||||
jd.Initialize(bA, bB, anchor, axis);
|
|
||||||
jd.motorSpeed = 10.0f;
|
|
||||||
jd.maxMotorForce = 10000.0f;
|
|
||||||
jd.enableMotor = true;
|
|
||||||
jd.lowerTranslation = 0.0f;
|
|
||||||
jd.upperTranslation = 10.0f;
|
|
||||||
jd.enableLimit = true;
|
|
||||||
|
|
||||||
m_joint = (b3PrismaticJoint*)m_world.CreateJoint(jd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "L - Enable Limit");
|
|
||||||
g_draw->DrawString(b3Color_white, "M - Enable Motor");
|
|
||||||
g_draw->DrawString(b3Color_white, "S - Flip Motor Speed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int button)
|
|
||||||
{
|
|
||||||
if (button == GLFW_KEY_L)
|
|
||||||
{
|
|
||||||
m_joint->EnableLimit(!m_joint->IsLimitEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_M)
|
|
||||||
{
|
|
||||||
m_joint->EnableMotor(!m_joint->IsMotorEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
m_joint->SetMotorSpeed(-m_joint->GetMotorSpeed());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new PrismaticTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BoxHull m_hullA;
|
|
||||||
b3BoxHull m_hullB;
|
|
||||||
b3PrismaticJoint* m_joint;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -47,9 +47,9 @@ public:
|
|||||||
|
|
||||||
// shift to ground center
|
// shift to ground center
|
||||||
b3Vec3 translation;
|
b3Vec3 translation;
|
||||||
translation.x = -0.5f * scalar(e_count) * boxSize.x;
|
translation.x = -0.5f * float32(e_count) * boxSize.x;
|
||||||
translation.y = 1.5f * boxSize.y;
|
translation.y = 1.5f * boxSize.y;
|
||||||
translation.z = -0.5f * scalar(e_count) * boxSize.z;
|
translation.z = -0.5f * float32(e_count) * boxSize.z;
|
||||||
|
|
||||||
u32 count = e_count;
|
u32 count = e_count;
|
||||||
for (u32 i = 0; i < e_count; ++i)
|
for (u32 i = 0; i < e_count; ++i)
|
||||||
@ -61,9 +61,9 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
bd.position.x = 1.05f * scalar(j) * boxSize.x;
|
bd.position.x = 1.05f * float32(j) * boxSize.x;
|
||||||
bd.position.y = 0.0f;
|
bd.position.y = 0.0f;
|
||||||
bd.position.z = 1.05f * scalar(k) * boxSize.z;
|
bd.position.z = 1.05f * float32(k) * boxSize.z;
|
||||||
bd.position += translation;
|
bd.position += translation;
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
b3Body* body = m_world.CreateBody(bd);
|
||||||
|
@ -48,15 +48,15 @@ public:
|
|||||||
|
|
||||||
// shift to ground center
|
// shift to ground center
|
||||||
b3Vec3 translation;
|
b3Vec3 translation;
|
||||||
translation.x = -0.5f * scalar(e_count - 1) * 4.0f * boxSize.x;
|
translation.x = -0.5f * float32(e_count - 1) * 4.0f * boxSize.x;
|
||||||
translation.y = 1.5f * boxSize.y;
|
translation.y = 1.5f * boxSize.y;
|
||||||
translation.z = -0.5f * scalar(e_depthCount) * boxSize.z;
|
translation.z = -0.5f * float32(e_depthCount) * boxSize.z;
|
||||||
|
|
||||||
for (u32 i = 0; i < e_count; ++i)
|
for (u32 i = 0; i < e_count; ++i)
|
||||||
{
|
{
|
||||||
// reset
|
// reset
|
||||||
translation.y = 1.5f * boxSize.y;
|
translation.y = 1.5f * boxSize.y;
|
||||||
translation.z = -0.5f * scalar(e_depthCount) * boxSize.z;
|
translation.z = -0.5f * float32(e_depthCount) * boxSize.z;
|
||||||
|
|
||||||
for (u32 j = 0; j < e_depthCount; ++j)
|
for (u32 j = 0; j < e_depthCount; ++j)
|
||||||
{
|
{
|
||||||
@ -66,7 +66,7 @@ public:
|
|||||||
bd.type = e_dynamicBody;
|
bd.type = e_dynamicBody;
|
||||||
bd.position.x = 0.0f;
|
bd.position.x = 0.0f;
|
||||||
bd.position.y = 0.0f;
|
bd.position.y = 0.0f;
|
||||||
bd.position.z = 1.05f * scalar(k) * boxSize.z;
|
bd.position.z = 1.05f * float32(k) * boxSize.z;
|
||||||
bd.position += translation;
|
bd.position += translation;
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
b3Body* body = m_world.CreateBody(bd);
|
||||||
|
@ -64,8 +64,8 @@ public:
|
|||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3CapsuleShape capsule;
|
b3CapsuleShape capsule;
|
||||||
capsule.m_vertex1.Set(0.0f, 0.0f, -1.0f);
|
capsule.m_centers[0].Set(0.0f, 0.0f, -1.0f);
|
||||||
capsule.m_vertex2.Set(0.0f, 0.0f, 1.0f);
|
capsule.m_centers[1].Set(0.0f, 0.0f, 1.0f);
|
||||||
capsule.m_radius = 1.0f;
|
capsule.m_radius = 1.0f;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
@ -83,7 +83,7 @@ public:
|
|||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
m_coneHull.SetExtents(1.0f, 1.0f);
|
m_coneHull.SetAsCone();
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &m_coneHull;
|
hull.m_hull = &m_coneHull;
|
||||||
@ -103,7 +103,7 @@ public:
|
|||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
m_cylinderHull.SetExtents(1.0f, 1.0f);
|
m_cylinderHull.SetAsCylinder();
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &m_cylinderHull;
|
hull.m_hull = &m_cylinderHull;
|
||||||
@ -126,8 +126,8 @@ public:
|
|||||||
return new QuadricShapes();
|
return new QuadricShapes();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3ConeHull m_coneHull;
|
b3QHull m_coneHull;
|
||||||
b3CylinderHull m_cylinderHull;
|
b3QHull m_cylinderHull;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -52,8 +52,8 @@ public:
|
|||||||
hip->ApplyForceToCenter(b3Vec3(0.0f, 0.0f, -5000.0f), true);
|
hip->ApplyForceToCenter(b3Vec3(0.0f, 0.0f, -5000.0f), true);
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
b3CapsuleShape cs;
|
||||||
cs.m_vertex1.Set(0.0f, 0.5f, 0.0f);
|
cs.m_centers[0].Set(0.0f, 0.5f, 0.0f);
|
||||||
cs.m_vertex2.Set(0.0f, -0.5f, 0.0f);
|
cs.m_centers[1].Set(0.0f, -0.5f, 0.0f);
|
||||||
cs.m_radius = 1.0f;
|
cs.m_radius = 1.0f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -70,8 +70,8 @@ public:
|
|||||||
head = m_world.CreateBody(bd);
|
head = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
b3CapsuleShape cs;
|
||||||
cs.m_vertex1.Set(0.0f, 0.15f, 0.0f);
|
cs.m_centers[0].Set(0.0f, 0.15f, 0.0f);
|
||||||
cs.m_vertex2.Set(0.0f, -0.15f, 0.0f);
|
cs.m_centers[1].Set(0.0f, -0.15f, 0.0f);
|
||||||
cs.m_radius = 0.5f;
|
cs.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -86,7 +86,7 @@ public:
|
|||||||
cd.bodyA = hip;
|
cd.bodyA = hip;
|
||||||
cd.bodyB = head;
|
cd.bodyB = head;
|
||||||
cd.collideLinked = false;
|
cd.collideLinked = false;
|
||||||
cd.enableConeLimit = true;
|
cd.enableLimit = true;
|
||||||
cd.Initialize(hip, head, b3Vec3(0.0f, 1.0f, 0.0f), b3Vec3(0.0f, 11.55f, 0.0f), 0.25f * B3_PI);
|
cd.Initialize(hip, head, b3Vec3(0.0f, 1.0f, 0.0f), b3Vec3(0.0f, 11.55f, 0.0f), 0.25f * B3_PI);
|
||||||
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
||||||
}
|
}
|
||||||
@ -95,12 +95,12 @@ public:
|
|||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = e_dynamicBody;
|
bd.type = e_dynamicBody;
|
||||||
bd.position.Set(-2.5f, 11.0f, 0.0f);
|
bd.position.Set(-2.5f, 11.0f, 0.0f);
|
||||||
bd.orientation = b3QuatRotationZ(0.5f * B3_PI);
|
bd.orientation.Set(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
||||||
lArm = m_world.CreateBody(bd);
|
lArm = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
b3CapsuleShape cs;
|
||||||
cs.m_vertex1.Set(0.0f, 1.0f, 0.0f);
|
cs.m_centers[0].Set(0.0f, 1.0f, 0.0f);
|
||||||
cs.m_vertex2.Set(0.0f, -1.0f, 0.0f);
|
cs.m_centers[1].Set(0.0f, -1.0f, 0.0f);
|
||||||
cs.m_radius = 0.5f;
|
cs.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -116,7 +116,7 @@ public:
|
|||||||
cd.bodyA = hip;
|
cd.bodyA = hip;
|
||||||
cd.bodyB = lArm;
|
cd.bodyB = lArm;
|
||||||
cd.collideLinked = false;
|
cd.collideLinked = false;
|
||||||
cd.enableConeLimit = true;
|
cd.enableLimit = true;
|
||||||
cd.Initialize(hip, lArm, b3Vec3(-1.0f, 0.0f, 0.0f), b3Vec3(-1.0f, 11.0f, 0.0f), B3_PI);
|
cd.Initialize(hip, lArm, b3Vec3(-1.0f, 0.0f, 0.0f), b3Vec3(-1.0f, 11.0f, 0.0f), B3_PI);
|
||||||
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
||||||
}
|
}
|
||||||
@ -125,12 +125,12 @@ public:
|
|||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = e_dynamicBody;
|
bd.type = e_dynamicBody;
|
||||||
bd.position.Set(2.5f, 11.0f, 0.0f);
|
bd.position.Set(2.5f, 11.0f, 0.0f);
|
||||||
bd.orientation.SetAxisAngle(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
bd.orientation.Set(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
||||||
rArm = m_world.CreateBody(bd);
|
rArm = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
b3CapsuleShape cs;
|
||||||
cs.m_vertex1.Set(0.0f, 1.0f, 0.0f);
|
cs.m_centers[0].Set(0.0f, 1.0f, 0.0f);
|
||||||
cs.m_vertex2.Set(0.0f, -1.0f, 0.0f);
|
cs.m_centers[1].Set(0.0f, -1.0f, 0.0f);
|
||||||
cs.m_radius = 0.5f;
|
cs.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -146,7 +146,7 @@ public:
|
|||||||
cd.bodyA = hip;
|
cd.bodyA = hip;
|
||||||
cd.bodyB = rArm;
|
cd.bodyB = rArm;
|
||||||
cd.collideLinked = false;
|
cd.collideLinked = false;
|
||||||
cd.enableConeLimit = true;
|
cd.enableLimit = true;
|
||||||
cd.Initialize(hip, rArm, b3Vec3(1.0f, 0.0f, 0.0f), b3Vec3(1.0f, 11.0f, 0.0f), B3_PI);
|
cd.Initialize(hip, rArm, b3Vec3(1.0f, 0.0f, 0.0f), b3Vec3(1.0f, 11.0f, 0.0f), B3_PI);
|
||||||
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
||||||
}
|
}
|
||||||
@ -158,8 +158,8 @@ public:
|
|||||||
lLeg = m_world.CreateBody(bd);
|
lLeg = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
b3CapsuleShape cs;
|
||||||
cs.m_vertex1.Set(0.0f, 2.0f, 0.0f);
|
cs.m_centers[0].Set(0.0f, 2.0f, 0.0f);
|
||||||
cs.m_vertex2.Set(0.0f, -2.0f, 0.0f);
|
cs.m_centers[1].Set(0.0f, -2.0f, 0.0f);
|
||||||
cs.m_radius = 0.45f;
|
cs.m_radius = 0.45f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -175,7 +175,7 @@ public:
|
|||||||
cd.bodyA = hip;
|
cd.bodyA = hip;
|
||||||
cd.bodyB = lLeg;
|
cd.bodyB = lLeg;
|
||||||
cd.collideLinked = false;
|
cd.collideLinked = false;
|
||||||
cd.enableConeLimit = true;
|
cd.enableLimit = true;
|
||||||
cd.Initialize(hip, lLeg, b3Vec3(0.0f, -1.0f, 0.0f), b3Vec3(-0.5f, 8.5f, 0.0f), 0.25f * B3_PI);
|
cd.Initialize(hip, lLeg, b3Vec3(0.0f, -1.0f, 0.0f), b3Vec3(-0.5f, 8.5f, 0.0f), 0.25f * B3_PI);
|
||||||
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
||||||
}
|
}
|
||||||
@ -187,8 +187,8 @@ public:
|
|||||||
rLeg = m_world.CreateBody(bd);
|
rLeg = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
b3CapsuleShape cs;
|
||||||
cs.m_vertex1.Set(0.0f, 2.0f, 0.0f);
|
cs.m_centers[0].Set(0.0f, 2.0f, 0.0f);
|
||||||
cs.m_vertex2.Set(0.0f, -2.0f, 0.0f);
|
cs.m_centers[1].Set(0.0f, -2.0f, 0.0f);
|
||||||
cs.m_radius = 0.45f;
|
cs.m_radius = 0.45f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -204,7 +204,7 @@ public:
|
|||||||
cd.bodyA = hip;
|
cd.bodyA = hip;
|
||||||
cd.bodyB = rLeg;
|
cd.bodyB = rLeg;
|
||||||
cd.collideLinked = false;
|
cd.collideLinked = false;
|
||||||
cd.enableConeLimit = true;
|
cd.enableLimit = true;
|
||||||
cd.Initialize(hip, rLeg, b3Vec3(0.0f, -1.0f, 0.0f), b3Vec3(0.5f, 8.5f, 0.0f), 0.25f * B3_PI);
|
cd.Initialize(hip, rLeg, b3Vec3(0.0f, -1.0f, 0.0f), b3Vec3(0.5f, 8.5f, 0.0f), 0.25f * B3_PI);
|
||||||
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
b3ConeJoint* cj = (b3ConeJoint*)m_world.CreateJoint(cd);
|
||||||
}
|
}
|
||||||
|
@ -159,8 +159,8 @@ public:
|
|||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3CapsuleShape hs;
|
b3CapsuleShape hs;
|
||||||
hs.m_vertex1.Set(0.0f, 1.0f, 0.0f);
|
hs.m_centers[0].Set(0.0f, 1.0f, 0.0f);
|
||||||
hs.m_vertex2.Set(0.0f, -1.0f, 0.0f);
|
hs.m_centers[1].Set(0.0f, -1.0f, 0.0f);
|
||||||
hs.m_radius = 3.0f;
|
hs.m_radius = 3.0f;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
@ -175,22 +175,11 @@ public:
|
|||||||
m_p12.Set(0.0f, 2.0f, 0.0f);
|
m_p12.Set(0.0f, 2.0f, 0.0f);
|
||||||
m_p22.Set(-50.0f, 2.0f, 0.0f);
|
m_p22.Set(-50.0f, 2.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastRay(const b3Vec3 p1, const b3Vec3 p2) const
|
void CastRay(const b3Vec3 p1, const b3Vec3 p2) const
|
||||||
{
|
{
|
||||||
class RayCastFilter : public b3RayCastFilter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool ShouldRayCast(b3Shape* shape)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RayCastFilter filter;
|
|
||||||
|
|
||||||
b3RayCastSingleOutput out;
|
b3RayCastSingleOutput out;
|
||||||
if (m_world.RayCastSingle(&out, &filter, p1, p2))
|
if (m_world.RayCastSingle(&out, p1, p2))
|
||||||
{
|
{
|
||||||
g_draw->DrawSegment(p1, out.point, b3Color_green);
|
g_draw->DrawSegment(p1, out.point, b3Color_green);
|
||||||
|
|
||||||
@ -205,7 +194,7 @@ public:
|
|||||||
|
|
||||||
void Step()
|
void Step()
|
||||||
{
|
{
|
||||||
scalar dt = g_testSettings->inv_hertz;
|
float32 dt = g_testSettings->inv_hertz;
|
||||||
b3Quat dq = b3QuatRotationY(0.05f * B3_PI * dt);
|
b3Quat dq = b3QuatRotationY(0.05f * B3_PI * dt);
|
||||||
|
|
||||||
m_p1 = b3Mul(dq, m_p1);
|
m_p1 = b3Mul(dq, m_p1);
|
||||||
|
@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 REVOLUTE_TEST_H
|
|
||||||
#define REVOLUTE_TEST_H
|
|
||||||
|
|
||||||
class RevoluteTest : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RevoluteTest()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
b3Body* ground = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape shape;
|
|
||||||
shape.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &shape;
|
|
||||||
|
|
||||||
ground->CreateShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* hinge, *door;
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = b3BodyType::e_staticBody;
|
|
||||||
bd.position.Set(0.0f, 7.0f, 0.0f);
|
|
||||||
hinge = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3CapsuleShape shape;
|
|
||||||
shape.m_vertex1.Set(0.0f, 0.0f, -4.0f);
|
|
||||||
shape.m_vertex2.Set(0.0f, 0.0f, 4.0f);
|
|
||||||
shape.m_radius = 0.5f;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &shape;
|
|
||||||
sd.density = 1.0f;
|
|
||||||
|
|
||||||
hinge->CreateShape(sd);
|
|
||||||
|
|
||||||
m_body = hinge;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
|
||||||
bd.position.Set(2.0f, 7.0f, 0.0f);
|
|
||||||
|
|
||||||
door = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
m_doorBox.SetExtents(1.0f, 0.5f, 4.0f);
|
|
||||||
|
|
||||||
b3HullShape hull;
|
|
||||||
hull.m_hull = &m_doorBox;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &hull;
|
|
||||||
sdef.density = 1.0f;
|
|
||||||
|
|
||||||
door->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
b3Vec3 axis(0.0f, 0.0f, 1.0f);
|
|
||||||
b3Vec3 anchor(0.0f, 7.0f, 0.0f);
|
|
||||||
|
|
||||||
b3RevoluteJointDef jd;
|
|
||||||
jd.Initialize(hinge, door, axis, anchor, -0.25f * B3_PI, 0.5f * B3_PI);
|
|
||||||
jd.maxMotorTorque = 1000.0f;
|
|
||||||
jd.enableMotor = false;
|
|
||||||
jd.enableLimit = true;
|
|
||||||
jd.motorSpeed = B3_PI;
|
|
||||||
|
|
||||||
m_rj = (b3RevoluteJoint*)m_world.CreateJoint(jd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalidate the orientation
|
|
||||||
b3Quat q = b3QuatRotationX(B3_PI);
|
|
||||||
door->SetTransform(door->GetPosition(), q);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "M - Motor");
|
|
||||||
g_draw->DrawString(b3Color_white, "L - Limits");
|
|
||||||
g_draw->DrawString(b3Color_white, "S/K/D - Static/kinematic/dynamic body");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int button)
|
|
||||||
{
|
|
||||||
if (button == GLFW_KEY_M)
|
|
||||||
{
|
|
||||||
m_rj->SetEnableMotor(!m_rj->IsMotorEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_L)
|
|
||||||
{
|
|
||||||
m_rj->SetEnableLimit(!m_rj->IsLimitEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_D)
|
|
||||||
{
|
|
||||||
m_body->SetType(e_dynamicBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
m_body->SetType(e_staticBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_K)
|
|
||||||
{
|
|
||||||
m_body->SetType(e_kinematicBody);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new RevoluteTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BoxHull m_doorBox;
|
|
||||||
b3Body* m_body;
|
|
||||||
b3RevoluteJoint* m_rj;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -30,7 +30,7 @@ public:
|
|||||||
Rope()
|
Rope()
|
||||||
{
|
{
|
||||||
b3Vec3 vs[e_count];
|
b3Vec3 vs[e_count];
|
||||||
scalar ms[e_count];
|
float32 ms[e_count];
|
||||||
|
|
||||||
vs[0].Set(0.0f, 0.0f, 0.0f);
|
vs[0].Set(0.0f, 0.0f, 0.0f);
|
||||||
ms[0] = 0.0f;
|
ms[0] = 0.0f;
|
||||||
@ -38,7 +38,7 @@ public:
|
|||||||
for (u32 i = 1; i < e_count; ++i)
|
for (u32 i = 1; i < e_count; ++i)
|
||||||
{
|
{
|
||||||
ms[i] = 1.0f;
|
ms[i] = 1.0f;
|
||||||
vs[i].Set(scalar(i), 0.0f, 0.0f);
|
vs[i].Set(float32(i), 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
b3RopeDef rd;
|
b3RopeDef rd;
|
||||||
|
@ -63,8 +63,8 @@ public:
|
|||||||
m_character = m_world.CreateBody(bd);
|
m_character = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape cap;
|
b3CapsuleShape cap;
|
||||||
cap.m_vertex1.Set(0.0f, 2.0f, 0.0f);
|
cap.m_centers[0].Set(0.0f, 2.0f, 0.0f);
|
||||||
cap.m_vertex2.Set(0.0f, -2.0f, 0.0f);
|
cap.m_centers[1].Set(0.0f, -2.0f, 0.0f);
|
||||||
cap.m_radius = 0.5f;
|
cap.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -129,7 +129,7 @@ public:
|
|||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
bd.position.Set(RandomFloat(-20.0f, 20.0f), RandomFloat(10.0f, 20.0f), RandomFloat(-20.0f, 20.0f));
|
bd.position.Set(RandomFloat(-20.0f, 20.0f), RandomFloat(10.0f, 20.0f), RandomFloat(-20.0f, 20.0f));
|
||||||
|
|
||||||
b3Vec3 n = m_character->GetTransform().translation - bd.position;
|
b3Vec3 n = m_character->GetTransform().position - bd.position;
|
||||||
n.Normalize();
|
n.Normalize();
|
||||||
|
|
||||||
bd.linearVelocity = 60.0f * n;
|
bd.linearVelocity = 60.0f * n;
|
||||||
|
@ -26,6 +26,7 @@ public:
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
|
bd.orientation.Set(b3Vec3(0.0f, 1.0f, 0.0f), 0.18f * B3_PI);
|
||||||
b3Body* ground = m_world.CreateBody(bd);
|
b3Body* ground = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3MeshShape ms;
|
b3MeshShape ms;
|
||||||
@ -38,7 +39,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (scalar y = 2.5f; y < 20.0f; y += 2.5f)
|
for (float32 y = 2.5f; y < 20.0f; y += 2.5f)
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
@ -58,18 +59,18 @@ public:
|
|||||||
body->CreateShape(sdef);
|
body->CreateShape(sdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (scalar y = 2.5f; y < 20.0f; y += 2.5f)
|
for (float32 y = 2.5f; y < 20.0f; y += 2.5f)
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
bd.position.Set(0.0f, y, 0.0f);
|
bd.position.Set(0.0f, y, 0.0f);
|
||||||
bd.orientation = b3QuatRotationZ(0.5f * B3_PI);
|
bd.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bd);
|
b3Body* body = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape capsule;
|
b3CapsuleShape capsule;
|
||||||
capsule.m_vertex1.Set(0.0f, -1.0f, 0.0f);
|
capsule.m_centers[0].Set(0.0f, -1.0f, 0.0f);
|
||||||
capsule.m_vertex2.Set(0.0f, 1.0f, 0.0f);
|
capsule.m_centers[1].Set(0.0f, 1.0f, 0.0f);
|
||||||
capsule.m_radius = 1.0f;
|
capsule.m_radius = 1.0f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -80,7 +81,7 @@ public:
|
|||||||
body->CreateShape(sd);
|
body->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (scalar y = 2.5f; y < 20.0f; y += 2.5f)
|
for (float32 y = 2.5f; y < 20.0f; y += 2.5f)
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
bd.type = b3BodyType::e_dynamicBody;
|
bd.type = b3BodyType::e_dynamicBody;
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 SHEET_H
|
|
||||||
#define SHEET_H
|
|
||||||
|
|
||||||
class Sheet : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 10,
|
|
||||||
e_h = 1,
|
|
||||||
e_d = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
Sheet()
|
|
||||||
{
|
|
||||||
// Downscale the block along the y axis
|
|
||||||
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
m_mesh.vertices[i].y *= 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create soft body
|
|
||||||
b3SoftBodyDef def;
|
|
||||||
def.mesh = &m_mesh;
|
|
||||||
def.density = 0.3f;
|
|
||||||
def.E = 200.0f;
|
|
||||||
def.nu = 0.3f;
|
|
||||||
|
|
||||||
m_body = new b3SoftBody(def);
|
|
||||||
|
|
||||||
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
|
||||||
m_body->SetGravity(gravity);
|
|
||||||
|
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
|
||||||
{
|
|
||||||
u32 v = m_mesh.GetVertex(0, j, 0);
|
|
||||||
|
|
||||||
b3SoftBodyNode* n = m_body->GetNode(v);
|
|
||||||
n->SetType(e_staticSoftBodyNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bodyDragger = new b3SoftBodyDragger(&m_ray, m_body);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Sheet()
|
|
||||||
{
|
|
||||||
delete m_bodyDragger;
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
m_bodyDragger->Drag();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_body->Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
m_body->Draw();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_bodyDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_bodyDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_softBodySolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_body->GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseMove(pw);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new Sheet();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BlockSoftBodyMesh<e_w, e_h, e_d> m_mesh;
|
|
||||||
b3SoftBody* m_body;
|
|
||||||
b3SoftBodyDragger* m_bodyDragger;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -24,15 +24,17 @@ class SheetStack : public Test
|
|||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
e_h = 5,
|
e_rowCount = 1,
|
||||||
e_w = 1,
|
e_columnCount = 10,
|
||||||
e_d = 1
|
e_depthCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
SheetStack()
|
SheetStack()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
|
bdef.type = b3BodyType::e_staticBody;
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
@ -42,87 +44,49 @@ public:
|
|||||||
sdef.shape = &hs;
|
sdef.shape = &hs;
|
||||||
sdef.friction = 1.0f;
|
sdef.friction = 1.0f;
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
b3Shape* shape = body->CreateShape(sdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static b3Vec3 sheetExtents(4.05f, 2.0f * B3_LINEAR_SLOP, 4.05f);
|
||||||
|
static b3BoxHull sheetHull(sheetExtents.x, sheetExtents.y, sheetExtents.z);
|
||||||
|
|
||||||
b3Vec3 e(4.0f, 2.0f * B3_LINEAR_SLOP, 4.0f);
|
b3Vec3 stackOrigin;
|
||||||
|
stackOrigin.Set(0.0f, 4.05f, 0.0f);
|
||||||
|
|
||||||
m_boxHull.SetExtents(e.x, e.y, e.z);
|
for (u32 i = 0; i < e_rowCount; ++i)
|
||||||
|
|
||||||
b3Vec3 separation;
|
|
||||||
separation.x = 1.0f;
|
|
||||||
separation.y = 1.0f;
|
|
||||||
separation.z = 1.0f;
|
|
||||||
|
|
||||||
b3Vec3 scale;
|
|
||||||
scale.x = 2.0f * e.x + separation.x;
|
|
||||||
scale.y = 2.0f * e.y + separation.y;
|
|
||||||
scale.z = 2.0f * e.z + separation.z;
|
|
||||||
|
|
||||||
b3Vec3 size;
|
|
||||||
size.x = 2.0f * e.x + scale.x * scalar(e_w - 1);
|
|
||||||
size.y = 2.0f * e.y + scale.y * scalar(e_h - 1);
|
|
||||||
size.z = 2.0f * e.z + scale.z * scalar(e_d - 1);
|
|
||||||
|
|
||||||
b3Vec3 translation;
|
|
||||||
translation.x = e.x - 0.5f * size.x;
|
|
||||||
translation.y = e.y - 0.5f * size.y;
|
|
||||||
translation.z = e.z - 0.5f * size.z;
|
|
||||||
|
|
||||||
translation.y += 9.0f;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < e_h; ++i)
|
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < e_w; ++j)
|
for (u32 j = 0; j < e_columnCount; ++j)
|
||||||
{
|
{
|
||||||
for (u32 k = 0; k < e_d; ++k)
|
for (u32 k = 0; k < e_depthCount; ++k)
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = b3BodyType::e_dynamicBody;
|
||||||
|
|
||||||
bdef.position.Set(scalar(j), scalar(i), scalar(k));
|
bdef.position.x = float32(i) * sheetExtents.x;
|
||||||
|
bdef.position.y = float32(j) * 50.0f * sheetExtents.y;
|
||||||
bdef.position.x *= scale.x;
|
bdef.position.z = float32(k) * sheetExtents.z;
|
||||||
bdef.position.y *= scale.y;
|
bdef.position += stackOrigin;
|
||||||
bdef.position.z *= scale.z;
|
|
||||||
|
|
||||||
bdef.position += translation;
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &m_boxHull;
|
hs.m_hull = &sheetHull;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.3f;
|
|
||||||
sdef.shape = &hs;
|
sdef.shape = &hs;
|
||||||
|
sdef.density = 0.5f;
|
||||||
|
sdef.friction = 0.2f;
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
body->CreateShape(sdef);
|
||||||
|
|
||||||
u32 bodyIndex = GetBodyIndex(i, j, k);
|
|
||||||
|
|
||||||
m_bodies[bodyIndex] = body;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetBodyIndex(u32 i, u32 j, u32 k)
|
|
||||||
{
|
|
||||||
B3_ASSERT(i < e_h);
|
|
||||||
B3_ASSERT(j < e_w);
|
|
||||||
B3_ASSERT(k < e_d);
|
|
||||||
return k + e_d * (j + e_w * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new SheetStack();
|
return new SheetStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_boxHull;
|
|
||||||
b3Body* m_bodies[e_h * e_w * e_d];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -19,6 +19,8 @@
|
|||||||
#ifndef SMASH_SOFTBODY_H
|
#ifndef SMASH_SOFTBODY_H
|
||||||
#define SMASH_SOFTBODY_H
|
#define SMASH_SOFTBODY_H
|
||||||
|
|
||||||
|
#include <testbed/framework/softbody_dragger.h>
|
||||||
|
|
||||||
class SmashSoftBody : public Test
|
class SmashSoftBody : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -40,13 +42,20 @@ public:
|
|||||||
def.c_yield = 0.6f;
|
def.c_yield = 0.6f;
|
||||||
def.c_creep = 1.0f;
|
def.c_creep = 1.0f;
|
||||||
def.c_max = 1.0f;
|
def.c_max = 1.0f;
|
||||||
def.radius = 0.05f;
|
|
||||||
def.friction = 0.2f;
|
|
||||||
|
|
||||||
m_body = new b3SoftBody(def);
|
m_body = new b3SoftBody(def);
|
||||||
|
|
||||||
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
||||||
m_body->SetGravity(gravity);
|
m_body->SetGravity(gravity);
|
||||||
|
m_body->SetWorld(&m_world);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
||||||
|
{
|
||||||
|
b3SoftBodyNode* n = m_body->GetVertexNode(i);
|
||||||
|
|
||||||
|
n->SetRadius(0.05f);
|
||||||
|
n->SetFriction(0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
// Create ground
|
// Create ground
|
||||||
{
|
{
|
||||||
@ -62,14 +71,30 @@ public:
|
|||||||
sd.shape = &groundShape;
|
sd.shape = &groundShape;
|
||||||
sd.friction = 0.3f;
|
sd.friction = 0.3f;
|
||||||
|
|
||||||
b3Shape* s = b->CreateShape(sd);
|
b->CreateShape(sd);
|
||||||
|
|
||||||
b3SoftBodyWorldShapeDef ssd;
|
|
||||||
ssd.shape = s;
|
|
||||||
|
|
||||||
m_body->CreateWorldShape(ssd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create body
|
||||||
|
{
|
||||||
|
b3BodyDef bd;
|
||||||
|
bd.type = e_dynamicBody;
|
||||||
|
bd.position.y = 10.0f;
|
||||||
|
|
||||||
|
b3Body* b = m_world.CreateBody(bd);
|
||||||
|
|
||||||
|
static b3BoxHull boxHull(5.0f, 1.0f, 5.0f);
|
||||||
|
|
||||||
|
b3HullShape boxShape;
|
||||||
|
boxShape.m_hull = &boxHull;
|
||||||
|
|
||||||
|
b3ShapeDef sd;
|
||||||
|
sd.shape = &boxShape;
|
||||||
|
sd.density = 0.1f;
|
||||||
|
sd.friction = 0.3f;
|
||||||
|
|
||||||
|
b->CreateShape(sd);
|
||||||
|
}
|
||||||
|
|
||||||
m_bodyDragger = new b3SoftBodyDragger(&m_ray, m_body);
|
m_bodyDragger = new b3SoftBodyDragger(&m_ray, m_body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,9 +122,9 @@ public:
|
|||||||
b3Vec3 pA = m_bodyDragger->GetPointA();
|
b3Vec3 pA = m_bodyDragger->GetPointA();
|
||||||
b3Vec3 pB = m_bodyDragger->GetPointB();
|
b3Vec3 pB = m_bodyDragger->GetPointB();
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pA, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pB, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
g_draw->DrawSegment(pA, pB, b3Color_white);
|
||||||
}
|
}
|
||||||
@ -107,7 +132,7 @@ public:
|
|||||||
extern u32 b3_softBodySolverIterations;
|
extern u32 b3_softBodySolverIterations;
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
||||||
|
|
||||||
scalar E = m_body->GetEnergy();
|
float32 E = m_body->GetEnergy();
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
g_draw->DrawString(b3Color_white, "E = %f", E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,177 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 SOFTBODY_ANCHOR_H
|
|
||||||
#define SOFTBODY_ANCHOR_H
|
|
||||||
|
|
||||||
class SoftBodyAnchor : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SoftBodyAnchor()
|
|
||||||
{
|
|
||||||
m_mesh.SetAsSphere(4.0f, 0);
|
|
||||||
|
|
||||||
// Create soft body
|
|
||||||
b3SoftBodyDef def;
|
|
||||||
def.mesh = &m_mesh;
|
|
||||||
def.density = 0.2f;
|
|
||||||
def.E = 1000.0f;
|
|
||||||
def.nu = 0.33f;
|
|
||||||
def.c_yield = 0.1f;
|
|
||||||
def.c_creep = 0.5f;
|
|
||||||
def.c_max = 1.0f;
|
|
||||||
def.massDamping = 0.2f;
|
|
||||||
|
|
||||||
m_body = new b3SoftBody(def);
|
|
||||||
|
|
||||||
u32 pinIndex = ~0;
|
|
||||||
scalar pinDot = -B3_MAX_SCALAR;
|
|
||||||
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
scalar dot = b3Dot(m_mesh.vertices[i], b3Vec3_y);
|
|
||||||
if (dot > pinDot)
|
|
||||||
{
|
|
||||||
pinDot = dot;
|
|
||||||
pinIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SoftBodyNode* pinNode = m_body->GetNode(pinIndex);
|
|
||||||
pinNode->SetType(e_staticSoftBodyNode);
|
|
||||||
|
|
||||||
u32 anchorIndex = ~0;
|
|
||||||
scalar anchorDot = -B3_MAX_SCALAR;
|
|
||||||
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
scalar dot = b3Dot(m_mesh.vertices[i], -b3Vec3_y);
|
|
||||||
if (dot > anchorDot)
|
|
||||||
{
|
|
||||||
anchorDot = dot;
|
|
||||||
anchorIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b3SoftBodyNode* anchorNode = m_body->GetNode(anchorIndex);
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = e_dynamicBody;
|
|
||||||
bd.position.y = -10.0f;
|
|
||||||
|
|
||||||
b3Body* b = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3CapsuleShape cs;
|
|
||||||
cs.m_vertex1.Set(0.0f, -1.0f, 0.0f);
|
|
||||||
cs.m_vertex2.Set(0.0f, 1.0f, 0.0f);
|
|
||||||
cs.m_radius = 1.0f;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &cs;
|
|
||||||
sd.density = 0.1f;
|
|
||||||
|
|
||||||
m_shape = b->CreateShape(sd);
|
|
||||||
|
|
||||||
// Create anchor
|
|
||||||
b3SoftBodyAnchorDef ad;
|
|
||||||
ad.Initialize(b, anchorNode, anchorNode->GetPosition());
|
|
||||||
|
|
||||||
m_body->CreateAnchor(ad);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
|
||||||
m_body->SetGravity(gravity);
|
|
||||||
|
|
||||||
m_bodyDragger = new b3SoftBodyDragger(&m_ray, m_body);
|
|
||||||
}
|
|
||||||
|
|
||||||
~SoftBodyAnchor()
|
|
||||||
{
|
|
||||||
delete m_bodyDragger;
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
m_bodyDragger->Drag();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_body->Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
m_body->Draw();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_bodyDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_bodyDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_softBodySolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_body->GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseMove(pw);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new SoftBodyAnchor();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3QSoftBodyMesh m_mesh;
|
|
||||||
|
|
||||||
b3SoftBody* m_body;
|
|
||||||
b3SoftBodyDragger* m_bodyDragger;
|
|
||||||
b3Shape* m_shape;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -24,103 +24,70 @@ class SphereStack : public Test
|
|||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
e_h = 5,
|
e_rowCount = 1,
|
||||||
e_w = 1,
|
e_columnCount = 5,
|
||||||
e_d = 1
|
e_depthCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
SphereStack()
|
SphereStack()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bd;
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
bd.type = e_staticBody;
|
||||||
|
b3Body* ground = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &m_groundHull;
|
hs.m_hull = &m_groundHull;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sd;
|
||||||
sdef.shape = &hs;
|
sd.shape = &hs;
|
||||||
sdef.friction = 1.0f;
|
sd.density = 0.0f;
|
||||||
|
sd.friction = 1.0f;
|
||||||
body->CreateShape(sdef);
|
sd.restitution = 0.0f;
|
||||||
|
|
||||||
|
b3Shape* groundShape = ground->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
scalar e = 1.0f;
|
b3Vec3 stackOrigin;
|
||||||
|
stackOrigin.Set(0.0f, 5.0f, 0.0f);
|
||||||
|
float32 radius = 1.0f;
|
||||||
|
float32 diameter = 2.0f * radius;
|
||||||
|
|
||||||
b3SphereShape sphere;
|
for (u32 i = 0; i < e_rowCount; ++i)
|
||||||
sphere.m_center.SetZero();
|
|
||||||
sphere.m_radius = e;
|
|
||||||
|
|
||||||
b3Vec3 separation;
|
|
||||||
separation.x = 1.0f;
|
|
||||||
separation.y = 1.0f;
|
|
||||||
separation.z = 1.0f;
|
|
||||||
|
|
||||||
b3Vec3 scale;
|
|
||||||
scale.x = 2.0f * e + separation.x;
|
|
||||||
scale.y = 2.0f * e + separation.y;
|
|
||||||
scale.z = 2.0f * e + separation.z;
|
|
||||||
|
|
||||||
b3Vec3 size;
|
|
||||||
size.x = 2.0f * e + scale.x * scalar(e_w - 1);
|
|
||||||
size.y = 2.0f * e + scale.y * scalar(e_h - 1);
|
|
||||||
size.z = 2.0f * e + scale.z * scalar(e_d - 1);
|
|
||||||
|
|
||||||
b3Vec3 translation;
|
|
||||||
translation.x = e - 0.5f * size.x;
|
|
||||||
translation.y = e - 0.5f * size.y;
|
|
||||||
translation.z = e - 0.5f * size.z;
|
|
||||||
|
|
||||||
translation.y += 9.0f;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < e_h; ++i)
|
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < e_w; ++j)
|
for (u32 j = 0; j < e_columnCount; ++j)
|
||||||
{
|
{
|
||||||
for (u32 k = 0; k < e_d; ++k)
|
for (u32 k = 0; k < e_depthCount; ++k)
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = b3BodyType::e_dynamicBody;
|
||||||
|
bdef.position.x = float32(i) * diameter;
|
||||||
bdef.position.Set(scalar(j), scalar(i), scalar(k));
|
bdef.position.y = float32(j) * diameter;
|
||||||
|
bdef.position.z = float32(k) * diameter;
|
||||||
bdef.position.x *= scale.x;
|
bdef.position += stackOrigin;
|
||||||
bdef.position.y *= scale.y;
|
bdef.linearVelocity.Set(0.0f, -50.0f, 0.0f);
|
||||||
bdef.position.z *= scale.z;
|
|
||||||
|
|
||||||
bdef.position += translation;
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
|
b3SphereShape sphere;
|
||||||
|
sphere.m_center.SetZero();
|
||||||
|
sphere.m_radius = radius;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.3f;
|
|
||||||
sdef.shape = &sphere;
|
sdef.shape = &sphere;
|
||||||
|
sdef.density = 1.0f;
|
||||||
|
sdef.friction = 0.3f;
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
b3Shape* shape = body->CreateShape(sdef);
|
||||||
|
|
||||||
u32 bodyIndex = GetBodyIndex(i, j, k);
|
|
||||||
|
|
||||||
m_bodies[bodyIndex] = body;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetBodyIndex(u32 i, u32 j, u32 k)
|
|
||||||
{
|
|
||||||
B3_ASSERT(i < e_h);
|
|
||||||
B3_ASSERT(j < e_w);
|
|
||||||
B3_ASSERT(k < e_d);
|
|
||||||
return k + e_d * (j + e_w * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new SphereStack();
|
return new SphereStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Body* m_bodies[e_h * e_w * e_d];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,185 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 SPRING_TEST_H
|
|
||||||
#define SPRING_TEST_H
|
|
||||||
|
|
||||||
class SpringTest : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpringTest()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
b3Body* ground = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &hs;
|
|
||||||
|
|
||||||
ground->CreateShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Car frame shape
|
|
||||||
m_frameHull.SetExtents(2.0f, 0.5f, 5.0f);
|
|
||||||
|
|
||||||
b3HullShape box;
|
|
||||||
box.m_hull = &m_frameHull;
|
|
||||||
|
|
||||||
// Wheel shape
|
|
||||||
b3SphereShape sphere;
|
|
||||||
sphere.m_center.SetZero();
|
|
||||||
sphere.m_radius = 1.0f;
|
|
||||||
|
|
||||||
// Car frame
|
|
||||||
b3Body* frame;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(0.0f, 10.0f, 0.0f);
|
|
||||||
|
|
||||||
frame = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.3f;
|
|
||||||
sdef.shape = &box;
|
|
||||||
|
|
||||||
frame->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* wheelLF;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(-1.0f, 7.0f, 4.5f);
|
|
||||||
bdef.fixedRotationY = true;
|
|
||||||
|
|
||||||
wheelLF = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &sphere;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
|
|
||||||
wheelLF->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3SpringJointDef def;
|
|
||||||
def.Initialize(frame, wheelLF, b3Vec3(-1.0f, 9.0f, 4.5), b3Vec3(-1.0f, 9.0f, 4.5f));
|
|
||||||
def.collideLinked = true;
|
|
||||||
def.dampingRatio = 0.5f;
|
|
||||||
def.frequencyHz = 4.0f;
|
|
||||||
|
|
||||||
m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* wheelRF;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(1.0f, 7.0, 4.5f);
|
|
||||||
bdef.fixedRotationY = true;
|
|
||||||
|
|
||||||
wheelRF = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
sdef.shape = &sphere;
|
|
||||||
|
|
||||||
wheelRF->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3SpringJointDef def;
|
|
||||||
def.Initialize(frame, wheelRF, b3Vec3(1.0f, 9.0, 4.5), b3Vec3(1.0f, 9.0, 4.5f));
|
|
||||||
def.collideLinked = true;
|
|
||||||
def.dampingRatio = 0.5f;
|
|
||||||
def.frequencyHz = 4.0f;
|
|
||||||
|
|
||||||
m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* wheelLB;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(-1.0f, 7.0f, -4.5f);
|
|
||||||
bdef.fixedRotationY = true;
|
|
||||||
|
|
||||||
wheelLB = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &sphere;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
|
|
||||||
wheelLB->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3SpringJointDef def;
|
|
||||||
def.Initialize(frame, wheelLB, b3Vec3(-1.0f, 9.0f, -4.5f), b3Vec3(-1.0f, 9.0f, -4.5f));
|
|
||||||
def.collideLinked = true;
|
|
||||||
def.dampingRatio = 0.8f;
|
|
||||||
def.frequencyHz = 4.0f;
|
|
||||||
|
|
||||||
m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* wheelRB;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(1.0f, 7.0f, -4.5f);
|
|
||||||
bdef.fixedRotationY = true;
|
|
||||||
|
|
||||||
wheelRB = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
sdef.shape = &sphere;
|
|
||||||
|
|
||||||
wheelRB->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3SpringJointDef def;
|
|
||||||
def.Initialize(frame, wheelRB, b3Vec3(1.0f, 9.0f, -4.5f), b3Vec3(1.0f, 9.0f, -4.5f));
|
|
||||||
def.collideLinked = true;
|
|
||||||
def.frequencyHz = 4.0f;
|
|
||||||
def.dampingRatio = 0.8f;
|
|
||||||
|
|
||||||
m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new SpringTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BoxHull m_frameHull;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -22,12 +22,6 @@
|
|||||||
class TableCloth : public Test
|
class TableCloth : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 10,
|
|
||||||
e_h = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
TableCloth()
|
TableCloth()
|
||||||
{
|
{
|
||||||
// Translate the mesh
|
// Translate the mesh
|
||||||
@ -41,13 +35,15 @@ public:
|
|||||||
def.mesh = &m_clothMesh;
|
def.mesh = &m_clothMesh;
|
||||||
def.density = 0.2f;
|
def.density = 0.2f;
|
||||||
def.streching = 10000.0f;
|
def.streching = 10000.0f;
|
||||||
def.strechDamping = 100.0f;
|
//def.shearing = 10000.0f;
|
||||||
|
def.damping = 100.0f;
|
||||||
def.thickness = 0.2f;
|
def.thickness = 0.2f;
|
||||||
def.friction = 0.1f;
|
def.friction = 0.1f;
|
||||||
|
|
||||||
m_cloth = new b3Cloth(def);
|
m_cloth = new b3Cloth(def);
|
||||||
|
|
||||||
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
||||||
|
m_cloth->SetWorld(&m_world);
|
||||||
|
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
@ -55,7 +51,7 @@ public:
|
|||||||
|
|
||||||
b3Body* b = m_world.CreateBody(bd);
|
b3Body* b = m_world.CreateBody(bd);
|
||||||
|
|
||||||
m_tableHull.SetExtents(5.0f, 2.0f);
|
m_tableHull.SetAsCylinder(5.0f, 2.0f);
|
||||||
|
|
||||||
b3HullShape tableShape;
|
b3HullShape tableShape;
|
||||||
tableShape.m_hull = &m_tableHull;
|
tableShape.m_hull = &m_tableHull;
|
||||||
@ -64,12 +60,7 @@ public:
|
|||||||
sd.shape = &tableShape;
|
sd.shape = &tableShape;
|
||||||
sd.friction = 1.0f;
|
sd.friction = 1.0f;
|
||||||
|
|
||||||
b3Shape* shape = b->CreateShape(sd);
|
b->CreateShape(sd);
|
||||||
|
|
||||||
b3ClothWorldShapeDef csd;
|
|
||||||
csd.shape = shape;
|
|
||||||
|
|
||||||
m_cloth->CreateWorldShape(csd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
m_clothDragger = new b3ClothDragger(&m_ray, m_cloth);
|
||||||
@ -94,9 +85,9 @@ public:
|
|||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
b3Vec3 pA = m_clothDragger->GetPointA();
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
b3Vec3 pB = m_clothDragger->GetPointB();
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pA, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pB, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
g_draw->DrawSegment(pA, pB, b3Color_white);
|
||||||
}
|
}
|
||||||
@ -104,7 +95,7 @@ public:
|
|||||||
extern u32 b3_clothSolverIterations;
|
extern u32 b3_clothSolverIterations;
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
||||||
|
|
||||||
scalar E = m_cloth->GetEnergy();
|
float32 E = m_cloth->GetEnergy();
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
g_draw->DrawString(b3Color_white, "E = %f", E);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,11 +134,11 @@ public:
|
|||||||
return new TableCloth();
|
return new TableCloth();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3GridClothMesh<e_w, e_h> m_clothMesh;
|
b3GridClothMesh<10, 10> m_clothMesh;
|
||||||
b3Cloth* m_cloth;
|
b3Cloth* m_cloth;
|
||||||
b3ClothDragger* m_clothDragger;
|
b3ClothDragger* m_clothDragger;
|
||||||
|
|
||||||
b3CylinderHull m_tableHull;
|
b3QHull m_tableHull;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
// Hot/Cold color map
|
// Hot/Cold color map
|
||||||
// See http://paulbourke.net/miscellaneous/colourspace/
|
// See http://paulbourke.net/miscellaneous/colourspace/
|
||||||
static inline b3Color Color(scalar x, scalar a, scalar b)
|
static inline b3Color Color(float32 x, float32 a, float32 b)
|
||||||
{
|
{
|
||||||
x = b3Clamp(x, a, b);
|
x = b3Clamp(x, a, b);
|
||||||
|
|
||||||
scalar d = b - a;
|
float32 d = b - a;
|
||||||
|
|
||||||
b3Color c(1.0f, 1.0f, 1.0f);
|
b3Color c(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
@ -58,12 +58,6 @@ static inline b3Color Color(scalar x, scalar a, scalar b)
|
|||||||
class TensionMapping : public Test
|
class TensionMapping : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum
|
|
||||||
{
|
|
||||||
e_w = 10,
|
|
||||||
e_h = 10
|
|
||||||
};
|
|
||||||
|
|
||||||
TensionMapping()
|
TensionMapping()
|
||||||
{
|
{
|
||||||
// Create cloth
|
// Create cloth
|
||||||
@ -71,25 +65,24 @@ public:
|
|||||||
def.mesh = &m_clothMesh;
|
def.mesh = &m_clothMesh;
|
||||||
def.density = 0.2f;
|
def.density = 0.2f;
|
||||||
def.streching = 10000.0f;
|
def.streching = 10000.0f;
|
||||||
def.strechDamping = 100.0f;
|
def.shearing = 5000.0f;
|
||||||
def.shearing = 1000.0f;
|
def.damping = 100.0f;
|
||||||
def.shearDamping = 10.0f;
|
|
||||||
def.bending = 1000.0f;
|
|
||||||
def.bendDamping = 10.0f;
|
|
||||||
|
|
||||||
m_cloth = new b3Cloth(def);
|
m_cloth = new b3Cloth(def);
|
||||||
|
|
||||||
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
m_cloth->SetGravity(b3Vec3(0.0f, -9.8f, 0.0f));
|
||||||
|
m_cloth->SetWorld(&m_world);
|
||||||
|
|
||||||
// Freeze some particles
|
// Freeze some particles
|
||||||
for (u32 i = 0; i < 2; ++i)
|
b3AABB3 aabb;
|
||||||
|
aabb.m_lower.Set(-5.0f, -1.0f, -6.0f);
|
||||||
|
aabb.m_upper.Set(5.0f, 1.0f, -4.0f);
|
||||||
|
|
||||||
|
for (b3Particle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext())
|
||||||
{
|
{
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
if (aabb.Contains(p->GetPosition()))
|
||||||
{
|
{
|
||||||
u32 v = m_clothMesh.GetVertex(i, j);
|
p->SetType(e_staticParticle);
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(v);
|
|
||||||
p->SetType(e_staticClothParticle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +103,8 @@ public:
|
|||||||
|
|
||||||
const b3ClothMesh* mesh = m_cloth->GetMesh();
|
const b3ClothMesh* mesh = m_cloth->GetMesh();
|
||||||
|
|
||||||
b3Vec3 tension[(e_h + 1) * (e_w + 1)];
|
b3StackArray<b3Vec3, 256> tension;
|
||||||
|
tension.Resize(mesh->vertexCount);
|
||||||
for (u32 i = 0; i < mesh->vertexCount; ++i)
|
for (u32 i = 0; i < mesh->vertexCount; ++i)
|
||||||
{
|
{
|
||||||
tension[i].SetZero();
|
tension[i].SetZero();
|
||||||
@ -118,100 +112,66 @@ public:
|
|||||||
|
|
||||||
for (b3Force* f = m_cloth->GetForceList().m_head; f; f = f->GetNext())
|
for (b3Force* f = m_cloth->GetForceList().m_head; f; f = f->GetNext())
|
||||||
{
|
{
|
||||||
if (f->GetType() == e_stretchForce)
|
if (f->GetType() == e_strechForce)
|
||||||
{
|
{
|
||||||
b3StretchForce* s = (b3StretchForce*)f;
|
b3StrechForce* s = (b3StrechForce*)f;
|
||||||
|
|
||||||
|
b3ClothTriangle* triangle = s->GetTriangle();
|
||||||
|
u32 triangleIndex = triangle->GetTriangle();
|
||||||
|
b3ClothMeshTriangle* mesh_triangle = m_clothMesh.triangles + triangleIndex;
|
||||||
|
|
||||||
|
u32 v1 = mesh_triangle->v1;
|
||||||
|
u32 v2 = mesh_triangle->v2;
|
||||||
|
u32 v3 = mesh_triangle->v3;
|
||||||
|
|
||||||
b3Vec3 f1 = s->GetActionForce1();
|
b3Vec3 f1 = s->GetActionForce1();
|
||||||
b3Vec3 f2 = s->GetActionForce2();
|
b3Vec3 f2 = s->GetActionForce2();
|
||||||
b3Vec3 f3 = s->GetActionForce3();
|
b3Vec3 f3 = s->GetActionForce3();
|
||||||
|
|
||||||
b3ClothParticle* p1 = s->GetParticle1();
|
|
||||||
b3ClothParticle* p2 = s->GetParticle2();
|
|
||||||
b3ClothParticle* p3 = s->GetParticle3();
|
|
||||||
|
|
||||||
u32 v1 = p1->GetMeshIndex();
|
|
||||||
u32 v2 = p2->GetMeshIndex();
|
|
||||||
u32 v3 = p3->GetMeshIndex();
|
|
||||||
|
|
||||||
tension[v1] += f1;
|
tension[v1] += f1;
|
||||||
tension[v2] += f2;
|
tension[v2] += f2;
|
||||||
tension[v3] += f3;
|
tension[v3] += f3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (b3ClothParticle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext())
|
|
||||||
{
|
|
||||||
if (p->GetType() == e_staticClothParticle)
|
|
||||||
{
|
|
||||||
b3Draw_draw->DrawPoint(p->GetPosition(), 4.0f, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->GetType() == e_kinematicClothParticle)
|
|
||||||
{
|
|
||||||
b3Draw_draw->DrawPoint(p->GetPosition(), 4.0f, b3Color_blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p->GetType() == e_dynamicClothParticle)
|
|
||||||
{
|
|
||||||
b3Draw_draw->DrawPoint(p->GetPosition(), 4.0f, b3Color_green);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < mesh->triangleCount; ++i)
|
for (u32 i = 0; i < mesh->triangleCount; ++i)
|
||||||
{
|
{
|
||||||
b3ClothMeshTriangle* triangle = mesh->triangles + i;
|
b3ClothMeshTriangle* t = mesh->triangles + i;
|
||||||
|
|
||||||
b3Vec3 v1 = m_cloth->GetParticle(triangle->v1)->GetPosition();
|
|
||||||
b3Vec3 v2 = m_cloth->GetParticle(triangle->v2)->GetPosition();
|
|
||||||
b3Vec3 v3 = m_cloth->GetParticle(triangle->v3)->GetPosition();
|
|
||||||
|
|
||||||
|
b3Vec3 v1 = m_cloth->GetParticle(t->v1)->GetPosition();
|
||||||
|
b3Vec3 v2 = m_cloth->GetParticle(t->v2)->GetPosition();
|
||||||
|
b3Vec3 v3 = m_cloth->GetParticle(t->v3)->GetPosition();
|
||||||
|
|
||||||
g_draw->DrawTriangle(v1, v2, v3, b3Color_black);
|
g_draw->DrawTriangle(v1, v2, v3, b3Color_black);
|
||||||
|
|
||||||
b3Vec3 c = (v1 + v2 + v3) / 3.0f;
|
b3Vec3 c = (v1 + v2 + v3) / 3.0f;
|
||||||
|
|
||||||
scalar s = 0.9f;
|
float32 s = 0.9f;
|
||||||
|
|
||||||
v1 = s * (v1 - c) + c;
|
v1 = s * (v1 - c) + c;
|
||||||
v2 = s * (v2 - c) + c;
|
v2 = s * (v2 - c) + c;
|
||||||
v3 = s * (v3 - c) + c;
|
v3 = s * (v3 - c) + c;
|
||||||
|
|
||||||
b3Vec3 f1 = tension[triangle->v1];
|
b3Vec3 f1 = tension[t->v1];
|
||||||
scalar L1 = b3Length(f1);
|
float32 L1 = b3Length(f1);
|
||||||
|
|
||||||
b3Vec3 f2 = tension[triangle->v2];
|
b3Vec3 f2 = tension[t->v2];
|
||||||
scalar L2 = b3Length(f2);
|
float32 L2 = b3Length(f2);
|
||||||
|
|
||||||
b3Vec3 f3 = tension[triangle->v3];
|
b3Vec3 f3 = tension[t->v3];
|
||||||
scalar L3 = b3Length(f3);
|
float32 L3 = b3Length(f3);
|
||||||
|
|
||||||
scalar L = (L1 + L2 + L3) / 3.0f;
|
float32 L = (L1 + L2 + L3) / 3.0f;
|
||||||
|
|
||||||
const scalar kMaxT = 10000.0f;
|
const float32 kMaxT = 10000.0f;
|
||||||
b3Color color = Color(L, 0.0f, kMaxT);
|
b3Color color = Color(L, 0.0f, kMaxT);
|
||||||
|
|
||||||
b3Vec3 n1 = b3Cross(v2 - v1, v3 - v1);
|
b3Vec3 n1 = b3Cross(v2 - v1, v3 - v1);
|
||||||
n1.Normalize();
|
n1.Normalize();
|
||||||
|
g_draw->DrawSolidTriangle(n1, v1, v2, v3, color);
|
||||||
|
|
||||||
scalar r = 0.05f;
|
b3Vec3 n2 = -n1;
|
||||||
|
g_draw->DrawSolidTriangle(n2, v3, v2, v1, color);
|
||||||
{
|
|
||||||
b3Vec3 x1 = v1 + r * n1;
|
|
||||||
b3Vec3 x2 = v2 + r * n1;
|
|
||||||
b3Vec3 x3 = v3 + r * n1;
|
|
||||||
|
|
||||||
g_draw->DrawSolidTriangle(n1, x1, x2, x3, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3Vec3 n2 = -n1;
|
|
||||||
|
|
||||||
b3Vec3 x1 = v1 + r * n2;
|
|
||||||
b3Vec3 x2 = v2 + r * n2;
|
|
||||||
b3Vec3 x3 = v3 + r * n2;
|
|
||||||
|
|
||||||
g_draw->DrawSolidTriangle(n2, x3, x2, x1, color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_clothDragger->IsDragging())
|
if (m_clothDragger->IsDragging())
|
||||||
@ -219,9 +179,9 @@ public:
|
|||||||
b3Vec3 pA = m_clothDragger->GetPointA();
|
b3Vec3 pA = m_clothDragger->GetPointA();
|
||||||
b3Vec3 pB = m_clothDragger->GetPointB();
|
b3Vec3 pB = m_clothDragger->GetPointB();
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pA, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
g_draw->DrawPoint(pB, 2.0f, b3Color_green);
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
g_draw->DrawSegment(pA, pB, b3Color_white);
|
||||||
}
|
}
|
||||||
@ -229,7 +189,7 @@ public:
|
|||||||
extern u32 b3_clothSolverIterations;
|
extern u32 b3_clothSolverIterations;
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_clothSolverIterations);
|
||||||
|
|
||||||
scalar E = m_cloth->GetEnergy();
|
float32 E = m_cloth->GetEnergy();
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
g_draw->DrawString(b3Color_white, "E = %f", E);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +228,7 @@ public:
|
|||||||
return new TensionMapping();
|
return new TensionMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3GridClothMesh<e_w, e_h> m_clothMesh;
|
b3GridClothMesh<10, 10> m_clothMesh;
|
||||||
b3Cloth* m_cloth;
|
b3Cloth* m_cloth;
|
||||||
b3ClothDragger* m_clothDragger;
|
b3ClothDragger* m_clothDragger;
|
||||||
};
|
};
|
||||||
|
@ -1,413 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 TETGEN_SOFTBODY_H
|
|
||||||
#define TETGEN_SOFTBODY_H
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
struct TetGenMesh : public b3SoftBodyMesh
|
|
||||||
{
|
|
||||||
TetGenMesh()
|
|
||||||
{
|
|
||||||
vertexCount = 0;
|
|
||||||
vertices = nullptr;
|
|
||||||
triangleCount = 0;
|
|
||||||
triangles = nullptr;
|
|
||||||
tetrahedronCount = 0;
|
|
||||||
tetrahedrons = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~TetGenMesh()
|
|
||||||
{
|
|
||||||
free(vertices);
|
|
||||||
free(triangles);
|
|
||||||
free(tetrahedrons);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Load(const char* node_filename, const char* face_filename, const char* ele_filename)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
std::ifstream file(node_filename);
|
|
||||||
if (!file.good())
|
|
||||||
{
|
|
||||||
printf("Could not open %s \n", node_filename);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nodeCount, nodeDimensions, attributeCount, boundaryMarkCount;
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(file, line))
|
|
||||||
{
|
|
||||||
if (line[0] == '#')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0] == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream line_stream(line);
|
|
||||||
|
|
||||||
line_stream >> nodeCount >> nodeDimensions >> attributeCount >> boundaryMarkCount;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeDimensions != 3)
|
|
||||||
{
|
|
||||||
printf(".node file: Only 3 dimensional nodes supported\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributeCount != 0)
|
|
||||||
{
|
|
||||||
printf(".node file: Only nodes with 0 attributes supported\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boundaryMarkCount != 0)
|
|
||||||
{
|
|
||||||
printf(".node file: Only nodes with 0 markers supported\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(vertexCount == 0);
|
|
||||||
vertices = (b3Vec3*)malloc(sizeof(b3Vec3) * nodeCount);
|
|
||||||
|
|
||||||
while (std::getline(file, line))
|
|
||||||
{
|
|
||||||
if (line[0] == '#')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0] == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nodeId;
|
|
||||||
float x, y, z;
|
|
||||||
|
|
||||||
std::stringstream line_stream(line);
|
|
||||||
|
|
||||||
line_stream >> nodeId >> x >> y >> z;
|
|
||||||
|
|
||||||
assert(nodeId > 0);
|
|
||||||
assert(nodeId <= nodeCount);
|
|
||||||
|
|
||||||
assert(b3IsValid(x));
|
|
||||||
assert(b3IsValid(y));
|
|
||||||
assert(b3IsValid(z));
|
|
||||||
|
|
||||||
vertices[vertexCount].x = x;
|
|
||||||
vertices[vertexCount].y = y;
|
|
||||||
vertices[vertexCount].z = z;
|
|
||||||
|
|
||||||
++vertexCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(vertexCount == nodeCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::ifstream file(face_filename);
|
|
||||||
if (!file.good())
|
|
||||||
{
|
|
||||||
printf("Could not open %s \n", face_filename);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int faceCount, boundaryMarkerCount;
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(file, line))
|
|
||||||
{
|
|
||||||
if (line[0] == '#')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0] == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream line_stream(line);
|
|
||||||
|
|
||||||
line_stream >> faceCount >> boundaryMarkerCount;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(triangleCount == 0);
|
|
||||||
triangles = (b3SoftBodyMeshTriangle*)malloc(sizeof(b3SoftBodyMeshTriangle) * faceCount);
|
|
||||||
|
|
||||||
while (std::getline(file, line))
|
|
||||||
{
|
|
||||||
if (line[0] == '#')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0] == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int faceId;
|
|
||||||
int v1, v2, v3;
|
|
||||||
int corner;
|
|
||||||
|
|
||||||
std::stringstream line_stream(line);
|
|
||||||
|
|
||||||
line_stream >> faceId >> v1 >> v2 >> v3 >> corner;
|
|
||||||
|
|
||||||
assert(faceId > 0);
|
|
||||||
assert(faceId <= faceCount);
|
|
||||||
|
|
||||||
// Make CCW
|
|
||||||
b3Swap(v2, v3);
|
|
||||||
|
|
||||||
triangles[triangleCount].v1 = u32(v1 - 1);
|
|
||||||
triangles[triangleCount].v2 = u32(v2 - 1);
|
|
||||||
triangles[triangleCount].v3 = u32(v3 - 1);
|
|
||||||
|
|
||||||
++triangleCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(triangleCount == faceCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::ifstream file(ele_filename);
|
|
||||||
if (!file.good())
|
|
||||||
{
|
|
||||||
printf("Could not open %s \n", ele_filename);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tetCount, nodesPerTet, attributeCount;
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(file, line))
|
|
||||||
{
|
|
||||||
if (line[0] == '#')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0] == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream line_stream(line);
|
|
||||||
|
|
||||||
line_stream >> tetCount >> nodesPerTet >> attributeCount;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodesPerTet != 4)
|
|
||||||
{
|
|
||||||
printf(".ele file: Only 4 nodes per tetrahedran supported\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributeCount != 0)
|
|
||||||
{
|
|
||||||
printf(".ele file: Only elements with 0 attributes supported\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(tetrahedronCount == 0);
|
|
||||||
tetrahedrons = (b3SoftBodyMeshTetrahedron*)malloc(sizeof(b3SoftBodyMeshTetrahedron) * tetCount);
|
|
||||||
|
|
||||||
while (std::getline(file, line))
|
|
||||||
{
|
|
||||||
if (line[0] == '#')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line[0] == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tetId;
|
|
||||||
int v1, v2, v3, v4;
|
|
||||||
|
|
||||||
std::stringstream line_stream(line);
|
|
||||||
|
|
||||||
line_stream >> tetId >> v1 >> v2 >> v3 >> v4;
|
|
||||||
|
|
||||||
assert(tetId > 0);
|
|
||||||
assert(tetId <= tetCount);
|
|
||||||
|
|
||||||
// Make CCW
|
|
||||||
b3Swap(v2, v3);
|
|
||||||
|
|
||||||
tetrahedrons[tetrahedronCount].v1 = u32(v1 - 1);
|
|
||||||
tetrahedrons[tetrahedronCount].v2 = u32(v2 - 1);
|
|
||||||
tetrahedrons[tetrahedronCount].v3 = u32(v3 - 1);
|
|
||||||
tetrahedrons[tetrahedronCount].v4 = u32(v4 - 1);
|
|
||||||
|
|
||||||
++tetrahedronCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(tetrahedronCount == tetCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TetGenSoftBody : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TetGenSoftBody()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
bool ok = m_mesh.Load("data/octopus.node", "data/octopus.face", "data/octopus.ele");
|
|
||||||
assert(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < m_mesh.vertexCount; ++i)
|
|
||||||
{
|
|
||||||
m_mesh.vertices[i].y += 10.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create soft body
|
|
||||||
b3SoftBodyDef def;
|
|
||||||
def.mesh = &m_mesh;
|
|
||||||
def.density = 0.2f;
|
|
||||||
def.E = 1000.0f;
|
|
||||||
def.nu = 0.3f;
|
|
||||||
def.radius = 0.05f;
|
|
||||||
def.friction = 0.2f;
|
|
||||||
|
|
||||||
m_body = new b3SoftBody(def);
|
|
||||||
|
|
||||||
b3Vec3 gravity(0.0f, -9.8f, 0.0f);
|
|
||||||
m_body->SetGravity(gravity);
|
|
||||||
|
|
||||||
// Create ground
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
bd.type = e_staticBody;
|
|
||||||
|
|
||||||
b3Body* b = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape groundShape;
|
|
||||||
groundShape.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &groundShape;
|
|
||||||
sd.friction = 0.3f;
|
|
||||||
|
|
||||||
b3Shape* s = b->CreateShape(sd);
|
|
||||||
|
|
||||||
b3SoftBodyWorldShapeDef ssd;
|
|
||||||
ssd.shape = s;
|
|
||||||
|
|
||||||
m_body->CreateWorldShape(ssd);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bodyDragger = new b3SoftBodyDragger(&m_ray, m_body);
|
|
||||||
}
|
|
||||||
|
|
||||||
~TetGenSoftBody()
|
|
||||||
{
|
|
||||||
delete m_bodyDragger;
|
|
||||||
delete m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
m_bodyDragger->Drag();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_body->Step(g_testSettings->inv_hertz, g_testSettings->velocityIterations, g_testSettings->positionIterations);
|
|
||||||
|
|
||||||
m_body->Draw();
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging())
|
|
||||||
{
|
|
||||||
b3Vec3 pA = m_bodyDragger->GetPointA();
|
|
||||||
b3Vec3 pB = m_bodyDragger->GetPointB();
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pA, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawPoint(pB, 4.0f, b3Color_green);
|
|
||||||
|
|
||||||
g_draw->DrawSegment(pA, pB, b3Color_white);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern u32 b3_softBodySolverIterations;
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", b3_softBodySolverIterations);
|
|
||||||
|
|
||||||
scalar E = m_body->GetEnergy();
|
|
||||||
g_draw->DrawString(b3Color_white, "E = %f", E);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseMove(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseMove(pw);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftDown(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftDown(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == false)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StartDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MouseLeftUp(const b3Ray3& pw)
|
|
||||||
{
|
|
||||||
Test::MouseLeftUp(pw);
|
|
||||||
|
|
||||||
if (m_bodyDragger->IsDragging() == true)
|
|
||||||
{
|
|
||||||
m_bodyDragger->StopDragging();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new TetGenSoftBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
TetGenMesh m_mesh;
|
|
||||||
b3SoftBody* m_body;
|
|
||||||
b3SoftBodyDragger* m_bodyDragger;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,237 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 TIME_OF_IMPACT_H
|
|
||||||
#define TIME_OF_IMPACT_H
|
|
||||||
|
|
||||||
class TimeOfImpact : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TimeOfImpact()
|
|
||||||
{
|
|
||||||
m_shapeA.m_hull = &b3BoxHull_identity;
|
|
||||||
m_shapeA.m_radius = 0.0f;
|
|
||||||
|
|
||||||
m_shapeB.m_hull = &b3BoxHull_identity;
|
|
||||||
m_shapeB.m_radius = 0.0f;
|
|
||||||
|
|
||||||
m_sweepA.localCenter.SetZero();
|
|
||||||
m_sweepA.worldCenter0.Set(0.0f, 0.0f, 5.0f);
|
|
||||||
m_sweepA.worldCenter.Set(0.0f, 0.0f, -5.0f);
|
|
||||||
m_sweepA.orientation0.SetIdentity();
|
|
||||||
m_sweepA.orientation.SetIdentity();
|
|
||||||
|
|
||||||
m_sweepB.localCenter.SetZero();
|
|
||||||
m_sweepB.worldCenter0.Set(5.0f, 0.0f, 0.0f);
|
|
||||||
m_sweepB.worldCenter.Set(-5.0f, 0.0f, 0.0f);
|
|
||||||
m_sweepB.orientation0.SetIdentity();
|
|
||||||
m_sweepB.orientation.SetIdentity();
|
|
||||||
|
|
||||||
m_proxyA.Set(&m_shapeA, 0);
|
|
||||||
m_proxyB.Set(&m_shapeB, 0);
|
|
||||||
|
|
||||||
m_time = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
b3Color colorA0(1.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
b3Color colorB0(0.0f, 1.0f, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
// t0
|
|
||||||
b3Transform xfA0 = m_sweepA.GetTransform(0.0f);
|
|
||||||
b3Transform xfB0 = m_sweepB.GetTransform(0.0f);
|
|
||||||
|
|
||||||
g_draw->DrawTransform(xfA0);
|
|
||||||
g_draw->DrawTransform(xfB0);
|
|
||||||
|
|
||||||
m_world.DrawShape(xfA0, &m_shapeA, b3Color_black);
|
|
||||||
m_world.DrawShape(xfB0, &m_shapeB, b3Color_black);
|
|
||||||
|
|
||||||
m_world.DrawSolidShape(xfA0, &m_shapeA, colorA0);
|
|
||||||
m_world.DrawSolidShape(xfB0, &m_shapeB, colorB0);
|
|
||||||
|
|
||||||
// t1
|
|
||||||
b3Transform xfA1 = m_sweepA.GetTransform(1.0f);
|
|
||||||
b3Transform xfB1 = m_sweepB.GetTransform(1.0f);
|
|
||||||
|
|
||||||
g_draw->DrawTransform(xfA1);
|
|
||||||
g_draw->DrawTransform(xfB1);
|
|
||||||
|
|
||||||
m_world.DrawShape(xfA1, &m_shapeA, b3Color_black);
|
|
||||||
m_world.DrawShape(xfB1, &m_shapeB, b3Color_black);
|
|
||||||
|
|
||||||
m_world.DrawSolidShape(xfA1, &m_shapeA, colorA0);
|
|
||||||
m_world.DrawSolidShape(xfB1, &m_shapeB, colorB0);
|
|
||||||
|
|
||||||
// time
|
|
||||||
b3Color colorAt(1.0f, 0.0f, 0.0f, 0.5f);
|
|
||||||
b3Color colorBt(0.0f, 1.0f, 0.0f, 0.5f);
|
|
||||||
|
|
||||||
b3Transform xfAx = m_sweepA.GetTransform(m_time);
|
|
||||||
b3Transform xfBx = m_sweepB.GetTransform(m_time);
|
|
||||||
|
|
||||||
g_draw->DrawTransform(xfAx);
|
|
||||||
g_draw->DrawTransform(xfBx);
|
|
||||||
|
|
||||||
m_world.DrawShape(xfAx, &m_shapeA, b3Color_black);
|
|
||||||
m_world.DrawShape(xfBx, &m_shapeB, b3Color_black);
|
|
||||||
|
|
||||||
m_world.DrawSolidShape(xfAx, &m_shapeA, colorAt);
|
|
||||||
m_world.DrawSolidShape(xfBx, &m_shapeB, colorBt);
|
|
||||||
|
|
||||||
b3TOIInput input;
|
|
||||||
input.proxyA = m_proxyA;
|
|
||||||
input.sweepA = m_sweepA;
|
|
||||||
input.proxyB = m_proxyB;
|
|
||||||
input.sweepB = m_sweepB;
|
|
||||||
input.tMax = 1.0f;
|
|
||||||
|
|
||||||
b3TOIOutput output = b3TimeOfImpact(input);
|
|
||||||
|
|
||||||
if (output.state == b3TOIOutput::e_touching)
|
|
||||||
{
|
|
||||||
b3Transform xfAt = m_sweepA.GetTransform(output.t);
|
|
||||||
b3Transform xfBt = m_sweepB.GetTransform(output.t);
|
|
||||||
|
|
||||||
m_world.DrawShape(xfAt, &m_shapeA, b3Color_black);
|
|
||||||
m_world.DrawShape(xfBt, &m_shapeB, b3Color_black);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "Left/Right/Up/Down Arrow/W/S - Translate shape");
|
|
||||||
g_draw->DrawString(b3Color_white, "X/Y/Z - Rotate shape");
|
|
||||||
g_draw->DrawString(b3Color_white, "F/B - Advance Time Forwards/Backwards");
|
|
||||||
g_draw->DrawString(b3Color_white, "Iterations = %d", output.iterations);
|
|
||||||
|
|
||||||
if (output.state == b3TOIOutput::e_failed)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Failed");
|
|
||||||
}
|
|
||||||
else if (output.state == b3TOIOutput::e_overlapped)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Overlapped");
|
|
||||||
}
|
|
||||||
else if (output.state == b3TOIOutput::e_separated)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Separated!");
|
|
||||||
}
|
|
||||||
else if (output.state == b3TOIOutput::e_touching)
|
|
||||||
{
|
|
||||||
g_draw->DrawString(b3Color_white, "State = Touching!");
|
|
||||||
}
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, m_sweepA.worldCenter0, "t0");
|
|
||||||
g_draw->DrawString(b3Color_white, m_sweepA.worldCenter, "t1");
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, m_sweepB.worldCenter0, "t0");
|
|
||||||
g_draw->DrawString(b3Color_white, m_sweepB.worldCenter, "t1");
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int key)
|
|
||||||
{
|
|
||||||
const scalar dt = 0.01f;
|
|
||||||
const scalar d = 0.15f;
|
|
||||||
const scalar theta = 0.05f * B3_PI;
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_F)
|
|
||||||
{
|
|
||||||
m_time += dt;
|
|
||||||
if (m_time > 1.0f)
|
|
||||||
{
|
|
||||||
m_time = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_B)
|
|
||||||
{
|
|
||||||
m_time -= dt;
|
|
||||||
if (m_time < 0.0f)
|
|
||||||
{
|
|
||||||
m_time = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_LEFT)
|
|
||||||
{
|
|
||||||
m_sweepB.worldCenter0.x -= d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_RIGHT)
|
|
||||||
{
|
|
||||||
m_sweepB.worldCenter0.x += d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_UP)
|
|
||||||
{
|
|
||||||
m_sweepB.worldCenter0.y += d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_DOWN)
|
|
||||||
{
|
|
||||||
m_sweepB.worldCenter0.y -= d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
m_sweepB.worldCenter0.z += d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_W)
|
|
||||||
{
|
|
||||||
m_sweepB.worldCenter0.z -= d;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_X)
|
|
||||||
{
|
|
||||||
b3Quat qx = b3QuatRotationX(theta);
|
|
||||||
|
|
||||||
m_sweepB.orientation0 = m_sweepB.orientation0 * qx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_Y)
|
|
||||||
{
|
|
||||||
b3Quat qy = b3QuatRotationY(theta);
|
|
||||||
|
|
||||||
m_sweepB.orientation0 = m_sweepB.orientation0 * qy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == GLFW_KEY_Z)
|
|
||||||
{
|
|
||||||
b3Quat qz = b3QuatRotationZ(theta);
|
|
||||||
|
|
||||||
m_sweepB.orientation0 = m_sweepB.orientation0 * qz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new TimeOfImpact();
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar m_time;
|
|
||||||
|
|
||||||
b3HullShape m_shapeA;
|
|
||||||
b3Sweep m_sweepA;
|
|
||||||
b3ShapeGJKProxy m_proxyA;
|
|
||||||
|
|
||||||
b3HullShape m_shapeB;
|
|
||||||
b3Sweep m_sweepB;
|
|
||||||
b3ShapeGJKProxy m_proxyB;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 TRIANGLE_CONTACT_TEST_H
|
|
||||||
#define TRIANGLE_CONTACT_TEST_H
|
|
||||||
|
|
||||||
class TriangleContactTest : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TriangleContactTest()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = b3BodyType::e_staticBody;
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3TriangleShape ts;
|
|
||||||
ts.m_vertex1.Set(-5.0f, 0.0f, 5.0f);
|
|
||||||
ts.m_vertex2.Set(5.0f, 0.0f, 5.0f);
|
|
||||||
ts.m_vertex3.Set(0.0f, 0.0f, -5.0f);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &ts;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = b3BodyType::e_dynamicBody;
|
|
||||||
bdef.position.Set(0.0f, 5.0f, 0.0f);
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &b3BoxHull_identity;
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.1f;
|
|
||||||
sdef.shape = &hs;
|
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new TriangleContactTest();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -39,10 +39,11 @@ public:
|
|||||||
{
|
{
|
||||||
static b3BoxHull box;
|
static b3BoxHull box;
|
||||||
|
|
||||||
box.SetExtents(50.0f, 1.0f, 200.0f);
|
b3Transform m;
|
||||||
|
m.position.Set(0.0f, -45.0f, 0.0f);
|
||||||
b3Vec3 translation(0.0f, -45.0f, 0.0f);
|
m.rotation = b3Diagonal(50.0f, 1.0f, 200.0f);
|
||||||
box.Translate(translation);
|
|
||||||
|
box.SetTransform(m);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &box;
|
hs.m_hull = &box;
|
||||||
@ -57,10 +58,11 @@ public:
|
|||||||
{
|
{
|
||||||
static b3BoxHull box;
|
static b3BoxHull box;
|
||||||
|
|
||||||
box.SetExtents(50.0f, 1.0f, 200.0f);
|
b3Transform m;
|
||||||
|
m.position.Set(0.0f, 50.0f, 0.0f);
|
||||||
b3Vec3 translation(0.0f, 50.0f, 0.0f);
|
m.rotation = b3Diagonal(50.0f, 1.0f, 200.0f);
|
||||||
box.Translate(translation);
|
|
||||||
|
box.SetTransform(m);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &box;
|
hs.m_hull = &box;
|
||||||
@ -75,10 +77,11 @@ public:
|
|||||||
{
|
{
|
||||||
static b3BoxHull box;
|
static b3BoxHull box;
|
||||||
|
|
||||||
box.SetExtents(50.0f, 50.0f, 1.0f);
|
b3Transform m;
|
||||||
|
m.position.Set(0.0f, 5.0f, -200.0f);
|
||||||
b3Vec3 translation(0.0f, 5.0f, -200.0f);
|
m.rotation = b3Diagonal(50.0f, 50.0f, 1.0f);
|
||||||
box.Translate(translation);
|
|
||||||
|
box.SetTransform(m);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &box;
|
hs.m_hull = &box;
|
||||||
@ -93,10 +96,11 @@ public:
|
|||||||
{
|
{
|
||||||
static b3BoxHull box;
|
static b3BoxHull box;
|
||||||
|
|
||||||
box.SetExtents(50.0f, 50.0f, 1.0f);
|
b3Transform m;
|
||||||
|
m.position.Set(0.0f, 5.0f, 200.0f);
|
||||||
b3Vec3 translation(0.0f, 5.0f, 200.0f);
|
m.rotation = b3Diagonal(50.0f, 50.0f, 1.0f);
|
||||||
box.Translate(translation);
|
|
||||||
|
box.SetTransform(m);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &box;
|
hs.m_hull = &box;
|
||||||
@ -111,10 +115,11 @@ public:
|
|||||||
{
|
{
|
||||||
static b3BoxHull box;
|
static b3BoxHull box;
|
||||||
|
|
||||||
box.SetExtents(1.0f, 50.0f, 200.0f);
|
b3Transform m;
|
||||||
|
m.position.Set(-50.0f, 5.0f, 0.0f);
|
||||||
b3Vec3 translation(-50.0f, 5.0f, 0.0f);
|
m.rotation = b3Diagonal(1.0f, 50.0f, 200.0f);
|
||||||
box.Translate(translation);
|
|
||||||
|
box.SetTransform(m);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &box;
|
hs.m_hull = &box;
|
||||||
@ -129,11 +134,11 @@ public:
|
|||||||
{
|
{
|
||||||
static b3BoxHull box;
|
static b3BoxHull box;
|
||||||
|
|
||||||
box.SetExtents(1.0f, 50.0f, 200.0f);
|
b3Transform m;
|
||||||
|
m.position.Set(50.0f, 5.0f, 0.0f);
|
||||||
b3Vec3 translation(50.0f, 5.0f, 0.0f);
|
m.rotation = b3Diagonal(1.0f, 50.0f, 200.0f);
|
||||||
|
|
||||||
box.Translate(translation);
|
box.SetTransform(m);
|
||||||
|
|
||||||
b3HullShape hs;
|
b3HullShape hs;
|
||||||
hs.m_hull = &box;
|
hs.m_hull = &box;
|
||||||
@ -156,8 +161,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_coneHull.SetExtents(1.0f, 1.0f);
|
m_coneHull.SetAsCone();
|
||||||
m_cylinderHull.SetExtents(1.0f, 1.0f);
|
m_cylinderHull.SetAsCylinder();
|
||||||
|
|
||||||
m_count = 0;
|
m_count = 0;
|
||||||
}
|
}
|
||||||
@ -199,8 +204,8 @@ public:
|
|||||||
b3Body* body = m_world.CreateBody(bdef);
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
b3CapsuleShape capsule;
|
b3CapsuleShape capsule;
|
||||||
capsule.m_vertex1.Set(0.0f, 0.0f, -1.0f);
|
capsule.m_centers[0].Set(0.0f, 0.0f, -1.0f);
|
||||||
capsule.m_vertex2.Set(0.0f, 0.0f, 1.0f);
|
capsule.m_centers[1].Set(0.0f, 0.0f, 1.0f);
|
||||||
capsule.m_radius = 1.0f;
|
capsule.m_radius = 1.0f;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
@ -274,8 +279,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 m_count;
|
u32 m_count;
|
||||||
b3ConeHull m_coneHull;
|
b3QHull m_coneHull;
|
||||||
b3CylinderHull m_cylinderHull;
|
b3QHull m_cylinderHull;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -36,12 +36,19 @@ public:
|
|||||||
ground->CreateShape(sd);
|
ground->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static b3BoxHull rampHull(25.0f, 0.5f, 25.0f);
|
static b3BoxHull rampHull;
|
||||||
|
|
||||||
|
{
|
||||||
|
b3Transform xf;
|
||||||
|
xf.position.SetZero();
|
||||||
|
xf.rotation = b3Diagonal(25.0f, 0.5f, 25.0f);
|
||||||
|
rampHull.SetTransform(xf);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.position.Set(-20.0f, 20.0f, 0.0f);
|
bdef.position.Set(-20.0f, 20.0f, 0.0f);
|
||||||
bdef.orientation = b3QuatRotationZ(-0.1f * B3_PI);
|
bdef.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), -0.1f * B3_PI);
|
||||||
|
|
||||||
b3Body* ramp = m_world.CreateBody(bdef);
|
b3Body* ramp = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
@ -57,7 +64,7 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.position.Set(20.0f, 30.0f, 0.0f);
|
bdef.position.Set(20.0f, 30.0f, 0.0f);
|
||||||
bdef.orientation = b3QuatRotationZ(0.1f * B3_PI);
|
bdef.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.1f * B3_PI);
|
||||||
|
|
||||||
b3Body* ramp = m_world.CreateBody(bdef);
|
b3Body* ramp = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
@ -73,7 +80,7 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.position.Set(-20.0f, 40.0f, 0.0f);
|
bdef.position.Set(-20.0f, 40.0f, 0.0f);
|
||||||
bdef.orientation = b3QuatRotationZ(-0.1f * B3_PI);
|
bdef.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), -0.1f * B3_PI);
|
||||||
|
|
||||||
b3Body* ramp = m_world.CreateBody(bdef);
|
b3Body* ramp = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
@ -89,7 +96,7 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.position.Set(20.0f, 50.0f, 0.0f);
|
bdef.position.Set(20.0f, 50.0f, 0.0f);
|
||||||
bdef.orientation = b3QuatRotationZ(0.1f * B3_PI);
|
bdef.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.1f * B3_PI);
|
||||||
|
|
||||||
b3Body* ramp = m_world.CreateBody(bdef);
|
b3Body* ramp = m_world.CreateBody(bdef);
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@ public:
|
|||||||
bA = m_world.CreateBody(bd);
|
bA = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape shape;
|
b3CapsuleShape shape;
|
||||||
shape.m_vertex1.Set(0.0f, -3.5f, 0.0f);
|
shape.m_centers[0].Set(0.0f, -3.5f, 0.0f);
|
||||||
shape.m_vertex2.Set(0.0f, 3.5f, 0.0f);
|
shape.m_centers[1].Set(0.0f, 3.5f, 0.0f);
|
||||||
shape.m_radius = 0.5f;
|
shape.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -64,7 +64,13 @@ public:
|
|||||||
|
|
||||||
bB = m_world.CreateBody(bd);
|
bB = m_world.CreateBody(bd);
|
||||||
|
|
||||||
static b3BoxHull doorHull(2.0f, 4.0f, 0.5f);
|
static b3BoxHull doorHull;
|
||||||
|
{
|
||||||
|
b3Transform xf;
|
||||||
|
xf.position.SetZero();
|
||||||
|
xf.rotation = b3Diagonal(2.0f, 4.0f, 0.5f);
|
||||||
|
doorHull.SetTransform(xf);
|
||||||
|
}
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &doorHull;
|
hull.m_hull = &doorHull;
|
||||||
@ -80,15 +86,14 @@ public:
|
|||||||
|
|
||||||
b3WeldJointDef jd;
|
b3WeldJointDef jd;
|
||||||
jd.Initialize(bA, bB, anchor);
|
jd.Initialize(bA, bB, anchor);
|
||||||
jd.frequencyHz = 2.0f;
|
|
||||||
jd.dampingRatio = 0.3f;
|
|
||||||
|
|
||||||
b3WeldJoint* wj = (b3WeldJoint*)m_world.CreateJoint(jd);
|
b3WeldJoint* wj = (b3WeldJoint*)m_world.CreateJoint(jd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate the orientation
|
// Invalidate the orientation
|
||||||
b3Quat q = b3QuatRotationX(B3_PI);
|
b3Vec3 axis(1.0f, 0.0f, 0.0f);
|
||||||
bB->SetTransform(bB->GetPosition(), q);
|
float32 angle = B3_PI;
|
||||||
|
bB->SetTransform(bB->GetPosition(), axis, angle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,204 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 WHEEL_TEST_H
|
|
||||||
#define WHEEL_TEST_H
|
|
||||||
|
|
||||||
class WheelTest : public Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WheelTest()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
b3BodyDef bd;
|
|
||||||
b3Body* ground = m_world.CreateBody(bd);
|
|
||||||
|
|
||||||
b3HullShape hs;
|
|
||||||
hs.m_hull = &m_groundHull;
|
|
||||||
|
|
||||||
b3ShapeDef sd;
|
|
||||||
sd.shape = &hs;
|
|
||||||
|
|
||||||
ground->CreateShape(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_chassisHull.SetExtents(2.0f, 0.5f, 5.0f);
|
|
||||||
|
|
||||||
b3HullShape chassisShape;
|
|
||||||
chassisShape.m_hull = &m_chassisHull;
|
|
||||||
|
|
||||||
m_wheelHull.SetExtents(1.0f, 0.5f);
|
|
||||||
|
|
||||||
b3HullShape wheelShape;
|
|
||||||
wheelShape.m_hull = &m_wheelHull;
|
|
||||||
|
|
||||||
// Chassis
|
|
||||||
b3Body* chassis;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(0.0f, 10.0f, 0.0f);
|
|
||||||
|
|
||||||
chassis = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.3f;
|
|
||||||
sdef.shape = &chassisShape;
|
|
||||||
|
|
||||||
chassis->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Quat orientation = b3QuatRotationZ(0.5f * B3_PI);
|
|
||||||
|
|
||||||
b3Body* wheelLF;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(-1.0f, 7.0f, 4.5f);
|
|
||||||
bdef.orientation = orientation;
|
|
||||||
|
|
||||||
wheelLF = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &wheelShape;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
|
|
||||||
wheelLF->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3WheelJointDef def;
|
|
||||||
def.Initialize(chassis, wheelLF, wheelLF->GetPosition(), b3Vec3_y, b3Vec3_x);
|
|
||||||
def.motorSpeed = 0.25f * B3_PI;
|
|
||||||
def.maxMotorTorque = 1000.0f;
|
|
||||||
|
|
||||||
m_joint1 = (b3WheelJoint*)m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* wheelRF;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(1.0f, 7.0, 4.5f);
|
|
||||||
bdef.orientation = orientation;
|
|
||||||
|
|
||||||
wheelRF = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
sdef.shape = &wheelShape;
|
|
||||||
|
|
||||||
wheelRF->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3WheelJointDef def;
|
|
||||||
def.Initialize(chassis, wheelRF, wheelRF->GetPosition(), b3Vec3_y, b3Vec3_x);
|
|
||||||
def.motorSpeed = 0.25f * B3_PI;
|
|
||||||
def.maxMotorTorque = 1000.0f;
|
|
||||||
|
|
||||||
m_joint2 = (b3WheelJoint*)m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* wheelLB;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(-1.0f, 7.0f, -4.5f);
|
|
||||||
bdef.orientation = orientation;
|
|
||||||
|
|
||||||
wheelLB = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.shape = &wheelShape;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
|
|
||||||
wheelLB->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3WheelJointDef def;
|
|
||||||
def.Initialize(chassis, wheelLB, wheelLB->GetPosition(), b3Vec3_y, b3Vec3_x);
|
|
||||||
|
|
||||||
m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
b3Body* wheelRB;
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
bdef.position.Set(1.0f, 7.0f, -4.5f);
|
|
||||||
bdef.orientation = orientation;
|
|
||||||
|
|
||||||
wheelRB = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 1.0f;
|
|
||||||
sdef.shape = &wheelShape;
|
|
||||||
|
|
||||||
wheelRB->CreateShape(sdef);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
b3WheelJointDef def;
|
|
||||||
def.Initialize(chassis, wheelRB, wheelRB->GetPosition(), b3Vec3_y, b3Vec3_x);
|
|
||||||
|
|
||||||
m_world.CreateJoint(def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Step()
|
|
||||||
{
|
|
||||||
Test::Step();
|
|
||||||
|
|
||||||
g_draw->DrawString(b3Color_white, "M - Enable Motor");
|
|
||||||
g_draw->DrawString(b3Color_white, "S - Flip Motor Speed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyDown(int button)
|
|
||||||
{
|
|
||||||
if (button == GLFW_KEY_M)
|
|
||||||
{
|
|
||||||
m_joint1->EnableMotor(!m_joint1->IsMotorEnabled());
|
|
||||||
m_joint2->EnableMotor(!m_joint2->IsMotorEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button == GLFW_KEY_S)
|
|
||||||
{
|
|
||||||
m_joint1->SetMotorSpeed(-m_joint1->GetMotorSpeed());
|
|
||||||
m_joint2->SetMotorSpeed(-m_joint2->GetMotorSpeed());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Test* Create()
|
|
||||||
{
|
|
||||||
return new WheelTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
b3BoxHull m_chassisHull;
|
|
||||||
b3CylinderHull m_wheelHull;
|
|
||||||
b3WheelJoint* m_joint1;
|
|
||||||
b3WheelJoint* m_joint2;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
2
external/glad_2/glad.c
vendored
2
external/glad_2/glad.c
vendored
@ -21,7 +21,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <glad_2/glad.h>
|
#include <glad_2\glad.h>
|
||||||
|
|
||||||
static void* get_proc(const char *namez);
|
static void* get_proc(const char *namez);
|
||||||
|
|
||||||
|
165
external/glfw/CMakeLists.txt
vendored
165
external/glfw/CMakeLists.txt
vendored
@ -1,165 +0,0 @@
|
|||||||
|
|
||||||
set(common_HEADERS internal.h mappings.h
|
|
||||||
"${GLFW_BINARY_DIR}/src/glfw_config.h"
|
|
||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
|
||||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
|
|
||||||
set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
|
|
||||||
|
|
||||||
if (_GLFW_COCOA)
|
|
||||||
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
|
|
||||||
posix_thread.h nsgl_context.h egl_context.h osmesa_context.h)
|
|
||||||
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
|
||||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
|
|
||||||
nsgl_context.m egl_context.c osmesa_context.c)
|
|
||||||
elseif (_GLFW_WIN32)
|
|
||||||
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
|
|
||||||
wgl_context.h egl_context.h osmesa_context.h)
|
|
||||||
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
|
|
||||||
win32_monitor.c win32_time.c win32_thread.c win32_window.c
|
|
||||||
wgl_context.c egl_context.c osmesa_context.c)
|
|
||||||
elseif (_GLFW_X11)
|
|
||||||
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h posix_time.h
|
|
||||||
posix_thread.h glx_context.h egl_context.h osmesa_context.h)
|
|
||||||
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
|
|
||||||
xkb_unicode.c posix_time.c posix_thread.c glx_context.c
|
|
||||||
egl_context.c osmesa_context.c)
|
|
||||||
elseif (_GLFW_WAYLAND)
|
|
||||||
set(glfw_HEADERS ${common_HEADERS} wl_platform.h
|
|
||||||
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
|
|
||||||
osmesa_context.h)
|
|
||||||
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
|
|
||||||
posix_time.c posix_thread.c xkb_unicode.c
|
|
||||||
egl_context.c osmesa_context.c)
|
|
||||||
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
|
|
||||||
BASENAME xdg-shell)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
|
||||||
BASENAME xdg-decoration)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
|
|
||||||
BASENAME viewporter)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
|
||||||
BASENAME relative-pointer-unstable-v1)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
|
||||||
BASENAME pointer-constraints-unstable-v1)
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
|
||||||
PROTOCOL
|
|
||||||
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
|
||||||
BASENAME idle-inhibit-unstable-v1)
|
|
||||||
elseif (_GLFW_OSMESA)
|
|
||||||
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
|
||||||
posix_time.h posix_thread.h osmesa_context.h)
|
|
||||||
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
|
|
||||||
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (_GLFW_X11 OR _GLFW_WAYLAND)
|
|
||||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
|
||||||
set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h)
|
|
||||||
set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c)
|
|
||||||
else()
|
|
||||||
set(glfw_HEADERS ${glfw_HEADERS} null_joystick.h)
|
|
||||||
set(glfw_SOURCES ${glfw_SOURCES} null_joystick.c)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (APPLE)
|
|
||||||
# For some reason, CMake doesn't know about .m
|
|
||||||
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Make GCC and Clang warn about declarations that VS 2010 and 2012 won't accept
|
|
||||||
# for all source files that VS will build
|
|
||||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
|
|
||||||
"${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
|
|
||||||
"${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
set(windows_SOURCES ${glfw_SOURCES})
|
|
||||||
else()
|
|
||||||
set(windows_SOURCES ${common_SOURCES})
|
|
||||||
endif()
|
|
||||||
set_source_files_properties(${windows_SOURCES} PROPERTIES
|
|
||||||
COMPILE_FLAGS -Wdeclaration-after-statement)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
|
||||||
set_target_properties(glfw PROPERTIES
|
|
||||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
|
||||||
VERSION ${GLFW_VERSION}
|
|
||||||
SOVERSION ${GLFW_VERSION_MAJOR}
|
|
||||||
POSITION_INDEPENDENT_CODE ON
|
|
||||||
FOLDER "GLFW3")
|
|
||||||
|
|
||||||
target_compile_definitions(glfw PRIVATE _GLFW_USE_CONFIG_H)
|
|
||||||
target_include_directories(glfw PUBLIC
|
|
||||||
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
|
|
||||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_FULL_INCLUDEDIR}>")
|
|
||||||
target_include_directories(glfw PRIVATE
|
|
||||||
"${GLFW_SOURCE_DIR}/src"
|
|
||||||
"${GLFW_BINARY_DIR}/src"
|
|
||||||
${glfw_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
|
|
||||||
# the inclusion of stddef.h (by glfw3.h), which is itself included before
|
|
||||||
# win32_platform.h. We define them here until a saner solution can be found
|
|
||||||
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
|
|
||||||
target_compile_definitions(glfw PRIVATE
|
|
||||||
"$<$<BOOL:${MINGW}>:UNICODE;WINVER=0x0501>")
|
|
||||||
|
|
||||||
# Enable a reasonable set of warnings (no, -Wextra is not reasonable)
|
|
||||||
target_compile_options(glfw PRIVATE
|
|
||||||
"$<$<C_COMPILER_ID:AppleClang>:-Wall>"
|
|
||||||
"$<$<C_COMPILER_ID:Clang>:-Wall>"
|
|
||||||
"$<$<C_COMPILER_ID:GNU>:-Wall>")
|
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS)
|
|
||||||
if (WIN32)
|
|
||||||
if (MINGW)
|
|
||||||
# Remove the lib prefix on the DLL (but not the import library)
|
|
||||||
set_target_properties(glfw PROPERTIES PREFIX "")
|
|
||||||
|
|
||||||
# Add a suffix to the import library to avoid naming conflicts
|
|
||||||
set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.a")
|
|
||||||
else()
|
|
||||||
# Add a suffix to the import library to avoid naming conflicts
|
|
||||||
set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib")
|
|
||||||
endif()
|
|
||||||
elseif (APPLE)
|
|
||||||
# Add -fno-common to work around a bug in Apple's GCC
|
|
||||||
target_compile_options(glfw PRIVATE "-fno-common")
|
|
||||||
|
|
||||||
set_target_properties(glfw PROPERTIES
|
|
||||||
INSTALL_NAME_DIR "${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
elseif (UNIX)
|
|
||||||
# Hide symbols not explicitly tagged for export from the shared library
|
|
||||||
target_compile_options(glfw PRIVATE "-fvisibility=hidden")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_compile_definitions(glfw INTERFACE GLFW_DLL)
|
|
||||||
target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
|
|
||||||
else()
|
|
||||||
target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (MSVC)
|
|
||||||
target_compile_definitions(glfw PRIVATE _CRT_SECURE_NO_WARNINGS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (GLFW_INSTALL)
|
|
||||||
install(TARGETS glfw
|
|
||||||
EXPORT glfwTargets
|
|
||||||
RUNTIME DESTINATION "bin"
|
|
||||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
|
||||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
endif()
|
|
||||||
|
|
22
external/glfw/LICENSE.md
vendored
22
external/glfw/LICENSE.md
vendored
@ -1,22 +0,0 @@
|
|||||||
Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
528
external/glfw/cocoa_init.m
vendored
528
external/glfw/cocoa_init.m
vendored
@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 macOS - www.glfw.org
|
// GLFW 3.3 OS X - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@ -27,8 +27,8 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <sys/param.h> // For MAXPATHLEN
|
#include <sys/param.h> // For MAXPATHLEN
|
||||||
|
|
||||||
// Needed for _NSGetProgname
|
|
||||||
#include <crt_externs.h>
|
#if defined(_GLFW_USE_CHDIR)
|
||||||
|
|
||||||
// Change to our application bundle's resources directory, if present
|
// Change to our application bundle's resources directory, if present
|
||||||
//
|
//
|
||||||
@ -66,110 +66,7 @@ static void changeToResourcesDirectory(void)
|
|||||||
chdir(resourcesPath);
|
chdir(resourcesPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the menu bar (manually)
|
#endif /* _GLFW_USE_CHDIR */
|
||||||
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
|
||||||
// could go away at any moment, lots of stuff that really should be
|
|
||||||
// localize(d|able), etc. Add a nib to save us this horror.
|
|
||||||
//
|
|
||||||
static void createMenuBar(void)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
NSString* appName = nil;
|
|
||||||
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
|
|
||||||
NSString* nameKeys[] =
|
|
||||||
{
|
|
||||||
@"CFBundleDisplayName",
|
|
||||||
@"CFBundleName",
|
|
||||||
@"CFBundleExecutable",
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try to figure out what the calling application is called
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
|
|
||||||
{
|
|
||||||
id name = bundleInfo[nameKeys[i]];
|
|
||||||
if (name &&
|
|
||||||
[name isKindOfClass:[NSString class]] &&
|
|
||||||
![name isEqualToString:@""])
|
|
||||||
{
|
|
||||||
appName = name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!appName)
|
|
||||||
{
|
|
||||||
char** progname = _NSGetProgname();
|
|
||||||
if (progname && *progname)
|
|
||||||
appName = @(*progname);
|
|
||||||
else
|
|
||||||
appName = @"GLFW Application";
|
|
||||||
}
|
|
||||||
|
|
||||||
NSMenu* bar = [[NSMenu alloc] init];
|
|
||||||
[NSApp setMainMenu:bar];
|
|
||||||
|
|
||||||
NSMenuItem* appMenuItem =
|
|
||||||
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
|
||||||
NSMenu* appMenu = [[NSMenu alloc] init];
|
|
||||||
[appMenuItem setSubmenu:appMenu];
|
|
||||||
|
|
||||||
[appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
|
|
||||||
action:@selector(orderFrontStandardAboutPanel:)
|
|
||||||
keyEquivalent:@""];
|
|
||||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
|
||||||
NSMenu* servicesMenu = [[NSMenu alloc] init];
|
|
||||||
[NSApp setServicesMenu:servicesMenu];
|
|
||||||
[[appMenu addItemWithTitle:@"Services"
|
|
||||||
action:NULL
|
|
||||||
keyEquivalent:@""] setSubmenu:servicesMenu];
|
|
||||||
[servicesMenu release];
|
|
||||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
|
||||||
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
|
|
||||||
action:@selector(hide:)
|
|
||||||
keyEquivalent:@"h"];
|
|
||||||
[[appMenu addItemWithTitle:@"Hide Others"
|
|
||||||
action:@selector(hideOtherApplications:)
|
|
||||||
keyEquivalent:@"h"]
|
|
||||||
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
|
|
||||||
[appMenu addItemWithTitle:@"Show All"
|
|
||||||
action:@selector(unhideAllApplications:)
|
|
||||||
keyEquivalent:@""];
|
|
||||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
|
||||||
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
|
|
||||||
action:@selector(terminate:)
|
|
||||||
keyEquivalent:@"q"];
|
|
||||||
|
|
||||||
NSMenuItem* windowMenuItem =
|
|
||||||
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
|
||||||
[bar release];
|
|
||||||
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
|
||||||
[NSApp setWindowsMenu:windowMenu];
|
|
||||||
[windowMenuItem setSubmenu:windowMenu];
|
|
||||||
|
|
||||||
[windowMenu addItemWithTitle:@"Minimize"
|
|
||||||
action:@selector(performMiniaturize:)
|
|
||||||
keyEquivalent:@"m"];
|
|
||||||
[windowMenu addItemWithTitle:@"Zoom"
|
|
||||||
action:@selector(performZoom:)
|
|
||||||
keyEquivalent:@""];
|
|
||||||
[windowMenu addItem:[NSMenuItem separatorItem]];
|
|
||||||
[windowMenu addItemWithTitle:@"Bring All to Front"
|
|
||||||
action:@selector(arrangeInFront:)
|
|
||||||
keyEquivalent:@""];
|
|
||||||
|
|
||||||
// TODO: Make this appear at the bottom of the menu (for consistency)
|
|
||||||
[windowMenu addItem:[NSMenuItem separatorItem]];
|
|
||||||
[[windowMenu addItemWithTitle:@"Enter Full Screen"
|
|
||||||
action:@selector(toggleFullScreen:)
|
|
||||||
keyEquivalent:@"f"]
|
|
||||||
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
|
||||||
|
|
||||||
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
|
|
||||||
// to get the application menu working properly.
|
|
||||||
SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
|
|
||||||
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create key code translation tables
|
// Create key code translation tables
|
||||||
//
|
//
|
||||||
@ -177,129 +74,129 @@ static void createKeyTables(void)
|
|||||||
{
|
{
|
||||||
int scancode;
|
int scancode;
|
||||||
|
|
||||||
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
|
memset(_glfw.ns.publicKeys, -1, sizeof(_glfw.ns.publicKeys));
|
||||||
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
|
memset(_glfw.ns.nativeKeys, -1, sizeof(_glfw.ns.nativeKeys));
|
||||||
|
|
||||||
_glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
|
_glfw.ns.publicKeys[0x1D] = GLFW_KEY_0;
|
||||||
_glfw.ns.keycodes[0x12] = GLFW_KEY_1;
|
_glfw.ns.publicKeys[0x12] = GLFW_KEY_1;
|
||||||
_glfw.ns.keycodes[0x13] = GLFW_KEY_2;
|
_glfw.ns.publicKeys[0x13] = GLFW_KEY_2;
|
||||||
_glfw.ns.keycodes[0x14] = GLFW_KEY_3;
|
_glfw.ns.publicKeys[0x14] = GLFW_KEY_3;
|
||||||
_glfw.ns.keycodes[0x15] = GLFW_KEY_4;
|
_glfw.ns.publicKeys[0x15] = GLFW_KEY_4;
|
||||||
_glfw.ns.keycodes[0x17] = GLFW_KEY_5;
|
_glfw.ns.publicKeys[0x17] = GLFW_KEY_5;
|
||||||
_glfw.ns.keycodes[0x16] = GLFW_KEY_6;
|
_glfw.ns.publicKeys[0x16] = GLFW_KEY_6;
|
||||||
_glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
|
_glfw.ns.publicKeys[0x1A] = GLFW_KEY_7;
|
||||||
_glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
|
_glfw.ns.publicKeys[0x1C] = GLFW_KEY_8;
|
||||||
_glfw.ns.keycodes[0x19] = GLFW_KEY_9;
|
_glfw.ns.publicKeys[0x19] = GLFW_KEY_9;
|
||||||
_glfw.ns.keycodes[0x00] = GLFW_KEY_A;
|
_glfw.ns.publicKeys[0x00] = GLFW_KEY_A;
|
||||||
_glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
|
_glfw.ns.publicKeys[0x0B] = GLFW_KEY_B;
|
||||||
_glfw.ns.keycodes[0x08] = GLFW_KEY_C;
|
_glfw.ns.publicKeys[0x08] = GLFW_KEY_C;
|
||||||
_glfw.ns.keycodes[0x02] = GLFW_KEY_D;
|
_glfw.ns.publicKeys[0x02] = GLFW_KEY_D;
|
||||||
_glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
|
_glfw.ns.publicKeys[0x0E] = GLFW_KEY_E;
|
||||||
_glfw.ns.keycodes[0x03] = GLFW_KEY_F;
|
_glfw.ns.publicKeys[0x03] = GLFW_KEY_F;
|
||||||
_glfw.ns.keycodes[0x05] = GLFW_KEY_G;
|
_glfw.ns.publicKeys[0x05] = GLFW_KEY_G;
|
||||||
_glfw.ns.keycodes[0x04] = GLFW_KEY_H;
|
_glfw.ns.publicKeys[0x04] = GLFW_KEY_H;
|
||||||
_glfw.ns.keycodes[0x22] = GLFW_KEY_I;
|
_glfw.ns.publicKeys[0x22] = GLFW_KEY_I;
|
||||||
_glfw.ns.keycodes[0x26] = GLFW_KEY_J;
|
_glfw.ns.publicKeys[0x26] = GLFW_KEY_J;
|
||||||
_glfw.ns.keycodes[0x28] = GLFW_KEY_K;
|
_glfw.ns.publicKeys[0x28] = GLFW_KEY_K;
|
||||||
_glfw.ns.keycodes[0x25] = GLFW_KEY_L;
|
_glfw.ns.publicKeys[0x25] = GLFW_KEY_L;
|
||||||
_glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
|
_glfw.ns.publicKeys[0x2E] = GLFW_KEY_M;
|
||||||
_glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
|
_glfw.ns.publicKeys[0x2D] = GLFW_KEY_N;
|
||||||
_glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
|
_glfw.ns.publicKeys[0x1F] = GLFW_KEY_O;
|
||||||
_glfw.ns.keycodes[0x23] = GLFW_KEY_P;
|
_glfw.ns.publicKeys[0x23] = GLFW_KEY_P;
|
||||||
_glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
|
_glfw.ns.publicKeys[0x0C] = GLFW_KEY_Q;
|
||||||
_glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
|
_glfw.ns.publicKeys[0x0F] = GLFW_KEY_R;
|
||||||
_glfw.ns.keycodes[0x01] = GLFW_KEY_S;
|
_glfw.ns.publicKeys[0x01] = GLFW_KEY_S;
|
||||||
_glfw.ns.keycodes[0x11] = GLFW_KEY_T;
|
_glfw.ns.publicKeys[0x11] = GLFW_KEY_T;
|
||||||
_glfw.ns.keycodes[0x20] = GLFW_KEY_U;
|
_glfw.ns.publicKeys[0x20] = GLFW_KEY_U;
|
||||||
_glfw.ns.keycodes[0x09] = GLFW_KEY_V;
|
_glfw.ns.publicKeys[0x09] = GLFW_KEY_V;
|
||||||
_glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
|
_glfw.ns.publicKeys[0x0D] = GLFW_KEY_W;
|
||||||
_glfw.ns.keycodes[0x07] = GLFW_KEY_X;
|
_glfw.ns.publicKeys[0x07] = GLFW_KEY_X;
|
||||||
_glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
|
_glfw.ns.publicKeys[0x10] = GLFW_KEY_Y;
|
||||||
_glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
|
_glfw.ns.publicKeys[0x06] = GLFW_KEY_Z;
|
||||||
|
|
||||||
_glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
|
_glfw.ns.publicKeys[0x27] = GLFW_KEY_APOSTROPHE;
|
||||||
_glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
|
_glfw.ns.publicKeys[0x2A] = GLFW_KEY_BACKSLASH;
|
||||||
_glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
|
_glfw.ns.publicKeys[0x2B] = GLFW_KEY_COMMA;
|
||||||
_glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
|
_glfw.ns.publicKeys[0x18] = GLFW_KEY_EQUAL;
|
||||||
_glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
|
_glfw.ns.publicKeys[0x32] = GLFW_KEY_GRAVE_ACCENT;
|
||||||
_glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
|
_glfw.ns.publicKeys[0x21] = GLFW_KEY_LEFT_BRACKET;
|
||||||
_glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
|
_glfw.ns.publicKeys[0x1B] = GLFW_KEY_MINUS;
|
||||||
_glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
|
_glfw.ns.publicKeys[0x2F] = GLFW_KEY_PERIOD;
|
||||||
_glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
|
_glfw.ns.publicKeys[0x1E] = GLFW_KEY_RIGHT_BRACKET;
|
||||||
_glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
|
_glfw.ns.publicKeys[0x29] = GLFW_KEY_SEMICOLON;
|
||||||
_glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
|
_glfw.ns.publicKeys[0x2C] = GLFW_KEY_SLASH;
|
||||||
_glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
|
_glfw.ns.publicKeys[0x0A] = GLFW_KEY_WORLD_1;
|
||||||
|
|
||||||
_glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
|
_glfw.ns.publicKeys[0x33] = GLFW_KEY_BACKSPACE;
|
||||||
_glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
|
_glfw.ns.publicKeys[0x39] = GLFW_KEY_CAPS_LOCK;
|
||||||
_glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
|
_glfw.ns.publicKeys[0x75] = GLFW_KEY_DELETE;
|
||||||
_glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
|
_glfw.ns.publicKeys[0x7D] = GLFW_KEY_DOWN;
|
||||||
_glfw.ns.keycodes[0x77] = GLFW_KEY_END;
|
_glfw.ns.publicKeys[0x77] = GLFW_KEY_END;
|
||||||
_glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
|
_glfw.ns.publicKeys[0x24] = GLFW_KEY_ENTER;
|
||||||
_glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
|
_glfw.ns.publicKeys[0x35] = GLFW_KEY_ESCAPE;
|
||||||
_glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
|
_glfw.ns.publicKeys[0x7A] = GLFW_KEY_F1;
|
||||||
_glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
|
_glfw.ns.publicKeys[0x78] = GLFW_KEY_F2;
|
||||||
_glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
|
_glfw.ns.publicKeys[0x63] = GLFW_KEY_F3;
|
||||||
_glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
|
_glfw.ns.publicKeys[0x76] = GLFW_KEY_F4;
|
||||||
_glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
|
_glfw.ns.publicKeys[0x60] = GLFW_KEY_F5;
|
||||||
_glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
|
_glfw.ns.publicKeys[0x61] = GLFW_KEY_F6;
|
||||||
_glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
|
_glfw.ns.publicKeys[0x62] = GLFW_KEY_F7;
|
||||||
_glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
|
_glfw.ns.publicKeys[0x64] = GLFW_KEY_F8;
|
||||||
_glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
|
_glfw.ns.publicKeys[0x65] = GLFW_KEY_F9;
|
||||||
_glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
|
_glfw.ns.publicKeys[0x6D] = GLFW_KEY_F10;
|
||||||
_glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
|
_glfw.ns.publicKeys[0x67] = GLFW_KEY_F11;
|
||||||
_glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
|
_glfw.ns.publicKeys[0x6F] = GLFW_KEY_F12;
|
||||||
_glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
|
_glfw.ns.publicKeys[0x69] = GLFW_KEY_F13;
|
||||||
_glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
|
_glfw.ns.publicKeys[0x6B] = GLFW_KEY_F14;
|
||||||
_glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
|
_glfw.ns.publicKeys[0x71] = GLFW_KEY_F15;
|
||||||
_glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
|
_glfw.ns.publicKeys[0x6A] = GLFW_KEY_F16;
|
||||||
_glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
|
_glfw.ns.publicKeys[0x40] = GLFW_KEY_F17;
|
||||||
_glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
|
_glfw.ns.publicKeys[0x4F] = GLFW_KEY_F18;
|
||||||
_glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
|
_glfw.ns.publicKeys[0x50] = GLFW_KEY_F19;
|
||||||
_glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
|
_glfw.ns.publicKeys[0x5A] = GLFW_KEY_F20;
|
||||||
_glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
|
_glfw.ns.publicKeys[0x73] = GLFW_KEY_HOME;
|
||||||
_glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
|
_glfw.ns.publicKeys[0x72] = GLFW_KEY_INSERT;
|
||||||
_glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
|
_glfw.ns.publicKeys[0x7B] = GLFW_KEY_LEFT;
|
||||||
_glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
|
_glfw.ns.publicKeys[0x3A] = GLFW_KEY_LEFT_ALT;
|
||||||
_glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
|
_glfw.ns.publicKeys[0x3B] = GLFW_KEY_LEFT_CONTROL;
|
||||||
_glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
|
_glfw.ns.publicKeys[0x38] = GLFW_KEY_LEFT_SHIFT;
|
||||||
_glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
|
_glfw.ns.publicKeys[0x37] = GLFW_KEY_LEFT_SUPER;
|
||||||
_glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
|
_glfw.ns.publicKeys[0x6E] = GLFW_KEY_MENU;
|
||||||
_glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
|
_glfw.ns.publicKeys[0x47] = GLFW_KEY_NUM_LOCK;
|
||||||
_glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
|
_glfw.ns.publicKeys[0x79] = GLFW_KEY_PAGE_DOWN;
|
||||||
_glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
|
_glfw.ns.publicKeys[0x74] = GLFW_KEY_PAGE_UP;
|
||||||
_glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
|
_glfw.ns.publicKeys[0x7C] = GLFW_KEY_RIGHT;
|
||||||
_glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
|
_glfw.ns.publicKeys[0x3D] = GLFW_KEY_RIGHT_ALT;
|
||||||
_glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
|
_glfw.ns.publicKeys[0x3E] = GLFW_KEY_RIGHT_CONTROL;
|
||||||
_glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
|
_glfw.ns.publicKeys[0x3C] = GLFW_KEY_RIGHT_SHIFT;
|
||||||
_glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
|
_glfw.ns.publicKeys[0x36] = GLFW_KEY_RIGHT_SUPER;
|
||||||
_glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
|
_glfw.ns.publicKeys[0x31] = GLFW_KEY_SPACE;
|
||||||
_glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
|
_glfw.ns.publicKeys[0x30] = GLFW_KEY_TAB;
|
||||||
_glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
|
_glfw.ns.publicKeys[0x7E] = GLFW_KEY_UP;
|
||||||
|
|
||||||
_glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
|
_glfw.ns.publicKeys[0x52] = GLFW_KEY_KP_0;
|
||||||
_glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
|
_glfw.ns.publicKeys[0x53] = GLFW_KEY_KP_1;
|
||||||
_glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
|
_glfw.ns.publicKeys[0x54] = GLFW_KEY_KP_2;
|
||||||
_glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
|
_glfw.ns.publicKeys[0x55] = GLFW_KEY_KP_3;
|
||||||
_glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
|
_glfw.ns.publicKeys[0x56] = GLFW_KEY_KP_4;
|
||||||
_glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
|
_glfw.ns.publicKeys[0x57] = GLFW_KEY_KP_5;
|
||||||
_glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
|
_glfw.ns.publicKeys[0x58] = GLFW_KEY_KP_6;
|
||||||
_glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
|
_glfw.ns.publicKeys[0x59] = GLFW_KEY_KP_7;
|
||||||
_glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
|
_glfw.ns.publicKeys[0x5B] = GLFW_KEY_KP_8;
|
||||||
_glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
|
_glfw.ns.publicKeys[0x5C] = GLFW_KEY_KP_9;
|
||||||
_glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
|
_glfw.ns.publicKeys[0x45] = GLFW_KEY_KP_ADD;
|
||||||
_glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
|
_glfw.ns.publicKeys[0x41] = GLFW_KEY_KP_DECIMAL;
|
||||||
_glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
|
_glfw.ns.publicKeys[0x4B] = GLFW_KEY_KP_DIVIDE;
|
||||||
_glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
|
_glfw.ns.publicKeys[0x4C] = GLFW_KEY_KP_ENTER;
|
||||||
_glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
|
_glfw.ns.publicKeys[0x51] = GLFW_KEY_KP_EQUAL;
|
||||||
_glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
|
_glfw.ns.publicKeys[0x43] = GLFW_KEY_KP_MULTIPLY;
|
||||||
_glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
|
_glfw.ns.publicKeys[0x4E] = GLFW_KEY_KP_SUBTRACT;
|
||||||
|
|
||||||
for (scancode = 0; scancode < 256; scancode++)
|
for (scancode = 0; scancode < 256; scancode++)
|
||||||
{
|
{
|
||||||
// Store the reverse translation for faster key name lookup
|
// Store the reverse translation for faster key name lookup
|
||||||
if (_glfw.ns.keycodes[scancode] >= 0)
|
if (_glfw.ns.publicKeys[scancode] >= 0)
|
||||||
_glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
|
_glfw.ns.nativeKeys[_glfw.ns.publicKeys[scancode]] = scancode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,9 +219,8 @@ static GLFWbool updateUnicodeDataNS(void)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.ns.unicodeData =
|
_glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,
|
||||||
TISGetInputSourceProperty(_glfw.ns.inputSource,
|
kTISPropertyUnicodeKeyLayoutData);
|
||||||
kTISPropertyUnicodeKeyLayoutData);
|
|
||||||
if (!_glfw.ns.unicodeData)
|
if (!_glfw.ns.unicodeData)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@ -340,8 +236,7 @@ static GLFWbool updateUnicodeDataNS(void)
|
|||||||
static GLFWbool initializeTIS(void)
|
static GLFWbool initializeTIS(void)
|
||||||
{
|
{
|
||||||
// This works only because Cocoa has already loaded it properly
|
// This works only because Cocoa has already loaded it properly
|
||||||
_glfw.ns.tis.bundle =
|
_glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
|
||||||
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
|
|
||||||
if (!_glfw.ns.tis.bundle)
|
if (!_glfw.ns.tis.bundle)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@ -352,6 +247,9 @@ static GLFWbool initializeTIS(void)
|
|||||||
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
||||||
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
||||||
CFSTR("kTISPropertyUnicodeKeyLayoutData"));
|
CFSTR("kTISPropertyUnicodeKeyLayoutData"));
|
||||||
|
CFStringRef* kNotifySelectedKeyboardInputSourceChanged =
|
||||||
|
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
||||||
|
CFSTR("kTISNotifySelectedKeyboardInputSourceChanged"));
|
||||||
_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
|
_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
|
||||||
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||||
CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
|
CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
|
||||||
@ -363,6 +261,7 @@ static GLFWbool initializeTIS(void)
|
|||||||
CFSTR("LMGetKbdType"));
|
CFSTR("LMGetKbdType"));
|
||||||
|
|
||||||
if (!kPropertyUnicodeKeyLayoutData ||
|
if (!kPropertyUnicodeKeyLayoutData ||
|
||||||
|
!kNotifySelectedKeyboardInputSourceChanged ||
|
||||||
!TISCopyCurrentKeyboardLayoutInputSource ||
|
!TISCopyCurrentKeyboardLayoutInputSource ||
|
||||||
!TISGetInputSourceProperty ||
|
!TISGetInputSourceProperty ||
|
||||||
!LMGetKbdType)
|
!LMGetKbdType)
|
||||||
@ -374,93 +273,24 @@ static GLFWbool initializeTIS(void)
|
|||||||
|
|
||||||
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
|
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
|
||||||
*kPropertyUnicodeKeyLayoutData;
|
*kPropertyUnicodeKeyLayoutData;
|
||||||
|
_glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged =
|
||||||
|
*kNotifySelectedKeyboardInputSourceChanged;
|
||||||
|
|
||||||
return updateUnicodeDataNS();
|
return updateUnicodeDataNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@interface GLFWHelper : NSObject
|
@interface GLFWLayoutListener : NSObject
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GLFWHelper
|
@implementation GLFWLayoutListener
|
||||||
|
|
||||||
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
||||||
{
|
{
|
||||||
updateUnicodeDataNS();
|
updateUnicodeDataNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)doNothing:(id)object
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@end // GLFWHelper
|
|
||||||
|
|
||||||
@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GLFWApplicationDelegate
|
|
||||||
|
|
||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
|
||||||
{
|
|
||||||
_GLFWwindow* window;
|
|
||||||
|
|
||||||
for (window = _glfw.windowListHead; window; window = window->next)
|
|
||||||
_glfwInputWindowCloseRequest(window);
|
|
||||||
|
|
||||||
return NSTerminateCancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
|
|
||||||
{
|
|
||||||
_GLFWwindow* window;
|
|
||||||
|
|
||||||
for (window = _glfw.windowListHead; window; window = window->next)
|
|
||||||
{
|
|
||||||
if (window->context.client != GLFW_NO_API)
|
|
||||||
[window->context.nsgl.object update];
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPollMonitorsNS();
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationWillFinishLaunching:(NSNotification *)notification
|
|
||||||
{
|
|
||||||
if (_glfw.hints.init.ns.menubar)
|
|
||||||
{
|
|
||||||
// In case we are unbundled, make us a proper UI application
|
|
||||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
|
||||||
|
|
||||||
// Menu bar setup must go between sharedApplication above and
|
|
||||||
// finishLaunching below, in order to properly emulate the behavior
|
|
||||||
// of NSApplicationMain
|
|
||||||
|
|
||||||
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
|
||||||
{
|
|
||||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
|
|
||||||
owner:NSApp
|
|
||||||
topLevelObjects:&_glfw.ns.nibObjects];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
createMenuBar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
|
||||||
{
|
|
||||||
[NSApp stop:nil];
|
|
||||||
|
|
||||||
_glfwPlatformPostEmptyEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationDidHide:(NSNotification *)notification
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < _glfw.monitorCount; i++)
|
|
||||||
_glfwRestoreVideoModeNS(_glfw.monitors[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@end // GLFWApplicationDelegate
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
@ -468,54 +298,19 @@ static GLFWbool initializeTIS(void)
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
||||||
|
[[NSDistributedNotificationCenter defaultCenter]
|
||||||
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
addObserver:_glfw.ns.listener
|
||||||
toTarget:_glfw.ns.helper
|
|
||||||
withObject:nil];
|
|
||||||
|
|
||||||
if (NSApp)
|
|
||||||
_glfw.ns.finishedLaunching = GLFW_TRUE;
|
|
||||||
|
|
||||||
[NSApplication sharedApplication];
|
|
||||||
|
|
||||||
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
|
||||||
if (_glfw.ns.delegate == nil)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Cocoa: Failed to create application delegate");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
[NSApp setDelegate:_glfw.ns.delegate];
|
|
||||||
|
|
||||||
NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
|
||||||
{
|
|
||||||
if ([event modifierFlags] & NSEventModifierFlagCommand)
|
|
||||||
[[NSApp keyWindow] sendEvent:event];
|
|
||||||
|
|
||||||
return event;
|
|
||||||
};
|
|
||||||
|
|
||||||
_glfw.ns.keyUpMonitor =
|
|
||||||
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
|
|
||||||
handler:block];
|
|
||||||
|
|
||||||
if (_glfw.hints.init.ns.chdir)
|
|
||||||
changeToResourcesDirectory();
|
|
||||||
|
|
||||||
// Press and Hold prevents some keys from emitting repeated characters
|
|
||||||
NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
|
|
||||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver:_glfw.ns.helper
|
|
||||||
selector:@selector(selectedKeyboardInputSourceChanged:)
|
selector:@selector(selectedKeyboardInputSourceChanged:)
|
||||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
|
#if defined(_GLFW_USE_CHDIR)
|
||||||
|
changeToResourcesDirectory();
|
||||||
|
#endif
|
||||||
|
|
||||||
createKeyTables();
|
createKeyTables();
|
||||||
|
|
||||||
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||||
@ -527,19 +322,17 @@ int _glfwPlatformInit(void)
|
|||||||
if (!initializeTIS())
|
if (!initializeTIS())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
_glfwInitTimerNS();
|
_glfwInitTimerNS();
|
||||||
_glfwInitJoysticksNS();
|
_glfwInitJoysticksNS();
|
||||||
|
|
||||||
_glfwPollMonitorsNS();
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
|
||||||
} // autoreleasepool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
|
||||||
|
|
||||||
if (_glfw.ns.inputSource)
|
if (_glfw.ns.inputSource)
|
||||||
{
|
{
|
||||||
CFRelease(_glfw.ns.inputSource);
|
CFRelease(_glfw.ns.inputSource);
|
||||||
@ -560,32 +353,43 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.ns.delegate = nil;
|
_glfw.ns.delegate = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.ns.helper)
|
if (_glfw.ns.listener)
|
||||||
{
|
{
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSDistributedNotificationCenter defaultCenter]
|
||||||
removeObserver:_glfw.ns.helper
|
removeObserver:_glfw.ns.listener
|
||||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
|
||||||
object:nil];
|
object:nil];
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSDistributedNotificationCenter defaultCenter]
|
||||||
removeObserver:_glfw.ns.helper];
|
removeObserver:_glfw.ns.listener];
|
||||||
[_glfw.ns.helper release];
|
[_glfw.ns.listener release];
|
||||||
_glfw.ns.helper = nil;
|
_glfw.ns.listener = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.ns.keyUpMonitor)
|
[_glfw.ns.cursor release];
|
||||||
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
_glfw.ns.cursor = nil;
|
||||||
|
|
||||||
free(_glfw.ns.clipboardString);
|
free(_glfw.ns.clipboardString);
|
||||||
|
|
||||||
_glfwTerminateNSGL();
|
_glfwTerminateNSGL();
|
||||||
_glfwTerminateJoysticksNS();
|
_glfwTerminateJoysticksNS();
|
||||||
|
_glfwTerminateThreadLocalStoragePOSIX();
|
||||||
|
|
||||||
} // autoreleasepool
|
[_glfw.ns.autoreleasePool release];
|
||||||
|
_glfw.ns.autoreleasePool = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa"
|
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
|
||||||
|
#if defined(_GLFW_USE_CHDIR)
|
||||||
|
" chdir"
|
||||||
|
#endif
|
||||||
|
#if defined(_GLFW_USE_MENUBAR)
|
||||||
|
" menubar"
|
||||||
|
#endif
|
||||||
|
#if defined(_GLFW_USE_RETINA)
|
||||||
|
" retina"
|
||||||
|
#endif
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" dynamic"
|
" dynamic"
|
||||||
#endif
|
#endif
|
||||||
|
26
external/glfw/cocoa_joystick.h
vendored
26
external/glfw/cocoa_joystick.h
vendored
@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Cocoa - www.glfw.org
|
// GLFW 3.3 Cocoa - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@ -24,27 +24,37 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
|
#ifndef _glfw3_cocoa_joystick_h_
|
||||||
|
#define _glfw3_cocoa_joystick_h_
|
||||||
|
|
||||||
#include <IOKit/IOKitLib.h>
|
#include <IOKit/IOKitLib.h>
|
||||||
#include <IOKit/IOCFPlugIn.h>
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
#include <IOKit/hid/IOHIDLib.h>
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
#include <IOKit/hid/IOHIDKeys.h>
|
#include <IOKit/hid/IOHIDKeys.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
_GLFWjoystickNS ns_js[GLFW_JOYSTICK_LAST + 1]
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
|
|
||||||
|
|
||||||
// Cocoa-specific per-joystick data
|
// Cocoa-specific per-joystick data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoystickNS
|
typedef struct _GLFWjoystickNS
|
||||||
{
|
{
|
||||||
IOHIDDeviceRef device;
|
GLFWbool present;
|
||||||
CFMutableArrayRef axes;
|
char name[256];
|
||||||
CFMutableArrayRef buttons;
|
|
||||||
CFMutableArrayRef hats;
|
IOHIDDeviceRef deviceRef;
|
||||||
|
|
||||||
|
CFMutableArrayRef axisElements;
|
||||||
|
CFMutableArrayRef buttonElements;
|
||||||
|
CFMutableArrayRef hatElements;
|
||||||
|
|
||||||
|
float* axes;
|
||||||
|
unsigned char* buttons;
|
||||||
} _GLFWjoystickNS;
|
} _GLFWjoystickNS;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitJoysticksNS(void);
|
void _glfwInitJoysticksNS(void);
|
||||||
void _glfwTerminateJoysticksNS(void);
|
void _glfwTerminateJoysticksNS(void);
|
||||||
|
|
||||||
|
#endif // _glfw3_cocoa_joystick_h_
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user