FIRE-13814; Octree fixing.
- Do not create octree children that can cause precision problems. - Error out when trying to put more than 8 children into a parent. That would just overwrite memory. - Add logging for hte future.
parent
1f37b1c487
commit
b4e7faee77
|
|
@ -93,6 +93,10 @@ set(llmath_HEADER_FILES
|
|||
xform.h
|
||||
)
|
||||
|
||||
set( llmath_SOURCE_FILES ${llmath_SOURCE_FILES} nd/ndoctreelog.cpp )
|
||||
set( llmath_HEADER_FILES ${llmath_HEADER_FILES} nd/ndoctreelog.h )
|
||||
|
||||
|
||||
set_source_files_properties(${llmath_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "llvector4a.h"
|
||||
#include <vector>
|
||||
|
||||
#include "nd/ndoctreelog.h"
|
||||
|
||||
#define OCT_ERRS LL_WARNS("OctreeErrors")
|
||||
|
||||
|
||||
|
|
@ -120,6 +122,7 @@ public:
|
|||
if ((mOctant == 255) && mParent)
|
||||
{
|
||||
mOctant = ((oct_node*) mParent)->getOctant(mCenter);
|
||||
ND_OCTREE_LOG << "set octant to " << (U32)mOctant << " mCenter " << mCenter << " mParent->mCenter " << mParent->mCenter << ND_OCTREE_LOG_END;
|
||||
}
|
||||
|
||||
mElementCount = 0;
|
||||
|
|
@ -319,12 +322,22 @@ public:
|
|||
}
|
||||
LLOctreeNode<T>* parent = getOctParent();
|
||||
|
||||
ND_OCTREE_LOG << "Inserting data, this->getSize " << this->getSize() << " this->getElementCount() " << this->getElementCount() << " this->getChildCount() " << this->getChildCount() << std::endl
|
||||
<< " this->mMin " << this->mMin << " this->mMax " << this->mMax << std::endl
|
||||
<< " data->getPositionGroup().greaterThan(mMax).getGatheredBits() " << (S32)( data->getPositionGroup().greaterThan(mMax).getGatheredBits() & 0x7 )
|
||||
<< " data->getPositionGroup().lessEqual(mMin).getGatheredBits() " << (S32)(data->getPositionGroup().lessEqual(mMin).getGatheredBits() & 0x7)
|
||||
<< std::endl << " data->getBinRadius() " << data->getBinRadius() << " data->getPositionGroup() " << data->getPositionGroup() << ND_OCTREE_LOG_END;
|
||||
|
||||
//is it here?
|
||||
if (isInside(data->getPositionGroup()))
|
||||
{
|
||||
ND_OCTREE_LOG << "Inserting data, isInside(data->getPositionGroup()) true " << ND_OCTREE_LOG_END;
|
||||
|
||||
if (((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius()) ||
|
||||
(data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
|
||||
{ //it belongs here
|
||||
ND_OCTREE_LOG << "Inserting data into this" << ND_OCTREE_LOG_END;
|
||||
|
||||
mData.push_back(NULL);
|
||||
mData[mElementCount] = data;
|
||||
mElementCount++;
|
||||
|
|
@ -335,11 +348,20 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
ND_OCTREE_LOG << "Inserting data into children this->getChildCount() " << this->getChildCount() << ND_OCTREE_LOG_END;
|
||||
|
||||
//find a child to give it to
|
||||
oct_node* child = NULL;
|
||||
for (U32 i = 0; i < getChildCount(); i++)
|
||||
{
|
||||
child = getChild(i);
|
||||
|
||||
ND_OCTREE_LOG << "child " << i << " child->getSize " << child->getSize() << " child->getElementCount() " << child->getElementCount() << " child->getChildCount() " << child->getChildCount() << std::endl
|
||||
<< " child->mMin " << child->mMin << " child->mMax " << child->mMax << std::endl
|
||||
<< " data->getPositionGroup().greaterThan(child->mMax).getGatheredBits() " << (S32)(data->getPositionGroup().greaterThan(child->mMax).getGatheredBits() & 0x7)
|
||||
<< " data->getPositionGroup().lessEqual(child->mMin).getGatheredBits() " << (S32)(data->getPositionGroup().lessEqual(child->mMin).getGatheredBits() & 0x7)
|
||||
<< std::endl << ND_OCTREE_LOG_END;
|
||||
|
||||
if (child->isInside(data->getPositionGroup()))
|
||||
{
|
||||
child->insert(data);
|
||||
|
|
@ -363,8 +385,15 @@ public:
|
|||
|
||||
S32 lt = val.lessThan(min_diff).getGatheredBits() & 0x7;
|
||||
|
||||
if( lt == 0x7 )
|
||||
ND_OCTREE_LOG << "Creating a new child new center " << center << " new size " << size << " val " << val << " min_diff " << min_diff << " lt " << lt << ND_OCTREE_LOG_END;
|
||||
|
||||
// <FS:ND> Do not create a child if any of x/y/z is under minimum. One of those falling below is enough to get precision errors.
|
||||
// if( lt == 0x7 )
|
||||
if( lt )
|
||||
// </FS:ND>
|
||||
{
|
||||
ND_OCTREE_LOG << "Adding to parent and exit" << ND_OCTREE_LOG_END;
|
||||
|
||||
mData.push_back(NULL);
|
||||
mData[mElementCount] = data;
|
||||
mElementCount++;
|
||||
|
|
@ -393,6 +422,8 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
ND_OCTREE_LOG << "Adding to child" << ND_OCTREE_LOG_END;
|
||||
|
||||
llassert(size[0] >= gOctreeMinSize*0.5f);
|
||||
//make the new kid
|
||||
child = new LLOctreeNode<T>(center, size, this);
|
||||
|
|
@ -577,6 +608,10 @@ public:
|
|||
OCT_ERRS <<"Octree node has too many children... why?" << llendl;
|
||||
}
|
||||
#endif
|
||||
ND_OCTREE_LOG << "addChild octant " << (U32)child->getOctant() << " mChildCount " << mChildCount << ND_OCTREE_LOG_END;
|
||||
|
||||
if( mChildCount >= 8 )
|
||||
llerrs << "Octree overrun" << llendl;
|
||||
|
||||
mChildMap[child->getOctant()] = mChildCount;
|
||||
|
||||
|
|
|
|||
|
|
@ -5373,6 +5373,8 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
|
|||
return;
|
||||
}
|
||||
|
||||
ND_OCTREE_LOG << "Creating octree with scale " << scaler << " mNumIndices " << mNumIndices << ND_OCTREE_LOG_END;
|
||||
|
||||
mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL);
|
||||
new LLVolumeOctreeListener(mOctree);
|
||||
|
||||
|
|
@ -5417,10 +5419,18 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
|
|||
|
||||
tri->mRadius = size.getLength3().getF32() * scaler;
|
||||
|
||||
ND_OCTREE_LOG << "insertion " << i
|
||||
<< " tri.mV " << *tri->mV[0] << "/" << *tri->mV[1] << "/" << *tri->mV[2]
|
||||
<< " tri.mIndex " << tri->mIndex[0] << "/" << tri->mIndex[1] << "/" << tri->mIndex[2]
|
||||
<< ND_OCTREE_LOG_END;
|
||||
|
||||
//insert
|
||||
mOctree->insert(tri);
|
||||
ND_OCTREE_LOG << "insertion done" << std::endl << ND_OCTREE_LOG_END;
|
||||
}
|
||||
|
||||
ND_OCTREE_LOG << "octree created" << std::endl << std::endl << ND_OCTREE_LOG_END;
|
||||
|
||||
//remove unneeded octree layers
|
||||
while (!mOctree->balance()) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* $LicenseInfo:firstyear=2014&license=fsviewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (C) 2014, Nicky Dasmijn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include "../llmath.h"
|
||||
#include "ndoctreelog.h"
|
||||
|
||||
|
||||
namespace nd
|
||||
{
|
||||
namespace octree
|
||||
{
|
||||
namespace debug
|
||||
{
|
||||
U32 gOctreeDebug;
|
||||
std::ofstream *pLogStream;
|
||||
std::string mOctreeLogFilename;
|
||||
|
||||
void setOctreeLogFilename( std::string const &aFilename )
|
||||
{
|
||||
mOctreeLogFilename = aFilename;
|
||||
}
|
||||
|
||||
void doOctreeLog( std::string const &aStr )
|
||||
{
|
||||
if( pLogStream )
|
||||
{
|
||||
*pLogStream << aStr;
|
||||
pLogStream->flush();
|
||||
}
|
||||
}
|
||||
|
||||
void checkOctreeLog()
|
||||
{
|
||||
if( !pLogStream && mOctreeLogFilename.size() )
|
||||
{
|
||||
pLogStream = new std::ofstream();
|
||||
pLogStream->open( mOctreeLogFilename.c_str(), std::ios::out );
|
||||
if( pLogStream->is_open() )
|
||||
{
|
||||
time_t curTime;
|
||||
time(&curTime);
|
||||
tm *curTimeUTC = gmtime( &curTime );
|
||||
|
||||
*pLogStream << "Starting octree log" << asctime( curTimeUTC ) << std::endl;
|
||||
pLogStream->flush();
|
||||
}
|
||||
else
|
||||
delete pLogStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* $LicenseInfo:firstyear=2014&license=fsviewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (C) 2014, Nicky Dasmijn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef NDOCTREELOG_H_
|
||||
#define NDOCTREELOG_H_
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace nd
|
||||
{
|
||||
namespace octree
|
||||
{
|
||||
namespace debug
|
||||
{
|
||||
extern U32 gOctreeDebug;
|
||||
void doOctreeLog( std::string const &aStr );
|
||||
void checkOctreeLog();
|
||||
void setOctreeLogFilename( std::string const & );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ND_OCTREE_LOG { if( nd::octree::debug::gOctreeDebug ){ nd::octree::debug::checkOctreeLog(); std::stringstream strm; strm << std::setprecision(10)
|
||||
#define ND_OCTREE_LOG_END std::endl; nd::octree::debug::doOctreeLog( strm.str() ); } }
|
||||
|
||||
inline std::ostream& operator<<( std::ostream &strm, const LLVector4a &vc )
|
||||
{
|
||||
strm << "{" << vc[0] << "/" << vc[1] << "/" << vc[2] << "}";
|
||||
return strm;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -22076,6 +22076,21 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<integer>1</integer>
|
||||
</map>
|
||||
<!-- <FS:Zi> Optionally disable the usage of timesteps - FIRE-3657 -->
|
||||
<!-- <FS:ND> Create a debyg log for octree insert -->
|
||||
<key>FSCreateOctreeLog</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Create a log of octree operation. This can cause huge frame stalls on edit</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<!-- <FS:ND/> -->
|
||||
</map>
|
||||
</llsd>
|
||||
|
||||
|
|
|
|||
|
|
@ -263,6 +263,8 @@
|
|||
|
||||
#include "nd/ndmallocstats.h" // <FS:ND/> collect stats about memory allocations
|
||||
#include "nd/ndallocstats.h" // <FS:ND/> collect stats about memory allocations
|
||||
#include "nd/ndoctreelog.h" // <FS:ND/> Octree operation logging.
|
||||
|
||||
#include "fsradar.h"
|
||||
|
||||
|
||||
|
|
@ -834,6 +836,8 @@ bool LLAppViewer::init()
|
|||
|
||||
nd::allocstats::startUp(); // <FS:ND/> start collecting alloc stats
|
||||
nd::mallocstats::startUp(); // <FS:ND/> start collecting alloc stats
|
||||
nd::octree::debug::setOctreeLogFilename( gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "octree.log" ) ); // <FS:ND/> Filename to log octree options to.
|
||||
|
||||
|
||||
//
|
||||
// Start of the application
|
||||
|
|
|
|||
|
|
@ -4146,7 +4146,19 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
|
|||
size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]);
|
||||
size.splat(size.getLength3().getF32()*0.5f);
|
||||
|
||||
// <FS:ND> Create a debug log for octree insertions if requested.
|
||||
static LLCachedControl<bool> debugOctree(gSavedSettings,"FSCreateOctreeLog");
|
||||
bool _debugOT( debugOctree );
|
||||
if( _debugOT )
|
||||
nd::octree::debug::gOctreeDebug += 1;
|
||||
// </FS:ND>
|
||||
|
||||
dst_face.createOctree(1.f);
|
||||
|
||||
// <FS:ND> Reset octree log
|
||||
if( _debugOT )
|
||||
nd::octree::debug::gOctreeDebug -= 1;
|
||||
// </FS:ND>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue