void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh, bool(*predicate)(scene::IMeshBuffer*)) { core::array<scene::SSkinMeshBuffer*>& all_mb = mesh->getMeshBuffers(); const int all_mb_size = all_mb.size(); for (int i = 0; i < all_mb_size; i++) { scene::SSkinMeshBuffer* mb = all_mb[i]; if (mb && predicate(mb)) { mb->convertToTangents(); const int index_count = mb->getIndexCount(); uint16_t* idx = mb->getIndices(); video::S3DVertexTangents* v = (video::S3DVertexTangents*)mb->getVertices(); for (int i = 0; i < index_count; i += 3) { calculateTangents( v[idx[i+0]].Normal, v[idx[i+0]].Tangent, v[idx[i+0]].Binormal, v[idx[i+0]].Pos, v[idx[i+1]].Pos, v[idx[i+2]].Pos, v[idx[i+0]].TCoords, v[idx[i+1]].TCoords, v[idx[i+2]].TCoords); calculateTangents( v[idx[i+1]].Normal, v[idx[i+1]].Tangent, v[idx[i+1]].Binormal, v[idx[i+1]].Pos, v[idx[i+2]].Pos, v[idx[i+0]].Pos, v[idx[i+1]].TCoords, v[idx[i+2]].TCoords, v[idx[i+0]].TCoords); calculateTangents( v[idx[i+2]].Normal, v[idx[i+2]].Tangent, v[idx[i+2]].Binormal, v[idx[i+2]].Pos, v[idx[i+0]].Pos, v[idx[i+1]].Pos, v[idx[i+2]].TCoords, v[idx[i+0]].TCoords, v[idx[i+1]].TCoords); } } } }
double tangentDistance(const double * imageOne, const double * imageTwo, const int height, const int width, const int * choice, const double background){ int i,numTangents=0,numTangentsRemaining; double ** tangents,dist; int size=width*height; for(i=0;i<maxNumTangents;++i) { if(choice[i]>0) numTangents++; } tangents=(double **)malloc(numTangents*sizeof(double *)); for(i=0;i<numTangents;++i) { tangents[i]=(double *)malloc(size*sizeof(double)); } calculateTangents(imageOne, tangents, numTangents, height, width, choice, background); numTangentsRemaining = normalizeTangents(tangents, numTangents, height, width); dist=calculateDistance(imageOne, imageTwo, (const double **) tangents, numTangentsRemaining, height, width); for(i=0;i<numTangents;++i) { free(tangents[i]); } free(tangents); return dist; }
void Mesh::createVPlane(Number w, Number h) { Polygon *imagePolygon = new Polygon(); imagePolygon->addVertex(0,0,0,0,0); imagePolygon->addVertex(w,0,0, 1, 0); imagePolygon->addVertex(w,h,0, 1, 1); imagePolygon->addVertex(0,h,0,0,1); addPolygon(imagePolygon); for(int i=0; i < polygons.size(); i++) { for(int j=0; j < polygons[i]->getVertexCount(); j++) { polygons[i]->getVertex(j)->x = polygons[i]->getVertex(j)->x - (w/2.0f); polygons[i]->getVertex(j)->y = polygons[i]->getVertex(j)->y - (h/2.0f); } } calculateNormals(); calculateTangents(); arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true; }
void Mesh::createCone(Number height, Number radius, int numSegments) { setMeshType(Mesh::TRI_MESH); Number lastx = -1; Number lastz = -1; for (int i=0 ; i < numSegments+1; i++) { Number pos = ((PI*2.0)/((Number)numSegments)) * i; Number x = sinf(pos) * radius; Number z = cosf(pos) * radius; if(i > 0) { // ie only construct faces one we have vertexes from i-1 to use. Polygon *polygon = new Polygon(); polygon->addVertex(lastx,0,lastz,0,0); polygon->addVertex(x,0,z, 1, 0); polygon->addVertex(0,height,0, 1, 1); addPolygon(polygon); polygon = new Polygon(); polygon->addVertex(x,0,z, 1, 1); polygon->addVertex(lastx,0,lastz, 1, 1); polygon->addVertex(0,0,0,0,0); addPolygon(polygon); } lastx = x; lastz = z; /* Polygon *polygon = new Polygon(); polygon->addVertex(w,0,h, 1, 1); polygon->addVertex(0,0,h, 1, 0); polygon->addVertex(0,0,0,0,0); polygon->addVertex(w,0,0,0,1); addPolygon(polygon); */ } for(int i=0; i < polygons.size(); i++) { for(int j=0; j < polygons[i]->getVertexCount(); j++) { // polygons[i]->getVertex(j)->x = polygons[i]->getVertex(j)->x - (radius/2.0f); polygons[i]->getVertex(j)->y = polygons[i]->getVertex(j)->y - (height/2.0f); // polygons[i]->getVertex(j)->z = polygons[i]->getVertex(j)->z - (radius/2.0f); } } calculateNormals(); calculateTangents(); arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int row1,row2,col,ww; int choice[]={1,1,1,1,1,1,1,1,1}; /*={0,0,0,0,0,0,1,0,0};*/ /*choice[]={1,1,1,1,1,1,0,0,0};*/ double * img1, *img2, *imgout,background=0.0; /*1) Read */ /*test*/ img1= mxGetPr(prhs[0]); /*train*/ img2= mxGetPr(prhs[1]); /*choice =mxGetPr(prhs[2]);*/ row1= mxGetN(prhs[0]); row2= mxGetN(prhs[0]); col= mxGetM(prhs[0]); ww=(int)sqrt(col); /*2) Calculate the tangent space at train */ int i,numTangents=0,numTangentsRemaining; double ** tangents; for(i=0;i<maxNumTangents;++i) { /*printf("nn %d,%\n",i,choice[i]);*/ if(choice[i]>0) numTangents++; } tangents=(double **)malloc(numTangents*sizeof(double *)); for(i=0;i<numTangents;++i) { tangents[i]=(double *)malloc(col*sizeof(double)); } /* determine the tangents of the first image*/ calculateTangents(img2, tangents, numTangents,ww,ww, choice, background); /* find the orthonormal tangent subspace */ numTangentsRemaining = normalizeTangents(tangents, numTangents, ww, ww); /*3) Project test onto the tangent space*/ plhs[0] =mxCreateDoubleMatrix(1,col, mxREAL); imgout = mxGetPr(plhs[0]); calculateClosest(img2, img1,tangents, numTangents, col,imgout); for(i=0;i<numTangents;++i) { free(tangents[i]); } free(tangents); }
void mesh::loadMesh(std::string fileLocation) { //assumes pattern: //vert count, tri count //vertices, triangles, normals, texcoords std::ifstream fileStream(fileLocation); fileStream >> vertCount; fileStream >> triCount; triangles.resize(3 * triCount); normals.resize(3 * vertCount); vertices.resize(3 * vertCount); texCoords.resize(2 * vertCount); std::string trash; fileStream >> trash; //read and store vertex positions for(int i = 0; i < 3*vertCount; i++) { fileStream >> vertices[i]; } fileStream >> trash; //read and store triangles (vertex indices) for(int j = 0; j < 3*triCount; j++) { fileStream >> triangles[j]; } fileStream >> trash; //read and store normals for(int k = 0; k < 3*vertCount; k++) { fileStream >> normals[k]; } fileStream >> trash; //read and store texture coordinates for(int l = 0; l < 2*vertCount; l++) { fileStream >> texCoords[l]; } fileStream.close(); calculateTangents(); setupBuffers(); }
// Constructor. Copy the provided picoSurface_t structure into this object RenderablePicoSurface::RenderablePicoSurface(picoSurface_t* surf, const std::string& fExt) : _shaderName(""), _dlRegular(0), _dlProgramVcol(0), _dlProgramNoVCol(0) { // Get the shader from the picomodel struct. If this is a LWO model, use // the material name to select the shader, while for an ASE model the // bitmap path should be used. picoShader_t* shader = PicoGetSurfaceShader(surf); std::string rawName = ""; if (shader != 0) { if (fExt == "lwo") { _shaderName = PicoGetShaderName(shader); } else if (fExt == "ase") { rawName = PicoGetShaderName(shader); std::string rawMapName = PicoGetShaderMapName(shader); _shaderName = cleanupShaderName(rawMapName); } } // If shader not found, fallback to alternative if available // _shaderName is empty if the ase material has no BITMAP // materialIsValid is false if _shaderName is not an existing shader if ((_shaderName.empty() || !GlobalMaterialManager().materialExists(_shaderName)) && !rawName.empty()) { _shaderName = cleanupShaderName(rawName); } // Capturing the shader happens later on when we have a RenderSystem reference // Get the number of vertices and indices, and reserve capacity in our // vectors in advance by populating them with empty structs. int nVerts = PicoGetSurfaceNumVertexes(surf); _nIndices = PicoGetSurfaceNumIndexes(surf); _vertices.resize(nVerts); _indices.resize(_nIndices); // Stream in the vertex data from the raw struct, expanding the local AABB // to include each vertex. for (int vNum = 0; vNum < nVerts; ++vNum) { // Get the vertex position and colour Vertex3f vertex(PicoGetSurfaceXYZ(surf, vNum)); // Expand the AABB to include this new vertex _localAABB.includePoint(vertex); _vertices[vNum].vertex = vertex; _vertices[vNum].normal = Normal3f(PicoGetSurfaceNormal(surf, vNum)); _vertices[vNum].texcoord = TexCoord2f(PicoGetSurfaceST(surf, 0, vNum)); _vertices[vNum].colour = getColourVector(PicoGetSurfaceColor(surf, 0, vNum)); } // Stream in the index data picoIndex_t* ind = PicoGetSurfaceIndexes(surf, 0); for (unsigned int i = 0; i < _nIndices; i++) _indices[i] = ind[i]; // Calculate the tangent and bitangent vectors calculateTangents(); // Construct the DLs createDisplayLists(); }
void recalculateTangentsT(scene::IMeshBuffer* buffer, bool recalculate_normals, bool smooth, bool angle_weighted) { if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS)) return; const u32 vtxCnt = buffer->getVertexCount(); const u32 idxCnt = buffer->getIndexCount(); T* idx = reinterpret_cast<T*>(buffer->getIndices()); video::S3DVertexTangents* v = (video::S3DVertexTangents*)buffer->getVertices(); if (smooth) { u32 i; for (i = 0; i != vtxCnt; ++i) { if (recalculate_normals) v[i].Normal.set(0.f, 0.f, 0.f); v[i].Tangent.set(0.f, 0.f, 0.f); v[i].Binormal.set(0.f, 0.f, 0.f); } //Each vertex gets the sum of the tangents and binormals from the faces around it for (i = 0; i<idxCnt; i += 3) { // if this triangle is degenerate, skip it! if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos || v[idx[i + 0]].Pos == v[idx[i + 2]].Pos || v[idx[i + 1]].Pos == v[idx[i + 2]].Pos /*|| v[idx[i+0]].TCoords == v[idx[i+1]].TCoords || v[idx[i+0]].TCoords == v[idx[i+2]].TCoords || v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */ ) continue; //Angle-weighted normals look better, but are slightly more CPU intensive to calculate core::vector3df weight(1.f, 1.f, 1.f); if (angle_weighted) weight = getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos); core::vector3df localNormal; core::vector3df localTangent; core::vector3df localBinormal; calculateTangents( localNormal, localTangent, localBinormal, v[idx[i + 0]].Pos, v[idx[i + 1]].Pos, v[idx[i + 2]].Pos, v[idx[i + 0]].TCoords, v[idx[i + 1]].TCoords, v[idx[i + 2]].TCoords); if (recalculate_normals) v[idx[i + 0]].Normal += localNormal * weight.X; v[idx[i + 0]].Tangent += localTangent * weight.X; v[idx[i + 0]].Binormal += localBinormal * weight.X; calculateTangents( localNormal, localTangent, localBinormal, v[idx[i + 1]].Pos, v[idx[i + 2]].Pos, v[idx[i + 0]].Pos, v[idx[i + 1]].TCoords, v[idx[i + 2]].TCoords, v[idx[i + 0]].TCoords); if (recalculate_normals) v[idx[i + 1]].Normal += localNormal * weight.Y; v[idx[i + 1]].Tangent += localTangent * weight.Y; v[idx[i + 1]].Binormal += localBinormal * weight.Y; calculateTangents( localNormal, localTangent, localBinormal, v[idx[i + 2]].Pos, v[idx[i + 0]].Pos, v[idx[i + 1]].Pos, v[idx[i + 2]].TCoords, v[idx[i + 0]].TCoords, v[idx[i + 1]].TCoords); if (recalculate_normals) v[idx[i + 2]].Normal += localNormal * weight.Z; v[idx[i + 2]].Tangent += localTangent * weight.Z; v[idx[i + 2]].Binormal += localBinormal * weight.Z; } // Normalize the tangents and binormals if (recalculate_normals) { for (i = 0; i != vtxCnt; ++i) v[i].Normal.normalize(); } for (i = 0; i != vtxCnt; ++i) { v[i].Tangent.normalize(); v[i].Binormal.normalize(); } } else { core::vector3df localNormal; for (u32 i = 0; i<idxCnt; i += 3) { calculateTangents( localNormal, v[idx[i + 0]].Tangent, v[idx[i + 0]].Binormal, v[idx[i + 0]].Pos, v[idx[i + 1]].Pos, v[idx[i + 2]].Pos, v[idx[i + 0]].TCoords, v[idx[i + 1]].TCoords, v[idx[i + 2]].TCoords); if (recalculate_normals) v[idx[i + 0]].Normal = localNormal; calculateTangents( localNormal, v[idx[i + 1]].Tangent, v[idx[i + 1]].Binormal, v[idx[i + 1]].Pos, v[idx[i + 2]].Pos, v[idx[i + 0]].Pos, v[idx[i + 1]].TCoords, v[idx[i + 2]].TCoords, v[idx[i + 0]].TCoords); if (recalculate_normals) v[idx[i + 1]].Normal = localNormal; calculateTangents( localNormal, v[idx[i + 2]].Tangent, v[idx[i + 2]].Binormal, v[idx[i + 2]].Pos, v[idx[i + 0]].Pos, v[idx[i + 1]].Pos, v[idx[i + 2]].TCoords, v[idx[i + 0]].TCoords, v[idx[i + 1]].TCoords); if (recalculate_normals) v[idx[i + 2]].Normal = localNormal; } } }
void MeshUtility::calculateTangentSpace(Vector3* vertices, Vector2* uv, UINT8* indices, UINT32 numVertices, UINT32 numIndices, Vector3* normals, Vector3* tangents, Vector3* bitangents, UINT32 indexSize) { calculateNormals(vertices, indices, numVertices, numIndices, normals, indexSize); calculateTangents(vertices, normals, uv, indices, numVertices, numIndices, tangents, bitangents, indexSize); }
uint32_t objToBin(const uint8_t* _objData , bx::WriterSeekerI* _writer , uint32_t _packUv , uint32_t _packNormal , bool _ccw , bool _flipV , bool _hasTangent , float _scale ) { int64_t parseElapsed = -bx::getHPCounter(); int64_t triReorderElapsed = 0; const int64_t begin = _writer->seek(); Vector3Array positions; Vector3Array normals; Vector3Array texcoords; Index3Map indexMap; TriangleArray triangles; BgfxGroupArray groups; uint32_t num = 0; MeshGroup group; group.m_startTriangle = 0; group.m_numTriangles = 0; group.m_name = ""; group.m_material = ""; char commandLine[2048]; uint32_t len = sizeof(commandLine); int argc; char* argv[64]; const char* next = (const char*)_objData; do { next = bx::tokenizeCommandLine(next, commandLine, len, argc, argv, BX_COUNTOF(argv), '\n'); if (0 < argc) { if (0 == strcmp(argv[0], "#") ) { if (2 < argc && 0 == strcmp(argv[2], "polygons") ) { } } else if (0 == strcmp(argv[0], "f") ) { Triangle triangle; memset(&triangle, 0, sizeof(Triangle) ); const int numNormals = (int)normals.size(); const int numTexcoords = (int)texcoords.size(); const int numPositions = (int)positions.size(); for (uint32_t edge = 0, numEdges = argc-1; edge < numEdges; ++edge) { Index3 index; index.m_texcoord = 0; index.m_normal = 0; index.m_vertexIndex = -1; char* vertex = argv[edge+1]; char* texcoord = strchr(vertex, '/'); if (NULL != texcoord) { *texcoord++ = '\0'; char* normal = strchr(texcoord, '/'); if (NULL != normal) { *normal++ = '\0'; const int nn = atoi(normal); index.m_normal = (nn < 0) ? nn+numNormals : nn-1; } const int tex = atoi(texcoord); index.m_texcoord = (tex < 0) ? tex+numTexcoords : tex-1; } const int pos = atoi(vertex); index.m_position = (pos < 0) ? pos+numPositions : pos-1; uint64_t hash0 = index.m_position; uint64_t hash1 = uint64_t(index.m_texcoord)<<20; uint64_t hash2 = uint64_t(index.m_normal)<<40; uint64_t hash = hash0^hash1^hash2; CS_STL::pair<Index3Map::iterator, bool> result = indexMap.insert(CS_STL::make_pair(hash, index) ); if (!result.second) { Index3& oldIndex = result.first->second; BX_UNUSED(oldIndex); BX_CHECK(oldIndex.m_position == index.m_position && oldIndex.m_texcoord == index.m_texcoord && oldIndex.m_normal == index.m_normal , "Hash collision!" ); } switch (edge) { case 0: case 1: case 2: triangle.m_index[edge] = hash; if (2 == edge) { if (_ccw) { std::swap(triangle.m_index[1], triangle.m_index[2]); } triangles.push_back(triangle); } break; default: if (_ccw) { triangle.m_index[2] = triangle.m_index[1]; triangle.m_index[1] = hash; } else { triangle.m_index[1] = triangle.m_index[2]; triangle.m_index[2] = hash; } triangles.push_back(triangle); break; } } } else if (0 == strcmp(argv[0], "g") ) { if (1 >= argc) { CS_PRINT("Error parsing *.obj file.\n"); return 0; } group.m_name = argv[1]; } else if (*argv[0] == 'v') { group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } if (0 == strcmp(argv[0], "vn") ) { Vector3 normal; normal.x = (float)atof(argv[1]); normal.y = (float)atof(argv[2]); normal.z = (float)atof(argv[3]); normals.push_back(normal); } else if (0 == strcmp(argv[0], "vp") ) { static bool once = true; if (once) { once = false; CS_PRINT("warning: 'parameter space vertices' are unsupported.\n"); } } else if (0 == strcmp(argv[0], "vt") ) { Vector3 texcoord; texcoord.x = (float)atof(argv[1]); texcoord.y = 0.0f; texcoord.z = 0.0f; switch (argc) { case 4: texcoord.z = (float)atof(argv[3]); // fallthrough case 3: texcoord.y = (float)atof(argv[2]); break; default: break; } texcoords.push_back(texcoord); } else { float px = (float)atof(argv[1]); float py = (float)atof(argv[2]); float pz = (float)atof(argv[3]); float pw = 1.0f; if (argc > 4) { pw = (float)atof(argv[4]); } float invW = _scale/pw; px *= invW; py *= invW; pz *= invW; Vector3 pos; pos.x = px; pos.y = py; pos.z = pz; positions.push_back(pos); } } else if (0 == strcmp(argv[0], "usemtl") ) { std::string material(argv[1]); if (material != group.m_material) { group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } } group.m_material = material; } // unsupported tags // else if (0 == strcmp(argv[0], "mtllib") ) // { // } // else if (0 == strcmp(argv[0], "o") ) // { // } // else if (0 == strcmp(argv[0], "s") ) // { // } } ++num; } while ('\0' != *next); group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } int64_t now = bx::getHPCounter(); parseElapsed += now; int64_t convertElapsed = -now; std::sort(groups.begin(), groups.end(), GroupSortByMaterial() ); bool hasColor = false; bool hasNormal; bool hasTexcoord; { Index3Map::const_iterator it = indexMap.begin(); hasNormal = 0 != it->second.m_normal; hasTexcoord = 0 != it->second.m_texcoord; if (!hasTexcoord && texcoords.size() == positions.size() ) { hasTexcoord = true; for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it) { it->second.m_texcoord = it->second.m_position; } } if (!hasNormal && normals.size() == positions.size() ) { hasNormal = true; for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it) { it->second.m_normal = it->second.m_position; } } } bgfx::VertexDecl decl; decl.begin(); decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); if (hasColor) { decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); } if (hasTexcoord) { switch (_packUv) { default: case 0: decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float); break; case 1: decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Half); break; } } if (hasNormal) { _hasTangent &= hasTexcoord; switch (_packNormal) { default: case 0: decl.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float); if (_hasTangent) { decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Float); } break; case 1: decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true); if (_hasTangent) { decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true); } break; } } decl.end(); uint32_t stride = decl.getStride(); uint8_t* vertexData = new uint8_t[triangles.size() * 3 * stride]; uint16_t* indexData = new uint16_t[triangles.size() * 3]; int32_t numVertices = 0; int32_t numIndices = 0; int32_t numPrimitives = 0; uint8_t* vertices = vertexData; uint16_t* indices = indexData; std::string material = groups.begin()->m_material; BgfxPrimitiveArray primitives; Primitive prim; prim.m_startVertex = 0; prim.m_startIndex = 0; uint32_t positionOffset = decl.getOffset(bgfx::Attrib::Position); uint32_t color0Offset = decl.getOffset(bgfx::Attrib::Color0); uint32_t ii = 0; for (BgfxGroupArray::const_iterator groupIt = groups.begin(); groupIt != groups.end(); ++groupIt, ++ii) { for (uint32_t tri = groupIt->m_startTriangle, end = tri + groupIt->m_numTriangles; tri < end; ++tri) { if (material != groupIt->m_material || 65533 < numVertices) { prim.m_numVertices = numVertices - prim.m_startVertex; prim.m_numIndices = numIndices - prim.m_startIndex; if (0 < prim.m_numVertices) { primitives.push_back(prim); } triReorderElapsed -= bx::getHPCounter(); for (BgfxPrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) { const Primitive& prim = *primIt; triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32); } triReorderElapsed += bx::getHPCounter(); if (_hasTangent) { calculateTangents(vertexData, numVertices, decl, indexData, numIndices); } write(_writer , vertexData , numVertices , decl , indexData , numIndices , material.c_str() , primitives.data() , (uint32_t)primitives.size() ); primitives.clear(); for (Index3Map::iterator indexIt = indexMap.begin(); indexIt != indexMap.end(); ++indexIt) { indexIt->second.m_vertexIndex = -1; } vertices = vertexData; indices = indexData; numVertices = 0; numIndices = 0; prim.m_startVertex = 0; prim.m_startIndex = 0; ++numPrimitives; material = groupIt->m_material; } Triangle& triangle = triangles[tri]; for (uint32_t edge = 0; edge < 3; ++edge) { uint64_t hash = triangle.m_index[edge]; Index3& index = indexMap[hash]; if (index.m_vertexIndex == -1) { index.m_vertexIndex = numVertices++; float* position = (float*)(vertices + positionOffset); memcpy(position, &positions[index.m_position], 3*sizeof(float) ); if (hasColor) { uint32_t* color0 = (uint32_t*)(vertices + color0Offset); *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff); } if (hasTexcoord) { float uv[2]; memcpy(uv, &texcoords[index.m_texcoord], 2*sizeof(float) ); if (_flipV) { uv[1] = -uv[1]; } bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, decl, vertices); } if (hasNormal) { float normal[4]; bx::vec3Norm(normal, (float*)&normals[index.m_normal]); bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, decl, vertices); } vertices += stride; } *indices++ = (uint16_t)index.m_vertexIndex; ++numIndices; } } if (0 < numVertices) { prim.m_numVertices = numVertices - prim.m_startVertex; prim.m_numIndices = numIndices - prim.m_startIndex; bx::strlcpy(prim.m_name, groupIt->m_name.c_str(), 128); primitives.push_back(prim); prim.m_startVertex = numVertices; prim.m_startIndex = numIndices; } //CS_PRINT("%3d: s %5d, n %5d, %s\n" // , ii // , groupIt->m_startTriangle // , groupIt->m_numTriangles // , groupIt->m_material.c_str() // ); } if (0 < primitives.size() ) { triReorderElapsed -= bx::getHPCounter(); for (BgfxPrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) { const Primitive& prim = *primIt; triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32); } triReorderElapsed += bx::getHPCounter(); if (_hasTangent) { calculateTangents(vertexData, numVertices, decl, indexData, numIndices); } write(_writer, vertexData, numVertices, decl, indexData, numIndices, material.c_str(), primitives.data(), (uint32_t)primitives.size()); } delete [] indexData; delete [] vertexData; now = bx::getHPCounter(); convertElapsed += now; const int64_t end = _writer->seek(); const uint32_t dataSize = uint32_t(end-begin); CS_PRINT("size: %u\n", dataSize); CS_PRINT("parse %f [s]\ntri reorder %f [s]\nconvert %f [s]\n# %d, g %d, p %d, v %d, i %d\n" , double(parseElapsed)/bx::getHPFrequency() , double(triReorderElapsed)/bx::getHPFrequency() , double(convertElapsed)/bx::getHPFrequency() , num , uint32_t(groups.size() ) , numPrimitives , numVertices , numIndices ); return dataSize; }
void Mesh::createCylinder(Number height, Number radius, int numSegments, bool capped) { setMeshType(Mesh::TRI_MESH); Number lastx = 0; Number lastz = 0; Number lastv = 0; for (int i=0 ; i < numSegments+1; i++) { Number v = ((Number)i)/((Number)numSegments); Number pos = ((PI*2.0)/((Number)numSegments)) * i; Number x = sin(pos) * radius; Number z = cos(pos) * radius; if(i > 0) { Polygon *polygon = new Polygon(); polygon->addVertex(lastx,0,lastz,lastv,0); polygon->addVertex(x,0,z, v, 0); polygon->addVertex(x,height,z, v, 1); addPolygon(polygon); polygon = new Polygon(); polygon->addVertex(x,height,z, v, 1); polygon->addVertex(lastx,height,lastz, lastv, 1); polygon->addVertex(lastx,0,lastz,lastv,0); addPolygon(polygon); if(capped) { polygon = new Polygon(); polygon->addVertex(lastx,height,lastz, 0.5+(lastz/radius*0.5), 0.5+(lastx/radius*0.5)); polygon->addVertex(x,height,z, 0.5+(z/radius*0.5), 0.5+(x/radius*0.5)); polygon->addVertex(0,height,0,0.5,0.5); addPolygon(polygon); polygon = new Polygon(); polygon->addVertex(lastx,0,lastz, 0.5+(lastz/radius*0.5), 0.5+(lastx/radius*0.5)); polygon->addVertex(0,0,0,0.5,0.5); polygon->addVertex(x,0,z, 0.5+(z/radius*0.5), 0.5+(x/radius*0.5)); addPolygon(polygon); } } lastx = x; lastz = z; lastv = v; /* Polygon *polygon = new Polygon(); polygon->addVertex(w,0,h, 1, 1); polygon->addVertex(0,0,h, 1, 0); polygon->addVertex(0,0,0,0,0); polygon->addVertex(w,0,0,0,1); addPolygon(polygon); */ } for(int i=0; i < polygons.size(); i++) { for(int j=0; j < polygons[i]->getVertexCount(); j++) { // polygons[i]->getVertex(j)->x = polygons[i]->getVertex(j)->x - (radius/2.0f); polygons[i]->getVertex(j)->y = polygons[i]->getVertex(j)->y - (height/2.0f); // polygons[i]->getVertex(j)->z = polygons[i]->getVertex(j)->z - (radius/2.0f); } } calculateNormals(); calculateTangents(); arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true; }
void Mesh::createTorus(Number radius, Number tubeRadius, int rSegments, int tSegments) { setMeshType(Mesh::TRI_MESH); Vector3 **grid = (Vector3 **) malloc(sizeof(Vector3*) * rSegments); for (int i=0 ; i < rSegments; i++) { grid[i] = (Vector3*) malloc(sizeof(Vector3) * tSegments); } for (int i=0 ; i < rSegments; i++) { for (int j = 0; j < tSegments; ++j) { Number u = ((Number)i) / rSegments * 2.0 * PI; Number v = ((Number)j) / tSegments * 2.0 * PI; grid[i][j] = Vector3((radius + tubeRadius*cos(v))*cos(u), tubeRadius*sin(v), (radius + tubeRadius*cos(v))*sin(u)); } } for (int i=0 ; i < rSegments; i++) { for (int j = 0; j < tSegments; ++j) { int ip = (i+1) % rSegments; int jp = (j+1) % tSegments; Vector3 a = grid[i ][j]; Vector3 b = grid[ip][j]; Vector3 c = grid[i ][jp]; Vector3 d = grid[ip][jp]; Vector2 uva = Vector2(((Number)i) / ((Number)rSegments), ((Number)j) / ((Number)tSegments)); Vector2 uvb = Vector2((((Number)i)+1.0) / ((Number)rSegments), ((Number)j) / ((Number)tSegments)); Vector2 uvc = Vector2(((Number)i) / ((Number)rSegments), (((Number)j)+1.0) / ((Number)tSegments)); Vector2 uvd = Vector2((((Number)i)+1.0) / ((Number)rSegments), (((Number)j)+1.0) / ((Number)tSegments)); Polygon *polygon = new Polygon(); polygon->addVertex(c.x, c.y, c.z, uvc.x ,uvc.y); polygon->addVertex(b.x, b.y, b.z, uvb.x ,uvb.y); polygon->addVertex(a.x, a.y, a.z, uva.x ,uva.y); addPolygon(polygon); polygon = new Polygon(); polygon->addVertex(b.x, b.y, b.z, uvb.x ,uvb.y); polygon->addVertex(c.x, c.y, c.z, uvc.x ,uvc.y); polygon->addVertex(d.x, d.y, d.z, uvd.x ,uvd.y); addPolygon(polygon); } } for (int i=0 ; i < rSegments; i++) { free(grid[i]); } free(grid); calculateNormals(); calculateTangents(); arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true; }
void Mesh::createSphere(Number _radius, int _segmentsH, int _segmentsW) { setMeshType(Mesh::TRI_MESH); Vector3 **grid = (Vector3 **) malloc(sizeof(Vector3*) * (_segmentsH+1)); for (int i=0 ; i < _segmentsH+1; i++) { grid[i] = (Vector3*) malloc(sizeof(Vector3) * _segmentsW+1); } for (int i = 0; i < _segmentsW; i++) { grid[0][i] = Vector3(0,-_radius,0); } for (int j = 1; j < _segmentsH; j++) { Number horangle = ((float)j) / ((float)_segmentsH) * PI; Number z = -_radius * cos(horangle); Number ringradius = _radius * sin(horangle); for (int i = 0; i < _segmentsW; i++) { Number verangle = 2.0 * ((float)i) / ((float)_segmentsW) * PI; Number x = ringradius * sin(verangle); Number y = ringradius * cos(verangle); grid[j][i] = Vector3(y, z, x); } } for (int i = 0; i < _segmentsW; i++) { grid[_segmentsH][i] = Vector3(0,_radius, 0); } for (int j = 1; j <= _segmentsH; j++) { for (int i = 0; i < _segmentsW; i++) { Vector3 a = grid[j][i]; Vector3 b = grid[j][(i-1+_segmentsW) % _segmentsW]; Vector3 c = grid[j-1][(i-1+_segmentsW) % _segmentsW]; Vector3 d = grid[j-1][i]; int i2 = i; if (i == 0) i2 = _segmentsW; Number vab = ((float)j) / ((float)_segmentsH); Number vcd = (((float)j)-1.0) / ((float)_segmentsH); Number uad = ((float)i2) / ((float)_segmentsW); Number ubc = (((float)i2)-1.0) / ((float)_segmentsW); Vector2 uva = Vector2(uad,vab); Vector2 uvb = Vector2(ubc,vab); Vector2 uvc = Vector2(ubc,vcd); Vector2 uvd = Vector2(uad,vcd); if (j < _segmentsH) { Polygon *polygon = new Polygon(); polygon->addVertex(c.x, c.y, c.z, uvc.x ,uvc.y); polygon->addVertex(b.x, b.y, b.z, uvb.x ,uvb.y); polygon->addVertex(a.x, a.y, a.z, uva.x ,uva.y); addPolygon(polygon); } if (j > 1) { Polygon *polygon = new Polygon(); polygon->addVertex(d.x, d.y, d.z, uvd.x ,uvd.y); polygon->addVertex(c.x, c.y, c.z, uvc.x ,uvc.y); polygon->addVertex(a.x, a.y, a.z, uva.x ,uva.y); addPolygon(polygon); } } } calculateNormals(); calculateTangents(); arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true; }
void Mesh::loadFromFile(OSFILE *inFile) { unsigned int meshType; OSBasics::read(&meshType, sizeof(unsigned int), 1, inFile); setMeshType(meshType); int verticesPerFace; switch(meshType) { case TRI_MESH: verticesPerFace = 3; break; case QUAD_MESH: verticesPerFace = 4; break; default: verticesPerFace = 1; break; } unsigned int numFaces; OSBasics::read(&numFaces, sizeof(unsigned int), 1, inFile); Vector3_struct pos; Vector3_struct nor; Vector4_struct col; Vector2_struct tex; for(int i=0; i < numFaces; i++) { Polygon *poly = new Polygon(); for(int j=0; j < verticesPerFace; j++) { OSBasics::read(&pos, sizeof(Vector3_struct), 1, inFile); OSBasics::read(&nor, sizeof(Vector3_struct), 1, inFile); OSBasics::read(&col, sizeof(Vector4_struct), 1, inFile); OSBasics::read(&tex, sizeof(Vector2_struct), 1, inFile); Vertex *vertex = new Vertex(pos.x, pos.y, pos.z); vertex->setNormal(nor.x,nor.y, nor.z); vertex->restNormal.set(nor.x,nor.y, nor.z); vertex->vertexColor.setColor(col.x,col.y, col.z, col.w); vertex->setTexCoord(tex.x, tex.y); unsigned int numBoneWeights; OSBasics::read(&numBoneWeights, sizeof(unsigned int), 1, inFile); for(int b=0; b < numBoneWeights; b++) { float weight; unsigned int boneID; OSBasics::read(&boneID, sizeof(unsigned int), 1, inFile); OSBasics::read(&weight, sizeof(float), 1, inFile); vertex->addBoneAssignment(boneID, weight); } Number totalWeight = 0; for(int m=0; m < vertex->getNumBoneAssignments(); m++) { BoneAssignment *ba = vertex->getBoneAssignment(m); totalWeight += ba->weight; } for(int m=0; m < vertex->getNumBoneAssignments(); m++) { BoneAssignment *ba = vertex->getBoneAssignment(m); ba->weight = ba->weight/totalWeight; } poly->addVertex(vertex); } addPolygon(poly); } calculateTangents(); arrayDirtyMap[RenderDataArray::VERTEX_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::COLOR_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TEXCOORD_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::NORMAL_DATA_ARRAY] = true; arrayDirtyMap[RenderDataArray::TANGENT_DATA_ARRAY] = true; }