void CircleShape::Draw(ref_ptr<dp::Batcher> batcher, ref_ptr<dp::TextureManager> textures) const { int const TriangleCount = 20; double const etalonSector = (2.0 * math::pi) / static_cast<double>(TriangleCount); dp::TextureManager::ColorRegion region; textures->GetColorRegion(m_params.m_color, region); glsl::vec2 colorPoint(glsl::ToVec2(region.GetTexRect().Center())); buffer_vector<gpu::SolidTexturingVertex, 22> vertexes; vertexes.push_back(gpu::SolidTexturingVertex { glsl::vec4(glsl::ToVec2(m_pt), m_params.m_depth, 0.0f), glsl::vec2(0.0f, 0.0f), colorPoint }); m2::PointD startNormal(0.0f, m_params.m_radius); for (size_t i = 0; i < TriangleCount + 1; ++i) { m2::PointD rotatedNormal = m2::Rotate(startNormal, (i) * etalonSector); vertexes.push_back(gpu::SolidTexturingVertex { glsl::vec4(glsl::ToVec2(m_pt), m_params.m_depth, 0.0f), glsl::ToVec2(rotatedNormal), colorPoint }); } dp::GLState state(gpu::TEXTURING_PROGRAM, dp::GLState::OverlayLayer); state.SetColorTexture(region.GetTexture()); double handleSize = 2 * m_params.m_radius; drape_ptr<dp::OverlayHandle> overlay = make_unique_dp<dp::SquareHandle>(m_params.m_id, dp::Center, m_pt, m2::PointD(handleSize, handleSize), GetOverlayPriority(), ""); dp::AttributeProvider provider(1, TriangleCount + 2); provider.InitStream(0, gpu::SolidTexturingVertex::GetBindingInfo(), make_ref(vertexes.data())); batcher->InsertTriangleFan(state, make_ref(&provider), move(overlay)); }
void gouradFill(int s, int e, int y, Edge line1, Edge line2, int oct, int plane, Surface ob, Point view, float* buffer) { Vector3 tempcolor(1,1,1); Vector3 inten_left, inten_right, i1, i2, color; float y1, y2, x1, x2; int start, end; if (s > e) { start = e; end = s; if (plane == XY) { y1 = flatlist[oct].pl[line2.p1 - 1].y; y2 = flatlist[oct].pl[line2.p2 - 1].y; } else if (plane == XZ) { y1 = flatlist[oct].pl[line2.p1 - 1].z; y2 = flatlist[oct].pl[line2.p2 - 1].z; } else if (plane == YZ) { y1 = flatlist[oct].pl[line2.p1 - 1].z; y2 = flatlist[oct].pl[line2.p2 - 1].z; } i1 = flatlist[oct].pl[line2.p1 - 1].ip; i2 = flatlist[oct].pl[line2.p2 - 1].ip; inten_left = i1 * ((y - y2) / (y1 - y2)) + i2 * ((y - y1) / (y2 - y1)); //if (oct == 1) cout << i1 << " " << i2 << " "; if (plane == XY) { y1 = flatlist[oct].pl[line1.p1 - 1].y; y2 = flatlist[oct].pl[line1.p2 - 1].y; } else if (plane == XZ) { y1 = flatlist[oct].pl[line1.p1 - 1].z; y2 = flatlist[oct].pl[line1.p2 - 1].z; } else if (plane == YZ) { y1 = flatlist[oct].pl[line1.p1 - 1].z; y2 = flatlist[oct].pl[line1.p2 - 1].z; } i1 = flatlist[oct].pl[line1.p1 - 1].ip; i2 = flatlist[oct].pl[line1.p2 - 1].ip; inten_right = i1 * ((y - y2) / (y1 - y2)) + i2 * ((y - y1) / (y2 - y1)); } else { start = s; end = e; if (plane == XY) { y1 = flatlist[oct].pl[line1.p1 - 1].y; y2 = flatlist[oct].pl[line1.p2 - 1].y; } else if (plane == XZ) { y1 = flatlist[oct].pl[line1.p1 - 1].z; y2 = flatlist[oct].pl[line1.p2 - 1].z; } else if (plane == YZ) { y1 = flatlist[oct].pl[line1.p1 - 1].z; y2 = flatlist[oct].pl[line1.p2 - 1].z; } i1 = flatlist[oct].pl[line1.p1 - 1].ip; i2 = flatlist[oct].pl[line1.p2 - 1].ip; inten_left = i1 * ((y - y2) / (y1 - y2)) + i2 * ((y - y1) / (y2 - y1)); if (plane == XY) { y1 = flatlist[oct].pl[line2.p1 - 1].y; y2 = flatlist[oct].pl[line2.p2 - 1].y; } else if (plane == XZ) { y1 = flatlist[oct].pl[line2.p1 - 1].z; y2 = flatlist[oct].pl[line2.p2 - 1].z; } else if (plane == YZ) { y1 = flatlist[oct].pl[line2.p1 - 1].z; y2 = flatlist[oct].pl[line2.p2 - 1].z; } i1 = flatlist[oct].pl[line2.p1 - 1].ip; i2 = flatlist[oct].pl[line2.p2 - 1].ip; inten_right = i1 * ((y - y2) / (y1 - y2)) + i2 * ((y - y1) / (y2 - y1)); } float ndotv, ndotl; Vector3 normal(ob.normx, ob.normy, ob.normz); Vector3 p_v(0,0,0); Vector3 v_v; Vector3 l_v; for (int x = start; x < end; x++) { x1 = start; x2 = end; color = inten_left * ((x - x2) / (x1 - x2)) + inten_right * ((x - x1) / (x2 - x1)); if ((ndotl > 0 && ndotv > 0) || (ndotl < 0 && ndotv < 0)) { colorPoint(x, y, color, buffer); } else { colorPoint(x, y, color, buffer); } } }
void downloadCalibration(unsigned int index) { /* Open a Kinect camera: */ Kinect::Camera camera(usbContext,index); std::cout<<"Downloading factory calibration data for Kinect "<<camera.getSerialNumber()<<"..."<<std::endl; /* Retrieve the factory calibration data: */ Kinect::Camera::CalibrationParameters cal; camera.getCalibrationParameters(cal); /* Calculate the depth-to-distance conversion formula: */ double numerator=10.0*(4.0*cal.dcmosEmitterDist*cal.referenceDistance)/cal.referencePixelSize; double denominator=4.0*cal.dcmosEmitterDist/cal.referencePixelSize+4.0*cal.constantShift+1.5; std::cout<<"Depth conversion formula: dist[mm] = "<<numerator<<" / ("<<denominator<<" - depth)"<<std::endl; /* Calculate the depth pixel unprojection matrix: */ double scale=2.0*cal.referencePixelSize/cal.referenceDistance; Math::Matrix depthMatrix(4,4,0.0); depthMatrix(0,0)=scale; depthMatrix(0,3)=-scale*640.0/2.0; depthMatrix(1,1)=scale; depthMatrix(1,3)=-scale*480.0/2.0; depthMatrix(2,3)=-1.0; depthMatrix(3,2)=-1.0/numerator; depthMatrix(3,3)=denominator/numerator; { std::cout<<std::endl<<"Depth unprojection matrix:"<<std::endl; std::streamsize oldPrec=std::cout.precision(8); std::cout.setf(std::ios::fixed); for(int i=0;i<4;++i) { std::cout<<" "; for(int j=0;j<4;++j) std::cout<<' '<<std::setw(11)<<depthMatrix(i,j); std::cout<<std::endl; } std::cout.unsetf(std::ios::fixed); std::cout.precision(oldPrec); } /* Calculate the depth-to-color mapping: */ double colorShiftA=cal.dcmosRcmosDist/(cal.referencePixelSize*2.0)+0.375; double colorShiftB=cal.dcmosRcmosDist*cal.referenceDistance*10.0/(cal.referencePixelSize*2.0); std::cout<<"Depth-to-color pixel shift formula: Shift = "<<colorShiftA<<" - "<<colorShiftB<<"/dist[mm]"<<std::endl; /* Formula to go directly from depth to displacement: */ double dispA=colorShiftA-colorShiftB*denominator/numerator; double dispB=colorShiftB/numerator; std::cout<<"Or: Shift = "<<dispA<<" + "<<dispB<<"*depth"<<std::endl; /* Tabulate the bivariate pixel mapping polynomial using forward differencing: */ double* colorx=new double[640*480]; double* colory=new double[640*480]; double ax=cal.ax; double bx=cal.bx; double cx=cal.cx; double dx=cal.dx; double ay=cal.ay; double by=cal.by; double cy=cal.cy; double dy=cal.dy; double dx0=(cal.dxStart<<13)>>4; double dy0=(cal.dyStart<<13)>>4; double dxdx0=(cal.dxdxStart<<11)>>3; double dxdy0=(cal.dxdyStart<<11)>>3; double dydx0=(cal.dydxStart<<11)>>3; double dydy0=(cal.dydyStart<<11)>>3; double dxdxdx0=(cal.dxdxdxStart<<5)<<3; double dydxdx0=(cal.dydxdxStart<<5)<<3; double dxdxdy0=(cal.dxdxdyStart<<5)<<3; double dydxdy0=(cal.dydxdyStart<<5)<<3; double dydydx0=(cal.dydydxStart<<5)<<3; double dydydy0=(cal.dydydyStart<<5)<<3; for(int y=0;y<480;++y) { dxdxdx0+=cx; dxdx0 +=dydxdx0/256.0; dydxdx0+=dx; dx0 +=dydx0/64.0; dydx0 +=dydydx0/256.0; dydydx0+=bx; dxdxdy0+=cy; dxdy0 +=dydxdy0/256.0; dydxdy0+=dy; dy0 +=dydy0/64.0; dydy0 +=dydydy0/256.0; dydydy0+=by; double coldxdxdy=dxdxdy0; double coldxdy=dxdy0; double coldy=dy0; double coldxdxdx=dxdxdx0; double coldxdx=dxdx0; double coldx=dx0; for(int x=0;x<640;++x) { colorx[y*640+x]=double(x)+coldx/131072.0+1.0; colory[y*640+x]=double(y)+coldy/131072.0+1.0; #if 0 if(x%40==20&&y%40==20) std::cout<<x<<", "<<y<<": "<<colorx[y*640+x]<<", "<<colory[y*640+x]<<std::endl; #endif coldx+=coldxdx/64.0; coldxdx+=coldxdxdx/256.0; coldxdxdx+=ax; coldy+=coldxdy/64.0; coldxdy+=coldxdxdy/256.0; coldxdxdy+=ay; } } /* Calculate the texture projection matrix by sampling the pixel mapping polynomial: */ int minDepth=Math::ceil(denominator-numerator/500.0); // 500mm is minimum viewing distance int maxDepth=Math::ceil(denominator-numerator/3000.0); // 3000mm is maximum reasonable viewing distance std::cout<<"Calculating best-fit color projection matrix for depth value range "<<minDepth<<" - "<<maxDepth<<"..."<<std::endl; Math::Matrix colorSystem(12,12,0.0); Math::Matrix depthPoint(4,1,0.0); depthPoint(3)=1.0; for(int y=20;y<480;y+=40) { depthPoint(1)=(double(y)+0.5)/480.0; for(int x=20;x<640;x+=40) { depthPoint(0)=(double(x)+0.5)/640.0; for(int depth=minDepth;depth<=maxDepth;depth+=20) { /* Transform the depth point to color image space using the non-linear transformation: */ // int xdisp=x+Math::floor(dispA+dispB*double(depth)+0.5); // if(xdisp>=0&&xdisp<640) { // double colX=double(xdisp)/640.0; // double colY=double(y)/480.0; // double colX=colorx[(479-y)*640+xdisp]/640.0; // double colY=(479.0-colory[(479-y)*640+xdisp])/480.0; double colX=(colorx[(479-y)*640+x]+dispA+dispB*double(depth))/640.0; double colY=(479.0-colory[(479-y)*640+x])/480.0; /* Calculate the 3D point based on the depth unprojection matrix: */ depthPoint(2)=double(depth)/double(maxDepth); Math::Matrix worldPoint=depthMatrix*depthPoint; /* Make the world point affine: */ for(int i=0;i<3;++i) worldPoint(i)/=worldPoint(3); /* Enter the world point / color point pair into the color projection system: */ double eq[2][12]; eq[0][0]=depthPoint(0); eq[0][1]=depthPoint(1); eq[0][2]=depthPoint(2); eq[0][3]=1.0; eq[0][4]=0.0; eq[0][5]=0.0; eq[0][6]=0.0; eq[0][7]=0.0; eq[0][8]=-colX*depthPoint(0); eq[0][9]=-colX*depthPoint(1); eq[0][10]=-colX*depthPoint(2); eq[0][11]=-colX; eq[1][0]=0.0; eq[1][1]=0.0; eq[1][2]=0.0; eq[1][3]=0.0; eq[1][4]=depthPoint(0); eq[1][5]=depthPoint(1); eq[1][6]=depthPoint(2); eq[1][7]=1.0; eq[1][8]=-colY*depthPoint(0); eq[1][9]=-colY*depthPoint(1); eq[1][10]=-colY*depthPoint(2); eq[1][11]=-colY; for(int row=0;row<2;++row) for(unsigned int i=0;i<12;++i) for(unsigned int j=0;j<12;++j) colorSystem(i,j)+=eq[row][i]*eq[row][j]; } } } } /* Find the linear system's smallest eigenvalue: */ std::pair<Math::Matrix,Math::Matrix> qe=colorSystem.jacobiIteration(); unsigned int minEIndex=0; double minE=Math::abs(qe.second(0,0)); for(unsigned int i=1;i<12;++i) { if(minE>Math::abs(qe.second(i,0))) { minEIndex=i; minE=Math::abs(qe.second(i,0)); } } std::cout<<"Smallest eigenvalue of color system = "<<minE<<std::endl; /* Create the normalized homography and extend it to a 4x4 matrix: */ Math::Matrix colorMatrix(4,4); double cmScale=qe.first(11,minEIndex); for(int i=0;i<2;++i) for(int j=0;j<4;++j) colorMatrix(i,j)=qe.first(i*4+j,minEIndex)/cmScale; for(int j=0;j<4;++j) colorMatrix(2,j)=j==2?1.0:0.0; for(int j=0;j<4;++j) colorMatrix(3,j)=qe.first(2*4+j,minEIndex)/cmScale; /* Un-normalize the color matrix: */ for(int i=0;i<4;++i) { colorMatrix(i,0)/=640.0; colorMatrix(i,1)/=480.0; colorMatrix(i,2)/=double(maxDepth); } /* Calculate the approximation error: */ double rms=0.0; unsigned int numPoints=0; depthPoint(3)=1.0; for(int y=20;y<480;y+=40) { depthPoint(1)=double(y)+0.5; for(int x=20;x<640;x+=40) { depthPoint(0)=double(x)+0.5; for(int depth=minDepth;depth<=maxDepth;depth+=20) { /* Transform the depth point to color image space using the non-linear transformation: */ // int xdisp=x+Math::floor(dispA+dispB*double(depth)+0.5); // if(xdisp>=0&&xdisp<640) { // double colX=double(xdisp)/640.0; // double colY=double(y)/480.0; // double colX=colorx[y*640+xdisp]/640.0; // double colY=(colory[y*640+xdisp]-50.0)/480.0; double colX=(colorx[y*640+x]+dispA+dispB*double(depth))/640.0; double colY=(colory[y*640+x]-0.0)/480.0; /* Transform the depth image point to color space using the color matrix: */ depthPoint(2)=double(depth); Math::Matrix colorPoint=colorMatrix*depthPoint; /* Calculate the approximation error: */ double dist=Math::sqr(colorPoint(0)/colorPoint(3)-colX)+Math::sqr(colorPoint(1)/colorPoint(3)-colY); rms+=dist; ++numPoints; } } } } /* Print the RMS: */ std::cout<<"Color matrix approximation RMS = "<<Math::sqrt(rms/double(numPoints))<<std::endl; /* Make the color matrix compatible with Kinect::Projector's way of doing things: */ // colorMatrix*=depthMatrix; { std::cout<<"Optimal homography from world space to color image space:"<<std::endl; std::streamsize oldPrec=std::cout.precision(8); std::cout.setf(std::ios::fixed); for(int i=0;i<4;++i) { std::cout<<" "; for(int j=0;j<4;++j) std::cout<<' '<<std::setw(11)<<colorMatrix(i,j); std::cout<<std::endl; } std::cout.unsetf(std::ios::fixed); std::cout.precision(oldPrec); } delete[] colorx; delete[] colory; /* Convert the depth matrix from mm to cm: */ Math::Matrix scaleMatrix(4,4,1.0); for(int i=0;i<3;++i) scaleMatrix(i,i)=0.1; depthMatrix=scaleMatrix*depthMatrix; /* Write the depth and color matrices to an intrinsic parameter file: */ std::string calibFileName=KINECT_CONFIG_DIR; calibFileName.push_back('/'); calibFileName.append(KINECT_CAMERA_INTRINSICPARAMETERSFILENAMEPREFIX); calibFileName.push_back('-'); calibFileName.append(camera.getSerialNumber()); calibFileName.append(".dat"); if(!Misc::doesPathExist(calibFileName.c_str())) { std::cout<<"Writing full intrinsic camera parameters to "<<calibFileName<<std::endl; IO::FilePtr calibFile=IO::openFile(calibFileName.c_str(),IO::File::WriteOnly); calibFile->setEndianness(Misc::LittleEndian); for(int i=0;i<4;++i) for(int j=0;j<4;++j) calibFile->write<double>(depthMatrix(i,j)); for(int i=0;i<4;++i) for(int j=0;j<4;++j) calibFile->write<double>(colorMatrix(i,j)); } else std::cout<<"Intrinsic camera parameter file "<<calibFileName<<" already exists"<<std::endl; }