Cone mesh creator

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Cone mesh creator

Post by itzjac »

Hi! I think the addArrowMesh(...) is a good primitive for some purpouse, but I needed the Cone primitive so I rebuild irrlicht and I modify the CSceneManager and CGeometryCreator here it the implementation methods(I omitted the include files):

CSceneManager.cpp

Code: Select all




//! Adds an arrow mesh to the mesh pool.

IAnimatedMesh* CSceneManager::addArrowMesh(const c8* name,

		video::SColor vtxColor0, video::SColor vtxColor1,

		u32 tesselationCylinder, u32 tesselationCone, f32 height,

		f32 cylinderHeight, f32 width0,f32 width1)

{

	if (!name)

		return 0;



	if (MeshCache->isMeshLoaded(name))

		return MeshCache->getMeshByFilename(name);



	IMesh* mesh = CGeometryCreator::createArrowMesh( tesselationCylinder,

			tesselationCone, height, cylinderHeight, width0,width1,

			vtxColor0, vtxColor1);

	if (!mesh)

		return 0;



	SAnimatedMesh* animatedMesh = new SAnimatedMesh();

	if (!animatedMesh)

	{

		mesh->drop();

		return 0;

	}



	animatedMesh->addMesh(mesh);

	mesh->drop();

	animatedMesh->recalculateBoundingBox();



	MeshCache->addMesh(name, animatedMesh);

	animatedMesh->drop();



	return animatedMesh;

}



CGeometryCreator

Code: Select all




/*

	a cone

	point up on (0,1.f, 0.f )

*/

IMesh* CGeometryCreator::createConeMesh(const u32 tesselationCone,

						const f32 offset,

						const f32 width,

						const video::SColor vtxColor)

{

	SMeshBuffer* buffer;

	video::S3DVertex v;

	u32 i;



	v.Color = vtxColor;



	// cone

	buffer = new SMeshBuffer();



	f32 angleStep = (core::PI * 2.f ) / tesselationCone;



	v.Color = vtxColor;

	for ( i = 0; i != tesselationCone; ++i )

	{

		f32 angle = angleStep * f32(i);



		v.Color = vtxColor;

		v.Pos.X = width * cosf ( angle );

		v.Pos.Y = offset;

		v.Pos.Z = width * sinf ( angle );

		v.Normal = v.Pos;

		v.Normal.normalize ();



		buffer->Vertices.push_back ( v );



		angle += angleStep / 2.f;

		v.Color = vtxColor;

		v.Pos.X = width * cosf ( angle );

		v.Pos.Y = offset;

		v.Pos.Z = width * sinf ( angle );

		v.Normal = v.Pos;

		v.Normal.normalize ();



		buffer->Vertices.push_back ( v );

	}

	u32 nonWrappedSize = buffer->Vertices.size () - 1;



	// close top

	v.Pos.X = 0.f;

	v.Pos.Y = offset;

	v.Pos.Z = 0.f;

	v.Normal.X = 0.f;

	v.Normal.Y = 1.f;

	v.Normal.Z = 0.f;

	buffer->Vertices.push_back ( v );



	u32 index = buffer->Vertices.size () - 1;



	for ( i = 0; i != nonWrappedSize; i += 1 )

	{

		buffer->Indices.push_back ( i + 0 );

		buffer->Indices.push_back ( index );

		buffer->Indices.push_back ( i + 1 );

	}



	buffer->Indices.push_back ( i + 0 );

	buffer->Indices.push_back ( index );

	buffer->Indices.push_back ( 0 );



	// close down

	v.Pos.X = 0.f;

	v.Pos.Y = offset;

	v.Pos.Z = 0.f;

	v.Normal.X = 0.f;

	v.Normal.Y = -1.f;

	v.Normal.Z = 0.f;

	buffer->Vertices.push_back ( v );



	index = buffer->Vertices.size () - 1;



	for ( i = 0; i != nonWrappedSize; i += 1 )

	{

		buffer->Indices.push_back ( index );

		buffer->Indices.push_back ( i + 0 );

		buffer->Indices.push_back ( i + 1 );

	}



	buffer->Indices.push_back ( index );

	buffer->Indices.push_back ( i + 0 );

	buffer->Indices.push_back ( 0 );



	// add to mesh
	SMesh* mesh = new SMesh();

	buffer->recalculateBoundingBox();

	mesh->addMeshBuffer(buffer);

	buffer->drop();



	mesh->recalculateBoundingBox();

	return mesh;

}



