Exemple #1
0
cylinder::cylinder(int edgeSize): meshData(edgeSize*1000, edgeSize*1000)
{
     n_indices = 0;
     n_edges = edgeSize;
     n_levels = 0;
     cylinderHeightPos = 0;

    float revStep = 360/edgeSize;
    for(int i = 0; i < edgeSize; i++){

        float x, z;
        x = cos(PI*(i*revStep)/180);
        z = sin(PI*(i*revStep)/180);
        vertexList[i].Set(Vert(x, cylinderHeightPos, z));
    }
    for(int i = 0; i < edgeSize; i++){

        float x, z;
        x = cos(PI*(i*revStep)/180);
        z = sin(PI*(i*revStep)/180);
        vertexList[i+edgeSize].Set(Vert(x, cylinderHeightPos+1, z));
    }
    listSize += edgeSize*2;
    int i;
    for( i = 0; i < edgeSize-1; i++){
        connectEdge(i, i+1, getIndexAtLevel(1, i), getIndexAtLevel(1, i+1));
    }
   // i++;
    connectEdge(i, 0,  getIndexAtLevel(1, i), getIndexAtLevel(1, 0));
    n_levels += 1;
    cylinderHeightPos +=2;

}
Exemple #2
0
void CRichModel::CreateEdgesFromVertsAndFaces()
{
	//printf("vert %d face %d" , GetNumOfVerts() , GetNumOfFaces() );
	m_Edges.reserve(2 * (GetNumOfVerts() + GetNumOfFaces() - 2));
	map<pair<int, int>, int> pondOfUndeterminedEdges;
	int szFaces = GetNumOfFaces();
	for (int i = 0; i < szFaces; ++i)
	{		
		int threeIndices[3];
		for (int j = 0; j < 3; ++j)
		{
			int post = (j + 1) % 3;
			int pre = (j + 2) % 3;
			
			int leftVert = Face(i)[pre];
			int rightVert = Face(i)[j];

			map<pair<int, int>, int>::const_iterator it = pondOfUndeterminedEdges.find(make_pair(leftVert, rightVert));
			if (it != pondOfUndeterminedEdges.end())
			{
				int posInEdgeList = it->second;
				if (m_Edges[posInEdgeList].indexOfOppositeVert != -1)
				{
					printf( "Repeated edges!");
					continue;
				}
				threeIndices[j] = posInEdgeList;
				m_Edges[posInEdgeList].indexOfOppositeVert = Face(i)[post];
				m_Edges[posInEdgeList].indexOfFrontFace = i;				
			}
			else
			{
				CEdge edge;
				edge.indexOfLeftVert = leftVert;
				edge.indexOfRightVert = rightVert;
				edge.indexOfFrontFace = i;
				edge.indexOfOppositeVert = Face(i)[post];
				edge.indexOfReverseEdge = (int)m_Edges.size() + 1;
				edge.length = (Vert(leftVert) - Vert(rightVert)).Len();
				m_Edges.push_back(edge);
				pondOfUndeterminedEdges[make_pair(leftVert, rightVert)] = threeIndices[j] = (int)m_Edges.size() - 1;

				edge.indexOfLeftVert = rightVert;
				edge.indexOfRightVert = leftVert;
				edge.indexOfReverseEdge = (int)m_Edges.size() - 1;
				edge.indexOfOppositeVert = -1;
				m_Edges.push_back(edge);
				pondOfUndeterminedEdges[make_pair(rightVert, leftVert)] = (int)m_Edges.size() - 1;
			}
		}
		for (int j = 0; j < 3; ++j)
		{
			m_Edges[threeIndices[j]].indexOfLeftEdge = Edge(threeIndices[(j + 2) % 3]).indexOfReverseEdge;
			m_Edges[threeIndices[j]].indexOfRightEdge = Edge(threeIndices[(j + 1) % 3]).indexOfReverseEdge;
		}
	}
	m_Edges.swap(vector<CEdge>(m_Edges));
}
Exemple #3
0
void CBaseModel::DrawWireframe() const
{
	glPushMatrix();
	glBegin(GL_LINES);
	for(int i = 0; i < (int) GetNumOfFaces();++i){
		for(int j = 0; j < 3; ++j){
			Vert(Face(i)[j]).Show();
			Vert(Face(i)[(j+1)%3]).Show();
		}

	}		
	glEnd();
	glPopMatrix();
}
Exemple #4
0
void Segmenter:: SortVert()
{
    for(unit_t i=X.lower;i<=X.upper;++i)
    {
		core::list_of<Junction> &js = Vert(i);
        core::merging<Junction>::sort( js, __compare_vert,0);
    }
}
Exemple #5
0
void CBaseModel::DrawPoint() const
{
	glPointSize(3);
	glPushMatrix();
	glBegin(GL_POINTS);
	for(int i = 0; i < (int)GetNumOfVerts();++i){
		Vert(i).Show();
	}		
	glEnd();
	glPopMatrix();
}
Exemple #6
0
void Segmenter:: process( const Bubbles &bubbles )
{
    assert(hseg!=NULL);
    assert(vseg!=NULL);
    
    //--------------------------------------------------------------------------
    // reset
    //--------------------------------------------------------------------------
    for( size_t i=segcount;i>0;--i)
        segments[i]->empty();
    markers.empty();
    duplicates.empty();
    
    //--------------------------------------------------------------------------
    // find all junctions
    //--------------------------------------------------------------------------
    for( const Bubble *bubble = bubbles.first(); bubble; bubble=bubble->next)
    {
        process_bubble(bubble, bubbles.pbc.up);
    }
    
    //--------------------------------------------------------------------------
    // sort junctions
    //--------------------------------------------------------------------------
    SortHorz();
    SortVert();
    
    //--------------------------------------------------------------------------
    // locate Horizontal junctions (for building B field + gradient eval)
    //--------------------------------------------------------------------------
    for( unit_t j=Y.lower;j<=Y.upper;++j)
    {
        for( Junction *J = Horz(j).head; J; J=J->next)
        {
            locate_value( J->vertex.x, X, J->klo, J->khi);
        }
    }
    
    //--------------------------------------------------------------------------
    // locate Vertical junctions (for gradient eval)
    //--------------------------------------------------------------------------
    for( unit_t i=X.lower;i<=X.upper;++i)
    {
        for( Junction *J = Vert(i).head; J; J=J->next)
        {
            locate_value( J->vertex.y, Y, J->klo, J->khi);
        }
    }
    
    
}
Exemple #7
0
AtlasOldMesher::VertIndex AtlasOldMesher::addSpecialVert(Point2I pos, S16 z)
{
   // We optimize a bit by checking against just the special lists.

   // We check special verts, too, it's fun.
   for(S32 i=0; i<mSpecialVerts.size(); i++)
      if(mVerts[mSpecialVerts[i]].isSpecialEqual(pos, z))
         return mSpecialVerts[i];

   // No hit, add it.
   mVerts.push_back(Vert(pos.x, pos.y, z));
   mSpecialVerts.push_back(mVerts.size() - 1);
   return mVerts.size() - 1;
}
Exemple #8
0
AtlasOldMesher::VertIndex AtlasOldMesher::getVertIndex(Point2I pos)
{
   // Calculate hash for this position.
   S32 bin = generatePointHash(pos) % HashBinCount;

   // First, check to see if it exists already.
   for(VertHashBin::const_iterator i=mVertHash[bin].begin(); i!=mVertHash[bin].end(); i++)
      if(mVerts[*i].isEqual(pos))
         return *i;

   // No hit, so let's add it to the vert store.
   mVerts.push_back(Vert(pos.x, pos.y));
   VertIndex vi = mVerts.size() - 1;

   // Add it to the hash, too.
   mVertHash[bin].push_back(vi);

   // And return...
   return vi;
}
Exemple #9
0
void Segmenter:: remove_vertical_junctions_below( const Real ylim )
{
    
    for(unit_t i=X.lower;i<=X.upper;++i)
    {
        Junctions &jvert = Vert(i);
        core::list_of<Junction> tmp;
        while( jvert.size )
        {
            Junction *J = jvert.pop_front();
            if( J->vertex.y < ylim )
            {
                duplicates.push_back(J);
            }
            else
            {
                tmp.push_back(J);
            }
        }
        jvert.swap_with(tmp);
    }
}
Exemple #10
0
//void CBaseModel::RenderFaces(GLenum mode , const vector<int>& faces , 
//                             const map<int,Point2D>
//                             const TexturedFaces& textured_faces ) const
//{
//    glPushMatrix();
//    GLint shadeModel;
//    glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
//
//    const vector<int>& faces = textured_faces.textured_faces;
//    const map<int, Point2D> textured_coordinates = textured_faces.texture_coordinate;
//    for(vector<int>::const_iterator itr = faces.begin(); itr != faces.end();++itr){
//        int face_id = *itr;
//        glBegin(GL_TRIANGLES);
//        for (int j = 0; j < 3; ++j)
//        {			
//            CPoint3D pt = Vert(Face(face_id)[j]) +  Normal(Face(face_id)[j]) * RateOfNormalShift / m_scale * 1.0;
//            const CPoint3D &normal = Normal(Face(face_id)[j]);
//            glNormal3f((float)normal.x, (float)normal.y, (float)normal.z);
//            const Point2D p_tex = textured_coordinates.find(Face(face_id)[j])->second;
//            glTexCoord2d( p_tex.x , p_tex.y);
//            glVertex3f((float)pt.x, (float)pt.y, (float)pt.z);
//        }
//        glEnd();
//    }		
//    glPopMatrix();
//
//}
//
void CBaseModel::Render(GLenum mode) const
{	

	if(mode == GL_SELECT){
        glPushMatrix();
        for (int i = 0; i < GetNumOfFaces(); ++i)
        {
            glPushName(i);
            glBegin(GL_POLYGON);
            for (int j = 0; j < 3; ++j)
            {			
                const CPoint3D &pt = Vert(Face(i)[j]);
                glVertex3f((float)pt.x, (float)pt.y, (float)pt.z);
            }
            glEnd();
            glPopName();
        }		
        glEnd();
        glPopMatrix();
        
        if(false){
            glPointSize(8);
            glPushMatrix();
            for(int i = 0; i < (int)GetNumOfVerts();++i){
                glPushName(i);
                glBegin(GL_POINTS);
                Vert(i).Show();
                glEnd();
                glPopName();
            }		
            glPopMatrix();
        }
		//glPushMatrix();
		////GLint shadeModel;
		////glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
		//for (int i = 0; i < GetNumOfFaces(); ++i)
		//{
		//	glPushName(i);
		//	glBegin(GL_POLYGON);
		//	for (int j = 0; j < 3; ++j)
		//	{			
		//		const CPoint3D &pt = Vert(Face(i)[j]);
		//		glVertex3f((float)pt.x, (float)pt.y, (float)pt.z);
		//	}
		//	glEnd();
		//	glPopName();
		//}		
		//glPopMatrix();
		
	}else{
        //glDisable(GL_LIGHTING);
		//GLenum mode = GL_RENDER;
		glPushMatrix();
		//glTranslated(-m_center.x, -m_center.y, -m_center.z);
		//glScaled(m_scale, m_scale, m_scale);
		GLint shadeModel;
        double alpha = 0.9;
        double alpha_small = 0.9;
		glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
			for (int i = 0; i < GetNumOfFaces(); ++i)
			{
				//if( mode == GL_SELECT )
				//	glPushName(i);
				glBegin(GL_TRIANGLES);
				//glColor3f(1.0,1.0,1.0);
				for (int j = 0; j < 3; ++j)
				{			
					//const CPoint3D &pt = Vert(Face(i)[j]);
					CPoint3D pt = Vert(Face(i)[j]) +  Normal(Face(i)[j]) * RateOfNormalShift / m_scale * -1.0;
					const CPoint3D &normal = Normal(Face(i)[j]);
					//glTexCoord2d( distance_field[Face(i)[j]], distance_field[Face(i)[j]] );
					glNormal3f((float)normal.x, (float)normal.y, (float)normal.z);
                    if (!m_vertex_colors.empty()) {
                        if(m_vertex_colors[Face(i)[j]].Len() < 0.1){
                            (m_vertex_colors[Face(i)[j]] * alpha_small + color_white * (1-alpha_small)).SetColor();
                        }else{
                            (m_vertex_colors[Face(i)[j]] * alpha + color_white * (1-alpha)).SetColor();
                        }
                    }
                    glVertex3f((float)pt.x, (float)pt.y, (float)pt.z);
				}
				glEnd();
				//if (mode == GL_SELECT)
				//	glPopName();
			}		
		glPopMatrix();
        //glEnable(GL_LIGHTING);
	}
}
Exemple #11
0
void CBaseModel::AdjustScaleAndComputeNormalsToVerts()
{
	if (m_Verts.empty())
		return;
	m_NormalsToVerts.resize(m_Verts.size(), CPoint3D(0, 0, 0));
	CPoint3D center(0, 0, 0);
	double sumArea(0);
	CPoint3D sumNormal(0, 0, 0);
	double deta(0);
	for (int i = 0; i < (int)m_Faces.size(); ++i)
	{
		CPoint3D normal = VectorCross(Vert(Face(i)[0]),
			Vert(Face(i)[1]),
			Vert(Face(i)[2]));
		double area = normal.Len();
		CPoint3D gravity3 = Vert(Face(i)[0]) +	Vert(Face(i)[1]) + Vert(Face(i)[2]);
		center += area * gravity3;
		sumArea += area;
		sumNormal += normal;
		deta += gravity3 ^ normal;
		normal.x /= area;
		normal.y /= area;
		normal.z /= area;
		for (int j = 0; j < 3; ++j)
		{
			m_NormalsToVerts[Face(i)[j]] += normal;
		}
	}
	center /= sumArea * 3;
    fprintf(stderr,"center %lf %lf %lf\n" , center.x , center.y , center.z );
	deta -= 3 * (center ^ sumNormal);
	if (true)//deta > 0)
	{
		for (int i = 0; i < GetNumOfVerts(); ++i)
		{
			if (fabs(m_NormalsToVerts[i].x)
				+ fabs(m_NormalsToVerts[i].y)
				+ fabs(m_NormalsToVerts[i].z) >= FLT_EPSILON)
			{					
				m_NormalsToVerts[i].Normalize();
			}
		}
	}
	else
	{
		for (int i = 0; i < GetNumOfFaces(); ++i)
		{
			int temp = m_Faces[i][0];
			m_Faces[i][0] = m_Faces[i][1];
			m_Faces[i][1] = temp;
		}
		for (int i = 0; i < GetNumOfVerts(); ++i)
		{
			if (fabs(m_NormalsToVerts[i].x)
				+ fabs(m_NormalsToVerts[i].y)
				+ fabs(m_NormalsToVerts[i].z) >= FLT_EPSILON)
			{					
				double len = m_NormalsToVerts[i].Len();
				m_NormalsToVerts[i].x /= -len;
				m_NormalsToVerts[i].y /= -len;
				m_NormalsToVerts[i].z /= -len;
			}
		}
	}

	CPoint3D ptUp(m_Verts[0]);
	CPoint3D ptDown(m_Verts[0]);
	for (int i = 1; i < GetNumOfVerts(); ++i)
	{
		if (m_Verts[i].x > ptUp.x)
			ptUp.x = m_Verts[i].x;
		else if (m_Verts[i].x < ptDown.x)
			ptDown.x = m_Verts[i].x;
		if (m_Verts[i].y > ptUp.y)
			ptUp.y = m_Verts[i].y;
		else if (m_Verts[i].y < ptDown.y)
			ptDown.y = m_Verts[i].y;
		if (m_Verts[i].z > ptUp.z)
			ptUp.z = m_Verts[i].z;
		else if (m_Verts[i].z < ptDown.z)
			ptDown.z = m_Verts[i].z;
	}	

	double maxEdgeLenOfBoundingBox = -1;
	if (ptUp.x - ptDown.x > maxEdgeLenOfBoundingBox)
		maxEdgeLenOfBoundingBox = ptUp.x - ptDown.x;
	if (ptUp.y - ptDown.y > maxEdgeLenOfBoundingBox)
		maxEdgeLenOfBoundingBox = ptUp.y - ptDown.y;
	if (ptUp.z - ptDown.z > maxEdgeLenOfBoundingBox)
		maxEdgeLenOfBoundingBox = ptUp.z - ptDown.z;
	m_scale = 2.0 / maxEdgeLenOfBoundingBox;
	m_center = center;
	m_ptUp = ptUp;
	m_ptDown = ptDown;

	m_ptUp = (m_ptUp - center) * m_scale;
	m_ptDown = (m_ptUp - m_ptDown) * m_scale;
	//for (int i = 0; i < (int)m_Verts.size(); ++i)
	//{
	//	m_Verts[i] = (m_Verts[i] - center) * m_scale;
	//}

	m_scale = 1;
	m_center = CPoint3D(0, 0, 0);
}
Exemple #12
0
AABB::AABB(float x, float y, float z)
{
  float xmax = x * 0.5f;
  float ymax = y * 0.5f;
  float zmax = z * 0.5f;

  float xmin = -xmax;
  float ymin = -ymax;
  float zmin = -zmax;

  Tris tris;
  tris.reserve(12);
  Tri t;

  // Bottom
  t.m_verts[0] = Vert(xmin, ymin, zmin, 0, 0,  0, -1, 0);
  t.m_verts[1] = Vert(xmax, ymin, zmin, 1, 0,  0, -1, 0);
  t.m_verts[2] = Vert(xmax, ymin, zmax, 1, 1,  0, -1, 0);
  tris.push_back(t);

  t.m_verts[0] = Vert(xmin, ymin, zmin, 0, 0,  0, -1, 0);
  t.m_verts[1] = Vert(xmax, ymin, zmax, 1, 1,  0, -1, 0);
  t.m_verts[2] = Vert(xmin, ymin, zmax, 0, 1,  0, -1, 0);
  tris.push_back(t);

  // Top
  t.m_verts[0] = Vert(xmax, ymax, zmin, 1, 0,  0, 1, 0);
  t.m_verts[1] = Vert(xmin, ymax, zmin, 0, 0,  0, 1, 0);
  t.m_verts[2] = Vert(xmax, ymax, zmax, 1, 1,  0, 1, 0);
  tris.push_back(t);

  t.m_verts[0] = Vert(xmax, ymax, zmax, 1, 1,  0, 1, 0);
  t.m_verts[1] = Vert(xmin, ymax, zmin, 0, 0,  0, 1, 0);
  t.m_verts[2] = Vert(xmin, ymax, zmax, 0, 1,  0, 1, 0);
  tris.push_back(t);

  // Side
  t.m_verts[0] = Vert(xmax, ymin, zmin, 1, 0,  0, 0, -1);
  t.m_verts[1] = Vert(xmin, ymin, zmin, 0, 0,  0, 0, -1);
  t.m_verts[2] = Vert(xmax, ymax, zmin, 1, 1,  0, 0, -1);
  tris.push_back(t);

  t.m_verts[0] = Vert(xmax, ymax, zmin, 1, 1,  0, 0, -1);
  t.m_verts[1] = Vert(xmin, ymin, zmin, 0, 0,  0, 0, -1);
  t.m_verts[2] = Vert(xmin, ymax, zmin, 0, 1,  0, 0, -1);
  tris.push_back(t);

  // Side
  t.m_verts[0] = Vert(xmin, ymin, zmax, 0, 0,  0, 0, 1);
  t.m_verts[1] = Vert(xmax, ymin, zmax, 1, 0,  0, 0, 1);
  t.m_verts[2] = Vert(xmax, ymax, zmax, 1, 1,  0, 0, 1);
  tris.push_back(t);

  t.m_verts[0] = Vert(xmin, ymin, zmax, 0, 0,  0, 0, 1);
  t.m_verts[1] = Vert(xmax, ymax, zmax, 1, 1,  0, 0, 1);
  t.m_verts[2] = Vert(xmin, ymax, zmax, 0, 1,  0, 0, 1);
  tris.push_back(t);

  // Side
  t.m_verts[0] = Vert(xmax, ymin, zmax, 0, 1,  1, 0, 0);
  t.m_verts[1] = Vert(xmax, ymin, zmin, 0, 0,  1, 0, 0);
  t.m_verts[2] = Vert(xmax, ymax, zmax, 1, 1,  1, 0, 0);
  tris.push_back(t);

  t.m_verts[0] = Vert(xmax, ymax, zmax, 1, 1,  1, 0, 0);
  t.m_verts[1] = Vert(xmax, ymin, zmin, 0, 0,  1, 0, 0);
  t.m_verts[2] = Vert(xmax, ymax, zmin, 1, 0,  1, 0, 0);
  tris.push_back(t);

  // Side
  t.m_verts[0] = Vert(xmin, ymin, zmin, 0, 0,  -1, 0, 0);
  t.m_verts[1] = Vert(xmin, ymin, zmax, 0, 1,  -1, 0, 0);
  t.m_verts[2] = Vert(xmin, ymax, zmax, 1, 1,  -1, 0, 0);
  tris.push_back(t);

  t.m_verts[0] = Vert(xmin, ymin, zmin, 0, 0,  -1, 0, 0);
  t.m_verts[1] = Vert(xmin, ymax, zmax, 1, 1,  -1, 0, 0);
  t.m_verts[2] = Vert(xmin, ymax, zmin, 1, 0,  -1, 0, 0);
  tris.push_back(t);

  SetFromTris(tris);
}
Exemple #13
0
void Segmenter:: compute_junctions(const Spot   *spot,
                                   const Vertex &self,
                                   const Vertex &other,
                                   const Tracer *to)
{
    const Coord   klo = spot->klo;
    const Coord   kup = spot->kup;
    
    const Vertex lo( X[klo.x], Y[klo.y]);
    const Vertex up( X[kup.x], Y[kup.y]);
    assert( INSIDE == ComputeOutCode(self,lo,up));
    
    const OutCode other_code = ComputeOutCode(other, lo, up);
    
    if( other_code & LEFT)
    {
        assert( other.x < self.x);
        Segment  &seg = Vert(klo.x);
        Junction *J   = seg.append();
#if JUNCTION_TAG == 1
        J->kind       = Junction::Vert;
        J->tag        = klo.x;
#endif
        J->vertex.x   = seg.value;
        J->alpha      = ( J->vertex.x - self.x)/(other.x - self.x);
        J->vertex.y   = self.y + (J->alpha)*(other.y - self.y);
        FinalizeJunction(J,spot->handle,to);
    }
    
    if( other_code & RIGHT)
    {
        assert( other.x > self.x);
        Segment  &seg = Vert(kup.x);
        Junction *J   = seg.append();
#if JUNCTION_TAG == 1
        J->kind       = Junction::Vert;
        J->tag        = kup.x;
#endif
        J->vertex.x   = seg.value;
        J->alpha      = ( J->vertex.x - self.x)/(other.x - self.x);
        J->vertex.y   = self.y + (J->alpha)*(other.y - self.y);
        FinalizeJunction(J,spot->handle,to);
    }
    
    if( other_code & BOTTOM )
    {
        assert( other.y < self.y );
        Segment  &seg = Horz(klo.y);
        Junction *J   = seg.append();
#if JUNCTION_TAG == 1
        J->kind       = Junction::Horz;
        J->tag        = klo.y;
#endif
        J->vertex.y   = seg.value;
        J->alpha      = (J->vertex.y - self.y)/(other.y-self.y);
        J->vertex.x   = self.x + (J->alpha)*(other.x-self.x);
        FinalizeJunction(J,spot->handle,to);
    }
    
    
    if( other_code & TOP )
    {
        assert( other.y > self.y );
        Segment  &seg = Horz(kup.y);
        Junction *J   = seg.append();
#if JUNCTION_TAG == 1
        J->kind       = Junction::Horz;
        J->tag        = kup.y;
#endif
        J->vertex.y   = seg.value;
        J->alpha      = (J->vertex.y - self.y)/(other.y-self.y);
        J->vertex.x   = self.x + (J->alpha)*(other.x-self.x);
        FinalizeJunction(J,spot->handle,to);
    }
    
    
}
Exemple #14
0
void Cuboid::draw()
{
	#define Vert(v) { Pd vt = (v); glVertex3d(vt.x,vt.y,vt.z); }
	#define Norm(u,v) { Vd n = ~((u)*(v)); glNormal3d(n.x,n.y,n.z); }
	#define A { glTexCoord2d(0.0,0.0); }
	#define B { glTexCoord2d(1.0,0.0); }
	#define C { glTexCoord2d(1.0,1.0); }
	#define D { glTexCoord2d(0.0,1.0); }

	Pd o = Vd(0,0,0);
	Pd a = o + u + v + w;

	glBegin(GL_QUADS);
		Norm(u,w); A Vert(o); B Vert(o+u); C Vert(o+u+w); D Vert(o+w);
		Norm(v,u); A Vert(o); B Vert(o+v); C Vert(o+v+u); D Vert(o+u);
		Norm(w,v); A Vert(o); B Vert(o+w); C Vert(o+w+v); D Vert(o+v);
		Norm(u,v); A Vert(a); B Vert(a-u); C Vert(a-u-v); D Vert(a-v);
		Norm(v,w); A Vert(a); B Vert(a-v); C Vert(a-v-w); D Vert(a-w);
		Norm(w,u); A Vert(a); B Vert(a-w); C Vert(a-w-u); D Vert(a-u);
	glEnd();

	#undef Vert
	#undef Norm
	#undef A
	#undef B
	#undef C
	#undef D
}