void FgGridTriangles::intersects(FgVect2F pos,vector<FgTriPoint> & ret) const { ret.clear(); FgVect2F gridCoord = m_clientToGridCoords * pos; if ((fgMinElem(gridCoord) < 0.0f) || (gridCoord[0] >= float(m_grid.width())) || (gridCoord[1] >= float(m_grid.height()))) return; FgVect2UI binIdx = FgVect2UI(gridCoord); const vector<uint> & bin = m_grid[binIdx]; for (size_t ii=0; ii<bin.size(); ++ii) { FgTriPoint tp; tp.triInd = bin[ii]; tp.pointInds = m_tris[bin[ii]]; FgOpt<FgVect3D> vbc = fgBarycentricCoords(pos, m_points[tp.pointInds[0]], m_points[tp.pointInds[1]], m_points[tp.pointInds[2]]); if (vbc.valid()) { tp.baryCoord = FgVect3F(vbc.val()); if (fgMinElem(tp.baryCoord) >= 0.0f) ret.push_back(tp); } } }
void FgGuiApi3d::markSurfPoint( FgVect2UI winSize, FgVect2I pos, FgMat44F toOics) // Transforms frustum to [-1,1] cube (depth & y inverted) { if (g_gg.dg.sinkNode(meshesN)) // feature disabled if node not modifiable return; vector<Fg3dMesh> meshes = g_gg.getVal(meshesN); const FgVertss & vertss = g_gg.getVal(vertssN); FgOpt<FgMeshesIntersect> vpt = fgMeshesIntersect(winSize,pos,toOics,meshes,vertss); if (vpt.valid()) { FgMeshesIntersect pt = vpt.val(); pt.surfPnt.label = g_gg.getVal(pointLabel).as_ascii(); vector<FgSurfPoint> & surfPoints = meshes[pt.meshIdx].surfaces[pt.surfIdx].surfPoints; if (!pt.surfPnt.label.empty()) { for (size_t ii=0; ii<surfPoints.size(); ++ii) { if (surfPoints[ii].label == pt.surfPnt.label) { // Replace SPs of same name: surfPoints[ii] = pt.surfPnt; g_gg.setVal(meshesN,meshes); return; } } } // Add new SP: surfPoints.push_back(pt.surfPnt); g_gg.setVal(meshesN,meshes); } }
static FgOpt<MeshesSurfPoint> intersect( FgVect2UI winSize, FgVect2I pos, FgMat44F toOics, // Transforms frustum to [-1,1] cube (depth & y inverted) const vector<Fg3dMesh> & meshes, const vector<FgVerts> & vertss) { MeshesSurfPoint ret; FgValid<float> minDepth; FgVect2D pnt(pos); FgMat32F oics(-1,1,1,-1,0,1); FgMat32F rcs(-0.5f,winSize[0]-0.5f,-0.5f,winSize[1]-0.5f,0,1); FgAffineCw3F oicsToRcs(oics,rcs); FgMat44F invXform = oicsToRcs.asAffine().asHomogenous() * toOics; for (size_t mm=0; mm<meshes.size(); ++mm) { const Fg3dMesh & mesh = meshes[mm]; const FgVerts & verts = vertss[mm]; FgVerts pvs(verts.size()); for (size_t ii=0; ii<pvs.size(); ++ii) { FgVect4F v = invXform * fgAsHomogVec(verts[ii]); pvs[ii] = v.subMatrix<3,1>(0,0) / v[3]; } for (size_t ss=0; ss<mesh.surfaces.size(); ++ss) { const Fg3dSurface & surf = mesh.surfaces[ss]; for (size_t tt=0; tt<surf.numTriEquivs(); ++tt) { FgVect3UI tri = surf.getTriEquiv(uint(tt)); FgVect3F t0 = pvs[tri[0]], t1 = pvs[tri[1]], t2 = pvs[tri[2]]; FgVect2D v0 = FgVect2D(t0.subMatrix<2,1>(0,0)), v1 = FgVect2D(t1.subMatrix<2,1>(0,0)), v2 = FgVect2D(t2.subMatrix<2,1>(0,0)); if (fgPointInTriangle(pnt,v0,v1,v2) == -1) { // CC winding FgOpt<FgVect3D> vbc = fgBarycentricCoords(pnt,v0,v1,v2); if (vbc.valid()) { FgVect3D bc = vbc.val(); // Depth value range for unclipped polys is [-1,1]. These correspond to the // negative inverse depth values of the frustum. // Only an approximation to the depth value but who cares: double dep = fgDot(bc,FgVect3D(t0[2],t1[2],t2[2])); if (!minDepth.valid() || (dep < minDepth.val())) { // OGL prj inverts depth minDepth = dep; ret.meshIdx = mm; ret.surfIdx = ss; ret.surfPnt.triEquivIdx = uint(tt); ret.surfPnt.weights = FgVect3F(bc); } } } } } } if (minDepth.valid()) return FgOpt<MeshesSurfPoint>(ret); return FgOpt<MeshesSurfPoint>(); }
void FgGuiApi3d::ctlClick(FgVect2UI winSize,FgVect2I pos,FgMat44F toOics) { const vector<Fg3dMesh> & meshes = g_gg.getVal(meshesN); const vector<FgVerts> & vertss = g_gg.getVal(vertssN); FgOpt<MeshesSurfPoint> vpt = intersect(winSize,pos,toOics,meshes,vertss); if (vpt.valid()) { MeshesSurfPoint pt = vpt.val(); uint mi = fgMaxIdx(pt.surfPnt.weights); lastCtlClick.meshIdx = pt.meshIdx; lastCtlClick.vertIdx = meshes[pt.meshIdx].surfaces[pt.surfIdx].getTriEquiv(pt.surfPnt.triEquivIdx)[mi]; } }
void FgGuiApi3d::markVertex( FgVect2UI winSize, FgVect2I pos, FgMat44F toOics) // Transforms frustum to [-1,1] cube (depth & y inverted) { if (g_gg.dg.sinkNode(meshesN)) // feature disabled if node not modifiable return; vector<Fg3dMesh> meshes = g_gg.getVal(meshesN); const FgVertss & vertss = g_gg.getVal(vertssN); FgOpt<FgMeshesIntersect> vpt = fgMeshesIntersect(winSize,pos,toOics,meshes,vertss); if (vpt.valid()) { FgMeshesIntersect pt = vpt.val(); uint facetIdx = fgMaxIdx(pt.surfPnt.weights); Fg3dMesh & mesh = meshes[pt.meshIdx]; uint vertIdx = mesh.surfaces[pt.surfIdx].getTriEquiv(pt.surfPnt.triEquivIdx)[facetIdx]; size_t vertMarkMode = g_gg.getVal(vertMarkModeN); if (vertMarkMode == 0) { if (!fgContains(mesh.markedVerts,vertIdx)) { mesh.markedVerts.push_back(FgMarkedVert(vertIdx)); g_gg.setVal(meshesN,meshes); } } else if (vertMarkMode < 3) { const FgVerts & verts = vertss[pt.meshIdx]; vector<FgVect3UI> tris = mesh.getTriEquivs().vertInds; Fg3dTopology topo(verts,tris); set<uint> seam; if (vertMarkMode == 1) seam = topo.seamContaining(vertIdx); else { Fg3dSurface surf; surf.tris.vertInds = tris; vector<FgBool> done(verts.size(),false); seam = topo.traceFold(fgNormals(fgSvec(surf),verts),done,vertIdx); } for (set<uint>::const_iterator it=seam.begin(); it != seam.end(); ++it) if (!fgContains(mesh.markedVerts,*it)) mesh.markedVerts.push_back(FgMarkedVert(*it)); if (!seam.empty()) g_gg.setVal(meshesN,meshes); } } }