terrain, get texture pixel from collision point

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
monkeycracks
Posts: 1029
Joined: Thu Apr 06, 2006 12:45 am
Location: Tennesee, USA
Contact:

terrain, get texture pixel from collision point

Post by monkeycracks »

I'm shooting a ray from the camera and obtaining an intersection point on an ITerrainSceneNode

The texture that I want to interact with is 1024x1024, while the heightmap is scaled to (40, 1, 40) and is a 257x257

So far I have

TextureY = 1024-(intersection.X+4)/40;
TextureX = (intersection.Z+4)/40;

The Y value seems correct, but the X value does not. It seems the further to the right I go, the smaller it gets (reverse what I'd expect). I know how to get the pixel color after I calculate these two numbers.. I just can't figure out how to calculate them :D

Anyone have any ideas?


Edit to add: I was wrong about the Y value. It's far from correct.
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

Here is a solution from my project. Maybe it helps :)

Code: Select all

unsigned int GetSelectedColor(const core::matrix4& m, const core::triangle3df& tri, const core::vector3df& point, video::IImage* colormap, const core::array<vector3df>& Vertices, const core::array<vector2df>& Textcoord)
{
	u32 indices[3];
	bool found[3];

	memset(found, 0, sizeof(found));
	for(u32 counter = 0; counter < Vertices.size(); counter++)
	{
		vector3df tempvec	= Vertices[counter];
		m.transformVect(tempvec);

		if(!found[0] && (tempvec - tri.pointA).getLengthSQ() < 0.0001f)
		{
			indices[0]	= counter;
			found[0]	= true;
		}
		else if(!found[1] && (tempvec - tri.pointB).getLengthSQ() < 0.0001f)
		{
			indices[1]	= counter;
			found[1]	= true;
		}
		else if(!found[2] && (tempvec - tri.pointC).getLengthSQ() < 0.0001f)
		{
			indices[2]	= counter;
			found[2]	= true;
		}
		else if(found[0] && found[1] && found[2])
			break;
	}
	assert(found[0] && found[1] && found[2]);
	//vektor vom koordursprung hin zum punkt
	vector3df AP = point - tri.pointA;
	//koordinatenachsen des aufgespannten systems
	vector3df AB = tri.pointB - tri.pointA;
	vector3df AC = tri.pointC - tri.pointA;

	float lenAB = AB.getLength();
	float lenAC = AC.getLength();

	//winkel zwischen den achsen
	float winkel = AB.dotProduct(AC) / (lenAB * lenAC);

	//erst projezieren wir den vektor auf unsere achsen welche wir normalisieren
	float proj_x = AP.dotProduct(AB) / lenAB;
	float proj_y = AP.dotProduct(AC) / lenAC;

	//holen uns die abstände der projezierten punkte vom zielpunkt
	float dist_x = sqrtf(AP.dotProduct(AP) - proj_x * proj_x);
	float dist_y = sqrtf(AP.dotProduct(AP) - proj_y * proj_y);

	//und berechnen darüber die stücke die wir wissen wollen, da die hypotenuse = unsere gesuchten strecke ist
	float final_x = dist_y / sinf(acosf(winkel));
	float final_y = dist_x / sinf(acosf(winkel));

	//nun noch auf relative koords umrechen
	final_x /= lenAB;
	final_y /= lenAC;

	vector2df n1		= Textcoord[indices[1]] - Textcoord[indices[0]];
	vector2df n2		= Textcoord[indices[2]] - Textcoord[indices[0]];
	vector2df TextPos	= final_x * n1 + final_y * n2 + Textcoord[indices[0]];

	s32 x = static_cast<s32>(TextPos.X * colormap->getDimension().Width);
	s32 y = static_cast<s32>(TextPos.Y * colormap->getDimension().Height);

	return colormap->getPixel(x,y).color | 0xFF000000;
}

Code: Select all

	unsigned int SelectedColor = 0xFF000000;
	{
		ISceneCollisionManager* Collm = Main->GetSmgr()->getSceneCollisionManager();
		line3d<f32> line = Collm->getRayFromScreenCoordinates(Main->GetCursorPos(), Kamera);

		Model->updateAbsolutePosition();

		const ISceneNode*	node;
		vector3df			outpoint;
		triangle3df			outtri;
		if(Collm->getCollisionPoint(line, Model->getTriangleSelector(), outpoint, outtri, node))
			SelectedColor = GetSelectedColor(Model->getAbsoluteTransformation(), outtri, outpoint, ProvincenKey, Vertices, Textcoord);
	}
monkeycracks
Posts: 1029
Joined: Thu Apr 06, 2006 12:45 am
Location: Tennesee, USA
Contact:

Post by monkeycracks »

Well, since I'm getting a breakpoint at assert(found[0] && etc), I'm going to assume I didn't get the vertices and tcoords correctly...

Code: Select all

