in this post I want to give a short summary on generating an icosahedron in panda3d. I had a demand for that in another post. So here we go:
As introduction to the types of my variables a short look in the header would be useful:
/* the vertices and its properties such as color- and normal-vector */ PT(GeomVertexData) vdata; GeomVertexWriter vertex, normal, color; PT(Geom) planetGeometryData; PT(GeomNode) planetGeometryNode; PT(GeomTriangles) vertexConnectionType;
In the C+±file we will work on this data. At first we need to set the format of our GeomVertexData object: We define what each cols data will look like (get_v3n3c4()). At the end we make the cols writable and define how the vertices shall be connected (Triangles, TriangleStrip, Points, Quads, …)
/* create space for base_vertices, normals and colors */ this->vdata = new GeomVertexData( "vdata", GeomVertexFormat::get_v3n3c4(), Geom::UH_static); /* enable direct input to different vdata-cols */ this->vertex = GeomVertexWriter(vdata, "vertex"); this->normal = GeomVertexWriter(vdata, "normal"); this->color = GeomVertexWriter(vdata, "color"); /* prepare drawing in triangles */ this->vertexConnectionType = new GeomTriangles(Geom::UH_static);
Then I start writing my vertices to the vdata-table, in usual this is done by extracting previously generated vertices from a list in a for-loop.
/* write all three vertices, colors and the normal to vdata */ this->vertexConnectionType->add_vertex(this->vertex.get_write_row()); this->vertex.add_data3f(v1); this->normal.add_data3f(n); this->color.add_data4f(c1);
When you have finished the writing then close the primitive and deal with the following steps of assignment between GeomVertexData, Geom, GeomNode and NodePath:
/* finish writing of vertices by closing primitive */ this->vertexConnectionType->close_primitive(); this->planetGeometryData = new Geom(vdata); this->planetGeometryData->add_primitive(this->vertexConnectionType); this->planetGeometryNode = new GeomNode("planetGeometryNode"); this->planetGeometryNode->add_geom(this->planetGeometryData); DPandaScene* pScene = &DPandaScene::getInstance(); this->planetNP = pScene->getScenegraph().attach_new_node(this->planetGeometryNode);
Thats how I generate a mesh on my own. To become more concrete, we can generate a sphere out of an icosahedron. Therefore it is very usefull to look at this picture from wikipedia:
These are your initial points. Its coordinates are always a mixture of (0, +/-A, +/-B), where A and B are the edges of a right angle triangle, in which the hypotenuse is the vector from the origin to your point, that has a length of one.
To be able to draw the isocahedron you have to connect these vertices to triangles, for example by creating a list of 3-tuples of indices, containing the cornerpoints of the triangles.
To get a more spherelike icosahedron you have to subdivide your triangles: Create four new triangles out of one by creating three new vertices as midpoints of the three edges. Don’t forget to normalize the vertices so that they get the distance of 1 to the origin. Otherwise you won’t have a smooth sphere in the end.
I hope that short sketch may help some of you or at least will save you some time of googling around.