diff --git a/Projects/Skylicht/Collision/Source/Decal/CDecalData.cpp b/Projects/Skylicht/Collision/Source/Decal/CDecalData.cpp index aa0a8a371..b2da72a3d 100644 --- a/Projects/Skylicht/Collision/Source/Decal/CDecalData.cpp +++ b/Projects/Skylicht/Collision/Source/Decal/CDecalData.cpp @@ -30,8 +30,7 @@ namespace Skylicht IMPLEMENT_DATA_TYPE_INDEX(CDecalRenderData); CDecalRenderData::CDecalRenderData() : - Texture(NULL), - Collision(NULL) + Texture(NULL) { Material = new CMaterial("DecalRenderer", "BuiltIn/Shader/Basic/TextureColorAlpha.xml"); } diff --git a/Projects/Skylicht/Collision/Source/Decal/CDecalData.h b/Projects/Skylicht/Collision/Source/Decal/CDecalData.h index ac2693dcc..77825265b 100644 --- a/Projects/Skylicht/Collision/Source/Decal/CDecalData.h +++ b/Projects/Skylicht/Collision/Source/Decal/CDecalData.h @@ -35,7 +35,6 @@ namespace Skylicht public: ITexture* Texture; CMaterial* Material; - CCollisionBuilder* Collision; DECLARE_DATA_TYPE_INDEX; diff --git a/Projects/Skylicht/Collision/Source/Decal/CDecals.cpp b/Projects/Skylicht/Collision/Source/Decal/CDecals.cpp index 09ae59234..75730ffff 100644 --- a/Projects/Skylicht/Collision/Source/Decal/CDecals.cpp +++ b/Projects/Skylicht/Collision/Source/Decal/CDecals.cpp @@ -27,6 +27,9 @@ This file is part of the "Skylicht Engine". #include "GameObject/CGameObject.h" #include "Entity/CEntityManager.h" #include "Transform/CWorldTransformData.h" +#include "Transform/CWorldInverseTransformData.h" +#include "Culling/CCullingData.h" +#include "Culling/CCullingBBoxData.h" namespace Skylicht { @@ -107,6 +110,11 @@ namespace Skylicht CWorldTransformData* transform = (CWorldTransformData*)entity->getDataByIndex(CWorldTransformData::DataTypeIndex); transform->Relative.setTranslation(position); + // Culling + entity->addData(); + entity->addData(); + entity->addData(); + // apply material m_renderData->Material->applyMaterial(decalData->MeshBuffer->getMaterial()); @@ -115,7 +123,143 @@ namespace Skylicht void CDecals::bake(CCollisionBuilder* collisionMgr) { - CDecalRenderData* renderData = (CDecalRenderData*)m_gameObject->getEntity()->getDataByIndex(CDecalRenderData::DataTypeIndex); - renderData->Collision = collisionMgr; + std::vector& entities = getEntities(); + for (CEntity* entity : entities) + { + CDecalData* decalData = (CDecalData*)entity->getDataByIndex(CDecalData::DataTypeIndex); + CWorldTransformData* decalTransform = (CWorldTransformData*)entity->getDataByIndex(CWorldTransformData::DataTypeIndex); + + if (decalData && decalData->Change) + { + initDecal(entity, decalData, decalTransform->Relative.getTranslation(), collisionMgr); + decalData->Change = false; + } + } + } + + void CDecals::initDecal(CEntity* entity, CDecalData* decal, const core::vector3df& position, CCollisionBuilder* collision) + { + // Create boxes + irr::core::aabbox3df box = irr::core::aabbox3df( + position - decal->Dimension * 0.5f, + position + decal->Dimension * 0.5f + ); + + // Query tris collision + core::array triangles; + core::array nodes; + collision->getTriangles(box, triangles, nodes); + u32 triangleCount = triangles.size(); + + // Scale to 0.0f - 1.0f (UV space) + core::vector3df uvScale = core::vector3df(1, 1, 1) / decal->Dimension; + core::vector3df uvOffset(0.5f, 0.0f, 0.5f); + + // UV Rotation matrix + core::quaternion r1; + r1.rotationFromTo(core::vector3df(0.0f, 1.0f, 0.0f), decal->Normal); + + core::quaternion r2; + r2.fromAngleAxis(decal->TextureRotation * core::DEGTORAD, core::vector3df(0.0f, 1.0f, 0.0f)); + + core::quaternion q = r2 * r1; + + // Inverse vertex to local position + core::matrix4 uvMatrix = q.getMatrix(); + uvMatrix.setTranslation(position); + uvMatrix.makeInverse(); + + // Position matrix + core::matrix4 worldInverse; + worldInverse.setTranslation(position); + worldInverse.makeInverse(); + + // Clip all triangles and fill vertex and indices + u32 vertexIndex = 0; + std::map positions; + + IIndexBuffer* indices = decal->MeshBuffer->getIndexBuffer(); + IVertexBuffer* vertices = decal->MeshBuffer->getVertexBuffer(); + + for (u32 i = 0; i < triangleCount; i++) + { + u32 index = 0; + + core::triangle3df uvTriangle = *triangles[i]; + core::triangle3df& triangle = *triangles[i]; + + core::vector3df triangleNormal = triangle.getNormal(); + triangleNormal.normalize(); + + // Rotate positions + uvMatrix.transformVect(uvTriangle.pointA); + uvMatrix.transformVect(uvTriangle.pointB); + uvMatrix.transformVect(uvTriangle.pointC); + + // Fill vertices and indices + { + video::SColor color(255, 255, 255, 255); + + for (u32 p = 0; p < 3; p++) + { + core::vector3df uvPos; + core::vector3df pos; + + if (p == 0) + { + uvPos = uvTriangle.pointA * uvScale + uvOffset; + pos = triangle.pointA; + } + else if (p == 1) + { + uvPos = uvTriangle.pointB * uvScale + uvOffset; + pos = triangle.pointB; + } + else if (p == 2) + { + uvPos = uvTriangle.pointC * uvScale + uvOffset; + pos = triangle.pointC; + } + + worldInverse.transformVect(pos); + + // Search if vertex already exists in the vertices list + std::map::iterator iter = positions.find(uvPos); + if (iter != positions.end()) + { + index = iter->second; + } + // Add vertex to list + else + { + index = vertexIndex; + positions.insert(std::pair(uvPos, vertexIndex)); + + pos += triangleNormal * decal->Distance; + + core::vector2df uv(uvPos.X, 1.0f - uvPos.Z); + + video::S3DVertex vtx( + pos, + triangleNormal, + color, + uv); + + vertices->addVertex(&vtx); + vertexIndex++; + } + + indices->addIndex(index); + } + } + } + + decal->MeshBuffer->recalculateBoundingBox(); + decal->MeshBuffer->setDirty(); + + CCullingBBoxData* cullingBox = (CCullingBBoxData*)entity->getDataByIndex(CCullingBBoxData::DataTypeIndex); + cullingBox->BBox = decal->MeshBuffer->getBoundingBox(); + cullingBox->Materials.clear(); + cullingBox->Materials.push_back(m_renderData->Material); } } \ No newline at end of file diff --git a/Projects/Skylicht/Collision/Source/Decal/CDecals.h b/Projects/Skylicht/Collision/Source/Decal/CDecals.h index 7edb5c641..b6724e1b2 100644 --- a/Projects/Skylicht/Collision/Source/Decal/CDecals.h +++ b/Projects/Skylicht/Collision/Source/Decal/CDecals.h @@ -65,5 +65,9 @@ namespace Skylicht void bake(CCollisionBuilder* collisionMgr); DECLARE_GETTYPENAME(CDecals); + + protected: + + void initDecal(CEntity* entity, CDecalData* decal, const core::vector3df& position, CCollisionBuilder* collision); }; } \ No newline at end of file diff --git a/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.cpp b/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.cpp index 12bdd5519..a359ae89f 100644 --- a/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.cpp +++ b/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.cpp @@ -24,7 +24,7 @@ This file is part of the "Skylicht Engine". #include "pch.h" #include "CDecalsRenderer.h" -#include "Culling/CVisibleData.h" +#include "Culling/CCullingData.h" namespace Skylicht { @@ -40,40 +40,24 @@ namespace Skylicht void CDecalsRenderer::beginQuery(CEntityManager* entityManager) { - m_decalRenders.set_used(0); - m_transforms.set_used(0); - m_decalData.set_used(0); m_decalTransforms.set_used(0); } void CDecalsRenderer::onQuery(CEntityManager* entityManager, CEntity* entity) { - CDecalRenderData* renderData = (CDecalRenderData*)entity->getDataByIndex(CDecalRenderData::DataTypeIndex); - if (renderData != NULL) + CDecalData* decalData = (CDecalData*)entity->getDataByIndex(CDecalData::DataTypeIndex); + if (decalData != NULL) { - CVisibleData* visibleData = (CVisibleData*)entity->getDataByIndex(CVisibleData::DataTypeIndex); - if (visibleData->Visible) + CCullingData* cullingData = (CCullingData*)entity->getDataByIndex(CCullingData::DataTypeIndex); + if (cullingData && cullingData->Visible) { CWorldTransformData* transform = (CWorldTransformData*)entity->getDataByIndex(CWorldTransformData::DataTypeIndex); - m_transforms.push_back(transform); - m_decalRenders.push_back(renderData); - } - } - else - { - CDecalData* decalData = (CDecalData*)entity->getDataByIndex(CDecalData::DataTypeIndex); - if (decalData != NULL) - { - CVisibleData* visibleData = (CVisibleData*)entity->getDataByIndex(CVisibleData::DataTypeIndex); - if (visibleData->Visible) - { - CWorldTransformData* transform = (CWorldTransformData*)entity->getDataByIndex(CWorldTransformData::DataTypeIndex); - m_decalTransforms.push_back(transform); - m_decalData.push_back(decalData); - } + m_decalTransforms.push_back(transform); + m_decalData.push_back(decalData); } } + } void CDecalsRenderer::init(CEntityManager* entityManager) @@ -83,28 +67,14 @@ namespace Skylicht void CDecalsRenderer::update(CEntityManager* entityManager) { - u32 numDecal = m_decalData.size(); - - // create decal buffer - CDecalData** decalDatas = m_decalData.pointer(); - CWorldTransformData** decalTransform = m_decalTransforms.pointer(); - for (u32 i = 0; i < numDecal; i++) - { - CDecalData* decalData = decalDatas[i]; - if (decalData->Change == true && - decalData->RenderData && - decalData->RenderData->Collision) - { - initDecal(decalData, decalTransform[i]->World.getTranslation()); - decalData->Change = false; - } - } } void CDecalsRenderer::render(CEntityManager* entityManager) { u32 numDecal = m_decalData.size(); + if (numDecal == 0) + return; // create decal buffer CDecalData** decalDatas = m_decalData.pointer(); @@ -112,131 +82,13 @@ namespace Skylicht IVideoDriver* videoDriver = getVideoDriver(); - // reset world transform - videoDriver->setTransform(video::ETS_WORLD, core::IdentityMatrix); - for (u32 i = 0; i < numDecal; i++) { CDecalData* decal = decalDatas[i]; - video::SMaterial& mat = decal->MeshBuffer->getMaterial(); - - videoDriver->setMaterial(mat); + videoDriver->setTransform(video::ETS_WORLD, decalTransform[i]->World); + videoDriver->setMaterial(decal->MeshBuffer->getMaterial()); videoDriver->drawMeshBuffer(decal->MeshBuffer); } } - - void CDecalsRenderer::initDecal(CDecalData* decal, const core::vector3df& position) - { - // Create boxes - irr::core::aabbox3df box = irr::core::aabbox3df( - position - decal->Dimension * 0.5f, - position + decal->Dimension * 0.5f - ); - - // Query tris collision - core::array triangles; - core::array nodes; - decal->RenderData->Collision->getTriangles(box, triangles, nodes); - u32 triangleCount = triangles.size(); - - // Scale to 0.0f - 1.0f (UV space) - core::vector3df uvScale = core::vector3df(1, 1, 1) / decal->Dimension; - core::vector3df uvOffset(0.5f, 0.0f, 0.5f); - - // UV Rotation matrix - core::quaternion r1; - r1.rotationFromTo(core::vector3df(0.0f, 1.0f, 0.0f), decal->Normal); - - core::quaternion r2; - r2.fromAngleAxis(decal->TextureRotation * core::DEGTORAD, core::vector3df(0.0f, 1.0f, 0.0f)); - - core::quaternion q = r2 * r1; - - core::matrix4 uvMatrix = q.getMatrix(); - uvMatrix.setTranslation(position); - - uvMatrix.makeInverse(); - - // Clip all triangles and fill vertex and indices - u32 vertexIndex = 0; - std::map positions; - - IIndexBuffer* indices = decal->MeshBuffer->getIndexBuffer(); - IVertexBuffer* vertices = decal->MeshBuffer->getVertexBuffer(); - - for (u32 i = 0; i < triangleCount; i++) - { - u32 index = 0; - - core::triangle3df uvTriangle = *triangles[i]; - core::triangle3df& triangle = *triangles[i]; - - core::vector3df triangleNormal = triangle.getNormal(); - triangleNormal.normalize(); - - // Rotate positions - uvMatrix.transformVect(uvTriangle.pointA); - uvMatrix.transformVect(uvTriangle.pointB); - uvMatrix.transformVect(uvTriangle.pointC); - - // Fill vertices and indices - { - video::SColor color(255, 255, 255, 255); - - for (u32 p = 0; p < 3; p++) - { - core::vector3df uvPos; - core::vector3df pos; - - if (p == 0) - { - uvPos = uvTriangle.pointA * uvScale + uvOffset; - pos = triangle.pointA; - } - else if (p == 1) - { - uvPos = uvTriangle.pointB * uvScale + uvOffset; - pos = triangle.pointB; - } - else if (p == 2) - { - uvPos = uvTriangle.pointC * uvScale + uvOffset; - pos = triangle.pointC; - } - - // Search if vertex already exists in the vertices list - std::map::iterator iter = positions.find(uvPos); - if (iter != positions.end()) - { - index = iter->second; - } - // Add vertex to list - else - { - index = vertexIndex; - positions.insert(std::pair(uvPos, vertexIndex)); - - pos += triangleNormal * decal->Distance; - - core::vector2df uv(uvPos.X, 1.0f - uvPos.Z); - - video::S3DVertex vtx( - pos, - triangleNormal, - color, - uv); - - vertices->addVertex(&vtx); - vertexIndex++; - } - - indices->addIndex(index); - } - } - } - - decal->MeshBuffer->recalculateBoundingBox(); - decal->MeshBuffer->setDirty(); - } } \ No newline at end of file diff --git a/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.h b/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.h index b822506bf..f04873397 100644 --- a/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.h +++ b/Projects/Skylicht/Collision/Source/Decal/CDecalsRenderer.h @@ -33,9 +33,6 @@ namespace Skylicht class CDecalsRenderer : public IRenderSystem { protected: - core::array m_decalRenders; - core::array m_transforms; - core::array m_decalData; core::array m_decalTransforms; @@ -52,8 +49,6 @@ namespace Skylicht virtual void update(CEntityManager* entityManager); - virtual void render(CEntityManager* entityManager); - - void initDecal(CDecalData* decal, const core::vector3df& position); + virtual void render(CEntityManager* entityManager); }; } \ No newline at end of file