Skip to content

Commit

Permalink
Rigidbody's physics shape setup initial scaling fix, 3d model import …
Browse files Browse the repository at this point in the history
…to destination folder
  • Loading branch information
Mormert committed Apr 10, 2024
1 parent 4b45b1a commit 521f18a
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 55 deletions.
47 changes: 41 additions & 6 deletions engine/cRigidbody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

#include "cRigidbody.h"

#include "cMesh.h"
#include "jleGameEngine.h"
#include "jlePhysics.h"
#include "cMesh.h"

#include <BulletCollision/CollisionShapes/btBoxShape.h>
#include <BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h>
Expand All @@ -27,9 +27,7 @@

JLE_EXTERN_TEMPLATE_CEREAL_CPP(cRigidbody)

cRigidbody::
cRigidbody(const cRigidbody &other)
: jleComponent(other)
cRigidbody::cRigidbody(const cRigidbody &other) : jleComponent(other)
{
_mass = other._mass;

Expand Down Expand Up @@ -86,13 +84,14 @@ cRigidbody::createRigidbody(bool isDynamic, btCollisionShape *shape)
btVector3 localInertia(0, 0, 0);
if (isDynamic) {
shape->calculateLocalInertia(_mass, localInertia);
}else {
} else {
_size.x = glm::length(glm::vec3(getTransform().getWorldMatrix()[0])); // Basis vector X
_size.y = glm::length(glm::vec3(getTransform().getWorldMatrix()[1])); // Basis vector Y
_size.z = glm::length(glm::vec3(getTransform().getWorldMatrix()[2])); // Basis vector Z

auto v = btVector3{_size.x, _size.y, _size.z};
_optionalLocalShape = std::make_unique<btScaledBvhTriangleMeshShape>(reinterpret_cast<btBvhTriangleMeshShape*>(shape), v);
_optionalLocalShape =
std::make_unique<btScaledBvhTriangleMeshShape>(reinterpret_cast<btBvhTriangleMeshShape *>(shape), v);
shape = _optionalLocalShape.get();
}

Expand All @@ -102,6 +101,7 @@ cRigidbody::createRigidbody(bool isDynamic, btCollisionShape *shape)

body->setUserIndex(-1);
body->setUserPointer(this);

return body;
}

Expand All @@ -121,6 +121,8 @@ cRigidbody::setupRigidbody()

scene()->getPhysics().addRigidbody(_body.get());

setWorldMatrixAndScaleRigidbody(getTransform().getWorldMatrix());

_body->activate();
}

Expand Down Expand Up @@ -148,3 +150,36 @@ cRigidbody::getBody()
{
return *_body.get();
}

void
cRigidbody::setWorldMatrixAndScaleRigidbody(const glm::mat4 &worldMatrix)
{
if (isDynamic()) {
getTransform().setWorldMatrix(worldMatrix);

setupNewRigidbodyAndDeleteOld();
glm::vec3 size;

size.x = glm::length(glm::vec3(worldMatrix[0])); // Basis vector X
size.y = glm::length(glm::vec3(worldMatrix[1])); // Basis vector Y
size.z = glm::length(glm::vec3(worldMatrix[2])); // Basis vector Z
getBody().getCollisionShape()->setLocalScaling({size.x, size.y, size.z});

} else {
// Remove scaling from the world matrix (bullet don't want the scaling for static objects)
glm::vec3 size;
size.x = glm::length(glm::vec3(worldMatrix[0])); // Basis vector X
size.y = glm::length(glm::vec3(worldMatrix[1])); // Basis vector Y
size.z = glm::length(glm::vec3(worldMatrix[2])); // Basis vector Z

getTransform().setWorldMatrix(worldMatrix);

const glm::mat4 scaledMatrix = glm::scale(worldMatrix, glm::vec3(1.f / size.x, 1.f / size.y, 1.f / size.z));

btTransform transform;
transform.setFromOpenGLMatrix((btScalar *)&scaledMatrix);

getBody().setWorldTransform(transform);
getBody().getCollisionShape()->setLocalScaling({size.x, size.y, size.z});
}
}
2 changes: 2 additions & 0 deletions engine/cRigidbody.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class cRigidbody : public jleComponent, public btMotionState

btRigidBody &getBody();

void setWorldMatrixAndScaleRigidbody(const glm::mat4& worldMatrix);

void setupRigidbody();

