查看原文
其他

模拟巴西奥运火炬台-代码浅析( Test-184 )

2016-08-12 Wenzy InsLab

分享一段代码练习,使用的工具是 Processing / Openframeworks。


前段时间大家都被巴西的奥运火炬台惊艳到了。我也不例外。当天在网上看到图片和视频,就被它的韵律美所打动。晚上回去就立刻用 Openframeworks 做了模拟。

第一张是奥运火炬的正面图


后面是作者的其他雕塑作品


(图片来源:Anthony Howe/youtube.com)

这是当时所能找到的参考资料。根据这些图片,下面是最终用代码实现的效果


源码与思路浅析

下面开始分析实现思路,同时做了 P5 和 OF 两个版本。从篇幅上考量,文中只放 Processing 的完整代码。

int num; int lineVertexNum;  // 单个元件的线段数 void setup() {  size(1000, 800, P3D);  pixelDensity(2);  lineVertexNum = 8; } void draw() {  background(0);  camera(30.0, 30, 1750, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  ambientLight(101, 0, 0);  pointLight(255, 215, 0, 0, 0, 0);  pointLight(255, 0, 0, -700, 0, 0);  pointLight(255, 0, 0, 700, 0, 0);  rotateY(millis()/1800.0);  num = int(mouseY/(float)height * 50);  for (int i = 0; i < 4; i++) {    fireLine(PI/2 * i);  } } void fireLine(float interval) {  pushMatrix();  rotateY(PI/2);  randomSeed(1);  for (int j = 0; j < num; j++) {    pushMatrix();    float angle = j/(float)num;    rotateX(j/(float)num * 2 * PI);    strokeWeight(2);    translate(0, 400);    float sinInterval, rotateInterval;    // rotateInterval 决定每个旋转部件间的偏移量    rotateInterval = 4 * mouseX/(float)width;    float speed = 2 * PI / 6;  // 控制旋转速度    rotate(-millis()/1000.0 * speed + j/(float)num * 2 * PI * rotateInterval + interval);    for (int i = 0; i < lineVertexNum; i++) {      float l = 16 + 10 * i;      float circleR = 15  - i * 1.5;      if (i == lineVertexNum - 1) {        circleR = 40;      }      stroke(255, 0, 0, 130);      line(0, 0, l, 0);      translate(l, 0);      pushMatrix();      rotateY(PI/2);      noStroke();      if (i == lineVertexNum - 1) {        ellipse(0, 0, circleR * 2, circleR * 2);      } else {        sphere(circleR);      }      popMatrix();      rotate(sin(i/(float)lineVertexNum * 2 * PI) * 1/9.0 * 2 * PI);    }    popMatrix();  }  popMatrix(); }

在 Processing 3.0 下直接复制就能正常运行,此链接(

思路浅析

这里先不逐句讲解代码,只分享实现思路

  • 当看到这样一个造型,第一步是要分解问题。它的基本组成单元是什么?


  • 经过观察,初步猜测如上图。所以先用简单的直线,圆,还有球体来概括。

  • 要在程序中画出一条类似于 S 形的曲线,不一定要用绝对坐标去表示。可以考虑相对坐标,这样更简便也更灵活。在 Processing 或 Openframeworks 中用相对坐标,就得熟悉这几个命令。translate,rotate,pushMatrix,popMatrix(对应 OF 中的 ofTranslate,ofRotate,ofPushMatrix,ofPopMatrix)。对于这样一条曲线,点与点之间的距离和角度是可以用某个关系式去表示的,角度可以使用周期函数 sin,因为它有一个来回的变化。而距离呈现的是一种递增关系,所以有了代码 float l = 16 + 10 * i。

  • 当结构写好,就得调各种参数,让它符合预期的造型。完成这步后,接着就可以将这些元件进行重复。同样是采用相对坐标的方式去旋转复制图形,用 for 循环再结合 rotate 就能实现


  • 这是经过重复并添加角度偏移后的效果。基本造型已经出来。只要将它打包成一个函数,再在 draw 里面传入不同的变量,就能让单个元件重复


  • 上面是原理图,可以看到由简至繁的整个过程

  • 最后在程序中添加三个点光源,中间用黄光,两旁用红光,就大功告成~

奥运火炬改装

最后放一个改装版。

在纸上画图,要重新设计必须得推倒重来。但在程序中,可能只要修改一下参数,多加几行代码即可,非常方便就能做出各种变化。这也是自己喜欢 coding 的原因之一,它可以带来更多创造的可能性。

一点心得

  • Processing 和 Openframeworks 内置的灯光系统有两个特性。一是没有投影,二是物体之间不会相互影响,光没有反射也没有折射。所以在真实感上比不上 Unity 这类游戏引擎,但只要参数调节得当,还是能有不错的三维表现力。

  • 编程不是一步到位的。就像绘画,先有个草稿,骨架,再去一步步补充并丰富细节。别想着把所有东西都写完才 RUN。

  • 多观察,多考虑图形间的相对关系。复杂图形也可以有简单的表示方法,学会概括。

  • pushMatrix 与 popMatrix 非常常用,尽量熟悉

Processing 与 Openframeworks 的异同对比

最近被问的问题里,频率最高之一的问题是:“ 这是用什么写的?Processing 还是 OF ?”。

这里解答一下,现在几乎只用 OF,因为它基于 C++,跨平台,效率高,能开发 App。所以选择它作为主力开发工具。

但无论 Processing 也好,OF 也好。它们之间的差别没有大家想象的大。若只从呈现的视觉结果来看,Processing 能做的,OF 也能做,反之亦然。

算法是内功,语言只是招式。核心的是算法,关键是思考用怎样的算法去造型去着色。无论你是用 JS,Python 还是 Unity,其实都大同小异,你只要用自己熟悉的工具即可。

目前的 Test 里,并没有用到多少高级的 OF 专用库。几乎都是用最简单的点线面去组织。而这些基础的造型元素,两种工具都会有。所以 98 % 的Test ,都可以同时用两者实现。

当然,若你想做一些更复杂的图形,OF 效率高的优势就能体现出来。正如这个例子的两个版本,OF 在图形元件数量更多时,跑起来就会更流畅。

工具的选择建议

学 Processing 还是 OF ,主要取决与你最终想做什么。有些是只有 Processing 能做的,比如输出程序在网页端运行(OF 理论上也行,但很不方便)。而有些只有 OF 能做,如开发 IOS 应用。

至于开发安卓应用,两者都可以。和 Kinect,Arduino 各种硬件传感器交互,也是两者皆可。如果你想做一些大型的互动装置,运算量较大,想更稳定,更推荐基于 C++ 的 OF。

但如果你是设计师,以前没接触过编程,想先提高 CreativeCoding 的内功,就可以考虑学 Processing,毕竟玩的人多,教程资源也丰富,更便于交流讨论。当熟悉两者中的任何一个,另一个只要花很少的时间既能掌握。假如你已经掌握 Processing,在教程资源完善的前提下,学习 OF 也只要一周的时间。

所以若是有意深入,不如两者都学,区别只是先后而已~

Openframeworks 版源码

点击阅读原文可下载 Openframeworks 版

(使用说明:单击拖动可切换角度。上下移动可改变元件数量,左右移动可改变元件间的旋转偏移量)



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存