﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Bill Hsu-随笔分类-C/C++</title><link>http://www.cppblog.com/billhsu/category/7689.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 01 Feb 2011 08:19:05 GMT</lastBuildDate><pubDate>Tue, 01 Feb 2011 08:19:05 GMT</pubDate><ttl>60</ttl><item><title>Android游戏计时</title><link>http://www.cppblog.com/billhsu/archive/2011/01/30/139627.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sun, 30 Jan 2011 15:16:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2011/01/30/139627.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/139627.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2011/01/30/139627.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/139627.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/139627.html</trackback:ping><description><![CDATA[
Read this post in english:<a target="_blank" href="http://androgeek.info/?p=299">http://androgeek.info/?p=299<br></a><br>以前代码经验很多都是基于windows的，所以对android下面的计时函数不是太了解。<br><br>在写<a target="_blank" href="http://hi.baidu.com/probill/blog/item/16945fde1f86005b94ee37bb.html">Friut3D</a>时，我用的代码是用gettimeofday()来计时的。但是效果不好，游戏里有个场景跑起来十分卡，acepig兄和我都觉得这个问题很诡异。开始觉得这是模型的问题，现在看来是计时函数不精确惹得祸。<br><br>看看当时写的获取系统时间的代码：<br><br>
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;getTime(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br><br>{<br>gettimeofday(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">now,&nbsp;NULL);<br></span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">long</span><span style="color: #000000;">)(now.tv_sec</span><span style="color: #000000;">*</span><span style="color: #000000;">1000</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;now.tv_usec</span><span style="color: #000000;">/</span><span style="color: #000000;">1000</span><span style="color: #000000;">);<br>}</span></div>
<br><br>今天在一个google讨论组里得知gettimeofday()记得的tick是不准确的。而这个游戏逻辑依赖于time delta来计算各个物体运动，计时不精确，渲染自然会卡顿。<br><br>于是用纳秒级的准确度的clock_gettime()重写了getTime()函数：<br><br>
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;_getTime(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br><br>{<br></span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;timespec&nbsp;now;<br>clock_gettime(CLOCK_MONOTONIC,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">now);<br></span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;now.tv_sec</span><span style="color: #000000;">*</span><span style="color: #000000;">1000000</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;now.tv_nsec</span><span style="color: #000000;">/</span><span style="color: #000000;">1000</span><span style="color: #000000;">;<br><br>}</span></div>
<br><br>改了计时函数后，游戏各个场景都流畅了。<br>  <img src ="http://www.cppblog.com/billhsu/aggbug/139627.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2011-01-30 23:16 <a href="http://www.cppblog.com/billhsu/archive/2011/01/30/139627.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android NDK 开发OpenGL ES 2.0一些注意点</title><link>http://www.cppblog.com/billhsu/archive/2010/08/10/122914.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Tue, 10 Aug 2010 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2010/08/10/122914.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/122914.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2010/08/10/122914.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/122914.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/122914.html</trackback:ping><description><![CDATA[Android是个好系统哇，特别是Android NDK r3出来以后，可以用OpenGL ES 2.0了。<br>自己也试了试用NDK编一个OpenGL ES 2.0的程序，可是，编译的时候出现了一大堆错。<br><img style="width: 592px; height: 392px;" src="http://www.cppblog.com/images/cppblog_com/billhsu/jni1.JPG" border="0"><br>如图，满屏幕都是 undefined reference to 那些OpenGL ES函数。<br>看来是库文件没有链接进来。<br><br>这是NDK例子里的Android.mk的写法：<br>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">LOCAL_PATH:</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;$(call&nbsp;my</span><span style="color: #000000;">-</span><span style="color: #000000;">dir)<br><br>include&nbsp;$(CLEAR_VARS)<br><br>LOCAL_MODULE&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;libgl2jni<br>LOCAL_CFLAGS&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Werror<br>LOCAL_SRC_FILES&nbsp;:</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;gl_code.cpp<br><span style="color: red;">LOCAL_LDLIBS&nbsp;&nbsp;&nbsp;&nbsp;:</span></span><span style="color: red;">=&nbsp;-llog&nbsp;-</span><span style="color: #000000;"><span style="color: red;">lGLESv2</span><br><br>include&nbsp;$(BUILD_SHARED_LIBRARY)</span></div>
<br>问题就出在用红色标出的那行。<br><br>把那句修改为：<br>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">LOCAL_LDLIBS&nbsp;:</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">L$(SYSROOT)</span><span style="color: #000000;">/</span><span style="color: #000000;">usr</span><span style="color: #000000;">/</span><span style="color: #000000;">lib&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">llog<br>LOCAL_LDLIBS</span><span style="color: #000000;">+=-</span><span style="color: #000000;">L$(SYSROOT)</span><span style="color: #000000;">/</span><span style="color: #000000;">usr</span><span style="color: #000000;">/</span><span style="color: #000000;">lib&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">lGLESv2</span></div>
<br>就可以正常编译了。<br><br>还有一些注意点是：<br>编译程序前要clean，否则编译会出错；<br>每次更新了自己的.so文件后，在eclipse的那个java项目里要记着refresh一下。<br><br>  <img src ="http://www.cppblog.com/billhsu/aggbug/122914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2010-08-10 11:37 <a href="http://www.cppblog.com/billhsu/archive/2010/08/10/122914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>靠得住的休眠函数XSleep</title><link>http://www.cppblog.com/billhsu/archive/2010/07/30/121679.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Fri, 30 Jul 2010 02:55:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2010/07/30/121679.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/121679.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2010/07/30/121679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/121679.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/121679.html</trackback:ping><description><![CDATA[直接用timeGetTime()这个函数的误差是有目共睹的，在15ms左右，于是，如果游戏的消息循环用了timeGetTime()，那么3D游戏画面会因为两帧之间时间误差大而有些抖动。<br>今天在csdn上看到了一篇文章：<a href="http://blog.csdn.net/lanzhengpeng2/archive/2008/05/06/2401554.aspx">http://blog.csdn.net/lanzhengpeng2/archive/2008/05/06/2401554.aspx</a><br>讲的也正好是这个问题，记录一下。<br><br>在使用timeGetTime()的代码块的前后加上<span class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span class="Apple-style-span" style="font-family: verdana,sans-serif; font-size: 14px; line-height: 21px; text-align: left;">timeBeginPeriod(1)和</span></span><span class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span class="Apple-style-span" style="font-family: verdana,sans-serif; font-size: 14px; line-height: 21px; text-align: left;">timeEndPeriod(1)，就可以提高</span></span>timeGetTime()的精度。<br><br>同时，可以利用timeSetEvent写了一个靠得住的休眠函数[代码来自上述文章]：<br>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;XSleep(DWORD&nbsp;dwDelay,HANDLE&nbsp;hEvent)<br>&nbsp;{<br>&nbsp;&nbsp;MMRESULT&nbsp;hTimer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;timeSetEvent(dwDelay,</span><span style="color: #000000;">1</span><span style="color: #000000;">,(LPTIMECALLBACK)hEvent,</span><span style="color: #000000;">0</span><span style="color: #000000;">,TIME_ONESHOT&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;TIME_CALLBACK_EVENT_SET);<br>&nbsp;&nbsp;MsgWaitForMultipleObjectsEx(</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">hEvent,INFINITE,QS_ALLINPUT,</span><span style="color: #000000;">0</span><span style="color: #000000;">);&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">当有Windows消息时，还能继续处理Windows消息。故选择了这个函数。</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;timeKillEvent(hTimer);<br>&nbsp;}</span></div>
<br>消息循环[代码来自上述文章]：<br>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;MSG&nbsp;msg;<br>&nbsp;DWORD&nbsp;dwLastTime;<br>&nbsp;HANDLE&nbsp;hSleepEvent&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;CreateEvent(NULL,FALSE,FALSE,NULL);<br><br>&nbsp;timeBeginPeriod(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br><br>&nbsp;dwLastTime&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;timeGetTime();<br>&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(isActive())<br>&nbsp;{<br>&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">需要一直处理Windows消息到无消息处理为止</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(;PeekMessage(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">msg,NULL,</span><span style="color: #000000;">0</span><span style="color: #000000;">,</span><span style="color: #000000;">0</span><span style="color: #000000;">,PM_REMOVE);)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(msg.message&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;WM_QUIT)<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hSleepEvent);<br>&nbsp;&nbsp;&nbsp;&nbsp;timeEndPeriod(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #000000;">!</span><span style="color: #000000;">TranslateAccelerator(msg.hwnd,hAccelTable,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">msg))<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;TranslateMessage(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;DispatchMessage(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">msg);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;DWORD&nbsp;FrameDelay&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;max(</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">1000</span><span style="color: #000000;">/</span><span style="color: #000000;">max(</span><span style="color: #000000;">1</span><span style="color: #000000;">,GetMaxFPS()));<br>&nbsp;&nbsp;DWORD&nbsp;dwTime&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;timeGetTime();<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(dwLastTime&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;FrameDelay&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;dwTime)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;XSleep(dwLastTime&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;FrameDelay&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;dwTime,hSleepEvent);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;update();<br>&nbsp;&nbsp;&nbsp;dwLastTime&nbsp;</span><span style="color: #000000;">+=</span><span style="color: #000000;">&nbsp;((dwTime&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;dwLastTime)&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">&nbsp;FrameDelay)&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;FrameDelay;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">当实际帧数严重低于预期帧数时，这段代码可以完成跳帧功能；当实际帧数大于等于预期帧数时，这段代码仍然可以使帧之间的时间间隔固定。之前谢Boss没有处理好的主要就是这个。</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;}<br>&nbsp;}<br><br>&nbsp;CloseHandle(hSleepEvent);<br>&nbsp;timeEndPeriod(</span><span style="color: #000000;">1</span><span style="color: #000000;">);</span></div>
这样，时间误差就会在1ms之内了，游戏也就不会抖动了。<br> <img src ="http://www.cppblog.com/billhsu/aggbug/121679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2010-07-30 10:55 <a href="http://www.cppblog.com/billhsu/archive/2010/07/30/121679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fstream那些事</title><link>http://www.cppblog.com/billhsu/archive/2010/03/27/110683.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sat, 27 Mar 2010 10:37:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2010/03/27/110683.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/110683.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2010/03/27/110683.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/110683.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/110683.html</trackback:ping><description><![CDATA[感觉fstream有些地方设计的不太合理，不知道是bug还是那些牛X们故意这样的。<br /><br />首先，fstream竟然在中文路径这种东西上不支持，网上也可以看到许多实现方法，但有的方法其实并不是太好。<br />我觉得这样做最简单：<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">setlocale(LC_ALL,</span><span style="color: rgb(0, 0, 0);">""</span><span style="color: rgb(0, 0, 0);">);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">设置成当前语言环境</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">ofstream </span><span style="color: rgb(0, 0, 255);">out</span><span style="color: rgb(0, 0, 0);">(filename);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">打开文件</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">setlocale(LC_CTYPE, </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">);</span></div><br />还有，fstream的getline也有问题，对于那些\n \r 空行 什么的都没考虑，用起来会出错。<br />在网上看到一个函数可以完美解决这个问题：<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">bool</span><span style="color: rgb(0, 0, 0);"> readline(ifstream</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);"> infile, </span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);"> textline)<br />{<br /><br /></span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(getline(infile, textline, </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\n</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">))<br />{<br />  </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> prev_pos </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">最开始有效字符位置.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> post_pos </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">最后有效字符位置<br />  </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">下面的循环语句能够用textline.find_first_not_of(filter,pos)来处理,出于效率考虑本处使用这样的算法</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(textline[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> textline[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> textline[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\r</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">过滤开始空白</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">   prev_pos</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br />  </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(textline[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\0</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)<br />   </span><span style="color: rgb(0, 0, 255);">continue</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">假如是空白行则再读一行进行处理.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />  {<br />       post_pos</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">textline.length()</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">;<br />       </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(textline[post_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> textline[post_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> textline[post_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\r</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">过滤最后的空白</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">             {<br />                  post_pos</span><span style="color: rgb(0, 0, 0);">--</span><span style="color: rgb(0, 0, 0);">;<br />             }<br />       textline</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">textline.substr(prev_pos,post_pos</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">prev_pos);<br />   </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">成功读取一有效行</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  }<br />  <br />}<br /></span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">读到文档的末尾</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">}<br /></span></div><br />我根据上面这个函数 重载了一个char* 版的：<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 255);">bool</span><span style="color: rgb(0, 0, 0);"> readline(ifstream</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);"> infile, </span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> textline)<br />{<br /></span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(infile.getline(textline,</span><span style="color: rgb(0, 0, 0);">32</span><span style="color: rgb(0, 0, 0);">))<br />{<br />  </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> prev_pos </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">最开始有效字符位置</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> post_pos </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">最后有效字符位置.  </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);"> str</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">textline;<br />  </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">下面的循环语句能够用textline.find_first_not_of(filter,pos)来处理,出于效率考虑本处使用这样的算法</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(str[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> str[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> str[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\r</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">过滤开始空白</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">   prev_pos</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br />  </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(str[prev_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\0</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)<br />   </span><span style="color: rgb(0, 0, 255);">continue</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">假如是空白行则再读一行进行处理</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />  {<br />         post_pos</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">str.length()</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">;<br />         </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(str[post_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> str[post_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);"> str[post_pos] </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">\r</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">过滤最后的空白</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">         {<br />               post_pos</span><span style="color: rgb(0, 0, 0);">--</span><span style="color: rgb(0, 0, 0);">;<br />         }<br />         </span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);"> str2</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">str.substr(prev_pos,post_pos</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">prev_pos);<br />         strcpy(textline,str2.c_str());<br />         </span><span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">   </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">成功读取一有效行</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">  }<br />}<br /></span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">读到文档的末尾</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">}</span></div><br /><br /><img src ="http://www.cppblog.com/billhsu/aggbug/110683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2010-03-27 18:37 <a href="http://www.cppblog.com/billhsu/archive/2010/03/27/110683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GPU水面模拟</title><link>http://www.cppblog.com/billhsu/archive/2010/03/23/110376.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Tue, 23 Mar 2010 12:59:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2010/03/23/110376.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/110376.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2010/03/23/110376.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/110376.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/110376.html</trackback:ping><description><![CDATA[先上个自己实现的水面模拟图：<br /><img id="ViewPicture1_GalleryImage" src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/r_water1.JPG" style="border: 2px solid Black;" height="206" width="274" /><br /><br />效果比较简单，只是模拟了下水面的反射效果。折射与Fresnel系数没有考虑。<br /><br />水面模拟大致需要分这么几步：<br />1.剪裁掉水面以下的顶点[gpu里的clipplane要注意转换到Clip Space]，<br />将摄像机放到同原摄像机关于水面对称的位置，比如原来摄像机在(x,y,z)，<br />此时就该把摄像机放在(x,-y,z)，up向量也要设置成向下的。<br />再把场景渲染到Render Target的纹理上(我用的纹理大小是256*256)，不知道为什么Render Target的纹理大小不能超过窗口大小，超过的话渲染会出错，知道的大大告诉我一下哈。<br /><br />于是，就得到了这样一个纹理：<br /><img id="ViewPicture1_GalleryImage" src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/r_water3.JPG" style="border: 2px solid Black;" height="198" width="198" /><br /><br />2.将上面得到的纹理与水面的顶点对应.<br />把Vertex Shader中乘过变换矩阵后的坐标传到Pixel Shader,<br />在PS中计算<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">        float2 clipspace = input.Coord.xy / input.Coord.w;<br />        clipspace.x=((clipspace.x * 0.5f) + 0.5f);<br />        clipspace.y = ((clipspace.y * -0.5f) + 0.5f);<br />        clipspace.x=1-clipspace.x;</span><span style="color: rgb(0, 0, 0);"></span></div>既可以让水面顶点与纹理对应，然后再想办法把纹理坐标扰乱来模拟水面波动。<br /><br />3.再渲染一次场景就可以了。<br /><br />大家也可以参考下Azure的水面渲染源代码：<a temp_href=" http://www.azure.com.cn/article.asp?id=186" href="%20http://www.azure.com.cn/article.asp?id=186"><br />http://www.azure.com.cn/article.asp?id=186</a><br /><img src ="http://www.cppblog.com/billhsu/aggbug/110376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2010-03-23 20:59 <a href="http://www.cppblog.com/billhsu/archive/2010/03/23/110376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>可编程管道下的剪裁平面</title><link>http://www.cppblog.com/billhsu/archive/2010/01/20/106088.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Wed, 20 Jan 2010 14:00:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2010/01/20/106088.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/106088.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2010/01/20/106088.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/106088.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/106088.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal">
				<span>剪裁平面</span>
				<span>(Clip Plane)</span>
				<span>在图形学领域有着重要的作用，比如水面模拟中，渲染折射纹理时，我们就必须将水面以上的顶点通过剪裁平面剪裁掉。</span>
		</p>
		<p class="MsoNormal">
				<span>在过去的固定渲染管道时代，剪裁平面的实现较为简单，比如在</span>
				<span>DirectX 9</span>
				<span>中，可以先设定剪裁平面在世界坐标系下的方程</span>
				<span>(ax+by+cz+d=0)</span>
				<span>，再调用</span>
				<span>SetClipPlane(DWORD Index,CONST float * pPlane)</span>
				<span>这个</span>
				<span>API</span>
				<span>函数就可以了。</span>
		</p>
		<p class="MsoNormal">
				<span> </span>
		</p>
		<p class="MsoNormal">
				<span>附上例子程序：</span>
		</p>
		<p class="MsoNormal" style="background: none repeat scroll 0% 0% rgb(238, 238, 238); text-align: left; -moz-background-inline-policy: continuous;" align="left">
				<span style="font-size: 10pt; color: black;">vPosition=D3DXVECTOR3(0,0,0);</span>
				<span style="font-size: 10pt; color: green;">//</span>
				<span style="font-size: 10pt; color: green;">平面上一个点<span><br /></span></span>
				<span style="font-size: 10pt; color: black;">vNormal=D3DXVECTOR3(0,1,0);</span>
				<span style="font-size: 10pt; color: green;">//</span>
				<span style="font-size: 10pt; color: green;">法向量<span><br /></span></span>
				<span style="font-size: 10pt; color: black;">D3DXPlaneFromPointNormal( &amp;clipplane, &amp;vPosition, &amp;vNormal );</span>
				<span style="font-size: 10pt; color: green;">//</span>
				<span style="font-size: 10pt; color: green;">生成剪裁平面<span><br /></span></span>
				<span style="font-size: 10pt; color: black;">
						<br />
m_pDevice()-&gt;SetClipPlane( 0, (</span>
				<span style="font-size: 10pt; color: blue;">float</span>
				<span style="font-size: 10pt; color: black;">*)clipplane); </span>
		</p>
		<p class="MsoNormal">
				<span> </span>
		</p>
		<p class="MsoNormal">
				<span>然而，在现在的可编程管道</span>
				<span>(programmable pipeline)</span>
				<span>下，设置的剪裁平面会被在剪裁坐标系下处理，而不是在世界坐标系下。</span>
		</p>
解决这个问题的方法有：<br /><br />
1）  给要剪裁的顶点做标记，在Pixel Shader中把它剪裁掉。<br /><br />
2）  使用近斜平面裁剪（Oblique Near-Plane Clipping），即修改投影矩阵，将要剪裁的顶点放在视截体之外，从而避免了该顶点的绘制。<br /><br />
3）  修改平面方程，使之从世界坐标系转换到剪裁坐标系。<span><br /><br /><br />
上述方法中，第一种和第二种效率并不高：在</span><span>Pixel Shader</span><span>中剪裁没有减少任何不必要的顶点处理，而计算近斜平面裁剪矩阵较为繁琐。所以，方法三是最佳选择。</span><p class="MsoNormal"><span> </span><span>要将一个平面从世界坐标系转换到剪裁坐标系，必须求出这个变换矩阵。</span></p><p class="MsoNormal"><span>设平面方程</span><span>ax+by+cz+d=0</span><span>，用一个</span><span>4</span><span>维向量来</span><span>n</span><span>表示</span><span>(a,b,c,d)</span><span>，设平面上有个点</span><span>p:(x,y,z,1)</span><span>。根据平面方程的定义，有：</span></p><p class="MsoNormal"><span><br /></span></p><p class="MsoNormal"><strong>n</strong><sup>T</sup><strong>p</strong> = ax + by + cz + d = 0</p><p class="MsoNormal"></p><p class="MsoNormal"><span>设矩阵</span><span>R</span><span>可以让点</span><span>P</span><span>从世界坐标系转换到剪裁坐标系，矩阵</span><span>Q</span><span>可以让平面</span><span>n</span><span>实现同样的变换。那么，有：</span></p><p class="MsoNormal" style="text-align: center;" align="center"></p><div align="left"><strong>p</strong>'= <strong>R</strong><strong>p</strong></div><div align="left"><strong>n'</strong>= <strong>Q</strong><strong>n</strong></div><p class="MsoNormal"><span>其中</span><span>p'</span><span>、</span><span>n'</span><span>分别是转换后的点与平面。</span></p><br /><div align="left"><strong>n</strong><span>'</span><sup>T</sup><strong>p'</strong>= 0</div><div align="left">(<strong>Q</strong><strong>n</strong>)<sup>T</sup> (<strong>R</strong><strong>p</strong>) = 0 <br /><strong>n</strong><sup>T</sup><strong>Q</strong><sup>T</sup><strong>R</strong><strong>p</strong> = 0<br /><br /><br /><span>如果：</span><strong>Q</strong><sup>T</sup><strong>R</strong> = <strong>I</strong></div><br /><p class="MsoNormal"><span>那么：</span></p><p class="MsoNormal"><strong>n</strong><sup>T</sup><strong>Q</strong><sup>T</sup><strong>R</strong><strong>p</strong> = <strong>n</strong><sup>T</sup><strong>I</strong><strong>p</strong> = <strong>n</strong><sup>T</sup><strong>p</strong> = 0</p><p class="MsoNormal"><span>于是：</span></p><div align="left"><strong>Q</strong><sup>T</sup> = <strong>R</strong><sup>-1</sup><strong><br />
Q</strong> = (<strong>R</strong><sup>-1</sup>)<sup>T</sup></div><br /><p class="MsoNormal"><span>在</span><span>DirectX 3D</span><span>中，将一个点从世界坐标系转换到剪裁坐标系，所用的矩阵为观察矩阵与投影矩阵的乘积，即：</span></p><p class="MsoNormal" style="background: none repeat scroll 0% 0% rgb(238, 238, 238); -moz-background-inline-policy: continuous;"><span style="font-size: 10pt; color: black;">D3DXMATRIX  TranMatrix = matView*matProj;</span></p><p class="MsoNormal"><span style="font-size: 9pt;">(TranMatrix</span><span style="font-size: 9pt;">为所求的变换矩阵，<span>matView</span>和<span>matProj</span>分别为</span><span>观察矩阵与投影矩阵</span><span>)</span></p><p class="MsoNormal"><span> </span></p><p class="MsoNormal"><span>附上在</span><span>D3D</span><span>中变换的完整代码：</span></p><p class="MsoNormal" style="background: none repeat scroll 0% 0% rgb(238, 238, 238); text-align: left; -moz-background-inline-policy: continuous;" align="left"><span style="font-size: 10pt; color: black;">D3DXPLANE tempPlane = clipplane;<br />
D3DXPlaneNormalize(&amp;tempPlane, &amp;tempPlane);<br /><br />
D3DXMATRIX  TranMatrix = matView*matProj;<br />
D3DXMatrixInverse(&amp;TranMatrix, NULL, &amp;TranMatrix);<br />
D3DXMatrixTranspose(&amp;TranMatrix, &amp;TranMatrix);<br />
D3DXPlaneTransform(&amp;tempPlane, &amp;tempPlane, &amp;TranMatrix);</span></p><p class="MsoNormal" style="background: none repeat scroll 0% 0% rgb(238, 238, 238); text-align: left; -moz-background-inline-policy: continuous;" align="left"></p><p class="MsoNormal"></p><p class="MsoNormal"><span>参考资料：</span></p><p class="MsoNormal"><span>1.Back Face Culling Notes ,Jordan Smith (University of California, Berkeley)<br /></span></p><p class="MsoNormal"><span>http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/backfacecull.shtml</span> </p><p class="MsoNormal">2.GameDev Forum</p><p class="MsoNormal">http://www.gamedev.net/community/forums/topic.asp?topic_id=402381</p><p class="MsoNormal">3.Oblique Near-Plane Clipping with Orthographic Camera ,Aras</p><p class="MsoNormal">http://aras-p.info/texts/obliqueortho.html</p><img src ="http://www.cppblog.com/billhsu/aggbug/106088.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2010-01-20 22:00 <a href="http://www.cppblog.com/billhsu/archive/2010/01/20/106088.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>矩阵求逆代码</title><link>http://www.cppblog.com/billhsu/archive/2009/12/11/103010.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Fri, 11 Dec 2009 14:23:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2009/12/11/103010.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/103010.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2009/12/11/103010.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/103010.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/103010.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 感觉线性代数作业里一直少不了矩阵求逆，<br><br>写个带输出算逆矩阵的步骤的矩阵求逆程序，希望给即将或正在学线代的同学一点方便。&nbsp;&nbsp;<a href='http://www.cppblog.com/billhsu/archive/2009/12/11/103010.html'>阅读全文</a><img src ="http://www.cppblog.com/billhsu/aggbug/103010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2009-12-11 22:23 <a href="http://www.cppblog.com/billhsu/archive/2009/12/11/103010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>发日志纪念~~第一次写导出插件</title><link>http://www.cppblog.com/billhsu/archive/2009/11/25/101921.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Wed, 25 Nov 2009 11:25:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2009/11/25/101921.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/101921.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2009/11/25/101921.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/101921.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/101921.html</trackback:ping><description><![CDATA[
		<div id="blog_text" class="cnt">
				<p>今天终于把模型导出插件最基本的功能--导出网格给写好了。</p>
				<p>c++和max sdk一起用的感觉很怪，系统崩溃了N次，不过，总算能导出网格了~</p>
				<p> </p>
				<p>有图有真相，截图纪念</p>
				<p>(注意：模型是从value的csol中弄出来的)</p>
				<p>
						<span>
								<img src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/o_2.JPG" small="0" class="blogimg" border="0" />
						</span>
				</p>
				<p>在d3d中渲染导出的模型­</p>
				<p>
						<span>
								<img src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/o_1.JPG" small="0" class="blogimg" border="0" />
						</span>
				</p>
				<p>在d3d中渲染导出的模型­</p>
				<p>
						<span>
								<img src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/o_3.JPG" small="0" class="blogimg" border="0" />
						</span>
						<br />
我的模型导出插件­</p>
				<p>
				</p>
				<p>导出数据样本：</p>
				<p>[这是一个带贴图的立方体的导出数据]</p>
				<p> </p>
				<p>8//　　8个顶点<br />
-6.70302 -21.2068 -5.46039<br />
17.1883 -6.46757  0.162097<br />
-22.4049 2.22378 -0.162097<br />
1.48644 16.963 5.46039<br />
-8.48039  -28.3257 20.7542<br />
15.411 -13.5865 26.3767<br />
-24.1823 -4.89514  26.0525<br />
-0.290929 9.84411 31.675</p>
				<p>12//　　12个纹理坐标<br />
0 1 0<br />
1 1 0<br />
0 0 0<br />
1 0 0<br />
0 1 0<br />
1 1 0<br />
0 0  0<br />
1 0 0<br />
0 1 0<br />
1 1 0<br />
0 0 0<br />
1 0 0</p>
				<p>12//　　12个面引索<br />
0 9 2 11 3 10<br />
3 10 1 8 0 9<br />
4 8 5 9 7 11<br />
7 11 6 10 4  8<br />
0 4 1 5 5 7<br />
5 7 4 6 0 4<br />
1 0 3 1 7 3<br />
7 3 5 2 1 0<br />
3 4 2 5 6  7<br />
6 7 7 6 3 4<br />
2 0 0 1 4 3<br />
4 3 6 2 2 0</p>
		</div>
<img src ="http://www.cppblog.com/billhsu/aggbug/101921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2009-11-25 19:25 <a href="http://www.cppblog.com/billhsu/archive/2009/11/25/101921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DirectX 3D 设备丢失(lost device)的处理</title><link>http://www.cppblog.com/billhsu/archive/2009/10/17/98823.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sat, 17 Oct 2009 05:10:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2009/10/17/98823.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/98823.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2009/10/17/98823.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/98823.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/98823.html</trackback:ping><description><![CDATA[
		<font color="#000000">
低手交流，高手勿入<br /><br />当初觉得DX中设备丢失很讨厌，差点就投奔OpenGL了。<br />
不过现在发现其实也没那么麻烦啦，写点东西，给不清楚</font>
		<font color="#000000">设备丢失怎么处理的同学参考下。<br /><br /></font>在创建时使用D3DPOOL_MANAGED标志的资源可以不需要重新载入，但D3DPOOL_DEFAULT加载的资源就需要先释放，后重建。<br /><br />通常需要这样处理的有ID3DXFont和ID3DXSprite，而.X模型什么的就不需要。<br />在发现设备丢失时，我们要调用 <span style="color: rgb(0, 0, 0);">OnLostDevice(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">)</span>函数让D3DPOOL_DEFAULT加载的资源释放掉。<br />好在ID3DXFont和ID3DXSprite有设备丢失处理函数，直接调用就好了<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> OnLostDevice(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">)<br />{<br /></span><span style="color: rgb(0, 0, 0);">    m_sprite</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">OnLostDevice();</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">    m_font</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">OnLostDevice();<br />}<br /></span></div><br />可是，怎么知道设备丢失了呢？<br />如果设备丢失，Present()函数就会“出问题”，返回值是D3DERR_DEVICELOST。<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);">m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">EndScene();<br /><br />HRESULT hr;<br />hr </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">Present(NULL, NULL, NULL, NULL);<br /></span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(hr </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> D3DERR_DEVICELOST)<br />{<br />    </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">TestCooperativeLevel() </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> D3DERR_DEVICENOTRESET)<br />    {<br />        OnLostDevice();<br />        OnResetDevice();<br />    }<br />}</span></div><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);">TestCooperativeLevel()</span><span style="color: rgb(0, 0, 0);"></span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> D3DERR_DEVICENOTRESET时，就可以恢复设备了。<br />于是，我们调用</span><span style="color: rgb(0, 0, 0);">OnLostDevice(</span><span style="color: rgb(0, 0, 0);">)</span>让D3DPOOL_DEFAULT加载的资源释放掉，之后，调用<span style="color: rgb(0, 0, 0);">OnResetDevice()来恢复设备就可以了。<br /><br />怎么恢复设备呢？<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> OnResetDevice(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">)<br />{<br />    </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(FAILED(m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">Reset(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">d3dpp)))<br />    {<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">;<br />    }<br /><br />    m_sprite</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">OnResetDevice();<br />    m_font</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">OnResetDevice();<br /><br />    InitDevice();<br />}</span></div>先让D3D设备reset，然后调用</span>ID3DXFont和ID3DXSprite的恢复函数，最后，需要把<span style="color: rgb(0, 0, 0);">D3D设备中的状态啊，矩阵变换啊这些重新设置下就完成了，也就是调用</span><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 0);">InitDevice()。<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> InitDevice()<br />{<br />m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">SetRenderState( D3DRS_ZENABLE, TRUE );<br /><br />m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">SetRenderState( D3DRS_AMBIENT, </span><span style="color: rgb(0, 0, 0);">0xffffffff</span><span style="color: rgb(0, 0, 0);"> );<br /><br />m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">SetSamplerState(</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);<br />m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">SetSamplerState(</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);<br />m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">SetSamplerState(</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">, D3DSAMP_MIPFILTER, D3DTEXF_POINT);<br /><br />D3DXMatrixPerspectiveFovLH( </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">matProj, D3DX_PI</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">1.0f</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">1.0f</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">1000.0f</span><span style="color: rgb(0, 0, 0);"> );<br />m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">SetTransform( D3DTS_PROJECTION, </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">matProj );<br /><br />vEyeVec</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">D3DXVECTOR3(</span><span style="color: rgb(0, 0, 0);">0.0f</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">0.0f</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1.0f</span><span style="color: rgb(0, 0, 0);">);<br />vLookatVec</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">D3DXVECTOR3(</span><span style="color: rgb(0, 0, 0);">0.0f</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">0.0f</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">0.0f</span><span style="color: rgb(0, 0, 0);">);<br />vUpVec</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">D3DXVECTOR3(</span><span style="color: rgb(0, 0, 0);">0.0f</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">1.0f</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">0.0f</span><span style="color: rgb(0, 0, 0);">);<br />D3DXMatrixLookAtLH( </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">matView, </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">vEyeVec, </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">vLookatVec, </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">vUpVec );<br />m_pIDirect3DDevice</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">SetTransform( D3DTS_VIEW, </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">matView );<br /><br />}</span></div><br /></span></span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br /></span><font color="#000000">啊，这样设备丢失就处理好了<br /><br />//<br /></font><font color="#ffffff">tag:DirectX 3D  d3d lost device TestCooperativeLevel OnLostDevice</font><font color="#ffffff"> 恢复设备 设备丢失 DeviceLost</font><font color="#000000"><br /></font><br /><img src ="http://www.cppblog.com/billhsu/aggbug/98823.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2009-10-17 13:10 <a href="http://www.cppblog.com/billhsu/archive/2009/10/17/98823.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己写的Rap3d 引擎 开源发布啦</title><link>http://www.cppblog.com/billhsu/archive/2009/07/25/91123.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sat, 25 Jul 2009 07:00:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2009/07/25/91123.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/91123.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2009/07/25/91123.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/91123.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/91123.html</trackback:ping><description><![CDATA[Rap3d是自己写的一个轻量级3D引擎，自己觉得比较好用。<br />我在sourceforge上申请了开源项目，在那里可以下载到Rap3d SDK.<br /><a target="_blank" href="http://rap3d.sf.net/">http://rap3d.sf.net/</a><br /><br />
Rap3d SDK 中有引擎的使用说明和几个例子，上手很快的。<br /><div align="center"><p class="style1" align="left">What Rap3d can do?</p><p class="style1" align="left">1.Display 3d models</p><p class="style1" align="left">2.Bill Board,Sprite,Animation..</p><p class="style1" align="left">3.Music playing</p><p class="style1" align="left">4.Draw text on screen</p><h2 align="left"><img src="http://rap3d.sourceforge.net/images/Rap3d.jpg" /></h2><p align="left"><span class="style1"><a class="style1" target="_blank" href="http://rap3d.sourceforge.net/">http://rap3d.sf.net/</a></span></p><p align="left"><br /></p></div><img src ="http://www.cppblog.com/billhsu/aggbug/91123.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2009-07-25 15:00 <a href="http://www.cppblog.com/billhsu/archive/2009/07/25/91123.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rap3d更新</title><link>http://www.cppblog.com/billhsu/archive/2009/06/23/88346.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Tue, 23 Jun 2009 02:12:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2009/06/23/88346.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/88346.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2009/06/23/88346.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/88346.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/88346.html</trackback:ping><description><![CDATA[
		<img src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/o_rap3d090623.JPG" width="314" height="235" />
		<br />增加了 TextureManager和 <br />BillBoard动画播放,方便渲染爆炸效果<br /><img src ="http://www.cppblog.com/billhsu/aggbug/88346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2009-06-23 10:12 <a href="http://www.cppblog.com/billhsu/archive/2009/06/23/88346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏中CPU使用率的控制</title><link>http://www.cppblog.com/billhsu/archive/2009/06/12/87472.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Fri, 12 Jun 2009 04:00:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2009/06/12/87472.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/87472.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2009/06/12/87472.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/87472.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/87472.html</trackback:ping><description><![CDATA[通常情况下，如果不处理下，再小的游戏也会让CPU使用率100%.<br />应该用Sleep(1)把多余的片段还给CPU,<br />像这样：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">)<br />{<br />DWORD start_time </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> GetTickCount();<br /></span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(PeekMessage(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">msg,NULL,</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,PM_REMOVE))<br />{<br /></span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (msg.message </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> WM_QUIT) </span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);">;<br />TranslateMessage(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">msg);<br />DispatchMessage(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">msg);<br />}</span><span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">update(</span><span style="color: rgb(0, 0, 255);">float</span><span style="color: rgb(0, 0, 0);">(GetTickCount() </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);"> start_time));<br /></span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">((GetTickCount() </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);"> start_time) </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">30</span><span style="color: rgb(0, 0, 0);">) Sleep(</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">);<br />}</span></div><br />update(float timeDelta)是游戏逻辑与画面更新的函数。<br />效果图：<br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/o_fps-ctrl.JPG" /><br /><img src ="http://www.cppblog.com/billhsu/aggbug/87472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2009-06-12 12:00 <a href="http://www.cppblog.com/billhsu/archive/2009/06/12/87472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>3D引擎计划</title><link>http://www.cppblog.com/billhsu/archive/2009/06/10/87356.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Wed, 10 Jun 2009 13:15:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2009/06/10/87356.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/87356.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2009/06/10/87356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/87356.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/87356.html</trackback:ping><description><![CDATA[暑假了，打算写一个3D游戏引擎。<br />
其实也就是把一些类封装一下，让开发更简结，以开源和实用为第一准则。<br /><br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/o_rap3d.JPG" height="392" width="491" /><br /><img src ="http://www.cppblog.com/billhsu/aggbug/87356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2009-06-10 21:15 <a href="http://www.cppblog.com/billhsu/archive/2009/06/10/87356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用GDI实现3D</title><link>http://www.cppblog.com/billhsu/archive/2008/12/27/70517.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sat, 27 Dec 2008 09:18:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2008/12/27/70517.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/70517.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2008/12/27/70517.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/70517.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/70517.html</trackback:ping><description><![CDATA[在CSDN上看到了一个很强大的程序：用GDI实现3D,可以变换视角的查看.x文件。<br /><br />不过想想看，好像实现起来也并不难。。。<br />和所有基础的3D程序一样，先把视椎变换为单位立方体，<br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/3_thumb.jpg" alt="3_thumb.jpg" border="0" width="334" height="113" /><br />变换矩阵为：<br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/5.jpg" alt="5.jpg" border="0" width="435" height="124" /><br /><br />当然，DirectX和OpenGL里都有现成的函数：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">OpenGL</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> gluPerspective(GLdouble fovy,<br />    GLdouble aspect,<br />    GLdouble zNear,<br />    GLdouble zFar);<br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">DirectX</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">D3DXMatrixPerspectiveFovLH( D3DXMATRIX </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">pOut,<br />    FLOAT fovY,<br />    FLOAT Aspect,<br />    FLOAT zn,<br />    FLOAT zf<br />); <br /></span></div><br />单位立方体中的点正交投影得到的(x,y,z)*视口变换矩阵 得到 (x',y',z')。<br />(x',y')对应屏幕点，z'为其深度，用于点的竞争。<br />把每个三角面匹配纹理用GDI基本函数画出来就可以了。<br /><br /><br />CSDN的那个程序<br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/rtwtsdgdg.JPG" alt="rtwtsdgdg.JPG" border="0" width="594" height="460" /><br /><br /><img src ="http://www.cppblog.com/billhsu/aggbug/70517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2008-12-27 17:18 <a href="http://www.cppblog.com/billhsu/archive/2008/12/27/70517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A* (A-star A星)寻路算法</title><link>http://www.cppblog.com/billhsu/archive/2008/11/01/65700.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sat, 01 Nov 2008 10:19:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2008/11/01/65700.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/65700.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2008/11/01/65700.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/65700.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/65700.html</trackback:ping><description><![CDATA[A*在游戏寻路算法里使用很广，可是感觉很多介绍它的文章故意让人看不懂。<br />仔细看了看gamedev.net的一片文章(<span class="title">A* Pathfinding for Beginners</span>
http://www.gamedev.net/reference/articles/article2003.asp    
          )，对A*更了解了一点，写点东西记录一下。<br />A*是一种启发式的算法，所谓的"启发式"，就是对每一个搜索的位置进行评估，也就是把找的位置离目标的距离当成找点的一个依据，然后猜测这个点是否最佳("启发式"就是猜测)。<br /><br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/image001.jpg" alt="image001.jpg" border="0" width="362" height="256" /><br /><br />为了找到最佳的那个点<br />可以规定：<br />G = 从起点，沿着产生的路径，移动到网格上指定方格的距离。<br />H = 从网格上那个方格移动到终点B的预估移动距离。<br /><br />F = G + H<br />F最小的点可以认为是该选的点。<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">引用</span><span style="color: rgb(0, 0, 0);">一下原文的翻译：<br />我们令水平或者垂直移动的耗费为10，对角线方向耗费为14。我们取这些值是因为沿对角线的距离是沿水平或垂直移动耗费的的根号2（别怕），或者约1.414倍。为了简化，我们用10和14近似。比例基本正确，同时我们避免了求根运算和小数。<br /><br /><br />既然我们在计算沿特定路径通往某个方格的G值，求值的方法就是取它父节点的G值，然后依照它相对父节点是对角线方向或者直角方向(非对角线)，分别增加14和10。例子中这个方法的需求会变得更多，因为我们从起点方格以外获取了不止一个方格。<br /><br />H值可以用不同的方法估算。我们这里使用的方法被称为曼哈顿方法，它计算从当前格到目的格之间水平和垂直的方格的数量总和，忽略对角线方向。然后把结果乘以10。这被成为曼哈顿方法是因为它看起来像计算城市中从一个地方到另外一个地方的街区数，在那里你不能沿对角线方向穿过街区。很重要的一点，我们忽略了一切障碍物。这是对剩余距离的一个估算，而非实际值，这也是这一方法被称为启发式的原因。想知道更多？你可以在这里找到方程和额外的注解。<br /><br /></span></div><br /><br /><span style="color: rgb(0, 0, 0);">第一步搜索的结果可以在下面的图表中看到。F,G和H的评分被写在每个方格里。正如在紧挨起始格右侧的方格所表示的，F被打印在左上角，G在左下角，H则在右下角。</span><br /><br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/image003.jpg" alt="image003.jpg" border="0" width="362" height="255" /><br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">引用</span><span style="color: rgb(0, 0, 0);">一下原文的翻译：</span><br /><span style="color: rgb(0, 0, 0);"><br />我们做如下操作开始搜索：<br />   </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">，从点A开始，并且把它作为待处理点存入一个“开启列表”。开启列表就像一张购物清单。尽管现在列表里只有一个元素，但以后就会多起来。你的路径可能会通过它包含的方格，也可能不会。基本上，这是一个待检查方格的列表。<br />   </span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">，寻找起点周围所有可到达或者可通过的方格，跳过有墙，水，或其他无法通过地形的方格。也把他们加入开启列表。为所有这些方格保存点A作为“父方格”。当我们想描述路径的时候，父方格的资料是十分重要的。后面会解释它的具体用途。<br />   </span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">，从开启列表中删除点A，把它加入到一个“关闭列表”，列表中保存所有不需要再次检查的方格。<br /><br />为了继续搜索，我们简单的从开启列表中选择F值最低的方格。然后，对选中的方格做如下处理：<br /><br />   </span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">，把它从开启列表中删除，然后添加到关闭列表中。<br />   </span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">，检查所有相邻格子。跳过那些已经在关闭列表中的或者不可通过的(有墙，水的地形，或者其他无法通过的地形)，把他们添加进开启列表，如果他们还不在里面的话。把选中的方格作为新的方格的父节点。<br />   </span><span style="color: rgb(0, 0, 0);">6</span><span style="color: rgb(0, 0, 0);">，如果某个相邻格已经在开启列表里了，检查现在的这条路径是否更好。换句话说，检查如果我们用新的路径到达它的话，G值是否会更低一些。如果不是，那就什么都不做。<br />      另一方面，如果新的G值更低，那就把相邻方格的父节点改为目前选中的方格（在上面的图表中，把箭头的方向改为指向这个方格）。最后，重新计算F和G的值。如果这看起来不够清晰，你可以看下面的图示。</span></div><br /><br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/image004.jpg" alt="image004.jpg" border="0" width="357" height="256" /><br /><br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/image005.jpg" alt="image005.jpg" border="0" width="357" height="254" /><br /><br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/image006.jpg" alt="image006.jpg" border="0" width="404" height="307" /><br /><br /><img src="http://www.cppblog.com/images/cppblog_com/billhsu/image007.jpg" alt="image007.jpg" border="0" width="411" height="308" /><br /><br />这样就可以找到最佳路径了。<br /><br /><br /><img src ="http://www.cppblog.com/billhsu/aggbug/65700.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2008-11-01 18:19 <a href="http://www.cppblog.com/billhsu/archive/2008/11/01/65700.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏框架</title><link>http://www.cppblog.com/billhsu/archive/2008/10/18/64311.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sat, 18 Oct 2008 09:46:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2008/10/18/64311.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/64311.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2008/10/18/64311.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/64311.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/64311.html</trackback:ping><description><![CDATA[如果不用框架，开始开发的速度可能有优势，但一旦代码过多，一切就乱大了。。。<br />可以把图形渲染，逻辑处理，网络联机等都做成差不多的模块，然后加到框架，这样好管理一点。<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> CFramework<br />{<br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br />CFramework();<br /></span><span style="color: rgb(0, 0, 0);">~</span><span style="color: rgb(0, 0, 0);">CFramework();<br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> init();<br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> update();<br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> Shutdown();<br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> add(Module </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">module);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">加入模块</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">};</span></div><span style="color: rgb(0, 0, 0);">Module </span><span style="color: rgb(0, 0, 0);">是一个纯虚函数类<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> Module<br />{<br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br /></span><span style="color: rgb(0, 0, 255);">virtual</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> init();<br /></span><span style="color: rgb(0, 0, 255);">virtual</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> update(</span><span style="color: rgb(0, 0, 255);">float</span><span style="color: rgb(0, 0, 0);"> dt);<br />};<br /><br /></span></div></span>图形渲染，逻辑处理，网络联机模块就可以运行了。<img src ="http://www.cppblog.com/billhsu/aggbug/64311.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2008-10-18 17:46 <a href="http://www.cppblog.com/billhsu/archive/2008/10/18/64311.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>栈对象和堆对象</title><link>http://www.cppblog.com/billhsu/archive/2008/10/10/63673.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Fri, 10 Oct 2008 09:36:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2008/10/10/63673.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/63673.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2008/10/10/63673.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/63673.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/63673.html</trackback:ping><description><![CDATA[在gameres上看见一个问题帖：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">什么时候该用 Object </span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);">;<br /><br />什么时候该用 Object </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);">;<br />             </span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Object();</span></div>感觉看起来没什么区别，其实不一样：前一个是栈对象，后一个是堆对象。<br /><br />引用一下别人对栈对象、堆对象的解释：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">　　栈对象的优势是在适当的时候自动生成，又在适当的时候自动销毁，不需要程序员操心；而且栈对象的创建速度一般较堆对象快，因为分配堆对象时，会调用 </span><span style="color: rgb(0, 0, 255);">operator</span><span style="color: rgb(0, 0, 0);"> new操作，</span><span style="color: rgb(0, 0, 255);">operator</span><span style="color: rgb(0, 0, 0);"> new会采用某种内存空间搜索算法，而该搜索过程可能是很费时间的，产生栈对象则没有这么麻烦，它仅仅需要移动栈顶指针就可以了。但是要注意的是，通常栈空间容量比较小，一般是1MB～2MB，所以体积比较大的对象不适合在栈中分配。特别要注意递归函数中最好不要使用栈对象，因为随着递归调用深度的增加，所需的栈空间也会线性增加，当所需栈空间不够时，便会导致栈溢出，这样就会产生运行时错误。<br /><br />　　堆对象，其产生时刻和销毁时刻都要程序员精确定义，也就是说，程序员对堆对象的生命具有完全的控制权。我们常常需要这样的对象，比如，我们需要创建一个对象，能够被多个函数所访问，但是又不想使其成为全局的，那么这个时候创建一个堆对象无疑是良好的选择，然后在各个函数之间传递这个堆对象的指针，便可以实现对该对象的共享。另外，相比于栈空间，堆的容量要大得多。实际上，当物理内存不够时，如果这时还需要生成新的堆对象，通常不会产生运行时错误，而是系统会使用虚拟内存来扩展实际的物理内存。</span></div><br />所以<br />当你知道你要使用的类型拥有准确数量时使用<span style="color: rgb(0, 0, 0);"> Object </span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);">;</span><br />当你不知道你要创建的类型有多少个时使用 <span style="color: rgb(0, 0, 0);">Object </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);">;<br />                                       </span><span style="color: rgb(0, 0, 255);">object</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Object();</span><br /><br /><img src ="http://www.cppblog.com/billhsu/aggbug/63673.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2008-10-10 17:36 <a href="http://www.cppblog.com/billhsu/archive/2008/10/10/63673.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>四元数入门</title><link>http://www.cppblog.com/billhsu/archive/2008/09/30/63099.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Tue, 30 Sep 2008 11:34:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2008/09/30/63099.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/63099.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2008/09/30/63099.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/63099.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/63099.html</trackback:ping><description><![CDATA[四元数常常可以在3D的书上看到。<br />但我的那本3D图形学书上，在没讲四元数是干什么的之前，就列了几张纸的公式，<br />大概因为自己还在上高中，不知道的太多，看了半天没看懂。。。<br />终于，在gameres上看到了某强人翻译的一个“4元数宝典 ”（原文是日本人写的。。。），感觉很好，分享下。<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">★旋转篇：<br />　我将说明使用了四元数（si yuan shu, quaternion）的旋转的操作步骤<br />（</span><span style="color: rgb(0, 0, 0);">１</span><span style="color: rgb(0, 0, 0);">）四元数的虚部，实部和写法<br />所谓四元数，就是把4个实数组合起来的东西。<br />4个元素中，一个是实部，其余3个是虚部。<br />比如，叫做Q的四元数，实部t而虚部是x,y,z构成，则像下面这样写。<br />Q </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (t; x, y, z) <br />又，使用向量 V</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">(x,y,z)，<br />Q </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (t; V)  <br />也可以这么写。<br /><br />正规地用虚数单位i,j,k的写法的话，<br />Q </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> t </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> xi </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> yj </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> zk <br />也这样写，不过，我不大使用<br /><br />（</span><span style="color: rgb(0, 0, 0);">２</span><span style="color: rgb(0, 0, 0);">）四元数之间的乘法<br />虚数单位之间的乘法 <br />ii </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">, ij </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">ji </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> k (其他的组合也是循环地以下同文) <br />有这么一种规则。（我总觉得，这就像是向量积（外积），对吧） <br />用这个规则一点点地计算很麻烦，所以请用像下面这样的公式计算。<br /><br />A </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (a; U) <br />B </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (b; V) <br />AB </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (ab </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);"> U·V; aV </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> bU </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> U×V)<br />不过，“U·V”是内积，「U×V」是外积的意思。<br />注意：一般AB</span><span style="color: rgb(0, 0, 0);">&lt;&gt;</span><span style="color: rgb(0, 0, 0);">BA所以乘法的左右要注意！<br /><br />（</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">）3次元的坐标的四元数表示<br />如要将某坐标(x,y,z)用四元数表示，<br />P </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; x, y, z) <br />则要这么写。<br /> <br />另外，即使实部是零以外的值，下文的结果也一样。用零的话省事所以我推荐。<br /><br />（</span><span style="color: rgb(0, 0, 0);">４</span><span style="color: rgb(0, 0, 0);">）旋转的四元数表示<br />以原点为旋转中心，旋转的轴是(α, β, γ)<br />（但 α</span><span style="color: rgb(0, 0, 0);">^</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> β</span><span style="color: rgb(0, 0, 0);">^</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> γ</span><span style="color: rgb(0, 0, 0);">^</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">）， <br />（右手系的坐标定义的话，望向向量(α, β, γ)的前进方向反时针地） <br />转θ角的旋转，用四元数表示就是，<br />Q </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (cos(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">); α sin(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">), β sin(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">), γ sin(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">)) <br />R </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (cos(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">); </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">α sin(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">), </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">β sin(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">), </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">γ sin(θ</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">)) <br />(另外R 叫 Q 的共轭四元数。） <br /><br />那么，如要实行旋转，<br /><b>则 <font color="#ff6600">R P Q<font color="#ffcc00"> </font></font></b></span><font color="#ffcc00"><b><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 0);">0</span></b></font><span style="color: rgb(0, 0, 0);"><b><font color="#ff6600">; 答案)</font> </b><br /><br />请像这样三明治式地计算。这个值的虚部就是旋转之后的点的坐标值。<br /> （另外，实部应该为零。请验算看看） </span></div><br />例子代码<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);"> Quaternion.cpp <br /></span><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);"> (C) Toru Nakata, toru-nakata@aist.go.jp <br /></span><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);"> 2004 Dec 29 </span><span style="color: rgb(128, 128, 128);"><br /></span><span style="color: rgb(0, 0, 0);">  <br />#include </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">math.h</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> <br />#include </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">iostream.h</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> <br />  <br /></span><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);"> Define Data type </span><span style="color: rgb(128, 128, 128);"><br /></span><span style="color: rgb(0, 0, 0);">typedef </span><span style="color: rgb(0, 0, 255);">struct</span><span style="color: rgb(0, 0, 0);"> <br />{ <br />              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> t; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> real-component </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> x; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> x-component </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> y; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> y-component </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> z; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> z-component </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">} quaternion; <br />  <br /><br /></span><b><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);">/ Bill 注：Kakezan </span></b><span style="color: rgb(128, 128, 128);"><font color="#669900"><b>在日语里是 “乘法”的意思</b></font><br /></span><span style="color: rgb(0, 0, 0);">quaternion Kakezan(quaternion left, quaternion right) <br />{ <br />              quaternion ans; <br />              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> d1, d2, d3, d4; <br />  <br />              d1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  left.t </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.t; <br />              d2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">left.x </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.x; <br />              d3 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">left.y </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.y; <br />              d4 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">left.z </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.z; <br />              ans.t </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> d1</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d2</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d3</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d4; <br />  <br />              d1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  left.t </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.x; <br />              d2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  right.t </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> left.x; <br />              d3 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  left.y </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.z; <br />              d4 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">left.z </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.y; <br />              ans.x </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  d1</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d2</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d3</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d4; <br />  <br />              d1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  left.t </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.y; <br />              d2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  right.t </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> left.y; <br />              d3 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  left.z </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.x; <br />              d4 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">left.x </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.z; <br />              ans.y </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  d1</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d2</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d3</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d4; <br />  <br />              d1 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  left.t </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.z; <br />              d2 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  right.t </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> left.z; <br />              d3 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  left.x </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.y; <br />              d4 </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">left.y </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> right.x; <br />              ans.z </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">  d1</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d2</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d3</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> d4; <br />              <br />              </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> ans; <br />} <br />  <br /></span><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);">/ Make Rotational quaternion </span><span style="color: rgb(128, 128, 128);"><br /></span><span style="color: rgb(0, 0, 0);">quaternion MakeRotationalQuaternion(</span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> radian, </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> AxisX, </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> AxisY, </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> AxisZ) <br />{ <br />              quaternion ans; <br />              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> norm; <br />              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> ccc, sss; <br />              <br />              ans.t </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> ans.x </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> ans.y </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> ans.z </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0.0</span><span style="color: rgb(0, 0, 0);">; <br />  <br />              norm </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> AxisX </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">  AxisX </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">  AxisY </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">  AxisY </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">  AxisZ </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">  AxisZ; <br />              </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(norm </span><span style="color: rgb(0, 0, 0);">&lt;=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0.0</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> ans; <br />  <br />              norm </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">1.0</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);"> sqrt(norm); <br />              AxisX </span><span style="color: rgb(0, 0, 0);">*=</span><span style="color: rgb(0, 0, 0);"> norm; <br />              AxisY </span><span style="color: rgb(0, 0, 0);">*=</span><span style="color: rgb(0, 0, 0);"> norm; <br />              AxisZ </span><span style="color: rgb(0, 0, 0);">*=</span><span style="color: rgb(0, 0, 0);"> norm; <br />  <br />              ccc </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> cos(</span><span style="color: rgb(0, 0, 0);">0.5</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> radian); <br />              sss </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sin(</span><span style="color: rgb(0, 0, 0);">0.5</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> radian); <br />  <br />              ans.t </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> ccc; <br />              ans.x </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sss </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> AxisX; <br />              ans.y </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sss </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> AxisY; <br />              ans.z </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sss </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> AxisZ; <br />  <br />              </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> ans; <br />} <br />  <br /></span><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);">/ Put XYZ into  quaternion </span><span style="color: rgb(128, 128, 128);"><br /></span><span style="color: rgb(0, 0, 0);">quaternion PutXYZToQuaternion(</span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> PosX, </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> PosY, </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> PosZ) <br />{ <br />              quaternion ans; <br />  <br />              ans.t </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0.0</span><span style="color: rgb(0, 0, 0);">; <br />              ans.x </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> PosX; <br />              ans.y </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> PosY; <br />              ans.z </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> PosZ; <br />  <br />              </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> ans; <br />} <br />  <br /></span><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);">// main </span><span style="color: rgb(128, 128, 128);"><br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> main() <br />{ <br />              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> px, py, pz; <br />              </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> ax, ay, az, th; <br />              quaternion ppp, qqq, rrr; <br />  <br />              cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Point Position (x, y, z) </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> endl; <br />              cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  x = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">; <br />              cin </span><span style="color: rgb(0, 0, 0);">&gt;&gt;</span><span style="color: rgb(0, 0, 0);"> px; <br />              cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  y = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">; <br />              cin </span><span style="color: rgb(0, 0, 0);">&gt;&gt;</span><span style="color: rgb(0, 0, 0);"> py; <br />              cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  z = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">; <br />              cin </span><span style="color: rgb(0, 0, 0);">&gt;&gt;</span><span style="color: rgb(0, 0, 0);"> pz; <br />              ppp </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> PutXYZToQuaternion(px, py, pz); <br />  <br />              </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">) { <br />                            cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\nRotation Degree ? (Enter 0 to Quit) </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> endl; <br />                            cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  angle = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">; <br />                            cin </span><span style="color: rgb(0, 0, 0);">&gt;&gt;</span><span style="color: rgb(0, 0, 0);"> th; <br />                            </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(th </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0.0</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);">; <br />  <br />                            cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Rotation Axis Direction ? (x, y, z) </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> endl; <br />                            cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  x = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">; <br />                            cin </span><span style="color: rgb(0, 0, 0);">&gt;&gt;</span><span style="color: rgb(0, 0, 0);"> ax; <br />                            cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  y = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">; <br />                            cin </span><span style="color: rgb(0, 0, 0);">&gt;&gt;</span><span style="color: rgb(0, 0, 0);"> ay; <br />                            cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">  z = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">; <br />                            cin </span><span style="color: rgb(0, 0, 0);">&gt;&gt;</span><span style="color: rgb(0, 0, 0);"> az; <br />  <br />  <br />                            th </span><span style="color: rgb(0, 0, 0);">*=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">3.1415926535897932384626433832795</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">180.0</span><span style="color: rgb(0, 0, 0);">; </span><span style="color: rgb(128, 128, 128);">///</span><span style="color: rgb(0, 128, 0);"> Degree -&gt; radian; </span><span style="color: rgb(128, 128, 128);"><br /></span><span style="color: rgb(0, 0, 0);">  <br />                            qqq </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> MakeRotationalQuaternion(th, ax, ay, az); <br />                            rrr </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> MakeRotationalQuaternion(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">th, ax, ay, az); <br />  <br />                            ppp </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Kakezan(rrr, ppp); <br />                            ppp </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Kakezan(ppp, qqq); <br />  <br />                            cout </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\nAnser X = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> ppp.x <br />                                          </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\n      Y = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> ppp.y <br />                                          </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\n      Z = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> ppp.z </span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);"> endl; <br />  <br />              } <br />  <br />              </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; <br />}  <br /></span></div>http://staff.aist.go.jp/toru-nakata/quaternion.html<br />http://bbs.gameres.com/showthread.asp?threadid=73511<br /><br /><img src ="http://www.cppblog.com/billhsu/aggbug/63099.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2008-09-30 19:34 <a href="http://www.cppblog.com/billhsu/archive/2008/09/30/63099.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>神经元网络的超级入门</title><link>http://www.cppblog.com/billhsu/archive/2008/08/30/60455.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Sat, 30 Aug 2008 12:08:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2008/08/30/60455.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/60455.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2008/08/30/60455.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/60455.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/60455.html</trackback:ping><description><![CDATA[一直不太懂神经元网络，看了这篇文章(来自IBM developerWorks 中国)后终于感觉有点明白了，特意拿出来大家一起看。<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">2001</span><span style="color: #000000;">&nbsp;年&nbsp;</span><span style="color: #000000;">6</span><span style="color: #000000;">&nbsp;月&nbsp;</span><span style="color: #000000;">01</span><span style="color: #000000;">&nbsp;日<br><br>&nbsp;&nbsp;&nbsp;&nbsp;神经网络也许是计算机计算的将来，一个了解它的好方法是用一个它可以解决的难题来说明。假设给出&nbsp;</span><span style="color: #000000;">500</span><span style="color: #000000;">&nbsp;个字符的代码段，您知道它们是&nbsp;C、C</span><span style="color: #000000;">++</span><span style="color: #000000;">、Java&nbsp;或者&nbsp;Python。现在构造一个程序，来识别编写这段代码的语言。一种解决方案是构造一个能够学习识别这些语言的神经网络。这篇文章讨论了神经网络的基本功能以及构造神经网络的方法，这样就可以在编码时应用它们了。</span></div>
<br>Bill注：解释一下，这文章是用) ( _ . = ; " , ' * / { } : - 0 + 1 [ ] 这20个特殊符号出现频率+人工神经元的判断来识别<span style="color: #000000;">代码段</span><span style="color: #000000;">是&nbsp;C、C</span><span style="color: #000000;">++</span><span style="color: #000000;">、Java&nbsp;或者&nbsp;Python<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"></span><br>
<p>根据一个简化的统计，人脑由百亿条神经组成 ―
每条神经平均连结到其它几千条神经。通过这种连结方式，神经可以收发不同数量的能量。神经的一个非常重要的功能是它们对能量的接受并不是立即作出响应，而
是将它们累加起来，当这个累加的总和达到某个临界阈值时，它们将它们自己的那部分能量发送给其它的神经。大脑通过调节这些连结的数目和强度进行学习。尽管
这是个生物行为的简化描述。但同样可以充分有力地被看作是神经网络的模型。</p>
<p><a name="1"><span class="atitle">阈值逻辑单元（Threshold Logic
Unit，TLU）</span></a></p>
<p>
理解神经网络的第一步是从对抽象生物神经开始，并把重点放在
<em>阈值逻辑单元（TLU）</em>这一特征上。一个
TLU
是一个对象，它可以输入一组加权系数的量，对它们进行求和，如果这个和达到或者超过了某个阈值，输出一个量。
让我们用符号标注这些功能，首先，有输入值以及它们的权系数：X
<sub>1</sub>,
X
<sub>2</sub>, ..., X
<sub>n</sub>和 W
<sub>1</sub>, W
<sub>2,</sub>
..., W
<sub>n</sub>。接着是求和计算出的 X
<sub>i</sub>*W
<sub>i</sub>
，产生了激发层 a，换一种方法表示：
</p>
<p>a = (X1 * W1)+(X2 * W2)+...+(Xi * Wi)+...+ (Xn * Wn)</p>
<p>阈值称为 theta。最后，输出结果 y。当 a &gt;=theta 时 y=1，反之
y=0。请注意输出可以是连续的，因为它也可以由一个 squash 函数 s（或
sigma）判定，该函数的自变量是 a，函数值在 0 和 1 之间，y=s(a)。</p>
<br><a name="N10080"><strong>图 1. 阈值逻辑单元，带有 sigma 函数（顶部）和 cutoff
函数（底部）
</strong></a><br>
<img src="http://www.ibm.com/developerworks/cn/linux/other/l-neural/mp.gif" alt="阈值逻辑单元" width="300" height="275">
<br>
<p>TLU 会分类，假设一个 TLU 有两个输入值，它们的权系数等于 1，theta
值等于 1.5。当这个 TLU 输入 &lt;0,0&gt;、&lt;0,1&gt;、&lt;1,0&gt;
和 &lt;1,1&gt; 时，它的输出分别为 0、0、0、1。TLU
将这些输入分为两组：0 组和 1 组。就像懂得逻辑连接（布尔运算
AND）的人脑可以类似地将逻辑连接的句子分类那样，TLU
也懂得一点逻辑连接之类的东西。</p>
<p>TLU
能够用几何学上的解释来阐明这种现象。它的四种可能输入对应于笛卡尔图的四个点。从等式
X
<sub>1</sub>*W
<sub>1</sub>+ X
<sub>2</sub>*W
<sub>2</sub> =
theta，换句话说，也即 TLU
转换其分类行为的点开始，它的点都分布在曲线 X
<sub>2</sub> =
-X
<sub>1</sub> + 1.5 上。这个方程的曲线将 4
个可能的输入分成了两个对应于 TLU 分类的区域。这是 TLU
原理中更为普通的实例。在 TLU 有任意数目的 N
个输入的情况下，一组可能的输入对应于 N
维空间中的一个点集。如果这些点可以被超平面 ―
换句话说，对应于上面示例中的线的 N
维的几何外形切割，那么就有一组权系数和一个阈值来定义其分类刚好与这个切割相匹配的
TLU。
</p>
</div>
</span>Bill注：<span style="color: #000000;">所谓的</span><span style="color: #000000;">N维空间就是N个输入节点<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"> </span><br>
<p><a name="2"><span class="atitle">TLU
的学习原理</span></a></p>
<p>
既然 TLU
懂得分类，它们就知道素材。神经网络也可假定为可以学习。它们的学习机制是模仿大脑调节神经连结的原理。TLU
通过改变它的权系数和阈值来学习。实际上，从数学的观点看，权系数阈值的特征有点武断。让我们回想一下当
SUM(Xi * Wi) &gt;= theta 时 TLU 在临界点时输出的是 1 而不是
0，这相当于说临界点是出现在 SUM(X
<sub>i</sub>* W
<sub>i</sub>)+ (-1
* theta) &gt;= 0 的时候。所以，我们可以把 -1
看成一个常量输入，它的权系数 theta
在学习（或者用技术术语，称为
<em>培训</em>）的过程中进行调整。这样，当
SUM(X
<sub>i</sub>* W
<sub>i</sub>)+ (-1 * theta) &gt;= 0
时，y=1，反之 y=0。
</p>
<p>在培训过程中，神经网络输入：</p>
<ol>
    <li>一系列需要分类的术语示例</li>
    <li>它们的正确分类或者目标</li>
</ol>
<p>这样的输入可以看成一个向量：&lt;X
<sub>1</sub>, X
<sub>2</sub>,
..., X
<sub>n</sub>, theta, t&gt;，这里 t
是一个目标或者正确分类。神经网络用这些来调整权系数，其目的使培训中的目标与其分类相匹配。更确切地说，这是有指导的培训，与之相反的是无指导的培训。前者是基于带目标的示例，而后者却只是建立在统计分析的基础上。权系数的调整有一个学习规则，一个理想化的学习算法如下所示：
</p>
<br><a name="listing1"><strong>清单 1.
理想化的学习算法</strong></a><br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">fully_trained = FALSE<br>DO UNTIL (fully_trained):<br>    fully_trained = TRUE<br>    FOR EACH training_vector = &lt;X1, X2, ..., Xn, theta, target&gt;::<br>                               # Weights compared to theta<br>        a = (X1 * W1)+(X2 * W2)+...+(Xn * Wn) - theta<br>        y = sigma(a)<br>        IF y != target:<br>            fully_trained = FALSE<br>        FOR EACH Wi:<br>        MODIFY_WEIGHT(Wi)      # According to the training rule<br>    IF (fully_trained):<br>        BREAK<br></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>
您或许想知道，&#8220;哪些培训规则？&#8221;有很多，不过有一条似乎合理的规则是基于这样一种思想，即权系数和阈值的调整应该由分式
(t - y) 确定。这个规则通过引入 alpha (0 &lt; alpha &lt; 1)
完成。我们把 alpha 称为
<em>学习率</em>。W
<sub>i</sub> 中的更改值等于
(alpha * (t - y)* Xi)。当 alpha 趋向于 0
时，神经网络的权系数的调整变得保守一点；当 alpha 趋向于 1
时，权系数的调整变得激进。一个使用这个规则的神经网络称为
<em>感知器</em>，并且这个规则被称为
<em>
感知器学习规则</em>。Rosenblatt 于 1962 年下的结论是，如果 N
维空间的点集被超平面切割，那么感知器的培训算法的应用将会最终导致权系数的分配，从而定义了一个
TLU，它的超平面会进行需要的分割。当然，为了记起
Keynes，最终我们都切断了与外界的联系，专心思考。但是在计算时间之外，我们仍濒临危险，因为我们需要自己的神经网络对可能输入的空间进行不止一次的切割。
</p>
<p>文章开始的难题举例说明了这个，假设给您 N
个字符的代码段，您知道是 C、C++、Java 或者
Python。难的是构造一个程序来标识编写这段代码的语言。用 TLU
来实现需要对可能的输入空间进行不止一次的分割。它需要把空间分成四个区域。每种语言一个区域。把神经网络培训成能实现两个切割就可完成这种工作。第一个切割将
C/C++ 和 Java/Python 分开来，另一个将 C/Java 和 C++/Python
分开。一个能够完成这些切割的网络同样可以识别源代码样本中的语言。但是这需要网络有不同结构，在描述这个不同之处之前，先来简单地看一下实践方面的考虑。</p>
<p>
<strong>图 2. 初步的（不完整的）感知器学习模型</strong>
<br>
<a href="http://www.ibm.com/developerworks/cn/linux/other/l-neural/lr.gif">
<img src="http://www.ibm.com/developerworks/cn/linux/other/l-neural/lr.gif" alt="感知器学习模型" name="Graphic2" border="0" width="430" height="300">
</a>
</p>
<p>考虑到排除取得 N 个字符代码所需的计算时间，统计从 ASCII 码的 32
到 127 的范围内可视 ASCII
码字符出现的频率，并在这个统计以及关于代码语言的目标信息的基础上培训神经网络。我们的方法是将字符统计限制到
C、C++、Java 和 Python 代码字符库中最常用的 20
个非字母数字字符。由于关注浮点运算的执行，我们打算用一种规格化因素将这
20
字符统计分开来，并以此培训我们的网络。显然，一个结构上的不同是我们的网络有
20
个输入节点，但这是很正常的，因为我们的描述已经暗示了这种可能性。一个更有意思的区别是出现了一对中间节点，N1
和 N2，以及输出节点数量从两个变成了四个（O1 到 O4）。</p>
<p>我们将培训 N1，这样当它一看到 C 或 C++，设置 y1=1，看到 Java 或
Python，它将设置 y1=0。同理培训 N2，当它一看到 C 或 Java，设置
y2=1，看到 C++ 或 Python，设置 y2=0。此外，N1 和 N2 将输出 1 或 0
给 Oi。现在如果 N1 看到 C 或 C++，而且 N2 看到 C 或者
Java，那么难题中的代码是 C。而如果 N1 看到 C 或 C++，N2 看到 C++ 或
Python，那么代码就是 C++。这个模式很显而易见。所以假设 Oi
已被培训并根据下面表格的情况输出 1 或 0。</p>
<p><a name="listing2"><span class="smalltitle">映射到输出（作为布尔函数）的中间节点</span></a></p>
<p>
</p>
<table border="1" cellpadding="4" cellspacing="0">
    <tbody>
        <tr valign="top">
            <td bgcolor="#cccccc" width="17%">
            N1
            </td>
            <td bgcolor="#cccccc" width="17%">
            N2
            </td>
            <td bgcolor="#cccccc" width="17%">
            O1 (C)
            </td>
            <td bgcolor="#cccccc" width="17%">
            O2 (C++)
            </td>
            <td bgcolor="#cccccc" width="17%">
            O3 (Java)
            </td>
            <td bgcolor="#cccccc" width="17%">
            O4 (Python)
            </td>
        </tr>
        <tr valign="bottom">
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
        </tr>
        <tr valign="bottom">
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
        </tr>
        <tr valign="bottom">
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
        </tr>
        <tr valign="bottom">
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
            <td bgcolor="#cccccc" width="17%">
            1
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
            <td bgcolor="#cccccc" width="17%">
            0
            </td>
        </tr>
    </tbody>
</table>
<p>
如果这样可行的话，我们的网络就可以从代码示例中识别出语言了。这个想法很好。但是在实践上却有些难以置信。不过这种解决方案预示了
C/C++ 和 Java/Python 输入被一个超平面切割了，同样 C/Java 和
C++/Python
输入被另一个切割。这是一个网络培训的解决方案，迂回地解决了这个输入空间的设想。</p>
</div>
</span>Bill注：看起来很强大<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"> <br></span>
<p><a name="3"><span class="atitle">关于 delta
规则</span></a></p>
<p>
另一种培训的规则叫做 delta 规则。感知器培训规则是基于这样一种思路
― 权系数的调整是由目标和输出的差分方程表达式决定。而
<em>delta</em>
规则是基于梯度降落这样一种思路。这个复杂的数学概念可以举个简单的例子来表示。从给定的几点来看，向南的那条路径比向东那条更陡些。向东就像从悬崖上掉
下来，但是向南就是沿着一个略微倾斜的斜坡下来，向西像登一座陡峭的山，而北边则到了平地，只要慢慢的闲逛就可以了。所以您要寻找的是到达平地的所有路径
中将陡峭的总和减少到最小的路径。在权系数的调整中，神经网络将会找到一种将误差减少到最小的权系数的分配方式。 </p>
<p>
将我们的网络限制为没有隐藏节点，但是可能会有不止一个的输出节点，设
p 是一组培训中的一个元素，t(p,n) 是相应的输出节点 n
的目标。但是，设 y(p,n) 由以上提到的 squash 函数 s 决定，这里
a(p,n) 是与 p 相关的 n 的激活函数，或者用 (p,n) = s( a(p,n) )
表示为与 p 相关的节点 n 的 squash
过的激活函数。为网络设定权系数（每个 Wi），也为每个 p 和 n 建立
t(p,n) 与 y(p,n) 的差分，这就意味着为每个 p
设定了网络全部的误差。因此对于每组权系数来说有一个平均误差。但是
delta
规则取决于求平均值方法的精确度以及误差。我们先不讨论细节问题，只是说一些与某些
p 和 n 相关的误差：?* square( t(p,n) - y(p,n) )。现在，对于每个
Wi，平均误差定义如下：
</p>
<br><a name="listing3"><strong>清单 2.
查找平均误差</strong></a><br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">sum = 0<br>FOR p = 1 TO M:         # M is number of training vectors<br>    FOR n = 1 TO N:     # N is number of output nodes<br>        sum = sum + (1/2 * (t(p,n)-y(p,n))^2)<br>average = 1/M * sum<br></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>delta
规则就是依据这个误差的定义来定义的。因为误差是依据那些培训向量来说明的，delta
规则是一种获取一个特殊的权系数集以及一个特殊的向量的算法。而改变权系数将会使神经网络的误差最小化。我们不需要讨论支持这个算法的微积分学，只要认为任何
Wi 发生的变化都是如下所示就够了：</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">alpha * s'(a(p,n)) * (t(p,n) - y(p,n)) * X(p,i,n).<br></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>X(p,i,n) 是输入到节点 n 的 p 中的第 i 个元素，alpha
是已知的学习率。最后 s'( a(p,n) ) 是与 p 相关的第 n 个节点激活的
squashing 函数的变化（派生）率，这就是 delta 规则，并且 Widrow 和
Stearns 向我们展示了当
alpha
非常小的时候，权系数向量接近某个将误差最小化的向量。用于权系数调节的基于
delta 规则的算法就是如此。
</p>
<br><a name="listing4"><strong>梯度降落（直到误差小到适当的程度为止）</strong></a><br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">step 1: for each training vector, p, find a(p)<br>step 2: for each i, change Wi by:<br>            alpha * s'(a(p,n)) * (t(p,n)-y(p,n)) * X(p,i,n)<br></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>
这里有一些与感知器算法相区别的重要不同点。显然，在权系数调整的公式下有着完全不同的分析。delta
规则算法总是在权系数上调整，而且这是建立在相对输出的激活方式上。最后，这不一定适用于存在隐藏节点的网络。</p>
<p>
<em>反向传播</em>这一算法把支持 delta
规则的分析扩展到了带有隐藏节点的神经网络。为了理解这个问题，设想
Bob 给 Alice 讲了一个故事，然后 Alice 又讲给了 Ted，Ted
检查了这个事实真相，发现这个故事是错误的。现在 Ted
需要找出哪些错误是 Bob 造成的而哪些又归咎于
Alice。当输出节点从隐藏节点获得输入，网络发现出现了误差，权系数的调整需要一个算法来找出整个误差是由多少不同的节点造成的，网络需要问，&#8220;是谁让我误入歧途？到怎样的程度？如何弥补？&#8221;这时，网络该怎么做呢？
</p>
<br><a name="N10215"><strong>图 3：&#8220;代码识别&#8221;反向传播的神经网络
</strong></a><br>
<img src="http://www.ibm.com/developerworks/cn/linux/other/l-neural/code_recognizer.gif" alt="" width="464" height="437">
<br>
<p>
反向传播算法同样来源于梯度降落原理，在权系数调整分析中的唯一不同是涉及到
t(p,n) 与 y(p,n) 的差分。通常来说 W
<sub>i</sub>的改变在于：
</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">alpha * s'(a(p,n)) * d(n) * X(p,i,n)</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>其中 d(n) 是隐藏节点 n 的函数，让我们来看（1）n
对任何给出的输出节点有多大影响；（2）输出节点本身对网络整体的误差有多少影响。一方面，n
影响一个输出节点越多，n
造成网络整体的误差也越多。另一方面，如果输出节点影响网络整体的误差越少，n
对输出节点的影响也相应减少。这里 d(j)
是对网络的整体误差的基值，W(n,j) 是 n 对 j 造成的影响，d(j) *
W(n,j) 是这两种影响的总和。但是 n
几乎总是影响多个输出节点，也许会影响每一个输出结点，这样，d(n)
可以表示为：</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">SUM(d(j)*W(n,j))</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>这里 j 是一个从 n
获得输入的输出节点，联系起来，我们就得到了一个培训规则，第 1
部分：在隐藏节点 n 和输出节点 j 之间权系数改变，如下所示：</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">alpha * s'(a(p,n))*(t(p,n) - y(p,n)) * X(p,n,j)</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>第 2 部分：在输入节点 i 和输出节点 n
之间权系数改变，如下所示：</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">alpha * s'(a(p,n)) * sum(d(j) * W(n,j)) * X(p,i,n)</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>这里每个从 n 接收输入的输出节点 j
都不同。关于反向传播算法的基本情况大致如此。</p>
<p>将 Wi 初始化为小的随机值。</p>
<p><a name="listing5"><span class="smalltitle">使误差小到适当的程度要遵循的步骤</span></a></p>
<p>
</p>
<table border="1" cellpadding="5" cellspacing="0" width="60%">
    <tbody>
        <tr>
            <td>第 1
            步：输入培训向量。
            <br>
            第 2 步：隐藏节点计算它们的输出
            <br>
            第 3 步：输出节点在第 2 步的基础上计算它们的输出。
            <br>
            第 4 步：计算第 3 步所得的结果和期望值之间的差。
            <br>
            第 5 步：把第 4 步的结果填入培训规则的第 1 部分。
            <br>
            第 6 步：对于每个隐藏节点 n，计算 d(n)。
            <br>
            第 7 步：把第 6 步的结果填入培训规则的第 2 部分。
            </td>
        </tr>
    </tbody>
</table>
<p>通常把第 1 步到第 3 步称为
<em>正向传播</em>，把第 4 步到第 7
步称为
<em>反向传播</em>。反向传播的名字由此而来。 <br></p>
<p>
在掌握了反向传播算法后，可以来看我们的识别源代码样本语言的难题。为了解决这个问题，我们提供了
Neil Schemenauer 的 Python 模型
<em>bpnn</em>。用它的模型解决问题真是难以置信的简单，在我们的类
<code>
<em>NN2</em>
</code> 里定制了一个类
<code>
<em>NN</em>
</code> ，不过我们的改变只是调整了表达方式和整个过程的输出，并没有涉及到算法。基本的代码如下所示：
</p>
<br><a name="listing6"><strong>清单 3：用 bpnn.py
建立一个神经网络</strong></a><br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">                # Create the network (number of input, hidden, and training nodes)<br>net = NN2(INPUTS, HIDDEN, OUTPUTS) <br>        # create the training and testing data<br>trainpat = []  <br>testpat = []  <br>for n in xrange(TRAINSIZE+TESTSIZE):  <br>    <br>        #... add vectors to each set<br># train it with some patterns <br>net.train(trainpat, iterations=ITERATIONS, N=LEARNRATE, M=MOMENTUM)  <br>        # test it <br>net.test(testpat)  <br>        # report trained weights <br>net.weights()<br>			<br>      </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>当然我们需要输入数据，实用程序 code2data.py
提供了这个功能。它的界面很直观：只要将一堆扩展名各不相同的文件放到一个子目录
./code
中，然后运行这个实用程序，并列举那些扩展名作为命令选项。例如：</p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">python code2data.py py c java</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>您得到的是一堆 STDOUT
上的向量，可以把这些向量输入到另一个进程或者重定向到一个文件，它的输出如下所示：</p>
<br><a name="listing7"><strong>清单 4：Code2Data
的输出向量</strong></a><br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">0.15 0.01 0.01 0.04 0.07 0.00 0.00 0.03 0.01 0.00 0.00 0.00 0.05 0.00 &gt; 1 0 0<br>0.14 0.00 0.00 0.05 0.13 0.00 0.00 0.00 0.02 0.00 0.00 0.00 0.13 0.00 &gt; 1 0 0<br>[...]</pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>
让我们回忆一下输入值都是不同特殊字符出现的规格化数目，目标值（在大于号以后）是
YES/NO，它代表包含这些字符的源代码文件的类型，不过对于什么是什么来说，并没有非常明显的东西。数字可以是输入或期望的
<em>
任意值</em>，这才是最重要的。
</p>
<p>下一步是运行实际的 code_recognizer.py 程序。这需要（在
STDIN
中）像上面一样的向量集。这个程序有一个包，它能够根据实际文件推断出需要多少输入节点（计算在内的和期望的），选择隐藏节点的数目是一个诀窍。对于源代码的识别，6
到 8
个隐藏节点似乎工作得很好。如果打算试验网络从而发现对于这些不同的选项它是如何做的，您可以覆盖命令行中的所有参数，但每一次运行还是会耗费一些时间。值得注意的是，
code_recognizer.py 将它的（大的）测试结果文件发送到
STDOUT，而将一些友好的消息放在 STDERR
里。这样在大部分时间里，为了安全保管，您将会把 STDOUT
定向到一个文件，并监视针对进程和结果概要的 STDERR。</p>
<br><a name="listing8"><strong>清单 5：运行
code_recognizer.py</strong></a><br>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&gt; code2data.py py c java | code_recognizer.py &gt; test_results.txt <br>Total bytes of py-source: 457729 <br>Total bytes of c-source: 245197 <br>Total bytes of java-source: 709858 <br>Input set: ) ( _ . = ; " , ' * / { } : - 0 + 1 [ ] <br>HIDDEN = 8 <br>LEARNRATE = 0.5 <br>ITERATIONS = 1000 <br>TRAINSIZE = 500 <br>OUTPUTS = 3 <br>MOMENTUM = 0.1 <br>ERROR_CUTOFF = 0.01 <br>TESTSIZE = 500 <br>INPUTS = 20 <br>error -&gt; 95.519... 23.696... 19.727... 14.012... 11.058... 9.652...  <br>8.858... 8.236... 7.637... 7.065... 6.398... 5.413... 4.508...  <br>3.860... 3.523... 3.258... 3.026... 2.818... 2.631... 2.463...  <br>2.313... 2.180... 2.065... 1.965... 1.877... 1.798... 1.725...  <br>[...] <br>0.113... 0.110... 0.108... 0.106... 0.104... 0.102... 0.100...  <br>0.098... 0.096... 0.094... 0.093... 0.091... 0.089... 0.088...  <br>0.086... 0.085... 0.084... <br>Success rate against test data: 92.60% <br></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>
不断减少误差是个很好的兆头，这至少在一段长时间里所获得的一种进步，且最后的结果必然是深入人心的。就我们的观点而言，网络完成了一项值得尊敬的工作，来识别代码
― 我们将会乐意倾听，对于您的数字向量它是如何做的。
</p>
</div>
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><br>
<p><a name="resources"><span class="atitle">参考资料 </span></a></p>
<ul>
    <li>您可以参阅本文在 developerWorks 全球站点上的
    <a href="http://www.ibm.com/developerworks/library/l-neural/index.html?S_TACT=105AGX52&amp;S_CMP=cn-a-l">英文原文</a>.
    <br><br></li>
    <li>我们的
    <a href="http://gnosis.cx/download/neural_net_1.zip">代码识别</a>程序是基于
    Neil Schemenauer 的反向传播模块。
    <br><br></li>
    <li>
    关于有指导培训和无指导培训的差异，以及神经网络的一般介绍，请参阅由
    D. Michie、D.J. Spiegelhalter 以及 C.C. Taylor 编辑的
    <a href="http://www.amsta.leeds.ac.uk/%7Echarles/statlog">Machine
    Learning, Neural and Statistical
    Classification</a>，具体内容请参阅
    <a href="http://www.amsta.leeds.ac.uk/%7Echarles/statlog/chap6.ps.gz">第
    6 章</a>。
    <br><br></li>
    <li>关于 Rosenblatt 的感知器结果，请参阅他的
    <em>Principles of
    Neurodynamics</em>, 1962, New York: Spartan Books。
    <br><br></li>
    <li>关于一些 delta 规则的详细信息，请参阅 Kevin Gurney 的著作
    <em>An
    Introduction to Neural Networks</em> 1997, London:
    Routledge。也可以参阅
    <a href="http://www.shef.ac.uk/psychology/gurney/notes/contents.html">Neural
    Nets</a>早期的在线版本。
    <br><br></li>
    <li>关于 delta 规则的证明，请参阅 B. Widrow 和 S.D. Stearns 的
    <em>Adaptive Signal Processing</em>, 1985, New Jersey:
    Prentice-Hall。
    <br><br></li>
    <li>关于包含图形界面的感知器的执行，请参阅 Omri Weisman 和 Ziv
    Pollack 撰写的
    <a href="http://www.cs.bgu.ac.il/%7Eomri/Perceptron/">The Perceptron</a>
    。
    <br><br></li>
    <li>什么是没有 FAQ 的科目？请参阅在任何时候都适用的
    <a href="ftp://ftp.sas.com/pub/neural/FAQ.html">Neural Net
    FAQ</a>。
    <br><br></li>
    <li>关于广泛的链接集合，请参阅
    <a href="http://www.dontveter.com/bpr/bpr.html">The Backpropagator's
    Review</a>。
    <br><br></li>
    <li>请参阅
    <a href="http://www.geocities.com/CapeCanaveral/1624/">Neural Networks
    at your Fingertips</a>，它讨论了一组 C 程序包，这些包说明了 Adaline
    网络、反向传播、Hopfield 模型以及其它，有一个
    <a href="http://www.geocities.com/CapeCanaveral/1624/bpn.html">The
    Back-propagation Network</a> 特别有趣，它是一个 C
    程序包，说明了一个分析日斑数据的网络。
    <br><br></li>
    <li>在
    <a href="http://www.dontveter.com/nnsoft/nnsoft.html">Neural
    Networking Software</a>，您将会找到有友好的图形界面的同时支持 DOS
    和 Linux 的神经网络代码。
    <br><br></li>
    <li>
    <a href="http://www.disi.unige.it/person/ValentiniG/NEURObjects">NEURObjects</a>
    提供了开发神经网络的 C++ 的库文件，它的优点在于面向对象。
    <br><br></li>
    <li>
    <a href="http://www-ra.informatik.uni-tuebingen.de/SNNS/">Stuttgart
    Neural Network Simulator</a>（SNNS），正如名字所示，是用有 GUI 的 C
    程序编写的，它的手册内容极为丰富，同时支持友好的 Linux 平台。
    <br></li>
</ul>
</div>
<br><br> <img src ="http://www.cppblog.com/billhsu/aggbug/60455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2008-08-30 20:08 <a href="http://www.cppblog.com/billhsu/archive/2008/08/30/60455.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开始写脚本引擎了</title><link>http://www.cppblog.com/billhsu/archive/2008/07/28/57340.html</link><dc:creator>Bill Hsu</dc:creator><author>Bill Hsu</author><pubDate>Mon, 28 Jul 2008 04:36:00 GMT</pubDate><guid>http://www.cppblog.com/billhsu/archive/2008/07/28/57340.html</guid><wfw:comment>http://www.cppblog.com/billhsu/comments/57340.html</wfw:comment><comments>http://www.cppblog.com/billhsu/archive/2008/07/28/57340.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/billhsu/comments/commentRss/57340.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/billhsu/services/trackbacks/57340.html</trackback:ping><description><![CDATA[<font color="#000000">题记：<br>
Python是荷兰人写的，Ruby是日本人写的，Lua是巴西人写的，我这个中国人只能在这里脸红。<br>
——CSDN主编  孟岩<br>
不打算自讨没趣地写个要超过Python,Ruby,Lua的脚本引擎，以锻炼能力为主。<br>
估计完成以后和Lua有点像，宗旨是：<span style="color: red;">以比Lua更短为荣，以比Python更长为耻</span> :-)<br>
┏━┓　　　┏━━┓　　　┏┓　　　　　<br>
┃┃┣━┳━┫━━╋━┳┳╋╋━┳━━┓<br>
┃　┫━┃┃┣━━┃┣┫┏┫┃┃┣┓┏┛<br>
┗┻┻┻┫┏┻━━┻━┻┛┗┫┏┛┗┛　<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; ┗┛　　　　　　　　┗┛　　　　<br>
引擎就叫RapScript好了(<strong><font color="#ff0000">R</font></strong>uby,Lu<strong><font color="#ff0000">a</font></strong>,<strong><font color="#ff0000">P</font></strong>ython 加一起)<br><img alt=""  src="http://www.cppblog.com/images/cppblog_com/billhsu/7643/o_Rap.JPG"><br>
</font>          <img src ="http://www.cppblog.com/billhsu/aggbug/57340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/billhsu/" target="_blank">Bill Hsu</a> 2008-07-28 12:36 <a href="http://www.cppblog.com/billhsu/archive/2008/07/28/57340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>