Chinaunix

标题: memo [打印本页]

作者: folklore    时间: 2013-05-07 15:43
标题: memo
Basic 3D Math: Matrices
Matrices are rectangular mathematical objects which have a number of rows and columns – think of it as a two-dimensional array. Take a look at the following:Above is a 3×4 Matrix (because it has 3 rows and 4 columns) – speak: 3 by 4 Matrix. Each element of the Matrix can be indexed by using the following notation: where i is the row and j the column: because the element at the 3rd rows and 2nd column has the value 10.Matrices are used in CG to represent a various number of different things like transformations and orientations.Part 1: Multiplying Matrices (Matrix Product)Matrix multiplication is not commutative, which means that the order of operation is relevant (as opposed to the multiplication of real numbers). In order to be able to multiply two matrices they must satisfy the rule that column of the first must match the rows of the second. Take a look at the following graphic which works as a simple reminder for the rules of matrix multiplication:But what’s the purpose of multiplying matrices? In 3D Programming you do Transforming a vertex with such a operation. Stop – how can i multiply a vector (which stores a vertex position) with a matrix? Vectors can be thought as Vectors with 1 Row and 4 Columns – and because multiplying a 1×4 Matrix with a 4×4 Matrix is a valid operation this works.In the first step, lets examine how to actually do the multiplication – formally this looks like:i = row index
j = column index
p = number of columns of the first matrix (or number of rows of the second one)Because a example often says more than thousand words, take a look at the following:We have two matrices: and . Multiplication of those two is possible because the number of columns of A matches the number of rows of B – the result is a 2×2 Matrix.Let’s perform the Calculation step by step.Step 1: Write down the calculation of every index for the resulting matrix
Step 2: Do the calculations
results in:Part 2: Creating Matrices for TransformationsAs mentioned above at the beginning of this document, matrices can be used to transform vectors. Its obvious that you need corresponding matrices which represent the transformation, so they are presented below – please note that they are for OpenGL only (The “why” is discussed at the end)Identity Matrix:The Identity matrix can be seen as the “reset” state matrix. If you multiply a vector with the Identity matrix you get the original vector. You initialise new matrices to the identity.Translation Matrix:X, Y and Z represent the amount you want to translate the vector on the axis.Scaling Matrix:X,Y and Z represent the amount of scaling on the corresponding axis.Rotation Matrix:There are four rotation matrices – one about each Axis (X,Y and Z) and one for rotating about an arbitrary axe. is the roation in radians.    The matrix used to rotate about an arbitrary axis is a little bit more complicated.Assumptations: Then the matrix looks like:The Vector (x,y,z) which represents the rotation axis must be normalizedMost of the time you don’t need to create those matrices by ourself because either the math library you are using provides them or you write your own.Part 3: Order of operation and combining transformationsThe order of multiplying multiple transformation matrices is cruical. In OpenGL you get the final transformation by reading your statement from left to right. Example:R is a rotation, T a translation matrix. The Vector V is first Translated and then rotated. Take a look at the pictures below to see the difference visually:In this Picture, the vertices of the Object are first multiplied by a rotation matrix (about Z) – which rotates the local object coordinates. After that a translation matrix (move along X)  is applied, so the object moves along the rotated X axis. The order of the multiplications are:As mentioned before, we read from right to left (Take Vector V, then Rotate, then Translate)This time we first multiply with a translation matrix (translate along X) and then apply a rotation matrix:Which means: Take Vector V, then translate, then rotate.Please note that the order only applies to OpenGL. In DirectX it’s from left to right – also the matrices are a little bit different in how they look like.Part 4: Going aheadMost OpenGL based 3D Libraries and Toolkits provide easy ways of creating the matrices mentioned above (i REALLY like Richard Wright’s Math3D Library which he uses in his Book OpenGL Superbible).If you want to dig deeper into the mathematics behind 3D Graphics, i highly recommend you the following two books:
作者: bruceteen    时间: 2013-05-07 15:58
不明觉厉,越发崇拜妇科老人了
作者: 木有Some    时间: 2013-05-07 16:45
3D矩阵。。好高深的样子。
作者: __BlueGuy__    时间: 2013-05-07 17:12
这些都是最简单的基础知识, JB用都没有 ...
作者: cokeboL    时间: 2013-05-07 17:27
以前还研究过,现在都忘光了

