环境:WinXP/Win7 Perl v5.16.3
需要图形渲染模块:OpenGL
单条Bezier的绘制函数参考 Wikipedia:貝茲曲線- =info
- Code By 523066680/vicyang
- 2015-01-02
- =cut
-
- use v5.16;
- use IO::Handle;
- use OpenGL qw/ :all /;
- use OpenGL::Config;
- use Time::HiRes 'sleep';
-
- STDOUT->autoflush(1);
-
- our $WinID;
- &Main();
-
- sub delta {
- my ($pta, $ptb) = @_;
- my $dtx = ($ptb->[0] - $pta->[0]);
- my $dty = ($ptb->[1] - $pta->[1]);
- my $delta = sqrt ($dtx ** 2 + $dty ** 2);
- return ($delta, $dtx, $dty);
- }
-
- sub PointOnCubicBezier {
- my ($cp0, $cp1, $cp2, $cp3, $t) = @_;
-
- my ($cx, $bx, $ax, $cy, $by, $ay);
- my ($tSquared, $tCubed, $result);
-
- $cx = 3.0 * ($cp1->[0] - $cp0->[0]);
- $bx = 3.0 * ($cp2->[0] - $cp1->[0]) - $cx;
- $ax = $cp3->[0] - $cp0->[0] - $cx - $bx;
-
- $cy = 3.0 * ($cp1->[1] - $cp0->[1]);
- $by = 3.0 * ($cp2->[1] - $cp1->[1]) - $cy;
- $ay = $cp3->[1] - $cp0->[1] - $cy - $by;
-
- $tSquared = $t **2;
- $tCubed = $t **3;
-
- $result->[0] = (
- ($ax * $tCubed) +
- ($bx * $tSquared) +
- ($cx * $t) +
- $cp0->[0]
- );
- $result->[1] = (
- ($ay * $tCubed) +
- ($by * $tSquared) +
- ($cy * $t) +
- $cp0->[1]
- );
-
- return $result;
- }
-
- sub getRevPoint {
- my ($A, $O, $B) = (shift, shift, undef);
-
- $B->[0] = $O->[0] + ($O->[0] - $A->[0]);
- $B->[1] = $O->[1] + ($O->[1] - $A->[1]);
-
- return $B;
- }
-
- sub display {
- state $count = 0;
- state $loops = 0;
-
- my ($i, $j);
- my $coord;
-
- my ($dt, $dtx, $dty);
-
- state $n_cpts = 4; #四个控制点
- state $cpts_path_parts = 50;
- state $bezier_parts = 30; #每条贝塞尔曲线分30部分
- state $n_bezier = 30; #贝塞尔曲线的堆叠数量
- state $curve = []; #每个cpt的曲线路径存储
- state $pti = 0; #pti数组记录4个cpt的其自身的cpt'坐标
- state $pt = [
- [0.0, 0.0],
- [0.0, 0.0],
- [0.0, 0.0],
- [0.0, 0.0],
- ];
-
- state $ptarr = [];
-
- if (($loops == 0) and ($count == 0)) {
- for $i (0 .. $n_bezier-1) {
- for $j (0 .. $bezier_parts) {
- $ptarr->[$i][$j] = [1000.0, -1000.0];
- }
-
- $curve->[$i] = [
- [rand(200)-100.0, rand(200)-100.0],
- [rand(200)-100.0, rand(200)-100.0],
- [rand(200)-100.0, rand(200)-100.0],
- [rand(200)-100.0, rand(200)-100.0]
- ]
- }
- }
-
- #处理四个控制点的演变
- RECOUNT:
- if ( $pti <= $cpts_path_parts ) {
- for $i (0 .. $n_cpts-1) {
- $coord = &PointOnCubicBezier(
- @{$curve->[$i]}[0..3],
- $pti/$cpts_path_parts
- );
- $pt->[$i] = $coord; #第 $i+1 个 cpt 的坐标
- }
- $pti++;
- } else {
- #控制点超过50次的时候,创建新的随机控制点,从头开始
- #起点是上一次的第50个点,同时也是新曲线的第0点
- #为了避免点重合,新的曲线点下标从1开始,而不是0开始
- for $i (0 .. $n_cpts-1) {
- $curve->[$i] = [
- $pt->[$i],
- getRevPoint($curve->[$i][2], $curve->[$i][3]),
- #Control Point 3 is A, Point 4 is O, Find Point B
- [rand(200)-100.0, rand(200)-100.0],
- [rand(200)-100.0, rand(200)-100.0]
- ];
- }
- $pti = 1;
- goto RECOUNT;
- }
-
-
- glClear(GL_COLOR_BUFFER_BIT);
- glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
-
- glPushMatrix();
- for $i (0 .. $bezier_parts ) {
- $coord = &PointOnCubicBezier(
- @{$pt}[0, 1, 2, 3],
- $i/$bezier_parts
- );
- $ptarr->[$count][$i] = $coord;
- }
-
- glBegin(GL_POINTS);
-
-
- for $i (0 .. $n_bezier-1) {
- glColor4f(0.4, 0.6, 0.8, 0.5);
- for $j (0.0 .. $bezier_parts) {
- glVertex3f($ptarr->[$i][$j][0], $ptarr->[$i][$j][1], 0.0);
- }
- }
- glEnd();
-
- glPopMatrix();
- glutSwapBuffers();
-
- if ($count < ($n_bezier-1)) {
- $count++;
- } else {
- $count = 0;
- $loops++;
- }
-
- }
-
- sub init {
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glPointSize(6.0);
- glLineWidth(10.0);
- glEnable(GL_BLEND);
- glEnable(GL_POINT_SMOOTH);
- glEnable(GL_LINE_SMOOTH);
- }
-
- sub idle {
- sleep 0.05;
- glutPostRedisplay();
- }
-
- sub Reshape {
- glViewport(0.0,0.0,500.0,500.0);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-100.0,100.0,-100.0,100.0,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 $key = shift;
- if (lc(chr($key)) eq 'q') {
- glutDestroyWindow($WinID);
- } elsif ($key == 27) {
- glutDestroyWindow($WinID);
- }
- }
-
- sub Main {
- glutInit();
- glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE );#| GLUT_MULTISAMPLE);
- glutInitWindowSize(500, 500);
- glutInitWindowPosition(1,1);
- our $WinID = glutCreateWindow("Curve_Vic");
- &init();
- glutDisplayFunc(\&display);
- glutReshapeFunc(\&Reshape);
- glutKeyboardFunc(\&hitkey);
- glutIdleFunc(\&idle);
- glutMainLoop();
- }
复制代码
|