Find the color of a vertex?

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Find the color of a vertex?

Post by Quark » Mon Apr 20, 2009 10:41 am

Is it possible to retrieve the color of a specific vertex? The base color, determined by the material, without any light influence?
I got the x,y float2 texture coordinates, found by retrieving VES_TEXTURE_COORDINATES alright, but how do I perform the texture lookup?
0 x

ming.zhu
Kobold
Posts: 30
Joined: Sun Nov 09, 2008 5:16 am
Location: Shanghai, China

Re: Find the color of a vertex?

Post by ming.zhu » Wed Apr 22, 2009 8:40 am

You already have the texture-coords right? Then just lock the texture and you can get the pixel data~
0 x

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Wed Apr 22, 2009 8:51 am

Could you point me in the right direction? How do I lock the texture and get the pixel data? Which class allows me to do so?
0 x

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Mon Apr 27, 2009 7:45 am

*bump*

Could anyone tell me exactly how to do a texture lookup in Ogre3D?
How do I lock the texture and get the pixel data?
0 x

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Mon May 04, 2009 9:00 am

Sorry to bump again, but I'm still a bit stuck on this.
0 x

User avatar
madmarx
OGRE Expert User
OGRE Expert User
Posts: 1668
Joined: Mon Jan 21, 2008 10:26 pm

Re: Find the color of a vertex?

Post by madmarx » Mon May 04, 2009 7:10 pm

There is an example of locking a texture, accessing the pixel data of the texture in the ogre demo called "dyn_tex" (for "dynamic texture").
From my head : get the texture from the texture manager, then ask for a pixel buffer (I can't remember if I had to create a pixel buffer to receive the texture last time I used this feature), and then call lock() on the pixel buffer. The lock will give you a pointer to the data of the texture (be careful of the data format anyway, not everything is RGB24).

Hope this help! :D

Good luck!


EDIT:
in OgreTexture :
HardwarePixelBufferSharedPtr getBuffer (size_t face=0, size_t mipmap=0)=0
then T * get () const
then virtual void * lock (size_t offset, size_t length, LockOptions options)
then unlock.
For example (NEVER write it like that of course !).
TextureManager::getSingletonPtr()->getByName("myTex")->getBuffer().get()->lock(size of the texture, ...);
0 x
Tutorials + Ogre searchable API + more for Ogre1.7 : http://sourceforge.net/projects/so3dtools/
Corresponding thread : http://www.ogre3d.org/forums/viewtopic. ... 93&start=0

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Tue Jul 07, 2009 11:50 am

It's been a while since my post. I've been working on other stuff and I couldn't return to this before.

I found the dynamic texture example at Wiki - Creating_dynamic_textures. This seems to be what you meant.

Also, I can use vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES) to find the texture coordinates alright.

However, how do I get a TexturePtr to the texture to use? For my specific submesh..
0 x

User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
Contact:

Re: Find the color of a vertex?

Post by Kencho » Tue Jul 07, 2009 12:27 pm

TextureManager::getByName() is one way. TextureUnitState::_getTexturePtr() is other.
0 x
Image

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Wed Jul 08, 2009 11:15 am

Ok, this is how I'm planning to do it, do you guys spot any problems with it?

Code: Select all

SubMesh* submesh; 	// Initialized elsewhere

Ogre::VertexData* vertex_data = submesh->useSharedVertices ? data.mesh->sharedVertexData : submesh->vertexData;
if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
{
	if(submesh->useSharedVertices) {
		added_shared = true;
		shared_offset = current_offset;
	}

	const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
	const Ogre::VertexElement* norElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL);
	const Ogre::VertexElement* texElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES, 0);
	Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
	unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
	float* pReal;
	float* nReal;
	float* tReal;

	for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) {
		posElem->baseVertexPointerToElement(vertex, &pReal);
		norElem->baseVertexPointerToElement(vertex, &nReal);
		texElem->baseVertexPointerToElement(vertex, &tReal);

		// What I'm trying to do here is find the (base) color of the current vertex
		Pass* pass = ((MaterialPtr) MaterialManager::getSingleton().getByName(submesh->getMaterialName()))->getTechnique(0)->getPass(0);
		if (pass->getNumTextureUnitStates() > 0) {
			TextureUnitState* texunit = pass->getTextureUnitStateIterator().getNext();
			TexturePtr texture = texunit->_getTexturePtr();

			// Get the pixel buffer
			HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();

			// Lock the pixel buffer and get a pixel box
			pixelBuffer->lock(HardwareBuffer::HBL_DISCARD);
			const PixelBox& pixelBox = pixelBuffer->getCurrentLock();

			int width = pixelBox.getWidth();
			int height = pixelBox.getHeight();
			std::cout << "width=" << width << " height=" << height << "\n";
			uint8* pDest = static_cast<uint8*>(pixelBox.data);

			// pDest contains our RGBA data (considering color format)

			pixelBuffer->unlock();
		}
	}
}
I assume that pDest contains all pixels.

However, how can I retrieve the color for the current vertex? Tex.x and tex.y contains floats from a wide range (including negative floats), so I assume I'm doing something wrong.
0 x

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Mon Jul 13, 2009 8:46 am

