Limit for number of objects

Technical discussions
Post Reply
Tor A
Posts: 4
Joined: Tue Dec 04, 2018 3:48 am

Limit for number of objects

Post by Tor A »

Hi!
We try to use KernelCad to display items in a database as boxes in the ocx in our VS C++ programmed container loading software. It takes very long time to add 3.000 items in the model by using IStdShape->Box. When all the boxes are added, the system crashes on IView->Reset. I looks like the system runs out of memory... Is there a limit considering how many objects KernelCAD can handle?

nickz
Site Admin
Posts: 236
Joined: Fri Jul 26, 2013 3:58 am

Re: Limit for number of objects

Post by nickz »

Hi Tor

Sorry about the problem. Yes it seems that you have hit a limit on the video card. There is no limit in our software.

Core of the problem is in the application design though. Our assumption is that an object is something complex with internal structure and geometric info about each patch. It is a significant amount of data per object. The expected number of object is tens on average, hundreds at most.

The 3DS type of object used for the default box has some overhead in memory consumption to keep the patch structure.

What I suggest as a quick workaround is reducing geometric resolution to minimum = 1. After you have created the box, add a call ISection.SetGeomResolution(1); The default there is 7. It might solve your problem.

A longer term solution would be to create the box as a mesh section. It has smaller default overhead and you can create its surface with minimal number of elements. So, I suggest implementing something like AddMeshBox(location, size, name) and inside build a mesh objects copying code from CMorphDlg::CreateDefault() of Morph sample. I recommend queering IDIObjGenerator from IModel instead. It is faster.

Even more economical solution is to have all the boxes as a single mesh section and have something like UpdateBoxSet(MyBoxList& boxes) which can be called many times when something in the box list has changed. This will make rendering faster also.

We can help with a sample which demonstrates that. Would you like that?

Tor A
Posts: 4
Joined: Tue Dec 04, 2018 3:48 am

Re: Limit for number of objects

Post by Tor A »

Thank you for your quick feedback and good suggestions. We would certainly appreciate a custom sample. Mesh seems to be a much quicker way of creating the model than boxes, but still uses too much memory. We’ve used IDraw-> Vertex on ISection objects in an IArray (which seems to use less memory).

nickz
Site Admin
Posts: 236
Joined: Fri Jul 26, 2013 3:58 am

Re: Limit for number of objects

Post by nickz »

Here it is:
http://www.dynoinsight.com/Prod/Examples/BoxesTest.zip
Or see the snippet below

It is a quick modification of C++ DIView sample. It demonstrates the third way: Creating all boxes in one mesh. It is a "Rendering into a mesh" technique.

It creates 8000 boxes. It starts in about a second on my machine. The rendering is pretty smooth.

In case you need a different colour it can be done with per vertex colour. Selection can be done by drawing a wire around boxes.

If you going to go this way you could store position of the relevant first vertex and simplex in your Box (or something) class and/or the DB record for easy removal or modification

Declarations:

Code: Select all

IModel* m_iModel = nullptr;
	ISection* m_iCargo = nullptr;
	IMeshTopolT* m_iMeshTopol = nullptr;
	IMeshT* m_iMesh = nullptr;
	IMeshExT* m_iMeshEx = nullptr;
	IIteratorT* m_iVertexIterator = nullptr;
	IIteratorT* m_iSimplexIterator = nullptr;
	IMeshModsT* m_iMeshMods = nullptr;
	INT_PTR m_posnVtx[8];		// Vertex position of the current box
	byte m_curNormal[8];
Code from DIViewView.cpp:

Code: Select all

void CDIViewView::Init()
{
	m_iModel = (IModel*)m_kernCAD.GetModel();

	IDIObjGenerator* iObjGenerator = nullptr;
	m_iModel->QueryInterface(IID_IDIObjGenerator, (void**)&iObjGenerator);
	iObjGenerator->Create(eObjTypeMeshSection, (IUnknown**)&m_iCargo);
	IModel2* iModel2 = nullptr;
	m_iModel->QueryInterface(IID_IModel2, (void**)&iModel2);
	iModel2->Add(m_iCargo);

	m_iCargo->QueryInterface(IID_IMeshTopolT, (void**)&m_iMeshTopol);
	m_iCargo->QueryInterface(IID_IMeshT, (void**)&m_iMesh);
	m_iMesh->QueryInterface(IID_IMeshExT, (void**)&m_iMeshEx);
	m_iMesh->GetVertexIterator(&m_iVertexIterator);
	m_iMesh->GetSimplexIterator(&m_iSimplexIterator);
	m_iCargo->QueryInterface(IID_IMeshModsT, (void**)&m_iMeshMods);

	LoadCargo();

	// Fit into the view
	IView* iView = (IView*)m_kernCAD.GetView();
	iView->Reset(VARIANT_TRUE);

	iView->Release(); iModel2->Release();	iObjGenerator->Release();
}

void CDIViewView::LoadCargo()
{
	DIPoint pt; memset(pt.x, 0, 3*sizeof(double));

	double sizeBox[] = {1, 2, 3};

	int nBoxesRow = 20;
	int nBoxesTotal = nBoxesRow*nBoxesRow*nBoxesRow;

	for (int i = 0; i < nBoxesRow; i++)
	{
		pt.x[1] = 0;
		for (int j = 0; j < nBoxesRow; j++)
		{
			pt.x[0] = 0;
			for (int k = 0; k < nBoxesRow; k++)
			{
				LoadBox(pt, sizeBox);
				pt.x[0] += 1.1*sizeBox[0];
			}
			pt.x[1] += 1.1*sizeBox[1];
		}

		pt.x[2] += 1.1*sizeBox[2];
	}
}

