poMesh3D::poMesh3D( int _numRows, int _numColumns ) { numRows = _numRows; numColumns = _numColumns; vertexList.resize( numRows*numColumns ); for( int i=0; i<numRows; i++ ) { for( int j=0; j<numColumns; j++ ) { getVertex( i,j ).position.set( i*10,j*10, 0 ); } } for( int i=0; i<numRows-1; i++ ) { for( int j=0; j<numColumns-1; j++ ) { int indexA = getVertexIndex(i,j); int indexB = getVertexIndex(i+1,j); int indexC = getVertexIndex(i,j+1); int indexD = getVertexIndex(i+1,j+1); addTriangle( indexA, indexB, indexC ); addTriangle( indexD, indexC, indexB ); } } calculateNormals(); }
// read through the input file and hook up the graph accordingly void hookupGraph(Graph *g, FILE *inputFile) { int maxLineLen = 1000; // maximum length of a line in the file char line[maxLineLen]; // will hold one line of the file at a time char delim[] = " \t\r\n\f\v"; char *token; int edgeIndex = 0; while(fgets(line, maxLineLen, inputFile)){ // 1st token in line is the source vertex if((token = strtok(line, delim))){ int vertIndex1 = getVertexIndex(g, token); Vertex *vert1 = g->vertices+vertIndex1; // loop through and add all edges/ConnectorElements while((token = strtok(NULL, delim))){ int vertIndex2 = getVertexIndex(g, token); // if index2 < index1, then we ignore it because we already added it if(vertIndex1 < vertIndex2){ Vertex *vert2 = g->vertices+vertIndex2; Edge *ep = g->edges+edgeIndex; ConnectorElement *con = g->connectors+(2*edgeIndex); connect(vert1, ep, con); con = g->connectors+(2*edgeIndex+1); connect(vert2, ep, con); edgeIndex++; } } } } }
/** * Atualiza o vértice * @param orig vértice de origem * @param dest vértice de destino * @param stat tipo de operação */ void update_aresta(int orig, int dest, int stat) { int i = getVertexIndex(orig), j = getVertexIndex(dest); if(i == count) { puts("Vérice origem não existe"); return; } if(j == count) { puts("Vertice de destino não encontrado"); return; } t_edge *here, *aux, *before; here = aux = before = NULL; here = edges[i]; while (here != NULL) if (here->dest == j) { if(stat) { puts("Aresta repetida"); return; } else break; } else { before = here; here = here->next; } if(stat) { aux = createEdge(j); if(before == NULL) edges[i] = aux; else before->next = aux; puts("Aresta inserida com sucesso"); } else { if(before == NULL) { aux = here; edges[i] = here->next; } else { aux = before->next; before->next = aux->next; } free(aux); aux = NULL; puts("Aresta removida com sucesso"); } }
int peano::integration::dataqueries::CartesianGridWriterProxy::getVertexIndex( const tarch::la::Vector<2,double>& position ) { tarch::la::Vector<3,double> position3D; position3D(0) = position(0); position3D(1) = position(1); position3D(2) = 0.0; return getVertexIndex(position3D); }
poSphere3D::poSphere3D( int _numRows, int _numColumns, float _radius ) : poMesh3D(_numRows,_numColumns) { radius = _radius; float dA = 360.f / (float)(numColumns-1); float dB = 180.f / (float)(numRows-1); for( int i=0; i<numRows; i++ ) { for( int j=0; j<numColumns; j++ ) { int N = getVertexIndex(i,j); if ( N==-1 || N < 0 || N >= (int)vertexList.size() ) { printf("ERROR\n"); continue; } float A = -1.f * dA * j; float B = 90 - dB * i; vertexList[N].position.set( cos_deg(B)*cos_deg(A)*radius, sin_deg(B)*radius, cos_deg(B)*sin_deg(A)*radius ); } } calculateNormals(); }
int tarch::plotter::griddata::regular::CartesianGridArrayWriter::getCellIndex( const tarch::la::Vector<2,double>& position ) { tarch::la::Vector<3,double> position3D; position3D(0) = position(0); position3D(1) = position(1); position3D(2) = 0.0; return getVertexIndex(position3D); }
FbxT getElement(const KFbxLayerElementTemplate<FbxT>* pLayerElement, const KFbxMesh* fbxMesh, int nPolygon, int nPolyVertex, int nMeshVertex) { return pLayerElement->GetDirectArray().GetAt(getVertexIndex( pLayerElement, fbxMesh, nPolygon, nPolyVertex, nMeshVertex)); }
void TetMesh::computeGradient(int element, const double * U, int numFields, double * grad) const { // grad is 9 x numFields // grad is constant inside a tet Vec3d vtx[4]; for(int i=0; i<4; i++) vtx[i] = *getVertex(element,i); // form M = // [b - a] // [c - a] // [d - a] Mat3d M(vtx[1] - vtx[0], vtx[2] - vtx[0], vtx[3] - vtx[0]); Mat3d MInv = inv(M); //printf("M=\n"); //M.print(); for(int field=0; field<numFields; field++) { // form rhs = // [U1 - U0] // [U2 - U0] // [U3 - U0] const double * u[4]; for(int i=0; i<4; i++) u[i] = &U[3 * numVertices * field + 3 * getVertexIndex(element, i)]; Vec3d rows[3]; for(int i=0; i<3; i++) rows[i] = Vec3d(u[i+1]) - Vec3d(u[0]); Mat3d rhs(rows); //printf("rhs=\n"); //rhs.print(); Mat3d gradM = trans(MInv * rhs); gradM.convertToArray(&grad[9 * field]); /* // test gradient if (field == 0) { printf("----\n"); printf("0: pos: %.15f %.15f %.15f | uExact: %.15f %.15f %.15f\n", vtx[0][0], vtx[0][1], vtx[0][2], u[0][0], u[0][1], u[0][2]); for(int vertex=0; vertex<3; vertex++) { Vec3d u1 = Vec3d(u[vertex+1]); printf("%d: ", vertex+1); printf("pos: %.15f %.15f %.15f | uExact: %.15f %.15f %.15f | ", vtx[vertex+1][0], vtx[vertex+1][1], vtx[vertex+1][2], u1[0], u1[1], u1[2]); Vec3d u1approx = Vec3d(u[0]) + gradM * (vtx[vertex+1] - vtx[0]); printf("uApprox: %.15f %.15f %.15f\n", u1approx[0], u1approx[1], u1approx[2]); } printf("----\n"); } */ } }
void CTerrainData::AddNode(int x,int y,int tx,int ty,unsigned char dir,int level,int father) { if (!isCellIn(x,y)) { return; } //if (((x!=tx) || (y!=ty))/* && (dir!=DIR_INVALID)*/) { if (getCell(x,y)->uAttribute&TERRAIN_ATT_TYPE_BALK) { return; } if (m_Searched[getVertexIndex(x,y)])// 可检查节点是否访问过 { return; } } m_nNodeCount++; int p = m_nNodeCount; int f = level + (7*abs(x-tx)+7*abs(y-ty)+3*abs(abs(x-tx)-abs(y-ty))) / 2;//启发函数定义 while( p > 1 ) { int q = p >> 1; if( f < node[q].f ) node[p] = node[q]; else break; p = q; } node[p].x = x; node[p].y = y; node[p].f = f; node[p].level = level; node[p].n = m_nAllNodeCount; assert(m_nAllNodeCount<MAX_ALLNODE); m_allnode[m_nAllNodeCount].dir = dir; m_allnode[m_nAllNodeCount].father = father; m_nAllNodeCount++; m_Searched[getVertexIndex(x,y)]=true; }
poVertex3D& poMesh3D::getVertex( int row, int col ) { if ( row < 0 || row >= numRows || col < 0 || col >= numColumns ) { printf("ERROR: poMesh3D::getVertex out of bounds (%d,%d) of (%d,%d)\n", row, col, numRows, numColumns ); return poShape3D::errorVertex; } int index = getVertexIndex(row,col); return vertexList[ index ]; }
void TetMesh::getElementEdges(int el, int * edgeBuffer) const { int v[4]; for(int i=0; i<4; i++) v[i] = getVertexIndex(el,i); int edgeMask[6][2] = { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 3 }, { 2, 3 } }; for(int edge=0; edge<6; edge++) { edgeBuffer[2*edge+0] = v[edgeMask[edge][0]]; edgeBuffer[2*edge+1] = v[edgeMask[edge][1]]; } }
void Map::init(DBAccessor& dba) { std::string texture_file_name; getSettings(dba,mapId,texture_file_name); initTexture(texture_file_name); getVertex(dba,mapId); getVertexIndex(dba,mapId); /* //Vertexの内容を標準出力に表示する std::cout<<"mapVertex"<<std::endl; int imax = mapVertex.size(); for(int i = 0; i < imax; i++) { std::cout << i << ", "; std::cout << mapVertex[i].longitude << ", "; std::cout << mapVertex[i].latitude << ", "; std::cout << mapVertex[i].u << ", "; std::cout << mapVertex[i].v; std::cout<<std::endl; } std::cout<<std::endl; std::cout<<"mapVertexIndex"<<std::endl; imax = mapVertexIndex.size(); for(int i = 0; i < imax; i++) { std::cout << i << ": "; int jmax = mapVertexIndex[i].size(); for (int j = 0; j < jmax; j++) { std::cout << mapVertexIndex[i][j].vertexIndex << ", "; } std::cout << std::endl; } */ }
//=========================================================================== bool cLoadFileOBJ(cMesh* a_mesh, const string& a_fileName) { cOBJModel fileObj; // load file into memory. If an error occurs, exit. if (!fileObj.LoadModel(a_fileName.c_str())) { return (false); }; // get information about mesh cWorld* world = a_mesh->getParentWorld(); // clear all vertices and triangle of current mesh a_mesh->clear(); // get information about file int numMaterials = fileObj.m_OBJInfo.m_materialCount; int numNormals = fileObj.m_OBJInfo.m_normalCount; int numTexCoord = fileObj.m_OBJInfo.m_texCoordCount; // extract materials vector<cMaterial> materials; // object has no material properties if (numMaterials == 0) { // create a new child cMesh *newMesh = a_mesh->createMesh(); a_mesh->addChild(newMesh); // Give him a default color a_mesh->setVertexColor(cColorb(255,255,255,255),1); a_mesh->useColors(1,1); a_mesh->useMaterial(0,1); a_mesh->enableTransparency(0,1); } // object has material properties. Create a child for each material // property. else { int i = 0; bool found_transparent_material = false; while (i < numMaterials) { // create a new child cMesh *newMesh = a_mesh->createMesh(); a_mesh->addChild(newMesh); // get next material cMaterial newMaterial; cMaterialInfo material = fileObj.m_pMaterials[i]; int textureId = material.m_textureID; if (textureId >= 1) { cTexture2D *newTexture = world->newTexture(); int result = newTexture->loadFromFile(material.m_texture); // If this didn't work out, try again in the obj file's path if (result == 0) { char model_dir[1024]; const char* fname = a_fileName.c_str(); find_directory(model_dir,fname); char new_texture_path[1024]; sprintf(new_texture_path,"%s/%s",model_dir,material.m_texture); result = newTexture->loadFromFile(new_texture_path); } if (result) newMesh->setTexture(newTexture); // We really failed to load a texture... else { #ifdef _WIN32 // CHAI_DEBUG_PRINT("Could not load texture map %s\n",material.m_texture); #endif } } float alpha = material.m_alpha; if (alpha < 1.0) { newMesh->enableTransparency(1,0); found_transparent_material = true; } // get ambient component: newMesh->m_material.m_ambient.setR(material.m_ambient[0]); newMesh->m_material.m_ambient.setG(material.m_ambient[1]); newMesh->m_material.m_ambient.setB(material.m_ambient[2]); newMesh->m_material.m_ambient.setA(alpha); // get diffuse component: newMesh->m_material.m_diffuse.setR(material.m_diffuse[0]); newMesh->m_material.m_diffuse.setG(material.m_diffuse[1]); newMesh->m_material.m_diffuse.setB(material.m_diffuse[2]); newMesh->m_material.m_diffuse.setA(alpha); // get specular component: newMesh->m_material.m_specular.setR(material.m_specular[0]); newMesh->m_material.m_specular.setG(material.m_specular[1]); newMesh->m_material.m_specular.setB(material.m_specular[2]); newMesh->m_material.m_specular.setA(alpha); // get emissive component: newMesh->m_material.m_emission.setR(material.m_emmissive[0]); newMesh->m_material.m_emission.setG(material.m_emmissive[1]); newMesh->m_material.m_emission.setB(material.m_emmissive[2]); newMesh->m_material.m_emission.setA(alpha); // get shininess newMaterial.setShininess((GLuint)(material.m_shininess)); i++; } // Enable material property rendering a_mesh->useColors(0,1); a_mesh->useMaterial(1,1); // Mark the presence of transparency in the root mesh; don't // modify the value stored in children... a_mesh->enableTransparency(found_transparent_material,0); } // Keep track of vertex mapping in each mesh; maps "old" vertices // to new vertices int nMeshes = a_mesh->getNumChildren(); vertexIndexSet_uint_map* vertexMaps = new vertexIndexSet_uint_map[nMeshes]; vertexIndexSet_uint_map::iterator vertexMapIter; // build object { int i = 0; // get triangles int numTriangles = fileObj.m_OBJInfo.m_faceCount; int j = 0; while (j < numTriangles) { // get next face cFace face = fileObj.m_pFaces[j]; // get material index attributed to the face int objIndex = face.m_materialIndex; // the mesh that we're reading this triangle into cMesh* curMesh = (cMesh*)a_mesh->getChild(objIndex); // create a name for this mesh if necessary (over-writing a previous // name if one has been written) if ( (face.m_groupIndex >= 0) && (fileObj.m_groupNames.size() > 0) ) strncmp(curMesh->m_objectName,fileObj.m_groupNames[face.m_groupIndex],CHAI_MAX_OBJECT_NAME_LENGTH); // get the vertex map for this mesh vertexIndexSet_uint_map* curVertexMap = &(vertexMaps[objIndex]); // number of vertices on face int vertCount = face.m_numVertices; if (vertCount >= 3) { int indexV1 = face.m_pVertexIndices[0]; if (g_objLoaderShouldGenerateExtraVertices==false) { vertexIndexSet vis(indexV1); if (numNormals > 0) vis.nIndex = face.m_pNormalIndices[0]; if (numTexCoord > 0) vis.tIndex = face.m_pTextureIndices[0]; indexV1 = getVertexIndex(curMesh, &fileObj, curVertexMap, vis); } for (int triangleVert = 2; triangleVert < vertCount; triangleVert++) { int indexV2 = face.m_pVertexIndices[triangleVert-1]; int indexV3 = face.m_pVertexIndices[triangleVert]; if (g_objLoaderShouldGenerateExtraVertices==false) { vertexIndexSet vis(indexV2); if (numNormals > 0) vis.nIndex = face.m_pNormalIndices[triangleVert-1]; if (numTexCoord > 0) vis.tIndex = face.m_pTextureIndices[triangleVert-1]; indexV2 = getVertexIndex(curMesh, &fileObj, curVertexMap, vis); vis.vIndex = indexV3; if (numNormals > 0) vis.nIndex = face.m_pNormalIndices[triangleVert]; if (numTexCoord > 0) vis.tIndex = face.m_pTextureIndices[triangleVert]; indexV3 = getVertexIndex(curMesh, &fileObj, curVertexMap, vis); } // For debugging, I want to look for degenerate triangles, but // I don't want to assert here. if (indexV1 == indexV2 || indexV2 == indexV3 || indexV1 == indexV3) { } unsigned int indexTriangle; // create triangle: if (g_objLoaderShouldGenerateExtraVertices==false) { indexTriangle = curMesh->newTriangle(indexV1,indexV2,indexV3); } else { indexTriangle = curMesh->newTriangle( fileObj.m_pVertices[indexV1], fileObj.m_pVertices[indexV2], fileObj.m_pVertices[indexV3] ); } cTriangle* curTriangle = curMesh->getTriangle(indexTriangle,false); // assign normals: if (numNormals > 0) { // set normals curTriangle->getVertex0()->setNormal(face.m_pNormals[0]); curTriangle->getVertex1()->setNormal(face.m_pNormals[triangleVert-1]); curTriangle->getVertex2()->setNormal(face.m_pNormals[triangleVert]); } // assign texture coordinates if (numTexCoord > 0) { // set texture coordinates curTriangle->getVertex0()->setTexCoord(face.m_pTexCoords[0]); curTriangle->getVertex1()->setTexCoord(face.m_pTexCoords[triangleVert-1]); curTriangle->getVertex2()->setTexCoord(face.m_pTexCoords[triangleVert]); } } } else { // This faces doesn't have 3 vertices... this line is just // here for debugging, since this should never happen, but // I don't want to assert here. } j++; } i++; } delete [] vertexMaps; // if no normals were specified in the file, compute them // based on triangle faces if (numNormals == 0) { a_mesh->computeAllNormals(true); } // compute boundary boxes a_mesh->computeBoundaryBox(true); // update global position in world if (world != 0) world->computeGlobalPositions(true); // return success return (true); }
osgDB::ReaderWriter::ReadResult OsgFbxReader::readMesh( KFbxNode* pNode, KFbxMesh* fbxMesh, std::vector<StateSetContent>& stateSetList, const char* szName) { GeometryMap geometryMap; osg::Geode* pGeode = new osg::Geode; pGeode->setName(szName); const KFbxLayerElementNormal* pFbxNormals = 0; const KFbxLayerElementVertexColor* pFbxColors = 0; const KFbxLayerElementMaterial* pFbxMaterials = 0; const KFbxVector4* pFbxVertices = fbxMesh->GetControlPoints(); // scan layers for Normals, Colors and Materials elements (this will get the first available elements)... for (int cLayerIndex = 0; cLayerIndex < fbxMesh->GetLayerCount(); cLayerIndex++) { const KFbxLayer* pFbxLayer = fbxMesh->GetLayer(cLayerIndex); if (!pFbxLayer) continue; // get normals, colors and materials... if (!pFbxNormals) pFbxNormals = pFbxLayer->GetNormals(); if (!pFbxColors) pFbxColors = pFbxLayer->GetVertexColors(); if (!pFbxMaterials) pFbxMaterials = pFbxLayer->GetMaterials(); } // look for UV elements (diffuse, opacity, reflection, emissive, ...) and get their channels names... std::string diffuseChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sDiffuse); std::string opacityChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sTransparentColor); std::string emissiveChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sEmissive); // look for more UV elements here... // UV elements... const KFbxLayerElementUV* pFbxUVs_diffuse = getUVElementForChannel(diffuseChannel, KFbxLayerElement::eDIFFUSE_TEXTURES, fbxMesh); const KFbxLayerElementUV* pFbxUVs_opacity = getUVElementForChannel(opacityChannel, KFbxLayerElement::eTRANSPARENT_TEXTURES, fbxMesh); const KFbxLayerElementUV* pFbxUVs_emissive = getUVElementForChannel(emissiveChannel, KFbxLayerElement::eEMISSIVE_TEXTURES, fbxMesh); // more UV elements here... // check elements validity... if (!layerElementValid(pFbxNormals)) pFbxNormals = 0; if (!layerElementValid(pFbxColors)) pFbxColors = 0; if (!layerElementValid(pFbxUVs_diffuse)) pFbxUVs_diffuse = 0; if (!layerElementValid(pFbxUVs_opacity)) pFbxUVs_opacity = 0; if (!layerElementValid(pFbxUVs_emissive)) pFbxUVs_emissive = 0; // more here... int nPolys = fbxMesh->GetPolygonCount(); int nDeformerCount = fbxMesh->GetDeformerCount(KFbxDeformer::eSKIN); int nDeformerBlendShapeCount = fbxMesh->GetDeformerCount(KFbxDeformer::eBLENDSHAPE); GeometryType geomType = GEOMETRY_STATIC; //determine the type of geometry if (nDeformerCount) { geomType = GEOMETRY_RIG; } else if (nDeformerBlendShapeCount) { geomType = GEOMETRY_MORPH; } FbxToOsgVertexMap fbxToOsgVertMap; OsgToFbxNormalMap osgToFbxNormMap; // First add only triangles and quads (easy to split into triangles without // more processing) // This is the reason we store polygons references: PolygonRefList polygonRefList; for (int i = 0, nVertex = 0; i < nPolys; ++i) { int lPolygonSize = fbxMesh->GetPolygonSize(i); int materialIndex = getPolygonIndex(pFbxMaterials, i); osg::Geometry* pGeometry = getGeometry(pGeode, geometryMap, stateSetList, geomType, materialIndex, pFbxNormals != 0, pFbxUVs_diffuse != 0, pFbxUVs_opacity != 0, pFbxUVs_emissive != 0, // more UV elements here... pFbxColors != 0, options, lightmapTextures); osg::Array* pVertices = pGeometry->getVertexArray(); osg::Array* pNormals = pGeometry->getNormalArray(); // get texture coordinates... osg::Array* pTexCoords_diffuse = pGeometry->getTexCoordArray(StateSetContent::DIFFUSE_TEXTURE_UNIT); osg::Array* pTexCoords_opacity = pGeometry->getTexCoordArray(StateSetContent::OPACITY_TEXTURE_UNIT); osg::Array* pTexCoords_emissive = pGeometry->getTexCoordArray(StateSetContent::EMISSIVE_TEXTURE_UNIT); // more texture coordinates here... osg::Array* pColors = pGeometry->getColorArray(); if (lPolygonSize == 3) { // Triangle readMeshTriangle(fbxMesh, i, 0, 1, 2, nVertex, nVertex+1, nVertex+2, fbxToOsgVertMap, osgToFbxNormMap, pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors, pGeometry, pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors); nVertex += 3; } else if (lPolygonSize == 4) { // Quad - Convert to triangles // Use some fast specialized code to see how the should be decomposed // Two cases : Split at '02' (012 and 023), or split at '13 (013 and 123) bool split02 = quadSplit02(fbxMesh, i, 0, 1, 2, 3, pFbxVertices); int p02 = split02 ? 2 : 3; // Triangle 0, point 2 int p10 = split02 ? 0 : 1; // Triangle 1, point 0 readMeshTriangle(fbxMesh, i, 0, 1, p02, nVertex, nVertex+1, nVertex+p02, fbxToOsgVertMap, osgToFbxNormMap, pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors, pGeometry, pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors); readMeshTriangle(fbxMesh, i, p10, 2, 3, nVertex+p10, nVertex+2, nVertex+3, fbxToOsgVertMap, osgToFbxNormMap, pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors, pGeometry, pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors); nVertex += 4; } else if (tessellatePolygons) { // Polygons - Store to add after triangles polygonRefList.push_back(PolygonRef(pGeometry, i, nVertex)); nVertex += lPolygonSize; } else { int nVertex0 = nVertex; nVertex += (std::min)(2, lPolygonSize); for (int j = 2; j < lPolygonSize; ++j, ++nVertex) { readMeshTriangle(fbxMesh, i, 0, j - 1, j, nVertex0, nVertex - 1, nVertex, fbxToOsgVertMap, osgToFbxNormMap, pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors, pGeometry, pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors); } } } for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i) { osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry(); osg::DrawArrays* pDrawArrays = new osg::DrawArrays( GL_TRIANGLES, 0, pGeometry->getVertexArray()->getNumElements()); pGeometry->addPrimitiveSet(pDrawArrays); } // Now add polygons - Convert to triangles // We put vertices in their own PrimitiveSet with Mode=POLYGON; then run the // Tessellator on the Geometry which should tessellate the polygons // automagically. for (PolygonRefList::iterator it = polygonRefList.begin(), itEnd=polygonRefList.end(); it != itEnd; ++it) { int i = it->numPoly; int lPolygonSize = fbxMesh->GetPolygonSize(i); //int materialIndex = getPolygonIndex(pFbxMaterials, i); osg::Geometry* pGeometry = it->pGeometry; osg::Array* pVertices = pGeometry->getVertexArray(); osg::Array* pNormals = pGeometry->getNormalArray(); osg::Array* pTexCoords_diffuse = pGeometry->getTexCoordArray(StateSetContent::DIFFUSE_TEXTURE_UNIT); osg::Array* pTexCoords_opacity = pGeometry->getTexCoordArray(StateSetContent::OPACITY_TEXTURE_UNIT); osg::Array* pTexCoords_emissive = pGeometry->getTexCoordArray(StateSetContent::EMISSIVE_TEXTURE_UNIT); osg::Array* pColors = pGeometry->getColorArray(); // Index of the 1st vertex of the polygon in the geometry int osgVertex0 = pVertices->getNumElements(); for (int j = 0, nVertex = it->nVertex; j<lPolygonSize; ++j, ++nVertex) { int v0 = fbxMesh->GetPolygonVertex(i, j); fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v0, GIPair(pGeometry, pVertices->getNumElements()))); addVec3ArrayElement(*pVertices, pFbxVertices[v0]); if (pNormals) { int n0 = getVertexIndex(pFbxNormals, fbxMesh, i, j, nVertex); osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements()), n0)); addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n0)); } // add texture maps data (avoid duplicates)... if (pTexCoords_diffuse) { addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, j, nVertex)); } if (pTexCoords_opacity && (pTexCoords_opacity != pTexCoords_diffuse)) { addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, j, nVertex)); } // Only spherical reflection maps are supported (so do not add coordinates for the reflection map) if (pTexCoords_emissive && (pTexCoords_emissive != pTexCoords_opacity) && (pTexCoords_emissive != pTexCoords_diffuse)) { addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, j, nVertex)); } // add more texture maps here... if (pColors) { addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, j, nVertex)); } } osg::DrawArrays* pDrawArrays = new osg::DrawArrays( GL_POLYGON, osgVertex0, pGeometry->getVertexArray()->getNumElements() - osgVertex0); pGeometry->addPrimitiveSet(pDrawArrays); } for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i) { osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry(); // Now split polygons if necessary osgUtil::Tessellator tessellator; tessellator.retessellatePolygons(*pGeometry); if (pGeode->getNumDrawables() > 1) { std::stringstream ss; ss << pGeode->getName() << " " << i + 1; pGeometry->setName(ss.str()); } else { pGeometry->setName(pGeode->getName()); } } if (geomType == GEOMETRY_RIG) { typedef std::map<osg::ref_ptr<osg::Geometry>, osg::ref_ptr<osgAnimation::RigGeometry> > GeometryRigGeometryMap; GeometryRigGeometryMap old2newGeometryMap; for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i) { osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry(); osgAnimation::RigGeometry* pRig = new osgAnimation::RigGeometry; pRig->setSourceGeometry(pGeometry); pRig->copyFrom(*pGeometry); old2newGeometryMap.insert(GeometryRigGeometryMap::value_type( pGeometry, pRig)); pRig->setDataVariance(osg::Object::DYNAMIC); pRig->setUseDisplayList( false ); pGeode->setDrawable(i, pRig); pRig->setInfluenceMap(new osgAnimation::VertexInfluenceMap); pGeometry = pRig; } for (int i = 0; i < nDeformerCount; ++i) { KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(i, KFbxDeformer::eSKIN); int nClusters = pSkin->GetClusterCount(); for (int j = 0; j < nClusters; ++j) { KFbxCluster* pCluster = (KFbxCluster*)pSkin->GetCluster(j); //assert(KFbxCluster::eNORMALIZE == pCluster->GetLinkMode()); KFbxNode* pBone = pCluster->GetLink(); KFbxXMatrix transformLink; pCluster->GetTransformLinkMatrix(transformLink); KFbxXMatrix transformLinkInverse = transformLink.Inverse(); const double* pTransformLinkInverse = transformLinkInverse; osg::Matrix bindMatrix(pTransformLinkInverse); int nIndices = pCluster->GetControlPointIndicesCount(); int* pIndices = pCluster->GetControlPointIndices(); double* pWeights = pCluster->GetControlPointWeights(); for (int k = 0; k < nIndices; ++k) { int fbxIndex = pIndices[k]; float weight = static_cast<float>(pWeights[k]); for (FbxToOsgVertexMap::const_iterator it = fbxToOsgVertMap.find(fbxIndex); it != fbxToOsgVertMap.end() && it->first == fbxIndex; ++it) { GIPair gi = it->second; osgAnimation::RigGeometry& rig = dynamic_cast<osgAnimation::RigGeometry&>( *old2newGeometryMap[gi.first]); addBindMatrix(boneBindMatrices, pBone, bindMatrix, &rig); osgAnimation::VertexInfluenceMap& vim = *rig.getInfluenceMap(); osgAnimation::VertexInfluence& vi = getVertexInfluence(vim, pBone->GetName()); vi.push_back(osgAnimation::VertexIndexWeight( gi.second, weight)); } } } } } else if (geomType == GEOMETRY_MORPH) { for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i) { osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry(); osgAnimation::MorphGeometry& morph = dynamic_cast<osgAnimation::MorphGeometry&>(*pGeometry); pGeode->addUpdateCallback(new osgAnimation::UpdateMorph(morph.getName())); //read morph geometry for (int nBlendShape = 0; nBlendShape < nDeformerBlendShapeCount; ++nBlendShape) { KFbxBlendShape* pBlendShape = KFbxCast<KFbxBlendShape>(fbxMesh->GetDeformer(nBlendShape, KFbxDeformer::eBLENDSHAPE)); const int nBlendShapeChannelCount = pBlendShape->GetBlendShapeChannelCount(); for (int nBlendShapeChannel = 0; nBlendShapeChannel < nBlendShapeChannelCount; ++nBlendShapeChannel) { KFbxBlendShapeChannel* pBlendShapeChannel = pBlendShape->GetBlendShapeChannel(nBlendShapeChannel); if (!pBlendShapeChannel->GetTargetShapeCount()) continue; //Assume one shape if (pBlendShapeChannel->GetTargetShapeCount() > 1) { OSG_WARN << "Multiple FBX Target Shapes, only the first will be used" << std::endl; } const KFbxGeometryBase* pMorphShape = pBlendShapeChannel->GetTargetShape(0); const KFbxLayerElementNormal* pFbxShapeNormals = 0; if (const KFbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0)) { pFbxShapeNormals = pFbxShapeLayer->GetNormals(); if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0; } osg::Geometry* pMorphTarget = new osg::Geometry(morph); pMorphTarget->setVertexArray(static_cast<osg::Array*>( pMorphTarget->getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); if (pFbxShapeNormals) { if (osg::Array* pNormals = pMorphTarget->getNormalArray()) { pMorphTarget->setNormalArray(static_cast<osg::Array*>( pNormals->clone(osg::CopyOp::DEEP_COPY_ARRAYS))); } } pMorphTarget->setName(pMorphShape->GetName()); morph.addMorphTarget(pMorphTarget, 0.0f); readAnimation(pNode, fbxScene, morph.getName(), pAnimationManager, fbxMesh, nBlendShape, nBlendShapeChannel, (int)morph.getMorphTargetList().size() - 1); } } } int nMorphTarget = 0; for (int nBlendShape = 0; nBlendShape < nDeformerBlendShapeCount; ++nBlendShape) { KFbxBlendShape* pBlendShape = KFbxCast<KFbxBlendShape>(fbxMesh->GetDeformer(nBlendShape, KFbxDeformer::eBLENDSHAPE)); const int nBlendShapeChannelCount = pBlendShape->GetBlendShapeChannelCount(); for (int nBlendShapeChannel = 0; nBlendShapeChannel < nBlendShapeChannelCount; ++nBlendShapeChannel) { KFbxBlendShapeChannel* pBlendShapeChannel = pBlendShape->GetBlendShapeChannel(nBlendShapeChannel); if (!pBlendShapeChannel->GetTargetShapeCount()) continue; //Assume one shape again const KFbxGeometryBase* pMorphShape = pBlendShapeChannel->GetTargetShape(0); const KFbxLayerElementNormal* pFbxShapeNormals = 0; if (const KFbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0)) { pFbxShapeNormals = pFbxShapeLayer->GetNormals(); if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0; } const KFbxVector4* pControlPoints = pMorphShape->GetControlPoints(); int nControlPoints = pMorphShape->GetControlPointsCount(); for (int fbxIndex = 0; fbxIndex < nControlPoints; ++fbxIndex) { osg::Vec3d vPos = convertVec3(pControlPoints[fbxIndex]); for (FbxToOsgVertexMap::const_iterator it = fbxToOsgVertMap.find(fbxIndex); it != fbxToOsgVertMap.end() && it->first == fbxIndex; ++it) { GIPair gi = it->second; osgAnimation::MorphGeometry& morphGeom = dynamic_cast<osgAnimation::MorphGeometry&>(*gi.first); osg::Geometry* pGeometry = morphGeom.getMorphTarget(nMorphTarget).getGeometry(); if (pGeometry->getVertexArray()->getType() == osg::Array::Vec3dArrayType) { osg::Vec3dArray* pVertices = static_cast<osg::Vec3dArray*>(pGeometry->getVertexArray()); (*pVertices)[gi.second] = vPos; } else { osg::Vec3Array* pVertices = static_cast<osg::Vec3Array*>(pGeometry->getVertexArray()); (*pVertices)[gi.second] = vPos; } if (pFbxShapeNormals && pGeometry->getNormalArray()) { if (pGeometry->getNormalArray()->getType() == osg::Array::Vec3dArrayType) { osg::Vec3dArray* pNormals = static_cast<osg::Vec3dArray*>(pGeometry->getNormalArray()); (*pNormals)[gi.second] = convertVec3( pFbxShapeNormals->GetDirectArray().GetAt(osgToFbxNormMap[gi])); } else { osg::Vec3Array* pNormals = static_cast<osg::Vec3Array*>(pGeometry->getNormalArray()); (*pNormals)[gi.second] = convertVec3( pFbxShapeNormals->GetDirectArray().GetAt(osgToFbxNormMap[gi])); } } } } //don't put this in the for loop as we don't want to do it if the loop continues early ++nMorphTarget; } } } KFbxXMatrix fbxGeometricTransform; fbxGeometricTransform.SetTRS( pNode->GeometricTranslation.Get(), pNode->GeometricRotation.Get(), pNode->GeometricScaling.Get()); const double* pGeometricMat = fbxGeometricTransform; osg::Matrix osgGeometricTransform(pGeometricMat); if (geomType == GEOMETRY_RIG) { KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN); if (pSkin->GetClusterCount()) { KFbxXMatrix fbxTransformMatrix; pSkin->GetCluster(0)->GetTransformMatrix(fbxTransformMatrix); const double* pTransformMatrix = fbxTransformMatrix; osgGeometricTransform.postMult(osg::Matrix(pTransformMatrix)); } } osg::Node* pResult = pGeode; if (!osgGeometricTransform.isIdentity()) { osg::MatrixTransform* pMatTrans = new osg::MatrixTransform(osgGeometricTransform); pMatTrans->addChild(pGeode); pResult = pMatTrans; } if (geomType == GEOMETRY_RIG) { //Add the geometry to the skeleton ancestor of one of the bones. KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN); if (pSkin->GetClusterCount()) { osgAnimation::Skeleton* pSkeleton = getSkeleton( pSkin->GetCluster(0)->GetLink(), fbxSkeletons, skeletonMap); pSkeleton->addChild(pResult); return osgDB::ReaderWriter::ReadResult::FILE_LOADED; } } return osgDB::ReaderWriter::ReadResult(pResult); }
void readMeshTriangle(const KFbxMesh * fbxMesh, int i /*polygonIndex*/, int posInPoly0, int posInPoly1, int posInPoly2, int meshVertex0, int meshVertex1, int meshVertex2, FbxToOsgVertexMap& fbxToOsgVertMap, OsgToFbxNormalMap& osgToFbxNormMap, const KFbxVector4* pFbxVertices, const KFbxLayerElementNormal* pFbxNormals, const KFbxLayerElementUV* pFbxUVs_diffuse, const KFbxLayerElementUV* pFbxUVs_opacity, const KFbxLayerElementUV* pFbxUVs_emissive, const KFbxLayerElementVertexColor* pFbxColors, osg::Geometry* pGeometry, osg::Array* pVertices, osg::Array* pNormals, osg::Array* pTexCoords_diffuse, osg::Array* pTexCoords_opacity, osg::Array* pTexCoords_emissive, osg::Array* pColors) { int v0 = fbxMesh->GetPolygonVertex(i, posInPoly0), v1 = fbxMesh->GetPolygonVertex(i, posInPoly1), v2 = fbxMesh->GetPolygonVertex(i, posInPoly2); fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v0, GIPair(pGeometry, pVertices->getNumElements()))); fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v1, GIPair(pGeometry, pVertices->getNumElements() + 1))); fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v2, GIPair(pGeometry, pVertices->getNumElements() + 2))); addVec3ArrayElement(*pVertices, pFbxVertices[v0]); addVec3ArrayElement(*pVertices, pFbxVertices[v1]); addVec3ArrayElement(*pVertices, pFbxVertices[v2]); if (pNormals) { int n0 = getVertexIndex(pFbxNormals, fbxMesh, i, posInPoly0, meshVertex0); int n1 = getVertexIndex(pFbxNormals, fbxMesh, i, posInPoly1, meshVertex1); int n2 = getVertexIndex(pFbxNormals, fbxMesh, i, posInPoly2, meshVertex2); osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements()), n0)); osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements() + 1), n1)); osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements() + 2), n2)); addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n0)); addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n1)); addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n2)); } // add texture maps data (avoid duplicates)... if (pTexCoords_diffuse) { addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, posInPoly0, meshVertex0)); addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, posInPoly1, meshVertex1)); addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, posInPoly2, meshVertex2)); } if (pTexCoords_opacity && (pTexCoords_opacity != pTexCoords_diffuse)) { addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, posInPoly0, meshVertex0)); addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, posInPoly1, meshVertex1)); addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, posInPoly2, meshVertex2)); } // Only spherical reflection maps are supported (so do not add coordinates for the reflection map) if (pTexCoords_emissive && (pTexCoords_emissive != pTexCoords_opacity) && (pTexCoords_emissive != pTexCoords_diffuse)) { addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, posInPoly0, meshVertex0)); addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, posInPoly1, meshVertex1)); addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, posInPoly2, meshVertex2)); } // add more texture maps here... if (pColors) { addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, posInPoly0, meshVertex0)); addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, posInPoly1, meshVertex1)); addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, posInPoly2, meshVertex2)); } }