void setupNewRigidbodyAndDeleteOld();
Expand Down
8 changes: 6 additions & 2 deletions engine/editor/jleEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,16 +182,20 @@ jleEditor::render(wi::jobsystem::context& ctx)
{
JLE_SCOPE_PROFILE_GPU(EditorRender);

// TODO : This needs to be restructured.
// Possibly fix with ECS/context passing struct
Wait(ctx);


renderGameView();


renderEditorSceneView();

// UI can touch game state, so we need to for game logic update to complete
Wait(ctx);

renderEditorGridGizmo();
renderEditorGizmos();
//renderEditorGizmos(); // disable since for some reason we're rendering it into the game view lol
renderEditorUI();

//resetRenderGraphForNewFrame();
Expand Down
51 changes: 35 additions & 16 deletions engine/editor/jleEditor3DImportWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@

#include "jleEditor3DImportWindow.h"
#include "cMesh.h"
#include "jleSkinnedMesh.h"
#include "cSkinnedMesh.h"
#include "jleEditor.h"
#include "jleMaterial.h"
#include "jleMesh.h"
#include "jlePath.h"
#include "jleSkinnedMesh.h"

#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
Expand All @@ -42,23 +42,34 @@ jleEditor3DImportWindow::update(jleGameEngine &ge)
ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
ImGui::Begin(window_name.c_str(), &isOpened, ImGuiWindowFlags_NoCollapse);

ImGui::Checkbox("Import With Skinning", &_importWithSkinning);
ImGui::Checkbox("Import with skinning (animated FBX)", &_importWithSkinning);

{
static char buf[128];
ImGui::InputText("Import 3D model path", buf, sizeof(buf));
ImGui::Text("Specify import path and destination for import. Import using jlePath syntax. (e.g. "
"GR:/MyFolder/MyAsset.fbx)");

static char bufImport[128];
ImGui::InputText("Import 3D model path", bufImport, sizeof(bufImport));

static char bufDestination[128];
ImGui::InputText("Destination folder", bufDestination, sizeof(bufDestination));

if (ImGui::Button("Process")) {
jlePath path = buf;
importModel(path);
jlePath pathImport = bufImport;
jlePath pathDest = bufImport;
if (pathImport.isEmpty() || pathDest.isEmpty()) {
LOGW << "Paths not specified for 3D model import!";
} else {
importModel(pathImport, pathDest);
}
}
}

ImGui::End();
}


void sanitizeAssimpsNames(const aiScene* scene)
void
sanitizeAssimpsNames(const aiScene *scene)
{
// Iterate through all material names
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
Expand All @@ -68,27 +79,33 @@ void sanitizeAssimpsNames(const aiScene* scene)
if (materialName.data[j] == '.') {
materialName.data[j] = '_';
}
if (materialName.data[j] == ' ') {
materialName.data[j] = '_';
}
}
scene->mMaterials[i]->AddProperty(&materialName, AI_MATKEY_NAME);
}

// Iterate through all animation names
for (unsigned int i = 0; i < scene->mNumAnimations; ++i) {
std::string name = scene->mAnimations[i]->mName.C_Str();
std::replace(name.begin(), name.end(), ' ', '_');
std::replace(name.begin(), name.end(), '.', '_');
scene->mAnimations[i]->mName.Set(name);
}

// Iterate through all mesh names
for (unsigned int i = 0; i < scene->mNumMeshes; ++i) {
std::string name = scene->mMeshes[i]->mName.C_Str();
std::replace(name.begin(), name.end(), ' ', '_');
std::replace(name.begin(), name.end(), '.', '_');
scene->mMeshes[i]->mName.Set(name);
}

