import asset - physics WIP
This commit is contained in:
parent
d410881377
commit
c36911e26d
18 changed files with 593 additions and 180 deletions
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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();
|
||||
|
|
|
@ -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);*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -204,11 +204,10 @@ struct PipelineImpl : public Pipeline
|
|||
else
|
||||
{
|
||||
parseFramebuffers(m_lua_state);
|
||||
registerCFunctions();
|
||||
decrementDepCount();
|
||||
}
|
||||
|
||||
registerCFunctions();
|
||||
|
||||
decrementDepCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
203
src/physics/physics_geometry_manager.cpp
Normal file
203
src/physics/physics_geometry_manager.cpp
Normal 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
|
80
src/physics/physics_geometry_manager.h
Normal file
80
src/physics/physics_geometry_manager.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,10 @@ void ScriptCompiler::compileAllModules()
|
|||
Module& module = *iter;
|
||||
compileModule(module.m_module_name);
|
||||
}
|
||||
if (m_modules.empty())
|
||||
{
|
||||
emitCompiled("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue