void do_bump_map( //const eiScalar i_bumpValue, //const eiScalar i_bumpDepth, const normal& i_normalCamera, normal& o_outNormal ) { eiScalar LOW = -1.0f, HEIGHT=1.0f; eiScalar offset = clamp(bumpValue(), LOW, HEIGHT) * abs(bumpDepth()); //Du_offset=d(offset)/du, Dv_offset=d(offset)/dv eiScalar Du_offset, Dv_offset; eiScalar DbumpValue_du, DbumpValue_dv; eiScalar DbumpDepth_du, DbumpDepth_dv; Du(bumpValue, DbumpValue_du); Dv(bumpValue, DbumpValue_dv); Du(bumpDepth, DbumpDepth_du); Dv(bumpDepth, DbumpDepth_dv); Du_offset = D_clamp(bumpValue(), LOW,HEIGHT) * DbumpValue_du * abs(bumpDepth()) + clamp(bumpValue(), LOW,HEIGHT) * D_abs(bumpDepth()) * DbumpDepth_du; Dv_offset = D_clamp(bumpValue(), LOW,HEIGHT) * DbumpValue_dv * abs(bumpDepth()) + clamp(bumpValue(), LOW,HEIGHT) * D_abs(bumpDepth()) * DbumpDepth_dv; /* These scale factors are a bit experimental. The constant is to roughly match maya's bump mapping. The part about dPdu/dPdv ensures that the bump's scale does not depend on the underlying parametrization of the patch (the use of Du and Dv below introduce that) and that it happens in object space. Note that maya's handling of object space appears to be slightly broken since an enlarged sphere will have the same bump as a sphere with its control points moved outwards by a scale, somehow. */ matrix toLocal = to_object(); eiScalar uscale = 1.0f / len(&(dPdu() * toLocal)) * 6.0f; eiScalar vscale = 1.0f / len(&(dPdv() * toLocal)) * 6.0f; vector gu = vector(1.0f, 0.0f, Du_offset * uscale); vector gv = vector(0.0f, 1.0f, Dv_offset * vscale); normal n = normal(gu ^ gv); vector basisz = normalize(i_normalCamera); vector basisx = normalize((basisz ^ dPdu()) ^ basisz); vector basisy = normalize((basisz ^ dPdv()) ^ basisz); o_outNormal = normal( n.x * basisx + n.y * basisy + n.z * basisz); o_outNormal = normalize(o_outNormal); }
void OpticalFlow::baseCalculate(cv::Mat& Im1, cv::Mat& Im2, flowUV& UV, const OpticalFlowParams& params){ int rows = Im1.rows; int cols = Im1.cols; FlowOperator flowOp(rows, cols); FArray X0(2 * rows * cols, false); FArray dUdV(2 * rows * cols, true, 0); cv::Mat Ix1(rows, cols, OPTFLOW_TYPE); cv::Mat Iy1(rows, cols, OPTFLOW_TYPE); cv::Mat Ix(rows, cols, OPTFLOW_TYPE); cv::Mat Iy(rows, cols, OPTFLOW_TYPE); getDXsCV(Im1, Ix1, Iy1); for (int i = 0; i < params.getIters(); ++i){ cv::Mat Ix2(rows, cols, OPTFLOW_TYPE); cv::Mat Iy2(rows, cols, OPTFLOW_TYPE); cv::Mat It(rows, cols, OPTFLOW_TYPE); cv::Mat im2Warpped(rows, cols, Im1.type()); WarpImage(Im2, UV.getU(), UV.getV(), im2Warpped); getDXsCV(im2Warpped, Ix2, Iy2); Ix = params.getWeightedDeriveFactor() * (Ix1 + Ix2); Iy = params.getWeightedDeriveFactor() * (Iy1 + Iy2); cv::subtract(im2Warpped, Im1, It); if (params.getDisplayDerivativs()){ cv::imshow("Derivative Ix", Ix); cv::imshow("Derivative Iy", Iy); cv::waitKey(1); } cv::Mat Du(rows, cols, OPTFLOW_TYPE, cv::Scalar(0)); cv::Mat Dv(rows, cols, OPTFLOW_TYPE, cv::Scalar(0)); for (int j = 0; j < params.getLinearIters(); ++j){ #if OPTFLOW_VERBOSE cout << "solving Ax=b with SOR "; clock_t start = std::clock(); #endif flowOp.construct(UV, Du, Dv, Ix, Iy, It, params); memcpy(X0.ptr, UV.getU().data, rows * cols * sizeof(float)); memcpy(X0.ptr + (rows * cols), UV.getV().data, rows * cols * sizeof(float)); //UtilsDebug::printCRSSparseMat(flowOp.getA(), "aaaa.txt"); if (params.getCheckResidualTolerance()){ LinearSolver::sparseMatSor(flowOp.getA(), X0 ,dUdV, flowOp.getb(), params.getOverRelaxation(), params.getSorIters(), params.getResidualTolerance()); }else{ //LinearSolver::multigrid(10,10,flowOp.getA(),flowOp.getb(), params.getResidualTolerance(), dUdV, 20, 20, LinearSolver::vCycle); LinearSolver::sparseMatSorNoResidual(flowOp.getA(), X0 ,dUdV, flowOp.getb(), params.getOverRelaxation(), params.getSorIters()); } #if OPTFLOW_VERBOSE std::cout<<" --- "<< (std::clock() - start) / (double)CLOCKS_PER_SEC <<'\n'; #endif #if OPTFLOW_DEBUG for(int i = 0; i < dUdV.size(); ++i){ if (!(dUdV.ptr[i] == dUdV.ptr[i])){ cout << "ERROR - NAN"; } } #endif UtilsMat::clamp(dUdV, -1, 1); memcpy(Du.data, dUdV.ptr, rows * cols * sizeof(float)); memcpy(Dv.data, dUdV.ptr + (rows * cols), rows * cols * sizeof(float)); flowUV UV0(UV); UV.getU() += Du; UV.getV() += Dv; cv::Mat tmpU, tmpV; UV.getU().copyTo(tmpU); UV.getV().copyTo(tmpV); WeightedMedianFilter::computeMedianFilter(UV.getU(), UV.getV(), Im1, Im2, params.getMedianFilterRadius()); Du = UV.getU() - UV0.getU(); Dv = UV.getV() - UV0.getV(); UV0.getU().copyTo(UV.getU()); UV0.getV().copyTo(UV.getV()); UV0.getU() += Du; UV0.getV() += Dv; if (params.isDisplay()) UtilsFlow::DrawFlow(UV0.getU(), UV0.getV(), "Flow"); } UV.getU() += Du; UV.getV() += Dv; } }
NurbsSurfaceSP<T,N> NurbsSurfaceSP<T,N>::generateParallel(T d) const { NurbsSurfaceSP<T,N> p(*this) ; Vector< Point_nD<T,N> > offset(this->P.rows()*this->P.cols()) ; Vector<T> ur(this->P.rows()*this->P.cols()) ; Vector<T> vr(this->P.rows()*this->P.cols()) ; Vector_INT Du(this->P.rows()*this->P.cols()) ; Vector_INT Dv(this->P.rows()*this->P.cols()) ; Du.reset(0) ; Dv.reset(0) ; int i,j,no ; no = 0 ; for(i=0;i<this->P.rows();++i) for(j=0;j<this->P.cols();++j){ Point_nD<T,N> norm ; norm = normal(maxAtU_[i],maxAtV_[j]) ; if(norm.x() == T(0) && norm.y() == T(0) && norm.z() == T(0)){ // normal is undefined there... // compute an average and find a suitable normal const T delta = 0.00001 ; // must handle the corner cases int ok = 0 ; if(i==0 && j==0){ norm = normal(maxAtU_[i]+delta,maxAtV_[j]) ; norm += normal(maxAtU_[i],maxAtV_[j]+delta) ; norm /= T(2) ; ok = 1 ; } if(i==this->P.rows()-1 && j==this->P.cols()-1){ norm = normal(maxAtU_[i]-delta,maxAtV_[j]) ; norm += normal(maxAtU_[i],maxAtV_[j]-delta) ; norm /= T(2) ; ok = 1 ; } if(i==0 && j==this->P.cols()-1){ norm = normal(maxAtU_[i]-delta,maxAtV_[j]) ; norm += normal(maxAtU_[i],maxAtV_[j]+delta) ; norm /= T(2) ; ok = 1 ; } if(i==this->P.rows()-1 && j==0){ norm = normal(maxAtU_[i]-delta,maxAtV_[j]) ; norm += normal(maxAtU_[i],maxAtV_[j]+delta) ; norm /= T(2) ; ok = 1 ; } if(!ok){ T nt = 1.0 ; while(norm.x() == T(0) && norm.y() == T(0) && norm.z() == T(0)){ if( nt*d >(this->U[this->U.n()-1]-this->U[0])){ #ifdef USE_EXCEPTION throw NurbsComputationError(); #else Error error("generateParallel"); error << "Can't compute a normal point.\n" ; error.fatal() ; #endif } T u1,u2,v1,v2 ; if(i==0 || i==this->P.rows()-1){ u1 = u2 = maxAtU_[i] ; v1 = maxAtV_[j]+ nt*delta ; v2 = maxAtV_[j]- nt*delta ; if(v1>this->V[this->V.n()-1]) v1 = this->V[this->V.n()-1] ; if(v2<this->V[0]) v2 = this->V[0] ; norm = normal(u1,v1); norm += normal(u2,v2) ; norm /= 2 ; } else{ u1 = maxAtU_[i]- nt*delta ; u2 = maxAtU_[i]+ nt*delta ; v1 = v2 = maxAtV_[j] ; if(u1 < this->U[0]) u1 = this->U[0] ; if(u2 > this->U[this->U.n()-1]) u2 = this->U[this->U.n()-1] ; T u3,v3 ; u3 = maxAtU_[i] ; if(j==0) v3 = maxAtV_[j]+ nt*delta ; else v3 = maxAtV_[j]- nt*delta ; if(v3<this->V[0]) v3 = this->V[0] ; if(v3>this->V[this->V.n()-1]) v3 = this->V[this->V.n()-1] ; norm = normal(u1,v1); norm += normal(u2,v2) ; norm += normal(u3,v3) ; norm /= 3 ; } nt *= 10.0 ; } } } Point_nD<T,N> unit = norm.unitLength(); unit *= d ; //HPoint_nD<T,N> offset(unit ) ; //offset.w() = 0.0 ; //p.modSurfCPby(i,j,offset) ; Du[no] = i ; Dv[no] = j ; offset[no] = unit ; ++no ; } p.movePoint(maxAtU_,maxAtV_,offset,Du,Dv) ; return p ; }