Compare commits
1 Commits
bounce-upg
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
9f8dcae52a |
@ -1,2 +0,0 @@
|
|||||||
cd ..\
|
|
||||||
premake5 solution_vs2019
|
|
Binary file not shown.
@ -58,7 +58,7 @@ PROJECT_LOGO =
|
|||||||
# entered, it will be relative to the location where doxygen was started. If
|
# entered, it will be relative to the location where doxygen was started. If
|
||||||
# left blank the current directory will be used.
|
# left blank the current directory will be used.
|
||||||
|
|
||||||
OUTPUT_DIRECTORY = api
|
OUTPUT_DIRECTORY = doc/api
|
||||||
|
|
||||||
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
|
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
|
||||||
# directories (in 2 levels) under the output directory of each output format and
|
# directories (in 2 levels) under the output directory of each output format and
|
@ -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,7 +59,13 @@ 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;
|
||||||
@ -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,19 +35,8 @@ 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;
|
||||||
}
|
}
|
||||||
@ -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 B = GetPointB();
|
|
||||||
|
|
||||||
if (m_staticDrag)
|
|
||||||
{
|
|
||||||
b3Vec3 A = GetPointA();
|
b3Vec3 A = GetPointA();
|
||||||
|
b3Vec3 B = GetPointB();
|
||||||
|
|
||||||
b3Vec3 dx = B - A;
|
b3Vec3 dx = B - A;
|
||||||
|
|
||||||
m_p1->ApplyTranslation(dx);
|
if (m_staticDrag)
|
||||||
m_p2->ApplyTranslation(dx);
|
{
|
||||||
m_p3->ApplyTranslation(dx);
|
b3Particle* p1 = m_cloth->GetParticle(m_triangle->v1);
|
||||||
|
p1->ApplyTranslation(dx);
|
||||||
|
|
||||||
|
b3Particle* p2 = m_cloth->GetParticle(m_triangle->v2);
|
||||||
|
p2->ApplyTranslation(dx);
|
||||||
|
|
||||||
|
b3Particle* p3 = m_cloth->GetParticle(m_triangle->v3);
|
||||||
|
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;
|
||||||
|
u32 m_triangleIndex;
|
||||||
|
b3ClothMeshTriangle* m_triangle;
|
||||||
|
float32 m_u, m_v;
|
||||||
|
|
||||||
bool m_isDragging;
|
float32 m_km;
|
||||||
b3ClothParticle* m_p1;
|
float32 m_kd;
|
||||||
b3ClothParticle* m_p2;
|
b3Particle* m_particle;
|
||||||
b3ClothParticle* m_p3;
|
|
||||||
scalar m_u, m_v;
|
|
||||||
|
|
||||||
scalar m_km;
|
|
||||||
scalar m_kd;
|
|
||||||
b3ClothParticle* 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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -20,16 +20,13 @@
|
|||||||
#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;
|
||||||
@ -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-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);
|
||||||
|
}
|
||||||
|
|
||||||
// Left to right lines
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
110
examples/testbed/framework/profiler.cpp
Normal file
110
examples/testbed/framework/profiler.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <testbed/framework/profiler.h>
|
||||||
|
|
||||||
|
Profiler* g_profiler = nullptr;
|
||||||
|
|
||||||
|
Profiler::Profiler() : m_pool(sizeof(ProfilerNode))
|
||||||
|
{
|
||||||
|
m_root = nullptr;
|
||||||
|
m_top = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler::~Profiler()
|
||||||
|
{
|
||||||
|
assert(m_root == nullptr);
|
||||||
|
assert(m_top == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilerNode* Profiler::CreateNode()
|
||||||
|
{
|
||||||
|
void* block = m_pool.Allocate();
|
||||||
|
ProfilerNode* n = new (block) ProfilerNode();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profiler::DestroyNode(ProfilerNode* node)
|
||||||
|
{
|
||||||
|
node->~ProfilerNode();
|
||||||
|
m_pool.Free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profiler::BeginScope(const char* name)
|
||||||
|
{
|
||||||
|
m_time.Update();
|
||||||
|
|
||||||
|
ProfilerNode* n = CreateNode();
|
||||||
|
n->name = name;
|
||||||
|
n->t0 = m_time.GetCurrentMilis();
|
||||||
|
n->t1 = 0.0;
|
||||||
|
n->parent = m_top;
|
||||||
|
|
||||||
|
if (m_root == nullptr)
|
||||||
|
{
|
||||||
|
m_root = n;
|
||||||
|
m_top = n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_top)
|
||||||
|
{
|
||||||
|
m_top->children.PushBack(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_top = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profiler::EndScope()
|
||||||
|
{
|
||||||
|
m_time.Update();
|
||||||
|
|
||||||
|
assert(m_top != nullptr);
|
||||||
|
m_top->t1 = m_time.GetCurrentMilis();
|
||||||
|
assert(m_top->t1 > m_top->t0);
|
||||||
|
|
||||||
|
m_top = m_top->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profiler::Begin()
|
||||||
|
{
|
||||||
|
// If this assert is hit then it means Profiler::End hasn't been called.
|
||||||
|
assert(m_root == nullptr);
|
||||||
|
assert(m_top == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profiler::RecurseDestroyNode(ProfilerNode* node)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||||
|
{
|
||||||
|
RecurseDestroyNode(node->children[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profiler::End()
|
||||||
|
{
|
||||||
|
assert(m_top == nullptr);
|
||||||
|
|
||||||
|
if (m_root)
|
||||||
|
{
|
||||||
|
RecurseDestroyNode(m_root);
|
||||||
|
m_root = nullptr;
|
||||||
|
}
|
||||||
|
}
|
73
examples/testbed/framework/profiler.h
Normal file
73
examples/testbed/framework/profiler.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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 PROFILER_H
|
||||||
|
#define PROFILER_H
|
||||||
|
|
||||||
|
#include <bounce/common/math/math.h>
|
||||||
|
#include <bounce/common/memory/block_pool.h>
|
||||||
|
#include <bounce/common/template/array.h>
|
||||||
|
#include <bounce/common/time.h>
|
||||||
|
|
||||||
|
// Profiler node
|
||||||
|
struct ProfilerNode
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
float64 t0;
|
||||||
|
float64 t1;
|
||||||
|
ProfilerNode* parent;
|
||||||
|
b3StackArray<ProfilerNode*, 32> children;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A single-threaded profiler.
|
||||||
|
class Profiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Profiler();
|
||||||
|
|
||||||
|
~Profiler();
|
||||||
|
|
||||||
|
// Must be called before profiling.
|
||||||
|
void Begin();
|
||||||
|
|
||||||
|
// Must be called after profiling.
|
||||||
|
void End();
|
||||||
|
|
||||||
|
// Begin a new scope.
|
||||||
|
void BeginScope(const char* name);
|
||||||
|
|
||||||
|
// End the top scope.
|
||||||
|
void EndScope();
|
||||||
|
|
||||||
|
// Get the root profiler node.
|
||||||
|
ProfilerNode* GetRoot() { return m_root; }
|
||||||
|
private:
|
||||||
|
ProfilerNode* CreateNode();
|
||||||
|
void DestroyNode(ProfilerNode* node);
|
||||||
|
|
||||||
|
void RecurseDestroyNode(ProfilerNode* node);
|
||||||
|
|
||||||
|
b3BlockPool m_pool; // pool of nodes
|
||||||
|
b3Time m_time; // timer
|
||||||
|
ProfilerNode* m_root; // tree root node
|
||||||
|
ProfilerNode* m_top; // top node
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Profiler* g_profiler;
|
||||||
|
|
||||||
|
#endif
|
197
examples/testbed/framework/profiler_st.cpp
Normal file
197
examples/testbed/framework/profiler_st.cpp
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <testbed/framework/profiler_st.h>
|
||||||
|
|
||||||
|
ProfilerSt* g_profilerSt = nullptr;
|
||||||
|
|
||||||
|
ProfilerSt::ProfilerSt() : m_pool(sizeof(ProfilerStNode))
|
||||||
|
{
|
||||||
|
m_root = nullptr;
|
||||||
|
m_top = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilerSt::~ProfilerSt()
|
||||||
|
{
|
||||||
|
assert(m_root == nullptr);
|
||||||
|
assert(m_top == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilerStNodeStat* ProfilerSt::FindStat(const char* name)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < m_stats.Count(); ++i)
|
||||||
|
{
|
||||||
|
if (m_stats[i].name == name)
|
||||||
|
{
|
||||||
|
return &m_stats[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilerStNodeStat* ProfilerSt::CreateStat()
|
||||||
|
{
|
||||||
|
m_stats.PushBack(ProfilerStNodeStat());
|
||||||
|
return &m_stats.Back();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilerStNode* ProfilerSt::CreateNode()
|
||||||
|
{
|
||||||
|
void* block = m_pool.Allocate();
|
||||||
|
return new (block) ProfilerStNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfilerSt::DestroyNode(ProfilerStNode* node)
|
||||||
|
{
|
||||||
|
node->~ProfilerStNode();
|
||||||
|
m_pool.Free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfilerSt::RecurseDestroyNode(ProfilerStNode* node)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < node->children.Count(); ++i)
|
||||||
|
{
|
||||||
|
return RecurseDestroyNode(node->children[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ProfilerStNode* RecurseFindNode(ProfilerStNode* node, const char* name)
|
||||||
|
{
|
||||||
|
if (node->name == name)
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilerStNode* result = nullptr;
|
||||||
|
for (u32 i = 0; result == nullptr && i < node->children.Count(); ++i)
|
||||||
|
{
|
||||||
|
result = RecurseFindNode(node->children[i], name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilerStNode* ProfilerSt::FindNode(const char* name)
|
||||||
|
{
|
||||||
|
if (m_top)
|
||||||
|
{
|
||||||
|
return RecurseFindNode(m_top, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_root)
|
||||||
|
{
|
||||||
|
return RecurseFindNode(m_root, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfilerSt::BeginScope(const char* name)
|
||||||
|
{
|
||||||
|
ProfilerStNode* fn = FindNode(name);
|
||||||
|
|
||||||
|
if (fn)
|
||||||
|
{
|
||||||
|
m_time.Update();
|
||||||
|
fn->t0 = m_time.GetCurrentMilis();
|
||||||
|
++fn->callCount;
|
||||||
|
m_top = fn;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_time.Update();
|
||||||
|
|
||||||
|
ProfilerStNode* n = CreateNode();
|
||||||
|
n->name = name;
|
||||||
|
n->t0 = m_time.GetCurrentMilis();
|
||||||
|
n->elapsed = 0.0f;
|
||||||
|
n->callCount = 1;
|
||||||
|
n->parent = m_top;
|
||||||
|
n->stat = nullptr;
|
||||||
|
|
||||||
|
if (m_root == nullptr)
|
||||||
|
{
|
||||||
|
m_root = n;
|
||||||
|
m_top = n;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_top)
|
||||||
|
{
|
||||||
|
m_top->children.PushBack(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_top = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfilerSt::EndScope()
|
||||||
|
{
|
||||||
|
assert(m_top != nullptr);
|
||||||
|
|
||||||
|
m_time.Update();
|
||||||
|
|
||||||
|
m_top->t1 = m_time.GetCurrentMilis();
|
||||||
|
|
||||||
|
float64 elapsedTime = m_top->t1 - m_top->t0;
|
||||||
|
|
||||||
|
m_top->elapsed += elapsedTime;
|
||||||
|
|
||||||
|
ProfilerStNodeStat* stat = FindStat(m_top->name);
|
||||||
|
|
||||||
|
if (stat == nullptr)
|
||||||
|
{
|
||||||
|
stat = CreateStat();
|
||||||
|
stat->name = m_top->name;
|
||||||
|
stat->minElapsed = elapsedTime;
|
||||||
|
stat->maxElapsed = elapsedTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stat->minElapsed = b3Min(stat->minElapsed, elapsedTime);
|
||||||
|
stat->maxElapsed = b3Max(stat->maxElapsed, elapsedTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_top->stat == nullptr)
|
||||||
|
{
|
||||||
|
m_top->stat = stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(m_top->stat == stat);
|
||||||
|
|
||||||
|
m_top = m_top->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfilerSt::Begin()
|
||||||
|
{
|
||||||
|
assert(m_top == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfilerSt::End()
|
||||||
|
{
|
||||||
|
assert(m_top == nullptr);
|
||||||
|
|
||||||
|
if (m_root)
|
||||||
|
{
|
||||||
|
RecurseDestroyNode(m_root);
|
||||||
|
m_root = nullptr;
|
||||||
|
}
|
||||||
|
}
|
94
examples/testbed/framework/profiler_st.h
Normal file
94
examples/testbed/framework/profiler_st.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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 PROFILER_ST_H
|
||||||
|
#define PROFILER_ST_H
|
||||||
|
|
||||||
|
#include <bounce/common/math/math.h>
|
||||||
|
#include <bounce/common/memory/block_pool.h>
|
||||||
|
#include <bounce/common/template/array.h>
|
||||||
|
#include <bounce/common/time.h>
|
||||||
|
|
||||||
|
// Profiler tree node statistics
|
||||||
|
struct ProfilerStNodeStat
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
float64 minElapsed;
|
||||||
|
float64 maxElapsed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A profiler tree node
|
||||||
|
struct ProfilerStNode
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
float64 t0;
|
||||||
|
float64 t1;
|
||||||
|
|
||||||
|
float64 elapsed;
|
||||||
|
u32 callCount;
|
||||||
|
|
||||||
|
ProfilerStNode* parent;
|
||||||
|
b3StackArray<ProfilerStNode*, 32> children;
|
||||||
|
|
||||||
|
ProfilerStNodeStat* stat;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A profiler tree
|
||||||
|
class ProfilerSt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProfilerSt();
|
||||||
|
|
||||||
|
~ProfilerSt();
|
||||||
|
|
||||||
|
// Must be called before profiling.
|
||||||
|
void Begin();
|
||||||
|
|
||||||
|
// Must be called after profiling.
|
||||||
|
void End();
|
||||||
|
|
||||||
|
// Begin a new scope.
|
||||||
|
void BeginScope(const char* name);
|
||||||
|
|
||||||
|
// End the top scope.
|
||||||
|
void EndScope();
|
||||||
|
|
||||||
|
ProfilerStNode* GetRoot() { return m_root; }
|
||||||
|
private:
|
||||||
|
ProfilerStNode* CreateNode();
|
||||||
|
void DestroyNode(ProfilerStNode* node);
|
||||||
|
|
||||||
|
void RecurseDestroyNode(ProfilerStNode* node);
|
||||||
|
|
||||||
|
ProfilerStNode* FindNode(const char* name);
|
||||||
|
|
||||||
|
ProfilerStNodeStat* CreateStat();
|
||||||
|
|
||||||
|
ProfilerStNodeStat* FindStat(const char* name);
|
||||||
|
|
||||||
|
b3BlockPool m_pool; // pool of nodes
|
||||||
|
b3Time m_time; // timer
|
||||||
|
ProfilerStNode* m_root; // tree root node
|
||||||
|
ProfilerStNode* m_top; // top node
|
||||||
|
|
||||||
|
b3StackArray<ProfilerStNodeStat, 256> m_stats; // node statistics
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ProfilerSt* g_profilerSt;
|
||||||
|
|
||||||
|
#endif
|
@ -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,36 +146,12 @@ 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_sA.m_hull = &m_boxA;
|
m.rotation = b3Diagonal(1.0f, 1.0f, 1.0f);
|
||||||
|
m.position.Set(0.0f, 0.0f, 0.0f);
|
||||||
|
m_box2.SetTransform(m);
|
||||||
|
|
||||||
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_shapeB = &m_sB;
|
m_sB.m_hull = &m_box2;
|
||||||
|
|
||||||
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(sdef);
|
body->CreateShape(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
e.x = rx + r;
|
|
||||||
e.y = r;
|
|
||||||
e.z = r;
|
|
||||||
|
|
||||||
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 k = 0; k < e_d; ++k)
|
|
||||||
{
|
|
||||||
b3BodyDef bdef;
|
|
||||||
bdef.type = e_dynamicBody;
|
|
||||||
|
|
||||||
bdef.position.Set(scalar(j), scalar(i), scalar(k));
|
|
||||||
|
|
||||||
bdef.position.x *= scale.x;
|
|
||||||
bdef.position.y *= scale.y;
|
|
||||||
bdef.position.z *= scale.z;
|
|
||||||
|
|
||||||
bdef.position += translation;
|
|
||||||
|
|
||||||
b3Body* body = m_world.CreateBody(bdef);
|
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.density = 0.1f;
|
|
||||||
sdef.friction = 0.3f;
|
|
||||||
sdef.shape = &capsule;
|
sdef.shape = &capsule;
|
||||||
|
sdef.density = 0.1f;
|
||||||
|
sdef.friction = 0.4f;
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
const u32 c = e_rowCount * e_columnCount * e_depthCount;
|
||||||
|
b3Body* bs[c];
|
||||||
|
u32 n = 0;
|
||||||
|
|
||||||
u32 bodyIndex = GetBodyIndex(i, j, k);
|
b3AABB3 aabb;
|
||||||
|
aabb.m_lower.Set(0.0f, 0.0f, 0.0f);
|
||||||
|
aabb.m_upper.Set(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
m_bodies[bodyIndex] = body;
|
for (u32 i = 0; i < e_rowCount; ++i)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 GetBodyIndex(u32 i, u32 j, u32 k)
|
|
||||||
{
|
{
|
||||||
B3_ASSERT(i < e_h);
|
for (u32 j = 0; j < e_columnCount; ++j)
|
||||||
B3_ASSERT(j < e_w);
|
{
|
||||||
B3_ASSERT(k < e_d);
|
for (u32 k = 0; k < e_depthCount; ++k)
|
||||||
return k + e_d * (j + e_w * i);
|
{
|
||||||
|
b3BodyDef bdef;
|
||||||
|
bdef.type = b3BodyType::e_dynamicBody;
|
||||||
|
|
||||||
|
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.z = (2.0f + separation) * float32(k) * radius;
|
||||||
|
|
||||||
|
bdef.orientation = b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.5f * B3_PI);
|
||||||
|
|
||||||
|
b3Body* body = m_world.CreateBody(bdef);
|
||||||
|
bs[n++] = body;
|
||||||
|
|
||||||
|
b3Shape* shape = body->CreateShape(sdef);
|
||||||
|
|
||||||
|
b3AABB3 aabb2;
|
||||||
|
shape->ComputeAABB(&aabb2, body->GetTransform());
|
||||||
|
|
||||||
|
aabb = b3Combine(aabb, aabb2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b3Vec3 center = aabb.Centroid();
|
||||||
|
|
||||||
|
for (u32 i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
b3Body* b = bs[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_xfA.SetIdentity();
|
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_sB.m_vertex1.Set(1.0f, -1.0f, 0.0f);
|
m_xfB.position.Set(0.f, 0.0f, 0.0f);
|
||||||
m_sB.m_vertex2.Set(0.0f, 1.0f, 0.0f);
|
m_xfB.rotation = b3QuatMat33(b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.0f * B3_PI));
|
||||||
m_sB.m_radius = 2.0f;
|
|
||||||
|
|
||||||
m_xfB.translation.Set(0.0f, 0.0f, 0.0f);
|
b3Transform xf;
|
||||||
m_xfB.rotation = b3QuatRotationZ(0.55f * B3_PI);
|
xf.SetIdentity();
|
||||||
|
xf.rotation = b3Diagonal(4.0f, 1.0f, 4.0f);
|
||||||
|
|
||||||
|
m_box.SetTransform(xf);
|
||||||
|
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,44 +16,45 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef B3_FRAME_ALLOCATOR_H
|
#ifndef DEGENERATE_CAPSULE_H
|
||||||
#define B3_FRAME_ALLOCATOR_H
|
#define DEGENERATE_CAPSULE_H
|
||||||
|
|
||||||
#include <bounce/common/settings.h>
|
class DegenerateCapsule : public Collide
|
||||||
|
|
||||||
// Allocate 1 MiB from the stack.
|
|
||||||
// Increase as you want.
|
|
||||||
const u32 b3_maxFrameSize = B3_MiB(1);
|
|
||||||
|
|
||||||
// A small frame allocator.
|
|
||||||
class b3FrameAllocator
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
b3FrameAllocator();
|
DegenerateCapsule()
|
||||||
~b3FrameAllocator();
|
|
||||||
|
|
||||||
// Allocate a block of memory.
|
|
||||||
// Allocate using b3Alloc if the memory is full.
|
|
||||||
void* Allocate(u32 size);
|
|
||||||
|
|
||||||
// Free the memory if it was allocated by b3Alloc.
|
|
||||||
void Free(void* q);
|
|
||||||
|
|
||||||
// Reset the memory pointer.
|
|
||||||
// This function should be called at the beginning of a frame.
|
|
||||||
void Reset();
|
|
||||||
private:
|
|
||||||
// Block header
|
|
||||||
struct b3Block
|
|
||||||
{
|
{
|
||||||
u32 size;
|
m_xfA.position.Set(0.0f, 0.0f, 0.0f);
|
||||||
void* p;
|
m_xfA.rotation = b3QuatMat33(b3Quat(b3Vec3(0.0f, 0.0f, 1.0f), 0.55f * B3_PI));
|
||||||
bool parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
u8 m_memory[b3_maxFrameSize];
|
m_sA.m_centers[0].Set(0.0f, 0.0f, 0.0f);
|
||||||
u8* m_p;
|
m_sA.m_centers[1].Set(0.0f, 0.0f, 0.0f);
|
||||||
u32 m_allocatedSize;
|
m_sA.m_radius = 0.05f;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
b3Transform xf;
|
||||||
|
xf.SetIdentity();
|
||||||
|
xf.rotation = b3Diagonal(4.0f, 1.0f, 4.0f);
|
||||||
|
|
||||||
|
m_box.SetTransform(xf);
|
||||||
|
|
||||||
|
m_sB.m_hull = &m_box;
|
||||||
|
|
||||||
|
m_shapeA = &m_sA;
|
||||||
|
m_shapeB = &m_sB;
|
||||||
|
m_cache.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Test* Create()
|
||||||
|
{
|
||||||
|
return new DegenerateCapsule();
|
||||||
|
}
|
||||||
|
|
||||||
|
b3CapsuleShape m_sA;
|
||||||
|
b3HullShape m_sB;
|
||||||
|
b3BoxHull m_box;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -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;
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef REVOLUTE_TEST_H
|
#ifndef HINGE_MOTOR_H
|
||||||
#define REVOLUTE_TEST_H
|
#define HINGE_MOTOR_H
|
||||||
|
|
||||||
class RevoluteTest : public Test
|
class HingeMotor : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RevoluteTest()
|
HingeMotor()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
@ -46,8 +46,8 @@ public:
|
|||||||
hinge = m_world.CreateBody(bd);
|
hinge = m_world.CreateBody(bd);
|
||||||
|
|
||||||
b3CapsuleShape shape;
|
b3CapsuleShape shape;
|
||||||
shape.m_vertex1.Set(0.0f, 0.0f, -4.0f);
|
shape.m_centers[0].Set(0.0f, 0.0f, -4.0f);
|
||||||
shape.m_vertex2.Set(0.0f, 0.0f, 4.0f);
|
shape.m_centers[1].Set(0.0f, 0.0f, 4.0f);
|
||||||
shape.m_radius = 0.5f;
|
shape.m_radius = 0.5f;
|
||||||
|
|
||||||
b3ShapeDef sd;
|
b3ShapeDef sd;
|
||||||
@ -66,7 +66,7 @@ public:
|
|||||||
|
|
||||||
door = m_world.CreateBody(bd);
|
door = m_world.CreateBody(bd);
|
||||||
|
|
||||||
m_doorBox.SetExtents(1.0f, 0.5f, 4.0f);
|
m_doorBox.Set(1.0f, 0.5f, 4.0f);
|
||||||
|
|
||||||
b3HullShape hull;
|
b3HullShape hull;
|
||||||
hull.m_hull = &m_doorBox;
|
hull.m_hull = &m_doorBox;
|
||||||
@ -78,34 +78,23 @@ public:
|
|||||||
door->CreateShape(sdef);
|
door->CreateShape(sdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
b3Vec3 axis(0.0f, 0.0f, 1.0f);
|
b3Vec3 axis(0.0f, 0.0f, 1.0f);
|
||||||
b3Vec3 anchor(0.0f, 7.0f, 0.0f);
|
b3Vec3 anchor(0.0f, 7.0f, 0.0f);
|
||||||
|
|
||||||
b3RevoluteJointDef jd;
|
b3RevoluteJointDef jd;
|
||||||
jd.Initialize(hinge, door, axis, anchor, -0.25f * B3_PI, 0.5f * B3_PI);
|
jd.Initialize(hinge, door, axis, anchor, 0.0f, B3_PI);
|
||||||
jd.maxMotorTorque = 1000.0f;
|
|
||||||
jd.enableMotor = false;
|
|
||||||
jd.enableLimit = true;
|
|
||||||
jd.motorSpeed = B3_PI;
|
jd.motorSpeed = B3_PI;
|
||||||
|
jd.maxMotorTorque = door->GetMass() * 10000.0f;
|
||||||
|
jd.enableMotor = true;
|
||||||
|
|
||||||
m_rj = (b3RevoluteJoint*)m_world.CreateJoint(jd);
|
m_rj = (b3RevoluteJoint*)m_world.CreateJoint(jd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate the orientation
|
// Invalidate the orientation
|
||||||
b3Quat q = b3QuatRotationX(B3_PI);
|
b3Vec3 axis(1.0f, 0.0f, 0.0f);
|
||||||
door->SetTransform(door->GetPosition(), q);
|
float32 angle = B3_PI;
|
||||||
}
|
door->SetTransform(door->GetPosition(), axis, angle);
|
||||||
|
|
||||||
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)
|
void KeyDown(int button)
|
||||||
@ -138,7 +127,7 @@ public:
|
|||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new RevoluteTest();
|
return new HingeMotor();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_doorBox;
|
b3BoxHull m_doorBox;
|
@ -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,7 +52,7 @@ 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;
|
||||||
@ -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,22 +33,28 @@ 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);
|
||||||
u32 v = m_clothMesh.GetVertex(0, j);
|
aabb1.m_upper.Set(5.0f, 1.0f, -4.0f);
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(v);
|
b3AABB3 aabb2;
|
||||||
p->SetType(e_staticClothParticle);
|
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())
|
||||||
|
{
|
||||||
|
if (aabb1.Contains(p->GetPosition()))
|
||||||
|
{
|
||||||
|
p->SetType(e_staticParticle);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
if (aabb2.Contains(p->GetPosition()))
|
||||||
{
|
{
|
||||||
u32 v = m_clothMesh.GetVertex(e_h, j);
|
p->SetType(e_staticParticle);
|
||||||
|
}
|
||||||
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;
|
||||||
@ -178,19 +178,8 @@ public:
|
|||||||
|
|
||||||
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);
|
||||||
|
@ -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;
|
||||||
|
121
examples/testbed/tests/shape_cast.h
Normal file
121
examples/testbed/tests/shape_cast.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#ifndef SHAPE_CAST_H
|
||||||
|
#define SHAPE_CAST_H
|
||||||
|
|
||||||
|
class ShapeCast : public Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShapeCast()
|
||||||
|
{
|
||||||
|
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.position.Set(-5.0f, 0.0f, 0.0f);
|
||||||
|
m_xfA.rotation.SetIdentity();
|
||||||
|
|
||||||
|
m_xfB.position.Set(10.0f, 0.0f, 0.0f);
|
||||||
|
m_xfB.rotation.SetIdentity();
|
||||||
|
|
||||||
|
m_proxyA.Set(&m_shapeA, 0);
|
||||||
|
m_proxyB.Set(&m_shapeB, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Step()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
b3Vec3 translationB = -100.0f * b3Vec3_x;
|
||||||
|
g_draw->DrawSegment(m_xfB.position, m_xfB.position + translationB, b3Color_white);
|
||||||
|
|
||||||
|
b3GJKShapeCastOutput out;
|
||||||
|
bool hit = b3GJKShapeCast(&out, m_xfA, m_proxyA, m_xfB, m_proxyB, translationB);
|
||||||
|
|
||||||
|
g_draw->DrawString(b3Color_white, "Iterations = %d", out.iterations);
|
||||||
|
|
||||||
|
if (hit)
|
||||||
|
{
|
||||||
|
g_draw->DrawPoint(out.point, 4.0f, b3Color_green);
|
||||||
|
g_draw->DrawSegment(out.point, out.point + out.normal, b3Color_green);
|
||||||
|
|
||||||
|
b3Transform xfB;
|
||||||
|
xfB.rotation = m_xfB.rotation;
|
||||||
|
xfB.position = m_xfB.position + out.t * translationB;
|
||||||
|
|
||||||
|
m_world.DrawShape(xfB, &m_shapeB, b3Color_black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyDown(int key)
|
||||||
|
{
|
||||||
|
if (key == GLFW_KEY_LEFT)
|
||||||
|
{
|
||||||
|
m_xfB.position.x -= 0.105f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == GLFW_KEY_RIGHT)
|
||||||
|
{
|
||||||
|
m_xfB.position.x += 0.105f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == GLFW_KEY_UP)
|
||||||
|
{
|
||||||
|
m_xfB.position.y += 0.105f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == GLFW_KEY_DOWN)
|
||||||
|
{
|
||||||
|
m_xfB.position.y -= 0.105f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == GLFW_KEY_X)
|
||||||
|
{
|
||||||
|
b3Quat qx(b3Vec3(1.0f, 0.0f, 0.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfx = b3QuatMat33(qx);
|
||||||
|
|
||||||
|
m_xfB.rotation = m_xfB.rotation * xfx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == GLFW_KEY_Y)
|
||||||
|
{
|
||||||
|
b3Quat qy(b3Vec3(0.0f, 1.0f, 0.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfy = b3QuatMat33(qy);
|
||||||
|
|
||||||
|
m_xfB.rotation = m_xfB.rotation * xfy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == GLFW_KEY_Z)
|
||||||
|
{
|
||||||
|
b3Quat qy(b3Vec3(0.0f, 0.0f, 1.0f), 0.05f * B3_PI);
|
||||||
|
b3Mat33 xfz = b3QuatMat33(qy);
|
||||||
|
|
||||||
|
m_xfB.rotation = m_xfB.rotation * xfz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Test* Create()
|
||||||
|
{
|
||||||
|
return new ShapeCast();
|
||||||
|
}
|
||||||
|
|
||||||
|
b3HullShape m_shapeA;
|
||||||
|
b3Transform m_xfA;
|
||||||
|
b3ShapeGJKProxy m_proxyA;
|
||||||
|
|
||||||
|
b3HullShape m_shapeB;
|
||||||
|
b3Transform m_xfB;
|
||||||
|
b3ShapeGJKProxy m_proxyB;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
b3Vec3 e(4.0f, 2.0f * B3_LINEAR_SLOP, 4.0f);
|
static b3Vec3 sheetExtents(4.05f, 2.0f * B3_LINEAR_SLOP, 4.05f);
|
||||||
|
static b3BoxHull sheetHull(sheetExtents.x, sheetExtents.y, sheetExtents.z);
|
||||||
|
|
||||||
m_boxHull.SetExtents(e.x, e.y, e.z);
|
b3Vec3 stackOrigin;
|
||||||
|
stackOrigin.Set(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.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,12 +71,28 @@ 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;
|
// Create body
|
||||||
ssd.shape = s;
|
{
|
||||||
|
b3BodyDef bd;
|
||||||
|
bd.type = e_dynamicBody;
|
||||||
|
bd.position.y = 10.0f;
|
||||||
|
|
||||||
m_body->CreateWorldShape(ssd);
|
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;
|
||||||
|
sd.restitution = 0.0f;
|
||||||
|
|
||||||
body->CreateShape(sdef);
|
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
|
@ -16,13 +16,13 @@
|
|||||||
* 3. This notice may not be removed or altered from any source distribution.
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SPRING_TEST_H
|
#ifndef SPRING_H
|
||||||
#define SPRING_TEST_H
|
#define SPRING_H
|
||||||
|
|
||||||
class SpringTest : public Test
|
class Spring : public Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpringTest()
|
Spring()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
b3BodyDef bd;
|
b3BodyDef bd;
|
||||||
@ -38,7 +38,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Car frame shape
|
// Car frame shape
|
||||||
m_frameHull.SetExtents(2.0f, 0.5f, 5.0f);
|
{
|
||||||
|
b3Transform xf;
|
||||||
|
xf.SetIdentity();
|
||||||
|
xf.rotation = b3Diagonal(2.0f, 0.5f, 5.0f);
|
||||||
|
|
||||||
|
m_frameHull.SetTransform(xf);
|
||||||
|
}
|
||||||
|
|
||||||
b3HullShape box;
|
b3HullShape box;
|
||||||
box.m_hull = &m_frameHull;
|
box.m_hull = &m_frameHull;
|
||||||
@ -69,7 +75,7 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = e_dynamicBody;
|
||||||
bdef.position.Set(-1.0f, 7.0f, 4.5f);
|
bdef.position.Set(-1.0f, 7.0f, -4.5f);
|
||||||
bdef.fixedRotationY = true;
|
bdef.fixedRotationY = true;
|
||||||
|
|
||||||
wheelLF = m_world.CreateBody(bdef);
|
wheelLF = m_world.CreateBody(bdef);
|
||||||
@ -84,7 +90,7 @@ public:
|
|||||||
|
|
||||||
{
|
{
|
||||||
b3SpringJointDef def;
|
b3SpringJointDef def;
|
||||||
def.Initialize(frame, wheelLF, b3Vec3(-1.0f, 9.0f, 4.5), b3Vec3(-1.0f, 9.0f, 4.5f));
|
def.Initialize(frame, wheelLF, b3Vec3(-1.0f, 9.0f, -4.5), b3Vec3(-1.0f, 9.0f, -4.5f));
|
||||||
def.collideLinked = true;
|
def.collideLinked = true;
|
||||||
def.dampingRatio = 0.5f;
|
def.dampingRatio = 0.5f;
|
||||||
def.frequencyHz = 4.0f;
|
def.frequencyHz = 4.0f;
|
||||||
@ -96,7 +102,7 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = e_dynamicBody;
|
||||||
bdef.position.Set(1.0f, 7.0, 4.5f);
|
bdef.position.Set(1.0f, 7.0, -4.5f);
|
||||||
bdef.fixedRotationY = true;
|
bdef.fixedRotationY = true;
|
||||||
|
|
||||||
wheelRF = m_world.CreateBody(bdef);
|
wheelRF = m_world.CreateBody(bdef);
|
||||||
@ -111,7 +117,7 @@ public:
|
|||||||
|
|
||||||
{
|
{
|
||||||
b3SpringJointDef def;
|
b3SpringJointDef def;
|
||||||
def.Initialize(frame, wheelRF, b3Vec3(1.0f, 9.0, 4.5), b3Vec3(1.0f, 9.0, 4.5f));
|
def.Initialize(frame, wheelRF, b3Vec3(1.0f, 9.0, -4.5), b3Vec3(1.0f, 9.0, -4.5f));
|
||||||
def.collideLinked = true;
|
def.collideLinked = true;
|
||||||
def.dampingRatio = 0.5f;
|
def.dampingRatio = 0.5f;
|
||||||
def.frequencyHz = 4.0f;
|
def.frequencyHz = 4.0f;
|
||||||
@ -123,7 +129,7 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = e_dynamicBody;
|
||||||
bdef.position.Set(-1.0f, 7.0f, -4.5f);
|
bdef.position.Set(-1.0f, 7.0f, 4.5f);
|
||||||
bdef.fixedRotationY = true;
|
bdef.fixedRotationY = true;
|
||||||
|
|
||||||
wheelLB = m_world.CreateBody(bdef);
|
wheelLB = m_world.CreateBody(bdef);
|
||||||
@ -138,7 +144,7 @@ public:
|
|||||||
|
|
||||||
{
|
{
|
||||||
b3SpringJointDef def;
|
b3SpringJointDef def;
|
||||||
def.Initialize(frame, wheelLB, b3Vec3(-1.0f, 9.0f, -4.5f), b3Vec3(-1.0f, 9.0f, -4.5f));
|
def.Initialize(frame, wheelLB, b3Vec3(-1.0f, 9.0f, 4.5f), b3Vec3(-1.0f, 9.0f, 4.5f));
|
||||||
def.collideLinked = true;
|
def.collideLinked = true;
|
||||||
def.dampingRatio = 0.8f;
|
def.dampingRatio = 0.8f;
|
||||||
def.frequencyHz = 4.0f;
|
def.frequencyHz = 4.0f;
|
||||||
@ -150,7 +156,7 @@ public:
|
|||||||
{
|
{
|
||||||
b3BodyDef bdef;
|
b3BodyDef bdef;
|
||||||
bdef.type = e_dynamicBody;
|
bdef.type = e_dynamicBody;
|
||||||
bdef.position.Set(1.0f, 7.0f, -4.5f);
|
bdef.position.Set(1.0f, 7.0f, 4.5f);
|
||||||
bdef.fixedRotationY = true;
|
bdef.fixedRotationY = true;
|
||||||
|
|
||||||
wheelRB = m_world.CreateBody(bdef);
|
wheelRB = m_world.CreateBody(bdef);
|
||||||
@ -165,7 +171,7 @@ public:
|
|||||||
|
|
||||||
{
|
{
|
||||||
b3SpringJointDef def;
|
b3SpringJointDef def;
|
||||||
def.Initialize(frame, wheelRB, b3Vec3(1.0f, 9.0f, -4.5f), b3Vec3(1.0f, 9.0f, -4.5f));
|
def.Initialize(frame, wheelRB, b3Vec3(1.0f, 9.0f, 4.5f), b3Vec3(1.0f, 9.0f, 4.5f));
|
||||||
def.collideLinked = true;
|
def.collideLinked = true;
|
||||||
def.frequencyHz = 4.0f;
|
def.frequencyHz = 4.0f;
|
||||||
def.dampingRatio = 0.8f;
|
def.dampingRatio = 0.8f;
|
||||||
@ -176,7 +182,7 @@ public:
|
|||||||
|
|
||||||
static Test* Create()
|
static Test* Create()
|
||||||
{
|
{
|
||||||
return new SpringTest();
|
return new Spring();
|
||||||
}
|
}
|
||||||
|
|
||||||
b3BoxHull m_frameHull;
|
b3BoxHull m_frameHull;
|
@ -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);
|
||||||
for (u32 j = 0; j < e_w + 1; ++j)
|
aabb.m_upper.Set(5.0f, 1.0f, -4.0f);
|
||||||
{
|
|
||||||
u32 v = m_clothMesh.GetVertex(i, j);
|
|
||||||
|
|
||||||
b3ClothParticle* p = m_cloth->GetParticle(v);
|
for (b3Particle* p = m_cloth->GetParticleList().m_head; p; p = p->GetNext())
|
||||||
p->SetType(e_staticClothParticle);
|
{
|
||||||
|
if (aabb.Contains(p->GetPosition()))
|
||||||
|
{
|
||||||
|
p->SetType(e_staticParticle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 v1 = m_cloth->GetParticle(t->v1)->GetPosition();
|
||||||
b3Vec3 v2 = m_cloth->GetParticle(triangle->v2)->GetPosition();
|
b3Vec3 v2 = m_cloth->GetParticle(t->v2)->GetPosition();
|
||||||
b3Vec3 v3 = m_cloth->GetParticle(triangle->v3)->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 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 n2 = -n1;
|
||||||
|
g_draw->DrawSolidTriangle(n2, v3, v2, v1, color);
|
||||||
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);
|
||||||
|
m.rotation = b3Diagonal(50.0f, 1.0f, 200.0f);
|
||||||
|
|
||||||
b3Vec3 translation(0.0f, -45.0f, 0.0f);
|
box.SetTransform(m);
|
||||||
box.Translate(translation);
|
|
||||||
|
|
||||||
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);
|
||||||
|
m.rotation = b3Diagonal(50.0f, 1.0f, 200.0f);
|
||||||
|
|
||||||
b3Vec3 translation(0.0f, 50.0f, 0.0f);
|
box.SetTransform(m);
|
||||||
box.Translate(translation);
|
|
||||||
|
|
||||||
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);
|
||||||
|
m.rotation = b3Diagonal(50.0f, 50.0f, 1.0f);
|
||||||
|
|
||||||
b3Vec3 translation(0.0f, 5.0f, -200.0f);
|
box.SetTransform(m);
|
||||||
box.Translate(translation);
|
|
||||||
|
|
||||||
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);
|
||||||
|
m.rotation = b3Diagonal(50.0f, 50.0f, 1.0f);
|
||||||
|
|
||||||
b3Vec3 translation(0.0f, 5.0f, 200.0f);
|
box.SetTransform(m);
|
||||||
box.Translate(translation);
|
|
||||||
|
|
||||||
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);
|
||||||
|
m.rotation = b3Diagonal(1.0f, 50.0f, 200.0f);
|
||||||
|
|
||||||
b3Vec3 translation(-50.0f, 5.0f, 0.0f);
|
box.SetTransform(m);
|
||||||
box.Translate(translation);
|
|
||||||
|
|
||||||
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);
|
||||||
|
m.rotation = b3Diagonal(1.0f, 50.0f, 200.0f);
|
||||||
|
|
||||||
b3Vec3 translation(50.0f, 5.0f, 0.0f);
|
box.SetTransform(m);
|
||||||
|
|
||||||
box.Translate(translation);
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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