没错,跳票已久的 “然而并没有什么卵用” 系列 (先自嘲一番,即使舆论出了偏差,也有心理准备)
首发 Perl+OpenGL 重绘inkscape生成的svg矢量图
当前主要是绘制路径,细节有待完善。multi.svg 由开源软件 inkscape 绘制并导出,你可以拖入浏览器中查看 | | | | | | | | | | | use IO::Handle; | | use OpenGL qw/ :all /; | | use OpenGL::Config; | | use Time::HiRes 'sleep'; | | use feature 'state'; | | | | STDOUT->autoflush(1); | | | | open READ, "<:raw", "multi.svg"; | | my @all; | | my $tl; | | for my $line (<READ>) | | { | | if ( $line=~/\s+d="(.*)"/ ) | | { | | @all = split(" ", $1 ); | | } | | } | | | | my @coords; | | | | for my $e (@all) | | { | | if ( $e =~/[a-zA-Z]/ ) | | { | | $head = $e; | | next; | | } | | push @coords, | | { | | 'head' => $head, | | 'data' => [ split(",", $e) ], | | }; | | } | | | | | | my ($ox, $oy); | | for (my $i = 0; $i <= $#coords; $i++) | | { | | if ($coords[$i]->{head} eq 'c') | | { | | grep | | { | | $coords[ $i+$_ ]->{'data'}[0] += $ox; | | $coords[ $i+$_ ]->{'data'}[1] += $oy; | | } (0..2) ; | | $i += 2; | | } | | else | | { | | | | } | | | | ($ox, $oy) = ($coords[$i]->{'data'}[0], $coords[$i]->{'data'}[1]) ; | | } | | | | my ($xmin, $xmax, $ymin, $ymax) = (10000.0, -10000.0, 10000.0, -10000.0); | | for my $e (@coords) | | { | | printf("%.2f, %.2f\n", $e->{'data'}[0], $e->{'data'}[1]); | | $xmin = $e->{'data'}[0] if ($e->{'data'}[0] < $xmin); | | $xmax = $e->{'data'}[0] if ($e->{'data'}[0] > $xmax); | | | | $ymin = $e->{'data'}[1] if ($e->{'data'}[1] < $ymin); | | $ymax = $e->{'data'}[1] if ($e->{'data'}[1] > $ymax); | | } | | printf("%f %f %f %f\n", $xmin, $xmax, $ymin, $ymax); | | | | &Main(); | | | | sub display | | { | | glClear(GL_COLOR_BUFFER_BIT); | | glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA); | | | | glPushMatrix(); | | | | my $array; | | my @points; | | | | for (my $i = 0; $i <= $#coords; $i++) | | { | | if ($coords[$i]->{head} =~/C/i) | | { | | glColor4f(0.0,0.5,0.0,1.0); | | $array = OpenGL::Array->new( 3*4, GL_FLOAT); | | @points = ( | | $coords[$i-1]->{'data'}[0], $coords[$i-1]->{'data'}[1], 0.0 , | | $coords[$i+0]->{'data'}[0], $coords[$i+0]->{'data'}[1], 0.0 , | | $coords[$i+1]->{'data'}[0], $coords[$i+1]->{'data'}[1], 0.0 , | | $coords[$i+2]->{'data'}[0], $coords[$i+2]->{'data'}[1], 0.0 , | | ); | | | | $array->assign(0, @points); | | | | glMap1f_c(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, $array->ptr); | | glMapGrid1f(20, 0.0, 1.0); | | glEvalMesh1(GL_LINE, 0, 20); | | $i+=2; | | } | | elsif ($coords[$i]->{head} =~/Q/i) | | { | | glColor4f(0.0,0.5,0.0,1.0); | | $array = OpenGL::Array->new( 3*3, GL_FLOAT); | | | | @points = ( $coords[$i-1]->{'data'}[0], $coords[$i-1]->{'data'}[1], 0.0, | | $coords[$i+0]->{'data'}[0], $coords[$i+0]->{'data'}[1], 0.0 , | | $coords[$i+1]->{'data'}[0], $coords[$i+1]->{'data'}[1], 0.0 , | | ); | | | | $array->assign(0, @points); | | | | glMap1f_c(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 3, $array->ptr); | | glMapGrid1f(20, 0.0, 1.0); | | glEvalMesh1(GL_LINE, 0, 20); | | $i += 1; | | } | | elsif ($coords[$i]->{head} =~/L/i) | | { | | glBegin(GL_LINES); | | glVertex3f( $coords[$i-1]->{'data'}[0], $coords[$i-1]->{'data'}[1], 0.0 ); | | glVertex3f( $coords[$i]->{'data'}[0], $coords[$i]->{'data'}[1], 0.0 ); | | glEnd(); | | } | | elsif ($coords[$i]->{head} =~/M/i) | | { | | glBegin(GL_POINTS); | | glColor3f(1.0, 1.0, 1.0); | | glVertex3f( $coords[$i]->{'data'}[0], $coords[$i]->{'data'}[1], 0.0 ); | | glEnd(); | | } | | } | | | | glPopMatrix(); | | glutSwapBuffers(); | | } | | | | sub init | | { | | glClearColor(0.0, 0.0, 0.0, 1.0); | | glPointSize(2.0); | | glLineWidth(2.0); | | glEnable(GL_BLEND); | | glEnable(GL_POINT_SMOOTH); | | glEnable(GL_LINE_SMOOTH); | | glEnable(GL_MAP1_VERTEX_3); | | } | | | | sub idle | | { | | sleep 0.05; | | glutPostRedisplay(); | | } | | | | sub Reshape | | { | | my $half = 1000; | | glViewport(0, 0, 500.0, 500.0); | | glMatrixMode(GL_PROJECTION); | | glLoadIdentity(); | | | | glOrtho($xmin, $xmax, $ymin, $ymax, 0.0, 200.0); | | glMatrixMode(GL_MODELVIEW); | | glLoadIdentity(); | | gluLookAt(0.0,0.0,100.0,0.0,0.0,0.0, 0.0,1.0,100.0); | | } | | | | sub hitkey | | { | | my $keychar = lc(chr(shift)); | | if ($keychar eq 'q') | | { | | glutDestroyWindow($WinID); | | } | | } | | | | sub Main | | { | | glutInit(); | | glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE ); | | glutInitWindowSize(500, 500); | | glutInitWindowPosition(1,1); | | our $WinID = glutCreateWindow("title"); | | &init(); | | glutDisplayFunc(\&display); | | glutReshapeFunc(\&Reshape); | | glutKeyboardFunc(\&hitkey); | | glutIdleFunc(\&idle); | | glutMainLoop(); | | } | | | | | | __END__ | | 要使glMap1f_c 正常工作,需要借用OpenGL::Array 建立一个 | | 仿C的指针 | | | | my $array = OpenGL::Array->new( 3*4, GL_FLOAT); | | $array->assign(0, @points); | | | | glMap1f_c(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, $array->ptr); | | glEnable(GL_MAP1_VERTEX_3);COPY |
IE浏览 VS 重绘
 |