九天雁翎的博客
如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。 -- Paul Graham

CMake中的字符串及文件操作

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

 以前写过一篇关于CMake的基本用法的文章(现代软件构建系统的使用 cmake简介...),在最近的使用中,发现一些更复杂情况的使用还有待学习,并且相关的资料也比较少,真正可以依赖的也就(CMake 实践)一文.所以,最近准备将一些非常重要,但是网上资料较少的用法--字符串,文件操作,好好整理一下.目标是,实现一个目录下的多个工程的一次性工程文件生成,而不是为每个工程都建立一个CMake文件,这个需求在我下载一些图书的配套源码时经常碰到,可能大部分的图书作者都习惯于仅仅提供原始源代码文件而不提供工程文件.

    特别声明的是,本文并不是一个完备3的CMake教程(以前写的简介也不是),需要相关入门教程的应该去寻找(CMake 实践),那才是你想要的.本文仅仅是作为一些缺失资料的收集,也包括我自己对CMake字符串,文件处理的探索.(真是纯个人探索,网上即使是英文的相关资料也不多,可能毕竟CMake还是不怎么流行吧),仅适合需要的人搜索到这里查看相关信息.

本文内容:

    实际上,本文研究的仅仅包括CMake的以下两部分,已经一些if,else中对字符串的判断.在本文中,由于目的不同,主要将会把CMake作为一种普通的编程语言来对待,(其实它本来就是)甚至很多地方根本不建工程,请注意.

string: String operations.
string(REGEX MATCH (regular_expression)
(output variable) (input) [(input)...])
string(REGEX MATCHALL (regular_expression)
(output variable) (input) [(input)...])
string(REGEX REPLACE (regular_expression)
(replace_expression) (output variable)
(input) [(input)...])
string(REPLACE (match_string)
(replace_string) (output variable)
(input) [(input)...])
string(COMPARE EQUAL (string1) (string2) (output variable))
string(COMPARE NOTEQUAL (string1) (string2) (output variable))
string(COMPARE LESS (string1) (string2) (output variable))
string(COMPARE GREATER (string1) (string2) (output variable))
string(ASCII (number) [(number) ...] (output variable))
string(CONFIGURE (string1) (output variable)
[@ONLY] [ESCAPE_QUOTES])
string(TOUPPER (string1) (output variable))
string(TOLOWER (string1) (output variable))
string(LENGTH (string) (output variable))
string(SUBSTRING (string) (begin) (length) (output variable))
string(STRIP (string) (output variable))
string(RANDOM [LENGTH (length)] [ALPHABET (alphabet)]
(output variable))


 

file: File manipulation command.
file(WRITE filename "message to write"... )
file(APPEND filename "message to write"... )
file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX])
file(STRINGS filename variable [LIMIT_COUNT num]
[LIMIT_INPUT numBytes] [LIMIT_OUTPUT numBytes]
[LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUM numBytes]
[NEWLINE_CONSUME] [REGEX regex]
[NO_HEX_CONVERSION])
file(GLOB variable [RELATIVE path] [globbing expressions]...)
file(GLOB_RECURSE variable [RELATIVE path]
[FOLLOW_SYMLINKS] [globbing expressions]...)
file(REMOVE [file1 ...])
file(REMOVE_RECURSE [file1 ...])
file(MAKE_DIRECTORY [directory1 directory2 ...])
file(RELATIVE_PATH variable directory file)
file(TO_CMAKE_PATH path result)
file(TO_NATIVE_PATH path result)
file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log])

 

以上列表来自于CMake最新的文档:http://www.cmake.org/cmake/help/cmake2.6docs.html

实验方式:

    完全依靠CMake的GUI工具,通过configure的输出来获取实验结果.最终的结果就是为我的博客所有源代码重建工程,以后在博客源代码中仅保留CMake的配置文件,不再保留工程, 保留工程很有局限性,比如Linux下没有makefile是很有问题的,个人建工程的时候用的是VS2008,这样VS2005的使用者也会很郁闷(虽然改个版本号就可以用),再加上以前刚开始学习OpenGL的时候非常短视,为了方便自己,将GLUT等库都装在系统目录下,这样的确是方便了自己,但是任何人clone的源代码都无法顺利运行,必须首先装一套配套的库才行,这可不是太好的工程管理方法,这次顺便解决.原来的源代码目录完全按照日期分目录,每天又分很多示例,很有典型意义.

    比如说( DirectX 9.0 3D游戏开发编程基础)--(d3d龙书)(英文名:(Introduction to 3D Game Programming with DirectX 9.0))的附带源码仅有源代码文件,分散在N个目录(每章一个目录+每章每个示例一个目录),也与我的博客中源代码的分配很类似,事实上,很多书籍配套的源代码都有这样的问题,通过这样的方法可以一次解决.没有CMake的时候,想OpenGL红宝书,D3d龙书,3D游戏编程大师这样的书的源代码你得分别建几十个工程才能很好的在Windows下使用,这是非常让人郁闷的事情,你郁闷吗?我想,我可以通过这中方法搞定这些源代码,弄一个配套的project放在google code上,方便大家;),辛苦我一人,方便千万家的工作,那是责无旁贷的完成啊:)
    本文顺便用于介绍CMake的强大及其推广,按照开源的理念,即使我没有真的参与某个开源产品的研发,我实际的使用了它,这是第一层次的支持,使用后感觉不错,向大家推广,这是第二层次的支持,我决定将我对CMake的支持上升一个层次(以前写简介的时候就上升过了)


实验过程

我的HelloWord:
获取某个源代码目录下的所有源代码,而不需要单个的列举,这是个很大的进步,在(现代软件构建系统的使用 cmake简介...)中介绍过,这是从
set(SRC_LIST test.cpp)

aux_source_directory(./ SRC_LIST)

的进步.通过aux_source_directory来实现.

现在的问题是,单个工程这个函数很好用了,对于多个工程多级目录的情况呢?答案是file()一族的函数.

