double GLC_Mesh::volume() { double resultVolume= 0.0; if (!m_MeshData.isEmpty()) { IndexList triangleIndex; QList<GLC_Material*> materials= materialSet().toList(); const int materialsCount= materials.count(); for (int i= 0; i < materialsCount; ++i) { GLC_uint materialId= materials.at(i)->id(); if (containsTriangles(0, materialId)) { triangleIndex.append(getTrianglesIndex(0, materialId).toList()); } if (containsStrips(0, materialId)) { triangleIndex.append(equivalentTrianglesIndexOfstripsIndex(0, materialId)); } if (containsFans(0, materialId)) { triangleIndex.append(equivalentTrianglesIndexOfFansIndex(0, materialId)); } } GLfloatVector vertices= m_MeshData.positionVector(); Q_ASSERT((triangleIndex.count() % 3) == 0); const int triangleCount= triangleIndex.count() / 3; for (int i= 0; i < triangleCount; ++i) { const int index= i * 3; const double v1x= vertices.at(triangleIndex.at(index) * 3); const double v1y= vertices.at(triangleIndex.at(index) * 3 + 1); const double v1z= vertices.at(triangleIndex.at(index) * 3 + 2); const double v2x= vertices.at(triangleIndex.at(index + 1) * 3); const double v2y= vertices.at(triangleIndex.at(index + 1) * 3 + 1); const double v2z= vertices.at(triangleIndex.at(index + 1) * 3 + 2); const double v3x= vertices.at(triangleIndex.at(index + 2) * 3); const double v3y= vertices.at(triangleIndex.at(index + 2) * 3 + 1); const double v3z= vertices.at(triangleIndex.at(index + 2) * 3 + 2); resultVolume+= ((v2y - v1y) * (v3z - v1z) - (v2z - v1z) * (v3y - v1y)) * (v1x + v2x + v3x); } resultVolume= resultVolume / 6.0; } return resultVolume; }
IndexList GLC_Mesh::equivalentTrianglesIndexOfFansIndex(int lodIndex, GLC_uint materialId) { IndexList trianglesIndex; if (containsFans(lodIndex, materialId)) { const QList<QVector<GLuint> > fanIndex= getFansIndex(lodIndex, materialId); const int fanCount= fanIndex.count(); for (int i= 0; i < fanCount; ++i) { const QVector<GLuint> currentFanIndex= fanIndex.at(i); const int size= currentFanIndex.size(); for (int j= 1; j < size - 1; ++j) { trianglesIndex.append(currentFanIndex.first()); trianglesIndex.append(currentFanIndex.at(j)); trianglesIndex.append(currentFanIndex.at(j + 1)); } } } return trianglesIndex; }
IndexList GLC_Mesh::equivalentTrianglesIndexOfstripsIndex(int lodIndex, GLC_uint materialId) { IndexList trianglesIndex; if (containsStrips(lodIndex, materialId)) { const QList<QVector<GLuint> > stripsIndex= getStripsIndex(lodIndex, materialId); const int stripCount= stripsIndex.count(); for (int i= 0; i < stripCount; ++i) { const QVector<GLuint> currentStripIndex= stripsIndex.at(i); trianglesIndex.append(currentStripIndex.at(0)); trianglesIndex.append(currentStripIndex.at(1)); trianglesIndex.append(currentStripIndex.at(2)); const int stripSize= currentStripIndex.size(); for (int j= 3; j < stripSize; ++j) { if ((j % 2) != 0) { trianglesIndex.append(currentStripIndex.at(j)); trianglesIndex.append(currentStripIndex.at(j - 1)); trianglesIndex.append(currentStripIndex.at(j - 2)); } else { trianglesIndex.append(currentStripIndex.at(j)); trianglesIndex.append(currentStripIndex.at(j - 2)); trianglesIndex.append(currentStripIndex.at(j - 1)); } } } } return trianglesIndex; }
IndexList GLC_Mesh::getEquivalentTrianglesStripsFansIndex(int lod, GLC_uint materialId) { IndexList subject; if (containsTriangles(lod, materialId)) { subject= getTrianglesIndex(lod, materialId).toList(); } if (containsStrips(lod, materialId)) { subject.append(equivalentTrianglesIndexOfstripsIndex(lod, materialId)); } if (containsFans(lod, materialId)) { subject.append(equivalentTrianglesIndexOfFansIndex(lod, materialId)); } Q_ASSERT((subject.count() % 3) == 0); return subject; }
void GLC_Cone::createMeshAndWire() { Q_ASSERT(GLC_Mesh::isEmpty()); Q_ASSERT(m_WireData.isEmpty()); // Create cosinus and sinus array according to the discretion and radius const int vertexNumber= m_Discret + 1; // Normals values QVector<float> cosNormalArray(vertexNumber); QVector<float> sinNormalArray(vertexNumber); QVector<float> cosArray(vertexNumber); QVector<float> sinArray(vertexNumber); const double angle= (2.0 * glc::PI) / static_cast<double>(m_Discret); // Normal Z value GLC_Vector3d normalVector(1.0, 0.0, 0.0); GLC_Matrix4x4 rotation(glc::Y_AXIS, -atan(m_Radius / m_Length)); normalVector= rotation * normalVector; const float normalZ= static_cast<float>(normalVector.z()); const double factor= normalVector.x(); // Normailsation factor for (int i= 0; i < vertexNumber; ++i) { const double cosValue= cos(static_cast<double>(i) * angle); const double sinValue= sin(static_cast<double>(i) * angle); cosNormalArray[i]= static_cast<GLfloat>(factor * cosValue); sinNormalArray[i]= static_cast<GLfloat>(factor * sinValue); cosArray[i]= static_cast<GLfloat>(m_Radius * cosValue); sinArray[i]= static_cast<GLfloat>(m_Radius * sinValue); } // Mesh Data GLfloatVector verticeVector; GLfloatVector normalsVector; GLfloatVector texelVector; // Wire Data GLfloatVector bottomWireData(vertexNumber * 3); const int size= vertexNumber * 3; verticeVector.resize(3 * size); normalsVector.resize(3 * size); texelVector.resize(2 * size); for (int i= 0; i < vertexNumber; ++i) { // Bottom Mesh verticeVector[3 * i]= cosArray[i]; verticeVector[3 * i + 1]= sinArray[i]; verticeVector[3 * i + 2]= 0.0f; normalsVector[3 * i]= cosNormalArray[i]; normalsVector[3 * i + 1]= sinNormalArray[i]; normalsVector[3 * i + 2]= normalZ; texelVector[2 * i]= static_cast<float>(i) / static_cast<float>(m_Discret); texelVector[2 * i + 1]= 0.0f; // Bottom Wire bottomWireData[3 * i]= cosArray[i]; bottomWireData[3 * i + 1]= sinArray[i]; bottomWireData[3 * i + 2]= 0.0f; // Top verticeVector[3 * i + 3 * vertexNumber]= 0.0f; verticeVector[3 * i + 1 + 3 * vertexNumber]= 0.0f; verticeVector[3 * i + 2 + 3 * vertexNumber]= static_cast<float>(m_Length); normalsVector[3 * i + 3 * vertexNumber]= cosNormalArray[i]; normalsVector[3 * i + 1 + 3 * vertexNumber]= sinNormalArray[i]; normalsVector[3 * i + 2 + 3 * vertexNumber]= normalZ; texelVector[2 * i + 2 * vertexNumber]= texelVector[i]; texelVector[2 * i + 1 + 2 * vertexNumber]= 1.0f; // Bottom Cap ends verticeVector[3 * i + 2 * 3 * vertexNumber]= cosArray[i]; verticeVector[3 * i + 1 + 2 * 3 * vertexNumber]= sinArray[i]; verticeVector[3 * i + 2 + 2 * 3 * vertexNumber]= 0.0f; normalsVector[3 * i + 2 * 3 * vertexNumber]= 0.0f; normalsVector[3 * i + 1 + 2 * 3 * vertexNumber]= 0.0f; normalsVector[3 * i + 2 + 2 * 3 * vertexNumber]= -1.0f; texelVector[2 * i + 2 * 2 * vertexNumber]= texelVector[i]; texelVector[2 * i + 1 + 2 * 2 * vertexNumber]= 0.0f; } // Add bulk data in to the mesh GLC_Mesh::addVertice(verticeVector); GLC_Mesh::addNormals(normalsVector); GLC_Mesh::addTexels(texelVector); // Add polyline to wire data GLC_Geometry::addPolyline(bottomWireData); // Set the material to use GLC_Material* pCylinderMaterial; if (hasMaterial()) { pCylinderMaterial= this->firstMaterial(); } else { pCylinderMaterial= new GLC_Material(); } IndexList circumferenceStrips; // Create the index for (int i= 0; i < vertexNumber; ++i) { circumferenceStrips.append(i + vertexNumber); circumferenceStrips.append(i); } addTrianglesStrip(pCylinderMaterial, circumferenceStrips); { IndexList bottomCap; IndexList topCap; int id1= 0; int id2= m_Discret - 1; const int size= m_Discret / 2 + (m_Discret % 2); for (int i= 0; i < size; ++i) { bottomCap.append(id1 + 2 * vertexNumber); bottomCap.append(id2 + 2 * vertexNumber); id1+= 1; id2-= 1; } addTrianglesStrip(pCylinderMaterial, bottomCap); } finish(); }
//! Create 3DRep from a Lib3dsNode GLC_3DRep GLC_3dsToWorld::create3DRep(Lib3dsMesh* p3dsMesh) { QString meshName(p3dsMesh->name); if (m_LoadedMeshes.contains(meshName)) { // This mesh as been already loaded QList<GLC_3DViewInstance*> instancesList(m_pWorld->collection()->instancesHandle()); GLC_3DViewInstance* pCurrentInstance= NULL; int currentIndex= -1; do { pCurrentInstance= instancesList[++currentIndex]; } while (pCurrentInstance->name() != meshName); // return an instance. //qDebug() << "instance"; return pCurrentInstance->representation(); } GLC_Mesh * pMesh= new GLC_Mesh(); pMesh->setName(p3dsMesh->name); // The mesh normals const int normalsNumber= p3dsMesh->faces * 3; Lib3dsVector *normalL= new Lib3dsVector[normalsNumber]; lib3ds_mesh_calculate_normals(p3dsMesh, normalL); // Position vector QVector<float> position(normalsNumber * 3); // Normal Vector QVector<float> normal(normalsNumber * 3); memcpy((void*)normal.data(), normalL, normalsNumber * 3 * sizeof(float)); // Texel Vector QVector<float> texel; if (p3dsMesh->texels > 0) { texel.resize(normalsNumber * 2); } int normalIndex= 0; for (unsigned int i= 0; i < p3dsMesh->faces; ++i) { IndexList triangleIndex; Lib3dsFace *p3dsFace=&p3dsMesh->faceL[i]; for (int i=0; i < 3; ++i) { triangleIndex.append(normalIndex); // Add vertex coordinate memcpy((void*)&(position.data()[normalIndex * 3]), &p3dsMesh->pointL[p3dsFace->points[i]], 3 * sizeof(float)); // Add texel if (p3dsMesh->texels > 0) { memcpy((void*)&(texel.data()[normalIndex * 2]), &p3dsMesh->texelL[p3dsFace->points[i]], 2 * sizeof(float)); } ++normalIndex; } // Load the material // The material current face index GLC_Material* pCurMaterial= NULL; if (p3dsFace->material[0]) { Lib3dsMaterial* p3dsMat=lib3ds_file_material_by_name(m_pLib3dsFile, p3dsFace->material); if (NULL != p3dsMat) { // Check it this material as already been loaded const QString materialName(p3dsFace->material); if (!m_Materials.contains(materialName)) { // Material not already loaded, load it loadMaterial(p3dsMat); } pCurMaterial= m_Materials.value(materialName); } } pMesh->addTriangles(pCurMaterial, triangleIndex); } pMesh->addVertice(position); pMesh->addNormals(normal); if (p3dsMesh->texels > 0) { pMesh->addTexels(texel); } // free normal memmory delete[] normalL; // Compute loading progress ++m_CurrentMeshNumber; m_CurrentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentMeshNumber) / m_NumberOfMeshes) * (100 - m_InitQuantumValue)) + m_InitQuantumValue; if (m_CurrentQuantumValue > m_PreviousQuantumValue) { emit currentQuantum(m_CurrentQuantumValue); } m_PreviousQuantumValue= m_CurrentQuantumValue; pMesh->finish(); return GLC_3DRep(pMesh); }