diff --git a/changes.txt b/changes.txt index 62be9e55..7cb529fb 100644 --- a/changes.txt +++ b/changes.txt @@ -1,7 +1,7 @@ -------------------------- Changes in 1.9 (not yet released) -- Add options for transparency node sorting algorithm +- Add options for transparency node sorting algorithm. - CImageWriterPNG now also supports the writeImageToFile param to allow setting compressing level. 0 stays default, 1-10 for range increasing compression level. - Add io::IUserData which can be set in SMaterial to make it easer passing additional material values to shaders - Add lens shift support for the camera and the perspective projection functions diff --git a/include/ISceneManager.h b/include/ISceneManager.h index 60c325d5..71248ed1 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -111,18 +111,24 @@ namespace scene //! Which can be used to do some custom sorting via scene-graph (mainly useful if you only have to that once) ETNS_NONE, - //! Distance from node origin to camera + //! Distance from node origin to camera position ETNS_ORIGIN, - //! Distance from node center to camera + //! Distance from node center to camera position ETNS_CENTER, //! Distance from the nearest of the 2 transformed bounding-box extend corners to camera ETNS_BBOX_EXTENTS, + //! Distance from node origin to camera plane + ETNS_PLANE_ORIGIN, + + //! Distance from node center to camera plane + ETNS_PLANE_CENTER, + //! Default sorting Irrlicht uses currently //! This may change in the future - ETNS_DEFAULT = ETNS_CENTER + ETNS_DEFAULT = ETNS_PLANE_CENTER }; class IAnimatedMesh; diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index ef789190..92e4c8d1 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -1364,14 +1364,14 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE case ESNRP_TRANSPARENT: if (!isCulled(node)) { - TransparentNodeList.push_back(TransparentNodeEntry(node, funcTransparentNodeDistance(node, camWorldPos))); + TransparentNodeList.push_back(TransparentNodeEntry(node, funcTransparentNodeDistance(node, CamWorldPos, CamWorldViewNormalized))); taken = 1; } break; case ESNRP_TRANSPARENT_EFFECT: if (!isCulled(node)) { - TransparentEffectNodeList.push_back(TransparentNodeEntry(node, funcTransparentNodeDistance(node, camWorldPos))); + TransparentEffectNodeList.push_back(TransparentNodeEntry(node, funcTransparentNodeDistance(node, CamWorldPos, CamWorldViewNormalized))); taken = 1; } break; @@ -1386,7 +1386,7 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE if (Driver->needsTransparentRenderPass(node->getMaterial(i))) { // register as transparent node - TransparentNodeEntry e(node, funcTransparentNodeDistance(node, camWorldPos)); + TransparentNodeEntry e(node, funcTransparentNodeDistance(node, CamWorldPos, CamWorldViewNormalized)); TransparentNodeList.push_back(e); taken = 1; break; @@ -1486,11 +1486,17 @@ void CSceneManager::drawAll() consistent Camera is needed for culling */ IRR_PROFILE(getProfiler().start(EPID_SM_RENDER_CAMERAS)); - camWorldPos.set(0,0,0); if (ActiveCamera) { ActiveCamera->render(); - camWorldPos = ActiveCamera->getAbsolutePosition(); + CamWorldPos = ActiveCamera->getAbsolutePosition(); + CamWorldViewNormalized = ActiveCamera->getTarget() - ActiveCamera->getAbsolutePosition(); + CamWorldViewNormalized.normalize(); + } + else + { + CamWorldPos.set(0,0,0); + CamWorldViewNormalized.set(0,0,1); } IRR_PROFILE(getProfiler().stop(EPID_SM_RENDER_CAMERAS)); @@ -2196,44 +2202,59 @@ E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const } // Not sorting this later -static f32 transparentSortingNone(const ISceneNode* node, const core::vector3df& camera) +static f32 transparentSortingNone(const ISceneNode*, const core::vector3df&, const core::vector3df&) { return 0.f; } -// Distance from node origin to camera -static f32 transparentSortingByOrigin(const ISceneNode* node, const core::vector3df& camera) +// Distance from node origin to camera pos +static f32 transparentSortingByOrigin(const ISceneNode* node, const core::vector3df& cameraPos, const core::vector3df&) { - return node->getAbsolutePosition().getDistanceFromSQ(camera); + return node->getAbsolutePosition().getDistanceFromSQ(cameraPos); } -// Distance from node center to camera -static f32 transparentSortingByCenter(const ISceneNode* node, const core::vector3df& camera) +// Distance from node center to camera pos +static f32 transparentSortingByCenter(const ISceneNode* node, const core::vector3df& cameraPos, const core::vector3df&) { core::vector3df center = node->getBoundingBox().getCenter(); const core::matrix4& absMat = node->getAbsoluteTransformation(); absMat.rotateVect(center); - return (absMat.getTranslation()+center).getDistanceFromSQ(camera); + return (absMat.getTranslation()+center).getDistanceFromSQ(cameraPos); +} + +// Distance from node origin to camera plane +static f32 transparentSortingByPlaneOrigin(const ISceneNode* node, const core::vector3df& cameraPos, const core::vector3df& cameraViewN) +{ + return cameraViewN.dotProduct(node->getAbsolutePosition()-cameraPos); +} + +// Distance from node center to camera plane +static f32 transparentSortingByPlaneCenter(const ISceneNode* node, const core::vector3df& cameraPos, const core::vector3df& cameraViewN) +{ + core::vector3df center = node->getBoundingBox().getCenter(); + const core::matrix4& absMat = node->getAbsoluteTransformation(); + absMat.rotateVect(center); + return cameraViewN.dotProduct(absMat.getTranslation()+center-cameraPos); } /* const core::aabbox3d box = Node->getTransformedBoundingBox(); Distance = core::min_(camera.getDistanceFromSQ(box.MinEdge), camera.getDistanceFromSQ(box.MaxEdge)); */ -static f32 transparentSortingBBoxExtents(const ISceneNode* node, const core::vector3df& camera) +static f32 transparentSortingBBoxExtents(const ISceneNode* node, const core::vector3df& cameraPos, const core::vector3df&) { const core::aabbox3d& box = node->getBoundingBox(); const f32* m = node->getAbsoluteTransformation().pointer(); f32 p[4]; - p[0] = camera.X - (box.MinEdge.X * m[0] + box.MinEdge.Y * m[4] + box.MinEdge.Z * m[8] + m[12]); - p[1] = camera.Y - (box.MinEdge.X * m[1] + box.MinEdge.Y * m[5] + box.MinEdge.Z * m[9] + m[13]); - p[2] = camera.Z - (box.MinEdge.X * m[2] + box.MinEdge.Y * m[6] + box.MinEdge.Z * m[10] + m[14]); + p[0] = cameraPos.X - (box.MinEdge.X * m[0] + box.MinEdge.Y * m[4] + box.MinEdge.Z * m[8] + m[12]); + p[1] = cameraPos.Y - (box.MinEdge.X * m[1] + box.MinEdge.Y * m[5] + box.MinEdge.Z * m[9] + m[13]); + p[2] = cameraPos.Z - (box.MinEdge.X * m[2] + box.MinEdge.Y * m[6] + box.MinEdge.Z * m[10] + m[14]); f32 l0 = (p[0] * p[0]) + (p[1] * p[1]) + (p[2] * p[2]); - p[0] = camera.X - (box.MaxEdge.X * m[0] + box.MaxEdge.Y * m[4] + box.MaxEdge.Z * m[8] + m[12]); - p[1] = camera.Y - (box.MaxEdge.X * m[1] + box.MaxEdge.Y * m[5] + box.MaxEdge.Z * m[9] + m[13]); - p[2] = camera.Z - (box.MaxEdge.X * m[2] + box.MaxEdge.Y * m[6] + box.MaxEdge.Z * m[10] + m[14]); + p[0] = cameraPos.X - (box.MaxEdge.X * m[0] + box.MaxEdge.Y * m[4] + box.MaxEdge.Z * m[8] + m[12]); + p[1] = cameraPos.Y - (box.MaxEdge.X * m[1] + box.MaxEdge.Y * m[5] + box.MaxEdge.Z * m[9] + m[13]); + p[2] = cameraPos.Z - (box.MaxEdge.X * m[2] + box.MaxEdge.Y * m[6] + box.MaxEdge.Z * m[10] + m[14]); f32 l1 = (p[0] * p[0]) + (p[1] * p[1]) + (p[2] * p[2]); return core::min_(l0, l1); } @@ -2244,16 +2265,22 @@ void CSceneManager::setTransparentNodeSorting(E_TRANSPARENT_NODE_SORTING sorting switch ( TransparentNodeSorting ) { case ETNS_NONE: - funcTransparentNodeDistance = transparentSortingNone; + funcTransparentNodeDistance = transparentSortingNone; break; case ETNS_ORIGIN: - funcTransparentNodeDistance = transparentSortingByOrigin; + funcTransparentNodeDistance = transparentSortingByOrigin; break; case ETNS_CENTER: - funcTransparentNodeDistance = transparentSortingByCenter; + funcTransparentNodeDistance = transparentSortingByCenter; break; case ETNS_BBOX_EXTENTS: - funcTransparentNodeDistance = transparentSortingBBoxExtents; + funcTransparentNodeDistance = transparentSortingBBoxExtents; + break; + case ETNS_PLANE_ORIGIN: + funcTransparentNodeDistance = transparentSortingByPlaneOrigin; + break; + case ETNS_PLANE_CENTER: + funcTransparentNodeDistance = transparentSortingByPlaneCenter; break; default: break; diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index 3bf83be2..36be8029 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -654,7 +654,8 @@ namespace scene //! current active camera ICameraSceneNode* ActiveCamera; - core::vector3df camWorldPos; // Position of camera for transparent nodes. + core::vector3df CamWorldPos; // Position of camera for transparent nodes. + core::vector3df CamWorldViewNormalized; // Normalized view direction of camera for transparent nodes. video::SColor ShadowColor; video::SColorf AmbientLight; @@ -671,8 +672,7 @@ namespace scene //! Algorithm used to sort transparent nodes E_TRANSPARENT_NODE_SORTING TransparentNodeSorting; //! Pointer to the actual algorithm to get the distance - // (Could be we have to pass more parameters for better results, like view normal) - f32 (*funcTransparentNodeDistance)(const ISceneNode* node, const core::vector3df& camera); + f32 (*funcTransparentNodeDistance)(const ISceneNode* node, const core::vector3df& cameraPos, const core::vector3df& cameraViewNormalized); //! An optional callbacks manager to allow the user app finer control //! over the scene lighting and rendering.