void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // „Ƕ„Ç£„É≥„Éâ„Ƕ„ÅÆËÉåÊôØ„Çí°ó„Çä„ŧ„Å∂„Å? & Èö†Èù¢Âá¶ÁêÅEÇíÂèØËÉΩ„Å´„Åô„Çã glEnable(GL_DEPTH_TEST); // Èö†Èù¢Âá¶ÁêÅEñãÂß? glEnable(GL_NORMALIZE); glEnable(GL_LIGHTING); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glPushMatrix(); glTranslatef(0.0, 1.0, 0.0); polarview(); // „Éù„ÅE„É©„ɺ„Éì„É•„ɺ„Å∏„ÅÆ„Éì„É•„ɺ„ǧ„É≥„Ç∞§âÊèõ glPushMatrix(); glLightfv(GL_LIGHT0, GL_POSITION, light0); glPopMatrix(); shading(5); drawGround2D(); shading(6); glDisable(GL_LIGHTING); drawGrass(); glEnable(GL_LIGHTING); shading(5); drawPlant(); if (rainFlag == GL_TRUE) drawRain(); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); drawCloud(); if (thunderFlag == GL_TRUE && rainFlag == GL_TRUE) { if (lightningnum == 0 || lightningnum == 4) lightning(); lightningnum++; if (lightningnum == 5) { lightningnum = 0; thunderFlag = GL_FALSE; } if (rand() % 10 == 4) fallFlag = GL_TRUE; } else thunderFlag = GL_FALSE; glPopMatrix(); glutSwapBuffers(); }
bool SceneNode::hit(const Ray& ray, double &tmin, Shading &s) { // transform ray so in object co-ordinates Ray local_ray(ray); local_ray.direction = m_invtrans * ray.direction; local_ray.origin = m_invtrans * ray.origin; Shading shading(s.world); double t; tmin = 10E24; Vector3D normal; Material *mat; for (ChildList::const_iterator it = m_children.begin(); it != m_children.end(); it++) { SceneNode *object = (*it); if (object->hit(local_ray, t, shading) && (t < tmin)) { tmin = t; normal = shading.hit_normal; mat = shading.material; } } if (shading.hit_object) { s.hit_object = true; s.t = tmin; s.hit_normal = m_invtrans.transpose() * normal; s.material = mat; return true; } return false; }
bool Mesh::hit(const Ray& ray, double &tmin, Shading &s) const { Ray local_ray(ray); Shading shading(s.world); double t; tmin = 10E24; Vector3D normal; // check bounding box first Shading shading2(s.world); bool was_bound = m_boundbox->hit(ray,tmin,shading2); if (!m_boundbox->hit(ray,tmin,shading2)) { return false; } tmin = 10E24; for (unsigned int i=0; i<m_triangles.size(); i++) { Triangle triangle = m_triangles[i]; if (triangle.hit(local_ray, t, shading) && (t < tmin)) { shading.hit_object = true; tmin = t; normal = shading.hit_normal; } } if (shading.hit_object) { s.hit_object = true; s.t = tmin; s.hit_normal = normal; return true; } return false; }
// Ray tracing int rayTracing(Ray ray, SPHERE sphere, POLY4 poly, float lrp[3], float ip) { float P; Point3dPtr n; Point3dPtr interp; int C; float * kd = (float*)malloc(sizeof(*kd)); n = (Point3dPtr)malloc(sizeof(Point3d)); interp = (Point3dPtr)malloc(sizeof(Point3d)); P = rayObjectIntersection(ray, sphere, poly, n, interp, kd); if (P != 0.0) { C = shading(lrp, n, interp, kd, ip); return C; } else return 0; free(n); free(interp); free(kd); }
Material::Material(Material_t tag) : tag(tag), vertexShader(this), fragmentShader(this), index0AttributeName(this) { mId = Material::MaterialIdCount++; mUuid = Math::generateUUID(); mName = ""; side() = kFrontSide; opacity() = 1.0f; transparent() = false; blending() = kNormalBlending; blendSrc() = kSrcAlphaFactor; blendDst() = kOneMinusSrcAlphaFactor; blendEquation() = kAddEquation; depthTest() = true; depthWrite() = true; polygonOffset() = false; polygonOffsetFactor() = 0; polygonOffsetUnits() = 0; // mAlphaTest = 0; overdraw() = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer visible() = true; needsUpdate() = true; // By default, bind position to attribute index 0. In WebGL, attribute 0 // should always be used to avoid potentially expensive emulation. index0AttributeName("position"); linewidth() = 1.0f; metal() = false; perPixel() = true; shading() = kNoShading; vertexColors() = kNoColors; wireframe() = false; wireframeLinewidth() = 1.0f; }
// OpenGL initialization void init() { program = glCreateProgram(); // Load shaders and use the resulting shader program Shader shading(program, "glsl/shader.vert", "glsl/shader.frag"); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glClearColor(0.0, 0.0, 0.0, 1.0); glCullFace(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // initally create a cube r1 = Rectangle(xyz<GLfloat>{-0.5, +0.5, +0.0}, xyz<GLfloat>{-0.5, -0.5, +0.0}, xyz<GLfloat>{+0.5, -0.5, +0.0}, xyz<GLfloat>{+0.5, +0.5, +0.0}); r2 = Rectangle(xyz<GLfloat>{-0.25, +0.25, +0.0}, xyz<GLfloat>{-0.25, -0.25, +0.0}, xyz<GLfloat>{+0.25, -0.25, +0.0}, xyz<GLfloat>{+0.25, +0.25, +0.0}); }
void CFWL_WidgetTP::DrawAxialShading(CFX_Graphics* pGraphics, FX_FLOAT fx1, FX_FLOAT fy1, FX_FLOAT fx2, FX_FLOAT fy2, FX_ARGB beginColor, FX_ARGB endColor, CFX_Path* path, int32_t fillMode, CFX_Matrix* pMatrix) { if (!pGraphics || !path) return; CFX_PointF begPoint(fx1, fy1); CFX_PointF endPoint(fx2, fy2); CFX_Shading shading(begPoint, endPoint, false, false, beginColor, endColor); pGraphics->SaveGraphState(); CFX_Color color1(&shading); pGraphics->SetFillColor(&color1); pGraphics->FillPath(path, fillMode, pMatrix); pGraphics->RestoreGraphState(); }
CalibrationData CalibratorLocHom::calibrate() { QSettings settings("SLStudio"); //Checkerboard parameters float checkerSize = settings.value("calibration/checkerSize").toFloat(); std::cout << "checkerSize== "<< checkerSize <<std::endl; unsigned int checkerRows = settings.value("calibration/checkerRows").toInt(); unsigned int checkerCols = settings.value("calibration/checkerCols").toInt(); // Number of saddle points on calibration pattern cv::Size patternSize(checkerCols,checkerRows); // Number of calibration sequences unsigned nFrameSeq = frameSeqsFromFile.size(); vector<cv::Mat> up(nFrameSeq), vp(nFrameSeq), shading(nFrameSeq), mask(nFrameSeq); // Decode frame sequences std::cout << "Decode frames: Num="<< nFrameSeq<< ", and begin.....>> "; for(unsigned int i=0; i<nFrameSeq; i++) { //vector<cv::Mat> frames = frameSeqs[i]; vector<cv::Mat> frames; vector<std::string> framesFromFile= frameSeqsFromFile[i]; for(unsigned int m=0; m<framesFromFile.size();m++) { cv::Mat curFrame = cv::imread(framesFromFile[m],CV_LOAD_IMAGE_GRAYSCALE); curFrame = curFrame.clone(); frames.push_back(curFrame); } for(unsigned int f=0; f<frames.size(); f++){ decoder->setFrame(f, frames[f]); #if 0 cv::imwrite(QString("m_frames_%1_%2.png").arg(i,2,10,QChar('0')).arg(f).toStdString(), frames[f]); #endif } decoder->decodeFrames(up[i], vp[i], mask[i], shading[i]); std::cout << i << ","; #if 0 cvtools::writeMat(shading[i], QString("shading[%1].mat").arg(i).toLocal8Bit()); cvtools::writeMat(up[i], QString("up[%1].mat").arg(i).toLocal8Bit()); cvtools::writeMat(vp[i], QString("vp[%1].mat").arg(i).toLocal8Bit()); #endif } std::cout << "-->end||."<<std::endl; unsigned int frameWidth = up[0].cols; unsigned int frameHeight = up[0].rows; // Generate local calibration object coordinates [mm] std::cout << "Generate local calibration object coordinates"<<std::endl; vector<cv::Point3f> Qi; for (int h=0; h<patternSize.height; h++) for (int w=0; w<patternSize.width; w++) Qi.push_back(cv::Point3f(checkerSize * w, checkerSize* h, 0.0)); // Find calibration point coordinates for camera and projector std::cout<< "Find calibration point coordinates for camera and projector!" <<std::endl; vector< vector<cv::Point2f> > qc, qp; vector< vector<cv::Point3f> > Q; for(unsigned int i=0; i<nFrameSeq; i++) { //std::cout << i << " 1" << std::endl; vector<cv::Point2f> qci; // Aid checkerboard extraction by slight blur //cv::GaussianBlur(shading[i], shading[i], cv::Size(5,5), 2, 2); // Extract checker corners std::cout << i << ": findChessboardCorners......" << std::endl; bool success = cv::findChessboardCorners(shading[i], patternSize, qci, cv::CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE+CALIB_CB_FAST_CHECK ); std::cout << " cv::findChessboardCorners: sucess = " << success << std::endl; if(!success) std::cout << "Calibrator: could not extract chess board corners on frame seqence " << i << std::endl << std::flush; else { std::cout << i << ": cornerSubPix......" << std::endl; // Refine corner locations cv::cornerSubPix(shading[i], qci, cv::Size(5, 5), cv::Size(1, 1), cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::MAX_ITER, 20, 0.01)); } // Draw colored chessboard cv::Mat shadingColor; cv::cvtColor(shading[i], shadingColor, cv::COLOR_GRAY2RGB); cv::drawChessboardCorners(shadingColor, patternSize, qci, success); #if 1 QString filename = QString("am_shadingColor%1.bmp").arg(i, 2, 10, QChar('0')); cv::imwrite(filename.toStdString(), shadingColor); // filename = QString("am_shadingColor%1.png").arg(i, 2, 10, QChar('0')); // cv::imwrite(filename.toStdString(), shadingColor); #endif //Emit chessboard results emit newSequenceResult(shadingColor, i, success); if(success) { // Vectors of accepted points for current view vector<cv::Point2f> qpi_a; vector<cv::Point2f> qci_a; vector<cv::Point3f> Qi_a; // Loop through checkerboard corners for(unsigned int j=0; j<qci.size(); j++) { const cv::Point2f &qcij = qci[j]; // Collect neighbor points const unsigned int WINDOW_SIZE = 10; std::vector<cv::Point2f> N_qcij, N_qpij; // avoid going out of bounds unsigned int starth = max(int(qcij.y+0.5)-WINDOW_SIZE, 0u); unsigned int stoph = min(int(qcij.y+0.5)+WINDOW_SIZE, frameHeight-1); unsigned int startw = max(int(qcij.x+0.5)-WINDOW_SIZE, 0u); unsigned int stopw = min(int(qcij.x+0.5)+WINDOW_SIZE, frameWidth-1); for(unsigned int h=starth; h<=stoph; h++) { for(unsigned int w=startw; w<=stopw; w++) { // stay within mask if(mask[i].at<bool>(h,w)) { N_qcij.push_back(cv::Point2f(w, h)); float upijwh = up[i].at<float>(h,w); float vpijwh = vp[i].at<float>(h,w); N_qpij.push_back(cv::Point2f(upijwh, vpijwh)); } } } //std::cout << i << " findHomography " << N_qcij.size() << " " << N_qpij.size() << std::endl; // if enough valid points to build homography if(N_qpij.size() >= 50) { // std::cout << i << " findHomography" << std::endl; // translate qcij into qpij using local homography cv::Mat H = cv::findHomography(N_qcij, N_qpij, cv::LMEDS); if(!H.empty()) { cv::Point3d Q = cv::Point3d(cv::Mat(H*cv::Mat(cv::Point3d(qcij.x, qcij.y, 1.0)))); cv::Point2f qpij = cv::Point2f(Q.x/Q.z, Q.y/Q.z); qpi_a.push_back(qpij); qci_a.push_back(qci[j]); Qi_a.push_back(Qi[j]); } } } if(!Qi_a.empty()) { // Store projector corner coordinates qp.push_back(qpi_a); // Store camera corner coordinates qc.push_back(qci_a); // Store world corner coordinates Q.push_back(Qi_a); } } } if(Q.size() < 1){ std::cerr << "Error: not enough calibration sequences!" << std::endl; CalibrationData nanData; return nanData; } //calibrate the camera std::cout<< "calibrate the camera!" <<std::endl; cv::Mat Kc, kc; std::vector<cv::Mat> cam_rvecs, cam_tvecs; cv::Size frameSize(frameWidth, frameHeight); double cam_error = cv::calibrateCamera(Q, qc, frameSize, Kc, kc, cam_rvecs, cam_tvecs, cv::CALIB_FIX_ASPECT_RATIO + cv::CALIB_FIX_PRINCIPAL_POINT + cv::CALIB_FIX_K2 + cv::CALIB_FIX_K3 + cv::CALIB_ZERO_TANGENT_DIST, cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 50, DBL_EPSILON)); //calibrate the projector std::cout<< "calibrate the projector!" <<std::endl; cv::Mat Kp, kp; std::vector<cv::Mat> proj_rvecs, proj_tvecs; cv::Size screenSize(screenCols, screenRows); double proj_error = cv::calibrateCamera(Q, qp, screenSize, Kp, kp, proj_rvecs, proj_tvecs, cv::CALIB_FIX_ASPECT_RATIO + cv::CALIB_FIX_K2 + cv::CALIB_FIX_K3 + cv::CALIB_ZERO_TANGENT_DIST, cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 50, DBL_EPSILON)); //stereo calibration std::cout<< "stereo calibrate!" <<std::endl; cv::Mat Rp, Tp, E, F; //Opencv2.x version //double stereo_error = cv::stereoCalibrate(Q, qc, qp, Kc, kc, Kp, kp, frameSize, Rp, Tp, E, F, // cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 100, DBL_EPSILON), cv::CALIB_FIX_INTRINSIC); //Opencv3.x version double stereo_error = cv::stereoCalibrate(Q, qc, qp, Kc, kc, Kp, kp, frameSize, Rp, Tp, E, F, cv::CALIB_FIX_INTRINSIC,cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 100, DBL_EPSILON)); CalibrationData calData(Kc, kc, cam_error, Kp, kp, proj_error, Rp, Tp, stereo_error); calData.print(std::cout); // Determine per-view reprojection errors: std::vector<float> cam_error_per_view(Q.size()); cam_error_per_view.resize(Q.size()); std::vector<float> proj_error_per_view(Q.size()); proj_error_per_view.resize(Q.size()); for(unsigned int i = 0; i < (unsigned int)Q.size(); ++i){ int n = (int)Q[i].size(); vector<cv::Point2f> qc_proj; cv::projectPoints(cv::Mat(Q[i]), cam_rvecs[i], cam_tvecs[i], Kc, kc, qc_proj); float err = 0; for(int j=0; j<qc_proj.size(); j++){ cv::Point2f d = qc[i][j] - qc_proj[j]; err += cv::sqrt(d.x*d.x + d.y*d.y); } cam_error_per_view[i] = (float)err/n; vector<cv::Point2f> qp_proj; cv::projectPoints(cv::Mat(Q[i]), proj_rvecs[i], proj_tvecs[i], Kp, kp, qp_proj); err = 0; for(int j=0; j<qc_proj.size(); j++){ cv::Point2f d = qp[i][j] - qp_proj[j]; err += cv::sqrt(d.x*d.x + d.y*d.y); } proj_error_per_view[i] = (float)err/n; std::cout << "Seq error " << i+1 << " cam:" << cam_error_per_view[i] << " proj:" << proj_error_per_view[i] << std::endl; } return calData; // CalibrationData nanData; // return nanData; }
//投影された三角形abcにラスタライズ、クリッピングでシェーディングを行う関数 //引数a, b, cは投影平面上の3点 //eg) //double a = {1.0, 2.0}; //nは法線ベクトル //Aは投影前の3点からなる三角形平面上の任意の点の座標. //(3点A、B、Cのうちいずれでも良いがmain関数内のAを使うものとする.) void shading(double *a, double *b, double *c, double *n, double *A){ //3点が1直線上に並んでいるときはシェーディングができない if(lineOrNot(a, b, c) == 1){ //塗りつぶす点が無いので何もしない. } else{ //y座標の値が真ん中点をp、その他の点をq、rとする //y座標の大きさはr <= p <= qの順 double p[2], q[2], r[2]; if(b[1] <= a[1] && a[1] <= c[1]){ memcpy(p, a, sizeof(double) * 2); memcpy(q, c, sizeof(double) * 2); memcpy(r, b, sizeof(double) * 2); } else{ if(c[1] <= a[1] && a[1] <= b[1]){ memcpy(p, a, sizeof(double) * 2); memcpy(q, b, sizeof(double) * 2); memcpy(r, c, sizeof(double) * 2); } else{ if(a[1] <= b[1] && b[1] <= c[1]){ memcpy(p, b, sizeof(double) * 2); memcpy(q, c, sizeof(double) * 2); memcpy(r, a, sizeof(double) * 2); } else{ if(c[1] <= b[1] && b[1] <= a[1]){ memcpy(p, b, sizeof(double) * 2); memcpy(q, a, sizeof(double) * 2); memcpy(r, c, sizeof(double) * 2); } else{ if(b[1] <= c[1] && c[1] <= a[1]){ memcpy(p, c, sizeof(double) * 2); memcpy(q, a, sizeof(double) * 2); memcpy(r, b, sizeof(double) * 2); } else{ if(a[1] <= c[1] && c[1] <= b[1]){ memcpy(p, c, sizeof(double) * 2); memcpy(q, b, sizeof(double) * 2); memcpy(r, a, sizeof(double) * 2); } else{ printf("エラーat2055\n"); printf("\na[1]=%f\tb[1]=%f\tc[1]=%f\n", a[1], b[1], c[1]); perror(NULL); } } } } } } //分割可能な三角形かを判定 if(p[1] == r[1] || p[1] == q[1]){ //分割できない //長さが1の光源方向ベクトルを作成する //光源方向ベクトルの長さ double length_l = sqrt(pow(light_dir[0], 2.0) + pow(light_dir[1], 2.0) + pow(light_dir[2], 2.0)); double light_dir_vec[3]; light_dir_vec[0] = light_dir[0] / length_l; light_dir_vec[1] = light_dir[1] / length_l; light_dir_vec[2] = light_dir[2] / length_l; //2パターンの三角形を特定 if(p[1] == r[1]){ //x座標が p <= r となるように調整 if(r[0] < p[0]){ double temp[2]; memcpy(temp, r, sizeof(double) * 2); memcpy(r, p, sizeof(double) * 2); memcpy(p, temp, sizeof(double) * 2); } //debug if(r[0] == p[0]){ perror("エラーat958"); } //シェーディング処理 //三角形pqrをシェーディング //y座標はp <= r //debug if(r[1] < p[1]){ perror("エラーat1855"); } /* 点(j, i)のシェーディング============================================= */ int i; i = ceil(p[1]); for(i; p[1] <= i && i <= q[1]; i++){ //撮像平面からはみ出ていないかのチェック if(0 <= i && i <= (HEIGHT - 1)){ double x1 = func1(p, q, i); double x2 = func1(r, q, i); int j; j = ceil(x1); for(j; x1 <= j && j <= x2 && 0 <= j && j <= (WIDTH - 1); j++){ /* 鏡面反射を計算 */ //描画する点の投影前の空間内の座標. double p_or[3]; p_or[0] = (j-(WIDTH/2)) * ((n[0]*A[0]) + (n[1]*A[1]) + (n[2]*A[2])) / ((n[0]*(j-(WIDTH/2))) + (n[1]*(i-(HEIGHT/2))) + n[2]*FOCUS); p_or[1] = (i-(HEIGHT/2)) * ((n[0]*A[0]) + (n[1]*A[1]) + (n[2]*A[2])) / ((n[0]*(j-(WIDTH/2))) + (n[1]*(i-(HEIGHT/2))) + n[2]*FOCUS); p_or[2] = FOCUS * ((n[0]*A[0]) + (n[1]*A[1]) + (n[2]*A[2])) / ((n[0]*(j-(WIDTH/2))) + (n[1]*(i-(HEIGHT/2))) + n[2]*FOCUS); /* eは描画中の点pから視点位置へ向かうベクトルを計算 */ //視点方向は原点に固定 double e[3]; e[0] = -1 * p_or[0]; e[1] = -1 * p_or[1]; e[2] = -1 * p_or[2]; double length_e = sqrt(pow(e[0], 2.0) + pow(e[1], 2.0) + pow(e[2], 2.0)); e[0] = (e[0] / length_e); e[1] = (e[1] / length_e); e[2] = (e[2] / length_e); /* iは光源から描画中の点pへの入射光ベクトルを計算 */ //平行光源のため光源方向は //const double light_dir[3] = {-1.0, -1.0, 2.0}; //を用いる double i_vec[3]; i_vec[0] = light_dir[0]; i_vec[1] = light_dir[1]; i_vec[2] = light_dir[2]; double length_i = sqrt(pow(i_vec[0], 2.0) + pow(i_vec[1], 2.0) + pow(i_vec[2], 2.0)); i_vec[0] = (i_vec[0] / length_i); i_vec[1] = (i_vec[1] / length_i); i_vec[2] = (i_vec[2] / length_i); /* sベクトルを計算 */ double s[3]; s[0] = e[0] - i_vec[0]; s[1] = e[1] - i_vec[1]; s[2] = e[2] - i_vec[2]; double s_length = sqrt(pow(s[0], 2.0) + pow(s[1], 2.0) + pow(s[2], 2.0)); s[0] = (s[0] / s_length); s[1] = (s[1] / s_length); s[2] = (s[2] / s_length); //内積sn double sn = ((s[0] * n[0]) + (s[1] * n[1]) + (s[2] * n[2])); if(sn <= 0){sn = 0;} /* 法線ベクトルnと光源方向ベクトルの内積 */ double ip = (n[0] * i_vec[0]) + (n[1] * i_vec[1]) + (n[2] * i_vec[2]); if(0 <= ip){ip = 0;} //zがzバッファの該当する値より大きければ描画を行わない(何もしない) if(z_buf[i][j] < p_or[2]){} else{ image[i][j][0] = (-1 * ip * diffuse_color[0] * light_rgb[0] * MAX) + (pow(sn, shininess) * specular_color[0] * light_rgb[0] * MAX) ; image[i][j][1] = (-1 * ip * diffuse_color[1] * light_rgb[1] * MAX) + (pow(sn, shininess) * specular_color[1] * light_rgb[1] * MAX) ; image[i][j][2] = (-1 * ip * diffuse_color[2] * light_rgb[2] * MAX) + (pow(sn, shininess) * specular_color[2] * light_rgb[2] * MAX) ; //zバッファの更新 z_buf[i][j] = p_or[2]; } } /* 点(j, i)のシェーディングここまで============================================= */ } //はみ出ている場合は描画しない else{} } } if(p[1] == q[1]){ //x座標が p < q となるように調整 if(q[0] < p[0]){ double temp[2]; memcpy(temp, q, sizeof(double) * 2); memcpy(q, p, sizeof(double) * 2); memcpy(p, temp, sizeof(double) * 2); } //debug if(q[0] == p[0]){ perror("エラーat1011"); } //シェーディング処理 //三角形pqrをシェーディング //y座標はp <= q //debug if(q[1] < p[1]){ perror("エラーat1856"); } int i; i = ceil(r[1]); for(i; r[1] <= i && i <= p[1]; i++){ //撮像部分からはみ出ていないかのチェック if( 0 <= i && i <= (HEIGHT - 1)){ double x1 = func1(p, r, i); double x2 = func1(q, r, i); int j; j = ceil(x1); for(j; x1 <= j && j <= x2 && 0 <= j && j <= (WIDTH - 1); j++){ /* 鏡面反射を適用 */ //描画する点の投影前の空間内の座標. double p_or[3]; p_or[0] = (j-(WIDTH/2)) * ((n[0]*A[0]) + (n[1]*A[1]) + (n[2]*A[2])) / ((n[0]*(j-(WIDTH/2))) + (n[1]*(i-(HEIGHT/2))) + n[2]*FOCUS); p_or[1] = (i-(MAX/2)) * ((n[0]*A[0]) + (n[1]*A[1]) + (n[2]*A[2])) / ((n[0]*(j-(WIDTH/2))) + (n[1]*(i-(HEIGHT/2))) + n[2]*FOCUS); p_or[2] = FOCUS * ((n[0]*A[0]) + (n[1]*A[1]) + (n[2]*A[2])) / ((n[0]*(j-(WIDTH/2))) + (n[1]*(i-(HEIGHT/2))) + n[2]*FOCUS); /* 描画中の点pから視点位置へ向かう単位方向ベクトルe計算 */ //視点方向は原点に固定 double e[3]; e[0] = -1 * p_or[0]; e[1] = -1 * p_or[1]; e[2] = -1 * p_or[2]; double length_e = sqrt(pow(e[0], 2.0) + pow(e[1], 2.0) + pow(e[2], 2.0)); e[0] = (e[0] / length_e); e[1] = (e[1] / length_e); e[2] = (e[2] / length_e); /* 光源から描画中の点pへの入射光ベクトルiを計算 */ //平行光源のため光源方向は //const double light_dir[3] = {-1.0, -1.0, 2.0}; //を用いる double i_vec[3]; i_vec[0] = light_dir[0]; i_vec[1] = light_dir[1]; i_vec[2] = light_dir[2]; double length_i = sqrt(pow(i_vec[0], 2.0) + pow(i_vec[1], 2.0) + pow(i_vec[2], 2.0)); i_vec[0] = (i_vec[0] / length_i); i_vec[1] = (i_vec[1] / length_i); i_vec[2] = (i_vec[2] / length_i); /* sベクトルを計算 */ double s[3]; s[0] = e[0] - i_vec[0]; s[1] = e[1] - i_vec[1]; s[2] = e[2] - i_vec[2]; double s_length = sqrt(pow(s[0], 2.0) + pow(s[1], 2.0) + pow(s[2], 2.0)); s[0] = (s[0] / s_length); s[1] = (s[1] / s_length); s[2] = (s[2] / s_length); //内積sn double sn = ((s[0] * n[0]) + (s[1] * n[1]) + (s[2] * n[2])); if(sn <= 0){sn = 0;} //拡散反射 /* 法線ベクトルnと光源方向ベクトルの内積を計算 */ double ip = (n[0] * i_vec[0]) + (n[1] * i_vec[1]) + (n[2] * i_vec[2]); if(0 <= ip){ip = 0;} //zがzバッファの該当する値より大きければ描画を行わない(何もしない) if(z_buf[i][j] < p_or[2]){} else{ image[i][j][0] = (-1 * ip * diffuse_color[0] * light_rgb[0] * MAX) + (pow(sn, shininess) * specular_color[0] * light_rgb[0] * MAX) ; image[i][j][1] = (-1 * ip * diffuse_color[1] * light_rgb[1] * MAX) + (pow(sn, shininess) * specular_color[1] * light_rgb[1] * MAX) ; image[i][j][2] = (-1 * ip * diffuse_color[2] * light_rgb[2] * MAX) + (pow(sn, shininess) * specular_color[2] * light_rgb[2] * MAX) ; z_buf[i][j] = p_or[2]; } } } //撮像平面からはみ出る部分は描画しない else{} } } } //分割できる //分割してそれぞれ再帰的に処理 //分割後の三角形はpp2qとpp2r else{ double p2[2]; p2[0] = func1(q, r, p[1]); p2[1] = p[1]; //p2のほうがpのx座標より大きくなるようにする if(p2[0] < p[0]){ double temp[2]; memcpy(temp, p2, sizeof(double) * 2); memcpy(p2, p, sizeof(double) * 2); memcpy(p, temp, sizeof(double) * 2); } //分割しても同一平面上なので法線ベクトルと //平面上の任意の点は同じものを使える. shading(p, p2, q, n, A); shading(p, p2, r, n, A); } } }
int main (int argc, char *argv[]){ /* VRML読み込み========================================================= */ int i; FILE *fp; Polygon poly; Surface surface; fp = fopen(argv[1], "r"); read_one_obj(fp, &poly, &surface); fprintf(stderr,"%d vertice are found.\n",poly.vtx_num); fprintf(stderr,"%d triangles are found.\n",poly.idx_num); //i th vertex for ( i = 0 ; i < poly.vtx_num ; i++ ) { fprintf(stdout,"%f %f %f # %d th vertex\n", poly.vtx[i*3+0], poly.vtx[i*3+1], poly.vtx[i*3+2], i); } //i th triangle for ( i = 0 ; i < poly.idx_num ; i++ ) { fprintf(stdout,"%d %d %d # %d th triangle\n", poly.idx[i*3+0], poly.idx[i*3+1], poly.idx[i*3+2], i); } /* material info */ fprintf(stderr, "diffuseColor %f %f %f\n", surface.diff[0], surface.diff[1], surface.diff[2]); fprintf(stderr, "specularColor %f %f %f\n", surface.spec[0], surface.spec[1], surface.spec[2]); fprintf(stderr, "ambientIntensity %f\n", surface.ambi); fprintf(stderr, "shininess %f\n", surface.shine); /* VRML読み込みここまで========================================================= */ FILE *fp_ppm; char *fname = argv[2]; fp_ppm = fopen(argv[2], "w"); //ファイルが開けなかったとき if( fp_ppm == NULL ){ printf("%sファイルが開けません.\n", fname); return -1; } //ファイルが開けたとき else{ //描画領域を初期化 for(int i = 0; i < 256; i++){ for(int j = 0; j < 256; j++){ image[i][j][0] = 0.0 * MAX; image[i][j][1] = 0.0 * MAX; image[i][j][2] = 0.0 * MAX; } } //zバッファを初期化 for(int i = 0; i < 256; i++){ for(int j = 0; j < 256; j++){ z_buf[i][j] = DBL_MAX; } } //diffuse_colorの格納 diffuse_color[0] = surface.diff[0]; diffuse_color[1] = surface.diff[1]; diffuse_color[2] = surface.diff[2]; //shininessの格納 //!!!!!!!!!!!!!注意!!!!!!!!!!!!!!!! //(実験ページの追加情報を参照) //各ファイルのshininessの値は //av4 0.5 //av5 0.5 //iiyama1997 1.0 //aa053 1.0 //av007 0.34 shininess = surface.shine * 128; //speculorColorの格納 specular_color[0] = surface.spec[0]; specular_color[1] = surface.spec[1]; specular_color[2] = surface.spec[2]; //投影された後の2次元平面上の各点の座標を格納する領域 double projected_ver_buf[3][2]; //シェーディング //三角形ごとのループ for(int i = 0; i < poly.idx_num; i++){ //各点の透視投影処理 for(int j = 0; j < 3; j++){ double xp = poly.vtx[(poly.idx[i*3+j])*3 + 0]; double yp = poly.vtx[(poly.idx[i*3+j])*3 + 1]; double zp = poly.vtx[(poly.idx[i*3+j])*3 + 2]; double zi = FOCUS; //debug if(zp == 0){ printf("\n(%f\t%f\t%f) i=%d, j=%d\n", xp, yp, zp, i, j); perror("\nエラー0934\n"); //break; } double xp2 = xp * (zi / zp); double yp2 = yp * (zi / zp); double zp2 = zi; //座標軸を平行移動 projected_ver_buf[j][0] = (MAX / 2) + xp2; projected_ver_buf[j][1] = (MAX / 2) + yp2; } double a[2], b[2], c[2]; a[0] = projected_ver_buf[0][0]; a[1] = projected_ver_buf[0][1]; b[0] = projected_ver_buf[1][0]; b[1] = projected_ver_buf[1][1]; c[0] = projected_ver_buf[2][0]; c[1] = projected_ver_buf[2][1]; double A[3], B[3], C[3]; A[0] = poly.vtx[(poly.idx[i*3+0])*3 + 0]; A[1] = poly.vtx[(poly.idx[i*3+0])*3 + 1]; A[2] = poly.vtx[(poly.idx[i*3+0])*3 + 2]; B[0] = poly.vtx[(poly.idx[i*3+1])*3 + 0]; B[1] = poly.vtx[(poly.idx[i*3+1])*3 + 1]; B[2] = poly.vtx[(poly.idx[i*3+1])*3 + 2]; C[0] = poly.vtx[(poly.idx[i*3+2])*3 + 0]; C[1] = poly.vtx[(poly.idx[i*3+2])*3 + 1]; C[2] = poly.vtx[(poly.idx[i*3+2])*3 + 2]; //ベクトルAB, ACから外積を計算して //法線ベクトルnを求める double AB[3], AC[3], n[3]; AB[0] = B[0] - A[0]; AB[1] = B[1] - A[1]; AB[2] = B[2] - A[2]; AC[0] = C[0] - A[0]; AC[1] = C[1] - A[1]; AC[2] = C[2] - A[2]; n[0] = (AB[1] * AC[2]) - (AB[2] * AC[1]); n[1] = (AB[2] * AC[0]) - (AB[0] * AC[2]); n[2] = (AB[0] * AC[1]) - (AB[1] * AC[0]); //長さを1に調整 double length_n = sqrt(pow(n[0], 2.0) + pow(n[1], 2.0) + pow(n[2], 2.0)); n[0] = n[0] / length_n; n[1] = n[1] / length_n; n[2] = n[2] / length_n; //平面iの投影先の三角形をシェーディング shading(a, b, c, n, A); } //ヘッダー出力 fputs(MAGICNUM, fp_ppm); fputs("\n", fp_ppm); fputs(WIDTH_STRING, fp_ppm); fputs(" ", fp_ppm); fputs(HEIGHT_STRING, fp_ppm); fputs("\n", fp_ppm); fputs(MAX_STRING, fp_ppm); fputs("\n" ,fp_ppm); //imageの出力 for(int i = 0; i < 256; i++){ for(int j = 0; j < 256; j++){ char r[256]; char g[256]; char b[256]; char str[1024]; sprintf(r, "%d", (int)round(image[i][j][0])); sprintf(g, "%d", (int)round(image[i][j][1])); sprintf(b, "%d", (int)round(image[i][j][2])); sprintf(str, "%s\t%s\t%s\n", r, g, b); fputs(str, fp_ppm); } } } fclose(fp_ppm); fclose(fp); printf("\nppmファイル %s に画像を出力しました.\n", fname ); return 1; }
int main(int argc, char** args) { GLFWwindow* window = setup(); //------------------------------------------ //-------- View-Projection settings -------- //------------------------------------------ glm::vec3 cameraPos = glm::vec3(5.0f, 1.0f, 0.0f); glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.01f, 20.0f); glm::mat4 View = glm::lookAt(cameraPos, //Position glm::vec3(0.0f, 0.0f, 0.0f), //Look direction glm::vec3(0.0f, 1.0f, 0.0f) ); //Up //Pre-multiply projection and view glm::mat4 vpMatrix = Projection * View; //--------------------------- //-------- Lighting --------- //--------------------------- PointLight p[2]; p[0].pos = glm::vec3(0.0f, 0.0f, +3.0f); p[0].intensity = 2.0f; p[0].falloff = 1.0f; p[1].pos = glm::vec3(0.0f, 0.0f, -3.0f); p[1].intensity = 2.0f; p[1].falloff = 1.0f; glm::vec3 p0 = glm::vec3(0.0f, 0.0f, +3.0f); glm::vec3 p1 = glm::vec3(0.0f, +4.0f, 0.0f); float angle = 0.0f; //---------------------------------- //-------- Geometry setting -------- //---------------------------------- if(argc != 3) { std::cout<<"Wrong input! Usage: "<<std::endl<<std::endl; std::cout<<" ./render path/to/file.obj gouraud|flat"<<std::endl<<std::endl; return 0; } std::string filepath(args[1]); std::string shading(args[2]); Object obj; obj.load(filepath, std::string("./shaders/") + shading); obj.setViewProjection(&vpMatrix); do { //Clear screen -> this function also clears stencil and depth buffer glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //Rotate lights glm::mat4 rot1 = glm::rotate(glm::mat4(1.0f), angle, glm::vec3(0.0f, 1.0f, 0.0f)); glm::mat4 rot2 = glm::rotate(glm::mat4(1.0f), angle, glm::vec3(0.0f, 0.0f, 1.0f)); p[0].pos = glm::vec3( rot1 * glm::vec4(p0, 1.0f) ); p[1].pos = glm::vec3( rot2 * glm::vec4(p1, 1.0f) ); angle += 0.05f; if(angle >= 6.28) angle = 0.0f; obj.draw(cameraPos, p, 2); //Swap buffer and query events glfwSwapBuffers(window); glfwPollEvents(); } while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && !glfwWindowShouldClose(window)); //Drop GLFW device glfwTerminate(); return 0; }
void CMapDEM::draw() { IMap::overlay_e overlay = status->getOverlayType(); if(CMapDEMSlopeSetup::self() && (overlay != old_overlay)) { if(overlay == IMap::eSlope) { CMapDEMSlopeSetup::self()->registerDEMMap(this); } else { CMapDEMSlopeSetup::self()->registerDEMMap(0); } } if(overlay == IMap::eNone) { old_overlay = overlay; pixBuffer.fill(Qt::transparent); return; } // check if old area matches new request // kind of a different way to calculate the needRedraw flag projXY p1, p2; float my_xscale, my_yscale; getArea_n_Scaling_fromBase(p1, p2, my_xscale, my_yscale); if( overlay == old_overlay && p1.u == old_p1.u && p1.v == old_p1.v && p2.u == old_p2.u && p2.v == old_p2.v && my_xscale == old_my_xscale && my_yscale == old_my_yscale ) { if(!needsRedraw) { return; } } old_p1 = p1; old_p2 = p2; old_my_xscale = my_xscale; old_my_yscale = my_yscale; old_overlay = overlay; pixBuffer.fill(Qt::transparent); if(pjsrc == 0) return; /* Calculate area of DEM data to be read. */ projXY _p1 = p1; projXY _p2 = p2; // 1. convert top left and bottom right point into the projection system used by the DEM data pj_transform(pjtar, pjsrc, 1, 0, &_p1.u, &_p1.v, 0); pj_transform(pjtar, pjsrc, 1, 0, &_p2.u, &_p2.v, 0); // determine intersection rect projXY r1 = { qMax(_p1.u, xref1), qMin(_p1.v, yref1) }; projXY r2 = { qMin(_p2.u, xref2), qMax(_p2.v, yref2) }; if (r1.u > _p2.u || r1.v < _p2.v || r2.u < _p1.u || r2.v > _p1.v) { // no interscetion return; } // 2. get floating point offset of topleft corner double xoff1_f = (r1.u - xref1) / xscale; double yoff1_f = (r1.v - yref1) / yscale; // 3. truncate floating point offset into integer offset int xoff1 = xoff1_f; int yoff1 = yoff1_f; // 4. get floating point offset of bottom right corner double xoff2_f = (r2.u - xref1) / xscale; double yoff2_f = (r2.v - yref1) / yscale; // 5. qRound up (!) floating point offset into integer offset int xoff2 = ceil(xoff2_f); int yoff2 = ceil(yoff2_f); /* The defined area into DEM data (xoff1,yoff1,xoff2,yoff2) covers a larger or equal area in world coordinates [m] than the current viewport. Next the width and height of the area in the DEM data and the corresponding sceen size is calculated. */ /* Calculate the width and the height of the area. Extend width until it's a multiple of 4. This will be of advantage as QImage will process 32bit aligned bitmaps much faster. */ unsigned int w1 = (xoff2 - xoff1 + 3) & ~0x03; unsigned int h1 = (yoff2 - yoff1); // bail out if this is getting too big if(w1 > 10000 || h1 > 10000) return; // now calculate the actual width and height of the viewport unsigned int w2 = w1 * xscale / my_xscale; unsigned int h2 = h1 * yscale / my_yscale; // as the first point off the DEM data will not match exactly the given top left corner // the bitmap has to be drawn with an offset. int pxx = ((xoff1_f - xoff1) * xscale - (r1.u - _p1.u)) / my_xscale; int pxy = ((yoff1_f - yoff1) * yscale - (r1.v - _p1.v)) / my_yscale; // read 16bit elevation data from GeoTiff QVector<qint16> data(w1*h1); GDALRasterBand * pBand; pBand = dataset->GetRasterBand(1); CPLErr err = pBand->RasterIO(GF_Read, xoff1, yoff1, qMin(w1, xsize_px - xoff1), qMin(h1, ysize_px - yoff1), data.data(), w1, h1, GDT_Int16, 0, 0); if(err == CE_Failure) { return; } QImage img(w1,h1,QImage::Format_Indexed8); if(overlay == IMap::eShading) { shading(img,data.data(), my_xscale, my_yscale); } else if(overlay == IMap::eContour) { contour(img,data.data(), my_xscale, my_yscale); } else if(overlay == IMap::eSlope) { slope(img,data.data(), xoff1, yoff1); } else { qWarning() << "Unknown shading type"; return; } // Finally scale the image to viewport size. QT will do the smoothing //img = img.scaled(w2,h2, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); QPainter p(&pixBuffer); p.drawImage(-pxx, -pxy, img.scaled(w2,h2, Qt::IgnoreAspectRatio,Qt::SmoothTransformation)); }
void drawPlant() { int i; glEnable(GL_LIGHTING); shading(4); glPushMatrix(); glTranslatef(0.0, -5.0 + plantHeight / 2, 0.0); glScalef(0.85, 0.85, 0.85); glRotatef(2 * wind, 0.0, 0.0, -1.0); glTranslatef(0.0, -plantHeight / 2., 0.0); glRotatef(falltheta - 1.0, 0.0, 0.0, -1.0); glPushMatrix(); glRotatef(90, -1, 0, 0); gluCylinder(gluNewQuadric(), plantWidth, plantWidth, plantHeight, 10, 10); if (grow>1){ shading(3); glPushMatrix(); glRotatef(90, -1, 0, 0); glRotatef(100.0, 0.0, 1.0, 0.0); glTranslatef(plantWidth, -plantHeight / 2.5, 0.0); glRotatef(10 * sin(2 * PI*(randrotation[GRASSAREA - 6] % 100 + 1) / 100 + thetawind*PI / 180.0)*wind, 0.0, 0.0, 1.0); glRotatef(90, 1, 0, 0); gluDisk(gluNewQuadric(), 0.0, diskR, 10, 10); glPopMatrix(); glPushMatrix(); glRotatef(90, -1, 0, 0); glRotatef(-45.0, 0.0, 1.0, 0.0); glTranslatef(plantWidth, -plantHeight / 2., 0.0); glRotatef(10 * sin(2 * PI*(randrotation[GRASSAREA - 7] % 100 + 1) / 100 + thetawind*PI / 180.0)*wind, 0.0, 0.0, 1.0); glRotatef(90, 1, 0, 0); gluDisk(gluNewQuadric(), 0.0, diskR, 10, 10); glPopMatrix(); glPushMatrix(); glRotatef(90, -1, 0, 0); glRotatef(170.0, 0.0, 1.0, 0.0); glTranslatef(plantWidth, -plantHeight / 5., 0.0); glRotatef(10 * sin(2 * PI*(randrotation[GRASSAREA - 8] % 100 + 1) / 100 + thetawind*PI / 180.0)*wind, 0.0, 0.0, 1.0); glRotatef(90, 1, 0, 0); gluDisk(gluNewQuadric(), 0.0, diskR, 10, 10); glPopMatrix(); } glPopMatrix(); glTranslatef(0.0, plantHeight - 0.2, 0.0); if (falltheta <= 70) glTranslatef(0.3*wind, 0.0, 0.0); else glTranslatef(-0.1*pow(2.71, -t4 / 10)*sin(t4*PI / 4), 0.0, 0.0); if (grow>2) { for (i = 0; i<5; i++){ glPushMatrix(); glRotatef((float)i*360. / 5., 0.0, 1.0, 0.0); if (falltheta <= 70) glTranslatef(0.0, 0.05*sin(2 * PI*(randrotation[GRASSAREA - i] % 100 + 1) / 100 + thetawind*PI / 180.0)*wind, 0.0); glTranslatef(growleaves*0.1 + plantWidth, 0.2*movey[i], 0.0); glScalef(1. + .5*scalex[i], 0.9, 1. + .2*scalez[i]); glutSolidSphere(leafR, 10, 10); glPopMatrix(); } } glPopMatrix(); glDisable(GL_LIGHTING); }
RTColor RTRayTracer::traceRay(RTRay &ray, int depth, RTLight light) { RTColor color(135,206,250); if(depth>scene.getMaxDepth()) { RTColor zero(0,0,0); return zero; //BLACK } std::vector<RTObject*> objects = this->scene.getPrimitives(); RTObject *closestObject=NULL; RTVector hitPoint,closestPoint; double t,nearest=INF; //percorre objetos da cena for(unsigned int io=0; io<objects.size(); io++) { //testa a inte rseção if(!objects[io]->intersect(ray,t)) continue; else { //hit hitPoint = ray.getPos()+(ray.getDir()*t); t= hitPoint.getNorma(); if(t<nearest) { nearest = t; closestObject=objects[io]; closestPoint=hitPoint; } } } if(nearest==INF) { //nao intersecionou return color; } RTColor reflectColor,refracColor,objColor; int surfaceType=closestObject->getBrdf()->getSurfaceType(); double fogFactor=0; //verifica se existe fog na cena if(scene.getHasFog()) { //calcula o fator fog fogFactor=(scene.getFog().getZ_end()-closestPoint.getZ())/(scene.getFog().getZ_end()-scene.getFog().getZ_start()); fogFactor=(fogFactor>1.0)?1.0:((fogFactor<0)?0:fogFactor); //clamp //fogFactor=pow(M_E,-scene.getFog().getDensity()*closestPoint.getZ()); } objColor= shading(closestObject, closestPoint, light); double reflectivePercentage = closestObject->getBrdf()->getKr(); double refractivePercentage = 0; bool isInside=false; double refraIndex=closestObject->getBrdf()->getRefracIndex(); if(surfaceType==REFLECTIVE||surfaceType==REFRACTIVE) { RTVector eyedir = -((ray.getPos()*1)-closestPoint); //d eyedir.normalize(); RTVector normal = closestObject->normalOfHitPoint(closestPoint);//N if(surfaceType==REFRACTIVE) { //aplica fresnel if(closestObject->getObjTag()==SPHERE) { //verifica se o raio de refração segue para dentro da esfera RTSphere *sp= dynamic_cast<RTSphere*>(closestObject); double centerDist =sqrt(pow(ray.getPos().getX() - sp->getCenter().getX(), 2) + pow(ray.getPos().getY() - sp->getCenter().getY(), 2) + pow(ray.getPos().getZ() - sp->getCenter().getZ(), 2)); isInside=(centerDist<sp->getRadius()); } reflectivePercentage=FresnelTerm(eyedir,normal,refraIndex,isInside); //R refractivePercentage=1-reflectivePercentage; //(1-R) } if(reflectivePercentage>0) { //calcula reflexão RTRay reflectionRay=genReflectionRay(eyedir,normal,closestPoint); reflectColor=(traceRay(reflectionRay,depth+1,light)); } if(refractivePercentage>0) { double refraIndex=closestObject->getBrdf()->getRefracIndex(); RTRay refracRay=genRefractRay(eyedir,normal,closestPoint,refraIndex,isInside); refracColor=(traceRay(refracRay,depth+1,light)); } } if(surfaceType==REFRACTIVE&&!isInside) { color=reflectColor*reflectivePercentage+refracColor*(refractivePercentage); } else { int kloc=(surfaceType==REFRACTIVE)?0:1; color=reflectColor*reflectivePercentage+refracColor*refraIndex+objColor*kloc; color=color/(reflectivePercentage+refractivePercentage+kloc); } if(scene.getHasFog()) color=(color*fogFactor)+(scene.getFog().getFogColor()*((1-fogFactor))); return color; }