// Iterate through all node names
std::function<void(aiNode*)> processNode = [&](aiNode *node) {
std::function<void(aiNode *)> processNode = [&](aiNode *node) {
std::string name = node->mName.C_Str();
std::replace(name.begin(), name.end(), ' ', '_');
std::replace(name.begin(), name.end(), '.', '_');
node->mName.Set(name);

Expand All @@ -101,13 +118,14 @@ void sanitizeAssimpsNames(const aiScene* scene)
}

bool
jleEditor3DImportWindow::importModel(const jlePath &path)
jleEditor3DImportWindow::importModel(const jlePath &importPath, const jlePath &destinationPath)
{
auto pathStr = path.getRealPath();
auto pathStr = importPath.getRealPath();

Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(
pathStr, aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_CalcTangentSpace | aiProcess_FlipUVs | aiProcess_GenUVCoords);
const aiScene *scene = importer.ReadFile(pathStr,
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_CalcTangentSpace |
aiProcess_FlipUVs | aiProcess_GenUVCoords);

if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
LOGE << "Error loading mesh with Assimp" << importer.GetErrorString();
Expand All @@ -122,7 +140,8 @@ jleEditor3DImportWindow::importModel(const jlePath &path)
auto assimpMaterial = scene->mMaterials[i];
std::string materialName = assimpMaterial->GetName().C_Str();

auto material = jleResourceRef<jleMaterialPBR>(jlePath{path.getVirtualFolder() + '/' + materialName + ".mat"});
auto material =
jleResourceRef<jleMaterialPBR>(jlePath{destinationPath.getVirtualFolder() + '/' + materialName + ".mat"});

const auto setTexture = [&](aiTextureType textureType, jleResourceRef<jleTexture> &textureRef) {
if (assimpMaterial->GetTextureCount(textureType)) {
Expand All @@ -138,7 +157,7 @@ jleEditor3DImportWindow::importModel(const jlePath &path)

std::replace(assimpPathStr.begin(), assimpPathStr.end(), ' ', '_');

std::string virtualMaterialPath = path.getVirtualFolder() + '/' + assimpPathStr;
std::string virtualMaterialPath = destinationPath.getVirtualFolder() + '/' + assimpPathStr;
textureRef = jleResourceRef<jleTexture>(jlePath{virtualMaterialPath});
}
};
Expand Down Expand Up @@ -225,7 +244,7 @@ jleEditor3DImportWindow::importModel(const jlePath &path)
createdMesh = mesh;
}

createdMesh->path = jlePath{path.getVirtualFolder() + '/' + meshName + ".fbx"};
createdMesh->path = jlePath{destinationPath.getVirtualFolder() + '/' + meshName + ".fbx"};
createdMesh->saveToFile();

createdMeshes.push_back(createdMesh);
Expand Down
4 changes: 2 additions & 2 deletions engine/editor/jleEditor3DImportWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class jleEditor3DImportWindow : public jleEditorWindowInterface

void update(jleGameEngine &ge) override;

bool importModel(const jlePath &path);
bool importModel(const jlePath &importPath, const jlePath& destinationPath);

private:
void processNode(const aiScene *scene,
Expand All @@ -47,7 +47,7 @@ class jleEditor3DImportWindow : public jleEditorWindowInterface
std::vector<std::shared_ptr<jleMesh>> &createdMeshes,
std::vector<jleResourceRef<jleMaterialPBR>> &createdMaterials);

bool _importWithSkinning;
bool _importWithSkinning{};
};

#endif // JLE_BUILD_EDITOR
30 changes: 1 addition & 29 deletions engine/editor/jleSceneEditorWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,35 +277,7 @@ jleSceneEditorWindow::update(jleGameEngine &ge)
if (transformMatrix != worldMatrixBefore) {
if (!gEngine->isGameKilled()) {
if (auto rb = obj->getComponent<cRigidbody>()) {
if (rb->isDynamic()) {
obj->getTransform().setWorldMatrix(worldMatrixBefore);

rb->setupNewRigidbodyAndDeleteOld();
glm::vec3 size;

size.x = glm::length(glm::vec3(worldMatrixBefore[0])); // Basis vector X
size.y = glm::length(glm::vec3(worldMatrixBefore[1])); // Basis vector Y
size.z = glm::length(glm::vec3(worldMatrixBefore[2])); // Basis vector Z
rb->getBody().getCollisionShape()->setLocalScaling({size.x, size.y, size.z});

} else {
// Remove scaling from the world matrix (bullet don't want the scaling for static objects)
glm::vec3 size;
size.x = glm::length(glm::vec3(worldMatrixBefore[0])); // Basis vector X
size.y = glm::length(glm::vec3(worldMatrixBefore[1])); // Basis vector Y
size.z = glm::length(glm::vec3(worldMatrixBefore[2])); // Basis vector Z

obj->getTransform().setWorldMatrix(worldMatrixBefore);

worldMatrixBefore =
glm::scale(worldMatrixBefore, glm::vec3(1.f / size.x, 1.f / size.y, 1.f / size.z));

btTransform transform;
transform.setFromOpenGLMatrix((btScalar *)&worldMatrixBefore);

rb->getBody().setWorldTransform(transform);
rb->getBody().getCollisionShape()->setLocalScaling({size.x, size.y, size.z});
}
rb->setWorldMatrixAndScaleRigidbody(worldMatrixBefore);
} else {
obj->getTransform().setWorldMatrix(worldMatrixBefore);
}
Expand Down

0 comments on commit 521f18a

Please sign in to comment.