*bump*

How do I use the texture_coordinates properly? What's the correct range (from 0.0f to 1.0f?)?

Code: Select all

uint8* pDest = static_cast<uint8*>(pixelBox.data);
This holds the texture_coordinates, but in my current model this can range from -10.0f to 110.0f, I can't really use it properly.
0 x

User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
Contact:

Re: Find the color of a vertex?

Post by Kencho » Mon Jul 13, 2009 8:53 am

I'm afraid you're mixing concepts here...
First of all, pixel boxes are "raw" images. The "uint8" data type should hint that the possible values are integers in the range [0, 255]. Then, they only store colour information, not texture coordinates.

Now, assuming you meant that you want to obtain the texture colour at positions outside the [0, 1] range, it all depends on the texture addressing mode. If you use clamping, then values below 0 are the values at 0 and above 1 are the values at 1. Wrapping results in repeating the whole cycle of [0, 1] (as with the modulus of a division), and so on.
0 x
Image

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Mon Jul 13, 2009 10:01 am

Oh sorry, I'm indeed mixing things up. I posted too soon without thinking right.
The pixelbox indeed holds the raw texture.

In my case tReal[0] and tReal[1] hold the x,y texture coordinates. And these values range from -10.0f to 110.0f in this case.

I'm wondering how to use these correctly. Must I clamp them to the range [0.0 .. 1.0]?
0 x

User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
Contact:

Re: Find the color of a vertex?

Post by Kencho » Mon Jul 13, 2009 1:19 pm

That's up to you. Sometimes you will want to clamp it, and sometimes you'll want to wrap it. Would you tile that texture? If so, wrap it. Otherwise, clamp it ;)
0 x
Image

Quark
Greenskin
Posts: 103
Joined: Tue Feb 27, 2007 2:55 pm

Re: Find the color of a vertex?

Post by Quark » Fri Jul 17, 2009 3:15 pm

I just can't seem to get any vertex color data using the above code.
Could any of you gurus please check if I'm doing anything wrong?

(Both using clamping and wrapping I'm not getting any color data)
0 x

ming.zhu
Kobold
Posts: 30
Joined: Sun Nov 09, 2008 5:16 am
Location: Shanghai, China

Re: Find the color of a vertex?

Post by ming.zhu » Thu Jul 23, 2009 4:41 am

You tried to get tex_coord data from the same vertex buffer source that stores the position data. However they may be of different sources.

Btw don't do lock/unlock in the vertex loop.
0 x

ming.zhu
Kobold
Posts: 30
Joined: Sun Nov 09, 2008 5:16 am
Location: Shanghai, China

Re: Find the color of a vertex?

Post by ming.zhu » Thu Jul 23, 2009 4:53 am

Just have a look at my comment.

Code: Select all

SubMesh* submesh; 	// Initialized elsewhere

Ogre::VertexData* vertex_data = submesh->useSharedVertices ? data.mesh->sharedVertexData : submesh->vertexData;
if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
{
	if(submesh->useSharedVertices) {
		added_shared = true;
		shared_offset = current_offset;
	}

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

/* the texElem may be of a different source from the posElem. You could try getSource to check it */
	const Ogre::VertexElement* texElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES, 0);

/* the vbuf is the buffer for the position data, you can pass in texElem->getSource() as the param to get tex_coord data */
	Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

	unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
	float* pReal;
	float* nReal;
	float* tReal;

	for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) {
		posElem->baseVertexPointerToElement(vertex, &pReal);
		norElem->baseVertexPointerToElement(vertex, &nReal);

/* after you get the tReal for the texture UV data, you could use it to get the color info from the texture( pixel box )
    usually the UV data should be two floats of the range [0.0, 1.0] */
		texElem->baseVertexPointerToElement(vertex, &tReal);

/* don't do lock/unlock here. move it out of the loop. */
		// What I'm trying to do here is find the (base) color of the current vertex
		Pass* pass = ((MaterialPtr) MaterialManager::getSingleton().getByName(submesh->getMaterialName()))->getTechnique(0)->getPass(0);
		if (pass->getNumTextureUnitStates() > 0) {
			TextureUnitState* texunit = pass->getTextureUnitStateIterator().getNext();
			TexturePtr texture = texunit->_getTexturePtr();

			// Get the pixel buffer
			HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();

/* don't use HBL_DISCARD since you want to read but not change the texture data. Try HBL_READ_ONLY */
			// Lock the pixel buffer and get a pixel box
			pixelBuffer->lock(HardwareBuffer::HBL_DISCARD);
			const PixelBox& pixelBox = pixelBuffer->getCurrentLock();

			int width = pixelBox.getWidth();
			int height = pixelBox.getHeight();
			std::cout << "width=" << width << " height=" << height << "\n";
/* you may need to check the format for the pixel box. uint8 is not always the case. */
			uint8* pDest = static_cast<uint8*>(pixelBox.data);

			// pDest contains our RGBA data (considering color format)

			pixelBuffer->unlock();
		}
	}
}
0 x

Post Reply