二维的射线跟踪
想要做一个光线跟踪引擎,感觉太困难了,虽然原理不太复杂,但是还是很难搞所以先搞一个二维的试试
这个是图形学那本书上的一个课后作业,就是试试反射怎么反射,做出来效果是这样的,从左下角出发的射线
经过几次反射的路径

代码:(main)
/*Author: lishicaoDate: 2013.2.19*/#include <iostream>#include <fstream>#include <windows.h>#include <gl/gl.h>#include <gl/glu.h>#include <gl/glut.h>#include "Common.h"using namespace std ;ofstream fout ( "ans.txt" ) ;void setWindow( double , double , double , double ) ;void setViewport( int , int , int , int ) ;void myDisplay() ;void myInit() ;void input() ;Line ray ;int main( int argc , char ** argv ){ input() ; glutInit( & argc , argv ) ; glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB ) ; glutInitWindowSize( 640 , 640 ) ; glutCreateWindow( "RayTracer2D" ) ; glutDisplayFunc( myDisplay ) ; myInit() ; setWindow( -5.0 , 15.0 , -5.0 , 15.0 ) ; setViewport( 0 , 640 , 0 , 640 ) ; glutMainLoop() ; return 0 ;}void input(){ Point P[4] ; Line lin[4] ; ObjectNumber = 0 ; memset( Count , 0 , sizeof( Count ) ) ; memset( line , 0 , sizeof( line ) ) ; memset( Count , 0 , sizeof( Count ) ) ; cout << "Input the Rectangle( two point ) " << endl ; cin >> P[0].x >> P[0].y ; cin >> P[3].x >> P[3].y ; P[1].x = P[0].x ; P[1].y = P[3].y ; P[2].x = P[3].x ; P[2].y = P[0].y ; lin[0].start = P[0] ; lin[0].end = P[1] ; lin[1].start = P[1] ; lin[1].end = P[3] ; lin[2].start = P[3] ; lin[2].end = P[2] ; lin[3].start = P[2] ; lin[3].end = P[0] ; for( int i = 0 ; i <= 3 ; i ++ ){ lin[i].flag = 2 ; line[ObjectNumber][i] = lin[i] ; } ObjectNumber ++ ; Count[0] = 3 ; char ch , str ; while( 1 ) { cout << "any other object? Y|N" << endl ; cin >> ch ; if( ch == 'N' ) break ; while( 1 ) { cout << "input Segment? Y|N" << endl ; cin >> str ; Line LINE ; if( str == 'N' ) break ; cout << "input two point " << endl ; cin >> LINE.start.x >> LINE.start.y >> LINE.end.x >> LINE.end.y ; LINE.flag = 2 ; line[ObjectNumber][Count[ObjectNumber]] = LINE ; Count[ObjectNumber] ++ ; } ObjectNumber ++ ; } cout << "input ray" << endl ; cin >> ray.start.x >> ray.start.y >> ray.end.x >> ray.end.y ; ray.flag = 1 ;}void setWindow( double left , double right , double buttom , double top ){ glMatrixMode( GL_PROJECTION ) ; glLoadIdentity() ; gluOrtho2D( left , right , buttom , top ) ;}void setViewport( int left , int right , int buttom , int top ){ glViewport( left , buttom , right - top , top - buttom ) ;}void myInit(){ glClearColor( 1.0 , 1.0 , 1.0 , 0.0 ) ; glColor3f( 0.0 , 0.0 , 1.0 ) ; glLineWidth( 2.0 ) ;}void myDisplay(){ glClear( GL_COLOR_BUFFER_BIT ) ; glMatrixMode( GL_MODELVIEW ) ; glLoadIdentity() ; for( int i = 0 ; i <= ObjectNumber ; i ++ ) for( int j = 0 ; j <= Count[i] ; j ++ ) { glBegin( GL_LINES ) ; glVertex2f( line[i][j].start.x , line[i][j].start.y ) ; glVertex2f( line[i][j].end.x , line[i][j].end.y ) ; glEnd() ; glFlush() ; } int cnt = 0 ; Point P ; Line * temp ; Line tmp , next ; while( cnt <= 10 ) { P.x = 0 ; P.y = 0 ; temp = RayFirstCollision( ray , P ) ; tmp = *temp ; next = reflection( ray , tmp ) ; for( double i = 0 ; i <= 1 ; i += 0.001 ) { Point cur ; cur.x = ray.start.x + i * ( P.x - ray.start.x ) ; cur.y = ray.start.y + i * ( P.y - ray.start.y ) ; glBegin( GL_POINTS ) ; glVertex2f( cur.x , cur.y ) ; glEnd() ; glFlush() ; } ray = next ; cnt ++ ; }}
common.h:
#include <gl/gl.h>#include <gl/glu.h>#include <gl/glut.h>#include <cmath>#include <iostream>using namespace std ;const double INF = 999999999 ;class Point{ public : double x , y ; int flag ; //0是向量,1是点} ;class Line{ public : Point start , end ; double K , B ; int flag ; // 0 是直线 1是射线 2是线段 void calc() { if( end.x - start.x < 0.00001 && end.x - start.x > -0.00001 ) { K = INF ; B = INF ; } else { K = ( end.y - start.y ) / ( end.x - start.x ) ; B = start.y - K * start.x ; } }} ;Line line[100][100] ;int ObjectNumber ;int Count[100] ;Point segIntersect( Line L1 , Line L2 ){ Point P ; L1.calc() ; L2.calc() ; if( L1.K == L2.K ) { P.x = 0 ; P.y = 0 ; P.flag = INF ; return P ; } if( L1.K == INF ) { P.x = L1.start.x ; P.y = L2.K * L1.start.x + L2.B ; } else if( L2.K == INF ) { P.x = L2.start.x ; P.y = L1.K * L2.start.x + L1.B ; } else { P.x = ( L2.B - L1.B ) / ( L1.K - L2.K ) ; P.y = L1.K * P.x + L1.B ; } return P ;}bool Intersect( Line L1 , Line L2 , Point &P ){ P = segIntersect( L1 , L2 ) ; if( P.x == 0 && P.y == 0 && P.flag == INF ) return false ; if( ( P.x - L1.start.x ) * ( P.x - L1.end.x ) <= 0 ) { if( ( P.x - L2.start.x ) * ( P.x - L2.end.x ) <= 0 ) return true ; else { if( L2.flag == 2 ) return false ; else if( L2.flag == 1 ) { if( ( L2.start.x - P.x ) * ( L2.start.x - L2.end.x ) < 0 ) return false ; else return true ; } else if( L2.flag == 0 ) return true ; } } else { if( L1.flag == 2 || ( L1.flag == 1 && ( L1.start.x - P.x ) * ( L1.start.x - L1.end.x ) <= 0 ) ) return false ; else { if( ( P.x - L2.start.x ) * ( P.x - L2.end.x ) <= 0 ) return true ; else if( ( L2.flag == 1 && ( L2.start.x - P.x ) * ( L2.start.x - L2.end.x ) >= 0 ) || L2.flag == 0 ) return true ; else return false ; } } return false ;}Line * RayFirstCollision( Line ray , Point & P ){ double Length = INF ; Line * nearest ; Point point ; int i , j ; for( i = 0 ; i <= ObjectNumber ; i ++ ) for( j = 0 ; j <= Count[i] ; j ++ ) if( Intersect( ray , line[i][j] , point ) ) { if( fabs( point.x - ray.start.x ) < 0.00001 && fabs( point.y - ray.start.y ) < 0.00001 ) continue ; if( fabs( ray.start.x - point.x ) < Length ) { Length = fabs( ray.start.x - point.x ) ; P = point ; nearest = &line[i][j] ; } } return nearest ;}Line reflection( Line ray , Line seg ){ Line nextRay , par , temp ; Point point , P , end , inter ; Point vector , vector_N ; Intersect( ray , seg , point ) ; vector.x = seg.end.x - seg.start.x ; vector.y = seg.end.y - seg.start.y ; if( vector.y != 0 ) { vector_N.x = 1 ; vector_N.y = ( - vector_N.x * vector.x ) / vector.y ; } else { vector_N.x = 0 ; vector_N.y = 1 ; } end.x = ray.start.x + vector.x ; end.y = ray.start.y + vector.y ; par.start = ray.start ; par.end = end ; par.flag = 0 ; temp.start = point ; end.x = point.x + vector_N.x ; end.y = point.y + vector_N.y ; temp.end = end ; temp.flag = 0 ; Intersect( par , temp , inter ) ; P.x = ( inter.x - ray.start.x ) * 2 + ray.start.x ; P.y = ( inter.y - ray.start.y ) * 2 + ray.start.y ; nextRay.start = point ; nextRay.end = P ; nextRay.flag = 1 ; return nextRay ;}
恩,写得太搓了==