예제 #1
0
		VertexDeclaration DX::CreateVertexDeclation( VertexElements *ve )
		{
			LPDIRECT3DVERTEXDECLARATION9 decl = declMap[ve->description.c_str()];

			if(decl)
				return decl;

			int size = ve->vertexElement.size();
			D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[size + 1];

			for(int i=0; i<size; ++i)
			{
				VertexElement *e = &ve->vertexElement[i];
				e->GetD3DElemnts( &(elements[i]) );
			}

			//decl end
			//D3DDECL_END()
			elements[size].Stream = 0xFF;
			elements[size].Offset = elements[size].Usage = 
				elements[size].UsageIndex = elements[size].Method = 0;
			elements[size].Type = D3DDECLTYPE_UNUSED;
			//DONE

			if( SUCCEEDED(device->CreateVertexDeclaration(elements, &decl) ) )
			{
				SOCHashMap<const char *, LPDIRECT3DVERTEXDECLARATION9>::value_type value(ve->description.c_str(), decl);
				declMap.insert(value);
			}

			return decl;
		}
예제 #2
0
// Sort routine for VertexElement
bool vertexElementLess(const VertexElement& e1, const VertexElement& e2)
{
	// Sort by source first
	if (e1.getSource() < e2.getSource())
	{
		return true;
	}
	else if (e1.getSource() == e2.getSource())
	{
		// Use ordering of semantics to sort
		if (e1.getSemantic() < e2.getSemantic())
		{
			return true;
		}
		else if (e1.getSemantic() == e2.getSemantic())
		{
			// Use index to sort
			if (e1.getIndex() < e2.getIndex())
			{
				return true;
			}
		}
	}
	return false;
}
예제 #3
0
	void G3djWriter::writeAttributes(Mesh * mesh){
		if (mesh->getVertexCount() > 0 )
		{
			for(int i=0; i<mesh->getVertexElementCount(); i++){
				if(i>0)
					writer->nextValue(false);
				VertexElement element = mesh->getVertexElement(i);
				writer->writeString(element.usageStr(element.usage));
			}
		}
	}
예제 #4
0
uint32_t
VertexStream::id (const VertexElement& element) 
{ 
    uint32_t id = (1 << (element.usage() + 16)); 
    if (element.usageIndex() >= 0)
    {
        id |= (1 << ((element.usageIndex()+1)));
    }
    
    //LOG ("Element Stream Id is " << id);
    return id;
}
예제 #5
0
	Mesh	*LoadCM3DFile( char const *file )
	{
		int const	nVertices = 3;

		// DUMMY DATA ---------------------------------------------------------
		// create vertices
		XMFLOAT3A	pos[nVertices];
		pos[0] = XMFLOAT3A(0.0f,  .5f, -1.0f);
		pos[1] = XMFLOAT3A( -.5f,  -.5f, -1.0f);
		pos[2] = XMFLOAT3A(0.5f, -0.5f, -1.0f);

		// colors
		XMFLOAT4	colors[nVertices] =
		{
			XMFLOAT4(1, 1, 1, 1), XMFLOAT4(1, 0, 0, 1), XMFLOAT4(0, 0, 1, 1)
		};

		// 1)	load mesh file
		// 2)	parse mesh file
		// 3)	mesh is made up of N subsets
		// 4)	for each subset:
		//			- get subset material
		//			- get subset geom info (vertex start, count, indices...)
		//			- create input element and add it to the mesh
		// 5)	load the shaders and create the input layout

		// fill the Mesh object with geom data (positions, normals...) --------
		(void)file;
		Mesh *mesh = new Mesh(/*nVertices*/);

		VertexElement	*vePos = new VertexElement(sizeof(XMFLOAT3A), nVertices);
		vePos->elementDesc.SemanticName = SemanticName::Position;
		vePos->elementDesc.InputSlot = 0;
		vePos->elementDesc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
		vePos->elementDesc.InputSlot = 0;
		vePos->SetData((float *)pos);
		
		VertexElement	*veClr = new VertexElement(sizeof(XMFLOAT4), nVertices);
		veClr->elementDesc.SemanticName = SemanticName::Color;
		veClr->elementDesc.InputSlot = 0;
		veClr->elementDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
		veClr->elementDesc.InputSlot = 0;
		veClr->elementDesc.AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
		veClr->SetData((float *)colors);

		mesh->AddVertexElement(vePos);
		mesh->AddVertexElement(veClr);
		//mesh->LoadToBuffers();

		return mesh;
	}