void CDIViewView::SetNormal(IVertex* iVertex, byte indNormal, byte axis, bool min)
{
	double v[] = {0,0,0};
	v[axis] = (min ? -1 : 1);
	iVertex->SetNormal(indNormal, v[0], v[1], v[2]);
}

void CDIViewView::SetNormalIndices(ISimplexT* iSimplex, int i0, int i1, int i2)
{
	iSimplex->SetNormalIndex(0, i0);
	iSimplex->SetNormalIndex(1, i1);
	iSimplex->SetNormalIndex(2, i2);
}

void CDIViewView::DefineVertex(int ind, double x, double y, double z, byte normal0Axis, bool normal0Min, byte normal1Axis, bool normal1Min, byte normal2Axis, bool normal2Min)
{
	m_iMeshMods->SetVertexCoord(m_posnVtx[ind], x, y, z);

	// Normals
	IVertex* iVertex = nullptr;
	m_iMeshEx->GetVertex(m_posnVtx[ind], &iVertex);
	iVertex->SetNormalCount(3);
	SetNormal(iVertex, 0, normal0Axis, normal0Min);
	SetNormal(iVertex, 1, normal1Axis, normal1Min);
	SetNormal(iVertex, 2, normal2Axis, normal2Min);
	iVertex->Release();
}

ISimplexT* CDIViewView::AddSimplex(int iVtx0, int iVtx1, int iVtx2)
{
	m_iMeshTopol->AddSimplex(m_posnVtx[iVtx0], m_posnVtx[iVtx1], m_posnVtx[iVtx2], -1);	// -1 - do not do anything with normals. It is manually managed here
	// Get it:
	POSNT tail = 0;
	m_iSimplexIterator->GetTailPosition(&tail);
	ISimplexT* iSimplex = nullptr;
	m_iMeshEx->GetSimplex(tail, &iSimplex);
	return iSimplex;
}

void CDIViewView::AddQuad(int iVtx0, int iVtx1, int iVtx2, int iVtx3)
{
	ISimplexT* iSimplex0 = AddSimplex(iVtx0, iVtx1, iVtx2);

	SetNormalIndices(iSimplex0, m_curNormal[iVtx0], m_curNormal[iVtx1], m_curNormal[iVtx2]);

	ISimplexT* iSimplex1 = AddSimplex(iVtx0, iVtx2, iVtx3);

	SetNormalIndices(iSimplex1, m_curNormal[iVtx0], m_curNormal[iVtx2], m_curNormal[iVtx3]);

	m_curNormal[iVtx0]++; m_curNormal[iVtx1]++;  m_curNormal[iVtx2]++; m_curNormal[iVtx3]++;

	iSimplex0->Release();	iSimplex1->Release();
}

void CDIViewView::LoadBox(DIPoint& pt, double sizeBox[3])
{
	memset(m_posnVtx, 0, 8 * sizeof(INT_PTR));
	memset(m_curNormal, 0, 8 * sizeof(byte));

	for (int i = 0; i<8; i++)
		m_iMeshTopol->AddVertex(m_posnVtx + i);

	// Front vertices
	DefineVertex(0, pt.x[0], pt.x[1], pt.x[2] + sizeBox[2],							2, false, 1, true, 0, true);
	DefineVertex(1, pt.x[0] + sizeBox[0], pt.x[1], pt.x[2] + sizeBox[2],				2, false, 1, true, 0, false);
	DefineVertex(2, pt.x[0] + sizeBox[0], pt.x[1] + sizeBox[1], pt.x[2] + sizeBox[2],		2, false, 0, false, 1, false);
	DefineVertex(3, pt.x[0], pt.x[1] + sizeBox[1], pt.x[2] + sizeBox[2],				2, false, 1, false, 0, true);

	// Back vertices
	DefineVertex(4, pt.x[0], pt.x[1], pt.x[2],									2, true, 1, true, 0, true);
	DefineVertex(5, pt.x[0] + sizeBox[0], pt.x[1], pt.x[2],							2, true, 1, true, 0, false);
	DefineVertex(6, pt.x[0] + sizeBox[0], pt.x[1] + sizeBox[1], pt.x[2],				2, true, 0, false, 1, false);
	DefineVertex(7, pt.x[0], pt.x[1] + sizeBox[1], pt.x[2],							2, true, 1, false, 0, true);

	AddQuad(0, 1, 2, 3);	// Front
	AddQuad(4, 7, 6, 5);	// Back
	AddQuad(0, 4, 5, 1);	// Bottom
	AddQuad(1, 5, 6, 2);	// Right
	AddQuad(3, 2, 6, 7);	// Top
	AddQuad(0, 3, 7, 4);	// Left
}

Tor A
Posts: 4
Joined: Tue Dec 04, 2018 3:48 am

Re: Limit for number of objects

Post by Tor A »

Thank you, Nick
We will try that

Tor A
Posts: 4
Joined: Tue Dec 04, 2018 3:48 am

Re: Limit for number of objects

Post by Tor A »

Thank you very much for the sample, is was very useful. Adding boxes without creating objects seems to be very effective when it comes to use of memory.
So the problem now seems to be updating the user interface. After adding 27.000 boxes it takes about 2,5 minutes to run iView->Reset(VARIANT_TRUE). 64.000 boxes takes 30 minutes... Are there any alternatives to update the view?

nickz
Site Admin
Posts: 236
Joined: Fri Jul 26, 2013 3:58 am

Re: Limit for number of objects

Post by nickz »

Hi Tor
We have made an improvement in the latest update. There was a bit of bottleneck in presentation generation.
Thank you for pointing it out

Post Reply