cmake_minimum_required(VERSION 2.8)
FILE(GLOB_RECURSE SRC_LIST "*.cpp")
FOREACH(src ${SRC_LIST})
MESSAGE( ${src} )
ENDFOREACH()
上面的代码,放在我的博客的根目录下,会找到所有的.cpp文件并输出
关键在于两个地方FILE(GLOB_RECURSE .......
及FOREACH的使用
FILE(GLOB_RECURSE .......用于循环递归遍历目录并且使用GLOB匹配,GLOB是我们熟悉的文件匹配语法,(类似正则的简化版)
*用于表示任意长度的任意文字,?用于匹配任意的一个字符.这里*.cpp用于匹配所有的.cpp后缀的文件.
同时还有FILE(GLOB....用于非递归式的寻找,(即只寻找当前目录)
FOREACH就是我在使用C++时一直梦寐以求的循环语法,这里很明白,就是遍历${SRC_LIST}的值,然后用MESSAGE输出,所以有了以下的输出.
在CMake的GUI中,确认正确的CMakeLists.txt的位置及工程准备在的位置,Configure后,
输出一下信息:
Check for working C compiler: cl

Check for working C compiler: cl -- works

Detecting C compiler ABI info

Detecting C compiler ABI info - done

Check for working CXX compiler: cl

Check for working CXX compiler: cl -- works

Detecting CXX compiler ABI info

Detecting CXX compiler ABI info - done

F:/MySrc/blog/2009-10-12/SimpleRectangle/SimpleRectangle.cpp

F:/MySrc/blog/2009-10-14/GLDrawCircle/GLDrawCircle.cpp

F:/MySrc/blog/2009-10-14/GLDrawFourCircle/GLDrawFourCircle.cpp

F:/MySrc/blog/2009-10-14/GLFourCircleAnimation/GLFourCircleAnimation.cpp

F:/MySrc/blog/2009-10-14/GLShadeAnimation/GLShadeAnimation.cpp

F:/MySrc/blog/2009-10-14/WinDrawCircle/WinDrawCircle.cpp

F:/MySrc/blog/2009-10-18/glInterleavedArrays/glInterleavedArrays.cpp

F:/MySrc/blog/2009-10-18/glRectWithArrayDraw/glRectWithArrayDraw.cpp

F:/MySrc/blog/2009-10-18/glRectWithDrawElements/glRectWithDrawElements.cpp

F:/MySrc/blog/2009-10-18/glRectWithMultiDrawElements/glRectWithMultiDrawElements.cpp

F:/MySrc/blog/2009-10-18/glVertexArray/glVertexArray.cpp

F:/MySrc/blog/2009-10-18/glVertexArrayWithColor/glVertexArrayWithColor.cpp

F:/MySrc/blog/2009-10-20/OpenGL/debug/moc_opengl.cpp

F:/MySrc/blog/2009-10-20/OpenGL/main.cpp

F:/MySrc/blog/2009-10-20/OpenGL/opengl.cpp

F:/MySrc/blog/2009-10-21/gl3DCoordinate/gl3DCoordinate.cpp

F:/MySrc/blog/2009-10-21/glSmoothColorPyramid/glSmoothColorPyramid.cpp

F:/MySrc/blog/2009-10-21/glWirePyramid/glWirePyramid.cpp

F:/MySrc/blog/2009-10-25/glCullFace/glCullFace.cpp

F:/MySrc/blog/2009-10-25/glPolygonFace/glPolygonFace.cpp

F:/MySrc/blog/2009-10-25/glViewingTrans/glViewingTrans.cpp

F:/MySrc/blog/2009-10-26/glComposModelTrans/glComposModelTrans.cpp

F:/MySrc/blog/2009-10-26/glComposModelTrans2/glComposModelTrans2.cpp

F:/MySrc/blog/2009-10-26/glScaleSample/glScaleSample.cpp

F:/MySrc/blog/2009-10-28/glOrthoSample/glOrthoSample.cpp

F:/MySrc/blog/2009-10-28/glPerspective/glPerspective.cpp

F:/MySrc/blog/2009-10-29/JTFourTangram/JTTangram.cpp

F:/MySrc/blog/2009-11-11/glHalfTrans/glHalfTrans.cpp

F:/MySrc/blog/2009-11-12/glDepthTest/glDepthTest.cpp

F:/MySrc/blog/2009-11-12/glFogSample/glFogSample.cpp

F:/MySrc/blog/2009-11-9/glSimpleColorPyramid/glSimpleColorPyramid.cpp

F:/MySrc/blog/2009-11-9/LightSimple/LightSimple.cpp

F:/MySrc/blog/2009-9-27/Win32OpenGLTemplate/Win32OpenGLTemplate.cpp

F:/MySrc/blog/2009-9-28/RotateRect/RotateRect.cpp

F:/MySrc/blog/2009-9-29/TestOpenGL/mvarray.cpp

F:/MySrc/blog/JTTangram/JTTangram.cpp

Configuring done


获取了SRC_LIST后,就可以开始处理了

FOREACH(src ${SRC_LIST})
    IF(NOT (src MATCHES ".*2009-10-20.*")) 
        MESSAGE( ${src} Finded)
        STRING( REGEX REPLACE ".*/(.*)/.cpp$" "/1" prjName ${src} )
        MESSAGE( ${prjName} Added)
        ADD_EXECUTABLE( ${prjName} ${src} )
        IF (NOT (prjName STREQUAL mvarray) )
            SET_TARGET_PROPERTIES(${prjName} PROPERTIES WIN32_EXECUTABLE "true")
        ENDIF(NOT (prjName STREQUAL mvarray) )
    ENDIF(NOT (src MATCHES ".*2009-10-20.*"))
ENDFOREACH(src)
一下是关键点的解释:

通过STRING( REGEX REPLACE命令来获取到所有的.cpp后缀的文件,因为我的工程中所有的工程都仅包含一个cpp,所以可以这样做

string(REGEX REPLACE (regular_expression)
(replace_expression) (output variable)

的语法不算太好用,学会以后,就主要靠你的正则表达式理解能力了,几乎无所不能.CMake的语法中用()来表示正则表达式的匹配捕获,

用"1"的方式在替换中表示捕获到的字符串(会正则的理解起来应该不难).但是,特别需要注意的是,CMake中需要用/1的形式来传递参数,就像你在C++中需要做的那样.


ADD_EXECUTABLE( ${prjName} ${src} )

以每个cpp的文件名来作为工程名,每个源文件作为此工程需要的文件.


SET_TARGET_PROPERTIES(${prjName} PROPERTIES WIN32_EXECUTABLE "true")

用于指定我的这些工程都是Win32的工程(调用WinMain),默认时时命令行的工程.


上面这么几句就完成了为我10多个工程的一次工程文件生成


此代码中有几个特别点:

2009-10-20那个工程是一个Linux的工程,不要生成VS下Win32的工程,我通过

IF(NOT (src MATCHES ".*2009-10-20.*")) 的形式过滤掉了


IF (NOT (prjName STREQUAL mvarray) )语句用于过滤mvarray所在的工程,因为它是一个命令行的工程(使用Glut管理窗口)


以下是完整的文件(CMake的高亮很漂亮吧:)见我以前fachc2c),完成文件也可在我博客的示例代码中获取.

PROJECT( JTianLingBLog )
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
INCLUDE_DIRECTORIES(./dependes/windows/include/)
LINK_DIRECTORIES(../dependes/windows/lib/)
FILE(GLOB_RECURSE SRC_LIST "*.cpp")
FOREACH(src ${SRC_LIST})
    IF(NOT (src MATCHES ".*2009-10-20.*"))
        MESSAGE( ${src} Finded)
        STRING( REGEX REPLACE ".*/(.*)/.cpp$" "/1" prjName ${src} )
        MESSAGE( ${prjName} Added)
        ADD_EXECUTABLE( ${prjName} ${src} )

        IF (NOT (prjName STREQUAL mvarray) )
            SET_TARGET_PROPERTIES(${prjName} PROPERTIES WIN32_EXECUTABLE "true")
        ENDIF(NOT (prjName STREQUAL mvarray) )

    ENDIF(NOT (src MATCHES ".*2009-10-20.*"))
ENDFOREACH(src)


进一步的应用

有了以上的经验后,我再为(d3d龙书)的源代码生成工程,以方便大家.
原来源代码的目录结构前面已经讲过了,直接先看全部CMake文件的代码:

PROJECT( IntroToD3D9 )
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

FILE(GLOB_RECURSE srcList "*.cpp")

# fliter duplicates projects
FOREACH(src ${srcList})
        MESSAGE("finded: " ${src})
        STRING( REGEX REPLACE "(.*/.*)/.*/.cpp$" "/1" dirName ${src} )
        LIST(APPEND dirNameList ${dirName})
        MESSAGE("directory Finded: " ${dirName} )
ENDFOREACH(src ${srcList})

MESSAGE("..................................................................")

LIST(REMOVE_DUPLICATES dirNameList)

FOREACH(dir ${dirNameList})
        MESSAGE( ${dir} " Process begin.....")
        STRING( REGEX REPLACE ".*/(.*)" "/1" prjName ${dir} )
        FILE(GLOB prjSrcList "${dir}/*.cpp" "${dir}/*.h")

        FOREACH(prjSrc ${prjSrcList})
                MESSAGE("src glob: " ${prjSrc})
        ENDFOREACH(prjSrc)

        MESSAGE("before replace Project: " ${prjName} )
        STRING( REPLACE " " "" prj ${prjName})
        ADD_EXECUTABLE( ${prj} ${prjSrcList} )

        MESSAGE("Added Project: " ${prj} )
        SET_TARGET_PROPERTIES(${prj} PROPERTIES WIN32_EXECUTABLE "true")
        TARGET_LINK_LIBRARIES(${prj} d3d9 d3dx9 winmm)

ENDFOREACH(dir ${dirName})


已经比较复杂了,基本上,看到这里,你会认可其实CMake就是一个专门用于管理工程的脚本语言-_-!

这里讲一下代码中的几个要点,就不多说了:

FILE(GLOB_RECURSE srcList "*.cpp" 遍历所有.cpp文件(带完整路径)

用STRING( REGEX REPLACE "(.*/.*)/.*/.cpp$" "/1" dirName ${src} )获取到目录名

LIST(APPEND dirNameList ${dirName})

保存所有的目录名,此时因为可能每个目录中有多个源代码导致重复,然后通过
LIST(REMOVE_DUPLICATES dirNameList)
将重复去掉
再通过
STRING( REGEX REPLACE ".*/(.*)" "/1" prjName ${dir} )
获取目录最后的名字作为每个工程的名字
FILE(GLOB prjSrcList "${dir}/*.cpp" "${dir}/*.h")
再反过来,获取每个目录下的源代码(此时已经获得了每个工程及其对应的源代码了
剩下的就简单了
STRING( REPLACE " " "" prj ${prjName})
是唯一有意思的,去掉所有的空格后再建立工程(原来的目录中有空格,所以获取的工程名也有空格,并且导致建立的目录及一些文件会出现问题)
TARGET_LINK_LIBRARIES(${prj} d3d9 d3dx9 winmm)
链接上需要的库,OK,一下子生成几十个工程,还带ALL_BUILD选项,爽
为了方便大家,我将所有的( DirectX 9.0 3D游戏开发编程基础)(英文名:(Introduction to 3D Game Programming with DirectX 9.0)源代码托管在Google Code上了,并且建立好了VS2008的工程(不需要的用CMake换吧),大家各取所需吧.
浏览地址:
http://code.google.com/p/jtianling/source/browse/?repo=introd3d9
CheckOut地址:
hg clone https://introd3d9.jtianling.googlecode.com/hg/ jtianling-introd3d9
下载地址:
呵呵独家出品带工程的源代码:)
最后其实还有个问题,原来的源代码资源全部在各自的目录中,运行时的默认工作路径与工程一直,这样会全部找不到资源.但是我没有找到CMake怎么改变工作路径.
在网上找到一个CMake 的 FAQ()是这样解释的:

 Can CMake set the Debugging/Working Directory property in Visual Studio projects?

No. The value of this property is not stored in the project files.
It is stored in extra files created by the IDE when a solution is
loaded (VS .NET 2003 uses a hidden .suo file next to the .sln solution
file). The format of these files is not known to CMake and cannot be
generated. In some versions of VS the files are binary and not human
readable. 

事实上,我一直以为VS中将工作路径放在suo文件中而不是工程文件是MS干过的最愚蠢的事情之一,导致工作中的使用从来没有达到过从

源代码库中获取源代码及工程后,直接正常编译运行的情况,工作路径必须的额外设置,并且,要知道,是每个工程的工作路径!也因为这个原因,还因为suo是一个只有MS才懂的二进制文件,CMake无法自动改变此值,也就是说,虽然我已经通过CMake为你生成了几十个工程,但是凡事需要用到资源的地方,你都得手动改变工作路径,真无聊啊!!!!还好资源文件都不一样,我将其全部移到projects目录下,这样,只要你在projects目录下生成工程,默认的运行工作路径就是当前工作路径,省去了这样的操作,但是带来的资源及projects混合的情况,那就没有办法了.你们去骂MS吧,我已经尽力了.

事实上,虽然用CMake完成上述工作后,一次就建立了所有需要的工程,几十个几十个的生成,会感觉很爽,其实,花去的时间(主要用于学习CMake诡异特别的语法)要远超过自己一个一个手动生成工程.但是,实在无法忍受手动生成几十个工程的枯燥,习惯重复的工作只能使人越来越懒,没有任何收获...................

enjoy them all!

    

博客本身完整源代码获取说明

由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

可商业使用的免费软件推荐列表(revision 2 )

write by 九天雁翎(JTianLing) -- www.jtianling.com


讨论新闻组及文件

 

缘起

 

     可以参看《谷歌金山词霸是完全免费的吗?谷歌自己的软件呢?
》中的原因,新的公司对软件的使用控制很严,(当然,从中国的情况出发显的很严,其实严是正常的)我需要能够可商业使用(其实仅表示可以在企业使用)的免费使用的软件,并且,事实上,为了维持工作环境的尽量统一,我将尽量保持公司家里一套软件环境而不是公司一套家里一套,这样会很麻烦,比如会碰到公司的openoffice文档在家里没有办法用office来编辑和查看的问题。

    于是,软件寻找之旅开始了。。。。。。。。。。中间有很多陷阱,这里会告诉大家。。。。。另外,每个软件后以(Linux Enable)标志Linux下也可用。

 

列表:

 

文本编辑工具:

OpenOffice:作为MS Office的替代,相对来说,有一些不太好用的地方,但是使用后发现数学公式的编写利用了类Tex的方式,强大的很,HTML,PDF的输出也是非常漂亮。(Linux Enable)

GVim:常用,特别是一般简单代码的编写,比如Python,Lua等。(Linux Enable)

notepad++:插件丰富,事实上,也用其16进制编辑插件用于替代Winhex,事实上由于我更习惯GVim,所以其实用的很少.

Google Doc:非常强大,支持博客的发布,并且自带版本控制,这点使得其更加强大,平时管理文档时使用hg的管理的麻烦方式完全省略了.(Linux Enable)

 

IDE:

作为程序员最常使用的东西之一,自然需要一个好用的,还好我们有很多选择:

C++: Visual studio express,MS出品的免费产品,事实上,因为不能使用Visual assist X和ViEmu,原来的VS还是还是太简单了,这几点有些郁闷,ViEmu就是无可替代的。。。。。。。在某些情况下,我们也仅能使用Autohotkey
+Ditto来稍微的替代一下Visual assist的snippet功能.

JAVA: Eclipse,强大无须多言,很多好用的插件都是免费的,唯一可惜的就是一个vi的模拟插件是要钱的(其实也相当不好用)。(Linux Enable)

 

 

版本控制:

TortoiseHg:我喜欢在本地使用TortoiseHg来管理自己的源代码。(Linux Enable)

TortoiseSVN: 仍然是世界上最优秀的源代码管理软件之一

 

文档生成工具:

doxygen: 通吃C++,C#,JAVA世界,开源世界最流行(不开源应该也流行)的文档生成工具,生成的文档漂亮并且索引做的很好,boost等众多开源产品使用的家伙。虽然JAVA自带JAVADOC功能,但是为了统一,感觉都是用doxygen也没有什么不可以。(Linux Enable)

资源管理器:

freecommand:以前还以为是彻底告别TotalCommand了,结果原来还有免费的可以用啊。。。。虽然没有TotalCommand好用,典型的就是插入U盘不刷新,常用目录功能设计不合理。但是,免费的嘛。

 

即时通信:

MSN:企业专用-_-!没得选择。

QQ: 偶尔用用,大众选择.

 

比较工具:

WinMerge:最好的目录,文件比较工具肯定是Beyond compare,可惜是收费的。。。。于是,WinMerge稍微替代一下吧,而在源代码合并时使用的比较工具,WinMerge是最优秀的。

 

浏览器:

这个世界浏览器这么重要的东西竟然几乎全是免费的。。。。。。。。。而那么多小工具却都是收费的,有人能够给我解释一下吗?我解释一下,因为世界上所占份额最高的产品是MS垄断的Internel Explorer,所以其他软件公司没有办法收费。。。。。。。按照这样的逻辑,假如有一天Windows是免费的,那么,估计很难再有其他收费的操作系统.不是吗?

IE:为了兼容性的考虑,很多时候不得不使用,比如迅雷看看,比如网银,其他时候一般不使用。

FireFox:最常使用的浏览器,因为众多插件的存在,无疑是世界上最优秀的浏览器,事实上,对我来说Firefox已经不仅仅是个浏览器了。我使用Gmail Manager来关注Gmail,使用FlashGot+DownthemAll!来作为下载工具,使用Adblock Plus来控制广告,使用FireShot(仅Windows下可用)来对网页进行截图,使用FoxTab来管理众多的Tab,使用Weave+XMarks来管理书签。。。。。当然,还有tor套装。(Linux Enable)

Chrome:使用此浏览器主要用于测试一些javascript,毕竟其效率比较高.

 

笔记软件:

Evernote:以前使用的是Google Note,的确比较好用,但是因为Google Note已经停止开发了,所以将所有数据导入了Evernote中使用,每月有40M的使用空间限制,但是基本够用了,对于文本以外的东西支持的也非常好(比如图片)。网页版在Linux下可用,并且可以使用Firefox的evernote插件.

 

截图软件:

picpick:网页的截图使用FireFox的FireShot插件,普通的截图使用Evernote带的功能,已经基本够用,再复杂点的情况,截图,然后绘制一些指导性的文字和箭头时,picpick这样非常小巧好用的软件就非常适合了.

 

看图软件:

Picasa:因为很多优秀的看图软件都是个人使用免费却非商业的,IrfanView,XnView等软件我在家里用用还可以,但是他们是不允许商业使用的(non-commercial)的,(特别注意啊。。。)Picasa以前使用过,可能因为用惯了IrfanView,觉得太花,认为它是管理照片才用的,所以开始没有使用,事实上使用后觉得看看图也不错。

 

思维导图:

XMind:虽然freemind也是不错的软件,但是感觉XMind生成的图片更好看,所以嘛。。。呵呵,割舍freemind了。(Linux Enable)

 

输入法:

搜狗输入法:虽然常常做出匪夷所思的广告行为,但是总体而言,输入法还是搜狗的用的比较舒服。

 

图像编辑:

GIMP
:不说太好用,但是基本还行,也找不到更好的免费软件了。同时还做为不常见图片格式的查看工具(比如tga)(Linux Enable)

 

邮件客户端:

Thunderbird
:以前工作的时候连网都不能上,使用Gmail的时候也靠Firefox的Gmail Manager插件使用,不用专业的邮件客户端(当年的foxmail可是很出名,也用过,可是当时真的没有这个工作需求),使用Thunderbird的感觉还是不错的。(Linux Enable)

 

文件搜索:

Everything: 搜索速度的确是如善用佳软中所说的快到令人发指。。。。。。不用不知道,一用吓一跳,真的比Windows自身的快太多了,Google桌面虽然搜索功能还还行,可是太花,太拖累系统了,所以割爱放弃。

 

脚本工具:

AutoHotkey
:GUI的bash工具,强大无比。以前我有过专门的文章介绍。见《懒惰是程序员的美德! 懒惰程序员的最爱AutoHotkey 尝鲜

 

视频播放:

k-mplayer:韩国的一个播放软件,无广告,支持的视频总类多,可选信息丰富,支持高清加速,个人使用后没有再考虑过别的软件。(据说其使用GNU不开源。。。。。)

Realplayer: 作为k-mplayer的补充。(Linux Enable)

 

压缩软件:

7-Zip:虽然使用方便程度上与Winrar还有一定差距,但是哪叫它是免费开源的呢。。。。(Linux Enable)

 

虚拟桌面软件:

VirtualWin:非常方便,支持自定义快捷键,切换速度也比很多同类软件快的多。(Linux下自然就不需要了)

 

FTP工具

FileZilla:不仅仅又方便的FTP客户端,甚至还有服务器版本。。。。强大的无以复加。

 

电子词典:

stardict:特别注意金山词霸。。。。。。。个人免费(non-commercial),别被谷歌和到处免费的字眼混淆了,stardict虽然在屏幕捕获上有些问题,(用复制来代替就好了)其他方面还是很好的。(Linux Enable)

 

日程管理:

Google Calendar+Gmail+Task:基本上已经很好用了,事实上我以前试用过Chandler这个梦幻般的软件,可惜速度上实在无法接受。。。。Python啊Python…….也许在用JAVA编写的大型软件都会有人抱怨速度慢的今天(比如Eclipse),用Python编写。。。。速度上要让人接受并不容易啊。。。。(Linux Enable)

 

剪贴板增强工具:

Ditto:剪贴板的历史记录保存算是小功能,但是在没有办法使用Visual Assist的功能时,与autohotkey互补使用Ditto的命名剪贴功能,作为补充。

 

UML绘制

StarUML:刚开始离开了Rational Rose会有不习惯的感觉。。。。。但是发现了StarUML后,发现原来开源免费的软件不一定就比庞大著名的商业软件差,Rational Rose的逆向工程(从代码到UML)我就没有搞明白怎么用过,但是一拿到StarUML就会用,非常好用!不过工程大了的时候,UML图会有点卡。

更多我会安装的东西,一般人可能不需要了。

 

数学计算及可视化

scilab:法国出的很强大的软件,以前因为其与matlab的语法不兼容而选择了与matlab语法兼容的GNU Octave和freemat等,但是到了更高级的计算时,这两个软件根本无法胜任,这个两个软件仅仅只能作为简单数学的可视化工具而已,相关的toolbox太少,因此,无奈的选择了与matlab不兼容的道路...............(Linux Enable)

 

Unix环境:

Cygwin:让Windows有类似Unix的环境,贡献无论怎么评价都不过分,特别是bash及其shell的全套引入,习惯了Unix脚本管理的人使用起来方便没有极限,哪怕是简单的grep工具的使用,Windows下我也不知道有啥可以替代的。。。。

MingW:Windows下的gcc套件,虽然我自己不用,但是很多软件用到,比如Qt

目前有些软件在公司还没没有碰到需求,所以暂时没有列出来,此列表考虑长期更新吧,不仅给大家一个参考,自己假如碰到重新安装电脑的时候,也能一一的安装。

 

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com


阅读全文....

从剪贴板到剪贴板的通用语法高亮软件发布(支持N多语言)

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

 需求来源

    不太喜欢太限制于Windows下的Windows live
writer(以下简称WLW),虽然很多人认为它是博客写作工具的number
one,甚至看到有外国的朋友曾经高呼,Linux下唯一缺少替代品的软件就是WLW了,经过长久的使用,本身功能并不算太强大,但是开放的插件系统,让
其强大到无以复加,我在以前《windows
live
writer
试用及众多插件试用评测...



文中有很详细的描述,过程中也解决过很多WLW本身的问题,比如没有模板的问题,(通过autohotkey解决),比如说本地保存目录不能改变的问题,
(通过junction来改变)比如在公司及家中文档不能同步的问题,(通过dropbox),但是越依赖WLW,我就感觉越不舒服,因为我在Linux
下越来越感觉没有好用的博客写作工具了,而且WLW专有的格式,使得我无法太好的使用已有的文档,这些都是无法忽视的大问题,于是,最终,我决定彻底的迁
移到Google Document上来,无论是普通的文档,还是Blog的写作。

    首先有个先天性的问题,Google
Document是没有开发插件系统的,这样,碰到问题我们都没有办法通过扩展来解决,特别突出的问题就是代码高亮问题,对于程序员的博客。。。。。。贴
代码实在是太经常的事情了,不能解决此问题也是我以前甚至愿意用Word2007来写博客都不用Google
Document。既然今天决定了使用Google
Document,那么找个办法来解决此问题吧,方法目前想到一个,HTML的直接插入,(还好Google
Document支持),那么我只需要将代码在剪贴板中保存为高亮的HTML,然后直接嵌入Google Document就行了,So
Easy................解决此问题吧,于是就有了我的新工程“code-highlight-clipboard2clipboard
”,因为自己写语法分析及高亮的代码实在太麻烦了,只好选择站在巨人的肩膀上:)我利用GVim来解决此问题。(目前使用时需要自己先安装Gvim,并且将其目录加进PATH中,即在任何目录下都能通过gvim命令调用到gvim)

 

先看看效果

 

此文在Google Document下完成,以下是主体源代码的实际转换效果。还算是比较漂亮吧:)

 


 1
from
 optparse import
 OptionParser
 2
from
 distutils.file_util import
 *
 3
import
 os
 4
import
 tempfile
 5

 6
def

 main
():
 7
    
 8
    usage = 'usage: %prog [options]
'
 9
    version = '''%prog 0.1 Created By JTianLing

10
Any Question could be sent to JTianLing{at}Gmail.com,

11
and any advice or any bug report is appreciated too.
'''
12
    
13
    parser = OptionParser(usage, version = version)
14
    parser.add_option('-f
', '--filename
', metavar = 'FILE
', dest = 'filename
',
15
                      help = 'Write output to FILE and save it.
')
16
    parser.add_option('-t
', '--syntax
', action = 'store
',
17
                      type = 'string
', dest = 'syntax
',
18
                      default = '',
19
                      help = 'Set the code syntax type
')
20
    parser.add_option('-c
', '--color
', action = 'store
',
21
                      type = 'string
', dest = 'color
',
22
                      default = 'default
',
23
                      help = 'Set the code highlight color template
')
24
    parser.add_option('-n
', action= 'store_true
', dest = 'isNumber
',
25
                      default = False,
26
                      help = 'Is output with line number.
')
27
    (options, args) = parser.parse_args()
28
    
29
    filename = tempfile.mktemp() + '.tmp
'
30
        
31
    cboutStr = 'cbout >
' + filename
32
    os.system(cboutStr)
33
    
34
    syn = options.syntax
35
    color = options.color
36
    
37
    # ugly but useful vim's format code

38
    vimCmd = 'gvim -c ":syntax on|:color
' + color + '|:set syn=
' + syn/

39
     + '|:set nu
' + ('' if

 options.isNumber else

 '!
') + '|TOhtml" -c ":w|:qa"
' + filename
40
    os.system(vimCmd)
41
    #print(vimCmd)

42
    
43
    newFilename = filename + '.html
'
44
    cbinStr = 'more
' + newFilename + ' | cbin
'
45
    os.system(cbinStr)          
46

47
    # Del the temp file when that's needed

48
    if

 options.filename:
49
        move_file(newFilename, './
' + options.filename)
50
    else

:
51
        os.remove(newFilename)
52
        
53
    os.remove(filename)
54
    
55
if

 __name__ == '__main__
':
56
    main()

 

 

使用

 

除了以上的源代码,我还实现了两个类似于stdin及stdout的与剪贴板相关的cbin,cbout命令(clipboard in or out)。实际使用方法类似stdin及stdout,分别是写入剪贴版中及从剪贴板中读出数据,(只支持文本格式)

其实下一版预计还可以抽出整个转换的过程,那样使用起来可能更加灵活。目前此代码仅在Windows下测试,但是为了兼容,我使用了PyQt的库(所以狂大,其实才几行代码),将来会在Linux下测试及发布Linux的

二进制版本。

 

使用方法是在Google Document中通过(Edit->Edit Html->粘贴->Update),你也可以保存为任何你想要的文件/粘贴到你想要去的任何位置。

命令的使用方法如下:

 

>chc2c --help
Usage: chc2c [options]

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -f FILE, --filename=FILE
                        Write output to FILE and save it.
  -t SYNTAX, --syntax=SYNTAX
                        Set the code syntax type
  -c COLOR, --color=COLOR
                        Set the code highlight color template
  -n                    Is output with line number.

 

支持的语言

 

支持的语言种类/语法格式几乎囊括了常见的所有语言,(仅限制于Vim支持的种类,站在巨人的肩膀上就是好),以下是一个列表:

 


2html          a2ps
a65            aap            abap           abaqus
abc            abel           acedb          ada
aflex          ahdl           alsaconf       amiga
aml            ampl           ant            antlr
apache         apachestyle    arch           art
asm            asm68k         asmh8300       asn
aspperl        aspvbs         asterisk       asteriskvm
atlas          autohotkey     autoit         automake
ave            awk            ayacc          b
baan           basic          bc             bdf
bib            bindzone       blank          bst
btm            bzr            c              calendar
catalog        cdl            cdrdaoconf     cdrtoc
cf             cfg            ch             change
changelog      chaskell       cheetah        chill
chordpro       cl             clean          clipper
cmake          cmusrc         cobol          coco
colortest      conaryrecipe   conf           config
context        cpp            crm            crontab
cs             csc            csh            csp
css            cterm          ctrlh          cuda
cupl           cuplsim        cvs            cvsrc
cweb           cynlib         cynpp          d
dcd            dcl            debchangelog   debcontrol
debsources     def            denyhosts      desc
desktop        dictconf       dictdconf      diff
dircolors      diva           django         dns
docbk          docbksgml      docbkxml       dosbatch
dosini         dot            doxygen        dracula
dsl            dtd            dtml           dtrace
dylan          dylanintr      dylanlid       ecd
edif           eiffel         elf            elinks
elmfilt        erlang         eruby          esmtprc
esqlc          esterel        eterm          eviews
exim           expect         exports        fasm
fdcc           fetchmail      fgl            flexwiki
focexec        form           forth          fortran
foxpro         framescript    freebasic      fstab
fvwm           fvwm2m4        gdb            gdmo
gedcom         git            gitcommit      gitconfig
gitrebase      gitsendemail   gkrellmrc      gnuplot
gp             gpg            grads          gretl
groff          groovy         group          grub
gsp            gtkrc          haml           hamster
haskell        haste          hastepreproc   hb
help           hercules       hex            hitest
hog            hostconf       html           htmlcheetah
htmldjango     htmlm4         htmlos         ia64
ibasic         icemenu        icon           idl
idlang         indent         inform         initex
initng         inittab        ipfilter       ishd
iss            ist            jal            jam
jargon         java           javacc         javascript
jess           jgraph         jproperties    jsp
kconfig        kix            kscript        kwt
lace           latte          ld             ldapconf
ldif           lex            lftp           lhaskell
libao          lifelines      lilo           limits
lisp           lite           litestep       loginaccess
logindefs      logtalk        lotos          lout
lpc            lprolog        lscript        lsl
lss            lua            lynx           m4
mail           mailaliases    mailcap        make
man            manconf        manual         maple
masm           mason          master         matlab
maxima         mel            messages       mf
mgl            mgp            mib            mma
mmix           mmp            modconf        model
modsim3        modula2        modula3        monk
moo            mp             mplayerconf    mrxvtrc
msidl          msmessages     msql           mupad
mush           muttrc         mysql          named
nanorc         nasm           nastran        natural
ncf            netrc          netrw          nosyntax
nqc            nroff          nsis           objc
objcpp         ocaml          occam          omnimark
openroad       opl            ora            pamconf
papp           pascal         passwd         pcap
pccts          pdf            perl           pf
pfmain         php            phtml          pic
pike           pilrc          pine           pinfo
plaintex       plm            plp            plsql
po             pod            postscr        pov
povini         ppd            ppwiz          prescribe
privoxy        procmail       progress       prolog
promela        protocols      psf            ptcap
purifylog      pyrex          python         qf
quake          r              racc           radiance
ratpoison      rc             rcs            rcslog
readline       README.txt         rebol          registry
remind         resolv         reva           rexx
rhelp          rib            rnc            rnoweb
robots         rpcgen         rpl            rst
rtf            ruby           samba          sas
sass           sather         scheme         scilab
screen         sd             sdl            sed
sendpr         sensors        services       setserial
sgml           sgmldecl       sgmllnx        sh
sicad          sieve          simula         sinda
sindacmp       sindaout       sisu           skill
sl             slang          slice          slpconf
slpreg         slpspi         slrnrc         slrnsc
sm             smarty         smcl           smil
smith          sml            snnsnet        snnspat
snnsres        snobol4        spec           specman
spice          splint         spup           spyce
sql            sqlanywhere    sqlforms       sqlinformix
sqlj           sqloracle      sqr            squid
sshconfig      sshdconfig     st             stata
stp            strace         sudoers        svn
syncolor       synload        syntax         sysctl
tads           tags           tak            takcmp
takout         tar            tasm           tcl
tcsh           terminfo       tex            texinfo
texmf          tf             tidy           tilde
tli            tpp            trasys         trustees
tsalt          tsscl          tssgm          tssop
uc             udevconf       udevperm       udevrules
uil            updatedb       valgrind       vb
vera           verilog        verilogams     vgrindefs
vhdl           vim            viminfo        virata
vmasm          voscm          vrml           vsejcl
wdiff          web            webmacro       wget
whitespace     winbatch       wml            wsh
wsml           wvdial         xbl            xdefaults
xf86conf       xhtml          xinetd         xkb
xmath          xml            xmodmap        xpm
xpm2           xquery         xs             xsd
xslt           xxd            yacc           yaml
z8a            zsh            

 

 

是不是比目前存在的所有语法高亮工具支持的语言种类还要多?你要是说你懂的上面没有的语言,我一定认为你是神仙。。。。。。。。。。。。

 

好了,别的不多说了,自己下载试用吧,目前还是0.1版,以后会慢慢增加一些功能的,最主要的是找到一个精简版的vim(目前需要首先自己安装Vim才能使用,并将Vim的目录加入PATH中才能使用)

 

 

完整源代码获取说明

工程保管在Google上:http://code.google.com/p/code-highlight-clipboard2clipboard/

也可以直接使用Mercurial克隆下库:

https://code-highlight-clipboard2clipboard.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

迅雷官方手把手教你,一个下载软件中到底可以强行植入多少广告

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

参看来源:http://vip.xunlei.com/freedom/freedom_skinad.html

的确是官方权威资料。。。。。。。。不弄虚作假哦

image

其实,即使成为会员,迅雷下方的“资讯”还是无法屏蔽,这也是上面官方未提及的广告。。。。。。。。。

唉。。。互联网时代,要用一个好的下载软件就得忍受这么多东西。。。。。。说实话,我几乎天天使用迅雷,还有迅雷看看,但是却怎么都对迅雷提不起好感,(好像这样的软件及公司就迅雷一家了)不知道是不是我自己有问题。。。。。。。。起码,迅雷对于我,还算是免费提供服务。为啥我对Google的感觉好的多呢?唉。。。。都是广告公司,看看广告的水平就知道了。

何况,迅雷软件的很多流氓做法实在让人忍无可忍。。。。。。。迅雷老总不是说么?有的软件的流氓行为看起来很诱人,但是我们坚决不会做。。。。。注意,“有的”两字,其他自己体会。

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

十五种途径告诉你什么不是云计算

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

云计算最近炒的很火,这点不用我说了,但是我们知道什么是云计算吗?

可以参考一下《技术百科:什么是云计算(图文)》

但是,广大的云计算应用还是容易让人迷惑,今天看到国外的一篇文章,教你怎么去识别伪云计算及真正的云计算,有的很实在,有的很搞,算是异类,翻译过来,给大家一个参考,大家也可以以此对比一下,到底广大厂商各自炒作的产品是真是伪,也可纯粹作为娱乐。

原文来自《15 Ways to Tell Its Not Cloud Computing》:(实际十六条)

假如它提到“网格计算”和“开放式网格计算服务”。。。。。它不是一个真的云

假如你需要发送40页需求文档给服务器提供商才能获取服务。。。。。它不是一个真的云

假如你不能用自己的信用卡购买。。。。。它不是一个真的云

假如他们尝试卖你硬件。。。。。它不是一个真的云

假如没有一个API可供调用。。。。。它不是一个真的云

假如你需要为了它重新设计你的系统。。。。。。它不是一个真的云

假如它需要超过10分钟才能提供服务。。。。。。它不是一个真的云

假如你不能在10分钟之内终止服务。。。。。它不是一个真的云

假如你知道机器在哪。。。。。。它不是一个真的云

假如房子里还有个顾问。。。。它不是一个真的云

假如你需要预先支付你需要的机器数量。。。。。它不是一个真的云

假如它只能在一个操作系统中运行。。。。。。它不是一个真的云

假如你不能从你自己的机器上连接上它。。。。。它不是一个真的云

假如你需要为使用它而安装软件。。。。。它不是一个真的云

假如你拥有所有的硬件。。。。。。。。。。。它不是一个真的云

假如它需要花费20页幻灯片来解释。。。。。。它不是一个真的云

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com 

阅读全文....

3D 图形编程的数学基础(3) 矩阵基本变换

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

这里开始,是真正的与3D图形编程相关的知识了,前两节只能算是纯数学。

 

平移矩阵

要想将向量(x, y, z, 1)沿x轴平移yyyy_html_1d45df16个单位,沿y轴平移yyyy_html_m6cec65e6,沿z轴平移yyyy_html_m63b4a2d4个单位,我们只需要将该向量与如下矩阵相乘。

N(p) = yyyy_html_m1964a5f8[4]

从中可以看出4*4矩阵N中的N41,N42,N43分别控制其在x轴y轴z轴上的平移单位.

yyyy_html_m75c5e44f是单位矩阵,我们已经知道,乘以其他矩阵相当于没有乘的家伙。这个矩阵就是从单位矩阵稍微变下型,多了第4行的几个值。我们先来看yyyy_html_1d45df16为最后结果做出的贡献,向量M(x,y,z,1)与矩阵N(p)相乘后,最后X坐标的值(也就是矩阵M11的值)为x*1 + y*0 + z*0 + 1*px = x + px。(套一下矩形相乘的公式)

y,z的公式一样,就不多说了。这里可以看到,对于实施矩阵平移计算来说,需要将原向量(3维)扩充的一维(一般用w表示)设为1,不然的话,上述x坐标=x*1 + y*0 + z*0 + 0*px=x,也就是说,完全不会改变原矩阵了。

GNU Octave(matlab) 验证一下:

> p = [1,0,0,0;0,1,0,0;0,0,1,0;2,3,4,1]
p =

   1   0   0   0
   0   1   0   0
   0   0   1   0
   2   3   4   1

octave-3.2.3.exe:6:d:/Octave/3.2.3_gcc-
> x
x =

   1   2   3   1

octave-3.2.3.exe:7:d:/Octave/3.2.3_gcc-
> x * p
ans =

   3   5   7   1

octave-3.2.3.exe:8:d:/Octave/3.2.3_gcc-

x = 2 + 1 = 3,依次类推,结果正确。

在irrlicht中,平移矩阵的代码直接偷懒。。。。。利用了上述公式的推导结果,转换后的x值为x+px。。。。汗-_-!,理论和实际果然还是有差距的。不过想想,说来也是,一个加法就可以完成的平移,为啥非要整个矩阵乘法去完成?此公式的存在就让人郁闷。。。难道仅仅是因为需要的是用矩阵进行的计算。。。。。。

template <class T>
inline void CMatrix4<T>::translateVect( vector3df& vect ) const
{
    vect.X = vect.X+M[12];
    vect.Y = vect.Y+M[13];
    vect.Z = vect.Z+M[14];
}

D3D中利用函数:

// Build a matrix which translates by (x, y, z)
D3DXMATRIX* WINAPI D3DXMatrixTranslation
    ( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z );

实现矩阵的平移,具体方式不明。

 

缩放矩阵

我们将一单位矩阵沿X轴缩放X倍,Y轴缩放Y倍,Z轴缩放Z倍,可令该向量与下列矩阵相乘。

html_html_m2794d7de

按公式推导:X(M11)坐标值为X*x+y*0+z*0+0*0=X*x

y,z的推导类似。

GNU Octave(matlab):

> x = [1,2,3,0]
x =

   1   2   3   0

octave-3.2.3.exe:6:f:
> p
p =

   2   0   0   0
   0   3   0   0
   0   0   4   0
   0   0   0   1

octave-3.2.3.exe:7:f:
> x * p
ans =

    2    6   12    0

结果正确。其实看了实现的源代码后也会发现这种公式还是没事找事,事实上直接乘多省事啊。

irrlicht中利用下面的实现来构造一个缩放矩阵:

    template <class T>
    inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale )
    {
        M[0] = scale.X;
        M[5] = scale.Y;
        M[10] = scale.Z;
#if defined ( USE_MATRIX_TEST )
        definitelyIdentityMatrix=false;
#endif
        return *this;
    }

 

D3D中利用下面的实现完成缩放运算,直接乘就好了。。。。。。

D3DXINLINE D3DXVECTOR3* D3DXVec3Scale
    ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, FLOAT s)
{
#ifdef D3DX_DEBUG
    if(!pOut || !pV)
        return NULL;
#endif

    pOut->x = pV->x * s;
    pOut->y = pV->y * s;
    pOut->z = pV->z * s;
    return pOut;
}

 

 

旋转矩阵:

旋转矩阵是在乘以一个向量的时候有改变向量的方向但不改变大小的效果的矩阵。旋转矩阵不包括反演,它可以把右手坐标系改变成左手坐标系或反之。所有旋转加上反演形成了正交矩阵的集合。需要注意的是,进行旋转变换时,扩充3维向量的办法是令w=0;

我们可用如下3个矩阵将一个分量分别绕着x,y,z轴顺时针旋转θ弧度。

X(θ) = yyyy_html_m5a3e8644

Y(θ) = yyyy_html_6d8ae198

Z(θ) = html_html_3de18d4c

还是先看第一个公式,向量M(x,y,z,0)与矩阵X(θ)相乘后,最后X(M11)坐标值为x*1+y*0+z*0+0*0=x,Y(M12)坐标值为x*0+y*cosθ+z*(-sinθ)+0*0 = y*cosθ + z * (-sinθ),Z(M13)坐标值为x*0+y*sinθ+z*cosθ+0*0 = y*sinθ + z*cosθ,w(m14)坐标为x*0+y*0+z*0+0*1 = 0。

这个就复杂了。。。。。不太好直观的看到验证的结果,我们将其收到2维去看结果。

我们利用GNU Octave(matlab) 的compass命令在2维空间中直观的显示出向量x = [ 1, tan(pi/3), 0, 0](实际显示在x,y平面中)

我们用其围绕Z轴顺时针旋转30度时,方式是乘以θ为30的如上矩阵,结果如下:

image

 

> a = pi / 6
> p = [cos(a),sin(a),0,0;-sin(a),cos(a),0,0;0,0,1,0;0,0,0,1]
p =

   0.86603   0.50000   0.00000   0.00000
  -0.50000   0.86603   0.00000   0.00000
   0.00000   0.00000   1.00000   0.00000
   0.00000   0.00000   0.00000   1.00000

octave-3.2.3.exe:26:f:/Octave/3.2.3_gcc-4.4.0/bin
> x = [1, tan(pi/3), 0, 0]
x =

   1.00000   1.73205   0.00000   0.00000

octave-3.2.3.exe:27:f:/Octave/3.2.3_gcc-4.4.0/bin
> x2 = x * p
x2 =

   0.00000   2.00000   0.00000   0.00000

octave-3.2.3.exe:28:f:/Octave/3.2.3_gcc-4.4.0/bin
>

精确的30度。

irrlicht中设置旋转矩阵就有学问了:

    template <class T>
    inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation )
    {
        const f64 cr = cos( rotation.X );
        const f64 sr = sin( rotation.X );
        const f64 cp = cos( rotation.Y );
        const f64 sp = sin( rotation.Y );
        const f64 cy = cos( rotation.Z );
        const f64 sy = sin( rotation.Z );

        M[0] = (T)( cp*cy );
        M[1] = (T)( cp*sy );
        M[2] = (T)( -sp );

        const f64 srsp = sr*sp;
        const f64 crsp = cr*sp;

        M[4] = (T)( srsp*cy-cr*sy );
        M[5] = (T)( srsp*sy+cr*cy );
        M[6] = (T)( sr*cp );

        M[8] = (T)( crsp*cy+sr*sy );
        M[9] = (T)( crsp*sy-sr*cy );
        M[10] = (T)( cr*cp );
#if defined ( USE_MATRIX_TEST )
        definitelyIdentityMatrix=false;
#endif
        return *this;
    }

为了解释这个函数的作用,看看下列程序:

#include "irrlicht.h"
#include <math.h>

#pragma comment(lib, "Irrlicht.lib")

using namespace irr;
using namespace irr::core;

int _tmain(int argc, _TCHAR* argv[])
{

    f32 a = 30;
    f32 M[16] = { 1, 0, 0, 0, 
                  0, 1, 0, 0,
                  0, 0, 1, 0,
                  0, 0, 0, 1};
    matrix4 mt;
    mt.setM(M);

    vector3df vec(0.0, 0.0, PI / 6);

    mt.setRotationRadians(vec);

    for(int i = 0; i < 4; ++i)
    {
        for(int j = 0; j < 4; ++j)
        {
            printf("%.6f/t", mt(i, j));
        }
        printf("/n");
    }


    return 0;
}

运行结果为:

0.866025        0.500000        -0.000000       0.000000
-0.500000       0.866025        0.000000        0.000000
0.000000        0.000000        1.000000        0.000000
0.000000        0.000000        0.000000        1.000000

看到是啥了吗?没错,就是GNU Octave(matlab) 那个例子中的矩阵:

p = [cos(a),sin(a),0,0;-sin(a),cos(a),0,0;0,0,1,0;0,0,0,1]

事实上,上面程序中的vec表示不绕x,y轴旋转,绕Z轴旋转PI/6,实际的作用就是构造了上述的矩阵P。

上述矩阵通过以下成员函数应用以使用生成的矩阵,其实就是乘法-_-!

template <class T>
inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
{
    vector3df tmp = vect;
    vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
    vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
    vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
}

//! An alternate transform vector method, writing into a second vector
template <class T>
inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const
{
    out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
    out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
    out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
}

//! An alternate transform vector method, writing into an array of 3 floats
template <class T>
inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
{
    out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
    out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
    out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
}

上面程序后加上如下几句,使用上面刚生成的矩阵:

vector3df x(1.0, tan(PI/3), 0.0);
mt.rotateVect(x);

printf("x = [%f, %f, %f]/n", x.X, x.Y, x.Z);

输出结果:

x = [-0.000000, 2.000000, 0.000000]

与通过GNU Octave(matlab) 的一样,精确的30度旋转。

与旋转有关的还有vector的几个函数:

//! Rotates the vector by a specified number of degrees around the Y axis and the specified center.
/** /param degrees Number of degrees to rotate around the Y axis.
/param center The center of the rotation. */
void rotateXZBy(f64 degrees, const vector3d<T>& center=vector3d<T>())
{
    degrees *= DEGTORAD64;
    f64 cs = cos(degrees);
    f64 sn = sin(degrees);
    X -= center.X;
    Z -= center.Z;
    set((T)(X*cs - Z*sn), Y, (T)(X*sn + Z*cs));
    X += center.X;
    Z += center.Z;
}

//! Rotates the vector by a specified number of degrees around the Z axis and the specified center.
/** /param degrees: Number of degrees to rotate around the Z axis.
/param center: The center of the rotation. */
void rotateXYBy(f64 degrees, const vector3d<T>& center=vector3d<T>())
{
    degrees *= DEGTORAD64;
    f64 cs = cos(degrees);
    f64 sn = sin(degrees);
    X -= center.X;
    Y -= center.Y;
    set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs), Z);
    X += center.X;
    Y += center.Y;
}

//! Rotates the vector by a specified number of degrees around the X axis and the specified center.
/** /param degrees: Number of degrees to rotate around the X axis.
/param center: The center of the rotation. */
void rotateYZBy(f64 degrees, const vector3d<T>& center=vector3d<T>())
{
    degrees *= DEGTORAD64;
    f64 cs = cos(degrees);
    f64 sn = sin(degrees);
    Z -= center.Z;
    Y -= center.Y;
    set(X, (T)(Y*cs - Z*sn), (T)(Y*sn + Z*cs));
    Z += center.Z;
    Y += center.Y;
}

事实上这些函数就是前面两步的一步实现,实际就是利用了上述公式推导最后的结果,可以去对比一下。

比如下列代码:

vector3df x(1.0, tan(PI/3), 0.0);
x.rotateXYBy(30);

printf("x = [%f, %f, %f]/n", x.X, x.Y, x.Z);

输出:

x = [-0.000000, 2.000000, 0.000000]

就是前面通过两步得出的结果。上面irrlicht代码需要注意的是,参数是degree是表示单位是度数,其他时候都默认为弧度。

D3D中使用下列函数实现旋转,没有实现源代码,没有太多好说的。

// Build a matrix which rotates around the X axis
D3DXMATRIX* WINAPI D3DXMatrixRotationX
    ( D3DXMATRIX *pOut, FLOAT Angle );

// Build a matrix which rotates around the Y axis
D3DXMATRIX* WINAPI D3DXMatrixRotationY
    ( D3DXMATRIX *pOut, FLOAT Angle );

// Build a matrix which rotates around the Z axis
D3DXMATRIX* WINAPI D3DXMatrixRotationZ
    ( D3DXMATRIX *pOut, FLOAT Angle );

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

更改windows live writer的本地保存目录

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

这个世界上总是有很多片让人不爽的事情,很多事情我们没有办法改变,因为程序员也没有办法控制世界的改变,虽然事实上我们在改变着世界,但是,只要这个让人不爽的事情发生在电脑上,那么,作为程序员,我们就能让这个不爽变得极爽。。。。。。呵呵,此为一例,原文来自:http://www.ditii.com/2009/01/30/guide-to-move-windows-live-writers-my-weblog-posts-folder-onto-a-seperate-location/

百度知道上:http://zhidao.baidu.com/question/63748594.html

极为误导,枪毙之。有人有百度账号的话给他回复一下,别继续误导人了。

我仅仅是大概翻译一下:

1.都是先将整个目录拷贝到你想要放在的位置。

2.

Vista/Win 7 用户:

命令行下:

mklink /D “目前本地保存目录” “你想要的新的保存目录”

Windows XP用户痛苦点(比如我)

先下个Junction,(好像是微软官方提供的)

junction “目前本地保存目录” “你想要的新的保存目录”

其中,目前本地保存的目录就是Windows live writer默认的那个My Weblog Posts

我将其放在了DropBox的目录里面。。。。。。。。。不会丢失辛苦的劳动成果了。

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

3D图形编程的数学基础(1)-向量及其计算

因为大学时在高等数学课程中学习过线性代数相关的内容, 所以学习3D编程的时候这一段事实上是跳过去了, 学习到某些内容的时候觉得很郁闷, (4, 5年没有用了, 难免忘掉)最后常常依靠高级API完成, 但是事实上这些高级API的算法具体实现啥的基本看不懂, 于是还是决定回来好好的将基础部分弄明白, 当然, 首先是数学部分. 为了更好的达到直观的效果, 还有在复杂矩阵运算的时候验证运算结果, 将引入MATLAB的使用. 具体牵涉到计算的时尽量实现DirectX与Irrlicht两个版本, 也会参考部分源代码. (主要用于看看公式用C/C++的实现)基本上, 我希望能以概念的讲解为主, 最好是直观的讲解.

阅读全文....

谷歌金山词霸是完全免费的吗?谷歌自己的软件呢?

write by 九天雁翎(JTianLing) -- www.jtianling.com


讨论新闻组及文件

缘起

在中国有多少人关心一个软件是否免费?有人关心吗?有的,我以前寻找优秀的免费软件常常到“善用佳软

”中看推荐,对于自己工作效率的提高有很多帮助,但是最近我换了新工作,因为是外企,使用软件的版权限制比以前会更加严格,不仅仅是不能使用盗版,而且要求此软件不仅仅是个人免费,还需要是商业使用免费的才能在公司使用,这样,“善用佳软

”这样的网站就不能起到帮助我的作用,甚至容易起误导作用了。。。。。。因为有太多的软件是表明个人使用免费并且不允许商业使用的,却又往往夹着100%免费软件的口号推广(最典型的就是谷歌金山词霸了,所以多讲了点)。。。。。。。其实本文是为“个人使用,商业使用都免费的常用软件列表”作的。。。。。算作前篇吧。特别是为身处相同环境的人提个醒,不论事实上一些软件看起来多么号称“免费”,还是不一定能在企业环境中使用。

原来我有个类似的使用软件列表,见《程序员手中的利器(1)--工欲善其事必先利其器
》,那时候对软件使用比较随便。。。。因为新公司对软件使用的版权限制很严,所以,我自己也需要一份可以免费商业使用的日常软件列表,(准备以后完成一个)以防不注意掉进版权的漩涡之中。。。。。要是以前,我写这样的文章那自然是被人骂“莫装B,装B被雷劈”了,现在是有这个真实的需求。事实上,为了维持工作环境的尽量统一,我是尽量保持公司家里一套软件环境而不是公司一套家里一套,这样会很麻烦,比如会碰到公司的openoffice文档在家里没有办法用office来编辑和查看的问题。

 

开源版权与自定免费版权

首先,让我们了解各种版权(以前有人关心吗?)你知道什么是GPL
,LGPL
,BSD,MIT……….吗?对于使用来说,类似的开源协议软件是我们的首选,因为此类软件的日常使用(不开发就不需要了解各个开源协议的不同了)肯定不会有版权纠纷,此类协议的设计宗旨之一就是free(自由) to use(当然,不仅仅是这一点),虽然很多次的强调了此free仅仅表示自由,但是现实中,选择此类协议的软件即便收费也都是靠服务收费的,也就是说,个人使用,即使是商用,你不寻求服务,也是免费和自由的,(有的pro版例外,我们也不追求这个)我选择软件时肯定也是尽量选择GPL协议(或其相容协议)的开源软件的。。。。。

其次,自定的免费协议,这类协议需要特别注意,一不小心就会掉进版权的陷阱之中,此类软件比较多,需要非常小心,比如谷歌金山词霸,这是最最典型的,

入选“Google 软件精选
”的一个软件,什么是“Google 软件精选”?原主页描述如下:

image

永久免费?aha?

还有说明的文字:

关于软件精选: 免费程序

Google 软件精选中的所有软件都是免费的。 有些程序可能提供付费版本以提供其他功能或正在进行的更新,但您可以选择不安装这些付费版本。
Google 软件精选中的 Spyware Doctor 和 Norton Security Scan 版本均包含订阅,可以进行自动更新。这些更新可让程序找出并消除新的威胁因素,并且用户可以免费使用这些更新。 虽然通过这些更新可以升级到付费版本,但您可以继续使用 Google 软件精选提供的免费版本(只要您已安装了这些免费版本)。

在谷歌金山词霸的主页上有更多类似“免费”的标志:

image6

主页光是一个title的图片就是3个免费。。。。。。。。。。

主页下载链接:

image12

纵观金山词霸全网,都是推荐产品的广告,竟然没有任何产品的licence信息说明。。。。。。(去看看国外的软件网站,必有)

好吧,好吧,既然谷歌和金山都说谷歌金山词霸免费,一个是永久的免费,一个是完全的免费,又没有任何版权说明,那应该就是免费了吧,下一个来用用吧,我去华军这个国内下载速度快的网站去下(上面也有版权提示信息的,而且没有一般没破解版和病毒),一看:

image15

好啊,免费版,下呗。。。。。。。。。。。。。。

 

安装时有个协议:

image21

这个框很小,放不大,只能拖动滚动条,看完累死你,我还需要将其全部选中,然后拷贝出来查看才会方便点。(一般的协议窗口好像都有这样的毛病。。。。其实都当自己是摆设来着)

其中,金山部分第1条:

1.  在一台个人所有计算机、工作站、终端机、手持式计算机或其它数字电子仪器(“计算机”)上安装、使用、显示、运行(“运行”)本“软件” 的一份副本。本“软件”仅供个人所有计算机使用,不得用于法人或其他组织(包括但不限于政府机关、公司、企事业单位、其他组织等;无论该组织是否为经济性组织;无论该组织的使用是否构成商业目的使用)所有计算机。如若个人所有计算机长期固定为法人或其他组织服务,则将被视为“法人或其他组织所有计算机”,无法享受本授权。任何超出上述授权范围的使用均被视为非法复制的盗版行为,金山软件保留权利要求相关责任人承担相应的法律责任包括但不限于民事责任、行政责任、刑事责任。

简而言之,谷歌金山词霸仅限个人使用,不允许商业使用,即使是公共机构的电脑上都不允许使用(不作为商业用途也不行),我不知道谷歌和金山是怎么理解“永久免费”和“完全免费”这两个词的意思。。。。。谷歌金山词霸就太搞了,平时使用的时候一堆堆的无聊信息自动弹出就算了,免费的嘛,结果还是个人免费。。。。。。

其实作为软件开发人员,对中国人没有养成软件的付费习惯这种事情也是很郁闷的,在中国这种大环境下,客户端软件走免费路线,极大的扩大用户群,然后赚增值服务费用和广告费是比较靠谱的做法,对于那些勇于免费的优秀软件我也是很欢迎的,可是见不得谷歌金山词霸这样。。。。。到处说免费,还“永久免费”,“完全免费”来着,那就算了,当是夸大广告推广吧,主页连个版权说明都没有,直到下载回来了,还得仔细的往那么一个小框中的协议中找,才能知道原来此软件仅仅是个人免费的。。。。。。。希望即便是作为免费的推广,你也标志清楚吧?网站连个版权信息都没有,必须等你下载回来安装了才能知道,这样太郁闷了。

 

Google也是个人使用非商业?

这事情到这里不算完,假如仅仅是金山词霸就算了,中国的公司嘛,我什么事情都看惯了,问题是,这次是谷歌金山词霸,入选谷歌软件精选软件的软件,谷歌什么时候开始推广个人免费企业禁用的软件了?你听说过?Google Chrome,Google Gmail,Google Doc,Google Note,Google Calendar只允许个人使用吗?(其实上述软件在Google软件精选中是列入Google企业应用套件的。。。。。。不允许企业使用的企业应用套件有价值吗?。。。。。。。)

这点我很有疑问,于是我查看了一下Google软件精选安装时的协议(最近协议看了无数,头都大了)

最接近的一条是:

您完全理解并同意:

    D) 本软件不能用于以下场合:核设施、生命支持系统、紧急通讯、飞行器导航或通讯系统、空中交通控制系统,或软件故障可能导致死亡、个人伤害或严重人身或环境损害的任何活动。

全文“非商业”一词仅出于:

18. Google 地球的其他规定

    B) 软件的使用。对于个人最终用户,仅可根据此处的服务条款和 Google 地球软件文档的规定下载本软件,并出于个人的、非商业的目的而使用本软件。对于企业实体最终用户或政府实体最终用户,您和您的员工可依照此处的服务条款和 Google 地球软件文档的规定在内部使用本软件(个人最终用户、企业最终用户和政府最终用户在本协议中统称为“您”)。除非您已经得到 Google 的特别许可,否则不得出于下列用途或与之有关的用途将 Google 地球软件和交通工具中安装的、以其他方式连接的或与之通信的任何产品、系统或应用程序结合起来使用,这些用途包括:(a) 实时路线导航(包括但不限于按转弯路口提供的分步路线导航和通过传感器启用的其他路线导航);(b) 任何用于自动或自主控制交通工具行为的系统或功能;或 (c) 调度、车队管理或类似应用。您不得使用本 Google 地球软件使自己或其他任何人能够对纬度和经度数字坐标进行批量下载和收录。

也就是说,注意了Google地球是不允许在企业使用的,但是Google软件精选的其他软件是允许的,但是不准在“软件故障可能导致死亡、个人伤害或严重人身或环境损害的任何活动”中使用而已。。。。。。(当然,我们事实知道,谷歌金山词霸是不允许的),这点,中文的协议让我很郁闷。。。。。。。。。。。既然谷歌金山词霸是非商业的为啥作为入学谷歌软件精选的软件在此不做额外声明?这不是拉着别人往火坑中跳吗?就这一点来说,我可以认为谷歌中国工作有不严谨的地方。(即使不说这是他们工作的严重问题)

这是Google中国,我很怀疑Google是否一直这样,就这样的工作风格和态度怎么能做成全球知名企业,(事实上,作为一名软件开发人员,我是典型的Google fans,因为原来Google App只能使用Python,我甚至因此学习了Python)我决定上Google 英文网站上一探究竟。。。可惜的是,Google 英文网站上没有将谷歌金山词霸入选软件精选(看来这个东西是谷歌公司各国自己搞的了)

谷歌软件精选的英文的协议有如下条款:

Open source software licenses for Google source code constitute separate written agreements.
To the limited extent that the open source software licenses expressly supersede these Terms and Conditions, the open source licenses govern your agreement with Google for the use of Google products or specific included components of Google products.

The Google Software, and any portion thereof, and the Third Party Software, and any portion thereof, are referred to herein as the "Software."
1. USE OF SOFTWARE

The Software is made available to you for your personal, non-commercial use only.
You may not use the Google Software in any manner that could damage, disable, overburden, or impair Google's search services (e.g., you may not use the Google Software in an automated manner), nor may you use Software in any manner that could interfere with any other party's use and enjoyment of Google's search services or the services and products of Third Parties. "Third Parties" means the third party licensors of the Software.

英文软件精选的版权说明就很明确的说明了,除了开源软件额外有版权说明的,其他软件都是仅允许个人使用,非商业的。。。。。

这点也与我对Google的传统形象有所区别,可能毕竟Google软件精选不是完全是Google自家的产品,只能在此放弃了企业用户了吧。。。当然,其他纯Google自家的产品,除了Google地球(可能的确是想靠为一些导航设备或者手机授权赚钱),还是能放心的使用的。

到此,对谷歌金山词霸不能商业使用表示理解,但是,对Google中国的不明确表示和谷歌金山词霸的网站无版权说明还是不理解。。。或者是,他们自己本身就没有期望在中国会有人仔细的看这些长篇大论的协议?

民众没有了版权意识的确是中国软件行业最可悲的事情之一,但是,当企业在中国也慢慢失去了版权意识,甚至不知道什么时候应该提示版权,不知道在什么地方应该明确的标志版权,这才是中国软件行业最最可悲的事情。

 

在今天早上再次去看Google中的软件精选安装时的声明时发现有以下条款:

本软件提供给您仅限于个人的、非商业性质的用途。您在使用 Google 软件时不得以任何方式损害、破坏、过载或消弱 Google 的搜索服务(例如:您不得以自动方式使用 Google 软件),也不得干扰他人使用和享受 Google 的搜索服务或第三方的服务和产品。“第三方”是指软件的第三许可方。

我昨天可能看漏了然后错怪Google中国了-_-!表示抱歉,然后修改题目。。。。。。。。。。

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com


阅读全文....