예제 #6
0
bool VertexDeclaration::push_back(const VertexElement& element)
{
	if (has(element.usage())) return false;

	_usageMask = _usageMask | vertexAttributeUsageMask(element.usage());
	
	_totalSize += vertexAttributeTypeSize(element.type());
	_list.push_back(element);

	if (_interleaved)
	{
		for (auto& i : _list)
			i.setStride(static_cast<int>(_totalSize));
	}

	return true;
}
예제 #7
0
파일: tetmesh.cpp 프로젝트: delalond/STEPS
void sefield::TetMesh::fill_ve_vec(set<VertexElement*> & veset, vector<VertexElement*> & vevec, queue<VertexElement*> & vequeue, uint ncons, VertexElement ** nbrs)
{

    //cout << "Veset size: " << veset.size();

    vector<uint>newindcs=std::vector<uint>();
    for (uint i=0; i < ncons; ++i)
    {
        bool inserted = veset.insert(nbrs[i]).second;
        if (inserted)
        {
            newindcs.push_back(i);
            // This is the important one- in a vector to keep the ordering
            vevec.push_back(nbrs[i]);
            // And add to the queue too, to find their neighbours:
            vequeue.push(nbrs[i]);
        }
    }


    // Go to the next element in the queue
    if (vequeue.empty() == true) return;
    else
    {
        VertexElement * nextve = vequeue.front();
        vequeue.pop();
        VertexElement ** newneighbs = nextve->getNeighbours();
        uint nextcons = nextve->getNCon();
        fill_ve_vec(veset, vevec, vequeue, nextcons, newneighbs);
    }

    /*
    for (uint i=0; i < newindcs.size(); ++i)
    {
        VertexElement ** newneighbs = nbrs[newindcs[i]]->getNeighbours();
        uint newcons = nbrs[newindcs[i]]->getNCon();
        fill_ve_vec(veset, vevec, newcons, newneighbs, false);
    }
     */
}
예제 #8
0
float* GeometryBuffer::getAttribute(VertexAttribute attribute, uint32 i) const
{
	VertexElement* elem = declarations.find(attribute);
	if( !elem ) return nullptr;

	if(elem->stride == 0)
	{
		uint8 elemSize = elem->getSize();

		const uint8* loc = &data.front() + elem->offset + (elemSize * i);
		return (float*) loc;
	}

	// Calculate the starting position of the attribute data.
	uint8 totalSize = declarations.getVertexSize();
	uint8 localOffset = declarations.getOffset(elem->attribute);

	// TODO: Check the bounds and return null in that case too.

	const uint8* loc = &data.front() + (totalSize * i) + localOffset;
	return (float*) loc;
}
예제 #9
0
void RenderState::setVertexAttribPointer(const VertexElement& e, size_t baseIndex, bool force)
{
#if !defined(ET_CONSOLE_APPLICATION)
	(void)force;
	
	if (e.dataType() == DataType::Int)
	{
		glVertexAttribIPointer(GLuint(e.usage()), static_cast<GLint>(e.components()), dataTypeValue(e.dataType()),
			e.stride(), reinterpret_cast<GLvoid*>(e.offset() + baseIndex));
	}
	else if (e.dataType() == DataType::Float)
	{
		glVertexAttribPointer(GLuint(e.usage()), static_cast<GLint>(e.components()), dataTypeValue(e.dataType()),
			false, e.stride(), reinterpret_cast<GLvoid*>(e.offset() + baseIndex));
	}
	else
	{
		ET_FAIL("Unhandled vertex attribute data type.");
	}

	checkOpenGLError("glVertexAttribPointer");
#endif
}
예제 #10
0
bool
VertexElement::operator != (const VertexElement &src) const
{
    if (_usageIndex != src.usageIndex())
        return true;
    if (_usage != src.usage())
        return true;
    if (_method != src.method())
        return true;
    if (_type != src.type())
        return true;
    if (_offset != src.offset())
        return true;
    if (_stream != src.stream())
        return true;

    return false;
}
예제 #11
0
void VertexDeclaration::rebuild()
{
	mHash = 0;
	int nTexCoord = 0;

	int nElem = 0;
	int nVB = mParent->vertexBufferCount();
	for (int v = 0; v<nVB; ++v) {
		VertexBuffer* vb = mParent->vertexBuffer(v);
		if (vb) {
			nElem += vb->vertexElementCount();
		}
	}

	delete[] mElements;
	mElements = TD_NEW D3D11_INPUT_ELEMENT_DESC[nElem];

	int eIdx = 0;
	for (int v = 0; v<nVB; ++v) {
		VertexBuffer* vb = mParent->vertexBuffer(v);

		if (vb) {
			int offset = 0;

			int nVbElem = vb->vertexElementCount();
			for (int e = 0; e<nVbElem; ++e)
			{
				VertexElement* ve = vb->vertexElement(e);
				D3D11_INPUT_ELEMENT_DESC& elem = mElements[eIdx];

				elem.SemanticName = s_SemanticNameLUT[ve->mUsage];
				elem.SemanticIndex = (BYTE)ve->mIndex;
				elem.Format = makeD3D11Type(ve->mType, ve->mCount);
				elem.AlignedByteOffset = (WORD)offset;
				elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
				elem.InputSlot = v;
				elem.InstanceDataStepRate = 0;

				offset += ve->size();
				++eIdx;

				// while we at this, create the hash (bitmask) that identifies this vertex structure
				if (ve->mUsage == VEU_TEXCOORD)
					nTexCoord++;

				int mask = 0;
				if (ve->mUsage != VEU_UNKNOWN) {
					mask = 1 << ve->mUsage;
				}

				mHash |= mask;
			}
		}
	}

	// add the number of texcoords (if any) to the hash
	mHash |= (nTexCoord << 16);

	// release any existing declaration object
	mLayout.Reset();

	// it seems pretty ugly from a dependency perspective, but D3D11 forces us to have an 
	// existing vertex shader in order to make a vertex declaration (input format), so we 
	// need to fetch one that matches the submesh (or face the warnings that the D3D runtime
	// will spew at us)
	VertexShader* vs = static_cast<VertexShader*>(ShaderManager::instance().createOrFindInstanceOf(mParent));

	// create the vertex declaration
	HRESULT hr = mDevice->CreateInputLayout(
		mElements,
		nElem,
		vs->bytecode(),
		vs->bytecodeLength(),
		&mLayout
		);

	if (FAILED(hr)) {
		throw Exception("Failed to (re)build vertex input layout in VertexDeclaration::rebuild");
	}
}
예제 #12
0
    //--------------------------------------------------------------------
    Status MeshManager::mLoad(std::shared_ptr<Mesh> mesh, const std::string &sid,
                              std::vector<glm::vec3> &positions,
                              std::vector<glm::vec2> &uvs,
                              std::vector<glm::vec3> &flatNormals,
                              std::vector<VertexIndices> &vertexIndices) const {

        bool hasUv, hasFlat, hasSmooth;
        hasUv = !uvs.empty();
        if (!hasUv) {
            Log::trace(TAG, "no UV mapping found for mesh \"%s\"", sid.c_str());
        }

        hasFlat = !flatNormals.empty();
        if (!hasFlat) {
            Log::trace(TAG, "no Flat normal mapping found for mesh \"%s\"", sid.c_str());
        }

        // generates normals
        std::vector<glm::vec3> smoothNormals;
        if (!hasFlat) {
            generateFlatNormals(flatNormals, positions, vertexIndices);
        }
        generateSmoothNormals(smoothNormals, flatNormals, positions, vertexIndices, hasFlat);
        hasSmooth = true; //TODO metadata

        if(!hasFlat) { //TODO handle it with metadata
            flatNormals.clear(); //no need from there
        }

        std::vector<U16> indices;
        std::vector<Vertex> vertices;
        // map one Vertex object to one or many VertexIndices
        std::map<VertexIndices, U16> indexMap;

        U16 currentVertexIndex = 0;
        //create Vertex objects out of VertexIndices.
        for (const VertexIndices& vi : vertexIndices) {

            // if Vertex object of this indices doesn't exist already
            if (indexMap.find(vi) == indexMap.end()) {
                //create it & refer to it.
                indexMap[vi] = currentVertexIndex;
                indices.push_back(currentVertexIndex);
                currentVertexIndex++;

                Vertex v;
                v.setPosition(positions[vi.p]);
                if (hasUv) {
                    v.setUv(uvs[vi.uv]);
                }
                if (hasFlat) {
                    v.setFlatNormal(flatNormals[vi.fn]);
                }
                if (hasSmooth) {
                    v.setSmoothNormal(smoothNormals[vi.sn]);
                }
                vertices.push_back(v);
            } else {
                indices.push_back(indexMap[vi]);
            }
        }

        U32 vertexSize = 0;
        U32 vertexCount = (U32) vertices.size();

        //Positions
        VertexElement positionElement(VertexElement::Semantic::POSITION, 3, GL_FLOAT, vertexSize);
        vertexSize += positionElement.getSizeInByte();
        mesh->addVertexElement(positionElement);


        //Normals
        if (hasFlat) {
            VertexElement flatNormalElement(VertexElement::Semantic::FLAT_NORMAL, 3, GL_FLOAT, vertexSize);
            vertexSize += flatNormalElement.getSizeInByte();
            mesh->addVertexElement(flatNormalElement);
        }
        if (hasSmooth) {
            VertexElement smoothNormalElement(VertexElement::Semantic::SMOOTH_NORMAL, 3, GL_FLOAT, vertexSize);
            vertexSize += smoothNormalElement.getSizeInByte();
            mesh->addVertexElement(smoothNormalElement);
        }

        // UVs
        if (hasUv) {
            VertexElement uvElement(VertexElement::Semantic::UV, 2, GL_FLOAT, vertexSize);
            vertexSize += uvElement.getSizeInByte();
            mesh->addVertexElement(uvElement);
        }

        mesh->mVertexSize = vertexSize;
        mesh->mVertexCount = vertexCount;
        //Log::debug(TAG, "vertexSize=%d vertexCount=%d", vertexSize, vertexCount);
        //Log::debug(TAG, "indices=%d", indices.size());

        BYTE* data = new BYTE[vertexSize * vertexCount];

        /////////////////////////////////////////////////////////////////////////
        // Generate vertex buffer
        //delete mesh->mVertexBuffer;
        if (mesh->mVertexBuffer != nullptr) {
            mesh->mVertexBuffer->wipe();
        }
        mesh->mVertexBuffer = std::make_shared<VertexBuffer>(vertexSize, (U32) (vertexSize * vertexCount));

        /////////////////////////////////////////////////////////////////////////
        // Fills data
        for (U32 v = 0; v < vertexCount; ++v) {
            if (mesh->hasVertexElement(VertexElement::Semantic::POSITION)) {
                VertexElement ve = mesh->getVertexElement(VertexElement::Semantic::POSITION);
                memcpy(&data[v * vertexSize + ve.getOffset()], &(vertices[v].getPosition()), ve.getSizeInByte());
            }
            if (mesh->hasVertexElement(VertexElement::Semantic::FLAT_NORMAL)) {
                VertexElement ve = mesh->getVertexElement(VertexElement::Semantic::FLAT_NORMAL);
                memcpy(&data[v * vertexSize + ve.getOffset()], &(vertices[v].getFlatNormal()), ve.getSizeInByte());
            }
            if (mesh->hasVertexElement(VertexElement::Semantic::SMOOTH_NORMAL)) {
                VertexElement ve = mesh->getVertexElement(VertexElement::Semantic::SMOOTH_NORMAL);
                memcpy(&data[v * vertexSize + ve.getOffset()], &(vertices[v].getSmoothNormal()), ve.getSizeInByte());
            }
            if (mesh->hasVertexElement(VertexElement::Semantic::UV)) {
                VertexElement ve = mesh->getVertexElement(VertexElement::Semantic::UV);
                memcpy(&data[v * vertexSize + ve.getOffset()], &(vertices[v].getUv()), ve.getSizeInByte());
            }
        }

        /////////////////////////////////////////////////////////////////////////
        // Uploads data to GPU
        mesh->mVertexBuffer->writeData(0, vertexSize * vertexCount, data);
        delete[] data;


        //delete mesh->mIndexBuffer;
        if (mesh->mIndexBuffer != nullptr) {
            mesh->mIndexBuffer->wipe();
        }
        mesh->mIndexBuffer = std::make_shared<IndexBuffer>((U32) indices.size());
        mesh->mIndexBuffer->writeData(indices.data());

        mesh->mBoundingSphere = generateBoundingSphere(positions);

        Log::trace(TAG, "Mesh %s loaded", sid.c_str());
        return STATUS_OK;
    }
