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; }
// 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; }
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)); } } }
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; }
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; }
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; }
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); } */ }
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; }
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 }
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; }
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"); } }
//-------------------------------------------------------------------- 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; }
//------------------------------------------------------------------------------ void Mesh::addVertexElement(const VertexElement& vertexElement) { mVertexElements[vertexElement.getSemantic()] = vertexElement; mVertexSemFlags |= (1L << vertexElement.getSemantic()); }
void VertexDeclaration::add( const VertexElement& element ) { _stride += element.getSize(); _elements.push_back(element); }
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; }
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(); }