没错,跳票已久的 “然而并没有什么卵用” 系列 (先自嘲一番,即使舆论出了偏差,也有心理准备)
首发 Perl+OpenGL 重绘inkscape生成的svg矢量图
当前主要是绘制路径,细节有待完善。multi.svg 由开源软件 inkscape 绘制并导出,你可以拖入浏览器中查看- =info
- Author: 523066680
- Date: 2016-11
- =cut
-
- 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 始终是最后一点的坐标值
- ($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(-$half, $half, -$half, $half, 0.0, 200.0);
- 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);
复制代码 IE浏览 VS 重绘
|