首先需要说明的一点是: openFrameworks
设计的初衷不是为计算机专业人士准备的, 而是为艺术专业人士准备的, 就像 Processing
一样.
openFrameworks
是一个功能强大, 上手超级简单的 C/C++
开源框架. 它集成封装了很多常用的库, 诸如:
openFrameworks
为这些库提供了一个统一的接口, 使得使用它们变得异常容易.
另外值得一提的就是 openFrameworks
的跨平台特性, 从桌面系统到移动终端, openFrameworks
目前支持:
最新的 0.9.0
版本还支持运行 Linux
系统的 arm
开发板, 例如树莓派.
openFrameworks
集成了 Emscripten
作为插件, 我们的 openFrameworks
程序可以通过它很容易地转换成 javascript
的格式, 这样非常方便就把本地项目转换成了 WEB
项目, 可以直接发布到网络上.
openFrameworks
除了支持命令行编译外, 还支持比较常用的几种集成开发环境. 如下:
其实 openFrameworks
最值得称道的是它的代码结构极其简单, 假设你的项目名为 myOF
, 那么代码结构如下:
#include "myOF.h"
//--------------------------------------------------------------
void myOF::setup(){
}
//--------------------------------------------------------------
void myOF::update(){
}
//--------------------------------------------------------------
void myOF::draw(){
}
//--------------------------------------------------------------
void myOF::keyPressed(int key){
}
...
如果你有过使用 Processing
的经验, 就会感觉非常熟悉, 没错, 这些函数跟 Processing
中的含义完全一样.
setup
在程序启动时执行一次;draw
在程序启动后每秒执行60次(该频率可设), 用来绘制图形;update
跟 draw
一样, 每秒执行60次, 把需要更新的代码放在这里;keyPressed
处理按键事件; 为什么会使用这种代码结构? 因为 openFrameworks
原本的设计目的就是要让非计算机专业的人士通过编程来创造各种计算机视觉/图像/视频/声音艺术, 就像 Processing
的设计目标一样, 所以它才会搞成这种简单易用但是功能强大的形式.
openFrameworks
支持多个平台的安装, 从官网下载地址取得对应的版本, 以树莓派为例, 如下:
解压后进入目录:
pi@rpi /opt/software/openFrameworks $ cd scripts/linux/debian/
pi@rpi /opt/software/openFrameworks/scripts/linux/debian $ ls
install_codecs.sh install_dependencies.sh
pi@rpi /opt/software/openFrameworks/scripts/linux/debian $
安装依赖:
pi@rpi /opt/software/openFrameworks/scripts/linux/debian $ sudo ./install_dependencies.sh
安装编解码:
pi@rpi /opt/software/openFrameworks/scripts/linux/debian $ sudo ./install_codecs.sh
编译oF库:
pi@rpi /opt/software/openFrameworks/scripts/linux $ ls
archlinux buildAllExamples.sh cleanAllExamples.sh compileOF.sh debian removeFMOD.sh ubuntu
archlinux_armv6 buildAllRPIExamples.sh codeblocks_wizard compilePG.sh fedora testAllExamples.sh ubuntu-omap4
pi@rpi /opt/software/openFrameworks/scripts/linux $ sudo ./compileOF.sh
编译项目生成器:
pi@rpi /opt/software/openFrameworks/scripts/linux $ sudo ./compilePG.sh
编译全部例程:
pi@rpi /opt/software/openFrameworks/scripts/linux $ sudo ./buildAllRPIExamples.sh
执行所有编译好的例程:
pi@rpi /opt/software/openFrameworks/scripts/linux $ sudo ./testAllExamples.sh
也可以单独编译某个例程, 只要进入其目录操作即可.
安装好之后, 在目录 ./examples/empty/
下有一个空项目模板 emptyExample
, 我们可以基于这个空项目模板来写自己的 oF
程序, 针对不同的平台, 空项目模板的结构也不同, 例如:
Raspbian
平台下, 空项目模板的结构如下:pi@rpi /opt/software/openFrameworks/examples/empty $ tree emptyExample/
emptyExample/
├── bin
│ ├── emptyExample
│ ├── libs
│ └── readMe.txt
├── config.make
├── Makefile
├── obj
│ └── linuxarmv7l
│ └── Release
│ └── src
│ ├── main.d
│ ├── main.o
│ ├── ofApp.d
│ └── ofApp.o
└── src
├── main.cpp
├── ofApp.cpp
└── ofApp.h
7 directories, 11 files
pi@rpi /opt/software/openFrameworks/examples/empty $
OSX
平台下, 空项目模板的结构如下:admin@Air:~/Downloads/of_v0.9.0_osx_release/examples/empty$ tree emptyExample/ |more
emptyExample/
├── Makefile
├── Project.xcconfig
├── addons.make
├── bin
│ ├── data
│ └── emptyExample.app
│ └── Contents
│ ├── Frameworks
│ │ └── GLUT.framework
│ │ ├── GLUT -> Versions/Current/GLUT
│ │ ├── Headers -> Versions/Current/Headers
│ │ ├── Resources -> Versions/Current/Resources
│ │ └── Versions
│ │ ├── A
│ │ │ ├── GLUT
│ │ │ ├── Headers
│ │ │ │ ├── copy.h
│ │ │ │ ├── extrude.h
│ │ │ │ ├── glsmap.h
│ │ │ │ ├── glsmapint.h
│ │ │ │ ├── glut.h
│ │ │ │ ├── glutbitmap.h
│ │ │ │ ├── glutf90.h
│ │ │ │ ├── glutstroke.h
│ │ │ │ ├── gutil.h
│ │ │ │ ├── intersect.h
│ │ │ │ ├── port.h
│ │ │ │ ├── rot.h
│ │ │ │ ├── segment.h
│ │ │ │ ├── tube.h
│ │ │ │ ├── tube_gc.h
│ │ │ │ └── vvector.h
│ │ │ └── Resources
│ │ │ ├── Caution.tiff
│ │ │ ├── English.lproj
│ │ │ │ ├── GLUT.nib
│ │ │ │ │ └── objects.nib
│ │ │ │ ├── GLUTClipboard.nib
│ │ │ │ │ └── objects.nib
│ │ │ │ ├── GLUTPreferences.nib
│ │ │ │ │ └── objects.nib
│ │ │ │ ├── GLUTUI.strings
│ │ │ │ └── InfoPlist.strings
│ │ │ ├── Info.plist
│ │ │ ├── blankCursor.tiff
│ │ │ ├── bottomCursor.tiff
│ │ │ ├── bottomleftCursor.tiff
│ │ │ ├── bottomrightCursor.tiff
│ │ │ ├── crossCursor.tiff
│ │ │ ├── cycleCursor.tiff
│ │ │ ├── destroyCursor.tiff
│ │ │ ├── fingerCursor.tiff
│ │ │ ├── helpCursor.tiff
│ │ │ ├── leftCursor.tiff
│ │ │ ├── leftRightCursor.tiff
│ │ │ ├── rightArrowCursor.tiff
│ │ │ ├── rightCursor.tiff
│ │ │ ├── sprayCursor.tiff
│ │ │ ├── topCursor.tiff
│ │ │ ├── topleftCursor.tiff
│ │ │ ├── toprightCursor.tiff
│ │ │ ├── upDownCursor.tiff
│ │ │ └── waitCursor.tiff
│ │ └── Current -> A
│ ├── Info.plist
│ ├── MacOS
│ │ ├── emptyExample
│ │ └── libfmodex.dylib
│ ├── PkgInfo
│ └── Resources
│ └── icon.icns
├── build
│ └── emptyExample.build
│ └── Release
│ └── emptyExample.build
│ ├── Objects-normal
│ │ └── x86_64
│ │ ├── emptyExample.LinkFileList
│ │ ├── emptyExample_dependency_info.dat
│ │ ├── main.d
│ │ ├── main.dia
│ │ ├── main.o
│ │ ├── ofApp.d
│ │ ├── ofApp.dia
│ │ └── ofApp.o
│ ├── Script-E4B6FFFD0C3F9AB9008CF71C.sh
│ ├── dgph
│ ├── dgph~
│ └── emptyExample.hmap
├── config.make
├── emptyExample.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ └── xcschemes
│ ├── emptyExample Debug.xcscheme
│ └── emptyExample Release.xcscheme
├── openFrameworks-Info.plist
└── src
├── main.cpp
├── ofApp.cpp
└── ofApp.h
29 directories, 72 files
admin@Air:~/Downloads/of_v0.9.0_osx_release/examples/empty$
这个空模板项目既可以在诸如 XCode
之类的 IDE
中打开, 也可以直接在命令行编辑, 然后在命令行编译, 下面, 我们分别在 Raspbian
和 OSX
的命令行下新建一个项目并编译它.
首先把空模板拷贝一份, 假设我们的项目叫 myOF
, 那么执行下面这条命令:
pi@rpi /opt/software/openFrameworks/examples/empty $ cp -R emptyExample/ ./myOF
pi@rpi /opt/software/openFrameworks/examples/empty $ ls
emptyExample myOF
pi@rpi /opt/software/openFrameworks/examples/empty $ cd myOF/
pi@rpi /opt/software/openFrameworks/examples/empty/myOF $ ls
bin config.make Makefile obj src
pi@rpi /opt/software/openFrameworks/examples/empty/myOF $
其中 src
目录是源代码目录, 进入查看
pi@rpi /opt/software/openFrameworks/examples/empty/myOF $ cd src
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $ ls
main.cpp ofApp.cpp ofApp.h
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $
总共3个文件, 分别看看内容:
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $ cat main.cpp
#include "ofMain.h"
#include "ofApp.h"
//========================================================================
int main( ){
ofSetupOpenGL(1024,768, OF_WINDOW); // <-------- setup the GL context
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp( new ofApp());
}
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $ cat ofApp.cpp
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
}
//--------------------------------------------------------------
void ofApp::update(){
}
//--------------------------------------------------------------
void ofApp::draw(){
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key){
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
}
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $ cat ofApp.h
#pragma once
#include "ofMain.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y);
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseEntered(int x, int y);
void mouseExited(int x, int y);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
};
pi@rpi /opt/software/openFrameworks/examples/empty/myOF/src $
容易看出, 我们要编辑的文件是 ofApp.cpp
, 我们打算画两个不同颜色的圆, 代码就是下面这些:
//--------------------------------------------------------------
void ofApp::draw(){
ofSetColor(255, 0, 255);
ofCircle(200, 300, 60);
ofSetColor(0, 255, 255);
ofCircle(500, 500, 100);
}
修改 ofApp.cpp
后保存, 回到上层目录, 开始编译:
pi@rpi /opt/software/openFrameworks/examples/empty/myOF $ sudo make
HOST_OS=Linux
HOST_ARCH=armv7l
checking pkg-config libraries: cairo zlib gstreamer-app-1.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-base-1.0 libudev freetype2 fontconfig sndfile openal openssl libpulse-simple alsa gtk+-3.0 libmpg123
Compiling OF library for Release
make[1]: Entering directory '/opt/software/openFrameworks/libs/openFrameworksCompiled/project'
HOST_OS=Linux
HOST_ARCH=armv7l
checking pkg-config libraries: cairo zlib gstreamer-app-1.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-base-1.0 libudev freetype2 fontconfig sndfile openal openssl libpulse-simple alsa gtk+-3.0 libmpg123
HOST_OS=Linux
HOST_ARCH=armv7l
checking pkg-config libraries: cairo zlib gstreamer-app-1.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-base-1.0 libudev freetype2 fontconfig sndfile openal openssl libpulse-simple alsa gtk+-3.0 libmpg123
Compiling /opt/software/openFrameworks/libs/openFrameworks/utils/ofSystemUtils.cpp
...
HOST_OS=Linux
HOST_ARCH=armv7l
checking pkg-config libraries: cairo zlib gstreamer-app-1.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-base-1.0 libudev freetype2 fontconfig sndfile openal openssl libpulse-simple alsa gtk+-3.0 libmpg123
compiling done
to launch the application
cd bin
./myOF
- or -
make run
make[1]: Leaving directory '/opt/software/openFrameworks/examples/empty/myOF'
pi@rpi /opt/software/openFrameworks/examples/empty/myOF $
成功编译, 没有错误!
我们可以直接进入目录 bin/myOF.app/Contents/MacOS/
下运行 ./myOF
, 也可以直接在当前目录下运行 make run
来查看结果:
pi@rpi /opt/software/openFrameworks/examples/empty/myOF $ make run
HOST_OS=Linux
HOST_ARCH=armv7l
checking pkg-config libraries: cairo zlib gstreamer-app-1.0 gstreamer-1.0 gstreamer-video-1.0 gstreamer-base-1.0 libudev freetype2 fontconfig sndfile openal openssl libpulse-simple alsa gtk+-3.0 libmpg123
[notice ] ofAppEGLWindow: setupRPiNativeWindow(): screenRect: 1280x1024
[notice ] ofAppEGLWindow: setupRPiNativeWindow(): windowRect: 1024x768
[notice ] ofAppEGLWindow: createSurface(): setting up EGL Display
[notice ] ofAppEGLWindow: createSurface(): EGL Display correctly set 0x1
[notice ] ofAppEGLWindow: createSurface(): no current renderer selected
[notice ] ofAppEGLWindow: createSurface(): default renderer detected
[notice ] ofAppEGLWindow: createSurface(): surface created correctly
[notice ] ofAppEGLWindow: createSurface(): API bound correctly
[notice ] ofAppEGLWindow: createSurface(): -----EGL-----
[notice ] ofAppEGLWindow: createSurface(): EGL_VERSION_MAJOR = 1
[notice ] ofAppEGLWindow: createSurface(): EGL_VERSION_MINOR = 4
[notice ] ofAppEGLWindow: createSurface(): EGL_CLIENT_APIS = OpenGL_ES OpenVG
[notice ] ofAppEGLWindow: createSurface(): EGL_VENDOR = Broadcom
[notice ] ofAppEGLWindow: createSurface(): EGL_VERSION = 1.4
[notice ] ofAppEGLWindow: createSurface(): EGL_EXTENSIONS = EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_KHR_vg_parent_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_lock_surface
[notice ] ofAppEGLWindow: createSurface(): GL_RENDERER = VideoCore IV HW
[notice ] ofAppEGLWindow: createSurface(): GL_VERSION = OpenGL ES-CM 1.1
[notice ] ofAppEGLWindow: createSurface(): GL_VENDOR = Broadcom
[notice ] ofAppEGLWindow: createSurface(): -------------
[notice ] ofAppEGLWindow: setupPeripherals(): peripheral setup complete
[notice ] ofAppEGLWindow: setupNativeUDev(): created udev object
[notice ] ofAppEGLWindow: setupMouse(): mouse_fd= 5 devicePath=/dev/input/by-path/platform-3f980000.usb-usb-0:1.2:1.0-event-mouse
[notice ] ofAppEGLWindow: setupMouse(): mouse device name = Logitech USB Optical Mouse
[notice ] ofAppEGLWindow: setupKeyboard(): keyboard_fd= 6 devicePath=/dev/input/by-path/platform-3f980000.usb-usb-0:1.3:1.0-event-kbd
[notice ] ofAppEGLWindow: setupKeyboard(): keyboard device name = USB Keyboard
[notice ] ofAppEGLWindow: setupPeripherals(): native event setup complete
按 ESC
或者 Ctrl-c
退出.
因为 openFrameworks
通过 framebuffer
绘图, 所以不需要 XWindows
.
说明: 因为树莓派下截图比较麻烦, 所以一律从 OSX
上截图.
注意: 在树莓派上运行需要有一个直接外接的屏幕, 只通过 VNC
连接是看不到绘制出的图像的.
为 OSX
准备的项目模板既可以通过命令行编译, 也可以通过 XCode
编译, 首次编译花的时间比较长, 因为要编译各种库, 之后再编译就快多了.
通过拷贝空项目模板来新建项目, 然后修改 ofApp.cpp
, 再进行编译, 记录如下:
...
admin@Air:~/Downloads/of_v0.9.0_osx_release/examples/empty/myOF$ sudo make
HOST_OS=Darwin
HOST_ARCH=x86_64
Compiling OF library for Release
HOST_OS=Darwin
HOST_ARCH=x86_64
HOST_OS=Darwin
HOST_ARCH=x86_64
HOST_OS=Darwin
HOST_ARCH=x86_64
Done!
Compiling myOF for Release
HOST_OS=Darwin
HOST_ARCH=x86_64
Compiling /Users/admin/Downloads/of_v0.9.0_osx_release/examples/empty/myOF/src/ofApp.cpp
...
HOST_OS=Darwin
HOST_ARCH=x86_64
TARGET=bin/myOF
compiling done
to launch the application
cd bin/myOF.app/Contents/MacOS/
./myOF
- or -
make run
admin@Air:~/Downloads/of_v0.9.0_osx_release/examples/empty/myOF$
没有任何错误, 完成编译, 用跟 Raspbian
同样的方式来运行编译好的程序
admin@Air:~/Downloads/of_v0.9.0_osx_release/examples/empty/myOF$ make run
HOST_OS=Darwin
HOST_ARCH=x86_64
运行截图如下:
如果打算增加点内容, 修改 ofApp.cpp
中对应的函数即可.
在 draw
中增加这一句:
ofDrawBitmapString(ofToString(ofGetFrameRate())+"fps", 10, 15);
可以在程序窗口左上角显示帧速率
在 setup
中增加这一句:
ofSetFrameRate(60);
在 setup
中增加这几句:
// 修改绘制精度
ofSetCircleResolution(120);
// 开启抗锯齿
ofEnableSmoothing();
// 开启垂直同步
ofSetVerticalSync(true);
在 setup
中增加这一句:
ofBackground(0,0,0);
把背景色改为黑色.
截图如下:
除了画圆,oF 也可以画其他的图案:
openFrameworks
的API
函数可以在它的官网文档查询, 该文档不仅包含对 openFrameworks
的 API
说明, 也包含了对插件 API
的说明, 相当详细.
openFrameworks
支持第三方插件, 我们先看看这个版本自带了哪些插件:
admin@Air:~/Downloads/of_v0.9.0_osx_release/addons$ ls -al
total 16
drwxr-xr-x@ 15 admin staff 510 12 17 17:25 .
drwxr-xr-x@ 17 admin staff 578 12 16 21:19 ..
-rw-r--r--@ 1 admin staff 6148 12 17 17:30 .DS_Store
drwxr-xr-x@ 6 admin staff 204 11 8 17:30 ofxAssimpModelLoader
drwxr-xr-x@ 4 admin staff 136 11 8 17:30 ofxEmscripten
drwxr-xr-x@ 3 admin staff 102 11 8 17:30 ofxGui
drwxr-xr-x@ 8 admin staff 272 11 8 17:30 ofxKinect
drwxr-xr-x 17 admin staff 578 12 17 17:29 ofxLua
drwxr-xr-x@ 4 admin staff 136 11 8 17:30 ofxNetwork
drwxr-xr-x@ 6 admin staff 204 11 8 17:30 ofxOpenCv
drwxr-xr-x@ 5 admin staff 170 11 8 17:30 ofxOsc
drwxr-xr-x@ 4 admin staff 136 11 8 17:30 ofxSvg
drwxr-xr-x@ 3 admin staff 102 11 8 17:30 ofxThreadedImageLoader
drwxr-xr-x@ 4 admin staff 136 11 8 17:30 ofxVectorGraphics
drwxr-xr-x@ 4 admin staff 136 11 8 17:30 ofxXmlSettings
admin@Air:~/Downloads/of_v0.9.0_osx_release/addons$
想看到更多的插件可以来这里官网插件查找, 或者到 github
搜索 ofx
打头的项目.
这里列举一些比较常见的插件
访问这个插件的 Github
项目主页;
把它克隆到你的 addons
目录:
进入你的 openFrameworks
目录下的 addons
目录,git clone
该项目;
如果这个项目自带 example
,可以直接 make && make run
编译和执行它看看结果。
说明: 本文大量参考A Brief Introduction to openFrameworks-介绍一个开源的 C++ 开发框架 openFrameworks文中的内容, 特此感谢.
A Brief Introduction to openFrameworks-介绍一个开源的 C++ 开发框架 openFrameworks