S3DVertex2TCoords* coords = (S3DVertex2TCoords*)mMapTerrain->getMesh()->getMeshBuffer(0)->getVertices();

					array<vector3df> vertices;
					for(u32 i = 0; i < mMapTerrain->getMesh()->getMeshBuffer(0)->getVertexCount(); ++i)
						vertices.push_back(coords[i].Pos);

					array<vector2df> tcoords;
					for(u32 j = 0; j < vertices.size(); ++j)
						tcoords.push_back(mMapTerrain->getMesh()->getMeshBuffer(0)->getTCoords(j));

					unsigned int SelectedColor = GetSelectedColor(mMapTerrain->getAbsoluteTransformation(), hitTriangle, intersection, mColormapImg, vertices, tcoords); 
This mesh and texture stuff really gets me :(
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

To be honest i dont know whats going wrong there. Maybe its a bug in my code :( . I extract the coords with:

Code: Select all

	IMesh* mesh				= static_cast<IMeshSceneNode*>(Model)->getMesh();
	IMeshBuffer* buffer		= mesh->getMeshBuffer(0);


	ITriangleSelector* s = Main->GetSmgr()->createTriangleSelector(mesh, Model);
	Model->setTriangleSelector(s);
	Model->setPosition(vector3df());
	s->drop();

	Vertices.reallocate(buffer->getVertexCount());
	Textcoord.reallocate(buffer->getVertexCount());

	switch(buffer->getVertexType())
	{
	case EVT_STANDARD:
		{
			S3DVertex* v = (S3DVertex*)buffer->getVertices();
			for(u32 counter = 0; counter < buffer->getVertexCount(); counter++)
			{
				Vertices.push_back(v[counter].Pos);
				Textcoord.push_back(v[counter].TCoords);
			}
		}break;
	case EVT_2TCOORDS:
		{
			S3DVertex2TCoords* v = (S3DVertex2TCoords*)buffer->getVertices();
			for(u32 counter = 0; counter < buffer->getVertexCount(); counter++)
			{
				Vertices.push_back(v[counter].Pos);
				Textcoord.push_back(v[counter].TCoords);
			}
		}break;
	case EVT_TANGENTS:
		{
			S3DVertexTangents* v = (S3DVertexTangents*)buffer->getVertices();
			for(u32 counter = 0; counter < buffer->getVertexCount(); counter++)
			{
				Vertices.push_back(v[counter].Pos);
				Textcoord.push_back(v[counter].TCoords);
			}
		}break;
	}
monkeycracks
Posts: 1029
Joined: Thu Apr 06, 2006 12:45 am
Location: Tennesee, USA
Contact:

Post by monkeycracks »

I'm still getting the assert at found[0] [1] [2]. Maybe it's because I'm dealing with an ITerrainSceneNode?

Code: Select all

vector3df intersection;
			triangle3df hitTriangle;
			line3df ray = mCollisionManager->getRayFromScreenCoordinates(vector2di(event.MouseInput.X, event.MouseInput.Y), mCamera);
			mMapTerrain->updateAbsolutePosition();

			IMeshBuffer* buffer = mMapTerrain->getMesh()->getMeshBuffer(0);
			array<vector3df> vertices;
			array<vector2df> tcoords;

			vertices.reallocate(buffer->getVertexCount());
			tcoords.reallocate(buffer->getVertexCount()); 

			switch(buffer->getVertexType())
			{
			case EVT_STANDARD:
				{
					S3DVertex* v = (S3DVertex*)buffer->getVertices();
					for(u32 counter = 0; counter < buffer->getVertexCount(); counter++)
					{
						vertices.push_back(v[counter].Pos);
						tcoords.push_back(v[counter].TCoords);
					}
				}break;
			case EVT_2TCOORDS:
				{
					S3DVertex2TCoords* v = (S3DVertex2TCoords*)buffer->getVertices();
					for(u32 counter = 0; counter < buffer->getVertexCount(); counter++)
					{
						vertices.push_back(v[counter].Pos);
						tcoords.push_back(v[counter].TCoords);
					}
				}break;
			case EVT_TANGENTS:
				{
					S3DVertexTangents* v = (S3DVertexTangents*)buffer->getVertices();
					for(u32 counter = 0; counter < buffer->getVertexCount(); counter++)
					{
						vertices.push_back(v[counter].Pos);
						tcoords.push_back(v[counter].TCoords);
					}
				}break;
			}

			const ISceneNode* node;
			if(mCollisionManager->getCollisionPoint(ray, mTerrainTriSelector, intersection, hitTriangle, node))
			{
				unsigned int SelectedColor = GetSelectedColor(mMapTerrain->getAbsoluteTransformation(), hitTriangle, intersection, mColormapImg, vertices, tcoords); 
Edit: I think the solution lies within IAnimatedMesh* createTerrainMesh(); I've created one of these, but I'm having results that are hardly decent so far.
Post Reply