Something is wrong with the math any help..? :(
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

Forget about extending CGeometry creating instead of recompiling I prefer to extend the ISceneNode class creating CConeNode, maybe all new geometry will be extended here before the new release here it is:

Code: Select all

#include <irrlicht.h>
#include <iostream>
#include <vector>

using namespace irr;
using namespace std;

class CConeNode : public scene::ISceneNode
{
	public:
		CConeNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
						u32 tesselationCone, f32 bottomHeight, f32 topHeight,
						f32 width, const video::SColor vtxColor);

		virtual ~CConeNode();
		virtual void OnRegisterSceneNode();

		virtual void render();

  		virtual const core::aabbox3d<f32>& getBoundingBox() const{return Box;}

		virtual s32 getMaterialCount(){return 1;}

		virtual video::SMaterial& getMaterial(s32 i){return Material;}


	private:
		core::aabbox3d<f32> Box;
		video::S3DVertex* Vertices;
		video::SMaterial Material;
		u16* indices;
		u32 coneDivisions;
};

Code: Select all



#include "CConeNode.h"

CConeNode::CConeNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
						u32 tesselationCone, f32 bottomHeight, f32 topHeight,
						f32 width, const video::SColor vtxColor)

 : scene::ISceneNode(parent, mgr, id)

{ 


	coneDivisions = tesselationCone;

	//default parameters
	Material.Wireframe = false;
	Material.Lighting = false;

	Vertices = new video::S3DVertex[tesselationCone+2];//number of the circle division plus the top and bottom vertex
	indices = new u16[3*(tesselationCone+2)];//triangle faces
	f32 x, y, z;
	s32 xNormal, yNormal, zNormal;

	f32 angleStep = (core::PI * 2.f ) / tesselationCone;

	u32 i= 0, j = 0	;


	//base
	for(i; i < tesselationCone; i++)
	{
		f32 angle = angleStep * f32(i);
		x = width * cosf ( angle );

		y = bottomHeight;

		z = width * sinf ( angle );
		
		xNormal = (x<0)?-1:1;
		yNormal = 1;
		zNormal = (z<0)?-1:1;
		Vertices[i] = video::S3DVertex(x,y,z,// coord
										xNormal, yNormal, zNormal,//normal
										vtxColor,//color
										0,0//texture (we won't use it)
													);
		Vertices[i].Normal = Vertices[i].Pos;
		Vertices[i].Normal.normalize();
	}


	u32 nonWrappedSize = tesselationCone - 1;//rear indexed zero number of circle division


	// top

	x = 0.f;

	y = topHeight;

	z = 0.f;

	Vertices[i] = video::S3DVertex(x,y,z,// coord
									1,0,-1,//normal
									vtxColor,//color
									0,0//texture (we won't use it)
									);
	Vertices[i].Normal = Vertices[i].Pos;
	Vertices[i].Normal.normalize();



	u32 index = tesselationCone;//indexed zero number circle division plus top



	for (j= 0, i = 0; i != nonWrappedSize; i += 1, j += 3 )

	{
		

		indices[j] = i;

		indices[j+1] = index;

		indices[j + 2] = i+ 1;

	}

	//closing the geometry
	indices[j] = i;

	indices[j+1] = index;

	indices[j + 2] = 0;
	j += 3;

	// close bottom
	x = 0.f;

	y = bottomHeight;

	z = 0.f;



	Vertices[tesselationCone+1] = video::S3DVertex(x,y,z,// coord
									0,1,0,//normal
									vtxColor,//color
									0,1//texture
									);



	index = tesselationCone+1;



	for ( i = 0; j < 3*(tesselationCone+2); i += 1, j+= 3)

	{

		indices[j] = index;

		indices[j+1] = i;

		indices[j + 2] = i+ 1;

	}



	 /* Box.reset(Vertices[0].Pos);
 		for (s32 i=1; i<4; ++i)
 			Box.addInternalPoint(Vertices[i].Pos);*/
}