예제 #13
0
파일: Mesh.cpp 프로젝트: e-biz/arpi-gl
 //------------------------------------------------------------------------------
 void Mesh::addVertexElement(const VertexElement& vertexElement) {
     mVertexElements[vertexElement.getSemantic()] = vertexElement;
     mVertexSemFlags |= (1L << vertexElement.getSemantic());
 }
예제 #14
0
void VertexDeclaration::add( const VertexElement& element ) {
	_stride += element.getSize();
	_elements.push_back(element);
}
예제 #15
0
void*
StreamedMesh::internalStreamPtr()
{    
    if (vertexBufferSize() == 0)
    {
        LOG ("Error, internal vertex buffer size is 0");
        return 0;
    }

    if (!_vertexBufferCpuMemory)
    {
        _vertexBufferCpuMemory = (float*)malloc(sizeof(float)*vertexBufferSize());
    }

    // stash the buffer and put it in an array
    std::map <uint32_t, float*> streamMap;

    for (auto it = _vertexStreams.begin();
        it != _vertexStreams.end();
        it++)
    {
        streamMap.insert (std::make_pair(it->first, it->second->stream()));
    }

    const std::vector <VertexElement>& declaration = _vertexDeclaration->getDeclaration();
    float* vb = (float*)_vertexBufferCpuMemory;

    for (uint32_t i = 0; i < vertexCount(); i++)
    {    
        for (uint32_t j = 0; j < declaration.size()-1; j++)
        {
            VertexElement element = declaration[j];
            VertexStream* stream = 0;
            if (findStream (stream, element))
            {
                uint32_t streamId = VertexStream::id(*stream);
                auto streamIt =  streamMap.find(streamId);

                if (streamIt != streamMap.end() &&
                    streamIt->second)
                {
                    for (uint32_t k = 0; k < stream->stride(); k++)
                    {
                        *vb++ = streamIt->second[k];
                    }
                    streamIt->second += stream->stride();
                }
                else
                {
                    uint32_t stride = IVertexDeclaration::elementToSize(element.type());
                    for (uint32_t k = 0; k < stride; stride++)
                    {
                        *vb++ = 0;
                    }
                }
            }
            else
            {
                // can't find a stream for this element.
                // warn user, and 0 the buffer for the stride size
                uint32_t stride = IVertexDeclaration::elementToSize(element.type());
                for (uint32_t k = 0; k < stride; stride++)
                {
                    *vb++ = 0;
                }
            }
        }
    }

    return _vertexBufferCpuMemory;
}
예제 #16
0
파일: tetmesh.cpp 프로젝트: delalond/STEPS
void sefield::TetMesh::axisOrderElements(uint opt_method, std::string const & opt_file_name)
{

	// Now this method provides a choice between Stefan and Robert's method
	// and the new method by Iain. The original method is fast and suffices for
	// simple geometries, Iain's method is superior and important for complex
	// geometries, but slow.

	if (opt_file_name != "")
	{
		std::fstream opt_file;

	    opt_file.open(opt_file_name.c_str(),
	                std::fstream::in | std::fstream::binary);
	    opt_file.seekg(0);

	    uint nelems = 0;
	    opt_file.read((char*)&nelems, sizeof(uint));
	    if (pElements.size() != nelems) {
	        std::ostringstream os;
	        os << "optimal data mismatch with simulator parameters: sefield::Tetmesh::nelems, ";
	        os << nelems << ":" << pElements.size();
	        throw steps::ArgErr(os.str());
	    }
	    opt_file.read((char*)pVertexPerm, sizeof(uint) * nelems);

	    VertexElementPVec elements_temp = pElements;

	    for (uint vidx = 0; vidx < nelems; ++vidx)
	    {
	    	VertexElementP vep = elements_temp[vidx];
	    	// sanity check
	    	assert(vep->getIDX() == vidx);
	    	uint new_idx = pVertexPerm[vidx];
	    	pElements[new_idx] = vep;
	    }

	    reindexElements();
	    reordered();
	    opt_file.close();
	    return;

	}


	if (opt_method == 2)
	{
		// / / / / / / / / / / / /  / / NEW / / / / / / / / / / / / / / / / / / //

		// LOOPING OVER ALL VERTICES, APPLYING THE WALK METHOD AND FINDING WHICH
		// STARTING VERTEX GIVES THE LOWEST MATRIX WIDTH.

		uint pNVerts = pElements.size();

		// the best vertex(narrowest width)
		uint bestone = 0;
		uint bestwidth = pNVerts;

		std::vector<VertexElement*> orig_indices = pElements;

        stringstream ss;
        ss << "\nFinding optimal vertex indexing. This can take some time...";
        cout << ss.str() << endl;
		for (uint vidx = 0; vidx < pNVerts; ++vidx)
		{
			set<VertexElement*> verteleset = set<VertexElement*>();
			vector<VertexElement*> vertelevec = vector<VertexElement*>();
			queue<VertexElement*> vertelqueue = queue<VertexElement*>();

			verteleset.insert(orig_indices[vidx]);
			vertelevec.push_back(orig_indices[vidx]);
			uint ve0ncons = orig_indices[vidx]->getNCon();
			VertexElement ** ve0neighbs = orig_indices[vidx]->getNeighbours();

			fill_ve_vec(verteleset, vertelevec, vertelqueue, ve0ncons, ve0neighbs);
			pElements.clear();

			vector<VertexElement*>::iterator vertele_end = vertelevec.end();
			uint ielt = 0;

			for (vector<VertexElement*>::iterator vertele = vertelevec.begin(); vertele != vertele_end; ++vertele)
			{
				pElements.push_back(*vertele);
				pVertexPerm[(*vertele)->getIDX()]=ielt;
				ielt++;
			}

			// Note: this will reorder the vertex indices as we go- not a problem in this loop
			// but they must be reset for the final index setting to work
			reindexElements();

			uint maxdi = 0;
			for (int iv = 0; iv < pNVerts; ++iv)
			{
				VertexElement* ve = getVertex(iv);
				int ind = ve->getIDX();

				for (int i = 0; i < ve->getNCon(); ++i)
				{
					int inbr = ve->nbrIdx(i);
					int di = ind - inbr;
					if (di < 0)
					{
						di = -di;
					}
					if (di > maxdi)
					{
						maxdi = di;
					}
				}
			}
			if (maxdi < bestwidth)
			{
				bestone = vidx;
				bestwidth = maxdi;
				//cout << "\nOriginal vertex "<< vidx << " gives banded matrix half-width " << maxdi;
			}
		}

		// reset the vertex indices to their original value: important
		for (uint v = 0; v < pNVerts; ++v)
		{
			orig_indices[v]->setIDX(v);
		}

		set<VertexElement*> verteleset = set<VertexElement*>();
		vector<VertexElement*> vertelevec = vector<VertexElement*>();
		queue<VertexElement*> vertelqueue = queue<VertexElement*>();

		verteleset.insert(orig_indices[bestone]);
		vertelevec.push_back(orig_indices[bestone]);
		uint ve0ncons = orig_indices[bestone]->getNCon();
		VertexElement ** ve0neighbs = orig_indices[bestone]->getNeighbours();

		fill_ve_vec(verteleset, vertelevec, vertelqueue, ve0ncons, ve0neighbs);
		pElements.clear();

		vector<VertexElement*>::iterator vertele_end = vertelevec.end();
		uint ielt = 0;
		for (vector<VertexElement*>::iterator vertele = vertelevec.begin(); vertele != vertele_end; ++vertele)
		{
			pElements.push_back(*vertele);
			pVertexPerm[(*vertele)->getIDX()]=ielt;
			ielt++;
		}
	}
    // / / / / / / / / / / / /  / / / / / / / / / / / / / / / / / / / / / / //

	else if (opt_method == 1)
	{
		/*

		THIS ORIGINAL CODE REPLACED WITH NEW 'WALKING' METHOD. A DRAMATIC
		REDUCTION IN BAND HALF-WIDTHS FOR COMPLEX 3D MESHES.
		This is not the end of the story: TODO investigate whether reordering
		a vertices neighbour's for the queue by distance will improve again.
		 */
		std::vector<double> com = centerOfMass();
		double ** m = new double*[3];
		for (uint i = 0; i < 3; i++)
		{
			m[i] = new double[3];
			m[i][0] = 0.0;
			m[i][1] = 0.0;
			m[i][2] = 0.0;
		}

		for (uint ivert = 0; ivert < countVertices(); ivert++)
		{
			VertexElement* ve = getVertex(ivert);
			double x = ve->getX() - com[0];
			double y = ve->getY() - com[1];
			double z = ve->getZ() - com[2];

			m[0][0] += x * x;
			m[0][1] += x * y;
			m[0][2] += x * z;

			m[1][0] += y * x;
			m[1][1] += y * y;
			m[1][2] += y * z;

			m[2][0] += z * x;
			m[2][1] += z * y;
			m[2][2] += z * z;
		}

		uint iret;
		double gamma;
		double evec[3];
		mainEvec(3, m, &iret, &gamma, evec);
		if (iret != 1)
		{
			cout << "\nWarning - eigenvalue faliure " << endl;
		}

		for (uint i = 0; i < 3; i++)
		{
			delete[] m[i];
		}
		delete[] m;

		double vx = evec[0];
		double vy = evec[1];
		double vz = evec[2];
		vx += 1.e-8;
		vy += 1.e-9;
		vz += 1.e-10;
		stringstream ss;
		ss << "aligning to axis " << vx << " " << vy << " " << vz << endl;
		//cout << ss.str();

		map<double, VertexElement*> hm;
		//vector<double> da;
		for (uint ielt = 0; ielt < countVertices(); ielt++)
		{
			VertexElement * ve = getVertex(ielt);
			double d = vx * ve->getX() + vy * ve->getY() + vz * ve->getZ();

			hm[d] = ve;
			//da.push_back(d);
		}

		//sort(da.begin(), da.end());

		pElements.clear();
		uint ielt = 0;
		map<double, VertexElement*>::const_iterator iter = hm.begin();

		while (iter != hm.end())
		{
			double d = iter->first;
			pElements.push_back(hm[d]);
			++iter;

			// pVertexPerm[i] contains the new index in the elements array
			// for the vertex that was originally at index i
			pVertexPerm[hm[d]->getIDX()] = ielt;
			ielt++;
		}
	}
	else
	{
		std::ostringstream os;
		os << "Unknown optimization method.\n";
		throw steps::ArgErr(os.str());
	}


    reindexElements();
    reordered();

}