Collision Tests on TileGrid

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
PumpkinPieman
Posts: 13
Joined: Fri Apr 20, 2007 4:35 pm

Collision Tests on TileGrid

Post by PumpkinPieman »

Hello there,

I've been trying to do collision tests on a tiles attached to the SceneManager. I just migrated the tiles from square tiles to isometric tiles. However the bounding boxes for these tiles still resemble the bounding boxes for square ones. I'm not exactly sure about this but even with TriangleSelectors on those individual TileNodes, I'm still unable tp pick them properly. The picking of the tiles is closer to picking the bounding boxes of the tiles then the triangles that make them up.

I'm thinking that getSceneNodeFromScreenCoordinatesBB tests the bounding boxes, but I'm not exactly sure. If this is the case is there anything I can do to pick the SceneNode from Coordinates and have them tested with the TriangleSelector's?


Image

(TileNode.h)

Code: Select all

#pragma once

#include "precompiled.h"

class TileNode : public scene::ISceneNode
{
private:
	static scene::SMeshBuffer Buffer;
	static scene::SMesh Mesh;

	video::SMaterial Material;

public:
	TileNode(float size, scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id);
	~TileNode(void);

	// Rendering Functions
	void OnRegisterSceneNode();
	void render();

	// SceneNode Functions
	const core::aabbox3d<f32>& getBoundingBox() const;
	u32 getMaterialCount() const;
	video::SMaterial& getMaterial(u32 num);

	// TileNode Functions
	void setTileSize(float size);

};
(TileNode.cpp)

Code: Select all

#include "precompiled.h"
#include "TileNode.h"

scene::SMeshBuffer TileNode::Buffer;
scene::SMesh TileNode::Mesh;