游戏引擎里都写好了接口,我这种鸟用不上这些姿势啊
作者: folklore    时间: 2013-05-07 20:02
回复 2# bruceteen


    我不想自已推导,所以做了个Memo,没想一上来就被你取笑。。
星星最近如何,转Linux了么?
作者: bruceteen    时间: 2013-05-08 09:15
回复 6# folklore
俺不懂洋文,想嘲笑你也没办法呀^_^
俺还没转到Linux上,最近还是在混着
你最近在搞什么呀,越来越深奥了
作者: folklore    时间: 2013-05-08 12:45
回复 7# bruceteen


    哪里深奥了。用高中的数学就能推出来吧。只是俺比较懒。。。。
现在在做一个CAD/CAM系统。各种苦B。
作者: folklore    时间: 2013-05-09 10:10
  1. static void Matrix3dMultiple(double rt[4][4],double multiplicand[4][4],double multiplicate[4][4]){
  2.         double rs[4][4];
  3.        
  4.         for(int iY =0;iY<_countof(rs);iY++){
  5.                 for(int iX =0;iX<_countof(rs[0]);iX++){
  6.                         rs[iY][iX] =0.0L;
  7.                         for(int iAdd=0;iAdd <_countof(multiplicand[0]);iAdd++){
  8.                                 rs[iY][iX] +=multiplicand[iY][iAdd] *multiplicate[iAdd][iX];
  9.                         }
  10.                 }
  11.         }

  12.         memcpy(rt,rs,sizeof(rs));
  13. }// end function: Matrix3dMultiple
复制代码

