Help with object picking

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Wathiant
Gnoblar
Posts: 10
Joined: Wed Aug 21, 2019 9:35 am
x 2

Help with object picking

Post by Wathiant »

I'm migrating from Ogre 1.9 to 2.1 and everything is working fine now, except for object picking by clicking on the screen.
I'm using code based on http://wiki.ogre3d.org/RetrieveVertexData, which first does a ray query followed by a mesh check to see if we actually hit the mesh.
The ray query works fine, but it uses bounding boxes and since I need to be able to pick an object out of many that are packed closely together, this isn't good enough.
The code used to work fine for Ogre 1.9 and it will build after some minor (v1 namespace) corrections, but the results are useless.
It comes down to a problem in getting the vertex information. At some point in this code, this call is made: posElem->baseVertexPointerToElement(vertex, &pReal);
For the first 8 vertices the results seem in a reasonable range, but it's hard to check if they're really correct. After that the rest has really strange big or tiny values, in the order of 1e15 or 1e33 etc. The values do seem to be consistent between calls and even between application runs, but completely useless for triangle intersection checks.
I'm guessing that this has something to do with the packed storage of values, but I don't know how to fix it. So I'm hoping someone here has the solution for this problem :D

ARRAY_PACKED_REALS is set to 4 (default)
I have attached debugger screenshots, one for vertex 0 (which seems ok), one for vertex 8 (which is the first that is definitely wrong) and one with a snapshot of the resulting vertices. If more information is needed to pinpoint the problem, please let me know.

Code: Select all

// Get the mesh information for the given mesh.
// Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData
void getMeshInformation(const Ogre::v1::MeshPtr mesh,
								size_t &vertex_count,
								Ogre::Vector3* &vertices,
								size_t &index_count,
								unsigned long* &indices,
								const Ogre::Vector3 &position,
								const Ogre::Quaternion &orient,
								const Ogre::Vector3 &scale)
{
	bool added_shared = false;
	size_t current_offset = 0;
	size_t shared_offset = 0;
	size_t next_offset = 0;
	size_t index_offset = 0;

	vertex_count = index_count = 0;

	// Calculate how many vertices and indices we're going to need
	for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
	{
		Ogre::v1::SubMesh* submesh = mesh->getSubMesh( i );

		// We only need to add the shared vertices once
		if (submesh->useSharedVertices)
		{
			if( !added_shared )
			{
				vertex_count += mesh->sharedVertexData[0]->vertexCount;
				added_shared = true;
			}
		}
		else
		{
			vertex_count += submesh->vertexData[0]->vertexCount;
		}

		// Add the indices
		index_count += submesh->indexData[0]->indexCount;
	}

	// Allocate space for the vertices and indices
	vertices = new Ogre::Vector3[vertex_count];
	indices = new unsigned long[index_count];

	added_shared = false;

	// Run through the submeshes again, adding the data into the arrays
	for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
	{
		Ogre::v1::SubMesh* submesh = mesh->getSubMesh(i);

		Ogre::v1::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData[0] : submesh->vertexData[0];

		if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
		{
			if(submesh->useSharedVertices)
			{
				added_shared = true;
				shared_offset = current_offset;
			}

			const Ogre::v1::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

			Ogre::v1::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

			unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::v1::HardwareBuffer::HBL_READ_ONLY));

			// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
			//  as second argument. So make it float, to avoid trouble when Ogre::Real will
			//  be compiled/typedefed as double:
			//      Ogre::Real* pReal;
			float* pReal = nullptr;

			for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);
				Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
				vertices[current_offset + j] = (orient * (pt * scale)) + position;
				// assert(abs(vertices[current_offset + j][0]) < 1000.0f);
			}

			vbuf->unlock();
			next_offset += vertex_data->vertexCount;
		}


		Ogre::v1::IndexData* index_data = submesh->indexData[0];
		size_t numTris = index_data->indexCount / 3;
		Ogre::v1::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

		bool use32bitindexes = (ibuf->getType() == Ogre::v1::HardwareIndexBuffer::IT_32BIT);

		unsigned long*  pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::v1::HardwareBuffer::HBL_READ_ONLY));
		unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);


		size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;

		if ( use32bitindexes )
		{
			for ( size_t k = 0; k < numTris*3; ++k)
			{
				indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
			}
		}
		else
		{
			for ( size_t k = 0; k < numTris*3; ++k)
			{
				indices[index_offset++] = static_cast<unsigned long>(pShort[k]) +
					static_cast<unsigned long>(offset);
			}
		}

		ibuf->unlock();
		current_offset = next_offset;
	}
}

