diff --git a/examples/testbed/framework/draw.cpp b/examples/testbed/framework/draw.cpp index a36376d..6b09223 100644 --- a/examples/testbed/framework/draw.cpp +++ b/examples/testbed/framework/draw.cpp @@ -116,7 +116,7 @@ b3Vec2 Camera::ConvertWorldToScreen(const b3Vec3& pw3) const return ps; } -Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const +b3Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const { float32 w = m_width, h = m_height; @@ -133,7 +133,7 @@ Ray3 Camera::ConvertScreenToWorld(const b3Vec2& ps) const b3Vec3 vw = xf.rotation * vv; vw.Normalize(); - Ray3 rw; + b3Ray3 rw; rw.direction = vw; rw.origin = xf.position; rw.fraction = m_zFar; diff --git a/examples/testbed/framework/draw.h b/examples/testbed/framework/draw.h index b151435..bd2fcdb 100644 --- a/examples/testbed/framework/draw.h +++ b/examples/testbed/framework/draw.h @@ -27,27 +27,6 @@ struct DrawTriangles; struct DrawWire; struct DrawSolid; -// -struct Ray3 -{ - b3Vec3 A() const; - b3Vec3 B() const; - - b3Vec3 direction; - b3Vec3 origin; - float32 fraction; -}; - -inline b3Vec3 Ray3::A() const -{ - return origin; -} - -inline b3Vec3 Ray3::B() const -{ - return origin + fraction * direction; -} - // class Camera { @@ -61,7 +40,7 @@ public: b3Transform BuildWorldTransform() const; b3Vec2 ConvertWorldToScreen(const b3Vec3& pw) const; - Ray3 ConvertScreenToWorld(const b3Vec2& ps) const; + b3Ray3 ConvertScreenToWorld(const b3Vec2& ps) const; float32 m_zoom; b3Vec3 m_center; diff --git a/examples/testbed/framework/model.cpp b/examples/testbed/framework/model.cpp index c2bb7a5..c91ba72 100644 --- a/examples/testbed/framework/model.cpp +++ b/examples/testbed/framework/model.cpp @@ -76,21 +76,21 @@ void Model::Command_Release_Key(int button) void Model::Command_Press_Mouse_Left(const b3Vec2& ps) { - Ray3 pw = m_camera.ConvertScreenToWorld(ps); + b3Ray3 pw = m_camera.ConvertScreenToWorld(ps); m_test->MouseLeftDown(pw); } void Model::Command_Release_Mouse_Left(const b3Vec2& ps) { - Ray3 pw = m_camera.ConvertScreenToWorld(ps); + b3Ray3 pw = m_camera.ConvertScreenToWorld(ps); m_test->MouseLeftUp(pw); } void Model::Command_Move_Cursor(const b3Vec2& ps) { - Ray3 pw = m_camera.ConvertScreenToWorld(ps); + b3Ray3 pw = m_camera.ConvertScreenToWorld(ps); m_test->MouseMove(pw); } diff --git a/examples/testbed/framework/test.cpp b/examples/testbed/framework/test.cpp index 4bceb6c..d612064 100644 --- a/examples/testbed/framework/test.cpp +++ b/examples/testbed/framework/test.cpp @@ -115,7 +115,7 @@ void Test::Step() } } -void Test::MouseMove(const Ray3& pw) +void Test::MouseMove(const b3Ray3& pw) { m_bodyRay = pw; @@ -125,7 +125,7 @@ void Test::MouseMove(const Ray3& pw) } } -void Test::MouseLeftDown(const Ray3& pw) +void Test::MouseLeftDown(const b3Ray3& pw) { if (m_bodyDragger.IsSelected() == false) { @@ -136,7 +136,7 @@ void Test::MouseLeftDown(const Ray3& pw) } } -void Test::MouseLeftUp(const Ray3& pw) +void Test::MouseLeftUp(const b3Ray3& pw) { if (m_bodyDragger.IsSelected() == true) { diff --git a/examples/testbed/framework/test.h b/examples/testbed/framework/test.h index 8261be0..7c3bed2 100644 --- a/examples/testbed/framework/test.h +++ b/examples/testbed/framework/test.h @@ -48,110 +48,6 @@ public: b3RayCastSingleOutput hit; }; -class BodyDragger -{ -public: - BodyDragger(Ray3* ray, b3World* world) - { - m_ray = ray; - m_world = world; - m_shape = nullptr; - m_mouseJoint = nullptr; - } - - ~BodyDragger() - { - - } - - bool StartDragging() - { - B3_ASSERT(m_mouseJoint == nullptr); - - b3RayCastSingleOutput out; - if (m_world->RayCastSingle(&out, m_ray->A(), m_ray->B()) == false) - { - return false; - } - - m_x = out.fraction; - m_shape = out.shape; - - b3BodyDef bd; - b3Body* groundBody = m_world->CreateBody(bd); - - b3Body* body = m_shape->GetBody(); - body->SetAwake(true); - - b3MouseJointDef jd; - jd.bodyA = groundBody; - jd.bodyB = body; - jd.target = out.point; - jd.maxForce = 2000.0f * body->GetMass(); - - m_mouseJoint = (b3MouseJoint*)m_world->CreateJoint(jd); - - m_p = body->GetLocalPoint(out.point); - - return true; - } - - void Drag() - { - B3_ASSERT(m_mouseJoint); - m_mouseJoint->SetTarget(GetPointB()); - } - - void StopDragging() - { - B3_ASSERT(m_mouseJoint); - - b3Body* groundBody = m_mouseJoint->GetBodyA(); - m_world->DestroyJoint(m_mouseJoint); - m_mouseJoint = nullptr; - m_world->DestroyBody(groundBody); - m_shape = nullptr; - } - - bool IsSelected() const - { - return m_mouseJoint != nullptr; - } - - - Ray3* GetRay() const - { - return m_ray; - } - - b3Body* GetBody() const - { - B3_ASSERT(m_shape); - return m_shape->GetBody(); - } - - b3Vec3 GetPointA() const - { - B3_ASSERT(m_shape); - return m_shape->GetBody()->GetWorldPoint(m_p); - } - - b3Vec3 GetPointB() const - { - B3_ASSERT(m_mouseJoint); - return (1.0f - m_x) * m_ray->A() + m_x * m_ray->B(); - } - -private: - Ray3* m_ray; - float32 m_x; - - b3World* m_world; - b3Shape* m_shape; - b3Vec3 m_p; - b3MouseJoint* m_mouseJoint; -}; - class Test : public b3ContactListener { public: @@ -162,9 +58,9 @@ public: virtual void Step(); - virtual void MouseMove(const Ray3& pw); - virtual void MouseLeftDown(const Ray3& pw); - virtual void MouseLeftUp(const Ray3& pw); + virtual void MouseMove(const b3Ray3& pw); + virtual void MouseLeftDown(const b3Ray3& pw); + virtual void MouseLeftUp(const b3Ray3& pw); virtual void KeyDown(int button) { } virtual void KeyUp(int button) { } @@ -177,8 +73,8 @@ public: b3World m_world; - Ray3 m_bodyRay; - BodyDragger m_bodyDragger; + b3Ray3 m_bodyRay; + b3BodyDragger m_bodyDragger; b3BoxHull m_groundHull; b3GridMesh<50, 50> m_groundMesh; diff --git a/examples/testbed/tests/cloth_test.h b/examples/testbed/tests/cloth_test.h index d514418..fb8f3a7 100644 --- a/examples/testbed/tests/cloth_test.h +++ b/examples/testbed/tests/cloth_test.h @@ -19,219 +19,6 @@ #ifndef CLOTH_TESH_H #define CLOTH_TESH_H -class ClothDragger -{ -public: - ClothDragger(Ray3* ray, b3Cloth*& cloth) : m_ray(ray), m_cloth(cloth) - { - m_isSelected = false; - m_spring = false; - } - - ~ClothDragger() - { - - } - - bool IsSelected() const - { - return m_isSelected; - } - - b3Vec3 GetPointA() const - { - B3_ASSERT(m_isSelected); - - b3ClothMesh* m = m_cloth->GetMesh(); - b3ClothMeshTriangle* t = m->triangles + m_selection; - - b3Vec3 A = m->vertices[t->v1]; - b3Vec3 B = m->vertices[t->v2]; - b3Vec3 C = m->vertices[t->v3]; - - return m_u * A + m_v * B + (1.0f - m_u - m_v) * C; - } - - b3Vec3 GetPointB() const - { - B3_ASSERT(m_isSelected); - return (1.0f - m_x) * m_ray->A() + m_x * m_ray->B(); - } - - bool StartDragging() - { - B3_ASSERT(m_isSelected == false); - - b3RayCastInput rayIn; - rayIn.p1 = m_ray->A(); - rayIn.p2 = m_ray->B(); - rayIn.maxFraction = B3_MAX_FLOAT; - - b3ClothRayCastOutput rayOut; - if (m_cloth->RayCast(&rayOut, &rayIn) == false) - { - return false; - } - - m_isSelected = true; - - m_selection = rayOut.triangle; - m_x = rayOut.fraction; - - b3ClothMesh* m = m_cloth->GetMesh(); - b3ClothMeshTriangle* t = m->triangles + m_selection; - - b3Particle* p1 = m->particles[t->v1]; - b3Particle* p2 = m->particles[t->v2]; - b3Particle* p3 = m->particles[t->v3]; - - b3Vec3 v1 = p1->GetPosition(); - b3Vec3 v2 = p2->GetPosition(); - b3Vec3 v3 = p3->GetPosition(); - - b3Vec3 B = GetPointB(); - - float32 wABC[4]; - b3BarycentricCoordinates(wABC, v1, v2, v3, B); - - if (wABC[3] > B3_EPSILON) - { - m_u = wABC[0] / wABC[3]; - m_v = wABC[1] / wABC[3]; - } - else - { - m_u = m_v = 0.0f; - } - - if (m_spring) - { - b3ParticleDef pd; - pd.type = e_staticParticle; - pd.position = B; - - m_particle = m_cloth->CreateParticle(pd); - - { - b3SpringForceDef sfd; - sfd.p1 = m_particle; - sfd.p2 = p1; - sfd.restLength = 0.0f; - sfd.structural = 10000.0f; - m_s1 = (b3SpringForce*)m_cloth->CreateForce(sfd); - } - - { - b3SpringForceDef sfd; - sfd.p1 = m_particle; - sfd.p2 = p2; - sfd.restLength = 0.0f; - sfd.structural = 10000.0f; - m_s2 = (b3SpringForce*)m_cloth->CreateForce(sfd); - } - - { - b3SpringForceDef sfd; - sfd.p1 = m_particle; - sfd.p2 = p3; - sfd.restLength = 0.0f; - sfd.structural = 10000.0f; - m_s3 = (b3SpringForce*)m_cloth->CreateForce(sfd); - } - } - else - { - m_t1 = p1->GetType(); - p1->SetType(e_staticParticle); - - m_t2 = p2->GetType(); - p2->SetType(e_staticParticle); - - m_t3 = p3->GetType(); - p3->SetType(e_staticParticle); - } - - return true; - } - - void Drag() - { - B3_ASSERT(m_isSelected); - - b3ClothMesh* m = m_cloth->GetMesh(); - b3ClothMeshTriangle* t = m->triangles + m_selection; - - b3Vec3 A = GetPointA(); - b3Vec3 B = GetPointB(); - - b3Vec3 dx = B - A; - - if (m_spring) - { - m_particle->SetPosition(B); - } - else - { - b3Particle* p1 = m->particles[t->v1]; - p1->ApplyTranslation(dx); - - b3Particle* p2 = m->particles[t->v2]; - p2->ApplyTranslation(dx); - - b3Particle* p3 = m->particles[t->v3]; - p3->ApplyTranslation(dx); - } - } - - void StopDragging() - { - B3_ASSERT(m_isSelected); - - m_isSelected = false; - - if (m_spring) - { - m_cloth->DestroyForce(m_s1); - m_cloth->DestroyForce(m_s2); - m_cloth->DestroyForce(m_s3); - m_cloth->DestroyParticle(m_particle); - } - else - { - b3ClothMesh* m = m_cloth->GetMesh(); - b3ClothMeshTriangle* t = m->triangles + m_selection; - - b3Particle* p1 = m->particles[t->v1]; - p1->SetType(m_t1); - - b3Particle* p2 = m->particles[t->v2]; - p2->SetType(m_t2); - - b3Particle* p3 = m->particles[t->v3]; - p3->SetType(m_t3); - } - } - -private: - bool m_isSelected; - - Ray3* m_ray; - float32 m_x; - - b3Cloth*& m_cloth; - u32 m_selection; - float32 m_u, m_v; - - bool m_spring; - - b3Particle* m_particle; - b3SpringForce* m_s1; - b3SpringForce* m_s2; - b3SpringForce* m_s3; - - b3ParticleType m_t1, m_t2, m_t3; -}; - class ClothTest : public Test { public: @@ -266,7 +53,7 @@ public: } } - void MouseMove(const Ray3& pw) + void MouseMove(const b3Ray3& pw) { m_clothRay = pw; @@ -276,7 +63,7 @@ public: } } - void MouseLeftDown(const Ray3& pw) + void MouseLeftDown(const b3Ray3& pw) { if (m_clothDragger.IsSelected() == false) { @@ -284,7 +71,7 @@ public: } } - void MouseLeftUp(const Ray3& pw) + void MouseLeftUp(const b3Ray3& pw) { if (m_clothDragger.IsSelected() == true) { @@ -292,9 +79,9 @@ public: } } - Ray3 m_clothRay; + b3Ray3 m_clothRay; b3Cloth* m_cloth; - ClothDragger m_clothDragger; + b3ClothDragger m_clothDragger; }; #endif \ No newline at end of file diff --git a/include/bounce/bounce.h b/include/bounce/bounce.h index 7b60d3c..1c4162f 100644 --- a/include/bounce/bounce.h +++ b/include/bounce/bounce.h @@ -72,4 +72,7 @@ #include #include +#include +#include + #endif \ No newline at end of file diff --git a/include/bounce/common/geometry.h b/include/bounce/common/geometry.h index 49770f3..5d7872a 100644 --- a/include/bounce/common/geometry.h +++ b/include/bounce/common/geometry.h @@ -22,6 +22,24 @@ #include #include +// A ray. +struct b3Ray3 +{ + b3Vec3 A() const + { + return origin; + } + + b3Vec3 B() const + { + return origin + fraction * direction; + } + + b3Vec3 direction; + b3Vec3 origin; + float32 fraction; +}; + // A plane in constant normal form. // dot(n, p) - d = 0. struct b3Plane diff --git a/include/bounce/controllers/body_dragger.h b/include/bounce/controllers/body_dragger.h new file mode 100644 index 0000000..aa1e051 --- /dev/null +++ b/include/bounce/controllers/body_dragger.h @@ -0,0 +1,131 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef B3_BODY_DRAGGER_H +#define B3_BODY_DRAGGER_H + +#include +#include + +// A body dragger. +class b3BodyDragger +{ +public: + b3BodyDragger(b3Ray3* ray, b3World* world) + { + m_ray = ray; + m_world = world; + m_shape = nullptr; + m_mouseJoint = nullptr; + } + + ~b3BodyDragger() + { + + } + + bool StartDragging() + { + B3_ASSERT(m_mouseJoint == nullptr); + + b3RayCastSingleOutput out; + if (m_world->RayCastSingle(&out, m_ray->A(), m_ray->B()) == false) + { + return false; + } + + m_x = out.fraction; + m_shape = out.shape; + + b3BodyDef bd; + b3Body* groundBody = m_world->CreateBody(bd); + + b3Body* body = m_shape->GetBody(); + body->SetAwake(true); + + b3MouseJointDef jd; + jd.bodyA = groundBody; + jd.bodyB = body; + jd.target = out.point; + jd.maxForce = 2000.0f * body->GetMass(); + + m_mouseJoint = (b3MouseJoint*)m_world->CreateJoint(jd); + + m_p = body->GetLocalPoint(out.point); + + return true; + } + + void Drag() + { + B3_ASSERT(m_mouseJoint); + m_mouseJoint->SetTarget(GetPointB()); + } + + void StopDragging() + { + B3_ASSERT(m_mouseJoint); + + b3Body* groundBody = m_mouseJoint->GetBodyA(); + m_world->DestroyJoint(m_mouseJoint); + m_mouseJoint = nullptr; + m_world->DestroyBody(groundBody); + m_shape = nullptr; + } + + bool IsSelected() const + { + return m_mouseJoint != nullptr; + } + + + b3Ray3* GetRay() const + { + return m_ray; + } + + b3Body* GetBody() const + { + B3_ASSERT(m_shape); + return m_shape->GetBody(); + } + + b3Vec3 GetPointA() const + { + B3_ASSERT(m_shape); + return m_shape->GetBody()->GetWorldPoint(m_p); + } + + b3Vec3 GetPointB() const + { + B3_ASSERT(m_mouseJoint); + return (1.0f - m_x) * m_ray->A() + m_x * m_ray->B(); + } + +private: + b3Ray3 * m_ray; + float32 m_x; + + b3World* m_world; + b3Shape* m_shape; + b3Vec3 m_p; + b3MouseJoint* m_mouseJoint; +}; + + +#endif \ No newline at end of file diff --git a/include/bounce/controllers/cloth_dragger.h b/include/bounce/controllers/cloth_dragger.h new file mode 100644 index 0000000..d9fcd28 --- /dev/null +++ b/include/bounce/controllers/cloth_dragger.h @@ -0,0 +1,242 @@ +/* +* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef B3_CLOTH_DRAGGER_H +#define B3_CLOTH_DRAGGER_H + +#include +#include +#include +#include +#include + +// A cloth triangle dragger. +class b3ClothDragger +{ +public: + b3ClothDragger(b3Ray3* ray, b3Cloth*& cloth) : m_ray(ray), m_cloth(cloth) + { + m_isSelected = false; + m_spring = false; + } + + ~b3ClothDragger() + { + + } + + bool IsSelected() const + { + return m_isSelected; + } + + b3Vec3 GetPointA() const + { + B3_ASSERT(m_isSelected); + + b3ClothMesh* m = m_cloth->GetMesh(); + b3ClothMeshTriangle* t = m->triangles + m_selection; + + b3Vec3 A = m->vertices[t->v1]; + b3Vec3 B = m->vertices[t->v2]; + b3Vec3 C = m->vertices[t->v3]; + + return m_u * A + m_v * B + (1.0f - m_u - m_v) * C; + } + + b3Vec3 GetPointB() const + { + B3_ASSERT(m_isSelected); + return (1.0f - m_x) * m_ray->A() + m_x * m_ray->B(); + } + + bool StartDragging() + { + B3_ASSERT(m_isSelected == false); + + b3RayCastInput rayIn; + rayIn.p1 = m_ray->A(); + rayIn.p2 = m_ray->B(); + rayIn.maxFraction = B3_MAX_FLOAT; + + b3ClothRayCastOutput rayOut; + if (m_cloth->RayCast(&rayOut, &rayIn) == false) + { + return false; + } + + m_isSelected = true; + + m_selection = rayOut.triangle; + m_x = rayOut.fraction; + + b3ClothMesh* m = m_cloth->GetMesh(); + b3ClothMeshTriangle* t = m->triangles + m_selection; + + b3Particle* p1 = m->particles[t->v1]; + b3Particle* p2 = m->particles[t->v2]; + b3Particle* p3 = m->particles[t->v3]; + + b3Vec3 v1 = p1->GetPosition(); + b3Vec3 v2 = p2->GetPosition(); + b3Vec3 v3 = p3->GetPosition(); + + b3Vec3 B = GetPointB(); + + float32 wABC[4]; + b3BarycentricCoordinates(wABC, v1, v2, v3, B); + + if (wABC[3] > B3_EPSILON) + { + m_u = wABC[0] / wABC[3]; + m_v = wABC[1] / wABC[3]; + } + else + { + m_u = m_v = 0.0f; + } + + if (m_spring) + { + b3ParticleDef pd; + pd.type = e_staticParticle; + pd.position = B; + + m_particle = m_cloth->CreateParticle(pd); + + { + b3SpringForceDef sfd; + sfd.p1 = m_particle; + sfd.p2 = p1; + sfd.restLength = 0.0f; + sfd.structural = 10000.0f; + m_s1 = (b3SpringForce*)m_cloth->CreateForce(sfd); + } + + { + b3SpringForceDef sfd; + sfd.p1 = m_particle; + sfd.p2 = p2; + sfd.restLength = 0.0f; + sfd.structural = 10000.0f; + m_s2 = (b3SpringForce*)m_cloth->CreateForce(sfd); + } + + { + b3SpringForceDef sfd; + sfd.p1 = m_particle; + sfd.p2 = p3; + sfd.restLength = 0.0f; + sfd.structural = 10000.0f; + m_s3 = (b3SpringForce*)m_cloth->CreateForce(sfd); + } + } + else + { + m_t1 = p1->GetType(); + p1->SetType(e_staticParticle); + + m_t2 = p2->GetType(); + p2->SetType(e_staticParticle); + + m_t3 = p3->GetType(); + p3->SetType(e_staticParticle); + } + + return true; + } + + void Drag() + { + B3_ASSERT(m_isSelected); + + b3ClothMesh* m = m_cloth->GetMesh(); + b3ClothMeshTriangle* t = m->triangles + m_selection; + + b3Vec3 A = GetPointA(); + b3Vec3 B = GetPointB(); + + b3Vec3 dx = B - A; + + if (m_spring) + { + m_particle->SetPosition(B); + } + else + { + b3Particle* p1 = m->particles[t->v1]; + p1->ApplyTranslation(dx); + + b3Particle* p2 = m->particles[t->v2]; + p2->ApplyTranslation(dx); + + b3Particle* p3 = m->particles[t->v3]; + p3->ApplyTranslation(dx); + } + } + + void StopDragging() + { + B3_ASSERT(m_isSelected); + + m_isSelected = false; + + if (m_spring) + { + m_cloth->DestroyForce(m_s1); + m_cloth->DestroyForce(m_s2); + m_cloth->DestroyForce(m_s3); + m_cloth->DestroyParticle(m_particle); + } + else + { + b3ClothMesh* m = m_cloth->GetMesh(); + b3ClothMeshTriangle* t = m->triangles + m_selection; + + b3Particle* p1 = m->particles[t->v1]; + p1->SetType(m_t1); + + b3Particle* p2 = m->particles[t->v2]; + p2->SetType(m_t2); + + b3Particle* p3 = m->particles[t->v3]; + p3->SetType(m_t3); + } + } + +private: + bool m_isSelected; + + b3Ray3* m_ray; + float32 m_x; + + b3Cloth*& m_cloth; + u32 m_selection; + float32 m_u, m_v; + + bool m_spring; + + b3Particle* m_particle; + b3SpringForce* m_s1; + b3SpringForce* m_s2; + b3SpringForce* m_s3; + + b3ParticleType m_t1, m_t2, m_t3; +}; + +#endif \ No newline at end of file