CConeNode::~CConeNode()
{
	delete [] indices;
	delete [] Vertices;
}


void CConeNode::OnRegisterSceneNode()
{
	if (IsVisible)

			SceneManager->registerNodeForRendering(this);



	ISceneNode::OnRegisterSceneNode();
}


void CConeNode::render()
{

  	video::IVideoDriver* driver = SceneManager->getVideoDriver();

  	driver->setMaterial(Material);
  	driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  	driver->drawIndexedTriangleList(Vertices, coneDivisions, indices, 6);
}



I have problems with some normal maybe tomorrow will be finished, if someone want to help... there it is and if you want to call it form your main program

Code: Select all


	CConeNode *cone = new CConeNode(smgr->getRootSceneNode(),//parent
									smgr,//manager
									 -1,//id
									 16,//tesselation
									 0,//bottom
									 10,//top
									 10,//width
									 0xFFFF0000//color
									);

:wink:
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Cone and cylinder are already separated in CGeometryCreator in latest SVN trunk repository. I think I did not yet expose the methods in the interfaces, but it would be rather simple to do so. Then you can add the mesh to an IMeshSceneNode, which is much simpler than adding a new scene node type...
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

Upps... what a sorry I already finish the CConeNode, besides I don't think is a good idea to download from SVN because my project will be share using the 1.4.1 version.... I will have to wait to the next version, meantime anyone could check it, already works fine without the bouding box, can anybody show me which vertex include for a proper bounding box???

Code: Select all

CConeNode::CConeNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
                  u32 tesselationCone, f32 bottomHeight, f32 topHeight,
                  f32 width, const video::SColor vtxColor)

 : scene::ISceneNode(parent, mgr, id)

{


   coneDivisions = tesselationCone;

   //default parameters
   Material.Wireframe = false;
   Material.Lighting = false;

   Vertices = new video::S3DVertex[tesselationCone+2];//number of the circle division plus the top and bottom vertex
   indices = new u16[(6*tesselationCone)+3];//triangle faces 3 indices per face and we want double of tesselation faces
   f32 x, y, z;

   f32 angleStep = (core::PI * 2.f ) / tesselationCone;

   u32 i= 0, j = 0;


   //base
   for(; i < tesselationCone; i++)
   {
      f32 angle = angleStep * f32(i);
      x = width * cosf ( angle );

      y = bottomHeight;

      z = width * sinf ( angle );

      Vertices[i] = video::S3DVertex(x,y,z,// coord
                              0, 1, 0,//normal
                              vtxColor,//color
                              0,0//texture (we won't use it)
                                       );
      Vertices[i].Normal = Vertices[i].Pos;
      Vertices[i].Normal.normalize();
   }


   u32 nonWrappedSize = tesselationCone - 1;//rear indexed zero number of circle division


   // top

   x = 0.f;

   y = topHeight;

   z = 0.f;

   Vertices[tesselationCone] = video::S3DVertex(x,y,z,// coord
                           1,1,1,//normal
                           vtxColor,//color
                           0,0//texture (we won't use it)
                           );
   Vertices[tesselationCone].Normal = Vertices[i].Pos;
   Vertices[tesselationCone].Normal.normalize();



   u32 index = tesselationCone;//indexed zero number circle division plus top



   for (j= 0, i = 0; i != nonWrappedSize; i += 1, j += 3 )

   {


      indices[j] = i;

      indices[j+1] = index;

      indices[j + 2] = i+ 1;

   }

   //closing the geometry
   indices[j] = i;

   indices[j+1] = index;

   indices[j + 2] = 0;
   j += 3;

   // close bottom
   x = 0.f;

   y = bottomHeight;

   z = 0.f;



   Vertices[tesselationCone+1] = video::S3DVertex(x,y,z,// coord
                           0,1,0,//normal
                           vtxColor,//color
                           0,1//texture
                           );



   index = tesselationCone+1;



   for ( i = 0; j < 6*tesselationCone; i++, j+= 3)
   {

      indices[j] = index;

      indices[j+1] = i;

      indices[j + 2] = i+ 1;

   }
    indices[j] = index;

    indices[j+1] = tesselationCone-1;

    indices[j + 2] = 0;


  //missing the bounding box code
}
Image

