I tried to compute normals on a small object (a pyramid).
The results are strange, when i turn on "normals display" in debug mode.
I got this:
Hmmm strange normals.. i wrote some code to display normals my own way. Here it is:
the small lines attached to the edges of the pyramid are my normals.
Let's face it. I'm dazed and confused (i should have set my color background as deep purple).
Here is the code :
Code: Select all
/* pyramid with computed normals */
#include <irrlicht.h>
irr::IrrlichtDevice *device=0;
irr::video::IVideoDriver *driver=0;
irr::scene::ISceneManager *scenemgr=0;
irr::scene::ICameraSceneNode *cam=0;
irr::scene::SMesh *mesh_pyramid=0;
irr::scene::ISceneNode *mesh_scenenode=0;
irr::scene::SMesh * create_mesh(float scale_x,float scale_y,float scale_z)
{
irr::scene::SMesh *mesh; //le mesh
irr::scene::SMeshBuffer *mesh_buffer; //son buffer
mesh = new irr::scene::SMesh();
mesh_buffer = new irr::scene::SMeshBuffer();
irr::f32 cubeSize = 5.f;
irr::video::SColor colour(255,255,0,0);
#define NB_INDICES 18
irr::u16 indices[NB_INDICES] = { 0,1,3, 1,2,3, 3,4,0, 2,4,3, 1,4,2, 0,4,1 };
mesh_buffer->Indices.set_used(NB_INDICES);
for (irr::s32 i=0; i<NB_INDICES; ++i)
mesh_buffer->Indices[i] = indices[i];
//S3DVertex: pos(x,y,z) normal(x,y,z) color(c) texture_coords(u,v)
//only vertices position are defined, normals will be computed later...
mesh_buffer->Vertices.set_used(5);
mesh_buffer->Vertices[0] = irr::video::S3DVertex(-.5,0,-.5, 0,0,0, colour, 0, 1);
mesh_buffer->Vertices[1] = irr::video::S3DVertex( .5,0,-.5, 0,0,0, colour, 1, 1);
mesh_buffer->Vertices[2] = irr::video::S3DVertex( .5,0, .5, 0,0,0, colour, 1, 0);
mesh_buffer->Vertices[3] = irr::video::S3DVertex(-.5,0, .5, 0,0,0, colour, 0, 0);
mesh_buffer->Vertices[4] = irr::video::S3DVertex( 0,1, 0, 0,0,0, colour, 0, 0); //normal OK
//now that we've defined vertices, we get their buffer, and recompute their normals.
// vertice[4] is the top of the pyramid, vertices 1,2,3,4 are the base of the prism.
irr::video::S3DVertex *vertice = (irr::video::S3DVertex *)mesh_buffer->getVertices();
irr::core::vector3df normal;
normal = (vertice[4].Pos - vertice[1].Pos).crossProduct ((vertice[0].Pos-vertice[4].Pos)) ;
normal.normalize();
vertice[0].Normal = normal;
normal = (vertice[4].Pos - vertice[2].Pos).crossProduct ((vertice[1].Pos-vertice[4].Pos)) ;
normal.normalize();
vertice[1].Normal = normal;
normal = (vertice[4].Pos - vertice[3].Pos).crossProduct ((vertice[2].Pos-vertice[4].Pos)) ;
normal.normalize();
vertice[2].Normal = normal;
normal = (vertice[4].Pos - vertice[0].Pos).crossProduct ((vertice[3].Pos-vertice[4].Pos)) ;
normal.normalize();
vertice[3].Normal = normal;
//normals computing done.
//the mesh buffer is now ready (bounding box is computed just after assignation)
mesh->addMeshBuffer(mesh_buffer);
//recalculate bounding box
for (int j=0; j<mesh->MeshBuffers.size(); ++j)
((irr::scene::SMeshBuffer*)mesh->MeshBuffers[j])->recalculateBoundingBox();
mesh->recalculateBoundingBox();
return mesh;
}
//the draw of the normals in Irrlicht seems weird to me.
//i want to display normals my own way.
static void draw_my_normals()
{
irr::scene::SMeshBuffer *mesh_buffer; //pyramid mesh buffer
//when you do getMeshBuffer, you have to pass the *index* of mesh buffer.
//usually, it's "0"
mesh_buffer = (irr::scene::SMeshBuffer *) mesh_pyramid->getMeshBuffer(0);
irr::video::S3DVertex *vertice = (irr::video::S3DVertex *)mesh_buffer->getVertices();
for (int i=0; i<5; i++) {
driver->draw3DLine(vertice[i].Pos, vertice[i].Pos + vertice[i].Normal);
}
}
static void start_irr()
{
device = irr::createDevice(irr::video::EDT_OPENGL, irr::core::dimension2d<irr::s32>(800,600), 32 );
if (!device) { printf("impossible de créer le device!\n"); exit(0); }
device->setWindowCaption(L"Pyramid");
driver = device->getVideoDriver();
if (!driver) printf("Erreur driver\n");
scenemgr = device->getSceneManager();
mesh_pyramid = create_mesh(1.0f,1.0f,2.0f);
mesh_scenenode = scenemgr->addMeshSceneNode(mesh_pyramid);
mesh_scenenode->setPosition(irr::core::vector3df(0,0,1) );
mesh_scenenode->setDebugDataVisible(irr::scene::EDS_FULL);
}
static void stop_irr()
{
device->drop();
}
static void main_loop()
{
irr::scene::ILightSceneNode *light=0;
cam = scenemgr->addCameraSceneNodeFPS (0, 10.0f, .01f, 0, 0, 0, false);
device->getCursorControl ()-> setVisible (false);
scenemgr->addLightSceneNode(0,irr::core::vector3df(0,0,-10));
while(device->run() && driver)
{
driver->beginScene(true, true, irr::video::SColor(255,0,0,255));
scenemgr->drawAll();
draw_my_normals(); //for debug purposes: draw the normals of the pyramid
driver->endScene();
device->sleep(20);
}
}
int main(void)
{
start_irr();
main_loop();
stop_irr();
return 0;
}
Thank you, and good night.