ISceneNode/drawIndexedTriangleList trouble

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
KG
Posts: 35
Joined: Wed Jun 07, 2006 12:00 am

ISceneNode/drawIndexedTriangleList trouble

Post by KG »

I am working on a custom scene node that consists of an X/Z plane of polygons. My plan is to make it similar to the built in hill plane mesh, but with functions to get/set the height and colour of the vertices on the fly. I know that other people have made similar things already, but I thought this was a good chance to learn more about the engine.

What I have here seems to create the proper vertices and triangles, according to the console output, but it doesn't actually render. I've been staring at it and these forums for about an hour and I can't figure it out.

Is it because I did not give the vertices texture coordinates, even though I don't actually have a texture assigned to it? And if so, what would be a good way to assign proper values to them?

Or maybe it's something else entirely?

Thanks in advance!

Terrain.h

Code: Select all

class Terrain : public irr::scene::ISceneNode
{
public:
	Terrain(irr::scene::ISceneManager* mgr, int id, irr::scene::ISceneNode* parent);
	~Terrain();

	void recalculateNormals();
	void recalculateBoundingBox();

	virtual void OnRegisterSceneNode();
	virtual void render();

	virtual const irr::core::aabbox3d<float>& getBoundingBox() const;
	virtual unsigned int getMaterialCount() const;
	virtual irr::video::SMaterial& getMaterial(unsigned int i);

private:
	irr::core::array<irr::video::S3DVertex> vertex;
	irr::core::array<unsigned short> index;
	irr::core::aabbox3d<float> Box;
	irr::video::SMaterial Material;
};

terrain.cpp

Code: Select all

#include <irrlicht.h>

#include "terrain.h"

Terrain::Terrain(irr::scene::ISceneManager* mgr, int id, irr::scene::ISceneNode* parent) : irr::scene::ISceneNode(parent, mgr, id)
{
	float tileSize = 100.0;
	unsigned int tileX = 10;
	unsigned int tileZ = 10;

	unsigned int x;
	unsigned int z;

	for (x = 0; x <= tileX; x++)
	{
		for (z = 0; z <= tileZ; z++)
		{
			irr::video::S3DVertex point = irr::video::S3DVertex
				(
					x * tileSize,
					0,
					z * tileSize,
					0,
					0,
					0,
					irr::video::SColor(255, 255, 255, 255),
					0,
					0
				);

			vertex.push_back(point);

			printf("Added point: %f x %f\n", x * tileSize, z * tileSize);
		}
	}

	for (x = 0; x < tileX; x++)
	{
		for (z = 0; z < tileZ; z++)
		{
			unsigned int upper = z + x + (x * tileZ);
			unsigned int lower = z + (x + 1) + ((x + 1) * tileZ);

			index.push_back(upper);
			index.push_back(upper + 1);
			index.push_back(lower);

			printf("Added triangle: %i, %i, %i\n", upper, upper + 1, lower);

			index.push_back(lower);
			index.push_back(upper + 1);
			index.push_back(lower + 1);

			printf("Added triangle: %i, %i, %i\n", lower, upper + 1, lower + 1);
		}
	}

	recalculateNormals();
	recalculateBoundingBox();
}

Terrain::~Terrain()
{

}

void Terrain::recalculateNormals()
{
	for (int i = 0; i < index.size(); i += 3)
	{
		irr::core::plane3d<float> plane
			(
			vertex[index[i]].Pos,
			vertex[index[i + 1]].Pos,
			vertex[index[i + 2]].Pos
			);

		vertex[index[i]].Normal = plane.Normal;
		vertex[index[i + 1]].Normal = plane.Normal;
		vertex[index[i + 2]].Normal = plane.Normal;
	}
}

void Terrain::recalculateBoundingBox()
{
	for (int i = 0; i < vertex.size(); i++)
	{
		Box.addInternalPoint(vertex[i].Pos);
	}
}

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

	ISceneNode::OnRegisterSceneNode();
}

void Terrain::render()
{
	SceneManager->getVideoDriver()->setMaterial(Material);
	SceneManager->getVideoDriver()->setTransform(irr::video::ETS_WORLD, AbsoluteTransformation);
	SceneManager->getVideoDriver()->drawIndexedTriangleList(vertex.const_pointer(), vertex.size(), index.const_pointer(), index.size());
}

const irr::core::aabbox3d<float>& Terrain::getBoundingBox() const
{
	return Box;
}

unsigned int Terrain::getMaterialCount() const
{
	return 1;
}

irr::video::SMaterial& Terrain::getMaterial(unsigned int i)
{
	return Material;
}
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

Is it because I did not give the vertices texture coordinates, even though I don't actually have a texture assigned to it? And if so, what would be a good way to assign proper values to them?
Maybe the problem, I'm not sure if it matters though. 0,0 for the top left vertex and 1,1 for the bottom right one would make sense.

Code: Select all

       unsigned int upper = z + x + (x * tileZ);
       unsigned int lower = z + (x + 1) + ((x + 1) * tileZ); 
shouldn't that be-

Code: Select all

       unsigned int upper = z + (x*tileZ);
       unsigned int lower = z + ((x + 1) * tileZ); 
Also, make sure you're not looking at the surface from the wrong side, because it will only be visible from one side.
Finally, you need to divide your index count by 3, since you're dealing with triangles. You might want to build a mesh buffer instead and use drawMeshBuffer
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
KG
Posts: 35
Joined: Wed Jun 07, 2006 12:00 am

Post by KG »

Thanks for the advice. I'm now using a CMeshBuffer, which simplifies things a bit and cuts out some of the room for error. It doesn't look like the problem was with passing a bad index count to drawIndexedTriangleList, though. It's also not being drawn upside-down, I just took a peek with an FPS camera.

I plugged in your formula for upper and lower, and according to the numbers that the console displays, it wouldn't quite work. With 10 tiles, there should be 11 vertices, and those numbers advance to the next row after 10 vertices. The original formulae match up with diagrams that I drew on paper, though I'm sure there's a nicer way of doing it. Math isn't really one of my strong points.

I do think that it's caused by a lack of proper texture coordinates, because every other example that uses drawIndexedTriangleList sets proper coordinates for each vertex. I'm having trouble adjusting the vertex adding loop to properly set the coordinates, so I'm going to have to figure that out somehow.

Thanks again for the help!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Meshes will also draw without texture coords, the coords are simply initialised to (0,0) for each vertex. Using a wrong tri count should crash your application (at best), or it simply fills the GPU with random data - that might cause almost anything.
Also, your plane is not properly built, the wrap at the border is not correct. Check your last tile on the right, it is connected to the left border, causing a flipped overdraw which could make the plane become hidden behind a backface.
KG
Posts: 35
Joined: Wed Jun 07, 2006 12:00 am

Post by KG »

Thanks for the help, hybrid and bitplane. I went over my math again and saw the mistake I made. After I fixed it it all checked out but wouldn't draw. After I went over the custome scene node tutorial again, I realized that I gave my node a parent of 0 instead of the root scene node, so it wasn't even being added to the scene. After I fixed that it started drawing.
Post Reply