From 521f18af1b04bdebe28c5ec2c946a9c1837b74ad Mon Sep 17 00:00:00 2001 From: Johan Lind Date: Wed, 10 Apr 2024 23:23:37 +0200 Subject: [PATCH] Rigidbody's physics shape setup initial scaling fix, 3d model import to destination folder --- engine/cRigidbody.cpp | 47 ++++++++++++++++++--- engine/cRigidbody.h | 2 + engine/editor/jleEditor.cpp | 8 +++- engine/editor/jleEditor3DImportWindow.cpp | 51 ++++++++++++++++------- engine/editor/jleEditor3DImportWindow.h | 4 +- engine/editor/jleSceneEditorWindow.cpp | 30 +------------ 6 files changed, 87 insertions(+), 55 deletions(-) diff --git a/engine/cRigidbody.cpp b/engine/cRigidbody.cpp index 04191907..b14d3348 100644 --- a/engine/cRigidbody.cpp +++ b/engine/cRigidbody.cpp @@ -15,9 +15,9 @@ #include "cRigidbody.h" +#include "cMesh.h" #include "jleGameEngine.h" #include "jlePhysics.h" -#include "cMesh.h" #include #include @@ -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; @@ -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(reinterpret_cast(shape), v); + _optionalLocalShape = + std::make_unique(reinterpret_cast(shape), v); shape = _optionalLocalShape.get(); } @@ -102,6 +101,7 @@ cRigidbody::createRigidbody(bool isDynamic, btCollisionShape *shape) body->setUserIndex(-1); body->setUserPointer(this); + return body; } @@ -121,6 +121,8 @@ cRigidbody::setupRigidbody() scene()->getPhysics().addRigidbody(_body.get()); + setWorldMatrixAndScaleRigidbody(getTransform().getWorldMatrix()); + _body->activate(); } @@ -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}); + } +} diff --git a/engine/cRigidbody.h b/engine/cRigidbody.h index 21e73284..ef0b7034 100644 --- a/engine/cRigidbody.h +++ b/engine/cRigidbody.h @@ -56,6 +56,8 @@ class cRigidbody : public jleComponent, public btMotionState btRigidBody &getBody(); + void setWorldMatrixAndScaleRigidbody(const glm::mat4& worldMatrix); + void setupRigidbody(); void setupNewRigidbodyAndDeleteOld(); diff --git a/engine/editor/jleEditor.cpp b/engine/editor/jleEditor.cpp index 130d1372..a8c2f3bc 100644 --- a/engine/editor/jleEditor.cpp +++ b/engine/editor/jleEditor.cpp @@ -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(); diff --git a/engine/editor/jleEditor3DImportWindow.cpp b/engine/editor/jleEditor3DImportWindow.cpp index 7f009ee0..026a6433 100644 --- a/engine/editor/jleEditor3DImportWindow.cpp +++ b/engine/editor/jleEditor3DImportWindow.cpp @@ -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 #include @@ -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) { @@ -68,6 +79,9 @@ 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); } @@ -75,6 +89,7 @@ void sanitizeAssimpsNames(const aiScene* scene) // 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); } @@ -82,13 +97,15 @@ void sanitizeAssimpsNames(const aiScene* scene) // 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 processNode = [&](aiNode *node) { + std::function 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); @@ -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(); @@ -122,7 +140,8 @@ jleEditor3DImportWindow::importModel(const jlePath &path) auto assimpMaterial = scene->mMaterials[i]; std::string materialName = assimpMaterial->GetName().C_Str(); - auto material = jleResourceRef(jlePath{path.getVirtualFolder() + '/' + materialName + ".mat"}); + auto material = + jleResourceRef(jlePath{destinationPath.getVirtualFolder() + '/' + materialName + ".mat"}); const auto setTexture = [&](aiTextureType textureType, jleResourceRef &textureRef) { if (assimpMaterial->GetTextureCount(textureType)) { @@ -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(jlePath{virtualMaterialPath}); } }; @@ -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); diff --git a/engine/editor/jleEditor3DImportWindow.h b/engine/editor/jleEditor3DImportWindow.h index 50f4a2fd..02e08218 100644 --- a/engine/editor/jleEditor3DImportWindow.h +++ b/engine/editor/jleEditor3DImportWindow.h @@ -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, @@ -47,7 +47,7 @@ class jleEditor3DImportWindow : public jleEditorWindowInterface std::vector> &createdMeshes, std::vector> &createdMaterials); - bool _importWithSkinning; + bool _importWithSkinning{}; }; #endif // JLE_BUILD_EDITOR \ No newline at end of file diff --git a/engine/editor/jleSceneEditorWindow.cpp b/engine/editor/jleSceneEditorWindow.cpp index 86ba0d5d..bc248624 100644 --- a/engine/editor/jleSceneEditorWindow.cpp +++ b/engine/editor/jleSceneEditorWindow.cpp @@ -277,35 +277,7 @@ jleSceneEditorWindow::update(jleGameEngine &ge) if (transformMatrix != worldMatrixBefore) { if (!gEngine->isGameKilled()) { if (auto rb = obj->getComponent()) { - 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); }