找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 21821|回复: 3

[原创代码] Perl 绘制3D模型文件 - 斯坦福兔子 (ply格式)

[复制链接]
发表于 2017-1-10 12:00:35 | 显示全部楼层 |阅读模式
本帖最后由 523066680 于 2017-1-10 12:06 编辑



模型文件下载地址
http://www.cc.gatech.edu/projects/large_models/bunny.html

以及针对这只兔子的渲染代码,没有做成通用的,在加载不同模型的时候需要自己调整大小和位置以适应窗口

使用说明:需要 OpenGL 模块的支持,成功渲染后,按 w a s d, j k 可以旋转观察角度。
  1. =Copy is not Right
  2.     Author: 523066680@163.com
  3.       Date: 2016-12
  4. =cut

  5. use v5.16;
  6. use IO::Handle;
  7. use OpenGL qw/ :all /;
  8. use OpenGL::Config;
  9. use Time::HiRes 'sleep';
  10. use feature 'state';
  11. STDOUT->autoflush(1);

  12. our $WinID;
  13. our $width  = 500;
  14. our $height = 500;

  15. our $rx = 0.0;
  16. our $ry = 0.0;
  17. our $rz = 0.0;

  18. my @vtx;
  19. my @faces;

  20. open READ, "<:raw", "bunny.ply";
  21. my $models = 0;

  22. for  my $e ( <READ> )
  23. {
  24.     $e =~ s/\r?\n$//;
  25.     if ($e =~ /v ([^\s]+) ([^\s]+) ([^\s]+)/i )
  26.     {
  27.         #考虑 科学表示法的情况 5.5e-05
  28.         push @vtx, [ sprintf("%f", $1) * 1500.0,
  29.                      sprintf("%f", $2) * 1500.0,
  30.                      sprintf("%f", $3) * 1500.0 ] ;
  31.     }
  32.     elsif ($e =~ /f (\d+) (\d+) (\d+)/i )
  33.     {
  34.         #某些模型文件的三角形索引从 1 开始
  35.         push @faces,
  36.             [
  37.                 $1 - 1,
  38.                 $2 - 1,
  39.                 $3 - 1
  40.             ];
  41.     }
  42.     else
  43.     {
  44.         printf("Other: $e\n");
  45.     }

  46.     if ($e =~ /feature/i )
  47.     {
  48.         $models++;
  49.         if ($models > 1)
  50.         {
  51.             #last;
  52.         }
  53.     }
  54. }
  55. close READ;

  56. printf("%d %d\n", $#vtx, $#faces);

  57. printf("%f %f %f\n", $vtx[0]->[0], $vtx[0]->[1], $vtx[0]->[2] );
  58. my @nums;
  59. grep { push @nums, @{$_} } @faces;
  60. @nums = (sort { $a <=> $b } @nums);
  61. printf("\n %d\n", $nums[$#nums]);

  62. &Main();

  63. sub normalize
  64. {
  65.     my $v = shift;
  66.     my $d = sqrt($v->[0]*$v->[0] + $v->[1]*$v->[1] + $v->[2]*$v->[2]);
  67.     if ($d == 0.0)
  68.     {
  69.         printf("length zero!\n");
  70.         return;
  71.     }

  72.     $v->[0] /= -$d;
  73.     $v->[1] /= -$d;
  74.     $v->[2] /= -$d;
  75. }

  76. sub normcrossprod
  77. {
  78.     my ( $v1, $v2, $out ) = @_;

  79.     $out->[0] = $v1->[1] * $v2->[2] - $v1->[2] * $v2->[1];
  80.     $out->[1] = $v1->[2] * $v2->[0] - $v1->[0] * $v2->[2];
  81.     $out->[2] = $v1->[0] * $v2->[1] - $v1->[1] * $v2->[0];

  82.     normalize( $out );
  83. }

  84. sub initlist
  85. {
  86.     my $idx;
  87.     my $base = glGenLists(1);
  88.     my ($a, $b, $c);

  89.     my @tpa;
  90.     my @tpb;
  91.     my @norm = ();

  92.     glNewList($base, GL_COMPILE);

  93.     glBegin(GL_TRIANGLES);

  94.     for my $i ( 0 ..  $#faces )
  95.     {
  96.         ($a, $b, $c) = @{ $faces[$i] } ;

  97.         for ( 0 .. 2 )
  98.         {
  99.             $tpa[$_] = $vtx[$b]->[$_] - $vtx[$a]->[$_] ;
  100.             $tpb[$_] = $vtx[$c]->[$_] - $vtx[$a]->[$_] ;
  101.         }

  102.         glColor3f( 0.9, 0.6, 0.2 );
  103.         normcrossprod( \@tpa, \@tpb, \@norm );

  104.         glNormal3f( @norm );
  105.         glVertex3f( @{$vtx[$a]} );
  106.         glVertex3f( @{$vtx[$b]} );
  107.         glVertex3f( @{$vtx[$c]} );
  108.     }
  109.     glEnd();

  110.     glEndList();
  111. }

  112. sub display
  113. {
  114.     my $idx;
  115.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  116.     glPushMatrix();
  117.     glRotatef($rx, 1.0, 0.0, 0.0);
  118.     glRotatef($ry, 0.0, 1.0, 0.0);
  119.     glRotatef($rz, 0.0, 0.0, 1.0);
  120.     glTranslatef(0.0, -150.0, 0.0);
  121.     glColor4f(0.8, 0.8, 0.5, 0.5);

  122.     glCallList(1);

  123.     glPopMatrix();
  124.     glutSwapBuffers();
  125. }

  126. sub init
  127. {
  128.     glClearColor(0.0, 0.0, 0.0, 0.5);
  129.     glPointSize(1.0);
  130.     glLineWidth(1.0);
  131.     glEnable(GL_DEPTH_TEST);
  132.     glEnable(GL_POINT_SMOOTH);
  133.     glEnable(GL_LINE_SMOOTH);
  134.    
  135.     my @mat_ambient = ( 0.5, 0.5, 0.5, 1.0 );
  136.     my @mat_specular = ( 1.0, 1.0, 1.0, 1.0 );
  137.     my @mat_shininess = ( 10.0 );
  138.     my @mat_diffuse = (0.5, 0.5, 0.5, 1.0);

  139.     my @light_specular = ( 0.5, 0.5, 0.5, 1.0 );
  140.     my @light_position = ( 200.0, 400.0, 0.0, 0.0 );

  141.     my $ambient  = OpenGL::Array->new( 4, GL_FLOAT);
  142.     my $specular = OpenGL::Array->new( 4, GL_FLOAT);
  143.     my $diffuse  = OpenGL::Array->new( 4, GL_FLOAT);
  144.     my $shininess = OpenGL::Array->new( 1, GL_FLOAT);

  145.     my $light_position = OpenGL::Array->new( 4, GL_FLOAT);
  146.     my $light_specular = OpenGL::Array->new( 4, GL_FLOAT);

  147.     $ambient->assign(0,  ( 0.5, 0.5, 0.5, 1.0 ) );
  148.     $specular->assign(0, ( 1.0, 1.0, 1.0, 1.0 ) );
  149.     $diffuse->assign(0,  ( 0.5, 0.5, 0.5, 1.0 ) );
  150.     $shininess->assign(0,  10.0 );

  151.     $light_position->assign(0, ( 200.0, 200.0, 0.0, 0.0 ) );

  152.     glMaterialfv_c(GL_FRONT_AND_BACK, GL_AMBIENT, $ambient->ptr );
  153.     glMaterialfv_c(GL_FRONT_AND_BACK, GL_SPECULAR, $specular->ptr );
  154.     glMaterialfv_c(GL_FRONT_AND_BACK, GL_DIFFUSE, $diffuse->ptr );
  155.     glMaterialfv_c(GL_FRONT_AND_BACK, GL_SHININESS, $shininess->ptr );

  156.     glLightfv_c(GL_LIGHT0, GL_POSITION, $light_position->ptr);

  157.     glEnable(GL_LIGHTING);
  158.     glEnable(GL_LIGHT0);

  159.     glColorMaterial(GL_FRONT, GL_DIFFUSE);
  160.     glEnable(GL_COLOR_MATERIAL);

  161.     initlist();
  162. }

  163. sub idle
  164. {
  165.     sleep 0.001;
  166.     glutPostRedisplay();
  167. }

  168. sub Reshape
  169. {
  170.     my ($w, $h) = (shift, shift);
  171.     my $half = 200.0;
  172.     my $fa = 250.0;

  173.     glViewport(0, 0, $w, $h);
  174.     glMatrixMode(GL_PROJECTION);
  175.     glLoadIdentity();
  176.     #glOrtho(-$half, $half, -$half, $half, 0.0, $fa*2.0);
  177.     gluPerspective( 90.0, 1.0, 1.0, $fa*2.0 );
  178.     glMatrixMode(GL_MODELVIEW);
  179.     glLoadIdentity();
  180.     gluLookAt(0.0,0.0,$fa,0.0,0.0,0.0, 0.0,1.0, $fa);
  181. }

  182. sub hitkey
  183. {
  184.     our $WinID;
  185.     my $k = lc(chr(shift));

  186.     given ($k)
  187.     {
  188.         when ('q') { glutDestroyWindow( $WinID ); }
  189.         when ('a') { $ry-=3.0; }
  190.         when ('d') { $ry+=3.0; }
  191.         when ('w') { $rx+=3.0; }
  192.         when ('s') { $rx-=3.0; }
  193.         when ('j') { $rz+=3.0; }
  194.         when ('k') { $rz-=3.0; }
  195.     }

  196. }

  197. sub Main
  198. {
  199.     glutInit();
  200.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE |GLUT_DEPTH |GLUT_MULTISAMPLE );
  201.     glutInitWindowSize(500, 500);
  202.     glutInitWindowPosition(1,1);
  203.     our $WinID = glutCreateWindow("bunny");
  204.     &init();
  205.     glutDisplayFunc(\&display);
  206.     glutReshapeFunc(\&Reshape);
  207.     glutKeyboardFunc(\&hitkey);
  208.     glutIdleFunc(\&idle);
  209.     glutMainLoop();
  210. }
复制代码

评分

参与人数 5技术 +5 收起 理由
老刘1号 + 1 不明嚼栗
莫奈良 + 1 厉害了
happy886rr + 1 牛,这三维空间都成动物世界了。
capslock + 1 感谢分享
pcl_test + 1 不明觉厉

查看全部评分

 楼主| 发表于 2017-1-10 12:03:04 | 显示全部楼层
本帖最后由 523066680 于 2017-1-10 14:21 编辑

强行转 Perl 代码发帖。

转换过程中感到的明显缺点是,大量的敲打 $ 符号。
爽快的地方:
  • given when 语句比 switch case 整洁多了。
  • 从纯文本文件中读取数据、处理数据相对方便
发表于 2017-1-10 13:56:24 | 显示全部楼层
尼玛,好丑啊。哈哈。
 楼主| 发表于 2017-1-10 14:49:37 | 显示全部楼层
回复 3# codegay


    另一种扫描没这么精细的三角形网格反而好看一些。
http://graphics.stanford.edu/pub/3Dscanrep/bunny.tar.gz

bun_zipper_res3.ply



代码稍作修改
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-16 23:45 , Processed in 0.019503 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表