作者: linux_c_py_php    时间: 2013-05-09 10:59
计算机领域太广了, 楼主竟然要和数学打交道.
作者: folklore    时间: 2013-05-09 14:03
本帖最后由 folklore 于 2013-05-09 15:28 编辑
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <windows.h>
  4. #include <vector>
  5. #include <sstream>

  6. #pragma comment(lib,"User32.lib")
  7. #pragma message("Compiling command(dll): cl.exe /EHsc /Ot /Ox /W4 /LD /DDLL "__FILE__" /link /subsystem:console")
  8. #pragma message("Compiling command(exe): cl.exe /EHsc /Ot /Ox /W4 "__FILE__" /link /subsystem:console")

  9. // -- Html Helper function
  10. static std::wstring HtmlEncode(const std::wstring& html){
  11.         std::wostringstream result;
  12.         for (std::wstring::const_iterator itCh = html.begin(); itCh !=html.end(); itCh++){
  13.                 switch(*itCh){
  14.                         case L'<':
  15.                                 result <<L"&lt;";
  16.                                 break;
  17.                         case L'>':
  18.                                 result <<L"&gt;";
  19.                                 break;
  20.                         case L'&':
  21.                                 result <<L"&amp;";
  22.                                 break;
  23.                         case L'\"':
  24.                                 result <<L"&quot;";
  25.                                 break;
  26.                         default:
  27.                                 result <<static_cast<wchar_t>(*itCh);
  28.                                 break;
  29.                 }
  30.         }
  31.         return result.str();
  32. }
  33. //static std::wstring HtmlDecode(const std::wstring& html)
  34. //{
  35. //        std::wostringstream result;
  36. //        size_t iParse =0;
  37. //        while(iParse <html.length()){
  38. //                if(html.at(iParse) !=L'&'){
  39. //                        result <<html.at(iParse++);
  40. //                }else{// enter slash staus
  41. //                        std::wostringstream enctext;
  42. //                        while(html.length() >iParse &&html.at(iParse) !=L';'){
  43. //                                enctext <<html.at(iParse++);
  44. //                        }
  45. //                        if(_wcsicmp(enctext.str().c_str(),L"&lt") ==0){
  46. //                                result <<L'<';
  47. //                        }else if(_wcsicmp(enctext.str().c_str(),L"&gt") ==0){
  48. //                                result <<L'>';
  49. //                        }else if(_wcsicmp(enctext.str().c_str(),L"&amp") ==0){
  50. //                                result <<L'&';
  51. //                        }else if(_wcsicmp(enctext.str().c_str(),L"&quot") ==0){
  52. //                                result <<L'\"';
  53. //                        }
  54. //                        if(html.length() >iParse) iParse++;        // Skip semicolon
  55. //                }
  56. //        }
  57. //        return result.str();
  58. //}// end function: HtmlDecode
  59. // -- end: Html helper functions

  60. struct IOS{
  61.         std::wstring Input;
  62.         std::vector<HWND> Output;
  63. };
  64. /// <summary>
  65. ///                Walk through all windows&subwindows that shown in current desktop, and figure out the window which be identified with special UUID prop
  66. ///        </summary>
  67. /// <see>
  68. ///                See msdn to get more info aboud this function (Relative API "EnumWindows"/"EnumChildWindows")
  69. ///        </see>
  70. static BOOL CALLBACK EnumWindowsProc(_In_ HWND hwnd,_In_ LPARAM lParam){
  71.         struct IOS *pIos =(struct IOS *)lParam;

  72.         HANDLE hData =::GetPropW(hwnd,pIos->Input.c_str());
  73.         if(hData !=NULL){
  74.                 pIos->Output.push_back(hwnd);
  75.                 EnumChildWindows(hwnd,EnumWindowsProc,lParam);
  76.         }
  77.         return TRUE;
  78. }// end function: EnumWindowsProc

  79. // -- local helper function
  80. static std::wstring _Makeparams(const wchar_t *const pParams){
  81.         std::wstring rsMsg;
  82.         rsMsg.append(L"\t\t\t<Params>\n");
  83.         const wchar_t *pParam =pParams;
  84.         do{
  85.                 rsMsg.append(L"\t\t\t\t<Param>");
  86.                 rsMsg.append(HtmlEncode(pParam));
  87.                 rsMsg.append(L"</Param>\n");
  88.                 while(pParam[0] !=NULL){
  89.                         pParam++;
  90.                 }// end if
  91.                 pParam++;
  92.         }while(pParam[0] !=NULL);
  93.         rsMsg.append(L"\t\t\t</Params>\n");
  94.         return rsMsg;
  95. }
  96. /// <summary>
  97. ///                MakeMessage: Input the message and translate it to XML format
  98. /// </summary>
  99. // The result string looks like
  100. // <messages>
  101. //        <message ext-code="3">
  102. //                <Title code="35" Description="">
  103. //                        <Params>
  104. //                                <Param>p1 of content<Param>
  105. //                        <Params>
  106. //                </Title>
  107. //                <Content code="53" Description="">
  108. //                        <Params>
  109. //                                <Param>p1 of content</Param>
  110. //                        <Params>
  111. //                </Content>
  112. //        </message>
  113. // </messages>
  114. static std::wstring MakeMessage(const wchar_t *const id,const long cdTitle,const wchar_t *const pTitle,const long cdBody,const wchar_t *const pBody,const wchar_t *const paramsTitle=NULL,const wchar_t *const paramsContent=NULL,const long cdExtend=-1){
  115.         (void) id;
  116.         wchar_t intbuf[MAX_PATH];        // Global buffer

  117.         // -- Xml header
  118.         std::wstring rsMsg(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  119.         rsMsg.append(L"<Messages>\n");
  120.         rsMsg.append(L"\t<Message ext-code=\"");
  121.         _itow_s(cdExtend,intbuf,MAX_PATH,10);
  122.         rsMsg.append(intbuf);
  123.         rsMsg.append(L"\"");
  124.         // -- UUID if specified
  125.         if(id !=NULL){
  126.                 rsMsg.append(L" UUID=\"");rsMsg.append(HtmlEncode(id));rsMsg.append(L"\"");
  127.         }//end if
  128.         rsMsg.append(L">\n");
  129.         // -- Title
  130.         _itow_s(cdTitle,intbuf,MAX_PATH,10);
  131.         rsMsg.append(L"\t\t<Title code=\"");rsMsg.append(intbuf);rsMsg.append(L"\"");
  132.         if(pTitle !=NULL){
  133.                 rsMsg.append(L" Description=\"");rsMsg.append(HtmlEncode(pTitle));rsMsg.append(L"\"");       
  134.         }

  135.         if(paramsTitle !=NULL){
  136.                 rsMsg.append(L">\n");
  137.                 rsMsg.append(_Makeparams(paramsTitle).c_str());
  138.                 rsMsg.append(L"\t\t</Title>\n");
  139.         }else{
  140.                 rsMsg.append(L"/>\n");
  141.         }

  142.         // -- Content
  143.         _itow_s(cdBody,intbuf,MAX_PATH,10);
  144.         rsMsg.append(L"\t\t<Content code=\"");rsMsg.append(intbuf);rsMsg.append(L"\"");
  145.         if(pBody !=NULL){
  146.                 rsMsg.append(L" Description=\"");rsMsg.append(HtmlEncode(pBody));rsMsg.append(L"\"");
  147.         }
  148.         if(paramsContent !=NULL){
  149.                 rsMsg.append(L">\n");
  150.                 rsMsg.append(_Makeparams(paramsContent).c_str());
  151.                 rsMsg.append(L"\t\t</Content>\n");
  152.         }else{
  153.                 rsMsg.append(L"/>\n");
  154.         }

  155.         rsMsg.append(L"\t</Message>\n");
  156.         rsMsg.append(L"</Messages>");
  157.         return rsMsg;
  158. }// end function: MakeMessage

  159. /// <summary>
  160. ///                Send message to UI (typically main window) program that registered. The COM component can be executed in remote host.
  161. ///                This function try to send message to *local host* (and typically the local host show a message depend on the message-code).
  162. /// </summary>
  163. /// <param name="pUUIDDes">UUID of target window (via get/setprop)</param>
  164. /// <param name="id">The message id, can be null</param>
  165. /// <param name="cdTitle">Code of message title</param>
  166. /// <param name="pTitle">Message title, can be null</param>
  167. /// <param name="cdBody">Code of message body</param>
  168. /// <param name="pBody">Message content, can be null</param>
  169. /// <Return> The number of the target window </Return>
  170. extern "C" __declspec(dllexport) int SendUIMessage(const wchar_t *const pUUIDDes,wchar_t *const id,const long cdTitle,const wchar_t *const pTitle,const long cdBody,const wchar_t *const pBody,const wchar_t *const paramsTitle=NULL,const wchar_t *const paramsContent=NULL,const long cdExtend=0){
  171.         int nSent =0;
  172.         if(pUUIDDes !=NULL){
  173.                 struct IOS ios;
  174.                 ios.Input =pUUIDDes;

  175.                 ::EnumWindows(EnumWindowsProc,(LPARAM)&ios);
  176.                 for(std::vector<HWND>::iterator itHwnd =ios.Output.begin(); itHwnd !=ios.Output.end();itHwnd++){
  177.                         std::wstring msgstr =MakeMessage(id,cdTitle,pTitle,cdBody,pBody,paramsTitle,paramsContent,cdExtend);
  178.                         COPYDATASTRUCT msg ={
  179.                                 NULL,(msgstr.size()+1)<<1,(LPVOID)msgstr.c_str()
  180.                         };
  181.                         ::SendMessage(*itHwnd,WM_COPYDATA,NULL,(LPARAM)&msg);
  182.                         //MessageBoxW(*itHwnd,L"OK",L"OK",MB_OK);        // -- Try to show message at destinate window
  183.                         nSent++;
  184.                 }
  185.         }// end if
  186.         return nSent;
  187. }

  188. #if !defined(DLL)
  189. static const wchar_t *const UUIDBendCAM =L"{3B0C708E-8014-4f33-BFC8-4AE1E8F3901C}";
  190. static size_t dntwcslen(const wchar_t *const pSrc){        //double null terminal string
  191.         size_t rsSize =0;
  192.         if(pSrc !=NULL){
  193.                 do{
  194.                         while(pSrc[rsSize] !=NULL){rsSize++;}
  195.                         rsSize++;
  196.                 }while(pSrc[rsSize] !=NULL);
  197.         }
  198.         return rsSize;
  199. }
  200. int main(void){
  201.         const wchar_t *const pParams =L"Param<01>\0Param02\0";
  202.         std::wstring params;
  203.         params.resize(dntwcslen(pParams));
  204.         for(size_t iAssign =0;iAssign <params.size();iAssign++){        // the size is not include the last terminal tocken
  205.                 params.at(iAssign) =pParams[iAssign];
  206.                 //wprintf(L"%c",params.at(iAssign));
  207.         }
  208.         //wprintf(L"\n%d",dntwcslen(pParams));
  209.         if(0 ==SendUIMessage(UUIDBendCAM,NULL,123,L"Title&b",456,L"Context: <happy new year.>",params.data(),params.data())){
  210.                 std::wstring msg=MakeMessage(NULL,123,L"Title&b",456,L"Context: <happy new year.>",params.data()/*,params.data()*/);
  211.                 wprintf(L"%s",msg.c_str());
  212.         }
  213.         return 0;
  214. }
  215. #endif //!defined(DLL)
复制代码
new version

作者: wait_rabbit    时间: 2013-05-09 14:35
马二进三,这还得去翻线性代数课本。
作者: wonghoifung    时间: 2013-05-09 15:13
:wink:
作者: folklore    时间: 2013-05-09 21:20
回复 10# linux_c_py_php


    以前一直以为程序和数学是不分家的。直到有一天,有个电信公司叫我写无聊的电信业务系统。
作者: folklore    时间: 2013-06-28 16:17
The following issue explain you how to apply the metries to an 3d vertex.

In order to apply a general 4x4 transformation matrix to a vertex represented as a 3 dimensional vector, you need to:
1.Expand the vector into the 4th dimension by adding a 1 as the W component:
        (x, y, z) => (x, y, z, 1)
2.Multiply the transformation matrix by the 4 dimensional vector above. The result will be another 4 dimensional vector:
        ( 4x4 matrix ) * (x, y, z, 1) => (tx, ty, tz, w)
The general formula for multiplying a 4x4 matrix by a 4x1 vector is (if I didn't mess up):
        [ m11 m12 m13 m14 ][ x ]   [ m11 * x + m12 * y + m13 * z + m14 * w ]
        [ m21 m22 m23 m24 ][ y ]   [ m21 * x + m22 * y + m23 * z + m24 * w ]
        [ m31 m32 m33 m34 ][ z ] = [ m31 * x + m32 * y + m33 * z + m34 * w ]
        [ m41 m42 m43 m44 ][ w ]   [ m41 * x + m42 * y + m43 * z + m44 * w ]
Or if you consider the usual configuration of a transformation matrix:
        [ m11 m12 m13 px ][ x ]   [ m11 * x + m12 * y + m13 * z + px ]
        [ m21 m22 m23 py ][ y ]   [ m21 * x + m22 * y + m23 * z + py ]
        [ m31 m32 m33 pz ][ z ] = [ m31 * x + m32 * y + m33 * z + pz ]
        [ 0   0   0   1  ][ 1 ]   [ 1 ]
3.Convert it back into the 3rd dimension by homogenizing the vector, i.e. dividing everything by the fourth component w:
        (tx, ty, tz, w) => (tx/w, tx/w, tz/w)

The thing is that if your transformation matrix only does a simple translation / rotation / scale, the value of w will be 1 and you can just drop the fourth component since that will be the same as dividing by 1.
But it's good to remember that it does not work for every case, e.g. with projection matrices you must remember to do this third step.


作者: folklore    时间: 2013-07-12 09:07
本帖最后由 folklore 于 2013-07-12 09:08 编辑

XSL文件真蛋疼, 麻烦死了, 写个函数:

  1. ///<summary>
  2. ///  Indent format file
  3. ///</summary>
  4. ///<param name ="pXmlDoc">Source xml document object</param>
  5. ///<return>formated xml document object</return>
  6. static MSXML2::IXMLDOMDocumentPtr ApplyXmlIndent(MSXML2::IXMLDOMDocumentPtr pXmlDoc){
  7.         static const wchar_t *const XmlStyleSpecString =
  8.                 L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
  9.                 L"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
  10.                 L"        <xsl:output method=\"xml\" indent=\"yes\"/>\n"
  11.                 L"        <xsl:template match=\"@* | node()\">\n"
  12.                 L"                <xsl:choose>\n"
  13.                 L"                        <xsl:when test=\"not(node()) and not(text())\">\n"
  14.                 L"                                <xsl:copy>\n"
  15.                 L"                                        <xsl:apply-templates select=\"@*\"/>\n"
  16.                 L"                                </xsl:copy>\n"
  17.                 L"                        </xsl:when>\n"
  18.                 L"                        <xsl:otherwise>\n"
  19.                 L"                                <xsl:copy>\n"
  20.                 L"                                        <xsl:apply-templates select=\"@* | node()\"/>\n"
  21.                 L"                                </xsl:copy>\n"
  22.                 L"                        </xsl:otherwise>\n"
  23.                 L"                </xsl:choose>\n"
  24.                 L"        </xsl:template>\n"
  25.                 L"</xsl:stylesheet>";

  26.         //Create the final document which will be indented properly
  27.         MSXML2::IXMLDOMDocumentPtr pXMLFormattedDoc(__uuidof(MSXML2::DOMDocument)),fmtXml(__uuidof(MSXML2::DOMDocument));

  28.         do{
  29.                 if(fmtXml->loadXML(_bstr_t(XmlStyleSpecString)) ==VARIANT_FALSE){
  30.                         break;
  31.                 }

  32.                 IDispatchPtr pDispatch;
  33.                 HRESULT hr = pXMLFormattedDoc->QueryInterface(IID_IDispatch, (void**)&pDispatch);
  34.                 if(FAILED(hr)){
  35.                         break;
  36.                 }

  37.                 _variant_t        vtOutObject;
  38.                 vtOutObject.vt = VT_DISPATCH;
  39.                 vtOutObject.pdispVal = pDispatch;
  40.                 vtOutObject.pdispVal->AddRef();        //< required

  41.                 //Apply the transformation to format the final document       
  42.                 pXmlDoc->transformNodeToObject(fmtXml,vtOutObject);

  43.                 //The default encoding method is utf-16. Change it to utf-8
  44.                 MSXML2::IXMLDOMNodePtr pXMLFirstChild = pXMLFormattedDoc->GetfirstChild();                                // <?xml version="1.0" encoding="UTF-8"?>
  45.                 MSXML2::IXMLDOMNamedNodeMapPtr pXMLAttributeMap =  pXMLFirstChild->Getattributes();                // A map of the a attributes (vesrsion, encoding) values (1.0, utf-8) pair
  46.                 MSXML2::IXMLDOMNodePtr pXMLEncodNode = pXMLAttributeMap->getNamedItem(_bstr_t(L"encoding"));       
  47.                 pXMLEncodNode->PutnodeValue(_bstr_t(L"utf-8"));//encoding = UTF-8       

  48.         }while(false);
  49.         return pXMLFormattedDoc;
  50. }//end function: ApplyXmlIndent
复制代码

作者: reiase    时间: 2013-07-12 09:20
做图形学的都好幸福,起码数学推出来的都是对的




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2