MAC 下用 Common Lisp 调试 OpenGL 程序

环境搭建

  • 运行环境: OSX 10.11.3 EI Capitan
  • Common Lisp: SBCL

使用 SBCL, 首先要安装这几个库 quicklisp, cl-opengl, cl-glu, lispbuilder-sdl. 先安装好 quicklisp, 再用它来安装其他库.

安装过程如下.

安装 quicklisp

先安装 quicklisp

Air:~ admin$ cd code-staff/
Air:code-staff admin$ mkdir sbcl
Air:code-staff admin$ cd sbcl
Air:sbcl admin$ curl -O https://beta.quicklisp.org/quicklisp.lisp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 57144 100 57144 0 0 12184 0 0:00:04 0:00:04 --:--:-- 12545
Air:sbcl admin$ ls
quicklisp.lisp
Air:sbcl admin$ sbcl --load quicklisp.lisp
This is SBCL 1.0.55, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>. SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information. ==== quicklisp quickstart 2015-01-28 loaded ==== To continue with installation, evaluate: (quicklisp-quickstart:install) For installation options, evaluate: (quicklisp-quickstart:help)

执行 (quicklisp-quickstart:install) 发现原来已经安装过了, 那就选择使用已经安装好的.

* (quicklisp-quickstart:install)

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "initial thread" RUNNING {10029A91C3}>:
Quicklisp has already been installed. Load #P"/Users/admin/quicklisp/setup.lisp" instead. Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name):
0: [LOAD-SETUP] Load #P"/Users/admin/quicklisp/setup.lisp"
1: [ABORT ] Exit debugger, returning to top level. (QUICKLISP-QUICKSTART:INSTALL
:PATH
NIL
:PROXY
NIL
:CLIENT-URL
NIL
:CLIENT-VERSION
NIL
:DIST-URL
NIL
:DIST-VERSION
NIL) 0] 0 T

然后执行 (ql:add-to-init-file) 加载到 SBCL 的初始化文件中, 这样每次启动 SBCL 就会自动加载 quicklisp:

* (ql:add-to-init-file)

I will append the following lines to #P"/Users/admin/.sbclrc":

  ;;; The following lines added by ql:add-to-init-file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init))) Press Enter to continue. #P"/Users/admin/.sbclrc"
*

安装好 quicklisp 之后, 剩下的就是用它来安装其他几个库, 具体来说就是这几条命令:

