WIP on materials
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Physics3D/PhysWorld3D.hpp>
|
||||
#include <Nazara/Core/MemoryHelper.hpp>
|
||||
#include <Newton/Newton.h>
|
||||
#include <cassert>
|
||||
#include <Nazara/Physics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -15,6 +17,8 @@ namespace Nz
|
||||
{
|
||||
m_world = NewtonCreate();
|
||||
NewtonWorldSetUserData(m_world, this);
|
||||
|
||||
m_materialIds.emplace("default", NewtonMaterialGetDefaultGroupID(m_world));
|
||||
}
|
||||
|
||||
PhysWorld3D::~PhysWorld3D()
|
||||
@@ -22,6 +26,16 @@ namespace Nz
|
||||
NewtonDestroy(m_world);
|
||||
}
|
||||
|
||||
int PhysWorld3D::CreateMaterial(Nz::String name)
|
||||
{
|
||||
NazaraAssert(m_materialIds.find(name) == m_materialIds.end(), "Material \"" + name + "\" already exists");
|
||||
|
||||
int materialId = NewtonMaterialCreateGroupID(m_world);
|
||||
m_materialIds.emplace(std::move(name), materialId);
|
||||
|
||||
return materialId;
|
||||
}
|
||||
|
||||
Vector3f PhysWorld3D::GetGravity() const
|
||||
{
|
||||
return m_gravity;
|
||||
@@ -32,6 +46,14 @@ namespace Nz
|
||||
return m_world;
|
||||
}
|
||||
|
||||
int PhysWorld3D::GetMaterial(const Nz::String& name)
|
||||
{
|
||||
auto it = m_materialIds.find(name);
|
||||
NazaraAssert(it != m_materialIds.end(), "Material \"" + name + "\" does not exists");
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
float PhysWorld3D::GetStepSize() const
|
||||
{
|
||||
return m_stepSize;
|
||||
@@ -52,6 +74,22 @@ namespace Nz
|
||||
m_stepSize = stepSize;
|
||||
}
|
||||
|
||||
void PhysWorld3D::SetMaterialCollisionCallback(int firstMaterial, int secondMaterial, CollisionCallback callback)
|
||||
{
|
||||
static_assert(sizeof(Nz::UInt64) >= 2 * sizeof(int), "Oops");
|
||||
|
||||
auto callbackPtr = std::make_unique<Callback>();
|
||||
callbackPtr->collisionCallback = std::move(callback);
|
||||
|
||||
NewtonMaterialSetCollisionCallback(m_world, firstMaterial, secondMaterial, callbackPtr.get(), nullptr, ProcessContact);
|
||||
|
||||
Nz::UInt64 firstMaterialId(firstMaterial);
|
||||
Nz::UInt64 secondMaterialId(secondMaterial);
|
||||
|
||||
Nz::UInt64 callbackIndex = firstMaterialId << 32 | secondMaterialId;
|
||||
m_callbacks[callbackIndex] = std::move(callbackPtr);
|
||||
}
|
||||
|
||||
void PhysWorld3D::Step(float timestep)
|
||||
{
|
||||
m_timestepAccumulator += timestep;
|
||||
@@ -62,4 +100,32 @@ namespace Nz
|
||||
m_timestepAccumulator -= m_stepSize;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysWorld3D::ProcessContact(const NewtonJoint* const contactJoint, float timestep, int threadIndex)
|
||||
{
|
||||
Nz::RigidBody3D* bodyA = static_cast<Nz::RigidBody3D*>(NewtonBodyGetUserData(NewtonJointGetBody0(contactJoint)));
|
||||
Nz::RigidBody3D* bodyB = static_cast<Nz::RigidBody3D*>(NewtonBodyGetUserData(NewtonJointGetBody1(contactJoint)));
|
||||
assert(bodyA && bodyB);
|
||||
|
||||
using ContactJoint = void*;
|
||||
|
||||
// Query all joints first, to prevent removing a joint from the list while iterating on it
|
||||
Nz::StackArray<ContactJoint> contacts = NazaraStackAllocationNoInit(ContactJoint, NewtonContactJointGetContactCount(contactJoint));
|
||||
std::size_t contactIndex = 0;
|
||||
for (ContactJoint contact = NewtonContactJointGetFirstContact(contactJoint); contact; contact = NewtonContactJointGetNextContact(contactJoint, contact))
|
||||
{
|
||||
assert(contactIndex < contacts.size());
|
||||
contacts[contactIndex++] = contact;
|
||||
}
|
||||
|
||||
for (ContactJoint contact : contacts)
|
||||
{
|
||||
NewtonMaterial* material = NewtonContactGetMaterial(contact);
|
||||
Callback* callbackData = static_cast<Callback*>(NewtonMaterialGetMaterialPairUserData(material));
|
||||
assert(callbackData);
|
||||
|
||||
if (!callbackData->collisionCallback(*bodyA, *bodyB))
|
||||
NewtonContactJointRemoveContact(contactJoint, contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,11 @@ namespace Nz
|
||||
return center;
|
||||
}
|
||||
|
||||
int RigidBody3D::GetMaterial() const
|
||||
{
|
||||
return NewtonBodyGetMaterialGroupID(m_body);
|
||||
}
|
||||
|
||||
const Matrix4f& RigidBody3D::GetMatrix() const
|
||||
{
|
||||
return m_matrix;
|
||||
@@ -228,6 +233,11 @@ namespace Nz
|
||||
return m_matrix.GetRotation();
|
||||
}
|
||||
|
||||
void* RigidBody3D::GetUserdata() const
|
||||
{
|
||||
return m_userdata;
|
||||
}
|
||||
|
||||
PhysWorld3D* RigidBody3D::GetWorld() const
|
||||
{
|
||||
return m_world;
|
||||
@@ -322,6 +332,16 @@ namespace Nz
|
||||
NewtonBodySetCentreOfMass(m_body, center);
|
||||
}
|
||||
|
||||
void RigidBody3D::SetMaterial(const Nz::String& materialName)
|
||||
{
|
||||
SetMaterial(m_world->GetMaterial(materialName));
|
||||
}
|
||||
|
||||
void RigidBody3D::SetMaterial(int materialIndex)
|
||||
{
|
||||
NewtonBodySetMaterialGroupID(m_body, materialIndex);
|
||||
}
|
||||
|
||||
void RigidBody3D::SetPosition(const Vector3f& position)
|
||||
{
|
||||
m_matrix.SetTranslation(position);
|
||||
@@ -336,6 +356,11 @@ namespace Nz
|
||||
UpdateBody();
|
||||
}
|
||||
|
||||
void RigidBody3D::SetUserdata(void* ud)
|
||||
{
|
||||
m_userdata = ud;
|
||||
}
|
||||
|
||||
RigidBody3D& RigidBody3D::operator=(const RigidBody3D& object)
|
||||
{
|
||||
RigidBody3D physObj(object);
|
||||
|
||||
Reference in New Issue
Block a user