import asset - physics WIP

This commit is contained in:
Mikulas Florek 2015-05-18 23:31:47 +02:00
parent d410881377
commit c36911e26d
18 changed files with 593 additions and 180 deletions

View file

@ -241,10 +241,12 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\physics\physics_geometry_manager.cpp" />
<ClCompile Include="..\..\..\src\physics\physics_scene.cpp" />
<ClCompile Include="..\..\..\src\physics\physics_system.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\physics\physics_geometry_manager.h" />
<ClInclude Include="..\..\..\src\physics\physics_scene.h" />
<ClInclude Include="..\..\..\src\physics\physics_system.h" />
</ItemGroup>

View file

@ -3,9 +3,11 @@
<ItemGroup>
<ClCompile Include="..\..\..\src\physics\physics_scene.cpp" />
<ClCompile Include="..\..\..\src\physics\physics_system.cpp" />
<ClCompile Include="..\..\..\src\physics\physics_geometry_manager.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\physics\physics_scene.h" />
<ClInclude Include="..\..\..\src\physics\physics_system.h" />
<ClInclude Include="..\..\..\src\physics\physics_geometry_manager.h" />
</ItemGroup>
</Project>

View file

@ -23,6 +23,7 @@ namespace Lumix
static const uint32_t PIPELINE = 0xbbcf4595; //PIPELINE
static const uint32_t ANIMATION = 0xc9909a33; //ANIMATION
static const uint32_t BITMAP_FONT = 0x89DEEEB4; //BITMAP_FONT
static const uint32_t PHYSICS = 0xE77419F9; //PHYSICS
ResourceManager(IAllocator& allocator);
~ResourceManager();

View file

@ -7,7 +7,7 @@ namespace Lumix
void enableFloatingPointTraps(bool enable)
{
unsigned int cw = _control87(0, 0) & MCW_EM;
/*unsigned int cw = _control87(0, 0) & MCW_EM;
if (enable)
{
cw &= ~(_EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID | _EM_DENORMAL); // can not enable _EM_INEXACT because it is common in QT
@ -16,7 +16,7 @@ void enableFloatingPointTraps(bool enable)
{
cw |= _EM_OVERFLOW | _EM_INVALID | _EM_DENORMAL; // can not enable _EM_INEXACT because it is common in QT
}
_control87(cw, MCW_EM);
_control87(cw, MCW_EM);*/
}

View file