Image

Image

Image

Thanks in advance :)
Wathiant
Gnoblar
Posts: 10
Joined: Wed Aug 21, 2019 9:35 am
x 2

Re: Help with object picking

Post by Wathiant »

I knew I shouldn't have posted this on friday the 13th, but I was hoping for at least a pointer to some documentation I missed :shock:
rujialiu
Goblin
Posts: 296
Joined: Mon May 09, 2016 8:21 am
x 35

Re: Help with object picking

Post by rujialiu »

Wathiant wrote: Fri Sep 20, 2019 11:25 am I knew I shouldn't have posted this on friday the 13th, but I was hoping for at least a pointer to some documentation I missed :shock:
Hmmm... Though I'm not using V1 entities anymore (for a long time), I can remember that I used exactly the same code snippet as you do, also did trivial changes like adding v1 namespace, and it automatically worked.

One trap we fell into, is that "long" can be 64-bit or 32-bit, depending on your compiler. Once we messed it up, resulting incorrect index size, then object picking "sometimes works and sometimes doesn't"

Besides that, I can't think of any other trap. Did you do anything very special? If you can convert your v1 objects to v2 objects I should be able to help more because we're doing a lot of object picking for v2 objects.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 169

Re: Help with object picking

Post by xrgo »

This my port for that method you linked:



just omit the "yObject" stuffs in the constructor and fill directly the mMesh (and the mNode, see below:)
notice that I dont really use the pos/ori/scale passed on the arguments and later when calling getRayIntersectionWithMesh I transform the ray to mesh's local coordinates using the SceneNode (mNode) of the item.... this way you can call getMeshInformation just one time, and store that in mVertices then later still get good result intersections even if the object has been moved/rotated (I omitted scaling)

cheers!!
Wathiant
Gnoblar
Posts: 10
Joined: Wed Aug 21, 2019 9:35 am
x 2

Re: Help with object picking

Post by Wathiant »

Thanks! I'll give it a try :)
Wathiant
Gnoblar
Posts: 10
Joined: Wed Aug 21, 2019 9:35 am
x 2

Re: Help with object picking

Post by Wathiant »

@xrgo Thanks for the code, but that's using v2 Meshes and I'm using v1 Meshes.
@rujialiu I can give it a try, but I hope there's nothing else that will break if I regenerate the meshes as v2.
I built Ogre with the same compiler that I'm now building my own code with, so I don't expect a conflict between definitions of long. I'm assuming it's intended as a 32-bit value here, but I'll play around with it a bit, see if it helps to change it to 16 bits.
And no, we're not doing anything special. The most special thing I did was that the meshes were upgraded form an older version to the latest (v1) version with the standard tool. Maybe that messed something up.
Wathiant
Gnoblar
Posts: 10
Joined: Wed Aug 21, 2019 9:35 am
x 2

Re: Help with object picking

Post by Wathiant »

Thanks for the tips. I reexported as the latest supported format (v1) which worked.
I then ran the OgreMeshTool since my Ogre complains about old formats, with the options I had provided before. At this point it stopped working again.
So I got the fresh files again and ran the OgreMeshTool with just the -srcd3d and -v1 options to upgrade without changing the internals of the mesh file and now object clicking works again! :)
Apparently I had some optimization option enabled that messed something up.

Cheers