and... is the repository on this page http://irrlicht.convextech.ca/? sometimes I can't access form my country. Thanks hybrid
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

Well... maybe this is another topic but it has to be explained after the cone discussion...

The purpose of having a simple geometric node is to create multiple graphic instances, in order to test AI algorithms, performance or whatever ... I have created some (50 to 500) cones with 32 tessellation an putting inside a

Code: Select all

vector<CConeNode*> coneList
then I show the triangle count with

Code: Select all

cout<<driver->getPrimitiveCountDrawn()<<endl;
And the frame rate for 32 000 polys (500 cones) is to poor, I want to improve the performance and I thought it is wrong to create a new object(with same geometry) for each element of the vector collection, maybe my question is too noobbie ... is it possible to create only one new object with the cone geometry and share the same geometry with other nodes? :roll:
Dark_Kilauea
Posts: 368
Joined: Tue Aug 21, 2007 1:43 am
Location: The Middle of Nowhere

Post by Dark_Kilauea »

In your scenenode change your Automatic Culling to something other than none.

(Because Automatic Culling is set to none, your cones will never be culled from the scene if they are out of sight)
rogerborg wrote:Every time someone learns to use a debugger, an angel gets their wings.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The basic idea of scene nodes and IMesh structs is that you only need one IMesh (geometry info) and can use it in arbitrary many scene nodes. However, this will only save memory, but won't improve render performance. The main problem for you setup is probably that you have many scene nodes. This requires lots of matrix calculations and other stuff which will easily become overkill. Another problem is that you're drawing lots of the same geometry, but it's always uploaded to the card for each mesh. With Irrlicht SVN/trunk you can use VBOs, which avoid this uploading.
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

I recompiled the trunk version exposing the cylinder method from CGeometryCreator successfully.

I used one mesh using the VBO from the trunk for adding many nodes to a vector list with addAnimatedMeshSceneNode(...) as well as calling the setHardwareMappingHint(scene::EHM_STATIC) for the mesh buffer of the cone. Everything runs OK but with poorly performance ... do I have to wait to some improvements for hardware buffers or I missed something else? :(
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The VBOs usually refuse buffers with less than 500 vertices, so it's possibly not a VBO at all. Or did you add hundreds of cones into one buffer? How many then?
itzjac
Posts: 57
Joined: Fri Nov 17, 2006 7:41 pm
Location: Mexico City

Post by itzjac »

No, I didn't add hundreds of cones into one buffer I just made like this:

Code: Select all


scene::IAnimatedMesh *mesh = smgr->addConeMesh("Cone1",
                1.0f, 1.0f, 16,
                0xFFFF0000,
                0xFFFF0000,
                0.0f);

    //scene::IAnimatedMesh *mesh  = smgr->getMesh("cono.obj");
    mesh->getMeshBuffer(0)->setHardwareMappingHint(scene::EHM_STATIC);

    for(int i = 0; i < SIZE; i++)
    {
        scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
        coneList.push_back(node);
    }

Then in the update cycle I work with every node changing thier behavior ... I don't know if it would be usefull the single buffer multiple meshes solution, some code for that will be apreciated ... I supose there most be a solution for meshes with very few polys ...
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You should definitely not use scene nodes for such few polys. It would be much better to create a copy of the meshbuffer and transform it manually, then add the vertices and indices to a combined meshbuffer (using e.g. buffer->append). Otherwise much overhead is introduced. bitplane also wrote a batching meshbuffer which can do this stuff with only a few methodcalls. Using VBOs you can also reduce the memory transfer much more efficient with larger buffers, because the small ones would always need a reenabling, which is also quite costly.
Post Reply