Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
markaren committed Mar 13, 2024
1 parent 5ba2d82 commit e6b5397
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 45 deletions.
106 changes: 68 additions & 38 deletions examples/extras/physics/PxEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "threepp/geometries/CapsuleGeometry.hpp"
#include "threepp/geometries/CylinderGeometry.hpp"
#include "threepp/geometries/SphereGeometry.hpp"
#include "threepp/objects/InstancedMesh.hpp"
#include "threepp/objects/LineSegments.hpp"
#include "threepp/objects/Mesh.hpp"
#include "threepp/objects/Points.hpp"
Expand Down Expand Up @@ -137,17 +138,28 @@ class PxEngine: public threepp::Object3D {

threepp::Matrix4 tmpMat;
threepp::Quaternion tmpQuat;
for (auto [obj, rb] : bodies) {
for (auto& [obj, rb] : bodies) {

obj->updateMatrixWorld();

const auto& t = rb->getGlobalPose();
const auto& pos = t.p;
const auto& quat = t.q;
if (auto instanced = obj->as<threepp::InstancedMesh>()) {

tmpQuat.set(quat.x, quat.y, quat.z, quat.w);
obj->matrix->makeRotationFromQuaternion(tmpQuat);
obj->matrix->setPosition(pos.x, pos.y, pos.z);
auto& array = instanced->instanceMatrix()->array();
for (int i = 0; i < instanced->count(); i++) {
auto pose = threepp::Matrix4().fromArray(physx::PxMat44(rb[i]->getGlobalPose()).front());
pose.premultiply(tmpMat.copy(*obj->matrix).invert());
for (auto j = 0; j < 16; j++) {
array[i * 16 + j] = pose[j];
}
}

instanced->instanceMatrix()->needsUpdate();

} else {

const auto pose = physx::PxMat44(rb.front()->getGlobalPose());
obj->matrix->fromArray(pose.front());
}
obj->matrix->premultiply(tmpMat.copy(*obj->parent->matrixWorld).invert());
}

Expand All @@ -170,10 +182,10 @@ class PxEngine: public threepp::Object3D {
return;
}

auto material = toPxMaterial(info._material);

obj.updateMatrixWorld();

auto material = toPxMaterial(info._material);

std::vector<physx::PxShape*> shapes;

if (info._useVisualGeometryAsCollider) {
Expand All @@ -190,39 +202,57 @@ class PxEngine: public threepp::Object3D {
shapes.emplace_back(shape);
}


if (info._type == threepp::RigidBodyInfo::Type::STATIC) {
auto staticActor = PxCreateStatic(*physics, toPxTransform(*obj.matrixWorld), *shapes.front());

for (unsigned i = 1; i < shapes.size(); i++) {
auto shape = shapes[i];
staticActor->attachShape(*shape);
staticActor->attachShape(*shapes[i]);
}

bodies[&obj] = staticActor;
bodies[&obj].emplace_back(staticActor);
} else {
auto rigidActor = PxCreateDynamic(*physics, toPxTransform(*obj.matrixWorld), *shapes.front(), 1.f);

rigidActor->setSolverIterationCounts(30, 2);
auto createSingle = [&](float* data) {
auto rigidActor = PxCreateDynamic(*physics, physx::PxTransform(physx::PxMat44(data)), *shapes.front(), 1.f);
rigidActor->setSolverIterationCounts(30, 2);

for (unsigned i = 1; i < shapes.size(); i++) {
auto shape = shapes[i];
rigidActor->attachShape(*shape);
}
for (unsigned i = 1; i < shapes.size(); i++) {
rigidActor->attachShape(*shapes[i]);
}

if (info._mass) {
physx::PxRigidBodyExt::setMassAndUpdateInertia(*rigidActor, *info._mass);
} else {
physx::PxRigidBodyExt::updateMassAndInertia(*rigidActor, 1.f);
}
return rigidActor;
};

if (info._mass) {
physx::PxRigidBodyExt::setMassAndUpdateInertia(*rigidActor, *info._mass);
if (auto instanced = obj.as<threepp::InstancedMesh>()) {

const auto& array = instanced->instanceMatrix()->array();

threepp::Matrix4 tmp;
for (unsigned i = 0; i < instanced->count(); i++) {
unsigned index = i * 16;
tmp.fromArray(array, index);
tmp.premultiply(*obj.matrixWorld);
auto body = createSingle(tmp.elements.data());
bodies[&obj].emplace_back(body);
}
} else {
physx::PxRigidBodyExt::updateMassAndInertia(*rigidActor, 1.f);
bodies[&obj].emplace_back(createSingle(obj.matrixWorld->elements.data()));
}

bodies[&obj] = rigidActor;
}

for (auto shape : shapes) {
shape->release();
}

scene->addActor(*bodies[&obj]);
for (auto actor : bodies[&obj]) {
scene->addActor(*actor);
}

obj.matrixAutoUpdate = false;
obj.addEventListener("remove", &onMeshRemovedListener);
Expand All @@ -233,8 +263,8 @@ class PxEngine: public threepp::Object3D {
o1->updateMatrixWorld();
if (o2) o2->updateMatrixWorld();

auto rb1 = bodies.at(o1);
auto rb2 = o2 ? bodies.at(o2) : nullptr;
auto rb1 = getBody(*o1);
auto rb2 = o2 ? getBody(*o2) : nullptr;

threepp::Matrix4 f1;
f1.makeRotationFromQuaternion(threepp::Quaternion().setFromUnitVectors({1, 0, 0}, axis));
Expand All @@ -252,9 +282,9 @@ class PxEngine: public threepp::Object3D {
return joint;
}

physx::PxRigidActor* getBody(threepp::Object3D& mesh) {
physx::PxRigidActor* getBody(threepp::Object3D& mesh, size_t index = 0) {
if (!bodies.count(&mesh)) return nullptr;
return bodies.at(&mesh);
return bodies.at(&mesh)[index];
}

template<class JointType>
Expand All @@ -274,8 +304,8 @@ class PxEngine: public threepp::Object3D {

~PxEngine() override {

for (auto [_, rb] : bodies) {
rb->release();
for (auto [_, list] : bodies) {
for (auto rb : list) rb->release();
}

for (auto material : materials) material->release();
Expand All @@ -300,7 +330,7 @@ class PxEngine: public threepp::Object3D {
physx::PxScene* scene;
std::vector<physx::PxMaterial*> materials;

std::unordered_map<threepp::Object3D*, physx::PxRigidActor*> bodies;
std::unordered_map<threepp::Object3D*, std::vector<physx::PxRigidActor*>> bodies;
std::unordered_map<threepp::Object3D*, std::vector<physx::PxJoint*>> joints;

std::shared_ptr<threepp::Mesh> debugTriangles = threepp::Mesh::create();
Expand All @@ -320,17 +350,17 @@ class PxEngine: public threepp::Object3D {
case 0:// Sphere
{
threepp::SphereCollider sphere = std::get<threepp::SphereCollider>(collider);
return physics->createShape(physx::PxSphereGeometry(sphere.radius), *material, true);
return physics->createShape(physx::PxSphereGeometry(sphere.radius), *material, false);
}
case 1:// Box
{
threepp::BoxCollider box = std::get<threepp::BoxCollider>(collider);
return physics->createShape(physx::PxBoxGeometry(box.halfWidth, box.halfHeight, box.halfDepth), *material, true);
return physics->createShape(physx::PxBoxGeometry(box.halfWidth, box.halfHeight, box.halfDepth), *material, false);
}
case 2:// Capsule
{
threepp::CapsuleCollider box = std::get<threepp::CapsuleCollider>(collider);
return physics->createShape(physx::PxCapsuleGeometry(box.radius, box.halfHeight), *material, true);
return physics->createShape(physx::PxCapsuleGeometry(box.radius, box.halfHeight), *material, false);
}
default:
return nullptr;
Expand All @@ -344,13 +374,13 @@ class PxEngine: public threepp::Object3D {
const auto type = geometry->type();
if (type == "BoxGeometry") {
const auto box = dynamic_cast<const threepp::BoxGeometry*>(geometry);
return physics->createShape(physx::PxBoxGeometry(physx::PxVec3{box->width / 2, box->height / 2, box->depth / 2}), *material, true);
return physics->createShape(physx::PxBoxGeometry(physx::PxVec3{box->width / 2, box->height / 2, box->depth / 2}), *material, false);
} else if (type == "SphereGeometry") {
const auto sphere = dynamic_cast<const threepp::SphereGeometry*>(geometry);
return physics->createShape(physx::PxSphereGeometry(sphere->radius), *material, true);
return physics->createShape(physx::PxSphereGeometry(sphere->radius), *material, false);
} else if (type == "CapsuleGeometry") {
const auto cap = dynamic_cast<const threepp::CapsuleGeometry*>(geometry);
return physics->createShape(physx::PxCapsuleGeometry(cap->radius, cap->length / 2), *material, true);
return physics->createShape(physx::PxCapsuleGeometry(cap->radius, cap->length / 2), *material, false);
} else {

if (auto pos = geometry->getAttribute<float>("position")) {
Expand Down Expand Up @@ -527,7 +557,7 @@ class PxEngine: public threepp::Object3D {
auto m = static_cast<threepp::Object3D*>(event.target);
if (scope->bodies.count(m)) {
auto rb = scope->bodies.at(m);
scope->scene->removeActor(*rb);
scope->scene->removeActor(*rb.front());
scope->bodies.erase(m);
}
m->removeEventListener("remove", this);
Expand Down
40 changes: 33 additions & 7 deletions examples/extras/physics/physx_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ namespace {
void onKeyReleased(KeyEvent evt) override;

private:
float speed = 0.25;
float speed = 2;
std::vector<physx::PxRevoluteJoint*> joints;
};

void KeyController::onKeyPressed(KeyEvent evt) {
if (evt.key == Key::NUM_1) {
joints[0]->setDriveVelocity(-5);
joints[0]->setDriveVelocity(-speed);
} else if (evt.key == Key::NUM_2) {
joints[0]->setDriveVelocity(5);
joints[0]->setDriveVelocity(speed);
} else if (evt.key == Key::NUM_3) {
joints[1]->setDriveVelocity(-5);
joints[1]->setDriveVelocity(-speed);
} else if (evt.key == Key::NUM_4) {
joints[1]->setDriveVelocity(5);
joints[1]->setDriveVelocity(speed);
} else if (evt.key == Key::NUM_5) {
joints[2]->setDriveVelocity(-5);
joints[2]->setDriveVelocity(-speed);
} else if (evt.key == Key::NUM_6) {
joints[2]->setDriveVelocity(5);
joints[2]->setDriveVelocity(speed);
}
}

Expand All @@ -62,6 +62,24 @@ namespace {
}
}

void setupInstancedMesh(InstancedMesh& mesh) {

Matrix4 matrix;
size_t index = 0;
int amount = std::cbrt(mesh.count());
float offset = static_cast<float>(amount - 1) / 2;
for (int x = 0; x < amount; x++) {
for (int y = 0; y < amount; y++) {
for (int z = 0; z < amount; z++) {
matrix.setPosition(offset - float(x), offset - float(y), offset - float(z));
mesh.setMatrixAt(index, matrix);
mesh.setColorAt(index, Color::gray);
++index;
}
}
}
}

auto spawnObject() {

auto geometry = SphereGeometry::create(0.1);
Expand Down Expand Up @@ -125,6 +143,11 @@ int main() {
ground->receiveShadow = true;
scene.add(ground);

auto instanced = InstancedMesh::create(SphereGeometry::create(0.25), MeshBasicMaterial::create(), std::pow(3, 3));
setupInstancedMesh(*instanced);
instanced->position.y = 50;
scene.add(instanced);

auto light1 = AmbientLight::create(Color::white, 0.3f);
scene.add(light1);

Expand Down Expand Up @@ -156,6 +179,9 @@ int main() {
auto meshBody = RigidBodyInfo{}.setMass(20).setMaterialProperties(1, 0);
mesh->userData["rigidbodyInfo"] = meshBody;

auto instancedBody = RigidBodyInfo();
instanced->userData["rigidbodyInfo"] = instancedBody;

engine.setup(scene);
scene.add(engine);

Expand Down

0 comments on commit e6b5397

Please sign in to comment.