overhauled physics engine
This commit is contained in:
+70
-22
@@ -2,16 +2,64 @@
|
||||
#include "Math/Vector.h"
|
||||
#include "Math/Matrix.h"
|
||||
#include "Containers/Array.h"
|
||||
|
||||
#include "Graphics/DebugVertex.h"
|
||||
namespace Seele
|
||||
{
|
||||
struct AABB
|
||||
{
|
||||
Math::Vector min = Math::Vector(std::numeric_limits<float>::max());
|
||||
Math::Vector max = Math::Vector(std::numeric_limits<float>::min());
|
||||
Vector min = Vector(std::numeric_limits<float>::max());
|
||||
Vector max = Vector(std::numeric_limits<float>::lowest());// cause of reasons
|
||||
void visualize(Array<DebugVertex>& vertices) const
|
||||
{
|
||||
StaticArray<DebugVertex, 8> corners;
|
||||
corners[0] = DebugVertex { .position = Vector(min.x, min.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[1] = DebugVertex { .position = Vector(min.x, min.y, max.z), .color = Vector(0, 1, 0) };
|
||||
corners[2] = DebugVertex { .position = Vector(min.x, max.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[3] = DebugVertex { .position = Vector(min.x, max.y, max.z), .color = Vector(0, 1, 0) };
|
||||
corners[4] = DebugVertex { .position = Vector(max.x, min.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[5] = DebugVertex { .position = Vector(max.x, min.y, max.z), .color = Vector(0, 1, 0) };
|
||||
corners[6] = DebugVertex { .position = Vector(max.x, max.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[7] = DebugVertex { .position = Vector(max.x, max.y, max.z), .color = Vector(0, 1, 0) };
|
||||
|
||||
vertices.add(corners[0]);
|
||||
vertices.add(corners[1]);
|
||||
|
||||
vertices.add(corners[1]);
|
||||
vertices.add(corners[3]);
|
||||
|
||||
vertices.add(corners[2]);
|
||||
vertices.add(corners[3]);
|
||||
|
||||
vertices.add(corners[0]);
|
||||
vertices.add(corners[2]);
|
||||
|
||||
vertices.add(corners[0]);
|
||||
vertices.add(corners[4]);
|
||||
|
||||
vertices.add(corners[1]);
|
||||
vertices.add(corners[5]);
|
||||
|
||||
vertices.add(corners[2]);
|
||||
vertices.add(corners[6]);
|
||||
|
||||
vertices.add(corners[3]);
|
||||
vertices.add(corners[7]);
|
||||
|
||||
vertices.add(corners[4]);
|
||||
vertices.add(corners[5]);
|
||||
|
||||
vertices.add(corners[5]);
|
||||
vertices.add(corners[7]);
|
||||
|
||||
vertices.add(corners[6]);
|
||||
vertices.add(corners[7]);
|
||||
|
||||
vertices.add(corners[4]);
|
||||
vertices.add(corners[6]);
|
||||
}
|
||||
float surfaceArea() const
|
||||
{
|
||||
Math::Vector d = max - min;
|
||||
Vector d = max - min;
|
||||
return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x);
|
||||
}
|
||||
bool intersects(const AABB& other) const
|
||||
@@ -52,31 +100,31 @@ struct AABB
|
||||
}
|
||||
return true;
|
||||
}
|
||||
AABB getTransformedBox(const Math::Matrix4& matrix) const
|
||||
AABB getTransformedBox(const Matrix4& matrix) const
|
||||
{
|
||||
StaticArray<Math::Vector, 8> corners;
|
||||
corners[0] = Math::Vector(min.x, min.y, min.z);
|
||||
corners[1] = Math::Vector(min.x, min.y, max.z);
|
||||
corners[2] = Math::Vector(min.x, max.y, min.z);
|
||||
corners[3] = Math::Vector(min.x, max.y, max.z);
|
||||
corners[4] = Math::Vector(max.x, min.y, min.z);
|
||||
corners[5] = Math::Vector(max.x, min.y, max.z);
|
||||
corners[6] = Math::Vector(max.x, max.y, min.z);
|
||||
corners[7] = Math::Vector(max.x, max.y, max.z);
|
||||
Math::Vector tmin = Math::Vector(1, 1, 1) * std::numeric_limits<float>::max();
|
||||
Math::Vector tmax = Math::Vector(1, 1, 1) * std::numeric_limits<float>::min();
|
||||
StaticArray<Vector, 8> corners;
|
||||
corners[0] = Vector(min.x, min.y, min.z);
|
||||
corners[1] = Vector(min.x, min.y, max.z);
|
||||
corners[2] = Vector(min.x, max.y, min.z);
|
||||
corners[3] = Vector(min.x, max.y, max.z);
|
||||
corners[4] = Vector(max.x, min.y, min.z);
|
||||
corners[5] = Vector(max.x, min.y, max.z);
|
||||
corners[6] = Vector(max.x, max.y, min.z);
|
||||
corners[7] = Vector(max.x, max.y, max.z);
|
||||
Vector tmin = Vector(1, 1, 1) * std::numeric_limits<float>::max();
|
||||
Vector tmax = Vector(1, 1, 1) * std::numeric_limits<float>::lowest();
|
||||
for(int i = 0; i < 8; ++i)
|
||||
{
|
||||
Math::Vector transformed = matrix * Math::Vector4(corners[i], 1.0f);
|
||||
tmin = Math::Vector(std::min(tmin.x, transformed.x), std::min(tmin.y, transformed.y), std::min(tmin.z, transformed.z));
|
||||
tmax = Math::Vector(std::max(tmax.x, transformed.x), std::max(tmax.y, transformed.y), std::max(tmax.z, transformed.z));
|
||||
Vector transformed = matrix * Vector4(corners[i], 1.0f);
|
||||
tmin = Vector(std::min(tmin.x, transformed.x), std::min(tmin.y, transformed.y), std::min(tmin.z, transformed.z));
|
||||
tmax = Vector(std::max(tmax.x, transformed.x), std::max(tmax.y, transformed.y), std::max(tmax.z, transformed.z));
|
||||
}
|
||||
return AABB {
|
||||
.min = tmin,
|
||||
.max = tmax,
|
||||
};
|
||||
}
|
||||
void adjust(const Math::Vector vertex)
|
||||
void adjust(const Vector vertex)
|
||||
{
|
||||
min.x = std::min(min.x, vertex.x);
|
||||
min.y = std::min(min.y, vertex.y);
|
||||
@@ -89,12 +137,12 @@ struct AABB
|
||||
AABB combine(const AABB& other) const
|
||||
{
|
||||
return AABB {
|
||||
.min = Math::Vector(
|
||||
.min = Vector(
|
||||
std::min(min.x, other.min.x),
|
||||
std::min(min.y, other.min.y),
|
||||
std::min(min.z, other.min.z)
|
||||
),
|
||||
.max = Math::Vector (
|
||||
.max = Vector (
|
||||
std::max(max.x, other.max.x),
|
||||
std::max(max.y, other.max.y),
|
||||
std::max(max.z, other.max.z)
|
||||
|
||||
@@ -15,14 +15,14 @@ struct Camera
|
||||
Camera();
|
||||
~Camera();
|
||||
|
||||
Math::Matrix4 getViewMatrix() const
|
||||
Matrix4 getViewMatrix() const
|
||||
{
|
||||
assert (!bNeedsViewBuild);
|
||||
return viewMatrix;
|
||||
}
|
||||
Math::Vector getCameraPosition() const
|
||||
Vector getCameraPosition() const
|
||||
{
|
||||
return Math::Vector(viewMatrix[3]);
|
||||
return Vector(viewMatrix[3]);
|
||||
}
|
||||
void setViewport(Gfx::PViewport viewport);
|
||||
void mouseMove(float deltaX, float deltaY);
|
||||
@@ -30,7 +30,7 @@ struct Camera
|
||||
void moveX(float amount);
|
||||
void moveY(float amount);
|
||||
void buildViewMatrix();
|
||||
Math::Matrix4 viewMatrix;
|
||||
Matrix4 viewMatrix;
|
||||
//Transforms relative to actor
|
||||
float yaw;
|
||||
float pitch;
|
||||
|
||||
@@ -13,7 +13,7 @@ enum class ColliderType
|
||||
};
|
||||
struct Collider
|
||||
{
|
||||
ColliderType type;
|
||||
ColliderType type = ColliderType::STATIC;
|
||||
AABB boundingbox;
|
||||
ShapeBase physicsMesh;
|
||||
Collider transform(const Transform& transform) const;
|
||||
|
||||
@@ -8,10 +8,10 @@ namespace Component
|
||||
struct RigidBody
|
||||
{
|
||||
float mass = 1.0f;
|
||||
Math::Vector force;
|
||||
Math::Vector torque;
|
||||
Math::Vector linearMomentum;
|
||||
Math::Vector angularMomentum;
|
||||
Vector force;
|
||||
Vector torque;
|
||||
Vector linearMomentum;
|
||||
Vector angularMomentum;
|
||||
};
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "ShapeBase.h"
|
||||
#include "AABB.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Component;
|
||||
@@ -20,13 +21,13 @@ struct ComputationState
|
||||
|
||||
/* volume integrals */
|
||||
float T0;
|
||||
Math::Vector T1, T2, TP;
|
||||
Vector T1, T2, TP;
|
||||
};
|
||||
|
||||
struct Face
|
||||
{
|
||||
StaticArray<Math::Vector, 3> vertices;
|
||||
Math::Vector normal;
|
||||
StaticArray<Vector, 3> vertices;
|
||||
Vector normal;
|
||||
float w;
|
||||
};
|
||||
|
||||
@@ -126,7 +127,7 @@ void computeFaceIntegrals(Face& f, ComputationState& state)
|
||||
+ w * (2 * (n[state.A] * state.Paa + n[state.B] * state.Pab) + w * state.Pa));
|
||||
}
|
||||
|
||||
void computeVolumeIntegrals(const Array<Math::Vector> vertices, const Array<uint32>& indices, ComputationState& state)
|
||||
void computeVolumeIntegrals(const Array<Vector> vertices, const Array<uint32>& indices, ComputationState& state)
|
||||
{
|
||||
std::memset(&state, 0, sizeof(ComputationState));
|
||||
for (size_t i = 0; i < indices.size(); i+=3)
|
||||
@@ -138,8 +139,8 @@ void computeVolumeIntegrals(const Array<Math::Vector> vertices, const Array<uint
|
||||
vertices[indices[i+2]],
|
||||
};
|
||||
|
||||
Math::Vector e1 = f.vertices[2] - f.vertices[0];
|
||||
Math::Vector e2 = f.vertices[1] - f.vertices[0];
|
||||
Vector e1 = f.vertices[2] - f.vertices[0];
|
||||
Vector e2 = f.vertices[1] - f.vertices[0];
|
||||
f.normal = glm::normalize(glm::cross(e1, e2));
|
||||
f.w = - f.normal.x * f.vertices[0].x
|
||||
- f.normal.y * f.vertices[0].y
|
||||
@@ -171,13 +172,13 @@ void computeVolumeIntegrals(const Array<Math::Vector> vertices, const Array<uint
|
||||
state.TP /= 2.0f;
|
||||
}
|
||||
|
||||
void computePhysicsParamsForMesh(Array<Math::Vector>& vertices, const Array<uint32_t>& indices, Math::Matrix3& bodyInertia, Math::Vector& centerOfMass, float& mass)
|
||||
void computePhysicsParamsForMesh(Array<Vector>& vertices, const Array<uint32_t>& indices, Matrix3& bodyInertia, Vector& centerOfMass, float& mass)
|
||||
{
|
||||
ComputationState state;
|
||||
computeVolumeIntegrals(vertices, indices, state);
|
||||
float density = 1;
|
||||
mass = density * state.T0;
|
||||
Math::Vector r = state.T1 / state.T0;
|
||||
Vector r = state.T1 / state.T0;
|
||||
centerOfMass = r;
|
||||
bodyInertia[0][0] = density * (state.T2.y + state.T2.z);
|
||||
bodyInertia[1][1] = density * (state.T2.z + state.T2.x);
|
||||
@@ -194,7 +195,12 @@ void computePhysicsParamsForMesh(Array<Math::Vector>& vertices, const Array<uint
|
||||
bodyInertia[2][1] = bodyInertia[1][2] += mass * r.z * r.x;
|
||||
}
|
||||
|
||||
ShapeBase::ShapeBase(Array<Math::Vector> vertices, Array<uint32> indices)
|
||||
ShapeBase::ShapeBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ShapeBase::ShapeBase(Array<Vector> vertices, Array<uint32> indices)
|
||||
: vertices(vertices)
|
||||
, indices(indices)
|
||||
{
|
||||
@@ -206,17 +212,17 @@ ShapeBase ShapeBase::transform(const Component::Transform& transform) const
|
||||
ShapeBase result = *this;
|
||||
for(auto& vert : result.vertices)
|
||||
{
|
||||
vert = transform.toMatrix() * Math::Vector4(vert, 1.0f);
|
||||
vert = transform.toMatrix() * Vector4(vert, 1.0f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShapeBase::addCollider(Array<Math::Vector> verts, Array<uint32> inds, Math::Matrix4 matrix)
|
||||
void ShapeBase::addCollider(Array<Vector> verts, Array<uint32> inds, Matrix4 matrix)
|
||||
{
|
||||
size_t indOffset = vertices.size();
|
||||
for(auto vert : verts)
|
||||
{
|
||||
vertices.add(Math::Vector(matrix * Math::Vector4(vert, 1.0f)));
|
||||
vertices.add(Vector(matrix * Vector4(vert, 1.0f)));
|
||||
}
|
||||
for(auto ind : inds)
|
||||
{
|
||||
@@ -224,3 +230,39 @@ void ShapeBase::addCollider(Array<Math::Vector> verts, Array<uint32> inds, Math:
|
||||
}
|
||||
computePhysicsParamsForMesh(vertices, indices, bodyInertia, centerOfMass, mass);
|
||||
}
|
||||
|
||||
void ShapeBase::visualize() const
|
||||
{
|
||||
for(uint32 i = 0; i < indices.size(); i+=3)
|
||||
{
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+0]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+1]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+1]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+2]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+2]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+0]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "Containers/Array.h"
|
||||
#include "Transform.h"
|
||||
#include "Graphics/DebugVertex.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -8,13 +9,15 @@ namespace Component
|
||||
{
|
||||
struct ShapeBase
|
||||
{
|
||||
ShapeBase(Array<Math::Vector> vertices, Array<uint32> indices);
|
||||
ShapeBase();
|
||||
ShapeBase(Array<Vector> vertices, Array<uint32> indices);
|
||||
ShapeBase transform(const Component::Transform& transform) const;
|
||||
void addCollider(Array<Math::Vector> vertices, Array<uint32> indices, Math::Matrix4 matrix);
|
||||
Math::Vector centerOfMass;
|
||||
void addCollider(Array<Vector> vertices, Array<uint32> indices, Matrix4 matrix);
|
||||
void visualize() const;
|
||||
Vector centerOfMass;
|
||||
float mass;
|
||||
Math::Matrix3 bodyInertia;
|
||||
Array<Math::Vector> vertices;
|
||||
Matrix3 bodyInertia;
|
||||
Array<Vector> vertices;
|
||||
Array<uint32> indices;
|
||||
};
|
||||
} // namespace Component
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Component
|
||||
{
|
||||
struct StaticMesh
|
||||
{
|
||||
StaticMesh() {}
|
||||
StaticMesh(PMeshAsset mesh) : mesh(mesh) {}
|
||||
PMeshAsset mesh;
|
||||
};
|
||||
} // namespace Component
|
||||
|
||||
@@ -5,55 +5,55 @@ using namespace Seele::Component;
|
||||
DEFINE_COMPONENT(Transform)
|
||||
|
||||
|
||||
void Transform::setPosition(Math::Vector pos)
|
||||
void Transform::setPosition(Vector pos)
|
||||
{
|
||||
transform.setPosition(pos);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void Transform::setRotation(Math::Quaternion quat)
|
||||
void Transform::setRotation(Quaternion quat)
|
||||
{
|
||||
transform.setRotation(quat);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void Transform::setScale(Math::Vector scale)
|
||||
void Transform::setScale(Vector scale)
|
||||
{
|
||||
transform.setScale(scale);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void Transform::setRelativeLocation(Math::Vector location)
|
||||
void Transform::setRelativeLocation(Vector location)
|
||||
{
|
||||
transform = Math::Transform(location, transform.getRotation(), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::setRelativeRotation(Math::Vector rotation)
|
||||
void Transform::setRelativeRotation(Vector rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), Math::Quaternion(rotation), transform.getScale());
|
||||
transform = Math::Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::setRelativeRotation(Math::Quaternion rotation)
|
||||
void Transform::setRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), rotation, transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::setRelativeScale(Math::Vector scale)
|
||||
void Transform::setRelativeScale(Vector scale)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation(), scale);
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::addRelativeLocation(Math::Vector translation)
|
||||
void Transform::addRelativeLocation(Vector translation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::addRelativeRotation(Math::Vector rotation)
|
||||
void Transform::addRelativeRotation(Vector rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * Math::Quaternion(rotation), transform.getScale());
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * Quaternion(rotation), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::addRelativeRotation(Math::Quaternion rotation)
|
||||
void Transform::addRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * rotation, transform.getScale());
|
||||
dirty = true;
|
||||
|
||||
@@ -8,31 +8,31 @@ namespace Component
|
||||
{
|
||||
struct Transform
|
||||
{
|
||||
Math::Vector getPosition() const { return transform.getPosition(); }
|
||||
Math::Quaternion getRotation() const { return transform.getRotation(); }
|
||||
Math::Vector getScale() const { return transform.getScale(); }
|
||||
Vector getPosition() const { return transform.getPosition(); }
|
||||
Quaternion getRotation() const { return transform.getRotation(); }
|
||||
Vector getScale() const { return transform.getScale(); }
|
||||
|
||||
Math::Vector getForward() const { return transform.getForward(); }
|
||||
Math::Vector getUp() const { return transform.getUp(); }
|
||||
Math::Vector getRight() const { return transform.getRight(); }
|
||||
Vector getForward() const { return transform.getForward(); }
|
||||
Vector getUp() const { return transform.getUp(); }
|
||||
Vector getRight() const { return transform.getRight(); }
|
||||
|
||||
Math::Matrix4 toMatrix() const { return transform.toMatrix(); }
|
||||
Matrix4 toMatrix() const { return transform.toMatrix(); }
|
||||
|
||||
bool isDirty() const { return dirty; }
|
||||
void clean() { dirty = false; }
|
||||
|
||||
void setPosition(Math::Vector pos);
|
||||
void setRotation(Math::Quaternion quat);
|
||||
void setScale(Math::Vector scale);
|
||||
void setPosition(Vector pos);
|
||||
void setRotation(Quaternion quat);
|
||||
void setScale(Vector scale);
|
||||
|
||||
void setRelativeLocation(Math::Vector location);
|
||||
void setRelativeRotation(Math::Quaternion rotation);
|
||||
void setRelativeRotation(Math::Vector rotation);
|
||||
void setRelativeScale(Math::Vector scale);
|
||||
void setRelativeLocation(Vector location);
|
||||
void setRelativeRotation(Quaternion rotation);
|
||||
void setRelativeRotation(Vector rotation);
|
||||
void setRelativeScale(Vector scale);
|
||||
|
||||
void addRelativeLocation(Math::Vector translation);
|
||||
void addRelativeRotation(Math::Quaternion rotation);
|
||||
void addRelativeRotation(Math::Vector rotation);
|
||||
void addRelativeLocation(Vector translation);
|
||||
void addRelativeRotation(Quaternion rotation);
|
||||
void addRelativeRotation(Vector rotation);
|
||||
private:
|
||||
bool dirty = true;
|
||||
Math::Transform transform;
|
||||
|
||||
Reference in New Issue
Block a user