@ -204,11 +204,10 @@ struct PipelineImpl : public Pipeline
else
{
parseFramebuffers(m_lua_state);
registerCFunctions();
decrementDepCount();
}
registerCFunctions();
decrementDepCount();
}
else
{

View file

@ -0,0 +1,203 @@
#include "physics_geometry_manager.h"
#include "core/fs/file_system.h"
#include "core/fs/ifile.h"
#include "core/resource_manager.h"
#include "physics/physics_system.h"
#include <PxPhysicsAPI.h>
namespace Lumix
{
struct OutputStream : public physx::PxOutputStream
{
OutputStream(IAllocator& allocator)
: allocator(allocator)
{
data = (uint8_t*)allocator.allocate(sizeof(uint8_t) * 4096);
capacity = 4096;
size = 0;
}
~OutputStream()
{
allocator.deallocate(data);
}
virtual physx::PxU32 write(const void* src, physx::PxU32 count)
{
if (size + (int)count > capacity)
{
int new_capacity = Math::maxValue(size + (int)count, capacity + 4096);
uint8_t* new_data = (uint8_t*)allocator.allocate(sizeof(uint8_t) * new_capacity);
memcpy(new_data, data, size);
allocator.deallocate(data);
data = new_data;
capacity = new_capacity;
}
memcpy(data + size, src, count);
size += count;
return count;
}
uint8_t* data;
IAllocator& allocator;
int capacity;
int size;
};
struct InputStream : public physx::PxInputStream
{
InputStream(unsigned char* data, int size)
{
this->data = data;
this->size = size;
pos = 0;
}
virtual physx::PxU32 read(void* dest, physx::PxU32 count)
{
if (pos + (int)count <= size)
{
memcpy(dest, data + pos, count);
pos += count;
return count;
}
else
{
memcpy(dest, data + pos, size - pos);
int real_count = size - pos;
pos = size;
return real_count;
}
}
int pos;
int size;
unsigned char* data;
};
Resource* PhysicsGeometryManager::createResource(const Path& path)
{
return m_allocator.newObject<PhysicsGeometry>(path, getOwner(), m_allocator);
}
void PhysicsGeometryManager::destroyResource(Resource& resource)
{
m_allocator.deleteObject(static_cast<PhysicsGeometry*>(&resource));
}
PhysicsGeometry::PhysicsGeometry(const Path& path, ResourceManager& resource_manager, IAllocator& allocator)
: Resource(path, resource_manager, allocator)
, m_geometry(nullptr)
{
}
PhysicsGeometry::~PhysicsGeometry()
{
getAllocator().deleteObject(m_geometry);
}
void PhysicsGeometry::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
{
if (success)
{
Header header;
file->read(&header, sizeof(header));
if (header.m_magic != HEADER_MAGIC || header.m_version > (uint32_t)Versions::LAST)
{
onFailure();
fs.close(file);
return;
}
PhysicsSystem& system = static_cast<PhysicsGeometryManager*>(m_resource_manager.get(ResourceManager::PHYSICS))->getSystem();
uint32_t num_verts;
Array<Vec3> verts(getAllocator());
file->read(&num_verts, sizeof(num_verts));
verts.resize(num_verts);
file->read(&verts[0], sizeof(verts[0]) * verts.size());
m_is_convex = header.m_convex != 0;
if (!m_is_convex)
{
physx::PxTriangleMeshGeometry* geom = getAllocator().newObject<physx::PxTriangleMeshGeometry>();
m_geometry = geom;
uint32_t num_indices;
Array<uint32_t> tris(getAllocator());
file->read(&num_indices, sizeof(num_indices));
tris.resize(num_indices);
file->read(&tris[0], sizeof(tris[0]) * tris.size());
physx::PxTriangleMeshDesc meshDesc;
meshDesc.points.count = num_verts;
meshDesc.points.stride = sizeof(physx::PxVec3);
meshDesc.points.data = &verts[0];
meshDesc.triangles.count = num_indices / 3;
meshDesc.triangles.stride = 3 * sizeof(physx::PxU32);
meshDesc.triangles.data = &tris[0];
OutputStream writeBuffer(getAllocator());
system.getCooking()->cookTriangleMesh(meshDesc, writeBuffer);
InputStream readBuffer(writeBuffer.data, writeBuffer.size);
geom->triangleMesh = system.getPhysics()->createTriangleMesh(readBuffer);
}
else
{
physx::PxConvexMeshGeometry* geom = getAllocator().newObject<physx::PxConvexMeshGeometry>();
m_geometry = geom;
physx::PxConvexMeshDesc meshDesc;
meshDesc.points.count = verts.size();
meshDesc.points.stride = sizeof(Vec3);
meshDesc.points.data = &verts[0];
meshDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;
OutputStream writeBuffer(getAllocator());
bool status = system.getCooking()->cookConvexMesh(meshDesc, writeBuffer);
if (!status)
return;
InputStream readBuffer(writeBuffer.data, writeBuffer.size);
physx::PxConvexMesh* mesh = system.getPhysics()->createConvexMesh(readBuffer);
geom->convexMesh = mesh;
}
m_size = file->size();
decrementDepCount();
}
else
{
onFailure();
}
fs.close(file);
}
IAllocator& PhysicsGeometry::getAllocator()
{
return static_cast<PhysicsGeometryManager*>(m_resource_manager.get(ResourceManager::PHYSICS))->getAllocator();
}
void PhysicsGeometry::doUnload(void)
{
getAllocator().deleteObject(m_geometry);
m_geometry = nullptr;
onEmpty();
}
} // namespace Lumix

View file

@ -0,0 +1,80 @@
#pragma once
#include "core/lumix.h"
#include "core/resource.h"
#include "core/resource_manager_base.h"
namespace physx
{
class PxGeometry;
}
namespace Lumix
{
class PhysicsSystem;
class LUMIX_PHYSICS_API PhysicsGeometryManager : public ResourceManagerBase
{
public:
PhysicsGeometryManager(PhysicsSystem& system, IAllocator& allocator)
: ResourceManagerBase(allocator)
, m_allocator(allocator)
, m_system(system)
{}
~PhysicsGeometryManager() {}
IAllocator& getAllocator() { return m_allocator; }
PhysicsSystem& getSystem() { return m_system; }
protected:
virtual Resource* createResource(const Path& path) override;
virtual void destroyResource(Resource& resource) override;
private:
IAllocator& m_allocator;
PhysicsSystem& m_system;
};
class LUMIX_PHYSICS_API PhysicsGeometry : public Resource
{
public:
static const uint32_t HEADER_MAGIC = 0x5f4c5046; // '_LPF'
struct Header
{
uint32_t m_magic;
uint32_t m_version;
uint32_t m_convex;
};
enum class Versions : uint32_t
{
FIRST,
LAST
};
public:
PhysicsGeometry(const Path& path, ResourceManager& resource_manager, IAllocator& allocator);
~PhysicsGeometry();
physx::PxGeometry* getGeometry() { return m_geometry; }
private:
IAllocator& getAllocator();
virtual void doUnload(void) override;
virtual void loaded(FS::IFile* file, bool success, FS::FileSystem& fs) override;
private:
physx::PxGeometry* m_geometry;
bool m_is_convex;
};
} // namespace Lumix

View file

@ -16,8 +16,10 @@
#include "core/resource_manager_base.h"
#include "engine/engine.h"
#include "graphics/render_scene.h"
#include "graphics/renderer.h"
#include "graphics/texture.h"
#include "physics/physics_system.h"
#include "physics/physics_geometry_manager.h"
namespace Lumix
@ -140,6 +142,33 @@ struct PhysicsSceneImpl : public PhysicsScene
};
class RigidActor
{
public:
RigidActor(PhysicsSceneImpl& scene, IAllocator& allocator)
: m_resource(nullptr)
, m_physx_actor(nullptr)
, m_scene(scene)
{ }
void setEntity(const Entity& entity) { m_entity = entity; }
void setResource(PhysicsGeometry* resource);
Entity& getEntity() { return m_entity; }
void setPhysxActor(physx::PxRigidActor* actor);
physx::PxRigidActor* getPhysxActor() const { return m_physx_actor; }
PhysicsGeometry* getResource() const { return m_resource; }
private:
void onStateChanged(Resource::State old_state, Resource::State new_state);
private:
physx::PxRigidActor* m_physx_actor;
PhysicsGeometry* m_resource;
Entity m_entity;
PhysicsSceneImpl& m_scene;
};
PhysicsSceneImpl(IAllocator& allocator)
: m_allocator(allocator)
, m_controllers(m_allocator)
@ -212,7 +241,8 @@ struct PhysicsSceneImpl : public PhysicsScene
}
else if (cmp.type == MESH_ACTOR_HASH || cmp.type == BOX_ACTOR_HASH)
{
m_actors[cmp.index]->m_entity.index = -1;
m_actors[cmp.index]->getEntity().index = -1;
m_actors[cmp.index]->setPhysxActor(nullptr);
m_universe->destroyComponent(cmp);
}
else
@ -265,10 +295,9 @@ struct PhysicsSceneImpl : public PhysicsScene
Component createBoxRigidActor(Entity entity)
{
RigidActor* actor = m_allocator.newObject<RigidActor>(m_allocator);
RigidActor* actor = m_allocator.newObject<RigidActor>(*this, m_allocator);
m_actors.push(actor);
actor->m_source = "";
actor->m_entity = entity;
actor->setEntity(entity);
physx::PxBoxGeometry geom;
geom.halfExtents.x = 1;
@ -282,7 +311,7 @@ struct PhysicsSceneImpl : public PhysicsScene
physx::PxRigidStatic* physx_actor = PxCreateStatic(*m_system->getPhysics(), transform, geom, *m_default_material);
physx_actor->userData = (void*)entity.index;
m_scene->addActor(*physx_actor);
actor->m_physx_actor = physx_actor;
actor->setPhysxActor(physx_actor);
physx_actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, true);
Component cmp = m_universe->addComponent(entity, BOX_ACTOR_HASH, this, m_actors.size() - 1);
@ -293,18 +322,16 @@ struct PhysicsSceneImpl : public PhysicsScene
Component createMeshRigidActor(Entity entity)
{
RigidActor* actor = m_allocator.newObject<RigidActor>(m_allocator);
RigidActor* actor = m_allocator.newObject<RigidActor>(*this, m_allocator);
m_actors.push(actor);
actor->m_source = "";
actor->m_entity = entity;
actor->m_physx_actor = NULL;
actor->setEntity(entity);
Component cmp = m_universe->addComponent(entity, MESH_ACTOR_HASH, this, m_actors.size() - 1);
m_universe->componentCreated().invoke(cmp);
return cmp;
}
virtual void getHeightmap(Component cmp, string& str) override
{
str = m_terrains[cmp.index]->m_heightmap ? m_terrains[cmp.index]->m_heightmap->getPath().c_str() : "";
@ -364,127 +391,33 @@ struct PhysicsSceneImpl : public PhysicsScene
virtual void getShapeSource(Component cmp, string& str) override
{
str = m_actors[cmp.index]->m_source;
str = m_actors[cmp.index]->getResource() ? m_actors[cmp.index]->getResource()->getPath().c_str() : "";
}
virtual void setShapeSource(Component cmp, const string& str) override
{
ASSERT(m_actors[cmp.index]);
bool is_dynamic = isDynamic(cmp);
if (m_actors[cmp.index]->m_source == str && (!m_actors[cmp.index]->m_physx_actor || is_dynamic == !m_actors[cmp.index]->m_physx_actor->isRigidStatic()))
if (m_actors[cmp.index]->getResource()
&& m_actors[cmp.index]->getResource()->getPath() == str.c_str()
&& (!m_actors[cmp.index]->getPhysxActor() || is_dynamic == !m_actors[cmp.index]->getPhysxActor()->isRigidStatic()))
{
return;
}
physx::PxTriangleMeshGeometry geom;
createTriMesh(str.c_str(), geom);
ResourceManagerBase* manager = m_engine->getResourceManager().get(ResourceManager::PHYSICS);
PhysicsGeometry* geom_res = static_cast<PhysicsGeometry*>(manager->load(Lumix::Path(str.c_str())));
physx::PxTransform transform;
Matrix mtx;
cmp.entity.getMatrix(mtx);
matrix2Transform(mtx, transform);
m_actors[cmp.index]->setResource(geom_res);
if (m_actors[cmp.index] && m_actors[cmp.index]->m_physx_actor)
if (m_actors[cmp.index]->getPhysxActor())
{
m_scene->removeActor(*m_actors[cmp.index]->m_physx_actor);
m_actors[cmp.index]->m_physx_actor->release();
m_actors[cmp.index]->m_physx_actor = NULL;
}
physx::PxRigidActor* actor;
if (is_dynamic)
{
actor = PxCreateDynamic(*m_system->getPhysics(), transform, geom, *m_default_material, 1.0f);
}
else
{
actor = PxCreateStatic(*m_system->getPhysics(), transform, geom, *m_default_material);
}
if (actor)
{
actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, true);
actor->userData = (void*)cmp.entity.index;
m_scene->addActor(*actor);
m_actors[cmp.index]->m_physx_actor = actor;
m_actors[cmp.index]->m_source = str;
}
else
{
g_log_error.log("PhysX") << "Could not create PhysX mesh " << str.c_str();
m_scene->removeActor(*m_actors[cmp.index]->getPhysxActor());
m_actors[cmp.index]->setPhysxActor(nullptr);
}
}
void createTriMesh(const char* path, physx::PxTriangleMeshGeometry& geom)
{
FILE* fp;
fopen_s(&fp, path, "rb");
if (fp)
{
Array<Vec3> verts(m_allocator);
int num_verts, num_indices;
Array<uint32_t> tris(m_allocator);
fread(&num_verts, sizeof(num_verts), 1, fp);
verts.resize(num_verts);
fread(&verts[0], sizeof(Vec3), num_verts, fp);
fread(&num_indices, sizeof(num_indices), 1, fp);
tris.resize(num_indices);
fread(&tris[0], sizeof(uint32_t), num_indices, fp);
physx::PxTriangleMeshDesc meshDesc;
meshDesc.points.count = num_verts;
meshDesc.points.stride = sizeof(physx::PxVec3);
meshDesc.points.data = &verts[0];
meshDesc.triangles.count = num_indices / 3;
meshDesc.triangles.stride = 3 * sizeof(physx::PxU32);
meshDesc.triangles.data = &tris[0];
for (int i = 0; i < num_indices; ++i)
{
ASSERT(tris[i] < (uint32_t)verts.size());
}
OutputStream writeBuffer(m_allocator);
m_system->getCooking()->cookTriangleMesh(meshDesc, writeBuffer);
InputStream readBuffer(writeBuffer.data, writeBuffer.size);
geom.triangleMesh = m_system->getPhysics()->createTriangleMesh(readBuffer);
fclose(fp);
}
}
void createConvexGeom(const char* path, physx::PxConvexMeshGeometry& geom)
{
FILE* fp;
fopen_s(&fp, path, "rb");
if (fp)
{
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
Array<Vec3> vertices(m_allocator);
vertices.resize(size / sizeof(Vec3));
fread(&vertices[0], size, 1, fp);
fclose(fp);
physx::PxConvexMeshDesc meshDesc;
meshDesc.points.count = vertices.size();
meshDesc.points.stride = sizeof(Vec3);
meshDesc.points.data = &vertices[0];
meshDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;
OutputStream writeBuffer(m_allocator);
bool status = m_system->getCooking()->cookConvexMesh(meshDesc, writeBuffer);
if (!status)
return;
InputStream readBuffer(writeBuffer.data, writeBuffer.size);
physx::PxConvexMesh* mesh = m_system->getPhysics()->createConvexMesh(readBuffer);
geom.convexMesh = mesh;
}
}
void setControllerPosition(int index, const Vec3& pos)
{
@ -493,8 +426,12 @@ struct PhysicsSceneImpl : public PhysicsScene
}
virtual void render() override
virtual void render(Renderer& renderer) override
{
renderer.cleanup();
Shader& shader = renderer.getDebugShader();
renderer.applyShader(shader, 0);
m_scene->getNbActors(physx::PxActorTypeSelectionFlag::eRIGID_STATIC);
const physx::PxRenderBuffer& rb = m_scene->getRenderBuffer();
const physx::PxU32 num_lines = rb.getNbLines();
@ -527,10 +464,9 @@ struct PhysicsSceneImpl : public PhysicsScene
m_scene->fetchResults(true);
for (int i = 0; i < m_dynamic_actors.size(); ++i)
{
physx::PxTransform trans = m_dynamic_actors[i]->m_physx_actor->getGlobalPose();
m_dynamic_actors[i]->m_entity.setPosition(trans.p.x, trans.p.y, trans.p.z);
m_dynamic_actors[i]->m_entity.setRotation(trans.q.x, trans.q.y, trans.q.z, trans.q.w);
physx::PxTransform trans = m_dynamic_actors[i]->getPhysxActor()->getGlobalPose();
m_dynamic_actors[i]->getEntity().setPosition(trans.p.x, trans.p.y, trans.p.z);
m_dynamic_actors[i]->getEntity().setRotation(trans.q.x, trans.q.y, trans.q.z, trans.q.w);
}
Vec3 g(0, time_delta * -9.8f, 0);
for (int i = 0; i < m_controllers.size(); ++i)
@ -597,7 +533,7 @@ struct PhysicsSceneImpl : public PhysicsScene
{
for (int i = 0, c = m_dynamic_actors.size(); i < c; ++i)
{
if (m_dynamic_actors[i]->m_entity == entity)
if (m_dynamic_actors[i]->getEntity() == entity)
{
Vec3 pos = entity.getPosition();
physx::PxVec3 pvec(pos.x, pos.y, pos.z);
@ -605,7 +541,7 @@ struct PhysicsSceneImpl : public PhysicsScene
entity.getMatrix().getRotation(q);
physx::PxQuat pquat(q.x, q.y, q.z, q.w);
physx::PxTransform trans(pvec, pquat);
m_dynamic_actors[i]->m_physx_actor->setGlobalPose(trans, false);
m_dynamic_actors[i]->getPhysxActor()->setGlobalPose(trans, false);
return;
}
}
@ -623,7 +559,7 @@ struct PhysicsSceneImpl : public PhysicsScene
for (int i = 0, c = m_actors.size(); i < c; ++i)
{
if (m_actors[i]->m_entity == entity)
if (m_actors[i]->getEntity() == entity)
{
Vec3 pos = entity.getPosition();
physx::PxVec3 pvec(pos.x, pos.y, pos.z);
@ -631,7 +567,7 @@ struct PhysicsSceneImpl : public PhysicsScene
entity.getMatrix().getRotation(q);
physx::PxQuat pquat(q.x, q.y, q.z, q.w);
physx::PxTransform trans(pvec, pquat);
m_actors[i]->m_physx_actor->setGlobalPose(trans, false);
m_actors[i]->getPhysxActor()->setGlobalPose(trans, false);
return;
}
}
@ -729,6 +665,18 @@ struct PhysicsSceneImpl : public PhysicsScene
bool isDynamic(int index)
{
RigidActor* actor = m_actors[index];
return isDynamic(actor);
}
virtual bool isDynamic(Component cmp) override
{
return isDynamic(cmp.index);
}
bool isDynamic(RigidActor* actor)
{
for (int i = 0, c = m_dynamic_actors.size(); i < c; ++i)
{
if (m_dynamic_actors[i] == actor)
@ -740,18 +688,12 @@ struct PhysicsSceneImpl : public PhysicsScene
}
virtual bool isDynamic(Component cmp) override
{
return isDynamic(cmp.index);
}
virtual Vec3 getHalfExtents(Component cmp) override
{
Vec3 size;
physx::PxRigidActor* actor = m_actors[cmp.index]->m_physx_actor;
physx::PxRigidActor* actor = m_actors[cmp.index]->getPhysxActor();
physx::PxShape* shapes;
if (actor->getNbShapes() == 1 && m_actors[cmp.index]->m_physx_actor->getShapes(&shapes, 1))
if (actor->getNbShapes() == 1 && m_actors[cmp.index]->getPhysxActor()->getShapes(&shapes, 1))
{
physx::PxVec3& half = shapes->getGeometry().box().halfExtents;
size.x = half.x;
@ -764,9 +706,9 @@ struct PhysicsSceneImpl : public PhysicsScene
virtual void setHalfExtents(Component cmp, const Vec3& size) override
{
physx::PxRigidActor* actor = m_actors[cmp.index]->m_physx_actor;
physx::PxRigidActor* actor = m_actors[cmp.index]->getPhysxActor();
physx::PxShape* shapes;
if (actor->getNbShapes() == 1 && m_actors[cmp.index]->m_physx_actor->getShapes(&shapes, 1))
if (actor->getNbShapes() == 1 && m_actors[cmp.index]->getPhysxActor()->getShapes(&shapes, 1))
{
physx::PxBoxGeometry box;
bool is_box = shapes->getBoxGeometry(box);
@ -804,7 +746,7 @@ struct PhysicsSceneImpl : public PhysicsScene
m_dynamic_actors.eraseItemFast(actor);
}
physx::PxShape* shapes;
if (m_actors[cmp.index]->m_physx_actor->getNbShapes() == 1 && m_actors[cmp.index]->m_physx_actor->getShapes(&shapes, 1, 0))
if (m_actors[cmp.index]->getPhysxActor()->getNbShapes() == 1 && m_actors[cmp.index]->getPhysxActor()->getShapes(&shapes, 1, 0))
{
physx::PxGeometryHolder geom = shapes->getGeometry();
@ -821,10 +763,7 @@ struct PhysicsSceneImpl : public PhysicsScene
actor = PxCreateStatic(*m_system->getPhysics(), transform, geom.any(), *m_default_material);
}
ASSERT(actor);
m_scene->removeActor(*m_actors[cmp.index]->m_physx_actor);
m_actors[cmp.index]->m_physx_actor->release();
m_scene->addActor(*actor);
m_actors[cmp.index]->m_physx_actor = actor;
m_actors[cmp.index]->setPhysxActor(actor);
}
}
}
@ -833,7 +772,7 @@ struct PhysicsSceneImpl : public PhysicsScene
void serializeActor(OutputBlob& serializer, int idx)
{
physx::PxShape* shapes;
if (m_actors[idx]->m_physx_actor->getNbShapes() == 1 && m_actors[idx]->m_physx_actor->getShapes(&shapes, 1))
if (m_actors[idx]->getPhysxActor()->getNbShapes() == 1 && m_actors[idx]->getPhysxActor()->getShapes(&shapes, 1))
{
physx::PxBoxGeometry geom;
physx::PxHeightFieldGeometry hf_geom;
@ -862,7 +801,7 @@ struct PhysicsSceneImpl : public PhysicsScene
serializer.read((int32_t&)type);
physx::PxTransform transform;
Matrix mtx;
m_actors[idx]->m_entity.getMatrix(mtx);
m_actors[idx]->getEntity().getMatrix(mtx);
matrix2Transform(mtx, transform);
physx::PxGeometry* geom;
@ -891,12 +830,12 @@ struct PhysicsSceneImpl : public PhysicsScene
{
actor = PxCreateStatic(*m_system->getPhysics(), transform, *geom, *m_default_material);
}
actor->userData = (void*)m_actors[idx]->m_entity.index;
actor->userData = (void*)m_actors[idx]->getEntity().index;
m_scene->addActor(*actor);
m_actors[idx]->m_physx_actor = actor;
m_actors[idx]->setPhysxActor(actor);
actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, true);
m_universe->addComponent(m_actors[idx]->m_entity, BOX_ACTOR_HASH, this, idx);
m_universe->addComponent(m_actors[idx]->getEntity(), BOX_ACTOR_HASH, this, idx);
}
@ -905,10 +844,10 @@ struct PhysicsSceneImpl : public PhysicsScene
serializer.write((int32_t)m_actors.size());
for (int i = 0; i < m_actors.size(); ++i)
{
serializer.writeString(m_actors[i]->m_source.c_str());
serializer.writeString(m_actors[i]->getResource() ? m_actors[i]->getResource()->getPath().c_str() : "");
serializer.write(isDynamic(i));
serializer.write(m_actors[i]->m_entity.index);
if(m_actors[i]->m_entity.index != -1)
serializer.write(m_actors[i]->getEntity().index);
if (m_actors[i]->getEntity().index != -1)
{
serializeActor(serializer, i);
}
@ -945,30 +884,32 @@ struct PhysicsSceneImpl : public PhysicsScene
serializer.read(count);
for (int i = count; i < m_actors.size(); ++i)
{
m_actors[i]->m_physx_actor->release();
m_actors[i]->getPhysxActor()->release();
}
int old_size = m_actors.size();
m_actors.resize(count);
for(int i = old_size; i < count; ++i)
{
RigidActor* actor = m_allocator.newObject<RigidActor>(m_allocator);
RigidActor* actor = m_allocator.newObject<RigidActor>(*this, m_allocator);
m_actors[i] = actor;
}
ResourceManagerBase* manager = m_engine->getResourceManager().get(ResourceManager::PHYSICS);
for (int i = 0; i < m_actors.size(); ++i)
{
char tmp[LUMIX_MAX_PATH];
serializer.readString(tmp, sizeof(tmp));
m_actors[i]->m_source = tmp;
m_actors[i]->setResource(static_cast<PhysicsGeometry*>(manager->load(Lumix::Path(tmp))));
bool is_dynamic;
serializer.read(is_dynamic);
if (is_dynamic)
{
m_dynamic_actors.push(m_actors[i]);
}
serializer.read(m_actors[i]->m_entity.index);
if(m_actors[i]->m_entity.index != -1)
serializer.read(m_actors[i]->getEntity().index);
if (m_actors[i]->getEntity().index != -1)
{
m_actors[i]->m_entity.universe = m_universe;
m_actors[i]->getEntity().universe = m_universe;
deserializeActor(serializer, i);
}
}
@ -1073,16 +1014,6 @@ struct PhysicsSceneImpl : public PhysicsScene
return *m_system;
}
struct RigidActor
{
RigidActor(IAllocator& allocator)
: m_source(allocator)
{ }
physx::PxRigidActor* m_physx_actor;
string m_source;
Entity m_entity;
};
struct Controller
{
@ -1136,14 +1067,14 @@ PhysicsScene* PhysicsScene::create(PhysicsSystem& system, Universe& universe, En
allocator.deleteObject(impl);
return NULL;
}
/*
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE, 1.0);
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eACTOR_AXES, 1.0f);
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 1.0f);
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eWORLD_AXES, 1.0f);
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCONTACT_POINT, 1.0f);
*/
impl->m_system = &system;
impl->m_default_material = impl->m_system->getPhysics()->createMaterial(0.5,0.5,0.5);
return impl;
@ -1159,6 +1090,75 @@ void PhysicsScene::destroy(PhysicsScene* scene)
}
void PhysicsSceneImpl::RigidActor::onStateChanged(Resource::State old_state, Resource::State new_state)
{
if (new_state == Resource::State::READY)
{
setPhysxActor(nullptr);
physx::PxTransform transform;
Matrix mtx;
m_entity.getMatrix(mtx);
matrix2Transform(mtx, transform);
physx::PxRigidActor* actor;
bool is_dynamic = m_scene.isDynamic(this);
if (is_dynamic)
{
actor = PxCreateDynamic(*m_scene.m_system->getPhysics(), transform, *m_resource->getGeometry(), *m_scene.m_default_material, 1.0f);
}
else
{
actor = PxCreateStatic(*m_scene.m_system->getPhysics(), transform, *m_resource->getGeometry(), *m_scene.m_default_material);
}
if (actor)
{
actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, true);
actor->userData = (void*)m_entity.index;
setPhysxActor(actor);
}
else
{
g_log_error.log("PhysX") << "Could not create PhysX mesh " << m_resource->getPath().c_str();
}
}
}
void PhysicsSceneImpl::RigidActor::setPhysxActor(physx::PxRigidActor* actor)
{
if (m_physx_actor)
{
m_scene.m_scene->removeActor(*m_physx_actor);
m_physx_actor->release();
}
m_physx_actor = actor;
if (actor)
{
m_scene.m_scene->addActor(*actor);
}
}
void PhysicsSceneImpl::RigidActor::setResource(PhysicsGeometry* resource)
{
if (m_resource)
{
m_resource->getObserverCb().unbind<RigidActor, &RigidActor::onStateChanged>(this);
m_resource->getResourceManager().get(ResourceManager::PHYSICS)->unload(*m_resource);
}
m_resource = resource;
if (resource)
{
m_resource->getObserverCb().bind<RigidActor, &RigidActor::onStateChanged>(this);
if (resource->isReady())
{
onStateChanged(Resource::State::READY, Resource::State::READY);
}
}
}
Terrain::Terrain()
{
m_heightmap = NULL;

View file

@ -13,6 +13,7 @@ namespace Lumix
class Engine;
class Renderer;
struct RaycastHit
@ -32,7 +33,7 @@ class LUMIX_PHYSICS_API PhysicsScene : public IScene
virtual ~PhysicsScene() {}
virtual void update(float time_delta) = 0;
virtual void render() = 0;
virtual void render(Renderer& renderer) = 0;
virtual bool raycast(const Vec3& origin, const Vec3& dir, float distance, RaycastHit& result) = 0;
virtual PhysicsSystem& getSystem() const = 0;

View file

@ -5,9 +5,11 @@
#include "cooking/PxCooking.h"
#include "core/crc32.h"
#include "core/log.h"
#include "core/resource_manager.h"
#include "editor/world_editor.h"
#include "editor/property_descriptor.h"
#include "engine/engine.h"
#include "physics/physics_geometry_manager.h"
#include "physics/physics_scene.h"
@ -27,7 +29,10 @@ struct PhysicsSystemImpl : public PhysicsSystem
PhysicsSystemImpl(Engine& engine)
: m_allocator(engine.getAllocator())
, m_engine(engine)
{}
, m_manager(*this, engine.getAllocator())
{
m_manager.create(ResourceManager::PHYSICS, engine.getResourceManager());
}
virtual bool create() override;
virtual IScene* createScene(Universe& universe) override;
@ -58,6 +63,7 @@ struct PhysicsSystemImpl : public PhysicsSystem
physx::PxAllocatorCallback* m_physx_allocator;
physx::PxErrorCallback* m_error_callback;
physx::PxCooking* m_cooking;
PhysicsGeometryManager m_manager;
class Engine& m_engine;
class BaseProxyAllocator m_allocator;
};
@ -112,7 +118,7 @@ void PhysicsSystemImpl::registerProperties(Engine& engine)
IAllocator& allocator = editor->getAllocator();
editor->registerProperty("box_rigid_actor", allocator.newObject<BoolPropertyDescriptor<PhysicsScene> >("dynamic", &PhysicsScene::isDynamic, &PhysicsScene::setIsDynamic, allocator));
editor->registerProperty("box_rigid_actor", allocator.newObject<Vec3PropertyDescriptor<PhysicsScene> >("size", &PhysicsScene::getHalfExtents, &PhysicsScene::setHalfExtents, allocator));
editor->registerProperty("mesh_rigid_actor", allocator.newObject<FilePropertyDescriptor<PhysicsScene> >("source", &PhysicsScene::getShapeSource, &PhysicsScene::setShapeSource, "Physics (*.pda)", allocator));
editor->registerProperty("mesh_rigid_actor", allocator.newObject<ResourcePropertyDescriptor<PhysicsScene> >("source", &PhysicsScene::getShapeSource, &PhysicsScene::setShapeSource, "Physics (*.pda)", allocator));
editor->registerProperty("physical_heightfield", allocator.newObject<ResourcePropertyDescriptor<PhysicsScene> >("heightmap", &PhysicsScene::getHeightmap, &PhysicsScene::setHeightmap, "Image (*.raw)", allocator));
editor->registerProperty("physical_heightfield", allocator.newObject<DecimalPropertyDescriptor<PhysicsScene> >("xz_scale", &PhysicsScene::getHeightmapXZScale, &PhysicsScene::setHeightmapXZScale, allocator));
editor->registerProperty("physical_heightfield", allocator.newObject<DecimalPropertyDescriptor<PhysicsScene> >("y_scale", &PhysicsScene::getHeightmapYScale, &PhysicsScene::setHeightmapYScale, allocator));

View file

@ -193,7 +193,7 @@ static bool isAssimpAsset(const QString& suffix)
static void getDefaultFilters(QStringList& filters)
{
filters << "*.msh" << "*.unv" << "*.ani" << "*.mat" << "*.fbx" << "*.shd" << "*.json";
filters << "*.msh" << "*.unv" << "*.ani" << "*.mat" << "*.fbx" << "*.shd" << "*.json" << "*.phy";
Assimp::Importer importer;
aiString extension_list;
importer.GetExtensionList(extension_list);
@ -499,6 +499,10 @@ void AssetBrowser::on_filterComboBox_currentTextChanged(const QString&)
{
filters << "*.json";
}
else if (m_ui->filterComboBox->currentText() == "Physics")
{
filters << "*.phy";
}
else if (m_ui->filterComboBox->currentText() == "Shader")
{
filters << "*.shd";

View file

@ -88,6 +88,11 @@
<string>Pipeline</string>
</property>
</item>
<item>
<property name="text">
<string>Physics</string>
</property>
</item>
<item>
<property name="text">
<string>Texture</string>

View file

@ -13,6 +13,7 @@
#include "graphics/model.h"
#include "mainwindow.h"
#include "metadata.h"
#include "physics/physics_geometry_manager.h"
#include <qfile.h>
#include <qfiledialog.h>
#include <qimagereader.h>
@ -90,6 +91,7 @@ ImportThread::ImportThread(ImportAssetDialog& dialog)
m_log_stream = new LogStream(*this);
m_importer.SetProgressHandler(this);
m_import_model = true;
m_import_physics = false;
m_import_materials = true;
}
@ -404,6 +406,72 @@ bool ImportThread::checkModel()
}
bool ImportThread::saveLumixPhysics()
{
if (!m_import_physics)
{
return true;
}
QVector<Lumix::Vec3> vertices;
QFileInfo source_path(m_source);
auto dest = m_destination + "/" + source_path.baseName() + ".phy";
QFile file(dest);
if (!file.open(QIODevice::WriteOnly))
{
return false;
}
const aiScene* scene = m_importer.GetScene();
Lumix::PhysicsGeometry::Header header;
header.m_magic = Lumix::PhysicsGeometry::HEADER_MAGIC;
header.m_version = (uint32_t)Lumix::PhysicsGeometry::Versions::LAST;
header.m_convex = (uint32_t)m_make_convex;
file.write((const char*)&header, sizeof(header));
int32_t count = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i)
{
count += (int32_t)scene->mMeshes[i]->mNumVertices;
}
file.write((const char*)&count, sizeof(count));
for (unsigned int i = 0; i < scene->mNumMeshes; ++i)
{
const aiMesh* mesh = scene->mMeshes[i];
file.write((const char*)mesh->mVertices, sizeof(mesh->mVertices[0]) * mesh->mNumVertices);
}
if (!m_make_convex)
{
count = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i)
{
count += (int32_t)scene->mMeshes[i]->mNumFaces * 3;
}
file.write((const char*)&count, sizeof(count));
int offset = 0;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i)
{
const aiMesh* mesh = scene->mMeshes[i];
for (unsigned int j = 0; j < mesh->mNumFaces; ++j)
{
Q_ASSERT(mesh->mFaces[j].mNumIndices == 3);
uint32_t index = mesh->mFaces[j].mIndices[0] + offset;
file.write((const char*)&index, sizeof(index));
index = mesh->mFaces[j].mIndices[1] + offset;
file.write((const char*)&index, sizeof(index));
index = mesh->mFaces[j].mIndices[2] + offset;
file.write((const char*)&index, sizeof(index));
}
offset += mesh->mNumVertices;
}
}
file.close();
return true;
}
bool ImportThread::saveLumixModel()
{
QDir().mkpath(m_destination);
@ -704,7 +772,7 @@ void ImportThread::run()
}
else
{
if (saveLumixModel())
if (saveLumixPhysics() && saveLumixModel())
{
saveLumixMaterials();
}
@ -722,6 +790,9 @@ ImportAssetDialog::ImportAssetDialog(MainWindow& main_window, QWidget* parent, c
m_ui = new Ui::ImportAssetDialog;
m_ui->setupUi(this);
m_ui->importPhysicsCheckbox->hide();
m_ui->convexPhysicsCheckbox->hide();
m_ui->convexPhysicsCheckbox->setEnabled(false);
m_ui->importMaterialsCheckbox->hide();
m_ui->importAnimationCheckbox->hide();
m_ui->importMeshCheckbox->hide();
@ -729,6 +800,11 @@ ImportAssetDialog::ImportAssetDialog(MainWindow& main_window, QWidget* parent, c
m_ui->convertToDDSCheckbox->hide();
m_ui->importButton->setEnabled(false);
connect(m_ui->importPhysicsCheckbox, &QCheckBox::stateChanged, [this](){
bool enabled = m_ui->importPhysicsCheckbox->isChecked();
m_ui->convexPhysicsCheckbox->setEnabled(enabled);
});
connect(m_import_thread, &ImportThread::progress, this, &ImportAssetDialog::on_progressUpdate, Qt::QueuedConnection);
connect(m_import_thread, &QThread::finished, this, &ImportAssetDialog::on_importFinished, Qt::QueuedConnection);
m_ui->destinationInput->setText(QDir::currentPath());
@ -758,6 +834,8 @@ void ImportAssetDialog::on_sourceInput_textChanged(const QString& text)
m_ui->convertToDDSCheckbox->hide();
m_ui->importAnimationCheckbox->hide();
m_ui->importMeshCheckbox->hide();
m_ui->importPhysicsCheckbox->hide();
m_ui->convexPhysicsCheckbox->hide();
m_ui->createDirectoryCheckbox->hide();
if (QFile::exists(text))
{
@ -783,6 +861,8 @@ void ImportAssetDialog::on_importFinished()
{
m_ui->importButton->setEnabled(true);
m_ui->importMeshCheckbox->show();
m_ui->importPhysicsCheckbox->show();
m_ui->convexPhysicsCheckbox->show();
m_ui->createDirectoryCheckbox->show();
m_ui->importAnimationCheckbox->show();
m_ui->importAnimationCheckbox->setEnabled(m_importer.GetScene()->HasAnimations());
@ -865,7 +945,8 @@ void ImportAssetDialog::importModel()
m_import_thread->setSource(m_ui->sourceInput->text());
m_import_thread->setConvertTexturesToDDS(m_ui->convertToDDSCheckbox->isChecked());
m_import_thread->setImportMaterials(m_ui->importMaterialsCheckbox->isChecked());
m_import_thread->setImpotModel(m_ui->importMeshCheckbox->isChecked());
m_import_thread->setImportModel(m_ui->importMeshCheckbox->isChecked());
m_import_thread->setImportPhysics(m_ui->importPhysicsCheckbox->isChecked(), m_ui->convexPhysicsCheckbox->isChecked());
m_import_thread->start();
QFileInfo source_path(m_ui->sourceInput->text());

View file

@ -33,7 +33,8 @@ class ImportThread : public QThread, public Assimp::ProgressHandler
void setDestination(const QString& destination) { m_destination = destination; }
void setConvertTexturesToDDS(bool convert) { m_convert_texture_to_DDS = convert; }
void setImportMaterials(bool import_materials) { m_import_materials = import_materials; }
void setImpotModel(bool import_model) { m_import_model = import_model; }
void setImportModel(bool import_model) { m_import_model = import_model; }
void setImportPhysics(bool import_physics, bool make_convex) { m_import_physics = import_physics; m_make_convex = make_convex; }
const QString& getErrorMessage() const { return m_error_message; }
private:
@ -43,6 +44,7 @@ class ImportThread : public QThread, public Assimp::ProgressHandler
bool saveLumixMaterials();
bool saveTexture(const QString& texture_path, const QFileInfo& material_info, QFile& material_file, bool is_normal_map);
bool saveLumixModel();
bool saveLumixPhysics();
bool saveEmbeddedTextures(const aiScene* scene);
bool checkModel();
@ -54,6 +56,8 @@ class ImportThread : public QThread, public Assimp::ProgressHandler
QString m_destination;
ImportAssetDialog& m_dialog;
bool m_import_model;
bool m_import_physics;
bool m_make_convex;
bool m_import_materials;
bool m_convert_texture_to_DDS;
Assimp::Importer& m_importer;

View file

@ -45,6 +45,24 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="physicsLayout">
<item>
<widget class="QCheckBox" name="importPhysicsCheckbox">
<property name="text">
<string>Import physics</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="convexPhysicsCheckbox">
<property name="text">
<string>Make convex</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="importAnimationCheckbox">
<property name="text">

View file

@ -205,7 +205,7 @@ class App
Lumix::PhysicsScene* scene = static_cast<Lumix::PhysicsScene*>(m_world_editor->getEngine().getScene(crc32("physics")));
if(scene)
{
scene->render();
scene->render(m_world_editor->getEngine().getRenderer());
}
}

View file

@ -96,6 +96,10 @@ void ScriptCompiler::compileAllModules()
Module& module = *iter;
compileModule(module.m_module_name);
}
if (m_modules.empty())
{
emitCompiled("");
}
}

View file

@ -25,7 +25,10 @@ ScriptCompilerWidget::ScriptCompilerWidget(QWidget* parent)
m_compiler = new ScriptCompiler;
QByteArray base_path = m_base_path.toLatin1();
connect(m_compiler, &ScriptCompiler::compiled, [this](const QString& module_name){
m_ui->compilerOutputView->setText(m_compiler->getLog(module_name));
if (!module_name.isEmpty())
{
m_ui->compilerOutputView->setText(m_compiler->getLog(module_name));
}
});
connect(m_ui->scriptListWidget, &QListWidget::itemDoubleClicked, [this](QListWidgetItem * item) {
QProcess* process = new QProcess;