bool QGLWindow::showImage(const cv::Mat &image, const SFace &face) { // get the detected face position m_face = SFace(face); // keep original image ratio m_ratio = static_cast<float>(image.cols)/static_cast<float>(image.rows); // convert the image in a Qt/OpenGL one if (image.channels() == 3) { m_renderedImage = QImage((const unsigned char*)image.data, image.cols, image.rows, static_cast<int>(image.step), QImage::Format_RGB888); } else if (image.channels() == 1) { m_renderedImage = QImage((const unsigned char*)image.data, image.cols, image.rows, static_cast<int>(image.step), QImage::Format_Indexed8); } else return false; // impossible to convert the image // conversion needs to mirror back the image m_renderedImage = m_renderedImage.mirrored(); updateScene(); return true; }
//---------------------------------------------------------------------------------------------- // Public : OnFace //---------------------------------------------------------------------------------------------- void CObjMesh::OnFace( int *pVertexCoords, int *pTexCoords, int *pNormals, int nNumCoords ) { for ( int nIndex = 0; nIndex < nNumCoords; nIndex++ ) { // Handle polygons (ie: 4 vertices implies 2 triangles, 5 vertices implies 3 triangles, etc) // This part effectively triangulates the face if ( nIndex >= 2 ) { //int nVertexCoord, nTexCoord, nNormal; // Add a triangle m_pFaces.push_back(SFace(pVertexCoords[0] - 1, pTexCoords[0] - 1, pNormals[0] - 1)); m_pFaces.push_back(SFace(pVertexCoords[nIndex - 1] - 1, pTexCoords[nIndex - 1] - 1, pNormals[nIndex - 1] - 1)); m_pFaces.push_back(SFace(pVertexCoords[nIndex] - 1, pTexCoords[nIndex] - 1, pNormals[nIndex] - 1)); } } }
//------------------------------------------------------------------------------ void CModels::createRect() { rect.vertices.resize(NHudRect::VERTICES_COUNT); rect.vertices[0].position = QVector3D( 0.5, 0.5, 0.0); rect.vertices[1].position = QVector3D(-0.5, 0.5, 0.0); rect.vertices[2].position = QVector3D(-0.5, -0.5, 0.0); rect.vertices[3].position = QVector3D( 0.5, -0.5, 0.0); rect.vertices[0].texCoord = QVector2D(1.0, 0.0); rect.vertices[1].texCoord = QVector2D(0.0, 0.0); rect.vertices[2].texCoord = QVector2D(0.0, 1.0); rect.vertices[3].texCoord = QVector2D(1.0, 1.0); rect.faces.push_back(SFaces()); SFaces *faces = &rect.faces.back(); faces->faces.resize(NHudRect::FACE_BLOCK_SIZE); faces->faces[0] = SFace(1, 0, 2); faces->faces[1] = SFace(3, 2, 0); createVbo(&rect); }
//------------------------------------------------------------------------------ void CWater::updateVirtual() { model.materials.clear(); model.meshes.clear(); // ground model.materials.push_back(SMaterial(context->getShaders()->getShaderProgram(NShader::PROGRAM_TERRAIN), NULL, NULL, NULL, water.detailGroundTexture, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); model.meshes.push_back(SMesh()); SMesh *mesh = &model.meshes.back(); mesh->transformation = SMatrix::composeTransformation(mesh->position, mesh->rotation, mesh->scale); mesh->faces.push_back(SFaces(&model.materials.back())); SFaces *faces = &mesh->faces.back(); faces->material = &model.materials.back(); mesh->vertices.resize(NWater::VERTICES_COUNT); mesh->vertices[0].position = QVector3D(-0.5, water.depth, 0.5); mesh->vertices[1].position = QVector3D( 0.5, water.depth, 0.5); mesh->vertices[2].position = QVector3D(-0.5, water.depth, -0.5); mesh->vertices[3].position = QVector3D( 0.5, water.depth, -0.5); mesh->vertices[0].texCoord = QVector2D(-0.0, 100.0); mesh->vertices[1].texCoord = QVector2D(-100.0, 100.0); mesh->vertices[2].texCoord = QVector2D(-0.0, 0.0); mesh->vertices[3].texCoord = QVector2D(-100.0, 0.0); for(uint32 i = 0; i < NWater::VERTICES_COUNT; i++) { mesh->vertices[i].color = water.color.toVector3D() * water.color.w(); mesh->vertices[i].color2 = QVector3D(1.0, 0.0, 0.0); } faces->faces.resize(NWater::FACE_BLOCK_SIZE); faces->faces[0] = SFace(0, 1, 2); faces->faces[1] = SFace(2, 1, 3); // level model.materials.push_back(SMaterial(context->getShaders()->getShaderProgram(NShader::PROGRAM_WATER), NULL, water.windTexture, NULL, water.detailTexture, water.environmentTexture, NULL, NULL, NULL, NULL, NULL, NULL, QVector<int32>(), true, true)); model.meshes.push_back(SMesh()); mesh = &model.meshes.back(); mesh->transformation = SMatrix::composeTransformation(mesh->position, mesh->rotation, mesh->scale); mesh->faces.push_back(SFaces(&model.materials.back())); faces = &mesh->faces.back(); faces->material = &model.materials.back(); mesh->vertices.resize(NWater::VERTICES_COUNT); mesh->vertices[0].position = QVector3D(-0.5, 0.0, 0.5); mesh->vertices[1].position = QVector3D( 0.5, 0.0, 0.5); mesh->vertices[2].position = QVector3D(-0.5, 0.0, -0.5); mesh->vertices[3].position = QVector3D( 0.5, 0.0, -0.5); mesh->vertices[0].texCoord = QVector2D(-0.0, 100.0); mesh->vertices[1].texCoord = QVector2D(-100.0, 100.0); mesh->vertices[2].texCoord = QVector2D(-0.0, 0.0); mesh->vertices[3].texCoord = QVector2D(-100.0, 0.0); faces->faces.resize(NWater::FACE_BLOCK_SIZE * 2); faces->faces[0] = SFace(0, 1, 2); faces->faces[1] = SFace(2, 1, 3); // under level model.materials.push_back(SMaterial(context->getShaders()->getShaderProgram(NShader::PROGRAM_UNDER_WATER), NULL, water.windTexture, NULL, water.detailTexture, water.environmentTexture, NULL, NULL, NULL, NULL, NULL, NULL, QVector<int32>(), true, true)); model.meshes.push_back(model.meshes.back()); mesh = &model.meshes.back(); faces = &mesh->faces.back(); faces->material = &model.materials.back(); faces->faces[0] = SFace(1, 0, 2); faces->faces[1] = SFace(1, 2, 3); }
//------------------------------------------------------------------------------ void CTerrain::updateVirtual() { const uint32 stepX = 1 << terrain.stepX; // edges count (vertices: step + 1) const uint32 stepZ = 1 << terrain.stepZ; const uint32 divStepX = 1 << terrain.divStepX; // count of chunks const uint32 divStepZ = 1 << terrain.divStepZ; const uint32 stepMeshX = stepX / divStepX; // number of edges in chunk const uint32 stepMeshZ = stepZ / divStepZ; QVector<SVertex> vx((stepX + 1) * (stepZ + 1)); QVector<float> heightMap((stepX + 1) * (stepZ + 1), 0.0f); QVector<bool> usedHeightMap((stepX + 1) * (stepZ + 1), false); QVector<int32> heightMapLayer((stepX + 1) * (stepZ + 1), -1); float depth = 1.0f; srand(terrain.seed); // compute heightmap if(!terrain.landBorder) { heightMap[0] = rndHeight(); heightMap[stepX] = rndHeight(); heightMap[(stepX + 1) * stepZ] = rndHeight(); heightMap[(stepX + 1) * stepZ + stepX] = rndHeight(); } usedHeightMap[0] = true; usedHeightMap[stepX] = true; usedHeightMap[(stepX + 1) * stepZ] = true; usedHeightMap[(stepX + 1) * stepZ + stepX] = true; fractalGrid(&heightMap[0], &usedHeightMap[0], stepX, stepZ, stepX, stepZ, 0, depth); // compute positions float x = 0.0f; float z = 0.0f; const float xInc = 1.0f / stepX; const float zInc = 1.0f / stepZ; for(uint32 i = 0; i <= stepX; i++, x += xInc) { for(uint32 j = 0; j <= stepZ; j++, z += zInc) { const uint32 k = ((stepX + 1) * i + j); vx[k].position = QVector3D(x - 0.5f, heightMap[k] * terrain.heightMultiplier, z - 0.5f); vx[k].normal = QVector3D(0.0, 1.0, 0.0); vx[k].texCoord = QVector2D(-x * 10, z * 10); vx[k].color = QVector3D(1.0, 0.0, 0.0); vx[k].color2 = QVector3D(0.0, 0.0, 0.0); } z = 0.0f; } // compute normals, tangents, bitangents for(int32 v = 0; v < vx.size(); v++) { uint32 x = v % (stepX + 1); uint32 z = v / (stepX + 1); if((x > 0) && (x < stepX) && (z > 0) && (z < stepZ)) { QVector3D &vC = vx[v].position; QVector3D &vL = vx[v - 1].position; QVector3D &vR = vx[v + 1].position; QVector3D &vT = vx[v - stepX - 1].position; QVector3D &vB = vx[v + stepX + 1].position; vx[v].normal = QVector3D::normal(vC, vL, vT); vx[v].normal += QVector3D::normal(vC, vT, vR); vx[v].normal += QVector3D::normal(vC, vR, vB); vx[v].normal += QVector3D::normal(vC, vB, vL); vx[v].normal.normalize(); vx[v].normalTangent = QVector3D(vx[v].normal.y(), -vx[v].normal.x(), -vx[v].normal.z()); vx[v].normalBitangent = QVector3D(-vx[v].normal.x(), -vx[v].normal.z(), vx[v].normal.y()); } } // compute colors by layers for(int32 v = 0; v < vx.size(); v++) { for(int32 l = 0; l != terrain.layers.size(); l++) { const SMaterialLayer *layer = &terrain.layers[l]; if(!(((layer->useHeightLimit) && ((vx[v].position.y() < layer->minHeight) || (vx[v].position.y() > layer->maxHeight))) || ((layer->useSlopeLimit) && (((1.0f - vx[v].normal.y()) < layer->minSlope) || ((1.0f - vx[v].normal.y()) > layer->maxSlope))))) { vx[v].color = layer->color.toVector3D() * layer->color.w(); heightMapLayer[v] = l; } } } /*for(int32 v = 0; v < vx.size(); v++) qDebug(QString("y %1, x %2: %3").arg(v / (stepX + 1)).arg(v % (stepX + 1)).arg(heightMapLayer[v]).toStdString().c_str());*/ // divide to meshes, fill model meshes /*model.materials.clear(); model.materials.push_back(SMaterial(context->getShaders()->getShaderProgram(NShader::PROGRAM_TERRAIN), context->getMaps()->addMap(SMap(":/maps/data/maps/rocks00n.png")), context->getMaps()->addMap(SMap(":/maps/data/maps/rocks00n.png")), context->getMaps()->addMap(SMap(":/maps/data/maps/rocks00n.png"))));*/ /*model.meshes.clear(); for(uint32 m = 0; m < (divStepX * divStepZ); m++) { model.meshes.push_back(SMesh()); SMesh *mesh = &model.meshes.back(); mesh->transformation = SMatrix::composeTransformation(mesh->position, mesh->rotation, mesh->scale); mesh->faces.push_back(SFaces()); SFaces *faces = &mesh->faces.back(); mesh->vertices.resize((stepMeshX + 1) * (stepMeshZ + 1)); faces->faces.resize(stepMeshX * stepMeshZ * NTerrain::FACE_BLOCK_SIZE); uint32 offset = (m / divStepZ) * stepMeshZ * (stepX + 1) + (m % divStepX) * stepMeshX; uint32 mCol2 = 0; for(uint32 mRow = 0; mRow <= stepMeshZ; mRow++, offset += (stepX + 1)) { for(uint32 mCol = 0; mCol <= stepMeshX; mCol++, mCol2++) { mesh->vertices[mCol2] = vx[offset + mCol]; if((mRow == stepMeshZ) || (mCol == stepMeshX)) mesh->vertices[mCol2].color = QVector3D(0.8, 0.2, 0.2); } } for(uint32 i = 0; i < stepMeshX; i++) { for(uint32 j = 0; j < stepMeshZ; j++) { const uint32 k = (stepMeshX * i + j) * NTerrain::FACE_BLOCK_SIZE; const uint32 l0 = (stepMeshX + 1) * i + j + 0; const uint32 l1 = (stepMeshX + 1) * i + j + 1; const uint32 l2 = (stepMeshX + 1) * (i + 1) + j + 0; const uint32 l3 = (stepMeshX + 1) * (i + 1) + j + 1; faces->faces[k + 0] = SFace(l0, l1, l2); faces->faces[k + 1] = SFace(l2, l1, l3); } } }*/ model.materials.clear(); const CMap *noMap = context->getMaps()->getMap(NMap::DEFAULT_NORMAL); // default map model.meshes.clear(); for(uint32 gz = 0; gz < divStepZ; gz++) { for(uint32 gx = 0; gx < divStepX; gx++) { // sub mesh //const uint32 groupBase = gz * divStepZ + gx; const uint32 vxGroupBase = gz * stepMeshZ * (stepX + 1) + gx * stepMeshX; //qDebug("new mesh"); model.meshes.push_back(SMesh()); SMesh *mesh = &model.meshes.back(); mesh->transformation = SMatrix::composeTransformation(mesh->position, mesh->rotation, mesh->scale); for(uint32 ez = 0; ez < stepMeshZ; ez++) { for(uint32 ex = 0; ex < stepMeshX; ex++) { // two faces block const uint32 vx0 = vxGroupBase + ez * (stepX + 1) + ex; const uint32 vx1 = vx0 + 1; const uint32 vx2 = vx0 + (stepX + 1); const uint32 vx3 = vx2 + 1; for(uint8 v = 0; v < NTerrain::FACE_BLOCK_SIZE; v++) { // one face const uint32 face[NModel::FACE_SIZE] = { (!v) ? vx0 : vx2, (!v) ? vx1 : vx1, (!v) ? vx2 : vx3 }; // material signature QSet<int32> faceSet; faceSet.insert(heightMapLayer[face[0]]); faceSet.insert(heightMapLayer[face[1]]); faceSet.insert(heightMapLayer[face[2]]); QVector<int32> faceMats = faceSet.toList().toVector(); qSort(faceMats.begin(), faceMats.end()); //qDebug(QString("%1 %2 %3 : %4 %5 %6 : %7").arg(face[0]).arg(face[1]).arg(face[2]).arg(heightMapLayer[face[0]]).arg(heightMapLayer[face[1]]).arg(heightMapLayer[face[2]]).arg(faceMats.size()).toStdString().c_str()); /*for(int32 i : faceMats) qDebug(QString("%1").arg(i).toStdString().c_str());*/ SFaces *faces = NULL; for(auto f = mesh->faces.begin(); f != mesh->faces.end(); f++) { // find faces group by material signature if(!f->material) { //qDebug("chyba mat chybi"); break; } else if(f->material->layerVx == faceMats) { //qDebug("nasel"); faces = &(*f); break; } } if(!faces) { SMaterial *material = NULL; for(auto m = model.materials.begin(); m != model.materials.end(); m++) { // find previous used material if(m->layerVx == faceMats) { //qDebug("nenasel, ale predchozí mat ano"); material = &(*m); break; } } if(!material) { //qDebug("nenasel"); const CMap *maps[NModel::FACE_SIZE]; for(int32 i = 0; static_cast<uint32>(i) < NModel::FACE_SIZE; i++) { maps[i] = (faceMats.size() > i) ? ((faceMats[i] != -1) ? terrain.layers[faceMats[i]].detailTexture : noMap) : NULL; /*if(maps[i]) qDebug(maps[i]->getMap()->file.toStdString().c_str()); else qDebug("no map");*/ } model.materials.push_back(SMaterial(context->getShaders()->getShaderProgram(NShader::PROGRAM_TERRAIN), NULL, NULL, NULL, maps[0], NULL, NULL, NULL, NULL, NULL, maps[1], maps[2], faceMats)); material = &model.materials.back(); } mesh->faces.push_back(SFaces(material)); faces = &mesh->faces.back(); } uint16 newFace[NModel::FACE_SIZE]; SVertex newVx[NModel::FACE_SIZE] = { vx[face[0]], vx[face[1]], vx[face[2]] }; for(uint32 i = 0; i < NModel::FACE_SIZE; i++) { // set texture using multiplier if(heightMapLayer[face[i]] == faceMats[0]) newVx[i].color2.setX(1.0f); else if(heightMapLayer[face[i]] == faceMats[1]) newVx[i].color2.setY(1.0f); else if(heightMapLayer[face[i]] == faceMats[2]) newVx[i].color2.setZ(1.0f); //qDebug(QString("face %1: %2 %3 %4").arg(i).arg(newVx[i].color2.x()).arg(newVx[i].color2.y()).arg(newVx[i].color2.z()).toStdString().c_str()); bool found = false; for(int32 v = 0; v < mesh->vertices.size(); v++) { // find same vertex if((mesh->vertices[v].position == newVx[i].position) && (mesh->vertices[v].color2 == newVx[i].color2)) { //qDebug("same vx found"); found = true; newFace[i] = v; break; } } if(!found) { //qDebug("same vx not found"); newFace[i] = mesh->vertices.size(); mesh->vertices.push_back(newVx[i]); } } faces->faces.push_back(SFace(newFace[0], newFace[1], newFace[2])); } } } //qDebug(QString("-------- face groups: %1").arg(mesh->faces.size()).toStdString().c_str()); } } //qDebug(QString("-------- meshes: %1").arg(model.meshes.size()).toStdString().c_str()); }