TileNode::TileNode(float size, scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
: scene::ISceneNode(parent, mgr, id)
{ 
	// setup buffer
	if(Buffer.Vertices.empty())
		setTileSize(size);
	
	// setup material
	Material.Wireframe = false;
	Material.Lighting = false;
	Material.BackfaceCulling = false;

	// setup triangle selector
	scene::ITriangleSelector* triSel = SceneManager->createTriangleSelector(&Mesh, this);
	this->setTriangleSelector(triSel);
	triSel->drop();
}

TileNode::~TileNode(void)
{
}

void TileNode::OnRegisterSceneNode()
{
	if (IsVisible)
		SceneManager->registerNodeForRendering(this);
}

void TileNode::render()
{
	video::IVideoDriver* driver = SceneManager->getVideoDriver();

	driver->setMaterial(Material);
	driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
	driver->drawIndexedTriangleList(Buffer.Vertices.const_pointer(), Buffer.Vertices.size(), Buffer.Indices.const_pointer(), Buffer.Indices.size() / 3);
}

const core::aabbox3d<f32>& TileNode::getBoundingBox() const
{
	return Buffer.getBoundingBox();
}

u32 TileNode::getMaterialCount() const
{
	return 1;
}

video::SMaterial& TileNode::getMaterial(u32 num)
{
	return Material;
} 

void TileNode::setTileSize(float size)
{
	float half = size / 2;

	Buffer.Vertices.clear();
	Buffer.Indices.clear();

	Buffer.Vertices.push_back(video::S3DVertex(0,half,0,	0,0,0,0xFFFFFFFF,	0,.5));
	Buffer.Vertices.push_back(video::S3DVertex(half,0,0,	0,0,0,0xFFFFFFFF,	.5,0));
	Buffer.Vertices.push_back(video::S3DVertex(half,size,0,	0,0,0,0xFFFFFFFF,	.5,1));
	Buffer.Vertices.push_back(video::S3DVertex(size,half,0,	0,0,0,0xFFFFFFFF,	1,.5));

	Buffer.Indices.push_back(0);
	Buffer.Indices.push_back(1);
	Buffer.Indices.push_back(2);
	Buffer.Indices.push_back(2);
	Buffer.Indices.push_back(1);
	Buffer.Indices.push_back(3);

	Buffer.recalculateBoundingBox();

	Mesh.MeshBuffers.clear();
	Mesh.addMeshBuffer(&Buffer);
	Mesh.recalculateBoundingBox();
}
(RenderSystem.cpp)

Code: Select all

for (y = 0; y < mapFile.GetHeight(); y++) {

		fy = (y-10) * halfTileSize;

		for (x = 0; x < mapFile.GetWidth(); x++) {

			id = (y+1) * 100 + x;

			if(y % 2) fx = (x-10) * tileSize;
			else fx = (x-10) * tileSize + halfTileSize;


			if (mapFile.GetMap(x, y)) {
				cube = new TileNode(tileSize, GetScene()->getRootSceneNode(), GetScene(), id);
				cube->setPosition(vector3df(fx, fy, 0));
				cube->setMaterialTexture(0, m_driver->getTexture("Textures/tile32.png"));
			} else {
				cube = new TileNode(tileSize, GetScene()->getRootSceneNode(), GetScene(), id);
				cube->setPosition(vector3df(fx, fy, 0));
				cube->setMaterialTexture(0, m_driver->getTexture("Textures/tile32blue.png"));
			}

			cube->setMaterialType(EMT_TRANSPARENT_ALPHA_CHANNEL);
			cube->setMaterialFlag(EMF_ANISOTROPIC_FILTER, true);
			cube->setMaterialFlag(EMF_TRILINEAR_FILTER, true);
			cube->setMaterialFlag(EMF_BILINEAR_FILTER, true);
			cube->setMaterialFlag(EMF_LIGHTING, false);
		}
	}
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Re: Collision Tests on TileGrid

Post by vitek »

PumpkinPieman wrote:Hello there,

I've been trying to do collision tests on a tiles attached to the SceneManager. I just migrated the tiles from square tiles to isometric tiles.
Wha? There is no such thing as 'isometric tiles'. The tiles themselves are still square, they're just rotated or you have an isometric projection.
PumpkinPieman wrote:However the bounding boxes for these tiles still resemble the bounding boxes for square ones.
I'm not exactly sure what you are trying to say here. As I mentioned above, the bounding box for a tile will be the same regardless of what perspective you use to look at the tile or how the tile is rotated. If you are displaying the bounding box of the tile and it is not oriented correctly, that is likely to be a problem with the code you have for rendering the box.
PumpkinPieman wrote:I'm not exactly sure about this but even with TriangleSelectors on those individual TileNodes, I'm still unable tp pick them properly. The picking of the tiles is closer to picking the bounding boxes of the tiles then the triangles that make them up.
If you setup your camera for isometric projection, did you set the flag to indicate that the camera is using an orthogonal projection? [i.e. camera->setIsOrthogonal(true)]?
PumpkinPieman wrote:I'm thinking that getSceneNodeFromScreenCoordinatesBB tests the bounding boxes, but I'm not exactly sure. If this is the case is there anything I can do to pick the SceneNode from Coordinates and have them tested with the TriangleSelector's?
Yes, it does test the bounding box of the each against a ray. The BB at the end of the function name stands for bounding box. If you don't want to test using bounding boxes, you have to write your own function to iterate over the nodes and use getCollisionPoint(). I don't know why you'd bother to do this as testing the bounding box should give you the same result with less code.

Travis
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

As an aside, I don't see why you've written your own scene node. You could just use the existing mesh scene node. All you'd have to do is pass a mesh object to each of the scene nodes and you'd be done.

Code: Select all

   SMeshBuffer* mb = new SMeshBuffer;

   mb->Vertices.push_back(video::S3DVertex(0, .5f, 0, 0, 0, 0, 0xFFFFFFFF, 0, .5f)); 
   mb->Vertices.push_back(video::S3DVertex(0.5f, 0, 0, 0, 0, 0, 0xFFFFFFFF, .5f, 0)); 
   mb->Vertices.push_back(video::S3DVertex(.5f, .5f, 0, 0, 0, 0, 0xFFFFFFFF, .5f, 1)); 
   mb->Vertices.push_back(video::S3DVertex(1.f, .5f, 0,   0, 0, 0, 0xFFFFFFFF, 1, .5)); 

   mb->Indices.push_back(0); 
   mb->Indices.push_back(1); 
   mb->Indices.push_back(2); 
   mb->Indices.push_back(2); 
   mb->Indices.push_back(1); 
   mb->Indices.push_back(3); 

   mb->recalculateBoundingBox(); 

   scene::SMesh* mesh = new scene::SMesh;
   mesh->addMeshBuffer(mb); 
   mb->drop();

   mesh->recalculateBoundingBox();

   // create your tiles
   video::ITexture* textures [2];
   textures [0] = driver->getTexture ("Texture/tile32blue.png");
   textures [1] = driver->getTexture ("Texture/tile32.png");

   for (y = 0; ...)
   {
      for (x = 0; ...)
      {
         scene::ISceneNode* tile = smgr->addMeshSceneNode(mesh, 0, id, pos);
         tile->setMaterialType(EMT_TRANSPARENT_ALPHA_CHANNEL); 
         tile->setMaterialFlag(EMF_ANISOTROPIC_FILTER, true); 
         tile->setMaterialFlag(EMF_TRILINEAR_FILTER, true); 
         tile->setMaterialFlag(EMF_BILINEAR_FILTER, true); 
         tile->setMaterialFlag(EMF_LIGHTING, false); 

         tile->setTexture (0, textures [mapFile.GetMap(x,y)]);
      }
   }
And since you don't really need the triangle selector, it might be a good idea to just not create them.

Travis
Post Reply