(ql:quickload 'cl-opengl)
(ql:quickload 'cl-glu)
(ql:quickload 'lispbuilder-sdl)

安装 cl-opengl

接下来就可以用 quicklispql:quickload 命令加载需要的库了, 先加载 cl-opengl

* (ql:quickload 'cl-opengl)
To load "cl-opengl":
Load 2 ASDF systems:
alexandria cffi
Install 1 Quicklisp release:
cl-opengl
; Fetching #<URL "http://beta.quicklisp.org/archive/cl-opengl/2013-03-12/cl-opengl-20130312-git.tgz">
; 356.91KB
==================================================
365,475 bytes in 1.52 seconds (235.43KB/sec)
; Loading "cl-opengl"
..................................................
[package cl-opengl-bindings]......................
..................................................
..................................................
[package cl-opengl]...............................
........
(CL-OPENGL)
*

安装 cl-glu

再加载 cl-glu

* (ql:quickload 'cl-glu)
To load "cl-glu":
Load 1 ASDF system:
cl-glu
; Loading "cl-glu"
[package cl-glu].....
(CL-GLU)
*

安装 lispbuilder-sdl

接下来加载 lispbuilder-sdl, 结果一开始出错, 报错信息如下:

* (ql:quickload 'lispbuilder-sdl)
To load "lispbuilder-sdl":
Load 1 ASDF system:
lispbuilder-sdl
; Loading "lispbuilder-sdl" debugger invoked on a LOAD-FOREIGN-LIBRARY-ERROR in thread
#<THREAD "initial thread" RUNNING {10029A91C3}>:
Unable to load any of the alternatives:
((:FRAMEWORK "cocoahelper") (:DEFAULT "cocoahelper")) Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name):
0: [RETRY ] Try loading the foreign library again.
1: [USE-VALUE ] Use another library instead.
2: [TRY-RECOMPILING] Recompile cocoahelper and try loading it again
3: [RETRY ] Retry
loading FASL for #<CL-SOURCE-FILE "cocoahelper" "cocoahelper" "cocoahelper">.
4: [ACCEPT ] Continue, treating
loading FASL for #<CL-SOURCE-FILE "cocoahelper" "cocoahelper" "cocoahelper">
as having been successful.
5: [ABORT ] Give up on "lispbuilder-sdl"
6: Exit debugger, returning to top level. (CFFI::FL-ERROR
"Unable to load any of the alternatives:~% ~S"
((:FRAMEWORK "cocoahelper") (:DEFAULT "cocoahelper")))
0]

仔细阅读这篇文档Using OpenGL with Common Lisp, 发现作者提到了这一点, 也说了解决办法, 就是进入对应的 cocoahelper 目录, 手动编译/安装, 实际上只要进到这个目录 /Users/admin/quicklisp/dists/quicklisp/software/lispbuilder-20130312-svn/lispbuilder-sdl/cocoahelper, 然后执行命令 make 就可以了.

另外开一个终端窗口, 编译 cocoahelper库, 在我的机器上操作记录如下:

Air:cocoahelper admin$ pwd
/Users/admin/quicklisp/dists/quicklisp/software/lispbuilder-20130312-svn/lispbuilder-sdl/cocoahelper
Air:cocoahelper admin$ make
gcc -fPIC -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_THREAD_SAFE -c cocoahelper.m -o cocoahelper.o
cocoahelper.m:90:52: warning: passing 'char [1024]' to parameter of type 'UInt8 *' (aka 'unsigned char *') converts between pointers to integer types with different sign
[-Wpointer-sign]
if (CFURLGetFileSystemRepresentation(url2, true, parentdir, MAXPATHLEN)) {
^~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFURL.h:113:91: note:
passing argument to parameter 'buffer' here
Boolean CFURLGetFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, UInt8 *buffer, CFIndex maxBufLen);
^
cocoahelper.m:163:12: warning: instance method '-setAppleMenu:' not found (return type defaults to 'id') [-Wobjc-method-access]
[NSApp setAppleMenu:appleMenu];
^~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSApplication.h:110:12: note:
receiver is instance of class declared here
@interface NSApplication : NSResponder <NSUserInterfaceValidations, NSAccessibilityElement, NSAccessibility>
^
cocoahelper.m:292:31: warning: incompatible pointer to integer conversion passing 'void *' to parameter of type 'int' [-Wint-conversion]
CustomApplicationMain (0, NULL);
^~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.3.0/include/stddef.h:105:16: note: expanded from macro 'NULL'
# define NULL ((void*)0)
^~~~~~~~~~
cocoahelper.m:293:5: warning: 'GetCurrentProcess' is deprecated: first deprecated in OS X 10.9 [-Wdeprecated-declarations]
GetCurrentProcess(&processSerialNum);
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks/HIServices.framework/Headers/Processes.h:415:1: note:
'GetCurrentProcess' has been explicitly marked deprecated here
MacGetCurrentProcess(ProcessSerialNumber * PSN) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_9;
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks/HIServices.framework/Headers/Processes.h:412:34: note:
expanded from macro 'MacGetCurrentProcess'
#define MacGetCurrentProcess GetCurrentProcess
^
cocoahelper.m:294:5: warning: implicit declaration of function 'CPSEnableForegroundOperation' is invalid in C99 [-Wimplicit-function-declaration]
CPSEnableForegroundOperation (&processSerialNum);
^
cocoahelper.m:295:5: warning: 'SetFrontProcess' is deprecated: first deprecated in OS X 10.9 [-Wdeprecated-declarations]
SetFrontProcess(&processSerialNum);
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks/HIServices.framework/Headers/Processes.h:603:1: note:
'SetFrontProcess' has been explicitly marked deprecated here
SetFrontProcess(const ProcessSerialNumber * PSN) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_9;
^
6 warnings generated.
gcc -dynamiclib -L/usr/local/lib -lSDLmain -lSDL -Wl,-framework,Cocoa -o cocoahelper.dylib cocoahelper.o
Air:cocoahelper admin$

回到刚才加载 lispbuilder-sdl 的窗口, 选择 0, 这样:

0] 0
[package lispbuilder-sdl-cffi]....................
..................................................
[package lispbuilder-sdl-base]....................
[package trivial-garbage].........................
[package lispbuilder-sdl].........................
..................................................
..............
(LISPBUILDER-SDL)
*

不太放心, 再重新来一次, 直接显示成功:

* (ql:quickload 'lispbuilder-sdl)
To load "lispbuilder-sdl":
Load 1 ASDF system:
lispbuilder-sdl
; Loading "lispbuilder-sdl" (LISPBUILDER-SDL)
*

别人写的例程

用 cl-glut 画的 Manderlbrot 图

这里有一段只用 cl-glut 库绘制的 manderlbrot 集的代码, 如下:

(ql:quickload "cl-glut")

(defparameter *width* 500)
(defparameter *height* 500)
(defparameter *magnification* 100.0) (defun get-latice-points (width height reduction)
(apply #'append (loop for x from (* -1 (/ width 2)) below (1+ (/ width 2))
collect (loop for y from (* -1 (/ height 2)) below (1+ (/ height 2))
collect (complex (/ x reduction) (/ y reduction)))))) (defun calc-mandelbrot (c)
(labels ((f (z c n)
(cond ((= n 27) `(,c -1))
((< 2 (abs z)) `(,c ,n))
(t (f (+ c (expt z 2)) c (1+ n))))))
(f 0 c 0))) (defun get-mandelbrot ()
(mapcar #'calc-mandelbrot (get-latice-points *width* *height* *magnification*))) (defun set-mandelbrot-vertexes (latice-points)
(mapcar #'(lambda (x)
(let ((latice-point (car x))
(n (cadr x)))
(cond ((= n -1) (%gl:color-3f 0 0 0))
(t (%gl:color-3f (* n 0.2) 0 0)))
(gl:vertex (* *magnification* (realpart latice-point)) (* *magnification* (imagpart latice-point)) 0)))
latice-points)) (defclass my-window (glut:window)
()
(:default-initargs :title "mandelbrot" :width *width* :height *height*
:mode '(:single :rgb :depth))) (defmethod glut:display-window :before ((w my-window))
(gl:clear-color 1 1 1 0)
(gl:matrix-mode :projection)
(gl:load-identity)
(gl:ortho 0 *width* *height* 0 -1 1)) (defmethod glut:display ((window my-window))
(gl:clear :color-buffer-bit)
(%gl:color-3f 0 0 0)
(gl:push-matrix)
(gl:translate (/ *width* 2) (/ *height* 2) 0)
(gl:begin :points)
(set-mandelbrot-vertexes *mandelbrot*)
(gl:end)
(gl:pop-matrix)
(gl:flush)) (defparameter *mandelbrot* (get-mandelbrot))
(defun draw-mandelbrot ()
(glut:display-window (make-instance 'my-window)))

加载命令:

sbcl --load mandelbrot.lisp

然后执行:

* (draw-mandelbrot)

运行截图:

立方体绘制代码

具体就是绘制一个立方体, 代码如下:

(require 'cl-opengl)
(require 'cl-glu)
(require 'lispbuilder-sdl) (defconstant +window-width+ 600)
(defconstant +window-height+ 600) (defconstant +cube-vertices+
#(#(0 0 0)
#(0 1 0)
#(1 1 0)
#(1 0 0)
#(0 0 1)
#(0 1 1)
#(1 1 1)
#(1 0 1))) (defconstant +cube-faces+
'((#(4 7 6 5) #(0 0 1))
(#(5 6 2 1) #(0 1 0))
(#(1 2 3 0) #(0 0 -1))
(#(0 3 7 4) #(0 -1 0))
(#(4 5 1 0) #(-1 0 0))
(#(3 2 6 7) #(1 0 0)))) (defun draw-figure (verts faces)
(labels ((set-normal (n)
(gl:normal (aref n 0) (aref n 1) (aref n 2)))
(set-vertex (index)
(let ((v (aref verts index)))
(gl:vertex (aref v 0) (aref v 1) (aref v 2))))
(draw-face (vertex-indices normal)
(set-normal normal)
(gl:begin :quads)
(map 'nil #'set-vertex vertex-indices)
(gl:end))) (map 'nil #'(lambda (x) (draw-face (first x) (second x))) faces))) (defun draw-frame (rotx roty rotz)
(gl:matrix-mode :modelview)
(gl:push-matrix)
(gl:translate 0.5 0.5 0.5)
(gl:rotate rotx 1 0 0)
(gl:rotate roty 0 1 0)
(gl:rotate rotz 0 0 1)
(gl:translate -0.5 -0.5 -0.5)
(draw-figure +cube-vertices+ +cube-faces+)
(gl:pop-matrix)) (defun start ()
(let ((rotx 0)
(roty 0)
(rotz 0))
(sdl:with-init ()
(sdl:window +window-width+ +window-height+
:opengl t
:opengl-attributes '((:sdl-gl-depth-size 16)
(:sdl-gl-doublebuffer 1)))
(setf (sdl:frame-rate) 10) (gl:viewport 0 0 +window-width+ +window-height+)
(gl:matrix-mode :projection)
(gl:load-identity)
(glu:perspective 50 (/ +window-height+ +window-width+) 1.0 10.0)
(glu:look-at -2 2 4
0.5 0.5 0.5
0 1 0) (gl:matrix-mode :modelview)
(gl:load-identity) (gl:clear-color 0 0 0 0)
(gl:shade-model :flat)
(gl:cull-face :back)
(gl:polygon-mode :front :fill)
(gl:draw-buffer :back)
(gl:material :front :ambient-and-diffuse #(0.7 0.7 0.7 0.4))
(gl:light :light0 :position #(0 0 1 0))
(gl:light :light0 :diffuse #(1 0 0 0))
(gl:light :light1 :position #(-1 2 -0.5 0))
(gl:light :light1 :diffuse #(0 1 0 0))
(gl:enable :cull-face :depth-test
:lighting :light0 :light1) (gl:clear :color-buffer :depth-buffer)
(draw-frame rotx roty rotz)
(sdl:update-display) (sdl:with-events ()
(:quit-event () t)
(:video-expose-event () (sdl:update-display))
(:idle
(setq rotx (mod (+ rotx 2.5) 360.0))
(setq roty (mod (+ roty 0.7) 360.0))
(setq rotz (mod (+ rotz 4.4) 360.0))
(gl:clear :color-buffer :depth-buffer)
(draw-frame rotx roty rotz)
(sdl:update-display))))))

运行截图如下:

这是一个非常好的开始, 以后就可以在这个基础上用 Common Lisp 来调试 OpenGL 程序了.

参考

Using OpenGL with Common Lisp

Common Lisp 3D/2D Graphics Engine for OpenGL

Common Lisp library for creative coding

MAC 下用 Common Lisp 调试 OpenGL 程序的更多相关文章

  1. 在Mac下运行ASP.NET Core应用程序

    在Mac下运行ASP.NET Core应用程序 通过参照.NET Core相关官方文档,在我的Mac电脑上用Visual Studio Code创建了我的第一个ASP.NET应用. 开发环境搭建 首先 ...

  2. Mac下运行ASP.NET Core应用程序

    Mac下运行ASP.NET Core应用程序 在Mac下运行ASP.NET Core应用程序 通过参照.NET Core相关官方文档,在我的Mac电脑上用Visual Studio Code创建了我的 ...

  3. MAC使用IDA PRO远程调试LINUX程序

    1 背景 在学习Linux系统上的一些漏洞知识的时候,往往需要进行“实地测试”,但是在Linux系统上进行调试并不太方便,因为LINUX自带的GDB调试工具真的不太人性化,即使有GDBTUI之类的“伪 ...

  4. 解决小米、红米及其他 Android 手机无法在 Mac 下进行真机调试的问题(转)

    转自:http://ju.outofmemory.cn/entry/103522 Begin iOS 2014-08-19 271 阅读 手机 Android 小米 mac 调试 在 Mac OSX ...

  5. .NET Core初体验 - 在Mac下运行第一个Web示例程序

    要说最近两天程序猿之间最喜欢吹水的事是什么?那绝壁是甲骨文要放弃Java!简直做梦都要笑醒!由于公司的产品线全面转向Java,最近几个月也一直在苦学Java技术.已经默默决定了,如果消息证实是真的,我 ...

  6. linux下如何用GDB调试c++程序

    转:http://blog.csdn.net/wfdtxz/article/details/7368357 GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形 ...

  7. 【VS开发】【OpenGL开发】OpenGL---Windows下配置与第一个OpenGL程序

    面记录一下Windows下配置OpenGL与我的第一个OpenGL程序. 第一步:选择一个编译环境    现在Windows系统的主流编译环境有Visual Studio,Broland C++ Bu ...

  8. mac下删除不需要的应用程序

    一般的应用程序删除: 1)可以在 前往--应用程序 中直接删除 2)直接在启动台中按住出现X直接删除. 问题: mac下不出现在应用程序中,启动台中按住也不出现X,也不可以直接拖到废纸篓中删除的应用如 ...

  9. 在ubuntu下使用eclipse来调试ARM程序

    该程序为外部Makefile project,导入到eclipse中来进行编译,之后使用Jlink来进行调试. 这个是因为你在编译的时候没有加-g这个标志,导致没有生成调试文件. 让你指定一个源文件. ...

随机推荐

  1. Arduino Leonardo读取DHT22温湿度传感器

    首先在该地址下载库:https://codeload.github.com/nethoncho/Arduino-DHT22/zip/master 使用以下代码测试: /**************** ...

  2. ABP ModuleZero后台框架materialize禁止模拟select和checkbox

    使用abp modulezero自带那个后台框架发现一个操蛋的问题,所有的select和checkbox都被改成div模拟的,虽然比原生美观,但有时候真的很难用. 比如说要用select做一个联动菜单 ...

  3. Activity设置背景透明之开发坑

    Activity设置背景透明的常规方法 方法一.在Manifest.xml中,直接在需要设置的Activity中添加主题样式: Android:theme="@android:style/T ...

  4. Scrum团队 《构建之法》第6~7章

    Scrum团队成立 团队名称: 22# 团队目标:做好每次布置的任务 还有提升自己 团队口号:做好现在,展望未来 团队成员:陈楷淇,张裕发,陈泽展,彭一建 角色分配 产品负责人(决定开发内容和优先级排 ...

  5. mysql按日期分组统计数据

    最近在做一个招聘网时,需要显示一个月内企业招聘信息的发布数量,按日期分组统计,刚开始是直接从源数据库表里面进行group by,但这样子就出现日期不连续的问题了,我想要的效果是,若当天没有数据,则显示 ...

  6. [转帖]SQLSERVER的兼容级别

    SQL Server数据库的兼容级别 http://www.cnblogs.com/sosoft/archive/2017/07/08/sqljrjb.html 改天尝试一下 在SQLSERVER20 ...

  7. [转帖]InfiniBand技术和协议架构分析

    InfiniBand技术和协议架构分析 2017年06月06日 20:54:16 Hardy晗狄 阅读数:15207 标签: 云计算存储Infiniband 更多 个人分类: 存储云计算   版权声明 ...

  8. 2013杭州网赛 1001 hdu 4738 Caocao's Bridges(双连通分量割边/桥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738 题意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥 ...

  9. 关于OpenGL游戏全屏模式的设置

    使用DirectX的API的话可以给游戏窗口设置指定的显示器和全屏独占模式,但是如果使用OpenGL的API就比较遗憾不能直接设置. 以下内容基于Windows系统. 如果使用OpenGL渲染,第一步 ...

  10. jQuery Mobile页面跳转后未加载外部JS原因分析及解决

    在使用jQuery Mobile进行Web开发中,当页面跳转时(pageA => pageB),在pageB中引用的JS并未成功运行.因为,JQM并为将整个页面加载到当前的dom中,仅将data ...