- 論壇徽章:
- 12
|
本帖最后由 523066680 于 2015-01-03 15:05 編輯
首先當(dāng)然是要安裝OpenGL模塊。
舊版本的OpenGL自帶Bezier求值器,但是并不返回坐標(biāo)值,而是求值并幫你進(jìn)行了頂點(diǎn)繪制操作。
為了能夠更自由地操縱頂點(diǎn)數(shù)據(jù),還是到wikipedia挖了一段函數(shù):
zh.wikipedia.org/wiki/貝茲曲線 ,將 PointOnCubicBezier函數(shù) 轉(zhuǎn)成Perl語言的格式
然后用50x50x3的結(jié)構(gòu)數(shù)組對頂點(diǎn)進(jìn)行存儲,迭代替換,效果就做出來啦,應(yīng)該還有很大優(yōu)化空間 
002.gif (1 MB, 下載次數(shù): 49)
下載附件
2015-01-03 15:05 上傳
圖片都超過1MB,其他的發(fā)到網(wǎng)絡(luò)相冊里了 paktc.lofter.com/post/45586_4f19e97- =info
- Code By: vicyang/5230
- E-mail : paktcmail@gmail.com
- DATE : 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; #四個控制點(diǎn)
- state $cpts_path_parts = 50;
- state $bezier_parts = 50; #每條貝塞爾曲線分50部分
- state $n_bezier = 50; #貝塞爾曲線的堆疊數(shù)量
- state $curve = []; #每個cpt的曲線路徑存儲
- state $pti = 0; #pti數(shù)組記錄4個cpt的其自身的cpt'坐標(biāo)
- 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]
- ]
- }
- }
-
- #處理四個控制點(diǎn)的演變
- 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 的坐標(biāo)
- }
- $pti++;
- } else {
- #控制點(diǎn)超過50次的時候,創(chuàng)建新的隨機(jī)控制點(diǎn),從頭開始
- #起點(diǎn)是上一次的第50個點(diǎn),同時也是新曲線的第0點(diǎn)
- #為了避免點(diǎn)重合,新的曲線點(diǎn)下標(biāo)從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(5.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();
- }
復(fù)制代碼 |
|